diff --git a/le_audio/certification_tool/bap_uclient_test_tool/Android.bp b/le_audio/certification_tool/bap_uclient_test_tool/Android.bp deleted file mode 100644 index ea9b244968a61efd3a3ca1fcd8524d68f82ac295..0000000000000000000000000000000000000000 --- a/le_audio/certification_tool/bap_uclient_test_tool/Android.bp +++ /dev/null @@ -1,55 +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. - * - ******************************************************************************/ - -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_binary { - name: "bap_uclient_test", - system_ext_specific: true, - enabled: false, - srcs: ["bap_uclient_test.cpp"], - - include_dirs: [ - ".", - "packages/modules/Bluetooth/system/include", - "packages/modules/Bluetooth/system/types", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/stack/l2cap", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/utils/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system", - "vendor/qcom/opensource/commonsys/bluetooth_lea/vhal/include", - "external/libchrome", - ], - - cflags: ["-DHAS_NO_BDROID_BUILDCFG"], - - shared_libs: [ - "libcutils", - "libchrome", - "libutils", - ], - - static_libs: ["libbluetooth-types-qti"], - -} diff --git a/le_audio/certification_tool/bap_uclient_test_tool/bap_uclient_test.cpp b/le_audio/certification_tool/bap_uclient_test_tool/bap_uclient_test.cpp deleted file mode 100644 index a3586f6a2dfab4fc5df2b742565d248f4e4577ed..0000000000000000000000000000000000000000 --- a/le_audio/certification_tool/bap_uclient_test_tool/bap_uclient_test.cpp +++ /dev/null @@ -1,1908 +0,0 @@ -/*********************************************************************** - * - * Copyright (c) 2014-2015, 2020 The Linux Foundation. All rights reserved. - * - * Copyright (C) 2009-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. - * - -******************************************************************************/ - - -/****************************************************************************** -****** - * - * Filename: bap_uclient_test.cpp - * - * Description: bap unicast client test application - * - -******************************************************************************* -****/ - - -#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 - -using bluetooth::Uuid; - -constexpr uint8_t ASE_DIRECTION_SINK = 0x01 << 0; -constexpr uint8_t ASE_DIRECTION_SRC = 0x01 << 1; - -constexpr uint8_t ASE_SINK_STEREO = 0x01 << 0; -constexpr uint8_t ASE_SRC_STEREO = 0x01 << 1; - -#ifndef BAP_UNICAST_TEST_APP_INTERFACE -#define BAP_UNICAST_TEST_APP_INTERFACE -/****************************************************************************** -****** -** Constants & Macros -******************************************************************************* -*****/ - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -#define PID_FILE "/data/.bdt_pid" - -#ifndef MAX -#define MAX(x, y) ((x) > (y) ? (x) : (y)) -#endif - -#define CASE_RETURN_STR(const) case const: return #const; - - -/****************************************************************************** -****** -** Local type definitions -******************************************************************************* -*****/ - - -/****************************************************************************** -****** -** Static variables -******************************************************************************* -*****/ - -static unsigned char main_done = 0; -static int status; - -#define LE_ACL_MAX_BUFF_SIZE 4096 -static int num_frames = 1; -static unsigned long g_delay = 1; /* Default delay before data transfer */ -static int count = 1; -static uint16_t g_BleEncKeySize = 16; -static int g_le_coc_if = 0; -static int rcv_itration = 0; -static volatile bool cong_status = FALSE; - - -/* Main API */ -const bt_interface_t* sBtInterface = NULL; - -static gid_t groups[] = { AID_NET_BT, AID_INET, AID_NET_BT_ADMIN, - AID_SYSTEM, AID_MISC, AID_SDCARD_RW, - AID_NET_ADMIN, AID_VPN}; - -enum { - DISCONNECT, - CONNECTING, - CONNECTED, - DISCONNECTING -}; - -static unsigned char bt_enabled = 0; -static int g_ConnectionState = DISCONNECT; -static int g_AdapterState = BT_STATE_OFF; -static int g_PairState = BT_BOND_STATE_NONE; - -static int g_conn_id = 0; -static int g_client_if = 0; -static int g_server_if = 0; -static int g_client_if_scan = 0; -static int g_server_if_scan = 0; - - -RawAddress* remote_bd_address; - -static uint16_t g_SecLevel = 0; -static bool g_ConnType = TRUE;//DUT is initiating connection - -/****************************************************************************** -****** -** Static functions -******************************************************************************* -*****/ - -static void process_cmd(char *p, unsigned char is_job); -//static void job_handler(void *param); -static void bdt_log(const char *fmt_str, ...); -static void l2c_connect(RawAddress bd_addr); -static uint16_t do_l2cap_connect(RawAddress bd_addr); - -int GetBdAddr(char *p, RawAddress* pbd_addr); -void bdt_init(void); -int reg_inst_id = -1; -int reg_status = -1; - - -/****************************************************************************** -****** -** ASCS Client Callbacks -******************************************************************************* -*****/ - - -/****************************************************************************** -****** -** PACS client Callbacks -******************************************************************************* -*****/ - - - -/****************************************************************************** -****** -** BAP Unicast client Callbacks -******************************************************************************* -*****/ - -/****************************************************************************** -****** -** Shutdown helper functions -******************************************************************************* -*****/ - -static void bdt_shutdown(void) -{ - bdt_log("shutdown bdroid test app.\n"); - main_done = 1; -} - - -/***************************************************************************** -** Android's init.rc does not yet support applying linux capabilities -*****************************************************************************/ - -static void config_permissions(void) -{ - struct __user_cap_header_struct header; - struct __user_cap_data_struct cap[2]; - - bdt_log("set_aid_and_cap : pid %d, uid %d gid %d", getpid(), getuid(), getgid()); - - header.pid = 0; - - prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); - - setuid(AID_BLUETOOTH); - setgid(AID_BLUETOOTH); - - header.version = _LINUX_CAPABILITY_VERSION_3; - - cap[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW); - cap[CAP_TO_INDEX(CAP_NET_ADMIN)].permitted |= CAP_TO_MASK(CAP_NET_ADMIN); - cap[CAP_TO_INDEX(CAP_NET_BIND_SERVICE)].permitted |= CAP_TO_MASK(CAP_NET_BIND_SERVICE); - cap[CAP_TO_INDEX(CAP_SYS_RAWIO)].permitted |= CAP_TO_MASK(CAP_SYS_RAWIO); - cap[CAP_TO_INDEX(CAP_SYS_NICE)].permitted |= CAP_TO_MASK(CAP_SYS_NICE); - cap[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID); - cap[CAP_TO_INDEX(CAP_WAKE_ALARM)].permitted |= CAP_TO_MASK(CAP_WAKE_ALARM); - - cap[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW); - cap[CAP_TO_INDEX(CAP_NET_ADMIN)].effective |= CAP_TO_MASK(CAP_NET_ADMIN); - cap[CAP_TO_INDEX(CAP_NET_BIND_SERVICE)].effective |= CAP_TO_MASK(CAP_NET_BIND_SERVICE); - cap[CAP_TO_INDEX(CAP_SYS_RAWIO)].effective |= CAP_TO_MASK(CAP_SYS_RAWIO); - cap[CAP_TO_INDEX(CAP_SYS_NICE)].effective |= CAP_TO_MASK(CAP_SYS_NICE); - cap[CAP_TO_INDEX(CAP_SETGID)].effective |= CAP_TO_MASK(CAP_SETGID); - cap[CAP_TO_INDEX(CAP_WAKE_ALARM)].effective |= CAP_TO_MASK(CAP_WAKE_ALARM); - - capset(&header, &cap[0]); - setgroups(sizeof(groups)/sizeof(groups[0]), groups); -} - - -/***************************************************************************** -** Logger API -*****************************************************************************/ - -void bdt_log(const char *fmt_str, ...) -{ - static char buffer[1024]; - va_list ap; - - va_start(ap, fmt_str); - vsnprintf(buffer, 1024, fmt_str, ap); - va_end(ap); - - fprintf(stdout, "%s\n", buffer); -} - -/****************************************************************************** -* - ** Misc helper functions - -*******************************************************************************/ -static const char* dump_bt_status(int status) -{ - switch(status) - { - CASE_RETURN_STR(BT_STATUS_SUCCESS) - CASE_RETURN_STR(BT_STATUS_FAIL) - CASE_RETURN_STR(BT_STATUS_NOT_READY) - CASE_RETURN_STR(BT_STATUS_NOMEM) - CASE_RETURN_STR(BT_STATUS_BUSY) - CASE_RETURN_STR(BT_STATUS_UNSUPPORTED) - - default: - return "unknown status code"; - } -} - - -/****************************************************************************** -* - ** Console helper functions - -*******************************************************************************/ - -void skip_blanks(char **p) -{ - while (**p == ' ') - (*p)++; -} - -uint32_t get_int(char **p, int DefaultValue) -{ - uint32_t Value = 0; - unsigned char UseDefault; - - UseDefault = 1; - skip_blanks(p); - - while ( ((**p)<= '9' && (**p)>= '0') ) - { - Value = Value * 10 + (**p) - '0'; - UseDefault = 0; - (*p)++; - } - if (UseDefault) - return DefaultValue; - else - return Value; -} - -int get_signed_int(char **p, int DefaultValue) -{ - int Value = 0; - unsigned char UseDefault; - unsigned char NegativeNum = 0; - - UseDefault = 1; - skip_blanks(p); - - if ((**p) == '-') - { - NegativeNum = 1; - (*p)++; - } - while ( ((**p)<= '9' && (**p)>= '0') ) - { - Value = Value * 10 + (**p) - '0'; - UseDefault = 0; - (*p)++; - } - - if (UseDefault) - return DefaultValue; - else - return ((NegativeNum == 0)? Value : -Value); -} - -void get_str_1(char **p, char *Buffer) -{ - skip_blanks(p); - while (**p != 0 && **p != '\0') - { - *Buffer = **p; - (*p)++; - Buffer++; - } - - *Buffer = 0; -} - -void get_str(char **p, char *Buffer) -{ - skip_blanks(p); - while (**p != 0 && **p != ' ') - { - *Buffer = **p; - (*p)++; - Buffer++; - } - - *Buffer = 0; -} - - - -#define is_cmd(str) ((strlen(str) == strlen(cmd)) && strncmp((const char *)&cmd, str, strlen(str)) == 0) -#define if_cmd(str) if (is_cmd(str)) - -typedef void (t_console_cmd_handler) (char *p); - -typedef struct { - const char *name; - t_console_cmd_handler *handler; - const char *help; - unsigned char is_job; -} t_cmd; - -void do_help(char *p); -void do_quit(char *p); -void do_init(char *p); -void do_enable(char *p); -void do_disable(char *p); -void do_cleanup(char *p); -void do_pairing(char *p); -void do_pacs_discovery(char *p); -void do_ascs_discovery(char *p); -void do_bap_connect(char *p); -void do_bap_disconnect(char *p); -void do_bap_start(char *p); -void do_bap_stop(char *p); -void do_bap_disc_in_connecting(char *p); -void do_bap_disc_in_starting(char *p); -void do_bap_disc_in_stopping(char *p); -void do_bap_stop_in_starting(char *p); -void do_bap_update_stream(char *p); - -/******************************************************************* - * - * CONSOLE COMMAND TABLE - * -*/ - -const t_cmd console_cmd_list[] = -{ - /* - * INTERNAL - */ - - { "help", do_help, "lists all available console commands", 0 }, - { "quit", do_quit, "", 0}, - - /* - * API CONSOLE COMMANDS - */ - - /* Init and Cleanup shall be called automatically */ - { "enable", do_enable, "cmd :: enable", 0 }, - { "disable", do_disable, "cmd :: disable", 0 }, - { "pair", do_pairing, "cmd :: pair ", 0 }, - { "pacs_discovery", do_pacs_discovery, "cmd :: pacs_discovery ", 0 }, - { "ascs_discovery", do_ascs_discovery, "cmd :: ascs_discovery ", 0 }, - { "bap_connect", do_bap_connect, "cmd :: bap_connect ", 0 }, - { "bap_disconnect", do_bap_disconnect, "cmd :: bap_disconnect ", 0 }, - { "bap_start", do_bap_start, "cmd :: bap_start ", 0 }, - { "bap_stop", do_bap_stop, "cmd :: bap_stop ", 0 }, - { "bap_disc_in_connecting", do_bap_disc_in_connecting, "cmd :: bap_disc_in_connecting ", 0 }, - { "bap_disc_in_starting", do_bap_disc_in_starting, "cmd :: bap_disc_in_starting ", 0 }, - { "bap_disc_in_stopping", do_bap_disc_in_stopping, "cmd :: bap_disc_in_stopping ", 0 }, - { "bap_stop_in_starting", do_bap_stop_in_starting, "cmd :: bap_stop_in_starting ", 0 }, - { "bap_update_stream", do_bap_update_stream, "cmd :: bap_update_stream ", 0 }, - /* last entry */ - {NULL, NULL, "", 0}, -}; - - -static int console_cmd_maxlen = 0; - -static void *cmdjob_handler(void *param) -{ - char *job_cmd = (char*)param; - - bdt_log("cmdjob starting (%s)", job_cmd); - - process_cmd(job_cmd, 1); - - bdt_log("cmdjob terminating"); - - free(job_cmd); - return NULL; -} - -static int create_cmdjob(char *cmd) -{ - pthread_t thread_id; - char *job_cmd; - - job_cmd = (char*)calloc(1, strlen(cmd)+1); /* freed in job handler */ - if (job_cmd) { - strlcpy(job_cmd, cmd,(strlen(cmd)+1)); - if (pthread_create(&thread_id, NULL, cmdjob_handler, (void *)job_cmd) != 0) - /*if (pthread_create(&thread_id, NULL, - (void*)cmdjob_handler, (void*)job_cmd) !=0)*/ - perror("pthread_create"); - return 0; - } - else - perror("create_Cmdjob malloc failed "); - return -1; -} - -/****************************************************************************** -* - ** Load stack lib - -*******************************************************************************/ -#define BLUETOOTH_LIBRARY_NAME "libbluetooth_qti.so" -int load_bt_lib(const bt_interface_t** interface) { - const char* sym = BLUETOOTH_INTERFACE_STRING; - bt_interface_t* itf = nullptr; - - // Always try to load the default Bluetooth stack on GN builds. - const char* path = BLUETOOTH_LIBRARY_NAME; - void* handle = dlopen(path, RTLD_NOW); - if (!handle) { - //const char* err_str = dlerror(); - printf("failed to load Bluetooth library\n"); - goto error; - } - - // Get the address of the bt_interface_t. - itf = (bt_interface_t*)dlsym(handle, sym); - if (!itf) { - printf("failed to load symbol from Bluetooth library\n"); - goto error; - } - - // Success. - printf(" loaded HAL Success\n"); - *interface = itf; - return 0; - -error: - *interface = NULL; - if (handle) dlclose(handle); - - return -EINVAL; -} - -int HAL_load(void) -{ - if (load_bt_lib((bt_interface_t const**)&sBtInterface)) { - printf("No Bluetooth Library found\n"); - return -1; - } - return 0; -} - -int HAL_unload(void) -{ - int err = 0; - - bdt_log("Unloading HAL lib"); - - sBtInterface = NULL; - - bdt_log("HAL library unloaded (%s)", strerror(err)); - - return err; -} - -/****************************************************************************** -* - ** HAL test functions & callbacks - -*******************************************************************************/ - -void setup_test_env(void) -{ - int i = 0; - - while (console_cmd_list[i].name != NULL) - { - console_cmd_maxlen = MAX(console_cmd_maxlen, (int)strlen(console_cmd_list[i].name)); - i++; - } -} - -void check_return_status(int status) -{ - if (status != BT_STATUS_SUCCESS) - { - bdt_log("HAL REQUEST FAILED status : %d (%s)", status, dump_bt_status(status)); - } - else - { - bdt_log("HAL REQUEST SUCCESS"); - } -} - -static void do_set_localname(char *p) -{ - printf("set name in progress: %s\n", p); - bt_property_t property = {BT_PROPERTY_BDNAME, static_cast(strlen(p)), p}; - status = sBtInterface->set_adapter_property(&property); -} - -static void adapter_state_changed(bt_state_t state) -{ - int V1 = 1000, V2=2; - char V3[] = "bap_uclient_test"; - bt_property_t property = {(bt_property_type_t)9 /* -BT_PROPERTY_DISCOVERY_TIMEOUT*/, 4, &V1}; - bt_property_t property1 = {(bt_property_type_t)7 /*SCAN*/, 2, &V2}; - bt_property_t property2 ={(bt_property_type_t)1,9, &V3}; - printf("ADAPTER STATE UPDATED : %s\n", (state == BT_STATE_OFF)?"OFF":"ON"); - - g_AdapterState = state; - - if (state == BT_STATE_ON) { - bt_enabled = 1; - status = sBtInterface->set_adapter_property(&property1); - status = sBtInterface->set_adapter_property(&property); - status = sBtInterface->set_adapter_property(&property2); - } else { - bt_enabled = 0; - } -} - -static void adapter_properties_changed(bt_status_t status, - int num_properties, bt_property_t *properties) -{ - char Bd_addr[15] = {0}; - if(NULL == properties) - { - printf("properties is null\n"); - return; - } - switch(properties->type) - { - case BT_PROPERTY_BDADDR: - memcpy(Bd_addr, properties->val, properties->len); - break; - default: - printf("property type not used\n"); - } - return; -} - -static void discovery_state_changed(bt_discovery_state_t state) -{ - printf("Discovery State Updated : %s\n", - (state == BT_DISCOVERY_STOPPED)?"STOPPED":"STARTED"); -} - - -static void pin_request_cb(RawAddress* remote_bd_addr, bt_bdname_t *bd_name, - uint32_t cod, bool min_16_digit ) -{ - remote_bd_address = remote_bd_addr; - //bt_pin_code_t pincode = {{0x31, 0x32, 0x33, 0x34}}; - printf("Enter the pin key displayed in the remote device and terminate the key entry with .\n"); - - /*if(BT_STATUS_SUCCESS != sBtInterface->pin_reply(remote_bd_addr, TRUE, 4 -, &pincode)) - { - printf("Pin Reply failed\n"); - }*/ -} -static void ssp_request_cb(RawAddress* remote_bd_addr, bt_bdname_t *bd_name, - uint32_t cod, bt_ssp_variant_t pairing_variant, -uint32_t pass_key) -{ - printf("ssp_request_cb : name=%s variant=%d passkey=%u\n", bd_name->name, -pairing_variant, pass_key); - if(BT_STATUS_SUCCESS != sBtInterface->ssp_reply(remote_bd_addr, -pairing_variant, TRUE, pass_key)) - { - printf("SSP Reply failed\n"); - } -} - -static void bond_state_changed_cb(bt_status_t status, RawAddress* -remote_bd_addr, bt_bond_state_t state) -{ - g_PairState = state; -} - -static void address_consolidate_cb(RawAddress* main_bd_addr, - RawAddress* secondary_bd_addr) {} - -static void acl_state_changed(bt_status_t status, RawAddress* remote_bd_addr, -bt_acl_state_t state, - bt_hci_error_code_t hci_reason) -{ - printf("acl_state_changed : remote_bd_addr=%02x:%02x:%02x:%02x:%02x:%02x, \ - acl status=%s \n", - remote_bd_addr->address[0], remote_bd_addr->address[1], remote_bd_addr->address[2], - remote_bd_addr->address[3], remote_bd_addr->address[4], remote_bd_addr->address[5], - (state == BT_ACL_STATE_CONNECTED)?"ACL Connected" :"ACL Disconnected"); -} -static void dut_mode_recv(uint16_t opcode, uint8_t *buf, uint8_t len) -{ - bdt_log("DUT MODE RECV : NOT IMPLEMENTED"); -} - -static void le_test_mode(bt_status_t status, uint16_t packet_count) -{ - bdt_log("LE TEST MODE END status:%s number_of_packets:%d", - dump_bt_status(status), packet_count); -} - -extern int timer_create (clockid_t, struct sigevent *__restrict, timer_t * -__restrict); -extern int timer_settime (timer_t, int, const struct itimerspec *__restrict, -struct itimerspec *__restrict); - -static bool set_wake_alarm(uint64_t delay_millis, bool should_wake, alarm_cb -cb, void *data) -{ - - static timer_t timer; - static bool timer_created; - - if (!timer_created) { - struct sigevent sigevent; - memset(&sigevent, 0, sizeof(sigevent)); - sigevent.sigev_notify = SIGEV_THREAD; - sigevent.sigev_notify_function = (void (*)(union sigval))cb; - sigevent.sigev_value.sival_ptr = data; - timer_create(CLOCK_MONOTONIC, &sigevent, &timer); - timer_created = true; - } - - struct itimerspec new_value; - new_value.it_value.tv_sec = delay_millis / 1000; - new_value.it_value.tv_nsec = (delay_millis % 1000) * 1000 * 1000; - new_value.it_interval.tv_sec = 0; - new_value.it_interval.tv_nsec = 0; - timer_settime(timer, 0, &new_value, NULL); - - return TRUE; -} - -static int acquire_wake_lock(const char *lock_name) -{ - return BT_STATUS_SUCCESS; -} - -static int release_wake_lock(const char *lock_name) -{ - return BT_STATUS_SUCCESS; -} - -static bt_callbacks_t bt_callbacks = { - sizeof(bt_callbacks_t), - adapter_state_changed, - adapter_properties_changed, /*adapter_properties_cb */ - NULL, /* remote_device_properties_cb */ - NULL, /* device_found_cb */ - discovery_state_changed, /* discovery_state_changed_cb */ - pin_request_cb, /* pin_request_cb */ - ssp_request_cb, /* ssp_request_cb */ - bond_state_changed_cb, /* bond_state_changed_cb */ - address_consolidate_cb, /* address_consolidate_cb */ - acl_state_changed, /* acl_state_changed_cb */ - NULL, /* thread_evt_cb */ - dut_mode_recv, /*dut_mode_recv_cb */ - le_test_mode, /* le_test_mode_cb */ - NULL /*energy_info_cb*/ -}; - -static bt_os_callouts_t bt_os_callbacks = { - sizeof(bt_os_callouts_t), - set_wake_alarm, - acquire_wake_lock, - release_wake_lock -}; - - -void bdt_enable(void) -{ - bdt_log("ENABLE BT"); - if (bt_enabled) { - bdt_log("Bluetooth is already enabled"); - return; - } - status = sBtInterface->enable(); - - check_return_status(status); -} - -void bdt_disable(void) -{ - bdt_log("DISABLE BT"); - if (!bt_enabled) { - bdt_log("Bluetooth is already disabled"); - return; - } - status = sBtInterface->disable(); - - check_return_status(status); -} - -void do_pairing(char *p) -{ - RawAddress bd_addr = {{0}}; - int transport = GATT_TRANSPORT_LE; - if(FALSE == GetBdAddr(p, &bd_addr)) return; // arg1 - if(BT_STATUS_SUCCESS != sBtInterface->create_bond(&bd_addr, transport)) - { - printf("Failed to Initiate Pairing \n"); - return; - } -} - - -void bdt_cleanup(void) -{ - bdt_log("CLEANUP"); - sBtInterface->cleanup(); -} - -/****************************************************************************** -* - ** Console commands - -*******************************************************************************/ - -void do_help(char *p) -{ - int i = 0; - char line[128]; -// int pos = 0; - - while (console_cmd_list[i].name != NULL) - { - snprintf(line, 128,"%s", (char*)console_cmd_list[i].name); - bdt_log("%s %s\n", (char*)line, (char*)console_cmd_list[i].help); - i++; - } -} - -void do_quit(char *p) -{ - bdt_shutdown(); -} - -/******************************************************************* - * - * BT TEST CONSOLE COMMANDS - * - * Parses argument lists and passes to API test function - * -*/ - -void do_init(char *p) -{ - bdt_init(); -} - -void do_enable(char *p) -{ - bdt_enable(); -} - -using bluetooth::bap::pacs::PacsClientInterface; -using bluetooth::bap::pacs::PacsClientCallbacks; - -static PacsClientInterface* sPacsClientInterface = nullptr; -static uint16_t pacs_client_id = 0; -static uint8_t pacsSearchComplete = 0; -static uint8_t pacsConnectionComplete = 0; -static uint8_t bapConnectionComplete = 0; -static RawAddress pac_bd_addr; - -class PacsClientCallbacksImpl : public PacsClientCallbacks { - public: - ~PacsClientCallbacksImpl() = default; - void OnInitialized(int status, - int client_id) override { - printf("%d\n", client_id); - pacs_client_id = client_id; - } - void OnConnectionState(const RawAddress& bd_addr, - bluetooth::bap::pacs::ConnectionState state) -override { - printf("%s\n", __func__); - if(state == bluetooth::bap::pacs::ConnectionState::CONNECTED) { - printf("%s Connected\n", __func__); - pacsConnectionComplete = 1; - } else if(state == bluetooth::bap::pacs::ConnectionState::DISCONNECTED) { - printf("%s Disconnected\n", __func__); - } - } - void OnAudioContextAvailable(const RawAddress& bd_addr, - uint32_t available_contexts) override { - printf("%s\n", __func__); - } - void OnSearchComplete(int status, const RawAddress& address, - std::vector sink_pac_records, - std::vector src_pac_records, - uint32_t sink_locations, - uint32_t src_locations, - uint32_t available_contexts, - uint32_t supported_contexts) override { - pacsSearchComplete = 1; - printf("%s\n", __func__); - } -}; - -static PacsClientCallbacksImpl sPacsClientCallbacks; - -void do_pacs_discovery(char *p) -{ - if(FALSE == GetBdAddr(p, &pac_bd_addr)) return; // arg1 - sPacsClientInterface = (PacsClientInterface*) - sBtInterface->get_profile_interface(BT_PROFILE_PACS_CLIENT_ID); - sPacsClientInterface->Init(&sPacsClientCallbacks); - sleep(1); - printf("%s going for connect\n", __func__); - sPacsClientInterface->Connect(pacs_client_id, pac_bd_addr); - while(!pacsConnectionComplete) sleep(1); - printf("%s going for discovery\n", __func__); - sPacsClientInterface->StartDiscovery(pacs_client_id, pac_bd_addr); - while(!pacsSearchComplete) sleep(1); - printf("%s going for disconnect\n", __func__); - sleep(5); - sPacsClientInterface->Disconnect(pacs_client_id, pac_bd_addr); -} - -using bluetooth::bap::ascs::AscsClientInterface; -using bluetooth::bap::ascs::AscsClientCallbacks; - -static AscsClientInterface* sAscsClientInterface = nullptr; -static uint16_t ascs_client_id = 0; -static uint8_t ascsSearchComplete = 0; -static uint8_t ascsConnectionComplete = 0; -static RawAddress ascs_bd_addr; - -class AscsClientCallbacksImpl : public AscsClientCallbacks { - public: - ~AscsClientCallbacksImpl() = default; - void OnAscsInitialized(int status, int client_id) override { - printf("%d\n", client_id); - ascs_client_id = client_id; - } - - void OnConnectionState(const RawAddress& address, - bluetooth::bap::ascs::GattState state) override { - printf("%s\n", __func__); - if(state == bluetooth::bap::ascs::GattState::CONNECTED) { - printf("%s Connected\n", __func__); - ascsConnectionComplete = 1; - } else if(state == bluetooth::bap::ascs::GattState::DISCONNECTED) { - printf("%s Disconnected\n", __func__); - } - } - - void OnAseOpFailed(const RawAddress& address, - bluetooth::bap::ascs::AseOpId ase_op_id, - std::vector status) { - printf("%s\n", __func__); - - } - - void OnAseState(const RawAddress& address, - bluetooth::bap::ascs::AseParams ase) override { - printf("%s\n", __func__); - } - - void OnSearchComplete(int status, const RawAddress& address, - std::vector sink_ase_list, - std::vector src_ase_list) override { - printf("%s\n", __func__); - ascsSearchComplete = 1; - } -}; - -static AscsClientCallbacksImpl sAscsClientCallbacks; - -void do_ascs_discovery(char *p) -{ - if(FALSE == GetBdAddr(p, &ascs_bd_addr)) return; // arg1 - sAscsClientInterface = (AscsClientInterface*) - sBtInterface->get_profile_interface(BT_PROFILE_ASCS_CLIENT_ID); - sAscsClientInterface->Init(&sAscsClientCallbacks); - sleep(1); - printf("%s going for connect\n", __func__); - sAscsClientInterface->Connect(ascs_client_id, ascs_bd_addr); - while(!ascsConnectionComplete) sleep(1); - printf("%s going for discovery\n", __func__); - sAscsClientInterface->StartDiscovery(ascs_client_id, ascs_bd_addr); - while(!ascsSearchComplete) sleep(1); - printf("%s going for disconnect\n", __func__); - sAscsClientInterface->Disconnect(ascs_client_id, ascs_bd_addr); -} - -template -std::string loghex(T x) { - std::stringstream tmp; - tmp << "0x" << std::internal << std::hex << std::setfill('0') - << std::setw(sizeof(T) * 2) << (unsigned int)x; - return tmp.str(); -} - -using bluetooth::bap::ucast::UcastClientCallbacks; -using bluetooth::bap::ucast::UcastClientInterface; - -static UcastClientInterface* sUcastClientInterface = nullptr; - -class UcastClientCallbacksImpl : public UcastClientCallbacks { - public: - ~UcastClientCallbacksImpl() = default; - void OnStreamState(const RawAddress &address, - std::vector streams_state_info) override { - for (auto it = streams_state_info.begin(); - it != streams_state_info.end(); it++) { - printf("%s stream type %d\n", __func__, (it->stream_type.type)); - printf("%s stream dir %s\n", __func__, loghex(it->stream_type.direction).c_str()); - printf("%s stream state %d\n", __func__, static_cast (it->stream_state)); - if(static_cast (it->stream_state) == 2 || - static_cast (it->stream_state) == 0) { - bapConnectionComplete = 1; - } - } - } - void OnStreamConfig(const RawAddress &address, - std::vector streams_config_info) override { - printf("%s\n",__func__); - } - void OnStreamAvailable(const RawAddress &address, - uint16_t src_audio_contexts, - uint16_t sink_audio_contexts) override { - printf("%s\n",__func__); - } -}; - -static UcastClientCallbacksImpl sUcastClientCallbacks; - -typedef struct { - char bdAddr[13]; - uint16_t profile; - uint16_t context; - uint8_t direction; -} Servers; - -typedef struct { - uint8_t cnt; - char codecConfig[7]; - char audioConfig[5]; - std::vector serv; -} UserParms; - -typedef struct { - uint8_t audio_dir; - uint8_t stereo; -} AudioType; - -typedef struct { - uint8_t num_servers; - uint8_t num_cises; - std::vector audio_type; -} AudioConfigSettings; - -// - -std::map audioConfigMap = { - {"1_1", {1, 1, {{ASE_DIRECTION_SINK, 0}}}}, // EB streaming - {"2_1", {1, 1, {{ASE_DIRECTION_SRC, 0}}}}, // EB Recording - {"3_1", {1, 1, {{ASE_DIRECTION_SRC|ASE_DIRECTION_SINK, 0}}}}, // EB Call Mono Bi-Dir CIS - {"4_1", {1, 1, {{ASE_DIRECTION_SINK, ASE_SINK_STEREO}}}}, // Stereo Headset stereo streaming - - {"5_1", {1, 1, {{ASE_DIRECTION_SRC|ASE_DIRECTION_SINK, ASE_SINK_STEREO}}}}, // EB Call with speaker stereo mono mic - - {"6_1", {1, 2, {{ASE_DIRECTION_SINK, 0}, {ASE_DIRECTION_SINK, 0}}}}, // TWM Streaming - {"6_2", {2, 2, {{ASE_DIRECTION_SINK, 0}, {ASE_DIRECTION_SINK, 0}}}}, // EBP Streaming same as 1_1 - {"7_1", {1, 2, {{ASE_DIRECTION_SINK, 0}, {ASE_DIRECTION_SRC, 0}}}}, // EB Call with dual CIS ( same as 3_1) - {"7_2", {2, 2, {{ASE_DIRECTION_SINK, 0}, {ASE_DIRECTION_SRC, 0}}}}, // EBP Call with speaker on EB1 and mic on EB2 - {"8_1", {1, 2, {{ASE_DIRECTION_SINK, 0}, {ASE_DIRECTION_SRC|ASE_DIRECTION_SINK, 0}}}}, // Headset Call with single mic - {"8_2", {2, 2, {{ASE_DIRECTION_SRC|ASE_DIRECTION_SINK, 0}, {ASE_DIRECTION_SINK, 0}}}}, // EBP Call with mic from one EB - {"9_1", {1, 2, {{ASE_DIRECTION_SRC, 0}, {ASE_DIRECTION_SRC, 0}}}}, // TWM Recording - {"9_2", {2, 2, {{ASE_DIRECTION_SRC, 0}, {ASE_DIRECTION_SRC, 0}}}}, // EBP Recording -{"10_1", {1, 1, {{ASE_DIRECTION_SRC, ASE_SRC_STEREO}}}}, // EB stereo Recording -{"11_1", {1, 2, {{ASE_DIRECTION_SRC|ASE_DIRECTION_SINK, 0}, {ASE_DIRECTION_SRC|ASE_DIRECTION_SINK, 0}}}}, // TWM Call -{"11_2", {2, 2, {{ASE_DIRECTION_SRC|ASE_DIRECTION_SINK, 0}, {ASE_DIRECTION_SRC|ASE_DIRECTION_SINK, 0}}}}}; // EBP Call - -int getInt(std::string &str) -{ - int ret; - std::stringstream integer(str); - integer >> ret; - return ret; -} - -void parse_parms(char *p, UserParms *ptr) -{ - std::string line(p); - std::vector token; - std::stringstream check1(line); - std::string intermediate; - while(getline(check1, intermediate, ' ')) - { - token.push_back(intermediate); - } - ptr->cnt = token.size(); - if (ptr->cnt == 11) - { - memcpy(ptr->codecConfig, token[1].c_str(), token[1].size()); - memcpy(ptr->audioConfig, token[2].c_str(), token[2].size()); - Servers serv1, serv2; - memcpy(serv1.bdAddr, token[3].c_str(), token[3].size()); - serv1.profile = static_cast(getInt(token[4])); - serv1.direction = static_cast(getInt(token[5])); - serv1.context = static_cast(getInt(token[6])); - ptr->serv.push_back(serv1); - memcpy(serv2.bdAddr, token[7].c_str(), token[7].size()); - serv2.profile = static_cast(getInt(token[8])); - serv2.direction = static_cast(getInt(token[9])); - serv2.context = static_cast(getInt(token[10])); - ptr->serv.push_back(serv2); - } - else if (ptr->cnt == 9) - { - Servers serv1, serv2; - memcpy(serv1.bdAddr, token[1].c_str(), token[1].size()); - serv1.profile = static_cast(getInt(token[2])); - serv1.direction = static_cast(getInt(token[3])); - serv1.context = static_cast(getInt(token[4])); - ptr->serv.push_back(serv1); - memcpy(serv2.bdAddr, token[5].c_str(), token[5].size()); - serv2.profile = static_cast(getInt(token[6])); - serv2.direction = static_cast(getInt(token[7])); - serv2.context = static_cast(getInt(token[8])); - ptr->serv.push_back(serv2); - } - else if (ptr->cnt == 7) - { - memcpy(ptr->codecConfig, token[1].c_str(), token[1].size()); - memcpy(ptr->audioConfig, token[2].c_str(), token[2].size()); - Servers serv1; - memcpy(serv1.bdAddr, token[3].c_str(), token[3].size()); - serv1.profile = static_cast(getInt(token[4])); - serv1.direction = static_cast(getInt(token[5])); - serv1.context = static_cast(getInt(token[6])); - ptr->serv.push_back(serv1); - } - else if (ptr->cnt == 5) - { - Servers serv1; - memcpy(serv1.bdAddr, token[1].c_str(), token[1].size()); - serv1.profile = static_cast(getInt(token[2])); - serv1.direction = static_cast(getInt(token[3])); - serv1.context = static_cast(getInt(token[4])); - ptr->serv.push_back(serv1); - } - else - { - printf("%s ERROR: Input\n", __func__); - } -} - -constexpr uint8_t CONFIG_FRAME_DUR_INDEX = 0x04; -constexpr uint8_t CONFIG_OCTS_PER_FRAME_INDEX = 0x04; -constexpr uint8_t CONFIG_PREF_AUDIO_CONT_INDEX = 0x06; // CS1 - -bool UpdateFrameDuration(bluetooth::bap::pacs::CodecConfig *config , - uint8_t frame_dur) { - uint64_t value = 0xFF; - config->codec_specific_1 &= - ~(value << (CONFIG_FRAME_DUR_INDEX*8)); - config->codec_specific_1 |= - static_cast(frame_dur) << (CONFIG_FRAME_DUR_INDEX * 8); - return true; -} - - -bool UpdatePreferredAudioContext(bluetooth::bap::pacs::CodecConfig *config , - uint16_t pref_audio_context) { - uint64_t value = 0xFFFF; - config->codec_specific_1 &= ~(value << (CONFIG_PREF_AUDIO_CONT_INDEX*8)); - config->codec_specific_1 |= static_cast(pref_audio_context) << - (CONFIG_PREF_AUDIO_CONT_INDEX * 8); - return true; -} - -bool UpdateOctsPerFrame(bluetooth::bap::pacs::CodecConfig *config , - uint16_t octs_per_frame) { - uint64_t value = 0xFFFF; - config->codec_specific_2 &= - ~(value << (CONFIG_OCTS_PER_FRAME_INDEX * 8)); - config->codec_specific_2 |= - static_cast(octs_per_frame) << (CONFIG_OCTS_PER_FRAME_INDEX * 8); - return true; -} - -void set_conn_info(bluetooth::bap::ucast::StreamConnect *conn_info, int type, int context, int dir) -{ - conn_info->stream_type.type = type; - conn_info->stream_type.direction = dir; - conn_info->stream_type.audio_context = context; -} - -bluetooth::bap::pacs::CodecSampleRate get_sample_rate (char *p) -{ - std::string str = p; - if (str.find("16_") != std::string::npos) - return bluetooth::bap::pacs::CodecSampleRate::CODEC_SAMPLE_RATE_16000; - else if (str.find("24_") != std::string::npos) - return bluetooth::bap::pacs::CodecSampleRate::CODEC_SAMPLE_RATE_24000; - else if (str.find("32_") != std::string::npos) - return bluetooth::bap::pacs::CodecSampleRate::CODEC_SAMPLE_RATE_32000; - else if (str.find("48_") != std::string::npos) - return bluetooth::bap::pacs::CodecSampleRate::CODEC_SAMPLE_RATE_48000; - else if (str.find("8_") != std::string::npos) - return bluetooth::bap::pacs::CodecSampleRate::CODEC_SAMPLE_RATE_8000; - else - return bluetooth::bap::pacs::CodecSampleRate::CODEC_SAMPLE_RATE_NONE; -} - -int get_frame_duration (char *p) -{ - std::string str = p; - int ret; - if ((str.find("_1_") != std::string::npos) || - (str.find("_3_") != std::string::npos) || - (str.find("_5_") != std::string::npos)) - ret = static_cast(bluetooth::bap::pacs::CodecFrameDuration::FRAME_DUR_7_5); - else if ((str.find("_2_") != std::string::npos) || - (str.find("_4_") != std::string::npos) || - (str.find("_6_") != std::string::npos)) - ret = static_cast(bluetooth::bap::pacs::CodecFrameDuration::FRAME_DUR_10); - else - ret = -1; - return ret; -} - -int get_sdu_interval (char *p) -{ - std::string str = p; - int ret; - if ((str.find("_1_") != std::string::npos) || - (str.find("_3_") != std::string::npos) || - (str.find("_5_") != std::string::npos)) - ret = 7500; - else if ((str.find("_2_") != std::string::npos) || - (str.find("_4_") != std::string::npos) || - (str.find("_6_") != std::string::npos)) - ret = 10000; - else - ret = -1; - return ret; -} - -std::map octetPerFrame = -{{"8_1", 26},{"8_2", 30},{"16_1", 30},{"16_2", 40}, -{"24_1", 45},{"24_2", 60},{"32_1", 60},{"32_2", 80}, -{"48_1", 75},{"48_2", 100},{"48_3", 90},{"48_4", 120}, -{"48_5", 117},{"48_6", 155}}; - -int get_octetPerFrame (char *p) -{ - std::string str = p; - int ret = -1; - size_t pos = str.rfind('_'); - std::string key = str.substr(0, pos); - for (std::map::iterator it = - octetPerFrame.begin(); it != octetPerFrame.end(); it++) - { - if (key.compare(it->first) == 0) - ret = it->second; - } - return ret; -} - -std::map tport_latency = -{{"8_1_1", 8},{"16_1_1", 8},{"24_1_1", 8},{"32_1_1", 8}, - {"8_2_1", 10},{"16_2_1", 10},{"24_2_1", 10},{"32_2_1", 10}, -{"48_1_1", 15},{"48_3_1", 15},{"48_5_1", 15}, -{"48_2_1", 20},{"48_4_1", 20},{"48_6_1", 20}, - {"8_1_2", 75},{"16_1_2", 75},{"24_1_2", 75}, -{"31_1_2", 75},{"48_1_2", 75},{"48_3_2", 75},{"48_5_2", 75}, - {"8_2_2", 95},{"16_2_2", 95},{"24_2_2", 95}, -{"32_2_2", 95},{"48_2_2", 95}, -{"48_4_2", 100},{"48_6_2", 100}}; - -int get_tport_latency (char *p) -{ - std::string str = p; - for (std::map::iterator it = tport_latency.begin(); - it != tport_latency.end(); it++) - { - if (str.compare(it->first) == 0) - return it->second; - } - return -1; -} - -int get_rtn (char *p) -{ - std::string str = p; - int ret; - size_t pos = str.rfind('_'); - std::string key = str.substr(pos); - if (str.find("_1_2") != std::string::npos || - str.find("_2_2") != std::string::npos || - str.find("_3_2") != std::string::npos || - str.find("_4_2") != std::string::npos || - str.find("_5_2") != std::string::npos || - str.find("_6_2") != std::string::npos ) { - ret = 13; - return ret; - } - if (str.find("48_") != std::string::npos) - ret = 5; - if ((str.find("8_") != std::string::npos) || - (str.find("16_") != std::string::npos) || - (str.find("24_") != std::string::npos) || - (str.find("32_") != std::string::npos)) - ret = 2; - else - ret = -1; - return ret; -} - -int getAudioConfigSettings(char *p, AudioConfigSettings *ptr) -{ - int ret = -1; - std::string key = p; - for (std::map::iterator it = - audioConfigMap.begin(); - it != audioConfigMap.end(); it++) - { - if (key.compare(it->first) == 0) - { - *ptr = it->second; - printf(" %s ERROR: audio type 0 %d \n", __func__, ptr->audio_type[0].audio_dir); - printf(" %s ERROR: audio type 1 %d \n", __func__, ptr->audio_type[1].audio_dir); - //memcpy(ptr, &it->second, sizeof(AudioConfigSettings)); - ret = 0; - } - } - return ret; -} - -typedef struct -{ - uint8_t A; - uint8_t B; - uint8_t C; -} setFormat; - -void set(void *dest, setFormat src) -{ - memcpy(dest, &src, sizeof(setFormat)); -} - -void set_codec_qos_config (bluetooth::bap::ucast::CodecQosConfig *codec_qos_config, - char *codecConfig, AudioConfigSettings *acs, - uint8_t audio_direction, uint16_t context, - uint8_t server_id, - uint8_t server_count, uint8_t total_servers) -{ - int frameDuration, octetPerFrame, tport_latency, sdu_interval, rtn, cis_t; - bluetooth::bap::pacs::CodecSampleRate sampleRate; - bool stereo_t = false; - bluetooth::bap::ucast::CIGConfig cig_config; - sampleRate = get_sample_rate(codecConfig); - printf("Sample Rate %d\n", sampleRate); - printf("server_id %d\n", server_id); - - if (sampleRate == bluetooth::bap::pacs::CodecSampleRate::CODEC_SAMPLE_RATE_NONE) - { - printf(" %s ERROR: sample rate\n", __func__); - exit(0); - } - frameDuration = get_frame_duration(codecConfig); - if (frameDuration < 0) - { - printf(" %s ERROR: frame duration\n", __func__); - exit(0); - } - octetPerFrame = get_octetPerFrame(codecConfig); - if (octetPerFrame < 0) - { - printf(" %s ERROR: octet per frame\n", __func__); - exit(0); - } - tport_latency = get_tport_latency(codecConfig); - if (tport_latency < 0) - { - printf(" %s ERROR: max transport latency\n", __func__); - exit(0); - } - rtn = get_rtn(codecConfig); - if (rtn < 0) - { - printf(" %s ERROR: re-transmission\n", __func__); - exit(0); - } - sdu_interval = get_sdu_interval(codecConfig); - codec_qos_config->codec_config.codec_type = - bluetooth::bap::pacs::CodecIndex::CODEC_INDEX_SOURCE_LC3; - codec_qos_config->codec_config.codec_priority = - bluetooth::bap::pacs::CodecPriority::CODEC_PRIORITY_DEFAULT; - codec_qos_config->codec_config.sample_rate = sampleRate; - UpdateFrameDuration(&codec_qos_config->codec_config, - static_cast(frameDuration)); - UpdatePreferredAudioContext(&codec_qos_config->codec_config, context); - cig_config.cig_id = 1; - cig_config.cis_count = acs->num_cises; - cig_config.packing = 0x01; // interleaved - cig_config.framing = 0x00; // unframed - cig_config.max_tport_latency_m_to_s = static_cast(tport_latency); - cig_config.max_tport_latency_s_to_m = static_cast(tport_latency); - if (sdu_interval == 7500) - { - set(&cig_config.sdu_interval_m_to_s, {0x4C, 0x1D, 0x00}); - set(&cig_config.sdu_interval_s_to_m, {0x4C, 0x1D, 0x00}); - } - else - { - set(&cig_config.sdu_interval_m_to_s, {0x10, 0x27, 0x00}); - set(&cig_config.sdu_interval_s_to_m, {0x10, 0x27, 0x00}); - } - memcpy(&codec_qos_config->qos_config.cig_config, - &cig_config, sizeof(cig_config)); - for (uint8_t i = 0; i < acs->num_cises; i++) { - bluetooth::bap::ucast::CISConfig cis_config; - bluetooth::bap::ucast::ASCSConfig ascs_config; - int max_sdu_m_to_s; - int max_sdu_s_to_m; - cis_config.cis_id = i; - ascs_config.cig_id = 1; - ascs_config.cis_id = i; - max_sdu_m_to_s = max_sdu_s_to_m = get_octetPerFrame(codecConfig); - printf("audio_dir %d\n", acs->audio_type[i].audio_dir); - printf("max_sdu_m_to_s %d\n", max_sdu_m_to_s); - printf("max_sdu_s_to_m %d\n", max_sdu_s_to_m); - if(acs->audio_type[i].stereo & ASE_SRC_STEREO) { - max_sdu_s_to_m *= 2; - if(audio_direction & ASE_DIRECTION_SRC) stereo_t = true; - } - if(acs->audio_type[i].stereo & ASE_SINK_STEREO) { - max_sdu_m_to_s *= 2; - if(audio_direction & ASE_DIRECTION_SINK) stereo_t = true; - } - - if (acs->audio_type[i].audio_dir == (ASE_DIRECTION_SINK|ASE_DIRECTION_SRC)) - { - printf("i %d Filling both m to s and s to m \n", i); - cis_config.max_sdu_m_to_s = static_cast(max_sdu_m_to_s); - cis_config.max_sdu_s_to_m = static_cast(max_sdu_s_to_m); - ascs_config.bi_directional = true; - } - else if (acs->audio_type[i].audio_dir == ASE_DIRECTION_SRC) - { - printf("i %d Filling s to m \n", i); - cis_config.max_sdu_s_to_m = static_cast(max_sdu_s_to_m); - cis_config.max_sdu_m_to_s = 0; - ascs_config.bi_directional = false; - } - else if (acs->audio_type[i].audio_dir == ASE_DIRECTION_SINK) - { - printf("i %d Filling m to s \n", i); - cis_config.max_sdu_m_to_s = static_cast(max_sdu_m_to_s); - cis_config.max_sdu_s_to_m = 0; - ascs_config.bi_directional = false; - } - cis_config.phy_m_to_s = 0x02; - cis_config.phy_s_to_m = 0x02; - cis_config.rtn_m_to_s = static_cast(rtn); - cis_config.rtn_s_to_m = static_cast(rtn); - printf("rtn %d \n", rtn); - set(&ascs_config.presentation_delay, {0x40, 0x9C, 0x00}); - codec_qos_config->qos_config.cis_configs.push_back(cis_config); - - - printf("i %d server_id %d \n", i, server_id); - if(total_servers == 1) { - if(acs->num_cises == 1) { - codec_qos_config->qos_config.ascs_configs.push_back(ascs_config); - } else if(acs->num_cises == 2) { - if(acs->audio_type[i % acs->num_cises].audio_dir == - acs->audio_type[(i + 1) % acs->num_cises].audio_dir) { - codec_qos_config->qos_config.ascs_configs.push_back(ascs_config); - } else if( i == server_count) { - codec_qos_config->qos_config.ascs_configs.push_back(ascs_config); - } - } - } else if(total_servers == 2) { - if(i == server_id) { - codec_qos_config->qos_config.ascs_configs.push_back(ascs_config); - } - } - } - if (stereo_t == true) { - codec_qos_config->codec_config.channel_mode = - bluetooth::bap::pacs::CodecChannelMode::CODEC_CHANNEL_MODE_STEREO; - UpdateOctsPerFrame(&codec_qos_config->codec_config, - static_cast(octetPerFrame*2)); - } else { - codec_qos_config->codec_config.channel_mode = - bluetooth::bap::pacs::CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - UpdateOctsPerFrame(&codec_qos_config->codec_config, - static_cast(octetPerFrame)); - } -} - -void do_bap_connect (char *p) -{ - UserParms args; - parse_parms(p, &args); - bluetooth::bap::ucast::CodecQosConfig codec_qos_config; - bluetooth::bap::ucast::CodecQosConfig codec_qos_config_2; - AudioConfigSettings acs; - bapConnectionComplete = 0; - if (getAudioConfigSettings(args.audioConfig, &acs) < 0) - { - printf("%s ERROR: AudioConfig\n", __func__); - exit(0); - } - //set_codec_qos_config(&codec_qos_config, args.codecConfig, &acs); - for (uint8_t i = 0; i < args.serv.size(); i++) { - RawAddress bap_bd_addr; - bluetooth::bap::ucast::StreamConnect conn_info; - std::vector streams; - codec_qos_config.qos_config.cis_configs.clear(); - codec_qos_config.qos_config.ascs_configs.clear(); - codec_qos_config_2.qos_config.cis_configs.clear(); - codec_qos_config_2.qos_config.ascs_configs.clear(); - if(FALSE == GetBdAddr(args.serv[i].bdAddr, &bap_bd_addr)) return; - if (args.serv[i].direction & ASE_DIRECTION_SINK) - { - set_codec_qos_config(&codec_qos_config, args.codecConfig, - &acs, ASE_DIRECTION_SINK, args.serv[i].context, - i, 0, - args.serv.size()); - set_conn_info(&conn_info, args.serv[i].profile, - args.serv[i].context, ASE_DIRECTION_SINK); - printf("%s ERROR: context %d\n", __func__, args.serv[i].context); - conn_info.codec_qos_config_pair.push_back(codec_qos_config); - streams.push_back(conn_info); - } - if (args.serv[i].direction & ASE_DIRECTION_SRC) - { - set_codec_qos_config(&codec_qos_config_2, args.codecConfig, - &acs, ASE_DIRECTION_SRC, args.serv[i].context, - i, 1, - args.serv.size()); - set_conn_info(&conn_info, args.serv[i].profile, - args.serv[i].context, ASE_DIRECTION_SRC); - printf("%s ERROR: context %d\n", __func__, args.serv[i].context); - conn_info.codec_qos_config_pair.push_back(codec_qos_config_2); - streams.push_back(conn_info); - } - std::vector address; - address.push_back(bap_bd_addr); - sUcastClientInterface->Connect(address, true, streams); - } - while(!bapConnectionComplete) sleep(1); -} - -void do_bap_disconnect (char *p) -{ - UserParms args; - parse_parms(p, &args); - for (uint8_t i = 0; i < ((args.cnt)/4); i++) { - RawAddress bap_bd_addr; - if(FALSE == GetBdAddr(args.serv[i].bdAddr, &bap_bd_addr)) return; - std::vector streams; - if (args.serv[i].direction & 1) { - bluetooth::bap::ucast::StreamType type_1 = - { .type = static_cast(args.serv[i].profile), - .audio_context = args.serv[i].context, - .direction = 1 - }; - streams.push_back(type_1); - } - if (args.serv[i].direction & 2) { - bluetooth::bap::ucast::StreamType type_1 = - { .type = static_cast(args.serv[i].profile), - .audio_context = args.serv[i].context, - .direction = 2 - }; - streams.push_back(type_1); - } - sUcastClientInterface->Disconnect(bap_bd_addr, streams); - } -} - -void do_bap_start (char *p) -{ - UserParms args; - parse_parms(p, &args); - for (uint8_t i = 0; i < ((args.cnt)/4); i++) { - RawAddress bap_bd_addr; - if(FALSE == GetBdAddr(args.serv[i].bdAddr, &bap_bd_addr)) return; - std::vector streams; - if (args.serv[i].direction & 1) { - bluetooth::bap::ucast::StreamType type_1 = - { .type = static_cast(args.serv[i].profile), - .audio_context = args.serv[i].context, - .direction = 1 - }; - streams.push_back(type_1); - } - if (args.serv[i].direction & 2) { - bluetooth::bap::ucast::StreamType type_1 = - { .type = static_cast(args.serv[i].profile), - .audio_context = args.serv[i].context, - .direction = 2 - }; - streams.push_back(type_1); - } - sUcastClientInterface->Start(bap_bd_addr, streams); - } -} - -void do_bap_stop (char *p) -{ - UserParms args; - parse_parms(p, &args); - for (uint8_t i = 0; i < ((args.cnt)/4); i++) { - RawAddress bap_bd_addr; - if(FALSE == GetBdAddr(args.serv[i].bdAddr, &bap_bd_addr)) return; - std::vector streams; - if (args.serv[i].direction & 1) { - bluetooth::bap::ucast::StreamType type_1 = - { .type = static_cast(args.serv[i].profile), - .audio_context = args.serv[i].context, - .direction = 1 - }; - streams.push_back(type_1); - } - if (args.serv[i].direction & 2) { - bluetooth::bap::ucast::StreamType type_1 = - { .type = static_cast(args.serv[i].profile), - .audio_context = args.serv[i].context, - .direction = 2 - }; - streams.push_back(type_1); - } - sUcastClientInterface->Stop(bap_bd_addr, streams); - } -} - -void do_bap_disc_in_connecting (char *p) -{ - int del; - printf("Enter the delay (ms)> "); - std::cin >> del; - do_bap_connect(p); - usleep(del *1000); - do_bap_disconnect(p); -} - -void do_bap_disc_in_starting (char *p) -{ - int del; - printf("Enter the delay (ms)> "); - std::cin >> del; - do_bap_start(p); - usleep(del *1000); - do_bap_disconnect(p); -} - -void do_bap_disc_in_stopping (char *p) -{ - int del; - printf("Enter the delay (ms)> "); - std::cin >> del; - do_bap_stop(p); - usleep(del *1000); - do_bap_disconnect(p); -} - -void do_bap_stop_in_starting (char *p) -{ - int del; - printf("Enter the delay (ms)> "); - std::cin >> del; - do_bap_start(p); - usleep(del *1000); - do_bap_stop(p); -} - -void do_bap_update_stream (char *p) -{ - UserParms args; - parse_parms(p, &args); - for (uint8_t i = 0; i < ((args.cnt)/4); i++) { - RawAddress bap_bd_addr; - if(FALSE == GetBdAddr(args.serv[i].bdAddr, &bap_bd_addr)) return; - std::vector Update_Stream; - if (args.serv[i].direction & 1) { - bluetooth::bap::ucast::StreamType type_1 = - { .type = static_cast(args.serv[i].profile), - .direction = 1 - }; - bluetooth::bap::ucast::StreamUpdate sUpdate = - { - type_1, - bluetooth::bap::ucast::StreamUpdateType::STREAMING_CONTEXT, - args.serv[i].context - }; - Update_Stream.push_back(sUpdate); - } - if (args.serv[i].direction & 2) { - bluetooth::bap::ucast::StreamType type_1 = - { .type = static_cast(args.serv[i].profile), - .direction = 2 - }; - bluetooth::bap::ucast::StreamUpdate sUpdate = - { - type_1, - bluetooth::bap::ucast::StreamUpdateType::STREAMING_CONTEXT, - args.serv[i].context - }; - Update_Stream.push_back(sUpdate); - } - sUcastClientInterface->UpdateStream(bap_bd_addr, Update_Stream); - } -} - -void do_disable(char *p) -{ - bdt_disable(); -} - -void do_cleanup(char *p) -{ - bdt_cleanup(); -} - -void bdt_init(void) -{ - bdt_log("INIT BT "); - status = sBtInterface->init(&bt_callbacks, false, false, 0, nullptr, false); - sleep(1); - if (status == BT_STATUS_SUCCESS) { - status = sBtInterface->set_os_callouts(&bt_os_callbacks); - } - check_return_status(status); -} - -/****************************************************************************** -* - ** GATT SERVER API commands - -*******************************************************************************/ - -/* - * Main console command handler -*/ - -static void process_cmd(char *p, unsigned char is_job) -{ - char cmd[2048]; - int i = 0; - bt_pin_code_t pincode; - char *p_saved = p; - - get_str(&p, cmd); - - /* table commands */ - while (console_cmd_list[i].name != NULL) - { - if (is_cmd(console_cmd_list[i].name)) - { - if (!is_job && console_cmd_list[i].is_job) - create_cmdjob(p_saved); - else - { - console_cmd_list[i].handler(p); - } - return; - } - i++; - } - //pin key - if(cmd[6] == '.') { - for(i=0; i<6; i++) { - pincode.pin[i] = cmd[i]; - } - if(BT_STATUS_SUCCESS != sBtInterface->pin_reply(remote_bd_address, -TRUE, strlen((const char*)pincode.pin), &pincode)) { - printf("Pin Reply failed\n"); - } - //flush the char for pinkey - cmd[6] = 0; - } - else { - bdt_log("%s : unknown command\n", p_saved); - do_help(NULL); - } -} - -int main() -{ - config_permissions(); - bdt_log("\n:::::::::::::::::::::::::::::::::::::::::::::::::::"); - bdt_log(":: Bluedroid test app starting"); - - if ( HAL_load() < 0 ) { - perror("HAL failed to initialize, exit\n"); - unlink(PID_FILE); - exit(0); - } - - setup_test_env(); - - /* Automatically perform the init */ - bdt_init(); - sleep(5); - bdt_enable(); - sleep(5); - - sUcastClientInterface = (UcastClientInterface*) - sBtInterface->get_profile_interface(BT_PROFILE_BAP_UCLIENT_ID); - sUcastClientInterface->Init(&sUcastClientCallbacks); - sPacsClientInterface = (PacsClientInterface*) - sBtInterface->get_profile_interface(BT_PROFILE_PACS_CLIENT_ID); - sPacsClientInterface->Init(&sPacsClientCallbacks); - sAscsClientInterface = (AscsClientInterface*) - sBtInterface->get_profile_interface(BT_PROFILE_ASCS_CLIENT_ID); - sAscsClientInterface->Init(&sAscsClientCallbacks); - - sleep(5); - while(!main_done) - { - char line[2048], *result; - - - /* command prompt */ - printf( ">" ); - fflush(stdout); - - if ((result = fgets (line, 2048, stdin)) == NULL) - { - printf("ERROR: The string is NULL. code %d\n", errno); - exit(0); - } - else - { - printf("UserInput\n"); - } - - if (line[0]!= '\0') - { - /* remove linefeed */ - line[strlen(line)-1] = 0; - - process_cmd(line, 0); - memset(line, '\0', 2048); - } - } - HAL_unload(); - - bdt_log(":: bap uca test app terminating"); - - return 0; -} - -int GetFileName(char *p, char *filename) -{ -// uint8_t i; - int len; - - skip_blanks(&p); - - printf("Input file name = %s\n", p); - - if (p == NULL) - { - printf("\nInvalid File Name... Please enter file name\n"); - return FALSE; - } - len = strlen(p); - - memcpy(filename, p, len); - filename[len] = '\0'; - - return TRUE; -} -uint8_t check_length(char *p) -{ - uint8_t val = 0; - while (*p != ' ' && *p != '\0') - { - val++; - p++; - } - return val; -} -int GetBdAddr(char *p, RawAddress* pbd_addr) -{ - char Arr[13] = {0}; - char *pszAddr = NULL; - uint8_t k1 = 0; - uint8_t k2 = 0; - uint8_t i; - - skip_blanks(&p); - - printf("Input=%s\n", p); - - if(12 != check_length(p)) - { - printf("\nInvalid Bd Address. Format[112233445566]\n"); - return FALSE; - } - memcpy(Arr, p, 12); - - for(i=0; i<12; i++) - { - Arr[i] = tolower(Arr[i]); - } - pszAddr = Arr; - - for(i=0; i<6; i++) - { - k1 = (uint8_t) ( (*pszAddr >= 'a') ? - ( 10 + (uint8_t)( *pszAddr - 'a' )) : (*pszAddr - '0') ); - pszAddr++; - k2 = (uint8_t) ( (*pszAddr >= 'a') ? - ( 10 + (uint8_t)( *pszAddr - 'a' )) : (*pszAddr - '0') ); - pszAddr++; - - if ( (k1>15)||(k2>15) ) - { - return FALSE; - } - pbd_addr->address[i] = (k1<<4 | k2); - } - return TRUE; -} -#endif //BAP_UNICAST_TEST_APP_INTERFACE diff --git a/le_audio/certification_tool/types/Android.bp b/le_audio/certification_tool/types/Android.bp deleted file mode 100644 index 90679df354e2a8dd1355caa276c2854341187042..0000000000000000000000000000000000000000 --- a/le_audio/certification_tool/types/Android.bp +++ /dev/null @@ -1,44 +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. - * - ******************************************************************************/ - - -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: "libbluetooth-types-qti", - vendor_available: true, - enabled: false, - defaults: ["fluoride_types_defaults"], - cflags: [ - /* we export all classes, so change default visibility, instead of having EXPORT_SYMBOL on each class*/ - "-fvisibility=default", - ], - host_supported: true, - srcs: [ - "class_of_device.cc", - "raw_address.cc", - "bluetooth/uuid.cc", - ], -} diff --git a/le_audio/certification_tool/types/bluetooth/uuid.cc b/le_audio/certification_tool/types/bluetooth/uuid.cc deleted file mode 100644 index d05f4370f0caedfaf14a4ee6af5edcf2f357a167..0000000000000000000000000000000000000000 --- a/le_audio/certification_tool/types/bluetooth/uuid.cc +++ /dev/null @@ -1,177 +0,0 @@ -/****************************************************************************** - * - * Copyright (C) 2017 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 "uuid.h" - -#include -#include -#include -#include - -namespace bluetooth { - -static_assert(sizeof(Uuid) == 16, "Uuid must be 16 bytes long!"); - -using UUID128Bit = Uuid::UUID128Bit; - -const Uuid Uuid::kEmpty = Uuid::From128BitBE(UUID128Bit{{0x00}}); - -namespace { -constexpr Uuid kBase = Uuid::From128BitBE( - UUID128Bit{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, - 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}}); -} // namespace - -size_t Uuid::GetShortestRepresentationSize() const { - if (memcmp(uu.data() + kNumBytes32, kBase.uu.data() + kNumBytes32, - kNumBytes128 - kNumBytes32) != 0) { - return kNumBytes128; - } - - if (uu[0] == 0 && uu[1] == 0) return kNumBytes16; - - return kNumBytes32; -} - -bool Uuid::Is16Bit() const { - return GetShortestRepresentationSize() == kNumBytes16; -} - -uint16_t Uuid::As16Bit() const { return (((uint16_t)uu[2]) << 8) + uu[3]; } - -uint32_t Uuid::As32Bit() const { - return (((uint32_t)uu[0]) << 24) + (((uint32_t)uu[1]) << 16) + - (((uint32_t)uu[2]) << 8) + uu[3]; -} - -Uuid Uuid::FromString(const std::string& uuid, bool* is_valid) { - if (is_valid) *is_valid = false; - Uuid ret = kBase; - - if (uuid.empty()) return ret; - - uint8_t* p = ret.uu.data(); - if (uuid.size() == kString128BitLen) { - if (uuid[8] != '-' || uuid[13] != '-' || uuid[18] != '-' || - uuid[23] != '-') { - return ret; - } - - int c; - int rc = - sscanf(uuid.c_str(), - "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx" - "-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%n", - &p[0], &p[1], &p[2], &p[3], &p[4], &p[5], &p[6], &p[7], &p[8], - &p[9], &p[10], &p[11], &p[12], &p[13], &p[14], &p[15], &c); - if (rc != 16) return ret; - if (c != kString128BitLen) return ret; - - if (is_valid) *is_valid = true; - } else if (uuid.size() == 8) { - int c; - int rc = sscanf(uuid.c_str(), "%02hhx%02hhx%02hhx%02hhx%n", &p[0], &p[1], - &p[2], &p[3], &c); - if (rc != 4) return ret; - if (c != 8) return ret; - - if (is_valid) *is_valid = true; - } else if (uuid.size() == 4) { - int c; - int rc = sscanf(uuid.c_str(), "%02hhx%02hhx%n", &p[2], &p[3], &c); - if (rc != 2) return ret; - if (c != 4) return ret; - - if (is_valid) *is_valid = true; - } - - return ret; -} - -Uuid Uuid::From16Bit(uint16_t uuid16) { - Uuid u = kBase; - - u.uu[2] = (uint8_t)((0xFF00 & uuid16) >> 8); - u.uu[3] = (uint8_t)(0x00FF & uuid16); - return u; -} - -Uuid Uuid::From32Bit(uint32_t uuid32) { - Uuid u = kBase; - - u.uu[0] = (uint8_t)((0xFF000000 & uuid32) >> 24); - u.uu[1] = (uint8_t)((0x00FF0000 & uuid32) >> 16); - u.uu[2] = (uint8_t)((0x0000FF00 & uuid32) >> 8); - u.uu[3] = (uint8_t)(0x000000FF & uuid32); - return u; -} - -Uuid Uuid::From128BitBE(const uint8_t* uuid) { - UUID128Bit tmp; - memcpy(tmp.data(), uuid, kNumBytes128); - return From128BitBE(tmp); -} - -Uuid Uuid::From128BitLE(const UUID128Bit& uuid) { - Uuid u; - std::reverse_copy(uuid.data(), uuid.data() + kNumBytes128, u.uu.begin()); - return u; -} - -Uuid Uuid::From128BitLE(const uint8_t* uuid) { - UUID128Bit tmp; - memcpy(tmp.data(), uuid, kNumBytes128); - return From128BitLE(tmp); -} - -const UUID128Bit Uuid::To128BitLE() const { - UUID128Bit le; - std::reverse_copy(uu.data(), uu.data() + kNumBytes128, le.begin()); - return le; -} - -const UUID128Bit& Uuid::To128BitBE() const { return uu; } - -Uuid Uuid::GetRandom() { - Uuid uuid; - base::RandBytes(uuid.uu.data(), uuid.uu.size()); - return uuid; -} - -bool Uuid::IsEmpty() const { return *this == kEmpty; } - -void Uuid::UpdateUuid(const Uuid& uuid) { - uu = uuid.uu; -} - -bool Uuid::operator<(const Uuid& rhs) const { - return std::lexicographical_compare(uu.begin(), uu.end(), rhs.uu.begin(), - rhs.uu.end()); -} - -bool Uuid::operator==(const Uuid& rhs) const { return uu == rhs.uu; } - -bool Uuid::operator!=(const Uuid& rhs) const { return uu != rhs.uu; } - -std::string Uuid::ToString() const { - return base::StringPrintf( - "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - uu[0], uu[1], uu[2], uu[3], uu[4], uu[5], uu[6], uu[7], uu[8], uu[9], - uu[10], uu[11], uu[12], uu[13], uu[14], uu[15]); -} -} // namespace bluetooth diff --git a/le_audio/certification_tool/types/bluetooth/uuid.h b/le_audio/certification_tool/types/bluetooth/uuid.h deleted file mode 100644 index 0fe5b5bd1e4b76a88e35c6e7768d80fc5cfcc0ab..0000000000000000000000000000000000000000 --- a/le_audio/certification_tool/types/bluetooth/uuid.h +++ /dev/null @@ -1,143 +0,0 @@ -/****************************************************************************** - * - * Copyright (C) 2017 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 { - -// This class is representing Bluetooth UUIDs across whole stack. -// Here are some general endianness rules: -// 1. UUID is internally kept as as Big Endian. -// 2. Bytes representing UUID coming from upper layers, Java or Binder, are Big -// Endian. -// 3. Bytes representing UUID coming from lower layer, HCI packets, are Little -// Endian. -// 4. UUID in storage is always string. -class Uuid final { - public: - static constexpr size_t kNumBytes128 = 16; - static constexpr size_t kNumBytes32 = 4; - static constexpr size_t kNumBytes16 = 2; - - static constexpr size_t kString128BitLen = 36; - - static const Uuid kEmpty; // 00000000-0000-0000-0000-000000000000 - - using UUID128Bit = std::array; - - Uuid() = default; - - // Creates and returns a random 128-bit UUID. - static Uuid GetRandom(); - - // Returns the shortest possible representation of this UUID in bytes. Either - // kNumBytes16, kNumBytes32, or kNumBytes128 - size_t GetShortestRepresentationSize() const; - - // Returns true if this UUID can be represented as 16 bit. - bool Is16Bit() const; - - // Returns 16 bit Little Endian representation of this UUID. Use - // GetShortestRepresentationSize() or Is16Bit() before using this method. - uint16_t As16Bit() const; - - // Returns 32 bit Little Endian representation of this UUID. Use - // GetShortestRepresentationSize() before using this method. - uint32_t As32Bit() const; - - // Converts string representing 128, 32, or 16 bit UUID in - // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, xxxxxxxx, or xxxx format to UUID. If - // set, optional is_valid parameter will be set to true if conversion is - // successfull, false otherwise. - static Uuid FromString(const std::string& uuid, bool* is_valid = nullptr); - - // Converts 16bit Little Endian representation of UUID to UUID - static Uuid From16Bit(uint16_t uuid16bit); - - // Converts 32bit Little Endian representation of UUID to UUID - static Uuid From32Bit(uint32_t uuid32bit); - - // Converts 128 bit Big Endian array representing UUID to UUID. - static constexpr Uuid From128BitBE(const UUID128Bit& uuid) { - Uuid u(uuid); - return u; - } - - // Converts 128 bit Big Endian array representing UUID to UUID. |uuid| points - // to beginning of array. - static Uuid From128BitBE(const uint8_t* uuid); - - // Converts 128 bit Little Endian array representing UUID to UUID. - static Uuid From128BitLE(const UUID128Bit& uuid); - - // Converts 128 bit Little Endian array representing UUID to UUID. |uuid| - // points to beginning of array. - static Uuid From128BitLE(const uint8_t* uuid); - - // Returns 128 bit Little Endian representation of this UUID - const UUID128Bit To128BitLE() const; - - // Returns 128 bit Big Endian representation of this UUID - const UUID128Bit& To128BitBE() const; - - // Returns string representing this UUID in - // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format, lowercase. - std::string ToString() const; - - // Returns true if this UUID is equal to kEmpty - bool IsEmpty() const; - - // Update UUID with new value - void UpdateUuid(const Uuid& uuid); - - bool operator<(const Uuid& rhs) const; - bool operator==(const Uuid& rhs) const; - bool operator!=(const Uuid& rhs) const; - - private: - constexpr Uuid(const UUID128Bit& val) : uu{val} {}; - - // Network-byte-ordered ID (Big Endian). - UUID128Bit uu; -}; -} // namespace bluetooth - -inline std::ostream& operator<<(std::ostream& os, const bluetooth::Uuid& a) { - os << a.ToString(); - return os; -} - -// Custom std::hash specialization so that bluetooth::UUID can be used as a key -// in std::unordered_map. -namespace std { - -template <> -struct hash { - std::size_t operator()(const bluetooth::Uuid& key) const { - const auto& uuid_bytes = key.To128BitBE(); - std::hash hash_fn; - return hash_fn(std::string(reinterpret_cast(uuid_bytes.data()), - uuid_bytes.size())); - } -}; - -} // namespace std diff --git a/le_audio/certification_tool/types/class_of_device.cc b/le_audio/certification_tool/types/class_of_device.cc deleted file mode 100644 index 775a412a35096292e9963d1b4488070b6ade0cf5..0000000000000000000000000000000000000000 --- a/le_audio/certification_tool/types/class_of_device.cc +++ /dev/null @@ -1,78 +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 "class_of_device.h" - -#include -#include -#include -#include -#include - -static_assert(sizeof(ClassOfDevice) == ClassOfDevice::kLength, - "ClassOfDevice must be 3 bytes long!"); - -ClassOfDevice::ClassOfDevice(const uint8_t (&class_of_device)[kLength]) { - std::copy(class_of_device, class_of_device + kLength, cod); -}; - -std::string ClassOfDevice::ToString() const { - return base::StringPrintf("%03x-%01x-%02x", - (static_cast(cod[2]) << 4) | cod[1] >> 4, - cod[1] & 0x0f, cod[0]); -} - -bool ClassOfDevice::FromString(const std::string& from, ClassOfDevice& to) { - ClassOfDevice new_cod; - if (from.length() != 8) return false; - - std::vector byte_tokens = - base::SplitString(from, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - - if (byte_tokens.size() != 3) return false; - if (byte_tokens[0].length() != 3) return false; - if (byte_tokens[1].length() != 1) return false; - if (byte_tokens[2].length() != 2) return false; - - uint16_t values[3]; - - for (size_t i = 0; i < kLength; i++) { - const auto& token = byte_tokens[i]; - - char* temp = nullptr; - values[i] = strtol(token.c_str(), &temp, 16); - if (*temp != '\0') return false; - } - - new_cod.cod[0] = values[2]; - new_cod.cod[1] = values[1] | ((values[0] & 0xf) << 4); - new_cod.cod[2] = values[0] >> 4; - - to = new_cod; - return true; -} - -size_t ClassOfDevice::FromOctets(const uint8_t* from) { - std::copy(from, from + kLength, cod); - return kLength; -}; - -bool ClassOfDevice::IsValid(const std::string& cod) { - ClassOfDevice tmp; - return ClassOfDevice::FromString(cod, tmp); -} diff --git a/le_audio/certification_tool/types/class_of_device.h b/le_audio/certification_tool/types/class_of_device.h deleted file mode 100644 index b0fffc88532721f78f6d0a363d748eef1c67cfd3..0000000000000000000000000000000000000000 --- a/le_audio/certification_tool/types/class_of_device.h +++ /dev/null @@ -1,63 +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 - -namespace bluetooth { -namespace types { - -/** Bluetooth Class of Device */ -class ClassOfDevice final { - public: - static constexpr unsigned int kLength = 3; - - uint8_t cod[kLength]; - - ClassOfDevice() = default; - ClassOfDevice(const uint8_t (&class_of_device)[kLength]); - - bool operator==(const ClassOfDevice& rhs) const { - return (std::memcmp(cod, rhs.cod, sizeof(cod)) == 0); - } - - std::string ToString() const; - - // Converts |string| to ClassOfDevice and places it in |to|. If |from| does - // not represent a Class of Device, |to| is not modified and this function - // returns false. Otherwise, it returns true. - static bool FromString(const std::string& from, ClassOfDevice& to); - - // Copies |from| raw Class of Device octets to the local object. - // Returns the number of copied octets (always ClassOfDevice::kLength) - size_t FromOctets(const uint8_t* from); - - static bool IsValid(const std::string& class_of_device); -}; - -inline std::ostream& operator<<(std::ostream& os, const ClassOfDevice& c) { - os << c.ToString(); - return os; -} - -} // namespace types -} // namespace bluetooth - -using ::bluetooth::types::ClassOfDevice; // TODO, remove diff --git a/le_audio/certification_tool/types/raw_address.cc b/le_audio/certification_tool/types/raw_address.cc deleted file mode 100644 index 8369f5f36af260667b2dcd612110d808b660e330..0000000000000000000000000000000000000000 --- a/le_audio/certification_tool/types/raw_address.cc +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* - * - * Copyright 2017 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 "raw_address.h" - -#include -#include -#include -#include -#include - -static_assert(sizeof(RawAddress) == 6, "RawAddress must be 6 bytes long!"); - -const RawAddress RawAddress::kAny{{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}; -const RawAddress RawAddress::kEmpty{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; - -RawAddress::RawAddress(const uint8_t (&addr)[6]) { - std::copy(addr, addr + kLength, address); -} - -std::string RawAddress::ToString() const { - return base::StringPrintf("%02x:%02x:%02x:%02x:%02x:%02x", address[0], - address[1], address[2], address[3], address[4], - address[5]); -} - -bool RawAddress::FromString(const std::string& from, RawAddress& to) { - RawAddress new_addr; - if (from.length() != 17) return false; - - std::vector byte_tokens = - base::SplitString(from, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - - if (byte_tokens.size() != 6) return false; - - for (int i = 0; i < 6; i++) { - const auto& token = byte_tokens[i]; - - if (token.length() != 2) return false; - - char* temp = nullptr; - new_addr.address[i] = strtol(token.c_str(), &temp, 16); - if (*temp != '\0') return false; - } - - to = new_addr; - return true; -} - -size_t RawAddress::FromOctets(const uint8_t* from) { - std::copy(from, from + kLength, address); - return kLength; -}; - -bool RawAddress::IsValidAddress(const std::string& address) { - RawAddress tmp; - return RawAddress::FromString(address, tmp); -} diff --git a/le_audio/certification_tool/types/raw_address.h b/le_audio/certification_tool/types/raw_address.h deleted file mode 100644 index ca750181b6c21c65d84d86001efcee501c50335d..0000000000000000000000000000000000000000 --- a/le_audio/certification_tool/types/raw_address.h +++ /dev/null @@ -1,79 +0,0 @@ -/****************************************************************************** - * - * Copyright 2017 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 Address */ -class RawAddress final { - public: - static constexpr unsigned int kLength = 6; - - uint8_t address[kLength]; - - RawAddress() = default; - RawAddress(const uint8_t (&addr)[kLength]); - - bool operator<(const RawAddress& rhs) const { - return (std::memcmp(address, rhs.address, sizeof(address)) < 0); - } - bool operator==(const RawAddress& rhs) const { - return (std::memcmp(address, rhs.address, sizeof(address)) == 0); - } - bool operator>(const RawAddress& rhs) const { return (rhs < *this); } - bool operator<=(const RawAddress& rhs) const { return !(*this > rhs); } - bool operator>=(const RawAddress& rhs) const { return !(*this < rhs); } - bool operator!=(const RawAddress& rhs) const { return !(*this == rhs); } - - bool IsEmpty() const { return *this == kEmpty; } - - std::string ToString() const; - - // Converts |string| to RawAddress and places it in |to|. If |from| does - // not represent a Bluetooth address, |to| is not modified and this function - // returns false. Otherwise, it returns true. - static bool FromString(const std::string& from, RawAddress& to); - - // Copies |from| raw Bluetooth address octets to the local object. - // Returns the number of copied octets - should be always RawAddress::kLength - size_t FromOctets(const uint8_t* from); - - static bool IsValidAddress(const std::string& address); - - static const RawAddress kEmpty; // 00:00:00:00:00:00 - static const RawAddress kAny; // FF:FF:FF:FF:FF:FF -}; - -inline std::ostream& operator<<(std::ostream& os, const RawAddress& a) { - os << a.ToString(); - return os; -} - -template <> -struct std::hash { - std::size_t operator()(const RawAddress& val) const { - static_assert(sizeof(uint64_t) >= RawAddress::kLength); - uint64_t int_addr = 0; - memcpy(reinterpret_cast(&int_addr), val.address, - RawAddress::kLength); - return std::hash{}(int_addr); - } -}; diff --git a/le_audio/frameworks/base/Android.bp b/le_audio/frameworks/base/Android.bp deleted file mode 100644 index 95d4675f568c8dcbd75abbe6a273050bd47d2676..0000000000000000000000000000000000000000 --- a/le_audio/frameworks/base/Android.bp +++ /dev/null @@ -1,31 +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. - * - ******************************************************************************/ - -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"], -} - -filegroup { - name: "framework-bluetooth-adva-srcs", - srcs: ["core/**/*.java",], -} diff --git a/le_audio/frameworks/base/core/java/android/bluetooth/BleBroadcastAudioScanAssistCallback.java b/le_audio/frameworks/base/core/java/android/bluetooth/BleBroadcastAudioScanAssistCallback.java deleted file mode 100644 index bbb5a3007287523ee4c555144badce4fda7102ae..0000000000000000000000000000000000000000 --- a/le_audio/frameworks/base/core/java/android/bluetooth/BleBroadcastAudioScanAssistCallback.java +++ /dev/null @@ -1,178 +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. - * - ******************************************************************************/ - - -package android.bluetooth; - -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Retention; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.le.ScanResult; -import android.annotation.IntDef; -import java.util.Map; -import java.lang.String; -import java.lang.Integer; -import java.util.List; - - - -/** - * Bluetooth LE Broadcast Scan Assistance related callbacks, used to deliver result of - * Broadcast Assist operations performed using {@link BleBroadcastAudioScanAssistManager} - * - * @hide - * @see BleBroadcastAudioScanAssistManager - */ -public abstract class BleBroadcastAudioScanAssistCallback { - - /** @hide */ - @IntDef(prefix = "BASS_STATUS_", value = { - BASS_STATUS_SUCCESS, - BASS_STATUS_FAILURE, - BASS_STATUS_FATAL, - BASS_STATUS_TXN_TIMEOUT, - BASS_STATUS_INVALID_SOURCE_ID, - BASS_STATUS_COLOCATED_SRC_UNAVAILABLE, - BASS_STATUS_INVALID_SOURCE_SELECTED, - BASS_STATUS_SOURCE_UNAVAILABLE, - BASS_STATUS_DUPLICATE_ADDITION, - }) - - @Retention(RetentionPolicy.SOURCE) - public @interface Bass_Status {} - - public static final int BASS_STATUS_SUCCESS = 0x00; - public static final int BASS_STATUS_FAILURE = 0x01; - public static final int BASS_STATUS_FATAL = 0x02; - public static final int BASS_STATUS_TXN_TIMEOUT = 0x03; - - public static final int BASS_STATUS_INVALID_SOURCE_ID = 0x04; - public static final int BASS_STATUS_COLOCATED_SRC_UNAVAILABLE = 0x05; - public static final int BASS_STATUS_INVALID_SOURCE_SELECTED = 0x06; - public static final int BASS_STATUS_SOURCE_UNAVAILABLE = 0x07; - public static final int BASS_STATUS_DUPLICATE_ADDITION = 0x08; - public static final int BASS_STATUS_NO_EMPTY_SLOT = 0x09; - public static final int BASS_STATUS_INVALID_GROUP_OP = 0x10; - - /** - * Callback when BLE broadcast audio source found. - * result of {@link BleBroadcastAudioScanAssistManager#searchforLeAudioBroadcasters} will be - * delivered through this callback - * - * @param scanres {@link ScanResult} object of the scanned result - */ - public void onBleBroadcastSourceFound(ScanResult scanres) { - }; - - - /** - * Callback when BLE broadcast audio source found. - * result of {@link BleBroadcastAudioScanAssistManager#searchforLeAudioBroadcasters} will be - * delivered through this callback - * - * @param status Status of the Broadcast source selection. - * @param broadcastSourceChannels {@link BleBroadcastSourceChannel} List - * containing avaiable broadcast source channels that are being broadcasted from the selected - * broadcast source - * - */ - public void onBleBroadcastSourceSelected(BluetoothDevice device, - @Bass_Status int status, - List broadcastSourceChannels) { - }; - - /** - * Callback when BLE broadcast audio source is been successfully added to the remote Scan delegator. - * result of {@link BleBroadcastAudioScanAssistManager#addBroadcastSource} will be - * delivered through this callback - * - * This callback is an acknowledgement confirming the source information added - * to the Scan delegator. Actual updated source Information values of resulting Broadcast Source Information - * will be notified using {@link BleBroadcastAudioScanAssistManager#ACTION_BROADCAST_RECEIVER_STATE} intent - * - * @param device remote scan delegator for which Source is been added. - * @param srcId source Id of the Broadcast source information added - * @param status true on succesful addition of source Information, false otherwise. - * - */ - public void onBleBroadcastAudioSourceAdded(BluetoothDevice device, - byte srcId, - @Bass_Status int status) { - }; - - /** - * Callback when BLE broadcast audio source Information is been updated to the remote Scan delegator. - * result of {@link BleBroadcastAudioScanAssistManager#updateBroadcastSource} will be - * delivered through this callback - * - * This callback is an acknowledgement confirming the source information update request is succesfully - * written on the Scan delegator. Actual updated source Information values of resulting Broadcast Source Information - * will be notified using {@link BleBroadcastAudioScanAssistManager#ACTION_BROADCAST_RECEIVER_STATE} intent - * - * @param device remote scan delegator for which Source is been updated. - * @param srcId source Id of the Broadcast source information updated. - * @param status true on succesful updating of source Information, false otherwise. - * - */ - public void onBleBroadcastAudioSourceUpdated(BluetoothDevice device, - byte srcId, - @Bass_Status int status) { - }; - - /** - * Callback when BLE broadcast audio source Information is updated with broadcast PIN code to the remote Scan delegator. - * result of {@link BleBroadcastAudioScanAssistManager#setBroadcastCode} will be - * delivered through this callback - * - * This callback is an acknowledgement confirming the Broadcast PIN update request is succesfully - * written to the Scan delegator. Actual updated source Information values of resulting Broadcast Source Information - * will be notified using {@link BleBroadcastAudioScanAssistManager#ACTION_BROADCAST_RECEIVER_STATE} intent. - * Encryption status from the {@link BleBroadcastAudioScanAssistManager#ACTION_BROADCAST_RECEIVER_STATE} will - * confirm the succesfull Broadcast PIN code and resulting decryption of the Broadcast data at the reciver side. - * - * @param device remote scan delegator for which Source is been updated. - * @param srcId source Id of the Broadcast PIN updated. - * @param status true on succesful updating of source Information, false otherwise. - * - */ - public void onBleBroadcastPinUpdated(BluetoothDevice rcvr, - byte srcId, - @Bass_Status int status) { - }; - - /** - * Callback when BLE broadcast audio source Information is removed from the remote Scan delegator. - * result of {@link BleBroadcastAudioScanAssistManager#removeBroadcastSource} will be - * delivered through this callback - * - * This callback is an acknowledgement confirming the Broadcast source infor removal request is succesfully - * written to the Scan delegator. Actual removal of source Information values of resulting Broadcast Source Information - * will be notified using {@link BleBroadcastAudioScanAssistManager#ACTION_BROADCAST_RECEIVER_STATE} intent. - * Deletion of source Information will result is setting all the source information attributes to ZERO other than - * source Id - * - * @param device remote scan delegator for which Source is removed. - * @param srcId source Id of the Broadcast source information removed. - * @param status true on succesful updating of source Information, false otherwise. - * - */ - public void onBleBroadcastAudioSourceRemoved(BluetoothDevice rcvr, - byte srcId, - @Bass_Status int status) { - }; -} diff --git a/le_audio/frameworks/base/core/java/android/bluetooth/BleBroadcastAudioScanAssistManager.java b/le_audio/frameworks/base/core/java/android/bluetooth/BleBroadcastAudioScanAssistManager.java deleted file mode 100644 index c16bcb6fe0d5a66154edaee7b2c0cb927f3bd239..0000000000000000000000000000000000000000 --- a/le_audio/frameworks/base/core/java/android/bluetooth/BleBroadcastAudioScanAssistManager.java +++ /dev/null @@ -1,635 +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. - * - ******************************************************************************/ - - -package android.bluetooth; - -import android.Manifest; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.RequiresPermission; -import android.annotation.SdkConstant; -import android.annotation.SystemApi; -import android.annotation.IntDef; -import android.annotation.SdkConstant.SdkConstantType; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Retention; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.IBluetoothGatt; -import android.bluetooth.IBluetoothManager; -import android.bluetooth.BluetoothProfile; -import android.bluetooth.BluetoothAdapter.LeScanCallback; -import android.os.Binder; -import android.os.IBinder; -import android.os.Handler; -import android.os.Looper; -import android.os.RemoteException; -import java.io.InvalidClassException; -import android.os.DeadObjectException; -import android.util.Log; -import android.content.Context; -import java.util.UUID; -import android.os.ParcelUuid; - -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.ArrayList; -import java.util.List; -import java.util.HashMap; -import java.util.Objects; - -import android.bluetooth.le.ScanResult; -import android.bluetooth.le.ScanSettings; -import android.bluetooth.le.ScanFilter; -import android.bluetooth.le.ScanCallback; -import android.bluetooth.le.ScanRecord; -import android.bluetooth.le.BluetoothLeScanner; -import android.bluetooth.BleBroadcastAudioScanAssistManager; - -import android.os.SystemProperties; - -/** - * This class provides methods to perform Broadcast Assistance related - * operations. - *

- * Use {@link BleBroadcastAudioScanAssistManager()} to get an - * instance of {@link BleBroadcastAudioScanAssistManager}. - *

- * Note: Most of the methods here require - * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. - * - * @hide - */ -public final class BleBroadcastAudioScanAssistManager { - - private static final String TAG = "BleBroadcastAudioScanAssistManager"; - private static final boolean DBG = true; - private static final boolean VDBG = true; - - /** @hide */ - @IntDef(prefix = "SYNC_", value = { - SYNC_METADATA, - SYNC_AUDIO, - SYNC_METADATA_AUDIO - }) - @Retention(RetentionPolicy.SOURCE) - public @interface BroadcastAssistSyncState {} - /** - * Input to {@link BleBroadcastAudioScanAssistManager#addBroadcastSource} method - * where Application wants to synchronize only to Metadata (i.e. Only Periodic advs) and not to - * Broadcsat audio stream (i.e. BIS )from broadcast source - */ - public static final int SYNC_METADATA = 0; - /** - * Input to {@link BleBroadcastAudioScanAssistManager#addBroadcastSource} method - * where Application wants to synchronize only to Broadcast Audio stream (i.e. BIS) and not to - Metadata (i.e. Periodic advs )from broadcast source - */ - public static final int SYNC_AUDIO = 1; - /** - * Input to {@link BleBroadcastAudioScanAssistManager#addBroadcastSource} method - * where Application wants to synchronize to both Broadcast Audio stream (i.e. BIS) and also to - * Metadata (i.e. Periodic advs )from broadcast source - */ - public static final int SYNC_METADATA_AUDIO = 2; - - private BluetoothAdapter mBluetoothAdapter; - BleBroadcastAudioScanAssistCallback mAppCallback; - BluetoothDevice mBluetoothDevice; - int mSyncState = SYNC_METADATA; - BluetoothSyncHelper mBluetoothSyncHelper = null; - BleBroadcastSourceInfo mBroadcastAudioSourceInfo = null; - private byte INVALID_SOURCE_ID = -1; - - /** - * Intent used to broadcast the "Broadcast receiver State" information of a Scan delegator device. - * Whenever there is a change in Broadcast source Information stored at Scan delegator device - * this Itent will be delivered to Application layer - * - * {@link #BluetoothSyncHelper} profile need to be connected to the Scan delegator device - * to get these notifications - * - *

This intent will have two extra: - *

    - *
  • {@link BluetoothDevice#EXTRA_DEVICE} - The remote device for which broadcast reciver - * state information is broadcasted. It can - * be null if no device is active.
  • - *
- *
    - *
  • {@link BleBroadcastSourceInfo#EXTRA_SOURCE_INFO} - The BleBroadcastSourceInfo Object - * having information Broadcast receiver state
  • - *
- *
    - *
  • {@link BleBroadcastSourceInfo#EXTRA_SOURCE_INFO_INDEX} - Index of the BleBroadcastSourceInfo - * object broadcasted
  • - *
- *
    - *
  • {@link BleBroadcastSourceInfo#EXTRA_MAX_NUM_SOURCE_INFOS} - Maximum number of source Informations - * that this Broadcast receiver can hold
  • - *
- * - *

Requires {@link android.Manifest.permission#BLUETOOTH} permission to - * receive. - * - * @hide - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_BROADCAST_SOURCE_INFO = - "android.bluetooth.BroadcastAudioSAManager.action.BROADCAST_SOURCE_INFO"; - - - // These callbacks run on the main thread. - private final class BassclientServiceListener - implements BluetoothProfile.ServiceListener { - - public void onServiceConnected(int profile, BluetoothProfile proxy) { - log(TAG, "BassService connected"); - onBluetoothSyncHelperStateChanged(true, proxy); - - } - - public void onServiceDisconnected(int profile) { - log(TAG, "BassService disconnected"); - onBluetoothSyncHelperStateChanged(false, null); - } - } - - private void onBluetoothSyncHelperStateChanged(boolean on, BluetoothProfile proxy) { - if (on) { - mBluetoothSyncHelper = (BluetoothSyncHelper) proxy; - mBluetoothSyncHelper.registerAppCallback(mBluetoothDevice, mAppCallback); - this.notifyAll(); - } else { - mBluetoothSyncHelper = null; - } - } - - /*package*/BleBroadcastAudioScanAssistManager(BluetoothSyncHelper scanOffloader, BluetoothDevice device, - BleBroadcastAudioScanAssistCallback callback - ) { - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - - mAppCallback = callback; - mBluetoothDevice = device; - mBluetoothSyncHelper = scanOffloader; - } - - - /*finalize method to cleanup*/ - protected void finalize() { - log(TAG, "finalize()"); - if (mBluetoothSyncHelper != null) { - mBluetoothSyncHelper.unregisterAppCallback(mBluetoothDevice, mAppCallback); - } - } - - /** - * Search for Le Audio Broadcasters on behalf of the Scan delegator with which this - * {@ BleBroadcastAudioScanAssistManager} is instantiated - * - * search results will be delivered to application using - * {@link BleBroadcastAudioScanAssistCallback#onBleBroadcastSourceFound} - * - * @return returns true if It is successfully initiated the Search for Audio broadcasters, - * false otherwise - * @hide - */ - public boolean searchforLeAudioBroadcasters () { - log(TAG, "searchforLeAudioBroadcasters: "); - if (mBluetoothSyncHelper != null) { - return mBluetoothSyncHelper.searchforLeAudioBroadcasters(mBluetoothDevice); - } else { - Log.e(TAG, "searchforLeAudioBroadcasters: mBluetoothSyncHelper is null"); - } - return false; - } - /** - * Stops an ongoing Bluetooth LE Search for Audio Broadcasters. - * - * @return returns true if It is successfully initiated the Stopped the Search for Audio broadcasters - * false otherwise - * - *@hide - */ - @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) - public boolean stopSearchforLeAudioBroadcasters() { - log(TAG, "stopSearchforLeAudioBroadcasters()"); - if (mBluetoothSyncHelper != null) { - return mBluetoothSyncHelper.stopSearchforLeAudioBroadcasters(mBluetoothDevice); - } else { - Log.e(TAG, "stopSearchforLeAudioBroadcasters: mBluetoothSyncHelper is null"); - } - return false; - - } - - /* Internal helper function to convert user input sync state to required internal - * format - */ - private int convertMetadataSyncState(int syncState) { - if (syncState == SYNC_METADATA_AUDIO || syncState == SYNC_METADATA) { - return BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC; - } - return BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IDLE; - } - - /* Internal helper function to convert user input sync state to required internal - * format - */ - private int convertAudioDataSyncState(int syncState) { - if (syncState == SYNC_METADATA_AUDIO || syncState == SYNC_AUDIO) { - return BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED; - } else { - Log.e(TAG, "searchforLeAudioBroadcasters: mBluetoothSyncHelper is null"); - } - return BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED; - } - - /** - * Selects broadcast source for the Scan delegator. This internally performs Periodic - * synchronization to the given Broadcast source device, upon acquision of Synchronization information, - * It will be notified with avaiable Broadcast source channels that can be synchronized in the remote - * device. - * Application should select set of Broadcast channels that need to be synchronized and follow up - * with a call to {@link #addBroadcastSource} operation - * - * Result of selction of Broadcast source will be delivered through - * {@link BleBroadcastAudioScanAssistCallback#OnBroadcastAudioSourceSelected} - * - * If this operation need to be performed over all the members of coordinated set members, isGroupOp - * will be set to true. Select broadcast source operation will be performed on behalf of - * all the Coordinated set devices - * - * - * @param ScanResult {@link #ScanResult} of the Broadcasting source, - * this is the result obtained from the {@link BleBroadcastAudioScanAssistCallback#onBleBroadcastSourceFound} - * @param isGroupOp set to true If Application wants to perform this operation for the whole - * coordinated set members - * - * @return returns true if It is successfully initiated select Broadcast source operation - * false otherwise - * @hide - */ - public boolean selectBroadcastSource(ScanResult scanRes, boolean isGroupOp) { - if (scanRes == null) { - Log.e(TAG, "selectBroadcastSource: Invalid scan res"); - return false; - } - log(TAG, "selectBroadcastSource: " + scanRes); - if (mBluetoothSyncHelper != null) { - return mBluetoothSyncHelper.selectBroadcastSource(mBluetoothDevice, scanRes, isGroupOp); - } else { - Log.e(TAG, "selectBroadcastSource: mBluetoothSyncHelper is null"); - } - return false; - } - - - private boolean isValidBroadcastSourceInfo(BleBroadcastSourceInfo srcInfo) { - boolean ret = true; - List currentSourceInfos = - mBluetoothSyncHelper.getAllBroadcastSourceInformation(mBluetoothDevice); - if (currentSourceInfos == null) { - Log.e(TAG, "no source info details for remote"); - ret = false; - } else { - for (int i=0; i currentSourceInfos = - mBluetoothSyncHelper.getAllBroadcastSourceInformation(mBluetoothDevice); - if (currentSourceInfos == null) { - retVal = false; - } else { - for (int i=0; i selectedBISIndicies) { - if (selectedBISIndicies == null) { - log(TAG, "printSelectedIndicies : no selected indicies"); - return; - } - for (int i=0; i selectedBroadcastChannels, - boolean isGroupOp) { - if (mBluetoothSyncHelper == null) { - log(TAG, "addBroadcastSource: no BluetoothSyncHelper handle"); - return false; - } - - if (syncState != SYNC_METADATA && - syncState != SYNC_METADATA_AUDIO) { - log(TAG, "addBroadcastSource: Invalid syncState" + syncState); - return false; - } - printSelectedIndicies(selectedBroadcastChannels); - int metadataSyncState = -1; - int audioSyncState = -1; - mSyncState = syncState; - metadataSyncState = convertMetadataSyncState (mSyncState); - audioSyncState = convertAudioDataSyncState(mSyncState); - if (mBroadcastAudioSourceInfo == null) { - //all of these will be overriden at service layer later - mBroadcastAudioSourceInfo = new BleBroadcastSourceInfo( - audioSource, - (byte)0xBB, /*advSid*/ - BleBroadcastSourceInfo.BROADCAST_ASSIST_ADDRESS_TYPE_PUBLIC, - metadataSyncState, - audioSyncState, - selectedBroadcastChannels); - if (mBroadcastAudioSourceInfo == null) { - Log.e(TAG, "addBroadcastSource: mBroadcastAudioSourceInfo instantiated failure"); - return false; - } - } - if(isValidBroadcastSourceInfo(mBroadcastAudioSourceInfo)) { - mBluetoothSyncHelper.addBroadcastSource(mBluetoothDevice, - mBroadcastAudioSourceInfo, - isGroupOp - ); - } else { - log(TAG, "Similar source information already exists"); - return false; - } - return true; - } - /** - * Updates a broadcast source information in the Scan delegator. - * It will be written on to the Scan delegator's Characteristics - * - * Result of updating of Broadcast source to the scan delegator will be delivered through - * {@link BleBroadcastAudioScanAssistCallback#onBleBroadcastAudioSourceUpdated} - * - * However Successful updating of Broadcast source information will be indicated through Broadcast reciver state information - * update intent through {@link #ACTION_BROADCAST_RECEIVER_STATE} intent - * - * If this operation need to be performed over all the members of coordinated set members, isGroupOp - * will be set to true. Update broadcast source operation will be performed on behalf of - * all the Coordinated set devices - * - * Same Broadcast source Information change will be written on to all the members of Coordinated set and - * PAST will be performed based on the request from remote. - * - * In case of Group Operation, If there are no matching source Information present in any of coordinated set members, - * Update Broadcast source opeation will be failed and result will notified through - * {@link BleBroadcastAudioScanAssistCallback#onBleBroadcastAudioSourceUpdated} - * - * @param sourceId sourceId of the Broadcast Source information which need to be updated - * @param syncState can be one of {@link #SYNC_METADATA}, - * {@link #SYNC_AUDIO}, {@link #SYNC_METADATA_AUDIO} - * - * @param selectedBroadcastChannels is a List of Broadcast channels that need to be synchronized with the given broadcast audio source - * from Avaialble Broadcast indicies. - * Avaiable broadcast indicies are notified application using {@link BleBroadcastAudioScanAssistCallback#onBleBroadcastSourceSelected} - * BroadcastSourceChannel.mStatus set to be TRUE or FALSE based on the need of synchronization. - * - * null value of selectedBroadcastChannels resulting in syncing to all avaialble Broadcast channels. - * check {@link BleurceChannel} for more information - * @param isGroupOp set to true If Application wants to perform this operation for the whole - * coordinated set members, False otherwise - * - * @return returns true if It is successfully initiated update Broadcast source information - * operation - * false otherwise - * @hide - */ - public boolean updateBroadcastSource (byte sourceId, int syncState, - List selectedBroadcastChannels, - boolean isGroupOp) { - if (mBluetoothSyncHelper == null) { - log(TAG, "updateBroadcastSource: no BluetoothSyncHelper handle"); - return false; - } - if (isValidSourceId(sourceId) == false) { - log(TAG, "updateBroadcastSource: Invalid source Id"); - return false; - } - int audioSyncState = -1; - int metadataSyncState = -1; - log(TAG, "updateBroadcastSource: sourceId" + sourceId + ", syncState:" + syncState); - - mSyncState = syncState; - metadataSyncState = convertMetadataSyncState (mSyncState); - audioSyncState = convertAudioDataSyncState(mSyncState); - - printSelectedIndicies(selectedBroadcastChannels); - - log(TAG, "updateBroadcastSource: audioSyncState:" + audioSyncState); - log(TAG, "updateBroadcastSource: metadataSyncState:" + metadataSyncState); - - BleBroadcastSourceInfo sourceInfo = new BleBroadcastSourceInfo(sourceId); - if (sourceInfo != null) { - sourceInfo.setMetadataSyncState(metadataSyncState); - sourceInfo.setAudioSyncState(audioSyncState); - sourceInfo.setSourceId(sourceId); - sourceInfo.setBroadcastChannelsSyncStatus(selectedBroadcastChannels); - } else { - Log.e(TAG, "updateBroadcastSource: sourceInfo not created"); - return false; - } - return mBluetoothSyncHelper.updateBroadcastSource(mBluetoothDevice, - sourceInfo, - isGroupOp); - } - /** - * Sets the Broadcast pin code to the Scan delegator so that It can decrypt - * the synchronized audio at the reciver side - * - * It will be written on to the Scan delegator's Characteristics. - * Result of Setting of Broadcast PIN code to the scan delegator will be delivered through - * {@link BleBroadcastAudioScanAssistCallback#onBroadcastPinUpdated} - * - * If this operation need to be performed over all the members of coordinated set members, isGroupOp - * will be set to true. set Broadcast PIN operation will be performed on all the Coordinated set devices - * - * Same Broadcast PIN code will be written on to all the members of Coordinated set and - * on the request from remote. - * - * In case of Group Operation, If there are no matching source Information(BD address, adv instance) - * present in any of coordinated set members, - * Set Broadcast PIN opeation will be failed and result will notified through - * {@link BleBroadcastAudioScanAssistCallback#onBroadcastPinUpdated} - * - * - * However, Successful updating of Broadcast PIN code will be indicated through Broadcast reciver state information - * update intent through {@link #ACTION_BROADCAST_RECEIVER_STATE} intent. - * - * @param sourceId sourceId of the Broadcast Source information which need to be updated - * @param broadcastCode is the String of maximum 16 characters in length - * @param isGroupOp set to true If Application wants to perform this operation for the whole - * coordinated set members, False otherwise - * - * @return returns true if It is successfully initiated set Broadcast code operation - * false otherwise - * @hide - */ - public boolean setBroadcastCode (byte sourceId, String broadcastCode, boolean isGroupOp) { - if (mBluetoothSyncHelper == null) { - log(TAG, "setBroadcastCode: no BluetoothSyncHelper handle"); - return false; - } - if (isValidSourceId(sourceId) == false) { - log(TAG, "setBroadcastCode: Invalid source Id"); - return false; - } - - log(TAG, "setBroadcastCode: " + "sourceId:" - + sourceId + "BroadcastCode:" + broadcastCode); - BleBroadcastSourceInfo sourceInfo = new BleBroadcastSourceInfo(sourceId); - if (sourceInfo != null) { - sourceInfo.setSourceId(sourceId); - sourceInfo.setBroadcastCode(broadcastCode); - } else { - Log.e(TAG, "setBroadcastCode: sourceInfo not created"); - return false; - } - return mBluetoothSyncHelper.setBroadcastCode(mBluetoothDevice, - sourceInfo, - isGroupOp); - } - /** - * Removes the Broadcast Source Information from the Scan delegator - * It will be written on to the "Scan delegators" Characteristics - * - * Result of removal of Broadcast source to the scan delegator will be delivered through - * {@link BleBroadcastAudioScanAssistCallback#OnBroadcastAudioSourRemoved} - * - * If this operation need to be performed over all the members of coordinated set members, isGroupOp - * will be set to true. remove broadcast operation will be performed on all the Coordinated set devices - * - * Remove Broadcast will be performed on to all the members of Coordinated set - * - * In case of Group Operation, If there are no matching source Information(BD address, adv instance) - * present in any of coordinated set members. - * - * Set Broadcast PIN opeation will be failed and result will notified through - * {@link BleBroadcastAudioScanAssistCallback#onBroadcastPinUpdated} - * Successful removal of Brocast source information will be indicated through - * Broadcast receiver state Information through - * {@link #ACTION_BROADCAST_RECEIVER_STATE} intent - * - * @param sourceId sourceId of the Broadcast Source information which need to be updated - * @param isGroupOp set to true If Application wants to perform this operation for the whole - * coordinated set members, False otherwise - * - * @return returns true if It is successfully initiated remove broadcast source operation - * false otherwise - * @hide - */ - public boolean removeBroadcastSource (byte sourceId, boolean isGroupOp) { - if (mBluetoothSyncHelper == null) { - log(TAG, "removeBroadcastSource: no BluetoothSyncHelper handle"); - return false; - } - if (isValidSourceId(sourceId) == false) { - log(TAG, "removeBroadcastSource: Invalid source Id"); - return false; - } - log(TAG, "removeBroadcastSource: sourceId" + sourceId); - - return mBluetoothSyncHelper.removeBroadcastSource(mBluetoothDevice, - sourceId, - isGroupOp); - } - /** - * Get all the Broadcast Source Information stored in remote Scan delegators - * - * @return returns the List of Broadcast Source Information {@link #BleBroadcastSourceInfo} stored in - * remote and its corresponding state or null in case if there are nothing - * - * @hide - */ - public List getAllBroadcastSourceInformation () { - if (mBluetoothSyncHelper == null) { - log(TAG, "GetNumberOfAcceptableBroadcastSources: no BluetoothSyncHelper handle"); - return null; - } - return mBluetoothSyncHelper.getAllBroadcastSourceInformation(mBluetoothDevice); - } - - private static void log(String TAG, String msg) { - BleBroadcastSourceInfo.BASS_Debug(TAG, msg); - } -} diff --git a/le_audio/frameworks/base/core/java/android/bluetooth/BleBroadcastSourceChannel.java b/le_audio/frameworks/base/core/java/android/bluetooth/BleBroadcastSourceChannel.java deleted file mode 100644 index d8f3d61d851979bfca0855fca0c360911365a9ab..0000000000000000000000000000000000000000 --- a/le_audio/frameworks/base/core/java/android/bluetooth/BleBroadcastSourceChannel.java +++ /dev/null @@ -1,231 +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. - * - ******************************************************************************/ - -package android.bluetooth; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.IBluetoothGatt; -import android.bluetooth.IBluetoothManager; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Retention; -import android.annotation.IntDef; -import android.compat.annotation.UnsupportedAppUsage; - -import android.os.Parcel; -import android.os.Parcelable; -import android.os.Handler; -import android.os.Looper; -import android.os.RemoteException; -import android.util.Log; -import java.util.Objects; -import android.util.Log; -import java.util.List; -import java.util.ArrayList; -import java.util.IdentityHashMap; -import java.util.Map; - -/** - * This class provides Interface to select the Broadcast source channels - * to be synchronized from the Broadcast source. these Broadcast source channels - * are mapped to the BIS indicies that given Broadcast source is broadcasting with. - * - *

This also acts as general data structure for updating the Broadcast - * source channel information - * - * This class is used to input the User provided data for below operations - * {@link BleBroadcastAudioScanAssistManager#addBroadcastSource}, - * {@link BleBroadcastAudioScanAssistManager#updateBroadcastSource} and - * - * mIndex : index is the Identifier for Broadcast channel - * mDescription: Description describing the type of Broadcast data being broadcasted - * mStatus: TRUE means broadcast source channel need to be synchronized - * FALSE means broadcast source channel need NOT be synchronized - * - * @hide - */ -public final class BleBroadcastSourceChannel implements Parcelable { - - private static final String TAG = "BleBroadcastSourceChannel"; - private int mIndex; - private String mDescription; - private boolean mStatus; - private int mSubGroupId; - private byte[] mMetadata; - - public BleBroadcastSourceChannel (int index, - String description, - boolean st, - int aSubGroupId, - byte[] aMetadata) { - mIndex = index; - mDescription = description; - mStatus = st; - mSubGroupId = aSubGroupId; - if (aMetadata != null && aMetadata.length != 0) { - mMetadata = new byte[aMetadata.length]; - System.arraycopy(aMetadata, 0, mMetadata, 0, aMetadata.length); - } - } - @Override - public boolean equals(Object o) { - if (o instanceof BleBroadcastSourceChannel) { - BleBroadcastSourceChannel other = (BleBroadcastSourceChannel) o; - return (other.mIndex == mIndex - && other.mDescription == mDescription - && other.mStatus == mStatus - ); - } - return false; - } - @Override - public int hashCode() { - return Objects.hash(mIndex, mDescription, mStatus); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public String toString() { - return mDescription; - } - - /** - * Gets the Source Id of the BleBroadcastSourceChannel Object - * - * @return byte representing the Source Id of the Broadcast Source Info Object - * {@link #BROADCAST_ASSIST_INVALID_SOURCE_ID} in case if this field is not valid - * @hide - */ - public int getIndex () { - return mIndex; - } - - /** - * Gets the Broadcast source Device object from the BleBroadcastSourceChannel Object - * - * @return BluetoothDevice object for Broadcast source device - * @hide - */ - public String getDescription () { - return mDescription; - } - - /** - * Gets the status of given BleBroadcastSourceChannel - * - * @return true if selected, false otherwise - * @hide - * - * @deprecated - */ - - public boolean getStatus () { - return mStatus; - } - - /** - * Gets the address type of the Broadcast source advertisement for the BleBroadcastSourceChannel Object - * - * @return byte addressType, this can be one of {@link #BROADCAST_ASSIST_ADDRESS_TYPE_PUBLIC} OR {@link #BROADCAST_ASSIST_ADDRESS_TYPE_PUBLIC} - * @hide - * - * @deprecated - */ - - public byte[] getMetadata () { - return mMetadata; - } - - /** - * Gets the subgroup Id that broadcast Channel belongs - * Internal helper function - * - * @hide - * @deprecated - */ - public int getSubGroupId () { - return mSubGroupId; - } - - /** - * Sets the status of given BleBroadcastSourceChannel - * - * @return true if selected, false otherwise - * @hide - * - * @deprecated - */ - public void setStatus (boolean status) { - mStatus = status; - } - - - public static final @android.annotation.NonNull Parcelable.Creator CREATOR = - new Parcelable.Creator() { - public BleBroadcastSourceChannel createFromParcel(Parcel in) { - - log(TAG, "createFromParcel>"); - final int index = in.readInt(); - final String desc = in.readString(); - final boolean status = in.readBoolean(); - final int subGroupId = in.readInt(); - - final int metadataLength = in.readInt(); - byte[] metadata = null; - if (metadataLength > 0) { - metadata = new byte[metadataLength]; - in.readByteArray(metadata); - } - - BleBroadcastSourceChannel srcChannel = - new BleBroadcastSourceChannel(index, desc, status, subGroupId, metadata); - log(TAG, "createFromParcel:" + srcChannel); - return srcChannel; - } - - public BleBroadcastSourceChannel[] newArray(int size) { - return new BleBroadcastSourceChannel[size]; - } - }; - - - - @Override - public void writeToParcel(Parcel out, int flags) { - log(TAG, "writeToParcel>"); - out.writeInt(mIndex); - out.writeString(mDescription); - out.writeBoolean(mStatus); - out.writeInt(mSubGroupId); - if (mMetadata != null) { - out.writeInt(mMetadata.length); - out.writeByteArray(mMetadata); - } else { - out.writeInt(0); - } - log(TAG, "writeToParcel:" + toString()); - } - private static void log(String TAG, String msg) { - BleBroadcastSourceInfo.BASS_Debug(TAG, msg); - } -}; - diff --git a/le_audio/frameworks/base/core/java/android/bluetooth/BleBroadcastSourceInfo.java b/le_audio/frameworks/base/core/java/android/bluetooth/BleBroadcastSourceInfo.java deleted file mode 100644 index 1e159017c9a8d2d12190ccd6b53bf1e637b38fc0..0000000000000000000000000000000000000000 --- a/le_audio/frameworks/base/core/java/android/bluetooth/BleBroadcastSourceInfo.java +++ /dev/null @@ -1,1052 +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. - * - ******************************************************************************/ - -package android.bluetooth; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.IBluetoothGatt; -import android.bluetooth.IBluetoothManager; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Retention; -import android.annotation.IntDef; -import android.compat.annotation.UnsupportedAppUsage; - -import android.os.Parcel; -import android.os.Parcelable; -import android.os.Handler; -import android.os.Looper; -import android.os.RemoteException; -import android.util.Log; -import java.util.Objects; -import android.util.Log; -import java.util.List; -import java.util.ArrayList; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.HashMap; - -/** - * This class provides methods to get various information of Broadcast - * source information stored in remote. Users can call get/set methods - * enquire the required information - * - *

This also acts as general data structure for updating the Broadcast - * source information - * This class is used to input the User provided data for below operations - * {@link BleBroadcastAudioScanAssistManager#addBroadcastSource}, - * {@link BleBroadcastAudioScanAssistManager#updateBroadcastSource} and - * {@link BleBroadcastAudioScanAssistManager#setBroadcastCode} - * - *

This is also used to pack all Broadcast source information as part of {@link #ACTION_BROADCAST_RECEIVER_STATE} - * Intent. User can retrive the {@link BleBroadcastSourceInfo} using {@link BleBroadcastSourceInfo#EXTRA_RECEIVER_STATE} - * extra field - * @hide - */ -public final class BleBroadcastSourceInfo implements Parcelable { - - private static final String TAG = "BleBroadcastSourceInfo"; - private static final boolean BASS_DBG = Log.isLoggable(TAG, Log.VERBOSE); - - /** @hide - * @deprecated - */ - @Deprecated - @IntDef(prefix = "BROADCAST_ASSIST_ADDRESS_TYPE_", value = { - BROADCAST_ASSIST_ADDRESS_TYPE_PUBLIC, - BROADCAST_ASSIST_ADDRESS_TYPE_RANDOM - }) - @Retention(RetentionPolicy.SOURCE) - public @interface BroadcastAssistAddressType {} - - /** - * Address Type of the LE Broadcast Audio Source Device - * Specifies whether LE Broadcast Audio Source device using public OR - * random address for the LE Audio broadcasts - * - * @deprecated - */ - @Deprecated - public static final int BROADCAST_ASSIST_ADDRESS_TYPE_PUBLIC = 0; - /** - * Address Type of the LE Broadcast Audio Source Device - * Specifies whether LE Broadcast Audio Source device using public OR - * random address for the LE Audio broadcasts - * - * @deprecated - */ - @Deprecated - public static final int BROADCAST_ASSIST_ADDRESS_TYPE_RANDOM = 1; - /** - * Address Type of the LE Broadcast Audio Source Device - * Specifies whether LE Broadcast Audio Source device using public PR - * random address for the LE Audio broadcasts - * - * @deprecated - */ - @Deprecated - public static final int BROADCAST_ASSIST_ADDRESS_TYPE_INVALID = 0xFFFF; - - /** @hide */ - @IntDef(prefix = "BROADCAST_ASSIST_PA_SYNC_STATE_", value = { - BROADCAST_ASSIST_PA_SYNC_STATE_IDLE, - BROADCAST_ASSIST_PA_SYNC_STATE_SYNCINFO_REQ, - BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC, - BROADCAST_ASSIST_PA_SYNC_STATE_SYNC_FAIL, - BROADCAST_ASSIST_PA_SYNC_STATE_NO_PAST - }) - @Retention(RetentionPolicy.SOURCE) - public @interface BroadcastAssistMetadataSyncState {} - - /** - * Meta data Sync State - * Broadcast receiver sync state w.r.t PA. State IDLE specifies that broadcast - * receiver is not able to sync the Metada/PA - */ - public static final int BROADCAST_ASSIST_PA_SYNC_STATE_IDLE = 0; - /** - * Meta data Sync State - * Broadcast receiver sync state w.r.t PA. State SYNCINFO REQ specifies that broadcast - * receiver requesting for SYNCINFO from the Scan Offloader to synchronie - * to Metadata/PA - */ - public static final int BROADCAST_ASSIST_PA_SYNC_STATE_SYNCINFO_REQ = 1; - /** - * Meta data Sync State - * Broadcast receiver sync state w.r.t PA. State INSYNC specifies that broadcast - * receiver in sync with to Metadata/PA. - */ - public static final int BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC = 2; - /** - * Meta data Sync State - * Broadcast receiver sync state w.r.t PA. State INSYNC specifies that broadcast - * receiver is failed to sync with Metadata/PA. - */ - public static final int BROADCAST_ASSIST_PA_SYNC_STATE_SYNC_FAIL = 3; - /** - * Meta data Sync State - * Broadcast receiver sync state w.r.t PA. State SYNC NOPAST denotes that broadcast - * receiver needs PAST procedure to sync with Metadata. - */ - public static final int BROADCAST_ASSIST_PA_SYNC_STATE_NO_PAST = 4; - /** - * Meta data Sync State - * Broadcast receiver sync state w.r.t PA. State SYNC NOPAST denotes that broadcast - * receiver needs PAST procedure to sync with Metadata. - */ - public static final int BROADCAST_ASSIST_PA_SYNC_STATE_INVALID = 0xFFFF; - - /** @hide */ - @IntDef(prefix = "BROADCAST_ASSIST_AUDIO_SYNC_STATE_", value = { - BROADCAST_ASSIST_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED, - BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED - }) - @Retention(RetentionPolicy.SOURCE) - public @interface BroadcastAssistAudioSyncState {} - - /** - * Broadcast Audio stream Sync State - * Broadcast receiver sync state w.r.t Broadcast Audio stream BIS. denotes - * receiver is not synchronized to LE Audio BIS - */ - public static final int BROADCAST_ASSIST_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED = 0; - /** - * Broadcast Audio stream Sync State - * Broadcast receiver sync state w.r.t Broadcast Audio stream BIS. denotes - * receiver is not synchronized to LE Audio BIS - */ - public static final int BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED = 1; - /** - * Broadcast Audio stream Sync State - * Broadcast receiver sync state w.r.t Broadcast Audio stream BIS. denotes - * receiver is not synchronized to LE Audio BIS - */ - public static final int BROADCAST_ASSIST_AUDIO_SYNC_STATE_INVALID = 0xFFFF; - - - /** @hide */ - @IntDef(prefix = "BROADCAST_ASSIST_ENC_STATE_", value = { - BROADCAST_ASSIST_ENC_STATE_UNENCRYPTED, - BROADCAST_ASSIST_ENC_STATE_PIN_NEEDED, - BROADCAST_ASSIST_ENC_STATE_DECRYPTING - }) - @Retention(RetentionPolicy.SOURCE) - public @interface BroadcastAssistEncryptionState {} - /** - * Encryption Status at the LE Audio broadcast receiver side - * UNENCRYPTED denoted that broadcast receiver is in sync with an uncrypted - * broadcasted audio - */ - public static final int BROADCAST_ASSIST_ENC_STATE_UNENCRYPTED = 0; - /** - * Encryption Status at the LE Audio broadcast receiver side - * PIN_NEEDED denote that the Broadcast receiver needs broadcast PIN - * to sync and listen to Broadcasted Audio - */ - public static final int BROADCAST_ASSIST_ENC_STATE_PIN_NEEDED = 1; - /** - * Encryption Status at the LE Audio broadcast receiver side - * state DECRYPTING denote that the Broadcast receiver is able to decrypt - * and listen to the Broadcasted Audio - */ - public static final int BROADCAST_ASSIST_ENC_STATE_DECRYPTING = 2; - /** - * Encryption Status at the LE Audio broadcast receiver side - * state BADCODE denote that the Broadcast receiver has got bad code - * and not able decrypt - * Incorrect code that Scan delegator tried to decrypt can be retrieved from - * - */ - public static final int BROADCAST_ASSIST_ENC_STATE_BADCODE = 3; - /** - * Encryption Status at the LE Audio broadcast receiver side - * state DECRYPTING denote that the Broadcast receiver is able to decrypt - * and listen to the Broadcasted Audio - */ - public static final int BROADCAST_ASSIST_ENC_STATE_INVALID = 0xFFFF; - - /* - * Invalid Broadcast source Information Id - */ - public static final byte BROADCAST_ASSIST_INVALID_SOURCE_ID = (byte)0x00; - /* - * Invalid Broadcaster Identifier of the given Broadcast Source - */ - public static final int BROADCASTER_ID_INVALID = 0xFFFF; - /** - * Used as an int extra field in {@link BleBroadcastAudioScanAssistManager#ACTION_BROADCAST_RECEIVER_STATE} - * intent notifys the Broadcast Source Information to Application layer - * - *

Source Info object can be extracted using this extra field at Application layer - * - * This is used to read the {@link BleBroadcastSourceInfo } parcelable object - * @hide - */ - public static final String EXTRA_SOURCE_INFO = "android.bluetooth.device.extra.SOURCE_INFO"; - /** - * Used as an int extra field in {@link BleBroadcastAudioScanAssistManager#ACTION_BROADCAST_RECEIVER_STATE} - * intent Broadcast Source Information to Application layer - * - *

Index of the Source Info object can be extracted using this extra field at Application layer - * - * This is used to read the {@link BleBroadcastSourceInfo } parcelable object - * @hide - */ - public static final String EXTRA_SOURCE_INFO_INDEX = "android.bluetooth.device.extra.SOURCE_INFO_INDEX"; - /** - * Used as an int extra field in {@link BleBroadcastAudioScanAssistManager#ACTION_BROADCAST_RECEIVER_STATE} - * intent notifys the Broadcast Source Information to Application layer - * - *

Maximm number of the Broadcast Source Information that given broadcast receiver can hold, can be extracted using - * this extra field at Application layer - * - * @hide - */ - public static final String EXTRA_MAX_NUM_SOURCE_INFOS = "android.bluetooth.device.extra.MAX_NUM_SOURCE_INFOS"; - private byte mSourceId; - private @BroadcastAssistAddressType int mSourceAddressType; - private BluetoothDevice mSourceDevice; - private byte mSourceAdvSid; - private int mBroadcasterId; - private @BroadcastAssistMetadataSyncState int mMetaDataSyncState; - private @BroadcastAssistAudioSyncState int mAudioSyncState; - private Map mAudioBisIndexList = new HashMap (); - private @BroadcastAssistEncryptionState int mEncyptionStatus; - private Map mMetadataList = new HashMap(); - private String mBroadcastCode; - private byte[] mBadBroadcastCode; - private byte mNumSubGroups; - private static final int BIS_NO_PREF = 0xFFFFFFFF; - private static final int BROADCAST_CODE_SIZE = 16; - - /** - * Constructor to create an Empty object of {@link BleBroadcastSourceInfo } with given source Id, - * which contains, Broadcast reciever state information for Broadcast Assistant Usecases. - * - * This is mainly used to represent the Empty Broadcast source entries - * - * @param sourceId Source Id for this broadcast source info object - * - * @deprecated - * @hide - */ - @Deprecated - public BleBroadcastSourceInfo (byte sourceId) { - mSourceId = sourceId; - mMetaDataSyncState = BROADCAST_ASSIST_PA_SYNC_STATE_INVALID; - mAudioSyncState = BROADCAST_ASSIST_AUDIO_SYNC_STATE_INVALID; - mSourceAddressType = BROADCAST_ASSIST_ADDRESS_TYPE_INVALID; - mSourceDevice = null; - mSourceAdvSid = (byte)0x00; - mEncyptionStatus = BROADCAST_ASSIST_ENC_STATE_INVALID; - mBroadcastCode = null; - mBadBroadcastCode = null; - mNumSubGroups = 0; - mBroadcasterId = BROADCASTER_ID_INVALID; - } - /** - * Constructor to create an object of {@link BleBroadcastSourceInfo } which contains - * Broadcast reciever state information for Broadcast Assistant Usecases. - * This is mainly used for input purpose of {@link BleBroadcastAudioScanAssistManager#addBroadcastSource} - * operation - * - * @param audioSource BluetoothDevice object whcih is selected as Broadcast source - * @param advSid advertising Sid of the Broadcast source device for which reciever synchronized with. - * @param addressType type of address. This can be be one of {@link #BROADCAST_ASSIST_ADDRESS_TYPE_PUBLIC} or - * {@link #BROADCAST_ASSIST_ADDRESS_TYPE_RANDOM} - * @param metadataSyncState sync status of metadata at the receiver side from this Broadcast source. This can - * be one of {@link #BROADCAST_ASSIST_PA_SYNC_STATE_IDLE}, {@link #BROADCAST_ASSIST_PA_SYNC_STATE_SYNCINFO_REQ}, - * {@link #BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC}, - * {@link #BROADCAST_ASSIST_PA_SYNC_STATE_SYNC_FAIL} OR {@link #BROADCAST_ASSIST_PA_SYNC_STATE_SYNC_NO_PAST} - * @param audioSyncState Audio sync status of metadata at the receiver side from this broadcast source. This can be - * one of {@link #BROADCAST_ASSIST_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED} OR - * {@link #BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED} - * @param audioBisIndex Audio BIS index for what Broadcast reciever synchronized with - * @param metadataLength Length of the metadata field - * @prama metadata metadata information about the type Broadcast information being synchronized at receiver side - * - * - * @hide - */ - /*package*/ BleBroadcastSourceInfo (BluetoothDevice audioSource, - byte advSid, - @BroadcastAssistAddressType int addressType, - @BroadcastAssistMetadataSyncState int metadataSyncstate, - @BroadcastAssistAudioSyncState int audioSyncstate, - List selectedBISIndicies - ) { - mMetaDataSyncState = metadataSyncstate; - mAudioSyncState = audioSyncstate; - mSourceAddressType = addressType; - mSourceDevice = audioSource; - mSourceAdvSid = advSid; - mBroadcasterId = BROADCASTER_ID_INVALID; - if (selectedBISIndicies == null) { - BASS_Debug(TAG, "selectedBISIndiciesList is null"); - } else { - for (int i=0; i> selectedBISIndiciesList, - Map metadataList - ) { - mSourceId = sourceId; - mSourceAddressType = addressType; - mSourceDevice = audioSource; - mSourceAdvSid = advSid; - mBroadcasterId = broadcasterId; - mMetaDataSyncState = metadataSyncstate; - mAudioSyncState = audioSyncstate; - mEncyptionStatus = encryptionStatus; - if (badCode != null) { - mBadBroadcastCode = new byte[BROADCAST_CODE_SIZE]; - System.arraycopy(badCode, 0, mBadBroadcastCode, 0, mBadBroadcastCode.length); - } - mNumSubGroups = numSubGroups; - int audioBisIndex = 0; - if (selectedBISIndiciesList != null) { - for (Map.Entry> entry : selectedBISIndiciesList.entrySet()) { - List selectedBISIndicies = entry.getValue(); - if (selectedBISIndicies == null) { - //do nothing - BASS_Debug(TAG, "selectedBISIndiciesList is null"); - } else { - for (int i=0; i entry : metadataList.entrySet()) { - byte[] metadata = entry.getValue(); - if (metadata != null && metadata.length != 0) { - byte[] mD = new byte[metadata.length]; - System.arraycopy(metadata, 0, mD, 0, metadata.length); - } - mMetadataList.put(entry.getKey(), metadata); - } - } - } - - /** - * Constructor override to create an object of {@link BleBroadcastSourceInfo } which contains - * Broadcast reciever state information for Broadcast Assistant Usecases. - * - * This is mainly used for output purpose to create an object from the receiver state information - * read from the remote BASS server. This will be packed and broadcasted as an Intent using - * {@link #ACTION_BROADCAST_RECEIVER_STATE} - * - * @param audioSource BluetoothDevice object whcih is selected as Broadcast source - * @param advSid advertising Sid of the Broadcast source device for which reciever synchronized with - * @param addressType type of address. This can be be one of {@link #BLE_ASSIST_ADDRESS_TYPE_PUBLIC} or - * {@link #BLE_ASSIST_ADDRESS_TYPE_RANDOM} - * @param metadataSyncState sync status of metadata at the receiver side from this Broadcast source. This can - * be one of {@link #BROADCAST_ASSIST_PA_SYNC_STATE_IDLE}, {@link #BROADCAST_ASSIST_PA_SYNC_STATE_SYNCINFO_REQ}, - * {@link #BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC}, - * {@link #BROADCAST_ASSIST_PA_SYNC_STATE_SYNC_FAIL} OR {@link #BROADCAST_ASSIST_PA_SYNC_STATE_SYNC_NO_PAST} - * @param audioSyncState Audio sync status of metadata at the receiver side from this broadcast source. This can be - * one of {@link #BROADCAST_ASSIST_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED} OR - * {@link #BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED} - * @param encryptionStatus Encryotion state at Broadcast receiver. This can be one of {@link #BROADCAST_ASSIST_ENC_STATE_UNENCRYPTED}, - * {@link #BROADCAST_ASSIST_ENC_STATE_PIN_NEEDED} OR {@link #BROADCAST_ASSIST_ENC_STATE_DECRYPTING} - * @param audioBisIndex Audio BIS index for what Broadcast reciever synchronized with - * @param metadataLength Length of the metadata field - * @prama metadata metadata information about the type Broadcast information being synchronized at receiver side - * @param broadcastCode Numeric Character String maximum of 16 characters in length, which serves as broadcast PIN code - * - * @hide - */ - /*package*/ BleBroadcastSourceInfo (BluetoothDevice device, - byte sourceId, - byte advSid, - @BroadcastAssistAddressType int addressType, - @BroadcastAssistMetadataSyncState int metadataSyncstate, - @BroadcastAssistAudioSyncState int audioSyncstate, - List selectedBISIndicies, - @BroadcastAssistEncryptionState int encryptionStatus, - String broadcastCode) { - mSourceId = sourceId; - mMetaDataSyncState = metadataSyncstate; - mAudioSyncState = audioSyncstate; - mEncyptionStatus = encryptionStatus; - mSourceAddressType = addressType; - mSourceDevice = device; - mSourceAdvSid = advSid; - mBroadcasterId = BROADCASTER_ID_INVALID; - if (selectedBISIndicies == null) { - BASS_Debug(TAG, "selectedBISIndiciesList is null"); - } else { - for (int i=0; i bisIndiciesList, - Map metadataList - ) { - mSourceId = sourceId; - mMetaDataSyncState = metadataSyncstate; - mAudioSyncState = audioSyncstate; - mEncyptionStatus = encryptionStatus; - mSourceAddressType = addressType; - mSourceDevice = device; - mSourceAdvSid = advSid; - mBroadcasterId = broadcasterId; - mBroadcastCode = broadcastCode; - if (badCode != null && badCode.length != 0) { - mBadBroadcastCode= new byte[badCode.length]; - System.arraycopy(badCode, 0, mBadBroadcastCode, 0, badCode.length); - } - mNumSubGroups = numSubGroups; - mAudioBisIndexList = new HashMap (bisIndiciesList); - mMetadataList = new HashMap (metadataList); - } - - @Override - public boolean equals(Object o) { - if (o instanceof BleBroadcastSourceInfo) { - BleBroadcastSourceInfo other = (BleBroadcastSourceInfo) o; - BASS_Debug(TAG, "other>> " + o.toString()); - BASS_Debug(TAG, "local>> " + toString()); - return (other.mSourceId == mSourceId - && other.mMetaDataSyncState == mMetaDataSyncState - && other.mAudioSyncState == mAudioSyncState - && other.mSourceAddressType == mSourceAddressType - && other.mSourceDevice == mSourceDevice - && other.mSourceAdvSid == mSourceAdvSid - && other.mEncyptionStatus == mEncyptionStatus - && other.mBroadcastCode == mBroadcastCode - && other.mBroadcasterId == mBroadcasterId - ); - } - return false; - } - - public boolean isEmptyEntry() { - boolean ret = false; - if (mMetaDataSyncState == (int)BROADCAST_ASSIST_PA_SYNC_STATE_INVALID && - mAudioSyncState == (int)BROADCAST_ASSIST_AUDIO_SYNC_STATE_INVALID && - mSourceAddressType == (int)BROADCAST_ASSIST_ADDRESS_TYPE_INVALID && - mSourceDevice == null && - mSourceAdvSid == (byte)0 && - mEncyptionStatus == (int)BROADCAST_ASSIST_ENC_STATE_INVALID - ) { - ret = true; - } - BASS_Debug(TAG, "isEmptyEntry returns: " + ret); - return ret; - } - - public boolean matches(BleBroadcastSourceInfo srcInfo) { - boolean ret = false; - if (srcInfo == null) { - ret = false; - } else { - if (mSourceDevice == null) { - if (mSourceAdvSid == srcInfo.getAdvertisingSid() && - mSourceAddressType == srcInfo.getAdvAddressType()) { - ret = true; - } - } else { - if (mSourceDevice.equals(srcInfo.getSourceDevice()) && - mSourceAdvSid == srcInfo.getAdvertisingSid() && - mSourceAddressType == srcInfo.getAdvAddressType() && - mBroadcasterId == srcInfo.getBroadcasterId()) { - ret = true; - } - } - } - BASS_Debug(TAG, "matches returns: " + ret); - return ret; - } - - @Override - public int hashCode() { - return Objects.hash(mSourceId, mMetaDataSyncState, mAudioSyncState, - mSourceAddressType, mSourceDevice, mSourceAdvSid, - mEncyptionStatus, mBroadcastCode); - } - - @Override - public int describeContents() { - return 0; - } - @Override - public String toString() { - return "{BleBroadcastSourceInfo : mSourceId" + mSourceId - + " sourceDevice: " + mSourceDevice - + " addressType: " + mSourceAddressType - + " mSourceAdvSid:" + mSourceAdvSid - + " mMetaDataSyncState:" + mMetaDataSyncState - + " mAudioSyncState" + mAudioSyncState - + " mEncyptionStatus" + mEncyptionStatus - + " mBadBroadcastCode" + mBadBroadcastCode - + " mNumSubGroups" + mNumSubGroups - + " mBroadcastCode" + mBroadcastCode - + " mAudioBisIndexList" + mAudioBisIndexList - + " mMetadataList" + mMetadataList - + " mBroadcasterId" + mBroadcasterId - + "}"; - } - - /** - * Gets the Source Id of the BleBroadcastSourceInfo Object - * - * @return byte representing the Source Id of the Broadcast Source Info Object - * {@link #BROADCAST_ASSIST_INVALID_SOURCE_ID} in case if this field is not valid - * @hide - */ - public byte getSourceId () { - return mSourceId; - } - - /** - * Sets the Source Id of the BleBroadcastSourceInfo Object - * - * @param byte source Id for the BleBroadcastSourceInfo Object - * - * @hide - */ - public void setSourceId (byte sourceId) { - mSourceId = sourceId; - } - - /** - * Sets the Broadcast source device for the BleBroadcastSourceInfo Object - * - * @param BluetoothDevice which need to be set as Broadcast source device - * @hide - */ - public void setSourceDevice(BluetoothDevice sourceDevice) { - mSourceDevice = sourceDevice; - } - - /** - * Gets the Broadcast source Device object from the BleBroadcastSourceInfo Object - * - * @return BluetoothDevice object for Broadcast source device - * @hide - */ - public BluetoothDevice getSourceDevice () { - return mSourceDevice; - } - - /** - * Sets the address type of the Broadcast source advertisement for the BleBroadcastSourceInfo Object - * - * @param byte addressType, this can be one of {@link #BROADCAST_ASSIST_ADDRESS_TYPE_PUBLIC} OR {@link #BROADCAST_ASSIST_ADDRESS_TYPE_PUBLIC} - * @hide - */ - public void setAdvAddressType(int addressType) { - mSourceAddressType = addressType; - } - - /** - * Gets the address type of the Broadcast source advertisement for the BleBroadcastSourceInfo Object - * - * @return byte addressType, this can be one of {@link #BROADCAST_ASSIST_ADDRESS_TYPE_PUBLIC} OR {@link #BROADCAST_ASSIST_ADDRESS_TYPE_PUBLIC} - * @hide - * - * @deprecated - */ - @UnsupportedAppUsage - @Deprecated - public int getAdvAddressType () { - return mSourceAddressType; - } - - /** - * Sets the advertising Sid of the Broadcast source advertisement for the BleBroadcastSourceInfo Object - * - * @param byte advertising Sid value - * @hide - */ - public void setAdvertisingSid(byte advSid) { - mSourceAdvSid = advSid; - } - - /** - * Gets the advertising Sid of the Broadcast source advertisement for the BleBroadcastSourceInfo Object - * - * @return byte advertising Sid value - * @hide - */ - public byte getAdvertisingSid () { - return mSourceAdvSid; - } - - /** - * Gets the Broadcast Id of the Broadcast source of the BleBroadcastSourceInfo Object - * - * @return int broadcast source Identifier - * @hide - */ - public int getBroadcasterId () { - return mBroadcasterId; - } - - /** - * Sets the Metadata sync status at the Broadcast receiver side for the BleBroadcastSourceInfo Object - * - * @param BroadcastAssistMetadataSyncState representing the state of Meta data sync status. this can be one of - * {@link #BROADCAST_ASSIST_PA_SYNC_STATE_IDLE}, {@link #BROADCAST_ASSIST_PA_SYNC_STATE_SYNCINFO_REQ}, - * {@link #BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC}, - * {@link #BROADCAST_ASSIST_PA_SYNC_STATE_SYNC_FAIL} OR {@link #BROADCAST_ASSIST_PA_SYNC_STATE_SYNC_NO_PAST} - * - * @hide - */ - /*package*/ void setMetadataSyncState(@BroadcastAssistMetadataSyncState int metadataSyncState) { - mMetaDataSyncState = metadataSyncState; - } - - /** - * Gets the Metadata sync status at the Broadcast receiver side from the BleBroadcastSourceInfo Object - * - * @return BroadcastAssistMetadataSyncState representing the state of Meta data sync status. this can be one of - * {@link #BROADCAST_ASSIST_PA_SYNC_STATE_IDLE}, {@link #BROADCAST_ASSIST_PA_SYNC_STATE_SYNCINFO_REQ}, - * {@link #BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC}, - * {@link #BROADCAST_ASSIST_PA_SYNC_STATE_SYNC_FAIL} OR {@link #BROADCAST_ASSIST_PA_SYNC_STATE_SYNC_NO_PAST} - * - * @hide - */ - public @BroadcastAssistMetadataSyncState int getMetadataSyncState () { - return mMetaDataSyncState; - } - - /** - * Sets the Audio sync status at the Broadcast receiver side for the BleBroadcastSourceInfo Object - * - * @param BroadcastAssistAudioSyncState representing the state of Meta data sync status. this can be one of - * {@link #BROADCAST_ASSIST_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED} OR - * {@link #BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED} - * - * @hide - */ - /*package*/ void setAudioSyncState(@BroadcastAssistAudioSyncState int audioSyncState) { - mAudioSyncState = audioSyncState; - } - - /** - * Gets the Audio sync status at the Broadcast receiver side from the BleBroadcastSourceInfo Object - * - * @return BroadcastAssistAudioSyncState representing the state of Meta data sync status. this can be one of - * {@link #BROADCAST_ASSIST_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED} OR - * {@link #BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED} * - * @hide - */ - public @BroadcastAssistAudioSyncState int getAudioSyncState () { - return mAudioSyncState; - } - - /** - * Sets the Encryption status at the Broadcast receiver side for the BleBroadcastSourceInfo Object - * - * @param BroadcastAssistEncryptionState representing the state of Meta data sync status. This can be one of - * {@link #BROADCAST_ASSIST_ENC_STATE_UNENCRYPTED}, - * {@link #BROADCAST_ASSIST_ENC_STATE_PIN_NEEDED}, {@link #BROADCAST_ASSIST_ENC_STATE_DECRYPTING} - * Or {@link #BROADCAST_ASSIST_ENC_STATE_BADCODE} - * @hide - */ - /*package*/ void setEncryptionStatus(@BroadcastAssistEncryptionState int encryptionStatus) { - mEncyptionStatus = encryptionStatus; - } - - /** - * Gets the Audio sync status at the Broadcast receiver side from the BleBroadcastSourceInfo Object - * - * @return BroadcastAssistEncryptionState representing the state of Meta data sync status. This can be one of - * {@link #BROADCAST_ASSIST_ENC_STATE_UNENCRYPTED}, - * {@link #BROADCAST_ASSIST_ENC_STATE_PIN_NEEDED} ,{@link #BROADCAST_ASSIST_ENC_STATE_DECRYPTING} - * Or {@link #BROADCAST_ASSIST_ENC_STATE_BADCODE} - * @hide - */ - public @BroadcastAssistEncryptionState int getEncryptionStatus () { - return mEncyptionStatus; - } - - /** - * Gets the Incorrect Broadcast code with which Scan delegator try - * decrypt the Broadcast audio and failed - * - * This code is valid only if {@link #getEncryptionStatus} returns - * {@link #BROADCAST_ASSIST_ENC_STATE_BADCODE} - * - * @param byte[] byte array containing bad broadcast value - * null if the current Encryptetion status is - * not {@link #BROADCAST_ASSIST_ENC_STATE_BADCODE} - * - * @hide - */ - public byte[] getBadBroadcastCode () { - return mBadBroadcastCode; - } - - /** - * Gets the number of subgroups of the BleBroadcastSourceInfo Object - * - * @return byte number of subgroups - * @hide - * - * @deprecated - */ - @UnsupportedAppUsage - @Deprecated - public byte getNumberOfSubGroups () { - return mNumSubGroups; - } - - /** - * Sets the Audio Broadcast channels to which receiver need to be synchronized with, - * for BleBroadcastSourceInfo Object - * - * - * @param int audioBis Index to which reciever need to be synchronized with - * @hide - */ - /*package*/ void setBroadcastChannelsSyncStatus(List selectedBISIndicies) { - if (selectedBISIndicies == null) { - //set No preference - BASS_Debug(TAG, "selectedBISIndiciesList is null"); - return; - } - for (int i=0; i getBroadcastChannelsSyncStatus () { - List bcastIndicies = new ArrayList(); - for (int i=0; i>1; - index++; - } - } - - BASS_Debug(TAG, "returning Bisindicies:" + bcastIndicies); - return bcastIndicies; - } - - @UnsupportedAppUsage - @Deprecated - public Map getBisIndexList() { - return mAudioBisIndexList; - } - - /*package*/ void setBroadcastCode(String broadcastCode) { - mBroadcastCode = broadcastCode; - } - - @UnsupportedAppUsage - @Deprecated - public void setBroadcasterId(int broadcasterId) { - mBroadcasterId = broadcasterId; - } - - /** - * Gets the broadcastCode value from BleBroadcastSourceInfo Object - * - * @param String broadcast code from the BleBroadcastSourceInfo object - * @hide - * - * @deprecated - */ - @UnsupportedAppUsage - @Deprecated - public String getBroadcastCode () { - return mBroadcastCode; - } - - private void writeMapToParcel(Parcel dest, Map bisIndexList) { - dest.writeInt(bisIndexList.size()); - for (Map.Entry entry : bisIndexList.entrySet()) { - dest.writeInt(entry.getKey()); - dest.writeInt(entry.getValue()); - } - } - - private static void readMapFromParcel(Parcel in, Map bisIndexList) { - int size = in.readInt(); - - for (int i = 0; i < size; i++) { - Integer key = in.readInt(); - Integer value = in.readInt(); - bisIndexList.put(key, value); - } - } - - private void writeMetadataListToParcel(Parcel dest, Map metadataList) { - dest.writeInt(metadataList.size()); - for (Map.Entry entry : metadataList.entrySet()) { - dest.writeInt(entry.getKey()); - byte[] metadata = entry.getValue(); - if (metadata != null) { - dest.writeInt(metadata.length); - dest.writeByteArray(metadata); - } - } - } - - private static void readMetadataListFromParcel(Parcel in, Map metadataList) { - int size = in.readInt(); - - for (int i = 0; i < size; i++) { - Integer key = in.readInt(); - Integer metaDataLen = in.readInt(); - byte[] metadata = null; - if (metaDataLen != 0) { - metadata = new byte[metaDataLen]; - in.readByteArray(metadata); - } - metadataList.put(key, metadata); - } - } - - public static final @android.annotation.NonNull Parcelable.Creator CREATOR = - new Parcelable.Creator() { - public BleBroadcastSourceInfo createFromParcel(Parcel in) { - - BASS_Debug(TAG, "createFromParcel>"); - final byte sourceId = in.readByte(); - final int sourceAddressType = in.readInt(); - final BluetoothDevice sourceDevice = in.readTypedObject( - BluetoothDevice.CREATOR); - final byte sourceAdvSid = in.readByte(); - final int broadcastId = in.readInt(); - BASS_Debug(TAG, "broadcastId" + broadcastId); - final int metaDataSyncState = in.readInt(); - final int audioSyncState = in.readInt(); - BASS_Debug(TAG, "audioSyncState" + audioSyncState); - final int encyptionStatus = in.readInt(); - final int badBroadcastLen = in.readInt(); - byte[] badBroadcastCode = null; - if (badBroadcastLen > 0) { - badBroadcastCode = new byte[badBroadcastLen]; - in.readByteArray(badBroadcastCode); - } - final byte numSubGroups = in.readByte(); - final String broadcastCode = in.readString(); - Map bisIndexList = new HashMap (); - readMapFromParcel(in, bisIndexList); - Map metadataList = new HashMap (); - readMetadataListFromParcel(in, metadataList); - - BleBroadcastSourceInfo srcInfo = new BleBroadcastSourceInfo(sourceDevice, sourceId, sourceAdvSid, broadcastId, - sourceAddressType, metaDataSyncState,audioSyncState, - encyptionStatus, broadcastCode, badBroadcastCode, numSubGroups, bisIndexList, metadataList); - BASS_Debug(TAG, "createFromParcel:" + srcInfo); - return srcInfo; - } - - public BleBroadcastSourceInfo[] newArray(int size) { - return new BleBroadcastSourceInfo[size]; - } - }; - - @Override - public void writeToParcel(Parcel out, int flags) { - BASS_Debug(TAG, "writeToParcel>"); - out.writeByte(mSourceId); - out.writeInt(mSourceAddressType); - out.writeTypedObject(mSourceDevice, 0); - out.writeByte(mSourceAdvSid); - out.writeInt(mBroadcasterId); - out.writeInt(mMetaDataSyncState); - out.writeInt(mAudioSyncState); - out.writeInt(mEncyptionStatus); - if (mBadBroadcastCode != null) { - out.writeInt(mBadBroadcastCode.length); - out.writeByteArray(mBadBroadcastCode); - } else { - //write ZERO to parcel to say no badBroadcastcode - out.writeInt(0); - } - out.writeByte(mNumSubGroups); - out.writeString(mBroadcastCode); - writeMapToParcel(out, mAudioBisIndexList); - writeMetadataListToParcel(out, mMetadataList); - BASS_Debug(TAG, "writeToParcel:" + toString()); - } - - static void BASS_Debug(String TAG, String msg) { - if (BASS_DBG) { - Log.d(TAG, msg); - } - } - -}; - diff --git a/le_audio/frameworks/base/core/java/android/bluetooth/BluetoothBroadcast.java b/le_audio/frameworks/base/core/java/android/bluetooth/BluetoothBroadcast.java deleted file mode 100644 index b709078cb7eaeafddbcbd5f7400914a263f1c789..0000000000000000000000000000000000000000 --- a/le_audio/frameworks/base/core/java/android/bluetooth/BluetoothBroadcast.java +++ /dev/null @@ -1,280 +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. - * - ******************************************************************************/ - -package android.bluetooth; - -import android.Manifest; -import android.annotation.Nullable; -import android.annotation.RequiresPermission; -import android.annotation.SdkConstant; -import android.annotation.SdkConstant.SdkConstantType; -import android.content.Context; -import android.os.Binder; -import android.os.Build; -import android.os.IBinder; -import android.os.ParcelUuid; -import android.os.RemoteException; -import android.util.Log; -import android.app.ActivityThread; -import java.util.ArrayList; -import java.util.List; - -/** - * This class provides the public APIs to control the Bluetooth Broadcast - * profile. - * - *

BluetoothBroadcast is a proxy object for controlling the Bluetooth - * Broadcast Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} - * to get the BluetoothBroadcast proxy object. - * - * @hide - */ - -public final class BluetoothBroadcast implements BluetoothProfile{ - private static final String TAG = "BluetoothBroadcast"; - private static final boolean DBG = true; - private static final boolean VDBG = false; - - /** - * Intent used to broadcast the change in broadcast state. - * - *

This intent will have 3 extras: - *

    - *
  • {@link #EXTRA_STATE} - The current state of the profile.
  • - *
  • {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.
  • - *
- * - *

{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of - * {@link #STATE_Disabled}, {@link #Enabling}, - * {@link #STATE_ENABLED}, {@link #STATE_DISABLING}. - * - *

Requires {@link android.Manifest.permission#BLUETOOTH} permission to - * receive. - * @hide - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_BROADCAST_STATE_CHANGED = - "android.bluetooth.broadcast.profile.action.BROADCAST_STATE_CHANGED"; - - /** - * Intent used to broadcast the change in broadcast audio state. - * - *

This intent will have 3 extras: - *

    - *
  • {@link #EXTRA_STATE} - The current audio state .
  • - *
  • {@link #EXTRA_PREVIOUS_STATE}- The previous audio state.
  • - *
- * - *

{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of - * {@link #STATE_PLAYING}, {@link #STATE_NOT_PLAYING}, - * - *

Requires {@link android.Manifest.permission#BLUETOOTH} permission to - * receive. - * @hide - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_BROADCAST_AUDIO_STATE_CHANGED = - "android.bluetooth.broadcast.profile.action.BROADCAST_AUDIO_STATE_CHANGED"; - - /** - * Intent used to broadcast encryption key generation status. - * - *

This intent will have 2 extras: - *

    - *
  • {@link #EXTRA_STATE} - The current audio state .
  • - *
- * - *

{@link #EXTRA_STATE} can be any of - * {@link #TRUE}, {@link #FALSE}, - * - *

Requires {@link android.Manifest.permission#BLUETOOTH} permission to - * receive. - * @hide - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_BROADCAST_ENCRYPTION_KEY_GENERATED = - "android.bluetooth.broadcast.profile.action.BROADCAST_ENCRYPTION_KEY_GENERATED"; - - public static final int STATE_DISABLED = 10; - public static final int STATE_ENABLING = 11; - public static final int STATE_ENABLED = 12; - public static final int STATE_DISABLING = 13; - public static final int STATE_STREAMING = 14; - public static final int STATE_PLAYING = 10; - public static final int STATE_NOT_PLAYING = 11; - - private BluetoothAdapter mAdapter; - private final BluetoothProfileConnector mProfileConnector = - new BluetoothProfileConnector(this, BluetoothProfile.BROADCAST, "BluetoothBroadcast", - IBluetoothBroadcast.class.getName()) { - @Override - public IBluetoothBroadcast getServiceInterface(IBinder service) { - return IBluetoothBroadcast.Stub.asInterface(Binder.allowBlocking(service)); - } - }; - /** - * Create a BluetoothBroadcast proxy object for interacting with the local - * Bluetooth Broadcast service. - * @hide - */ - /*package*/ BluetoothBroadcast(Context context, ServiceListener listener) { - mAdapter = BluetoothAdapter.getDefaultAdapter(); - mProfileConnector.connect(context, listener); - } - - /* - * @hide - */ - //@UnsupportedAppUsage - /*package*/ void close() { - mProfileConnector.disconnect(); - } - - /* - * @hide - */ - private IBluetoothBroadcast getService() { - return mProfileConnector.getService(); - } - - @Override - public void finalize() { - // The empty finalize needs to be kept or the - // cts signature tests would fail. - } - /* - * @hide - */ - //@UnsupportedAppUsage - public boolean SetBroadcastMode(boolean enable) { - if (DBG) log("EnableBroadcast"); - String packageName = ActivityThread.currentPackageName(); - try { - final IBluetoothBroadcast service = getService(); - if (service != null && isEnabled()) { - return service.SetBroadcast(enable, packageName); - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; - } - } - /** - * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)} - * with {@link BluetoothProfile#GATT} as argument - * - * @throws UnsupportedOperationException - */ - @Override - public int getConnectionState(BluetoothDevice device) { - throw new UnsupportedOperationException( - "Use BluetoothManager#getConnectedDevices instead."); - } - /** - * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)} - * with {@link BluetoothProfile#GATT} as argument - * - * @throws UnsupportedOperationException - */ - @Override - public List getDevicesMatchingConnectionStates(int[] states) { - throw new UnsupportedOperationException( - "Use BluetoothManager#getConnectedDevices instead."); - } - /** - * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)} - * with {@link BluetoothProfile#GATT} as argument - * - * @throws UnsupportedOperationException - */ - @Override - public List getConnectedDevices() { - throw new UnsupportedOperationException( - "Use BluetoothManager#getConnectedDevices instead."); - } - - /* - * @hide - */ - public boolean SetEncryption(boolean enable, int enc_len/*4bytes,16bytes*/, boolean use_existing) { - if (DBG) log("SetEncryption"); - String packageName = ActivityThread.currentPackageName(); - try { - final IBluetoothBroadcast service = getService(); - if (service != null && isEnabled()) { - return service.SetEncryption(enable, enc_len, use_existing, packageName); - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; - } - } - /* - * @hide - */ - public byte[] GetEncryptionKey() { - if (DBG) log("GetBroadcastEncryptionKey"); - String packageName = ActivityThread.currentPackageName(); - try { - final IBluetoothBroadcast service = getService(); - if (service != null && isEnabled()) { - return service.GetEncryptionKey(packageName); - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return null; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return null; - } - } - /* - * @hide - */ - public int GetBroadcastStatus() { - if (DBG) log("GetBroadcastStatus"); - String packageName = ActivityThread.currentPackageName(); - try { - final IBluetoothBroadcast service = getService(); - if (service != null && isEnabled()) { - return service.GetBroadcastStatus(packageName); - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return STATE_DISABLED; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return STATE_DISABLED; - } - } - //@UnsupportedAppUsage -// public @Nullable BluetoothCodecStatus getCodecStatus(BluetoothDevice device) {return null;} - - private boolean isEnabled() { - if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; - return false; - } - - private static void log(String msg) { - Log.d(TAG, msg); - } -} - - diff --git a/le_audio/frameworks/base/core/java/android/bluetooth/BluetoothSyncHelper.java b/le_audio/frameworks/base/core/java/android/bluetooth/BluetoothSyncHelper.java deleted file mode 100644 index 7072891d9745fc6bef8647b5ef97d85b67f7b5d5..0000000000000000000000000000000000000000 --- a/le_audio/frameworks/base/core/java/android/bluetooth/BluetoothSyncHelper.java +++ /dev/null @@ -1,736 +0,0 @@ -/* - * Copyright (c) 2020 The Linux Foundation. All rights reserved. - - * Copyright (C) 2017 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 android.Manifest; -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.RequiresPermission; -import android.annotation.SdkConstant; -import android.annotation.SystemApi; -import android.annotation.SdkConstant.SdkConstantType; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BleBroadcastSourceInfo; -import android.bluetooth.IBluetoothGatt; -import android.bluetooth.IBluetoothManager; -import android.bluetooth.IBleBroadcastAudioScanAssistCallback; -import android.bluetooth.IBluetoothSyncHelper; -import android.bluetooth.BluetoothAdapter.LeScanCallback; -import android.os.Binder; -import android.os.IBinder; -import android.os.Handler; -import android.os.Looper; -import android.os.RemoteException; -import android.util.Log; -import android.content.Context; - -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.ArrayList; -import java.util.List; -import java.util.HashMap; - -import android.bluetooth.le.ScanResult; -import android.bluetooth.le.ScanSettings; -import android.bluetooth.le.ScanFilter; -import android.bluetooth.le.ScanCallback; -import android.bluetooth.le.ScanRecord; -import android.bluetooth.le.PeriodicAdvertisingCallback; -import android.bluetooth.le.PeriodicAdvertisingManager; -import android.bluetooth.le.PeriodicAdvertisingReport; -import android.bluetooth.le.BluetoothLeScanner; -import android.os.SystemProperties; -import java.util.IdentityHashMap; - -/** - * This class provides methods to perform Broadcast Scan Assistance client Profile related - * operations. - * It uses Bluetooth GATT APIs to achieve Braodcast Scan assistance client operations. Application should ensure - * BASS profile is connected with the given remote device before performing the operations using - * {@link BleBroadcastAudioScanAssistManager} interface operations - * - *

BluetoothSyncHelper is a proxy object for controlling the Bluetooth Scan Offloader (BASS client) - * Service via IPC. - * - *

Use {@link BluetoothAdapter#getProfileProxy} to get - * the BluetoothScanOfflaoder proxy object. Use - * {@link BluetoothAdapter#closeProfileProxy} to close the service connection. - * - *

Use {@link BluetoothAdapter#getProfileProxy} to get - * the BluetoothSyncHelper proxy object. Use - * {@link BluetoothAdapter#closeProfileProxy} to close the service connection. - * - * Note: Most of the methods here require - * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. - * - * @hide - */ -public final class BluetoothSyncHelper implements BluetoothProfile { - - private static final String TAG = "BluetoothSyncHelper"; - private static final boolean DBG = true; - - private BluetoothAdapter mBluetoothAdapter; - /* maps callback, to callback wrapper and sync handle */ - private Map mAppCallbackWrappers; - - private Map sBleAssistManagers = null; - private Context mContext = null; - - /** - * Intent used to broadcast the change in connection state of the Bass client - * profile. - * - *

This intent will have 3 extras: - *

    - *
  • {@link #EXTRA_STATE} - The current state of the profile.
  • - *
  • {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.
  • - *
  • {@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
  • - *
- * - *

{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of - * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, - * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}. - * - *

Requires {@link android.Manifest.permission#BLUETOOTH} permission to - * receive. - */ - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String ACTION_CONNECTION_STATE_CHANGED = - "android.bluetooth.bc.profile.action.CONNECTION_STATE_CHANGED"; - - - private final BluetoothProfileConnector mProfileConnector = - new BluetoothProfileConnector(this, BluetoothProfile.BC_PROFILE, - "BluetoothSyncHelper", IBluetoothSyncHelper.class.getName()) { - @Override - public IBluetoothSyncHelper getServiceInterface(IBinder service) { - return IBluetoothSyncHelper.Stub.asInterface(Binder.allowBlocking(service)); - } - }; - - /*package*/ void close() { - mProfileConnector.disconnect(); - mAppCallbackWrappers.clear(); - } - - /*package*/ IBluetoothSyncHelper getService() { - return mProfileConnector.getService(); - } - - static boolean isSupported() { - boolean isSupported = SystemProperties.getBoolean("persist.vendor.service.bt.bc", true); - log("BluetoothSyncHelper: isSupported returns " + isSupported); - return isSupported; - } - /** - * Create a BluetoothHeadset proxy object. - */ - /*package*/ BluetoothSyncHelper(Context context, ServiceListener listener) { - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - mProfileConnector.connect(context, listener); - BluetoothManager bluetoothManager = context.getSystemService( - BluetoothManager.class); - mAppCallbackWrappers = new IdentityHashMap(); - sBleAssistManagers = new IdentityHashMap(); - mContext = context; - } - - /** - * Interface to get Broadcast Audio Scan assistance for LE Audio usecases.This is instantiated per BluetoothDevice - * which is Scan delegator - * Application will get an Instance of the {@link BleBroadcastAudioScanAssistManager} for the given - * scan delegator device - * - * @param BluetoothDevice Scan Delegator device for which BLE Broadcast SCAN Assistance operations will - * be performed - * @param {@link #BleBroadcastAudioScanAssistCallback} where callbacks related to BLE Broadcast Scan - * assistance will be deliverd - * @hide - */ - public BleBroadcastAudioScanAssistManager getBleBroadcastAudioScanAssistManager( - BluetoothDevice device, - BleBroadcastAudioScanAssistCallback callback) { - if (isSupported() == false) { - Log.e(TAG, "Broadcast scan assistance not supported"); - return null; - } - - BleBroadcastAudioScanAssistManager assistMgr = null; - if (sBleAssistManagers != null) { - assistMgr = sBleAssistManagers.get(device); - } - if (assistMgr == null) { - assistMgr = new BleBroadcastAudioScanAssistManager(this, device, - callback); - } else { - //object already exists, just registers the callback and retrun the same object - log("calling registerAppCb only"); - } - registerAppCallback(device, callback); - return assistMgr; - } - - - /** - * Initiate connection to a BASS server profile of the remote bluetooth device. - * - *

This API returns false in scenarios like the profile on the - * device is already connected or Bluetooth is not turned on. - * When this API returns true, it is guaranteed that - * connection state intent for the profile will be broadcasted with - * the state. Users can get the connection state of the profile - * from this intent. - * - *

Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} - * permission. - * - * @param device Remote Bluetooth Device - * @return false on immediate error, true otherwise - * @hide - */ - public boolean connect(BluetoothDevice device) { - log("connect(" + device + ")"); - final IBluetoothSyncHelper service = getService(); - try { - if (service != null && isEnabled() && isValidDevice(device)) { - return service.connect(device); - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; - } - } - - /** - * Initiate disconnection from a profile - * - *

This API will return false in scenarios like the profile on the - * Bluetooth device is not in connected state etc. When this API returns, - * true, it is guaranteed that the connection state change - * intent will be broadcasted with the state. Users can get the - * disconnection state of the profile from this intent. - * - *

If the disconnection is initiated by a remote device, the state - * will transition from {@link #STATE_CONNECTED} to - * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the - * host (local) device the state will transition from - * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to - * state {@link #STATE_DISCONNECTED}. The transition to - * {@link #STATE_DISCONNECTING} can be used to distinguish between the - * two scenarios. - * - *

Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} - * permission. - * - * @param device Remote Bluetooth Device - * @return false on immediate error, true otherwise - * @hide - */ - public boolean disconnect(BluetoothDevice device) { - if (DBG) log("disconnect(" + device + ")"); - final IBluetoothSyncHelper service = getService(); - try { - if (service != null && isEnabled() && isValidDevice(device)) { - return service.disconnect(device); - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; - } - } - - /** - * {@inheritDoc} - */ - @Override - public @NonNull List getConnectedDevices() { - log("getConnectedDevices()"); - final IBluetoothSyncHelper service = getService(); - try { - if (service != null && isEnabled()) { - return service.getConnectedDevices(); - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public @NonNull List getDevicesMatchingConnectionStates( - @NonNull int[] states) { - log("getDevicesMatchingStates()"); - final IBluetoothSyncHelper service = getService(); - try { - if (service != null && isEnabled()) { - return service.getDevicesMatchingConnectionStates(states); - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return new ArrayList(); - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return new ArrayList(); - } - } - - /** - * {@inheritDoc} - */ - @Override - public @BluetoothProfile.BtProfileState int getConnectionState( - @NonNull BluetoothDevice device) { - log("getState(" + device + ")"); - final IBluetoothSyncHelper service = getService(); - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - return service.getConnectionState(device); - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.STATE_DISCONNECTED; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.STATE_DISCONNECTED; - } - } - /** - * 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 - */ - //@SystemApi - @RequiresPermission(Manifest.permission.BLUETOOTH) - public int getConnectionPolicy(@NonNull BluetoothDevice device) { - log("getConnectionPolicy(" + device + ")"); - final IBluetoothSyncHelper service = getService(); - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - return service.getConnectionPolicy(device); - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; - } - } - - /** - * 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} - * - * @param device Paired bluetooth device - * @param connectionPolicy is the connection policy to set to for this profile - * @return true if connectionPolicy is set, false on error - * @hide - */ - //@SystemApi - @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) - public boolean setConnectionPolicy(@NonNull BluetoothDevice device, - int connectionPolicy) { - if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")"); - final IBluetoothSyncHelper service = getService(); - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - return false; - } - return service.setConnectionPolicy(device, connectionPolicy); - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; - } - } - - private IBleBroadcastAudioScanAssistCallback wrap(BleBroadcastAudioScanAssistCallback callback, - Handler handler) { - return new IBleBroadcastAudioScanAssistCallback.Stub() { - public void onBleBroadcastSourceFound(ScanResult scanres) { - handler.post(new Runnable() { - @Override - public void run() { - log("calling onBleBroadcastSourceFound for " + - "scanres:" + scanres); - callback.onBleBroadcastSourceFound( - scanres); - } - }); - } - - public void onBleBroadcastAudioSourceSelected(BluetoothDevice device, int status, - List broadcastSourceChannels) { - handler.post(new Runnable() { - @Override - public void run() { - log("calling onBleBroadcastSourceSelected for " + - "status:" + status); - callback.onBleBroadcastSourceSelected(device, - status, broadcastSourceChannels); - } - }); - } - public void onBleBroadcastAudioSourceAdded(BluetoothDevice rcvr, - byte srcId, - int status) { - handler.post(new Runnable() { - @Override - public void run() { - log("calling onBleBroadcastAudioSourceAdded for " + rcvr + - "srcId:" + srcId + "status:" + status); - callback.onBleBroadcastAudioSourceAdded(rcvr, srcId, - status); - } - }); - } - public void onBleBroadcastAudioSourceUpdated(BluetoothDevice rcvr, - byte srcId, - int status) { - handler.post(new Runnable() { - @Override - public void run() { - log("calling onBleBroadcastAudioSourceUpdated for " + rcvr + - "srcId:" + srcId + "status:" + status); - callback.onBleBroadcastAudioSourceUpdated(rcvr, srcId, - status); - } - }); - } - public void onBleBroadcastPinUpdated(BluetoothDevice rcvr, - byte srcId, - int status) { - handler.post(new Runnable() { - @Override - public void run() { - log("calling onBleBroadcastPinUpdated for " + rcvr + - "srcId:" + srcId + "status:" + status); - callback.onBleBroadcastPinUpdated(rcvr, srcId, - status); - // App can still unregister the sync until notified it's lost. - // Remove callback after app was notifed. - //mCallbackWrappers.remove(callback); - } - }); - } - - public void onBleBroadcastAudioSourceRemoved(BluetoothDevice rcvr, - byte srcId, - int status) { - handler.post(new Runnable() { - @Override - public void run() { - log("calling onBleBroadcastAudioSourceRemoved for " + rcvr + - "srcId:" + srcId + "status:" + status); - callback.onBleBroadcastAudioSourceRemoved(rcvr, srcId, - status); - - } - }); - } - }; - } - - - boolean startScanOffload (BluetoothDevice device, boolean isGroupOp) { - log("startScanOffload(" + device + ", isGroupOp: " + isGroupOp + ")"); - final IBluetoothSyncHelper service = getService(); - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - return service.startScanOffload(device, isGroupOp); - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; - } - } - - boolean stopScanOffload (BluetoothDevice device, boolean isGroupOp) { - log("stopScanOffload(" + device + ", isGroupOp: " + isGroupOp + ")" ); - final IBluetoothSyncHelper service = getService(); - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - return service.stopScanOffload(device, isGroupOp); - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; - } - } - - boolean searchforLeAudioBroadcasters (BluetoothDevice device) { - log("searchforLeAudioBroadcasters(" + device + ")"); - final IBluetoothSyncHelper service = getService(); - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - return service.searchforLeAudioBroadcasters(device); - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; - } - } - - @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) - boolean stopSearchforLeAudioBroadcasters(BluetoothDevice device) { - log("stopSearchforLeAudioBroadcasters(" + device + ")"); - final IBluetoothSyncHelper service = getService(); - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - return service.stopSearchforLeAudioBroadcasters(device); - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; - } - } - - boolean selectBroadcastSource (BluetoothDevice device, ScanResult scanRes, boolean isGroupOp) { - log("selectBroadcastSource(" + device + ": groupop" + isGroupOp +")"); - final IBluetoothSyncHelper service = getService(); - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - return service.selectBroadcastSource(device, scanRes, isGroupOp); - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return false; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return false; - } - } - - void registerAppCallback(BluetoothDevice device, BleBroadcastAudioScanAssistCallback appCallback) { - log("registerAppCallback device :" + device + "appCB: " + appCallback); - Handler handler = new Handler(Looper.getMainLooper()); - - IBleBroadcastAudioScanAssistCallback wrapped = wrap(appCallback, handler); - final IBluetoothSyncHelper service = getService(); - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - service.registerAppCallback(device, wrapped); - if (mAppCallbackWrappers != null) { - mAppCallbackWrappers.put(appCallback, wrapped); - } - } - if (service == null) { - Log.w(TAG, "Proxy not attached to service"); - return; - } - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return; - } - } - - void unregisterAppCallback(BluetoothDevice device, BleBroadcastAudioScanAssistCallback appCallback) { - log("unregisterAppCallback: device" + device + "appCB:" + appCallback); - // Remove callback after app was notifed. - - final IBluetoothSyncHelper service = getService(); - IBleBroadcastAudioScanAssistCallback cb = mAppCallbackWrappers.get(device); - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - service.unregisterAppCallback(device, cb); - mAppCallbackWrappers.remove(appCallback); - return; - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return; - } - } - - - boolean addBroadcastSource (BluetoothDevice sinkDevice, - BleBroadcastSourceInfo srcInfo, - boolean isGroupOp) { - log("addBroadcastSource for :" + sinkDevice - + "SourceInfo: " + srcInfo+ "isGroupOp: " + isGroupOp); - boolean ret = false; - final IBluetoothSyncHelper service = getService(); - try { - if (service != null && isEnabled() - && isValidDevice(sinkDevice)) { - - return service.addBroadcastSource(sinkDevice, srcInfo, isGroupOp); - } - if (service == null) - { - Log.w(TAG, "Proxy not attached to service"); - ret = false; - } - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - ret = false; - } - return ret; - } - boolean updateBroadcastSource (BluetoothDevice device, - BleBroadcastSourceInfo srcInfo, - boolean isGroupOp) { - //Same device can have more than one SourceId - log("updateBroadcastSource for :" + device + - "SourceInfo: " + srcInfo+ "isGroupOp: " + isGroupOp); - boolean ret = false; - final IBluetoothSyncHelper service = getService(); - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - return service.updateBroadcastSource(device, - srcInfo, isGroupOp); - } - if (service == null) - { - Log.w(TAG, "Proxy not attached to service"); - ret = false; - } - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - ret = false; - } - return ret; - } - - boolean setBroadcastCode (BluetoothDevice device, - BleBroadcastSourceInfo srcInfo, - boolean isGroupOp) { - //Same device can have more than one SourceId - log("setBroadcastCode for :" + device); - log("SourceInfo: " + srcInfo+ "isGroupOp: " + isGroupOp); - boolean ret = false; - final IBluetoothSyncHelper service = getService(); - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - return service.setBroadcastCode(device, - srcInfo, isGroupOp); - } - if (service == null) - { - Log.w(TAG, "Proxy not attached to service"); - ret = false; - } - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - ret = false; - } - return ret; - } - boolean removeBroadcastSource (BluetoothDevice device, - byte sourceId, - boolean isGroupOp - ) { - log("removeBroadcastSource for :" + device + - "SourceId: " + sourceId + "isGroupOp: " + isGroupOp); - final IBluetoothSyncHelper service = getService(); - boolean ret = false; - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - return service.removeBroadcastSource(device, sourceId - , isGroupOp); - } - if (service == null) - { - Log.w(TAG, "Proxy not attached to service"); - ret = false; - } - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - ret = false; - } - return ret; - } - - List getAllBroadcastSourceInformation (BluetoothDevice device) { - log("GetAllBroadcastReceiverStates for :" + device); - final IBluetoothSyncHelper service = getService(); - try { - if (service != null && isEnabled() - && isValidDevice(device)) { - return service.getAllBroadcastSourceInformation(device); - } - if (service == null) Log.w(TAG, "Proxy not attached to service"); - return null; - } catch (RemoteException e) { - Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); - return null; - } - } - private boolean isEnabled() { - if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) return true; - return false; - } - - private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; - - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; - } - - private static void log(String msg) { - BleBroadcastSourceInfo.BASS_Debug(TAG, msg); - } - -} diff --git a/le_audio/frameworks/base/packages/SettingsLib/Android.bp b/le_audio/frameworks/base/packages/SettingsLib/Android.bp deleted file mode 100644 index ac4fdad86899c22e658b7391f8b4a87c03e361d7..0000000000000000000000000000000000000000 --- a/le_audio/frameworks/base/packages/SettingsLib/Android.bp +++ /dev/null @@ -1,31 +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. - * - ******************************************************************************/ - -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"], -} - -filegroup { - name: "framework-settingslib-adva-srcs", - srcs: ["src/**/*.java"], -} diff --git a/le_audio/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/BCProfile.java b/le_audio/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/BCProfile.java deleted file mode 100644 index 677186eab178dd402217f1049c19459a622b6da8..0000000000000000000000000000000000000000 --- a/le_audio/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/BCProfile.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright (c) 2020 The Linux Foundation. All rights reserved. - - * Copyright (C) 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 - */ - -package com.android.settingslib.bluetooth; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothClass; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothSyncHelper; -import android.bluetooth.BluetoothProfile; -import android.content.Context; -import android.util.Log; -import android.os.ParcelUuid; -import android.bluetooth.BleBroadcastAudioScanAssistManager; -import android.bluetooth.BleBroadcastAudioScanAssistCallback; -import android.content.Intent; -import android.bluetooth.BleBroadcastSourceInfo; - -import com.android.settingslib.R; -import android.os.SystemProperties; -import android.os.Handler; - -import androidx.annotation.Keep; -import java.util.ArrayList; -import java.util.List; - -@Keep -public class BCProfile implements LocalBluetoothProfile { - private static final String TAG = "BCProfile"; - private static boolean V = true; - - private Context mContext; - - private BluetoothSyncHelper mService; - private boolean mIsProfileReady; - - private final CachedBluetoothDeviceManager mDeviceManager; - - static final String NAME = "BCProfile"; - private final LocalBluetoothProfileManager mProfileManager; - - // Order of this profile in device profiles list - private static final int ORDINAL = 1; - - // These callbacks run on the main thread. - private final class BassclientServiceListener - implements BluetoothProfile.ServiceListener { - - public void onServiceConnected(int profile, BluetoothProfile proxy) { - Log.d(TAG, "BassclientService connected"); - mService = (BluetoothSyncHelper) proxy; - // We just bound to the service, so refresh the UI for any connected Bassclient devices. - //List deviceList = mService.getConnectedDevices(); - mIsProfileReady=true;//BassService connected - mProfileManager.callServiceConnectedListeners(); - } - - public void onServiceDisconnected(int profile) { - Log.d(TAG, "BassclientService disconnected"); - mIsProfileReady=false; - } - } - - public boolean isProfileReady() { - return mIsProfileReady; - } - - @Override - public int getProfileId() { - return BluetoothProfile.BC_PROFILE; - } - - @Override - public boolean setEnabled(BluetoothDevice device, boolean enabled) { - boolean isEnabled = false; - if (mService == null) { - return false; - } - if (enabled) { - Log.d(TAG, "BCProfile: " + device + ":" + enabled); - if (mService.getConnectionPolicy(device) < BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - isEnabled = mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_ALLOWED); - } - } else { - isEnabled = mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_FORBIDDEN); - } - - return isEnabled; - } - - @Override - public boolean isEnabled(BluetoothDevice device) { - if (mService == null) { - return false; - } - return mService.getConnectionPolicy(device) > BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; - - } - - @Override - public int getConnectionPolicy(BluetoothDevice device) { - return BluetoothProfile.CONNECTION_POLICY_ALLOWED; - } - - BCProfile(Context context, CachedBluetoothDeviceManager deviceManager, - LocalBluetoothProfileManager profileManager) { - mContext = context; - mDeviceManager = deviceManager; - mProfileManager = profileManager; - BluetoothAdapter.getDefaultAdapter().getProfileProxy(context, - new BassclientServiceListener(), BluetoothProfile.BC_PROFILE); - } - - public boolean accessProfileEnabled() { - //return true for BASS always so that - //It shows the profile preference in device details - return true; - } - - public boolean isAutoConnectable() { - if (mService == null) return false; - Log.d(TAG, "isAutoConnectable return false"); - return false; - } - - /** - * Get Scan delegator devices matching connection states{ - * @code BluetoothProfile.STATE_CONNECTED, - * @code BluetoothProfile.STATE_CONNECTING, - * @code BluetoothProfile.STATE_DISCONNECTING} - * - * @return Matching device list - */ - public List getConnectedDevices() { - return getDevicesByStates(new int[] { - BluetoothProfile.STATE_CONNECTED, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTING}); - } - - /** - * Get Scan delegator devices matching connection states{ - * @code BluetoothProfile.STATE_DISCONNECTED, - * @code BluetoothProfile.STATE_CONNECTED, - * @code BluetoothProfile.STATE_CONNECTING, - * @code BluetoothProfile.STATE_DISCONNECTING} - * - * @return Matching device list - */ - public List getConnectableDevices() { - return getDevicesByStates(new int[] { - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.STATE_CONNECTED, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTING}); - } - - private List getDevicesByStates(int[] states) { - if (mService == null) { - return new ArrayList(0); - } - return mService.getDevicesMatchingConnectionStates(states); - } - - public boolean connect(BluetoothDevice device) { - Log.d(TAG, "BCProfile Connect to device: " + device); - if (mService == null) return false; - return mService.connect(device); - } - - public boolean disconnect(BluetoothDevice device) { - Log.d(TAG, "BCProfile disonnect to device: " + device); - if (mService == null) return false; - // Downgrade priority as user is disconnecting the Bassclient. - if (mService.getConnectionPolicy(device) > BluetoothProfile.PRIORITY_ON){ - mService.setConnectionPolicy(device, BluetoothProfile.PRIORITY_ON); - } - return mService.disconnect(device); - } - - public int getConnectionStatus(BluetoothDevice device) { - if (mService == null) { - return BluetoothProfile.STATE_DISCONNECTED; - } - return mService.getConnectionState(device); - } - - public int getPreferred(BluetoothDevice device) { - if (mService == null) return BluetoothProfile.CONNECTION_POLICY_UNKNOWN; - return mService.getConnectionPolicy(device); - } - - public void setPreferred(BluetoothDevice device, boolean preferred) { - if (mService == null) return; - if (preferred) { - if (mService.getConnectionPolicy(device) != - BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - mService.setConnectionPolicy(device, - BluetoothProfile.CONNECTION_POLICY_ALLOWED); - } - } else { - mService.setConnectionPolicy(device, BluetoothProfile.CONNECTION_POLICY_UNKNOWN); - } - } - - public String toString() { - return NAME; - } - - public int getOrdinal() { - return ORDINAL; - } - - public int getNameResource(BluetoothDevice device) { - return R.string.bluetooth_profile_bc; - } - - public BleBroadcastAudioScanAssistManager getBSAManager(BluetoothDevice device, - BleBroadcastAudioScanAssistCallback callback) { - if (mService == null) { - Log.d(TAG, "getBroadcastAudioScanAssistManager: service is null"); - return null; - } - return mService.getBleBroadcastAudioScanAssistManager(device, callback); - } - - public int getSummaryResourceForDevice(BluetoothDevice device) { - int state = getConnectionStatus(device); - switch (state) { - case BluetoothProfile.STATE_DISCONNECTED: - return R.string.bluetooth_bc_profile_summary_use_for; - - case BluetoothProfile.STATE_CONNECTED: - return R.string.bluetooth_bc_profile_summary_connected; - - default: - return BluetoothUtils.getConnectionStateSummary(state); - } - } - - public int getDrawableResource(BluetoothClass btClass) { - return com.android.internal.R.drawable.ic_bt_hearing_aid; - } - - protected void finalize() { - Log.d(TAG, "finalize()"); - if (mService != null) { - try { - BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.BC_PROFILE, - mService); - mService = null; - }catch (Throwable t) { - Log.w(TAG, "Error cleaning up BAss client proxy", t); - } - } - } - - static boolean isBCSupported() { - boolean isBCSupported = SystemProperties.getBoolean("persist.vendor.service.bt.bc", true); - Log.d(TAG, "BassClientProfile: isBCSupported returns " + isBCSupported); - return isBCSupported; - } - - static public boolean isBASeeker(BluetoothDevice device) { - //always send true - boolean isSeeker = SystemProperties.getBoolean("persist.vendor.service.bt.baseeker", false); - ParcelUuid[] uuids = null; - if (device != null) { - uuids = device.getUuids(); - } - ParcelUuid sd = ParcelUuid.fromString("0000184F-0000-1000-8000-00805F9B34FB"); - if (isBCSupported()) { - if (uuids != null) { - for (ParcelUuid uid : uuids) { - if (uid.equals(sd)) { - Log.d(TAG, "SD uuid present"); - isSeeker = true; - } - } - } - } - Log.d(TAG,"isBASeeker returns:" + isSeeker); - return isSeeker; - } - -} diff --git a/le_audio/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/BroadcastProfile.java b/le_audio/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/BroadcastProfile.java deleted file mode 100644 index d1d9c013cf7b64267d6ead46a6db8a9b137f5adc..0000000000000000000000000000000000000000 --- a/le_audio/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/BroadcastProfile.java +++ /dev/null @@ -1,180 +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. - * - ******************************************************************************/ - - -package com.android.settingslib.bluetooth; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothClass; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothBroadcast; -import android.bluetooth.BluetoothProfile; -import android.content.Context; -import android.util.Log; -import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; -import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED; -import com.android.settingslib.R; -import androidx.annotation.Keep; - -/** - * BroadcastProfile handles Bluetooth Broadcast profile. - */ -@Keep -public final class BroadcastProfile implements LocalBluetoothProfile { - private static final String TAG = "BroadcastProfile"; - private static boolean V = true; - - private BluetoothBroadcast mService; - private boolean mIsProfileReady = false; - - static final String NAME = "Broadcast"; - - // Order of this profile in device profiles list - private static final int ORDINAL = 0; - - // These callbacks run on the main thread. - private final class BroadcastListener - implements BluetoothProfile.ServiceListener { - - public void onServiceConnected(int profile, BluetoothProfile proxy) { - if (profile == BluetoothProfile.BROADCAST) { - if (V) Log.d(TAG,"Bluetooth Broadcast service connected"); - mService = (BluetoothBroadcast) proxy; - mIsProfileReady = true; - } - } - - public void onServiceDisconnected(int profile) { - if (profile == BluetoothProfile.BROADCAST) { - if (V) Log.d(TAG,"Bluetooth Broadcast service disconnected"); - mIsProfileReady = false; - } - } - } - - public boolean isProfileReady() { - Log.d(TAG,"isProfileReady = " + mIsProfileReady); - return mIsProfileReady; - } - - @Override - public int getProfileId() { - Log.d(TAG,"getProfileId"); - return BluetoothProfile.BROADCAST; - } - - BroadcastProfile(Context context) { - Log.d(TAG,"BroadcastProfile constructor"); - BluetoothAdapter.getDefaultAdapter().getProfileProxy(context, - new BroadcastListener(), BluetoothProfile.BROADCAST); - } - - public boolean accessProfileEnabled() { - Log.d(TAG,"accessProfileEnabled"); - return false; - } - - public boolean isAutoConnectable() { - return false; - } - - public boolean connect(BluetoothDevice device) { - return false; - } - - public boolean disconnect(BluetoothDevice device) { - return false; - } - - public int getConnectionStatus(BluetoothDevice device) { - return BluetoothProfile.STATE_DISCONNECTED; - } - - public boolean isEnabled(BluetoothDevice device) { - return false; - } - - public int getConnectionPolicy(BluetoothDevice device) { - return CONNECTION_POLICY_FORBIDDEN; - } - - public boolean setEnabled(BluetoothDevice device, boolean enabled) { - return false;//CONNECTION_POLICY_ALLOWED; - } - - public void setPreferred(BluetoothDevice device, boolean preferred) { - } - public int getPreferred(BluetoothDevice device) { - return BluetoothProfile.PRIORITY_OFF; - } - public boolean isPreferred(BluetoothDevice device) { - return false; - } - public String toString() { - return NAME; - } - - public int getOrdinal() { - return ORDINAL; - } - - public int getNameResource(BluetoothDevice device) { - return R.string.bluetooth_profile_broadcast; - } - - public int getSummaryResourceForDevice(BluetoothDevice device) { - return 0; - } - - public int getDrawableResource(BluetoothClass btClass) { - return 0; - } - - public boolean setEncryption(boolean enable, int enc_len, boolean use_existing) { - Log.d(TAG,"setEncryption"); - return mService.SetEncryption(enable, enc_len, use_existing); - } - - public byte[] getEncryptionKey() { - Log.d(TAG,"getEncryptionKey"); - return mService.GetEncryptionKey(); - } - - public int getBroadcastStatus() { - Log.d(TAG,"getBroadcastStatus"); - return mService.GetBroadcastStatus(); - } - - public boolean setBroadcastMode(boolean enable) { - Log.d(TAG,"setBroadcastMode"); - return mService.SetBroadcastMode(enable); - } - - protected void finalize() { - if (V) Log.d(TAG, "finalize()"); - if (mService != null) { - try { - BluetoothAdapter.getDefaultAdapter().closeProfileProxy - (BluetoothProfile.BROADCAST, mService); - mService = null; - } catch (Throwable t) { - Log.w(TAG, "Error cleaning up Broadcast proxy", t); - } - } - } -} diff --git a/le_audio/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/BroadcastSourceInfoHandler.java b/le_audio/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/BroadcastSourceInfoHandler.java deleted file mode 100644 index 054623e9235c72a28831bde9941eab44601386d3..0000000000000000000000000000000000000000 --- a/le_audio/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/BroadcastSourceInfoHandler.java +++ /dev/null @@ -1,79 +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. - * - ******************************************************************************/ - - -package com.android.settingslib.bluetooth; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.content.Context; -import android.util.Log; -import android.bluetooth.BleBroadcastAudioScanAssistManager; -import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager; -import android.content.Intent; -import android.bluetooth.BleBroadcastSourceInfo; -import android.os.Handler; - -public class BroadcastSourceInfoHandler implements BluetoothEventManager.Handler { - private static final String TAG = "BroadcastSourceInfoHandler"; - private static final boolean V = Log.isLoggable(TAG, Log.VERBOSE); - private final CachedBluetoothDeviceManager mDeviceManager; - BroadcastSourceInfoHandler(CachedBluetoothDeviceManager deviceManager - ) { - mDeviceManager = deviceManager; - } - @Override - public void onReceive(Context context, Intent intent, BluetoothDevice device) { - if (device == null) { - Log.w(TAG, "BroadcastSourceInfoHandler: device is null"); - return; - } - - final String action = intent.getAction(); - if (action == null) { - Log.w(TAG, "BroadcastSourceInfoHandler: action is null"); - return; - } - BleBroadcastSourceInfo sourceInfo = intent.getParcelableExtra( - BleBroadcastSourceInfo.EXTRA_SOURCE_INFO); - - int sourceInfoIdx = intent.getIntExtra( - BleBroadcastSourceInfo.EXTRA_SOURCE_INFO_INDEX, - BluetoothAdapter.ERROR); - - int maxNumOfsrcInfo = intent.getIntExtra( - BleBroadcastSourceInfo.EXTRA_MAX_NUM_SOURCE_INFOS, - BluetoothAdapter.ERROR); - if (V) { - Log.d(TAG, "Rcved :BCAST_RECEIVER_STATE Intent for : " + device); - Log.d(TAG, "Rcvd BroadcastSourceInfo index=" + sourceInfoIdx); - Log.d(TAG, "Rcvd max num of source Info=" + maxNumOfsrcInfo); - Log.d(TAG, "Rcvd BroadcastSourceInfo=" + sourceInfo); - } - CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device); - VendorCachedBluetoothDevice vDevice = - VendorCachedBluetoothDevice.getVendorCachedBluetoothDevice(cachedDevice, null); - if (vDevice != null) { - vDevice.onBroadcastReceiverStateChanged(sourceInfo, - sourceInfoIdx, maxNumOfsrcInfo); - cachedDevice.dispatchAttributesChanged(); - } else { - Log.e(TAG, "No vCachedDevice created for this Device"); - } - } -}; diff --git a/le_audio/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/VendorCachedBluetoothDevice.java b/le_audio/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/VendorCachedBluetoothDevice.java deleted file mode 100644 index f1d0afd9b9e5ef8d15035a301e96bf0ca5e91aae..0000000000000000000000000000000000000000 --- a/le_audio/frameworks/base/packages/SettingsLib/src/com/android/settingslib/bluetooth/VendorCachedBluetoothDevice.java +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (C) 2008 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.settingslib.bluetooth; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothClass; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothHearingAid; -import android.bluetooth.BleBroadcastSourceInfo; -import android.bluetooth.BleBroadcastSourceChannel; -import android.bluetooth.BluetoothProfile; -import android.bluetooth.BleBroadcastAudioScanAssistManager; -import android.bluetooth.BleBroadcastAudioScanAssistCallback; -import android.bluetooth.le.ScanResult; -import android.bluetooth.BluetoothUuid; -import android.os.ParcelUuid; -import android.content.Context; -import android.content.SharedPreferences; -import java.util.IdentityHashMap; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.ParcelUuid; -import android.os.SystemClock; -import java.util.HashMap; -import java.util.Map; -import java.util.List; -import android.text.TextUtils; -import android.util.EventLog; -import android.util.Log; -import java.lang.Integer; - -import android.os.SystemProperties; -import androidx.annotation.VisibleForTesting; - -import com.android.internal.util.ArrayUtils; -import com.android.settingslib.R; -import com.android.settingslib.Utils; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -/** - * VendorCachedBluetoothDevice represents a remote Bluetooth device. It contains - * attributes of the device (such as the address, name, RSSI, etc.) and - * functionality that can be performed on the device (connect, pair, disconnect, - * etc.). - */ -public class VendorCachedBluetoothDevice extends CachedBluetoothDevice { - private static final String TAG = "VendorCachedBluetoothDevice"; - private static final boolean V = Log.isLoggable(TAG, Log.VERBOSE); - private ScanResult mScanRes = null; - private BleBroadcastAudioScanAssistManager mScanAssistManager; - static private Map mBleBroadcastReceiverStates - = new HashMap(); - private LocalBluetoothProfileManager mProfileManager = null; - static private Map mVcbdEntries = new IdentityHashMap(); - - public static VendorCachedBluetoothDevice getVendorCachedBluetoothDevice( - CachedBluetoothDevice cachedDevice, - LocalBluetoothProfileManager profileManager) { - VendorCachedBluetoothDevice vCbd = null; - if (mVcbdEntries != null) { - vCbd = mVcbdEntries.get(cachedDevice); - } - //dont create new instance if profileMgr is null - if (vCbd == null && profileManager != null) { - vCbd = new VendorCachedBluetoothDevice(cachedDevice, - profileManager); - Log.d(TAG, "getVendorCachedBluetoothDevice: created new Instance"); - mVcbdEntries.put(cachedDevice, vCbd); - } - return vCbd; - } - - VendorCachedBluetoothDevice(CachedBluetoothDevice cachedDevice,LocalBluetoothProfileManager profileManager) { - super(cachedDevice); - mProfileManager = profileManager; - mBleBroadcastReceiverStates = new HashMap(); - InitializeSAManager(); - } - - VendorCachedBluetoothDevice(Context context, LocalBluetoothProfileManager profileManager, - BluetoothDevice device) { - super(context, profileManager, device); - mProfileManager = profileManager; - mBleBroadcastReceiverStates = new HashMap(); - InitializeSAManager(); - } - - /** - * Describes the current device and profile for logging. - * - * @param profile Profile to describe - * @return Description of the device and profile - */ - private String describe(LocalBluetoothProfile profile) { - StringBuilder sb = new StringBuilder(); - sb.append("Address:").append(mDevice); - if (profile != null) { - sb.append(" Profile:").append(profile); - } - - return sb.toString(); - } - - void onProfileStateChanged(LocalBluetoothProfile profile, int newProfileState) { - if (V) { - Log.d(TAG, "onProfileStateChanged: profile " + profile + ", device=" + mDevice - + ", newProfileState " + newProfileState); - } - if (profile instanceof BCProfile - && newProfileState == BluetoothProfile.STATE_DISCONNECTED) { - cleanUpSAMananger(); - super.dispatchAttributesChanged(); - } - } - - private BleBroadcastAudioScanAssistCallback mScanAssistCallback = new BleBroadcastAudioScanAssistCallback() { - public void onBleBroadcastSourceFound(ScanResult res) { - if (V) { - Log.d(TAG, "onBleBroadcastSourceFound" + res.getDevice()); - } - setScanResult(res); - }; - - public void onBleBroadcastAudioSourceAdded(BluetoothDevice rcvr, - byte srcId, - int status) { - }; - - public void onBleBroadcastSourceSelected( int status, - List broadcastSourceIndicies) { - }; - - public void onBleBroadcastAudioSourceUpdated(BluetoothDevice rcvr, - byte srcId, - int status) { - }; - - public void onBleBroadcastPinUpdated(BluetoothDevice rcvr, - byte srcId, - int status) { - }; - public void onBleBroadcastAudioSourceRemoved(BluetoothDevice rcvr, - byte srcId, - int status) { - }; - }; - - public BleBroadcastAudioScanAssistManager getScanAssistManager() - { InitializeSAManager(); - return mScanAssistManager; - } - - void InitializeSAManager() { - BCProfile bcProfile = (BCProfile)mProfileManager.getBCProfile(); - mScanAssistManager = bcProfile.getBSAManager( - mDevice, mScanAssistCallback); - } - - void cleanUpSAMananger() { - mScanAssistManager = null; - if (mBleBroadcastReceiverStates != null) { - mBleBroadcastReceiverStates.clear(); - } - } - - void updateBroadcastreceiverStates(BleBroadcastSourceInfo srcInfo, int index, - int maxSourceInfosNum) { - BleBroadcastSourceInfo entry = mBleBroadcastReceiverStates.get(index); - if (entry != null) { - Log.d(TAG, "updateBroadcastreceiverStates: Replacing receiver State Information"); - mBleBroadcastReceiverStates.replace(index, srcInfo); - } else { - mBleBroadcastReceiverStates.put(index, srcInfo); - } - super.dispatchAttributesChanged(); - } - - public int getNumberOfBleBroadcastReceiverStates() { - int ret = 0; - if (mScanAssistManager == null) { - InitializeSAManager(); - if (mScanAssistManager == null) { - return ret; - } - } - List srcInfo = mScanAssistManager.getAllBroadcastSourceInformation(); - if (srcInfo != null) { - ret = srcInfo.size(); - } - if (V) { - Log.d(TAG, "getNumberOfBleBroadcastReceiverStates:"+ ret); - } - return ret; - } - - public Map getAllBleBroadcastreceiverStates() { - if (mScanAssistManager == null) { - InitializeSAManager(); - if (mScanAssistManager == null) { - Log.e(TAG, "SA Manager cant be initialized"); - return null; - } - } - List srcInfos = mScanAssistManager.getAllBroadcastSourceInformation(); - if (srcInfos == null) { - Log.e(TAG, "getAllBleBroadcastreceiverStates: no src Info"); - return null; - } - for (int i=0; i srcInfos = mScanAssistManager.getAllBroadcastSourceInformation(); - if (srcInfos == null) { - Log.e(TAG, "isBroadcastAudioSynced: no src Info"); - return false; - } - for (int i=0; i -#include - -using bluetooth::bap::pacs::CodecIndex; -using bluetooth::bap::pacs::CodecPriority; -using bluetooth::bap::pacs::CodecSampleRate; -using bluetooth::bap::pacs::CodecBPS; -using bluetooth::bap::pacs::CodecChannelMode; - -namespace android { -static jmethodID method_onConnectionStateChanged; -static jmethodID method_onAudioStateChanged; -static jmethodID method_onCodecConfigChanged; - -static struct { - jclass clazz; - jmethodID constructor; - jmethodID getCodecType; - jmethodID getCodecPriority; - jmethodID getSampleRate; - jmethodID getBitsPerSample; - jmethodID getChannelMode; - jmethodID getCodecSpecific1; - jmethodID getCodecSpecific2; - jmethodID getCodecSpecific3; - jmethodID getCodecSpecific4; -} android_bluetooth_BluetoothCodecConfig; - -static const btacm_initiator_interface_t* sBluetoothAcmInterface = nullptr; -static std::shared_timed_mutex interface_mutex; - -static jobject mCallbacksObj = nullptr; -static std::shared_timed_mutex callbacks_mutex; - -static void btacm_connection_state_callback(const RawAddress& bd_addr, - btacm_connection_state_t state, uint16_t contextType) { - ALOGI("%s", __func__); - - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - - ScopedLocalRef addr( - sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); - if (!addr.get()) { - ALOGE("%s: Fail to new jbyteArray bd addr", __func__); - return; - } - - sCallbackEnv->SetByteArrayRegion( - addr.get(), 0, sizeof(RawAddress), - reinterpret_cast(bd_addr.address)); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, - addr.get(), (jint)state, (jint)contextType); -} - -static void btacm_audio_state_callback(const RawAddress& bd_addr, - btacm_audio_state_t state, uint16_t contextType) { - ALOGI("%s", __func__); - - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - - ScopedLocalRef addr( - sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); - if (!addr.get()) { - ALOGE("%s: Fail to new jbyteArray bd addr", __func__); - return; - } - - sCallbackEnv->SetByteArrayRegion( - addr.get(), 0, sizeof(RawAddress), - reinterpret_cast(bd_addr.address)); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged, - addr.get(), (jint)state, (jint)contextType); -} - -static void btacm_audio_config_callback( - const RawAddress& bd_addr, CodecConfig codec_config, - std::vector codecs_local_capabilities, - std::vector codecs_selectable_capabilities, uint16_t contextType) { - ALOGI("%s", __func__); - - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - - jobject codecConfigObj = sCallbackEnv->NewObject( - android_bluetooth_BluetoothCodecConfig.clazz, - android_bluetooth_BluetoothCodecConfig.constructor, - (jint)codec_config.codec_type, (jint)codec_config.codec_priority, - (jint)codec_config.sample_rate, (jint)codec_config.bits_per_sample, - (jint)codec_config.channel_mode, (jlong)codec_config.codec_specific_1, - (jlong)codec_config.codec_specific_2, - (jlong)codec_config.codec_specific_3, - (jlong)codec_config.codec_specific_4); - - jsize i = 0; - jobjectArray local_capabilities_array = sCallbackEnv->NewObjectArray( - (jsize)codecs_local_capabilities.size(), - android_bluetooth_BluetoothCodecConfig.clazz, nullptr); - for (auto const& cap : codecs_local_capabilities) { - jobject capObj = sCallbackEnv->NewObject( - android_bluetooth_BluetoothCodecConfig.clazz, - android_bluetooth_BluetoothCodecConfig.constructor, - (jint)cap.codec_type, (jint)cap.codec_priority, (jint)cap.sample_rate, - (jint)cap.bits_per_sample, (jint)cap.channel_mode, - (jlong)cap.codec_specific_1, (jlong)cap.codec_specific_2, - (jlong)cap.codec_specific_3, (jlong)cap.codec_specific_4); - sCallbackEnv->SetObjectArrayElement(local_capabilities_array, i++, capObj); - sCallbackEnv->DeleteLocalRef(capObj); - } - - i = 0; - jobjectArray selectable_capabilities_array = sCallbackEnv->NewObjectArray( - (jsize)codecs_selectable_capabilities.size(), - android_bluetooth_BluetoothCodecConfig.clazz, nullptr); - for (auto const& cap : codecs_selectable_capabilities) { - jobject capObj = sCallbackEnv->NewObject( - android_bluetooth_BluetoothCodecConfig.clazz, - android_bluetooth_BluetoothCodecConfig.constructor, - (jint)cap.codec_type, (jint)cap.codec_priority, (jint)cap.sample_rate, - (jint)cap.bits_per_sample, (jint)cap.channel_mode, - (jlong)cap.codec_specific_1, (jlong)cap.codec_specific_2, - (jlong)cap.codec_specific_3, (jlong)cap.codec_specific_4); - sCallbackEnv->SetObjectArrayElement(selectable_capabilities_array, i++, - capObj); - sCallbackEnv->DeleteLocalRef(capObj); - } - - ScopedLocalRef addr( - sCallbackEnv.get(), sCallbackEnv->NewByteArray(RawAddress::kLength)); - if (!addr.get()) { - ALOGE("%s: Fail to new jbyteArray bd addr", __func__); - return; - } - sCallbackEnv->SetByteArrayRegion( - addr.get(), 0, RawAddress::kLength, - reinterpret_cast(bd_addr.address)); - - sCallbackEnv->CallVoidMethod( - mCallbacksObj, method_onCodecConfigChanged, addr.get(), codecConfigObj, - local_capabilities_array, selectable_capabilities_array, (jint)contextType); -} - -static btacm_initiator_callbacks_t sBluetoothAcmCallbacks = { - sizeof(sBluetoothAcmCallbacks), - btacm_connection_state_callback, - btacm_audio_state_callback, - btacm_audio_config_callback -}; - -static void classInitNative(JNIEnv* env, jclass clazz) { - jclass jniBluetoothCodecConfigClass = - env->FindClass("android/bluetooth/BluetoothCodecConfig"); - android_bluetooth_BluetoothCodecConfig.constructor = - env->GetMethodID(jniBluetoothCodecConfigClass, "", "(IIIIIJJJJ)V"); - android_bluetooth_BluetoothCodecConfig.getCodecType = - env->GetMethodID(jniBluetoothCodecConfigClass, "getCodecType", "()I"); - android_bluetooth_BluetoothCodecConfig.getCodecPriority = - env->GetMethodID(jniBluetoothCodecConfigClass, "getCodecPriority", "()I"); - android_bluetooth_BluetoothCodecConfig.getSampleRate = - env->GetMethodID(jniBluetoothCodecConfigClass, "getSampleRate", "()I"); - android_bluetooth_BluetoothCodecConfig.getBitsPerSample = - env->GetMethodID(jniBluetoothCodecConfigClass, "getBitsPerSample", "()I"); - android_bluetooth_BluetoothCodecConfig.getChannelMode = - env->GetMethodID(jniBluetoothCodecConfigClass, "getChannelMode", "()I"); - android_bluetooth_BluetoothCodecConfig.getCodecSpecific1 = env->GetMethodID( - jniBluetoothCodecConfigClass, "getCodecSpecific1", "()J"); - android_bluetooth_BluetoothCodecConfig.getCodecSpecific2 = env->GetMethodID( - jniBluetoothCodecConfigClass, "getCodecSpecific2", "()J"); - android_bluetooth_BluetoothCodecConfig.getCodecSpecific3 = env->GetMethodID( - jniBluetoothCodecConfigClass, "getCodecSpecific3", "()J"); - android_bluetooth_BluetoothCodecConfig.getCodecSpecific4 = env->GetMethodID( - jniBluetoothCodecConfigClass, "getCodecSpecific4", "()J"); - - method_onConnectionStateChanged = - env->GetMethodID(clazz, "onConnectionStateChanged", "([BII)V"); - - method_onAudioStateChanged = - env->GetMethodID(clazz, "onAudioStateChanged", "([BII)V"); - - method_onCodecConfigChanged = - env->GetMethodID(clazz, "onCodecConfigChanged", - "([BLandroid/bluetooth/BluetoothCodecConfig;" - "[Landroid/bluetooth/BluetoothCodecConfig;" - "[Landroid/bluetooth/BluetoothCodecConfig;I)V"); - - ALOGI("%s: succeeds", __func__); -} - -static std::vector prepareCodecPreferences( - JNIEnv* env, jobject object, jobjectArray codecConfigArray) { - std::vector codec_preferences; - - int numConfigs = env->GetArrayLength(codecConfigArray); - for (int i = 0; i < numConfigs; i++) { - jobject jcodecConfig = env->GetObjectArrayElement(codecConfigArray, i); - if (jcodecConfig == nullptr) continue; - if (!env->IsInstanceOf(jcodecConfig, - android_bluetooth_BluetoothCodecConfig.clazz)) { - ALOGE("%s: Invalid BluetoothCodecConfig instance", __func__); - continue; - } - jint codecType = env->CallIntMethod( - jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecType); - jint codecPriority = env->CallIntMethod( - jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecPriority); - jint sampleRate = env->CallIntMethod( - jcodecConfig, android_bluetooth_BluetoothCodecConfig.getSampleRate); - jint bitsPerSample = env->CallIntMethod( - jcodecConfig, android_bluetooth_BluetoothCodecConfig.getBitsPerSample); - jint channelMode = env->CallIntMethod( - jcodecConfig, android_bluetooth_BluetoothCodecConfig.getChannelMode); - jlong codecSpecific1 = env->CallLongMethod( - jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific1); - jlong codecSpecific2 = env->CallLongMethod( - jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific2); - jlong codecSpecific3 = env->CallLongMethod( - jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific3); - jlong codecSpecific4 = env->CallLongMethod( - jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific4); - - CodecConfig codec_config = { - .codec_type = static_cast(codecType), - .codec_priority = - static_cast(codecPriority), - .sample_rate = static_cast(sampleRate), - .bits_per_sample = - static_cast(bitsPerSample), - .channel_mode = - static_cast(channelMode), - .codec_specific_1 = codecSpecific1, - .codec_specific_2 = codecSpecific2, - .codec_specific_3 = codecSpecific3, - .codec_specific_4 = codecSpecific4}; - - codec_preferences.push_back(codec_config); - } - return codec_preferences; -} - -static void initNative(JNIEnv* env, jobject object, - jint maxConnectedAudioDevices, - jobjectArray codecConfigArray) { - std::unique_lock interface_lock(interface_mutex); - std::unique_lock callbacks_lock(callbacks_mutex); - - const bt_interface_t* btInf = getBluetoothInterface(); - if (btInf == nullptr) { - ALOGE("%s: Bluetooth module is not loaded", __func__); - return; - } - - if (sBluetoothAcmInterface != nullptr) { - ALOGW("%s: Cleaning up ACM Interface before initializing...", __func__); - sBluetoothAcmInterface->cleanup(); - sBluetoothAcmInterface = nullptr; - } - - if (mCallbacksObj != nullptr) { - ALOGW("%s: Cleaning up ACM callback object", __func__); - env->DeleteGlobalRef(mCallbacksObj); - mCallbacksObj = nullptr; - } - - if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) { - ALOGE("%s: Failed to allocate Global Ref for ACM Callbacks", __func__); - return; - } - - android_bluetooth_BluetoothCodecConfig.clazz = (jclass)env->NewGlobalRef( - env->FindClass("android/bluetooth/BluetoothCodecConfig")); - if (android_bluetooth_BluetoothCodecConfig.clazz == nullptr) { - ALOGE("%s: Failed to allocate Global Ref for BluetoothCodecConfig class", - __func__); - return; - } - - sBluetoothAcmInterface = - (btacm_initiator_interface_t*)btInf->get_profile_interface( - BT_PROFILE_ACM_ID); - if (sBluetoothAcmInterface == nullptr) { - ALOGE("%s: Failed to get Bluetooth ACM Interface", __func__); - return; - } - - std::vector codec_priorities = - prepareCodecPreferences(env, object, codecConfigArray); - - bt_status_t status = sBluetoothAcmInterface->init( - &sBluetoothAcmCallbacks, maxConnectedAudioDevices, codec_priorities); - if (status != BT_STATUS_SUCCESS) { - ALOGE("%s: Failed to initialize Bluetooth ACM, status: %d", __func__, - status); - sBluetoothAcmInterface = nullptr; - return; - } -} - -static void cleanupNative(JNIEnv* env, jobject object) { - std::unique_lock interface_lock(interface_mutex); - std::unique_lock callbacks_lock(callbacks_mutex); - - const bt_interface_t* btInf = getBluetoothInterface(); - if (btInf == nullptr) { - ALOGE("%s: Bluetooth module is not loaded", __func__); - return; - } - - if (sBluetoothAcmInterface != nullptr) { - sBluetoothAcmInterface->cleanup(); - sBluetoothAcmInterface = nullptr; - } - - env->DeleteGlobalRef(android_bluetooth_BluetoothCodecConfig.clazz); - android_bluetooth_BluetoothCodecConfig.clazz = nullptr; - - if (mCallbacksObj != nullptr) { - env->DeleteGlobalRef(mCallbacksObj); - mCallbacksObj = nullptr; - } -} - -static jboolean connectAcmNative(JNIEnv* env, jobject object, - jbyteArray address, jint contextType, - jint profileType, jint preferredContext) { - ALOGI("%s: sBluetoothAcmInterface: %p", __func__, sBluetoothAcmInterface); - std::shared_lock lock(interface_mutex); - if (!sBluetoothAcmInterface) { - ALOGE("%s: Failed to get the Bluetooth ACM Interface", __func__); - return JNI_FALSE; - } - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - - RawAddress bd_addr; - bd_addr.FromOctets(reinterpret_cast(addr)); - bt_status_t status = sBluetoothAcmInterface->connect(bd_addr, contextType, - profileType, preferredContext); - if (status != BT_STATUS_SUCCESS) { - ALOGE("%s: Failed ACM connection, status: %d", __func__, status); - } - env->ReleaseByteArrayElements(address, addr, 0); - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static jboolean disconnectAcmNative(JNIEnv* env, jobject object, - jbyteArray address, jint contextType) { - ALOGI("%s: sBluetoothAcmInterface: %p", __func__, sBluetoothAcmInterface); - std::shared_lock lock(interface_mutex); - if (!sBluetoothAcmInterface) { - ALOGE("%s: Failed to get the Bluetooth ACM Interface", __func__); - return JNI_FALSE; - } - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - - RawAddress bd_addr; - bd_addr.FromOctets(reinterpret_cast(addr)); - bt_status_t status = sBluetoothAcmInterface->disconnect(bd_addr, contextType); - if (status != BT_STATUS_SUCCESS) { - ALOGE("%s: Failed ACM disconnection, status: %d", __func__, status); - } - env->ReleaseByteArrayElements(address, addr, 0); - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static jboolean startStreamNative(JNIEnv* env, jobject object, - jbyteArray address, jint contextType) { - ALOGI("%s: sBluetoothAcmInterface: %p", __func__, sBluetoothAcmInterface); - std::shared_lock lock(interface_mutex); - if (!sBluetoothAcmInterface) { - ALOGE("%s: Failed to get the Bluetooth ACM Interface", __func__); - return JNI_FALSE; - } - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - - RawAddress bd_addr = RawAddress::kEmpty; - if (addr) { - bd_addr.FromOctets(reinterpret_cast(addr)); - } - bt_status_t status = sBluetoothAcmInterface->start_stream(bd_addr, contextType); - if (status != BT_STATUS_SUCCESS) { - ALOGE("%s: Failed ACM set_active_device, status: %d", __func__, status); - } - env->ReleaseByteArrayElements(address, addr, 0); - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static jboolean stopStreamNative(JNIEnv* env, jobject object, - jbyteArray address, jint contextType) { - ALOGI("%s: sBluetoothAcmInterface: %p", __func__, sBluetoothAcmInterface); - std::shared_lock lock(interface_mutex); - if (!sBluetoothAcmInterface) { - ALOGE("%s: Failed to get the Bluetooth ACM Interface", __func__); - return JNI_FALSE; - } - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - - RawAddress bd_addr = RawAddress::kEmpty; - if (addr) { - bd_addr.FromOctets(reinterpret_cast(addr)); - } - bt_status_t status = sBluetoothAcmInterface->stop_stream(bd_addr, contextType); - if (status != BT_STATUS_SUCCESS) { - ALOGE("%s: Failed ACM set_active_device, status: %d", __func__, status); - } - env->ReleaseByteArrayElements(address, addr, 0); - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static jboolean setActiveDeviceNative(JNIEnv* env, jobject object, - jbyteArray address, jint contextType) { - ALOGI("%s: sBluetoothAcmInterface: %p", __func__, sBluetoothAcmInterface); - std::shared_lock lock(interface_mutex); - if (!sBluetoothAcmInterface) { - ALOGE("%s: Failed to get the Bluetooth ACM Interface", __func__); - return JNI_FALSE; - } - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - - RawAddress bd_addr = RawAddress::kEmpty; - if (addr) { - bd_addr.FromOctets(reinterpret_cast(addr)); - } - bt_status_t status = sBluetoothAcmInterface->set_active_device(bd_addr, contextType); - if (status != BT_STATUS_SUCCESS) { - ALOGE("%s: Failed ACM set_active_device, status: %d", __func__, status); - } - env->ReleaseByteArrayElements(address, addr, 0); - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static jboolean setCodecConfigPreferenceNative(JNIEnv* env, jobject object, - jbyteArray address, - jobjectArray codecConfigArray, - jint contextType, jint preferredContext) { - ALOGI("%s: sBluetoothAcmInterface: %p", __func__, sBluetoothAcmInterface); - std::shared_lock lock(interface_mutex); - if (!sBluetoothAcmInterface) { - ALOGE("%s: Failed to get the Bluetooth ACM Interface", __func__); - return JNI_FALSE; - } - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - - RawAddress bd_addr; - bd_addr.FromOctets(reinterpret_cast(addr)); - std::vector codec_preferences = - prepareCodecPreferences(env, object, codecConfigArray); - - bt_status_t status = - sBluetoothAcmInterface->config_codec(bd_addr, codec_preferences, contextType, preferredContext); - if (status != BT_STATUS_SUCCESS) { - ALOGE("%s: Failed codec configuration, status: %d", __func__, status); - } - env->ReleaseByteArrayElements(address, addr, 0); - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static jboolean ChangeCodecConfigPreferenceNative(JNIEnv* env, jobject object, - jbyteArray address, - jstring message) { - ALOGI("%s: sBluetoothAcmInterface: %p", __func__, sBluetoothAcmInterface); - std::shared_lock lock(interface_mutex); - if (!sBluetoothAcmInterface) { - ALOGE("%s: Failed to get the Bluetooth ACM Interface", __func__); - return JNI_FALSE; - } - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - - RawAddress bd_addr; - bd_addr.FromOctets(reinterpret_cast(addr)); - const char* c_msg = env->GetStringUTFChars(message, NULL); - bt_status_t status = - sBluetoothAcmInterface->change_config_codec(bd_addr, (char*)c_msg); - if (status != BT_STATUS_SUCCESS) { - ALOGE("%s: Failed codec configuration, status: %d", __func__, status); - } - env->ReleaseByteArrayElements(address, addr, 0); - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static JNINativeMethod sMethods[] = { - {"classInitNative", "()V", (void*)classInitNative}, - {"initNative", "(I[Landroid/bluetooth/BluetoothCodecConfig;)V", - (void*)initNative}, - {"cleanupNative", "()V", (void*)cleanupNative}, - {"connectAcmNative", "([BIII)Z", (void*)connectAcmNative}, - {"disconnectAcmNative", "([BI)Z", (void*)disconnectAcmNative}, - {"startStreamNative", "([BI)Z", (void*)startStreamNative}, - {"stopStreamNative", "([BI)Z", (void*)stopStreamNative}, - {"setActiveDeviceNative", "([BI)Z", (void*)setActiveDeviceNative}, - {"setCodecConfigPreferenceNative", - "([B[Landroid/bluetooth/BluetoothCodecConfig;II)Z", - (void*)setCodecConfigPreferenceNative}, - {"ChangeCodecConfigPreferenceNative", - "([BLjava/lang/String;)Z", - (void*)ChangeCodecConfigPreferenceNative}, -}; - -int register_com_android_bluetooth_acm(JNIEnv* env) { - return jniRegisterNativeMethods( - env, "com/android/bluetooth/acm/AcmNativeInterface", sMethods, - NELEM(sMethods)); -} -} diff --git a/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_apm.cpp b/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_apm.cpp deleted file mode 100644 index 6ffa2daff652556adb13b4476201048f0cb8b7f5..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_apm.cpp +++ /dev/null @@ -1,194 +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. - * - ******************************************************************************/ - - -#define LOG_TAG "BluetoothAPM_Jni" - -#define LOG_NDEBUG 0 - -#include "android_runtime/AndroidRuntime.h" -#include "com_android_bluetooth.h" -#include "hardware/bt_apm.h" -#include "utils/Log.h" - -#include -#include - -namespace android { -static jmethodID method_onGetActiveprofileCallback; - -static const bt_apm_interface_t* sBluetoothApmInterface = nullptr; -static std::shared_timed_mutex interface_mutex; - -static jobject mCallbacksObj = nullptr; -static std::shared_timed_mutex callbacks_mutex; - - -static int btapm_active_profile_callback(const RawAddress& bd_addr, uint16_t audio_type) -{ - ALOGI("%s", __func__); - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return -1; - - ScopedLocalRef addr( - sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); - if (!addr.get()) { - ALOGE("%s: Fail to new jbyteArray bd addr", __func__); - return -1; - } - - sCallbackEnv->SetByteArrayRegion( - addr.get(), 0, sizeof(RawAddress), - reinterpret_cast(bd_addr.address)); - return sCallbackEnv->CallIntMethod(mCallbacksObj, method_onGetActiveprofileCallback, - addr.get(), (jint)audio_type); -} - - -static btapm_initiator_callbacks_t sBluetoothApmCallbacks = { - sizeof(sBluetoothApmCallbacks), - btapm_active_profile_callback -}; - -static void classInitNative(JNIEnv* env, jclass clazz) { - - ALOGI("%s: succeeds", __func__); - method_onGetActiveprofileCallback = - env->GetMethodID(clazz, "getActiveProfile", "([BI)I"); -} - -static bool initNative(JNIEnv* env, jobject object) { - std::unique_lock interface_lock(interface_mutex); - std::unique_lock callbacks_lock(callbacks_mutex); - - const bt_interface_t* btInf = getBluetoothInterface(); - if (btInf == nullptr) { - ALOGE("%s: Bluetooth module is not loaded", __func__); - return JNI_FALSE; - } - - if (sBluetoothApmInterface != nullptr) { - ALOGW("%s: Cleaning up APM Interface before initializing...", __func__); - sBluetoothApmInterface->cleanup(); - sBluetoothApmInterface = nullptr; - } - - if (mCallbacksObj != nullptr) { - ALOGW("%s: Cleaning up APM callback object", __func__); - env->DeleteGlobalRef(mCallbacksObj); - mCallbacksObj = nullptr; - } - - if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) { - ALOGE("%s: Failed to allocate Global Ref for APM Callbacks", __func__); - return JNI_FALSE; - } - - sBluetoothApmInterface = - (bt_apm_interface_t*)btInf->get_profile_interface( - BT_APM_MODULE_ID); - if (sBluetoothApmInterface == nullptr) { - ALOGE("%s: Failed to get Bluetooth APM Interface", __func__); - return JNI_FALSE; - } - bt_status_t status = sBluetoothApmInterface->init(&sBluetoothApmCallbacks); - if (status != BT_STATUS_SUCCESS) { - ALOGE("%s: Failed to initialize Bluetooth APM, status: %d", __func__, - status); - sBluetoothApmInterface = nullptr; - return JNI_FALSE; - } - return JNI_TRUE; -} - -static void cleanupNative(JNIEnv* env, jobject object) { - std::unique_lock interface_lock(interface_mutex); - std::unique_lock callbacks_lock(callbacks_mutex); - - const bt_interface_t* btInf = getBluetoothInterface(); - if (btInf == nullptr) { - ALOGE("%s: Bluetooth module is not loaded", __func__); - return; - } - - if (sBluetoothApmInterface != nullptr) { - sBluetoothApmInterface->cleanup(); - sBluetoothApmInterface = nullptr; - } - - if (mCallbacksObj != nullptr) { - env->DeleteGlobalRef(mCallbacksObj); - mCallbacksObj = nullptr; - } -} - -static jboolean activeDeviceUpdateNative(JNIEnv* env, jobject object, - jbyteArray address, jint profile, jint audio_type) { - ALOGI("%s: sBluetoothApmInterface: %p", __func__, sBluetoothApmInterface); - std::shared_lock lock(interface_mutex); - if (!sBluetoothApmInterface) { - ALOGE("%s: Failed to get the Bluetooth APM Interface", __func__); - return JNI_FALSE; - } - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - - RawAddress bd_addr = RawAddress::kEmpty; - if (addr) { - bd_addr.FromOctets(reinterpret_cast(addr)); - } - bt_status_t status = sBluetoothApmInterface->active_device_change(bd_addr, profile, audio_type); - if (status != BT_STATUS_SUCCESS) { - ALOGE("%s: Failed APM active_device_change, status: %d", __func__, status); - } - env->ReleaseByteArrayElements(address, addr, 0); - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static jboolean setContentControlNative(JNIEnv* env, jobject object, - jint content_control_id, jint profile) { - ALOGI("%s: sBluetoothApmInterface: %p", __func__, sBluetoothApmInterface); - std::shared_lock lock(interface_mutex); - if (!sBluetoothApmInterface) { - ALOGE("%s: Failed to get the Bluetooth APM Interface", __func__); - return JNI_FALSE; - } - - bt_status_t status = sBluetoothApmInterface->set_content_control_id(content_control_id, profile); - if (status != BT_STATUS_SUCCESS) { - ALOGE("%s: Failed APM content control update, status: %d", __func__, status); - } - - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static JNINativeMethod sMethods[] = { - {"classInitNative", "()V", (void*)classInitNative}, - {"initNative", "()V", (void*)initNative}, - {"cleanupNative", "()V", (void*)cleanupNative}, - {"activeDeviceUpdateNative", "([BII)Z", (void*)activeDeviceUpdateNative}, - {"setContentControlNative", "(II)Z", (void*)setContentControlNative}, -}; - -int register_com_android_bluetooth_apm(JNIEnv* env) { - return jniRegisterNativeMethods( - env, "com/android/bluetooth/apm/ApmNativeInterface", sMethods, - NELEM(sMethods)); -} -} diff --git a/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_broadcast.cpp b/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_broadcast.cpp deleted file mode 100644 index 75ea08504d14406937f661b2d356b7765c6a9878..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_broadcast.cpp +++ /dev/null @@ -1,470 +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. - * - ******************************************************************************/ - -#define LOG_TAG "BluetoothBapBroadcastServiceJni" - -#define LOG_NDEBUG 0 - -#include "android_runtime/AndroidRuntime.h" -#include "com_android_bluetooth.h" -#include "hardware/bt_av.h" -#include "hardware/bt_bap_ba.h" -#include "utils/Log.h" - -#include -#include - -namespace android { -static jmethodID method_onBroadcastStateChanged; -static jmethodID method_onAudioStateChanged; -static jmethodID method_onCodecConfigChanged; -//static jmethodID method_onIsoDataPathChanged; -static jmethodID method_onEncryptionKeyGenerated; -static jmethodID method_onSetupBIG; -static jmethodID method_onBroadcastIdGenerated; -static struct { - jclass clazz; - jmethodID constructor; - jmethodID getCodecType; - jmethodID getCodecPriority; - jmethodID getSampleRate; - jmethodID getBitsPerSample; - jmethodID getChannelMode; - jmethodID getCodecSpecific1; - jmethodID getCodecSpecific2; - jmethodID getCodecSpecific3; - jmethodID getCodecSpecific4; -} android_bluetooth_BluetoothCodecConfig; - -static const btbap_broadcast_interface_t* sBluetoothBapBroadcastInterface = nullptr; -static std::shared_timed_mutex interface_mutex; - -static jobject mCallbacksObj = nullptr; -static std::shared_timed_mutex callbacks_mutex; - -static void btbap_broadcast_state_callback(jint adv_id, btbap_broadcast_state_t state) { - ALOGI("%s", __func__); - - std::shared_lock lock(callbacks_mutex); - ALOGI("%s: lock acquired", __func__); - CallbackEnv sCallbackEnv(__func__); - ALOGI("%s:got callback env", __func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) { - ALOGI("%s:either callback is not valid or callbackobj is null", __func__); - return; - } - ALOGI("%s: calling method to native interface", __func__); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onBroadcastStateChanged, adv_id, (jint)state); -} - -static void btbap_broadcast_audio_state_callback(jint big_handle, btbap_broadcast_audio_state_t state) { - ALOGI("%s", __func__); - - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onAudioStateChanged, big_handle, (jint)state); -} - -static void btbap_broadcast_audio_config_callback(jint adv_id, btav_a2dp_codec_config_t codec_config, - std::vector codec_capabilities) { - ALOGI("%s", __func__); - - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - - jobject codecConfigObj = sCallbackEnv->NewObject( - android_bluetooth_BluetoothCodecConfig.clazz, - android_bluetooth_BluetoothCodecConfig.constructor, - (jint)codec_config.codec_type, (jint)codec_config.codec_priority, - (jint)codec_config.sample_rate, (jint)codec_config.bits_per_sample, - (jint)codec_config.channel_mode, (jlong)codec_config.codec_specific_1, - (jlong)codec_config.codec_specific_2, - (jlong)codec_config.codec_specific_3, - (jlong)codec_config.codec_specific_4); - - jsize i = 0; - jobjectArray local_capabilities_array = sCallbackEnv->NewObjectArray( - (jsize)codec_capabilities.size(), - android_bluetooth_BluetoothCodecConfig.clazz, nullptr); - for (auto const& cap : codec_capabilities) { - jobject capObj = sCallbackEnv->NewObject( - android_bluetooth_BluetoothCodecConfig.clazz, - android_bluetooth_BluetoothCodecConfig.constructor, - (jint)cap.codec_type, (jint)cap.codec_priority, (jint)cap.sample_rate, - (jint)cap.bits_per_sample, (jint)cap.channel_mode, - (jlong)cap.codec_specific_1, (jlong)cap.codec_specific_2, - (jlong)cap.codec_specific_3, (jlong)cap.codec_specific_4); - sCallbackEnv->SetObjectArrayElement(local_capabilities_array, i++, capObj); - sCallbackEnv->DeleteLocalRef(capObj); - } - - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCodecConfigChanged, - adv_id, codecConfigObj, local_capabilities_array); -} - -/*static void btbap_broadcast_iso_datapath_callback(jint big_handle, jint state) { - ALOGI("%s", __func__); - - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onIsoDataPathChanged, big_handle, state); -}*/ - -static void btbap_broadcast_enckey_callback(std::string pin) { - ALOGI("%s", __func__); - - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - /*ScopedLocalRef pinkey( - sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(pin))); - if (!addr.get()) { - ALOGE("%s: Fail to new jbyteArray bd addr", __func__); - return; - } - - sCallbackEnv->SetByteArrayRegion( - pinkey.get(), 0, sizeof(pin), - reinterpret_cast(pin));*/ - - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onEncryptionKeyGenerated, - sCallbackEnv->NewStringUTF(pin.c_str())); -} - -static void btbap_broadcast_setup_big_callback(jint setup, jint adv_id, jint big_handle, - jint num_bises, std::vector bis_handles) { - ALOGI("%s", __func__); - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - ScopedLocalRef jc(sCallbackEnv.get(), sCallbackEnv->NewCharArray(bis_handles.size())); - sCallbackEnv->SetCharArrayRegion(jc.get(), 0, bis_handles.size(), (jchar*) bis_handles.data()); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSetupBIG, setup, adv_id, big_handle, num_bises, jc.get()); -} - -static void btbap_broadcast_bid_callback(std::vector broadcast_id) { - ALOGI("%s", __func__); - - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - ALOGI("%s: broadcast_id size = %d",__func__,broadcast_id.size()); - ScopedLocalRef jb(sCallbackEnv.get(), sCallbackEnv->NewByteArray(broadcast_id.size())); - if (!jb.get()) { - ALOGI("%s:Failed to allocate byte array"); - return; - } - sCallbackEnv->SetByteArrayRegion(jb.get(), 0, broadcast_id.size(), (jbyte*) broadcast_id.data()); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onBroadcastIdGenerated, jb.get()); -} - -static btbap_broadcast_callbacks_t sBluetoothBapBroadcastCallbacks = { - sizeof(sBluetoothBapBroadcastCallbacks), - btbap_broadcast_state_callback, - btbap_broadcast_audio_state_callback, - btbap_broadcast_audio_config_callback, - //btbap_broadcast_iso_datapath_callback, - btbap_broadcast_enckey_callback, - btbap_broadcast_setup_big_callback, - btbap_broadcast_bid_callback, -}; - -static void classInitNative(JNIEnv* env, jclass clazz) { - jclass jniBluetoothCodecConfigClass = - env->FindClass("android/bluetooth/BluetoothCodecConfig"); - android_bluetooth_BluetoothCodecConfig.constructor = - env->GetMethodID(jniBluetoothCodecConfigClass, "", "(IIIIIJJJJ)V"); - android_bluetooth_BluetoothCodecConfig.getCodecType = - env->GetMethodID(jniBluetoothCodecConfigClass, "getCodecType", "()I"); - android_bluetooth_BluetoothCodecConfig.getCodecPriority = - env->GetMethodID(jniBluetoothCodecConfigClass, "getCodecPriority", "()I"); - android_bluetooth_BluetoothCodecConfig.getSampleRate = - env->GetMethodID(jniBluetoothCodecConfigClass, "getSampleRate", "()I"); - android_bluetooth_BluetoothCodecConfig.getBitsPerSample = - env->GetMethodID(jniBluetoothCodecConfigClass, "getBitsPerSample", "()I"); - android_bluetooth_BluetoothCodecConfig.getChannelMode = - env->GetMethodID(jniBluetoothCodecConfigClass, "getChannelMode", "()I"); - android_bluetooth_BluetoothCodecConfig.getCodecSpecific1 = env->GetMethodID( - jniBluetoothCodecConfigClass, "getCodecSpecific1", "()J"); - android_bluetooth_BluetoothCodecConfig.getCodecSpecific2 = env->GetMethodID( - jniBluetoothCodecConfigClass, "getCodecSpecific2", "()J"); - android_bluetooth_BluetoothCodecConfig.getCodecSpecific3 = env->GetMethodID( - jniBluetoothCodecConfigClass, "getCodecSpecific3", "()J"); - android_bluetooth_BluetoothCodecConfig.getCodecSpecific4 = env->GetMethodID( - jniBluetoothCodecConfigClass, "getCodecSpecific4", "()J"); - - method_onBroadcastStateChanged = - env->GetMethodID(clazz, "onBroadcastStateChanged", "(II)V"); - - method_onAudioStateChanged = - env->GetMethodID(clazz, "onAudioStateChanged", "(II)V"); - - method_onCodecConfigChanged = - env->GetMethodID(clazz, "onCodecConfigChanged", - "(ILandroid/bluetooth/BluetoothCodecConfig;" - "[Landroid/bluetooth/BluetoothCodecConfig;)V"); - -// method_onIsoDataPathChanged = -// env->GetMethodID(clazz, "onIsoDataPathChanged","(II)V"); - method_onEncryptionKeyGenerated = - env->GetMethodID(clazz, "onEncryptionKeyGenerated", "(Ljava/lang/String;)V"); - - method_onSetupBIG = env->GetMethodID(clazz, "onSetupBIG", "(IIII[C)V"); - method_onBroadcastIdGenerated = env->GetMethodID(clazz, "onBroadcastIdGenerated", "([B)V"); - - ALOGI("%s: succeeds", __func__); -} -static btav_a2dp_codec_config_t prepare_codec_config( - JNIEnv* env, jobject object,jobject jcodecConfig) { - - /*if (!env->IsInstanceOf(jcodecConfig, - android_bluetooth_BluetoothCodecConfig.clazz)) { - ALOGE("%s: Invalid BluetoothCodecConfig instance", __func__); - return ((btav_a2dp_codec_config_t)NULL); - }*/ - jint codecType = env->CallIntMethod( - jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecType); - jint codecPriority = env->CallIntMethod( - jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecPriority); - jint sampleRate = env->CallIntMethod( - jcodecConfig, android_bluetooth_BluetoothCodecConfig.getSampleRate); - jint bitsPerSample = env->CallIntMethod( - jcodecConfig, android_bluetooth_BluetoothCodecConfig.getBitsPerSample); - jint channelMode = env->CallIntMethod( - jcodecConfig, android_bluetooth_BluetoothCodecConfig.getChannelMode); - jlong codecSpecific1 = env->CallLongMethod( - jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific1); - jlong codecSpecific2 = env->CallLongMethod( - jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific2); - jlong codecSpecific3 = env->CallLongMethod( - jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific3); - jlong codecSpecific4 = env->CallLongMethod( - jcodecConfig, android_bluetooth_BluetoothCodecConfig.getCodecSpecific4); - - btav_a2dp_codec_config_t codec_config = { - .codec_type = static_cast(codecType), - .codec_priority = - static_cast(codecPriority), - .sample_rate = static_cast(sampleRate), - .bits_per_sample = - static_cast(bitsPerSample), - .channel_mode = - static_cast(channelMode), - .codec_specific_1 = codecSpecific1, - .codec_specific_2 = codecSpecific2, - .codec_specific_3 = codecSpecific3, - .codec_specific_4 = codecSpecific4}; - return codec_config; -} - -static void initNative(JNIEnv* env, jobject object, - jint maxBroadcast, jobject codecConfig, jint mode) { - std::unique_lock interface_lock(interface_mutex); - std::unique_lock callbacks_lock(callbacks_mutex); - - const bt_interface_t* btInf = getBluetoothInterface(); - if (btInf == nullptr) { - ALOGE("%s: Bluetooth module is not loaded", __func__); - return; - } - - if (sBluetoothBapBroadcastInterface != nullptr) { - ALOGW("%s: Cleaning up BapBroadcast Interface before initializing...", __func__); - sBluetoothBapBroadcastInterface->cleanup(); - sBluetoothBapBroadcastInterface = nullptr; - } - - if (mCallbacksObj != nullptr) { - ALOGW("%s: Cleaning up BapBroadcast callback object", __func__); - env->DeleteGlobalRef(mCallbacksObj); - mCallbacksObj = nullptr; - } - - if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) { - ALOGE("%s: Failed to allocate Global Ref for bap broadcast Callbacks", __func__); - return; - } - - android_bluetooth_BluetoothCodecConfig.clazz = (jclass)env->NewGlobalRef( - env->FindClass("android/bluetooth/BluetoothCodecConfig")); - if (android_bluetooth_BluetoothCodecConfig.clazz == nullptr) { - ALOGE("%s: Failed to allocate Global Ref for BluetoothCodecConfig class", - __func__); - return; - } - - sBluetoothBapBroadcastInterface = - (btbap_broadcast_interface_t*)btInf->get_profile_interface( - BT_PROFILE_BAP_BROADCAST_ID); - if (sBluetoothBapBroadcastInterface == nullptr) { - ALOGE("%s: Failed to get Bluetooth BapBroadcast Interface", __func__); - return; - } - btav_a2dp_codec_config_t codec_config = - prepare_codec_config(env, object, codecConfig); - /*if (codec_config == NULL) { - ALOGE("%s:Invalid codec config",__func__); - return; - }*/ - bt_status_t status = sBluetoothBapBroadcastInterface->init( - &sBluetoothBapBroadcastCallbacks, maxBroadcast, codec_config, mode); - if (status != BT_STATUS_SUCCESS) { - ALOGE("%s: Failed to initialize Bluetooth A2DP, status: %d", __func__, - status); - sBluetoothBapBroadcastInterface = nullptr; - return; - } -} - -static void cleanupNative(JNIEnv* env, jobject object) { - std::unique_lock interface_lock(interface_mutex); - std::unique_lock callbacks_lock(callbacks_mutex); - - const bt_interface_t* btInf = getBluetoothInterface(); - if (btInf == nullptr) { - ALOGE("%s: Bluetooth module is not loaded", __func__); - return; - } - - if (sBluetoothBapBroadcastInterface != nullptr) { - sBluetoothBapBroadcastInterface->cleanup(); - sBluetoothBapBroadcastInterface = nullptr; - } - - env->DeleteGlobalRef(android_bluetooth_BluetoothCodecConfig.clazz); - android_bluetooth_BluetoothCodecConfig.clazz = nullptr; - - if (mCallbacksObj != nullptr) { - env->DeleteGlobalRef(mCallbacksObj); - mCallbacksObj = nullptr; - } -} - -static jboolean setActiveDeviceNative(JNIEnv* env, jobject object, - jboolean enable, jint adv_id) { - ALOGI("%s: sBluetoothBapBroadcastInterface: %p", __func__, sBluetoothBapBroadcastInterface); - std::shared_lock lock(interface_mutex); - if (!sBluetoothBapBroadcastInterface) { - ALOGE("%s: Failed to get the BapBroadcast Interface", __func__); - return JNI_FALSE; - } - bt_status_t status = sBluetoothBapBroadcastInterface->set_broadcast_active(enable, adv_id); - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static jboolean enableBroadcastNative(JNIEnv* env, jobject object, jobject codecConfig) { - ALOGI("%s: sBluetoothBapBroadcastInterface: %p", __func__, sBluetoothBapBroadcastInterface); - btav_a2dp_codec_config_t codec_config = - prepare_codec_config(env, object, codecConfig); - std::shared_lock lock(interface_mutex); - if (!sBluetoothBapBroadcastInterface) { - ALOGE("%s: Failed to get the BapBroadcast Interface", __func__); - return JNI_FALSE; - } - bt_status_t status = sBluetoothBapBroadcastInterface->enable_broadcast(codec_config); - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static jboolean disableBroadcastNative(JNIEnv* env, jobject object, jint adv_id) { - ALOGI("%s: sBluetoothBapBroadcastInterface: %p", __func__, sBluetoothBapBroadcastInterface); - std::shared_lock lock(interface_mutex); - if (!sBluetoothBapBroadcastInterface) { - ALOGE("%s: Failed to get the BapBroadcast Interface", __func__); - return JNI_FALSE; - } - bt_status_t status = sBluetoothBapBroadcastInterface->disable_broadcast(adv_id); - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static jboolean setupAudioPathNative(JNIEnv* env, jobject object, jboolean enable,jint adv_id, - jint big_handle, jint num_bises, jintArray bises) { - ALOGI("%s: sBluetoothBapBroadcastInterface: %p", __func__, sBluetoothBapBroadcastInterface); - std::shared_lock lock(interface_mutex); - if (!sBluetoothBapBroadcastInterface) { - ALOGE("%s: Failed to get the BapBroadcast Interface", __func__); - return JNI_FALSE; - } - jint* bis_handles = env->GetIntArrayElements(bises, NULL); - bt_status_t status = sBluetoothBapBroadcastInterface->setup_audiopath(enable, adv_id, big_handle, num_bises, bis_handles); - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static jstring getEncryptionKeyNative(JNIEnv* env, jobject object) { - ALOGI("%s: sBluetoothBapBroadcastInterface: %p", __func__, sBluetoothBapBroadcastInterface); - std::shared_lock lock(interface_mutex); - if (!sBluetoothBapBroadcastInterface) { - ALOGE("%s: Failed to get the BapBroadcast Interface", __func__); - return JNI_FALSE; - } - std::string stdstr = sBluetoothBapBroadcastInterface->get_encryption_key(); - return env->NewStringUTF(stdstr.c_str()); -} - -static jboolean setEncryptionKeyNative(JNIEnv* env, jobject object, jboolean enabled, jint length) { - ALOGI("%s: sBluetoothBapBroadcastInterface: %p", __func__, sBluetoothBapBroadcastInterface); - std::shared_lock lock(interface_mutex); - if (!sBluetoothBapBroadcastInterface) { - ALOGE("%s: Failed to get the BapBroadcast Interface", __func__); - return JNI_FALSE; - } - bt_status_t status = sBluetoothBapBroadcastInterface->set_encryption(enabled, length); - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static jboolean setCodecConfigPreferenceNative(JNIEnv* env, jobject object, - jint adv_handle, jobject codecConfig) { - ALOGI("%s: sBluetoothBapBroadcastInterface: %p", __func__, sBluetoothBapBroadcastInterface); - std::shared_lock lock(interface_mutex); - if (!sBluetoothBapBroadcastInterface) { - ALOGE("%s: Failed to get the BapBroadcast Interface", __func__); - return JNI_FALSE; - } - btav_a2dp_codec_config_t codec_config = - prepare_codec_config(env, object, codecConfig); - bt_status_t status = sBluetoothBapBroadcastInterface->codec_config_change(adv_handle, codec_config); - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static JNINativeMethod sMethods[] = { - {"classInitNative", "()V", (void*)classInitNative}, - {"initNative", "(ILandroid/bluetooth/BluetoothCodecConfig;I)V", - (void*)initNative}, - {"cleanupNative", "()V", (void*)cleanupNative}, - {"setActiveDeviceNative", "(ZI)Z", (void*)setActiveDeviceNative}, - {"enableBroadcastNative", "(Landroid/bluetooth/BluetoothCodecConfig;)Z", (void*)enableBroadcastNative}, - {"disableBroadcastNative", "(I)Z", (void*)disableBroadcastNative}, - {"getEncryptionKeyNative", "()Ljava/lang/String;", (void*)getEncryptionKeyNative}, - {"setEncryptionKeyNative", "(ZI)Z", (void*)setEncryptionKeyNative}, - {"setupAudioPathNative", "(ZIII[I)Z", (void*)setupAudioPathNative}, - {"setCodecConfigPreferenceNative", - "(ILandroid/bluetooth/BluetoothCodecConfig;)Z", - (void*)setCodecConfigPreferenceNative}, -}; - -int register_com_android_bluetooth_bap_broadcast(JNIEnv* env) { - return jniRegisterNativeMethods( - env, "com/android/bluetooth/broadcast/BroadcastNativeInterface", sMethods, - NELEM(sMethods)); -} - -} diff --git a/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterServiceExt.cpp b/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterServiceExt.cpp deleted file mode 100644 index f763310d9776e08c55bfd1ae43da6ec027a7864f..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_btservice_AdapterServiceExt.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/****************************************************************************** - * - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - - -#include "android_runtime/AndroidRuntime.h" -#include "com_android_bluetooth_ext.h" - -namespace android { - - int register_com_android_bluetooth_adv_audio_profiles(JNIEnv* env) { - ALOGE("%s", __func__); - - int status = android::register_com_android_bluetooth_csip_client(env); - if (status < 0) { - ALOGE("jni csip registration failure: %d", status); - return JNI_ERR; - } - - status = android::register_com_android_bluetooth_acm(env); - if (status < 0) { - ALOGE("jni acm registration failure: %d", status); - return JNI_ERR; - } - - status = android::register_com_android_bluetooth_apm(env); - if (status < 0) { - ALOGE("jni APM registration failure: %d", status); - return JNI_ERR; - } - - status = android::register_com_android_bluetooth_bap_broadcast(env); - if (status < 0) { - ALOGE("jni bap broadcast registration failure: %d", status); - return JNI_ERR; - } - - status = android::register_com_android_bluetooth_vcp_controller(env); - if (status < 0) { - ALOGE("jni vcp controller registration failure: %d", status); - return JNI_ERR; - } - - status = android::register_com_android_bluetooth_pacs_client(env); - if (status < 0) { - ALOGE("jni pacs client registration failure: %d", status); - return JNI_ERR; - } - status = android::register_com_android_bluetooth_call_controller(env); - if (status < 0) { - ALOGE("jni CC registration failure: %d", status); - return JNI_ERR; - } - - status = android::register_com_android_bluetooth_mcp(env); - if (status < 0) { - ALOGE("jni mcp registration failure: %d", status); - return JNI_ERR; - } - return JNI_VERSION_1_6; - } -} diff --git a/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_cc.cpp b/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_cc.cpp deleted file mode 100644 index e8203eac2ed17159011138c93273167d63963b08..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_cc.cpp +++ /dev/null @@ -1,402 +0,0 @@ -/* - *Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. - - * Copyright 2012 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 "BluetoothCCServiceJni" - -#define LOG_NDEBUG 0 - -#include -#include -#include -#include -#include -#include - -#include "android_runtime/AndroidRuntime.h" -#include "base/logging.h" -#include "com_android_bluetooth.h" -#include "hardware/bluetooth.h" -#include "hardware/bluetooth_callcontrol_callbacks.h" -#include "hardware/bluetooth_callcontrol_interface.h" - -using bluetooth::call_control::CallControllerCallbacks; -using bluetooth::call_control::CallControllerInterface; -using bluetooth::Uuid; -static CallControllerInterface* sCallControllerInterface = nullptr; - -namespace android { -static jmethodID method_CallControlInitializedCallback; -static jmethodID method_OnConnectionStateChanged; -static jmethodID method_CallControlPointChangedRequest; -static std::shared_timed_mutex interface_mutex; -static jobject mCallbacksObj = nullptr; -static std::shared_timed_mutex callbacks_mutex; - -class CallControllerCallbacksImpl : public CallControllerCallbacks { - public: - ~CallControllerCallbacksImpl() = default; - void CallControlInitializedCallback(uint8_t state) override { - LOG(INFO) << __func__; - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_CallControlInitializedCallback, - (jint)state); - } - void ConnectionStateCallback(uint8_t state, const RawAddress& bd_addr) override { - LOG(INFO) << __func__; - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - ScopedLocalRef addr( - sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); - if (!addr.get()) { - LOG(ERROR) << "Failed to new jbyteArray bd addr for connection state"; - return; - } - sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), - (jbyte*)&bd_addr); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_OnConnectionStateChanged, - (jint)state, addr.get()); - } - - void CallControlCallback(uint8_t op, std::vector p_indices, int count, std::vector uri_data, const RawAddress& bd_addr) override { - LOG(INFO) << __func__; - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - - ScopedLocalRef addr( - sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); - if (!addr.get()) { - LOG(ERROR) << "Failed to new jbyteArray bd addr for connection state"; - return; - } - ScopedLocalRef indices(sCallbackEnv.get(), (jintArray)sCallbackEnv->NewIntArray(count)); - ScopedLocalRef originate_uri( - sCallbackEnv.get(), sCallbackEnv->NewByteArray(uri_data.size())); - if (!originate_uri.get()) { - ALOGE("Error while allocation byte array for uri data in %s", __func__); - return; - } - sCallbackEnv->SetByteArrayRegion(originate_uri.get(), 0, uri_data.size(), - (jbyte*)uri_data.data()); - - sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), - (jbyte*)&bd_addr); - sCallbackEnv->SetIntArrayRegion(indices.get(), 0, count,(jint*)p_indices.data()); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_CallControlPointChangedRequest, - (jint)op, indices.get(), (jint)count, originate_uri.get(), addr.get()); - } -}; - -static CallControllerCallbacksImpl sCallControllerCallbacks; - -static void classInitNative(JNIEnv* env, jclass clazz) { - method_CallControlInitializedCallback = - env->GetMethodID(clazz, "callControlInitializedCallback", "(I)V"); - method_OnConnectionStateChanged = - env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V"); - method_CallControlPointChangedRequest = - env->GetMethodID(clazz, "callControlPointChangedRequest", "(I[II[B[B)V"); - - LOG(INFO) << __func__ << " : succeeds"; -} - -static void initializeNative(JNIEnv* env, jobject object, jstring uuid, - jint max_ccs_clients, jboolean inband_ringing_enabled) { - std::unique_lock interface_lock(interface_mutex); - std::unique_lock callbacks_lock(callbacks_mutex); - - const bt_interface_t* btInf = getBluetoothInterface(); - if (!btInf) { - ALOGE("%s: Bluetooth module is not loaded", __func__); - jniThrowIOException(env, EINVAL); - return; - } - - if (sCallControllerInterface) { - ALOGI("%s: Cleaning up Bluetooth CallControl Interface before initializing", - __func__); - sCallControllerInterface->Cleanup(); - sCallControllerInterface = nullptr; - } - - if (mCallbacksObj) { - ALOGI("%s: Cleaning up Bluetooth CallControl callback object", __func__); - env->DeleteGlobalRef(mCallbacksObj); - mCallbacksObj = nullptr; - } - - const char* _uuid = env->GetStringUTFChars(uuid, nullptr); - - sCallControllerInterface = - (CallControllerInterface*)btInf->get_profile_interface( - BT_PROFILE_CC_ID); - if (!sCallControllerInterface) { - ALOGW("%s: Failed to get Bluetooth CallControl Interface", __func__); - jniThrowIOException(env, EINVAL); - return; - } - bt_status_t status = - sCallControllerInterface->Init(&sCallControllerCallbacks, - bluetooth::Uuid::FromString(_uuid), max_ccs_clients, inband_ringing_enabled); - if (status != BT_STATUS_SUCCESS) { - ALOGE("%s: Failed to initialize LE audio Call control Interface, status: %d", - __func__, status); - sCallControllerInterface = nullptr; - return; - } - - env->ReleaseStringUTFChars(uuid, _uuid); - mCallbacksObj = env->NewGlobalRef(object); -} - -static void cleanupNative(JNIEnv* env, jobject object) { - std::unique_lock interface_lock(interface_mutex); - std::unique_lock callbacks_lock(callbacks_mutex); - - const bt_interface_t* btInf = getBluetoothInterface(); - if (btInf == nullptr) { - LOG(ERROR) << "Bluetooth module is not loaded"; - return; - } - - if (sCallControllerInterface != nullptr) { - sCallControllerInterface->Cleanup(); - sCallControllerInterface = nullptr; - } - - if (mCallbacksObj != nullptr) { - env->DeleteGlobalRef(mCallbacksObj); - mCallbacksObj = nullptr; - } -} - -static jboolean updateBearerNameNative(JNIEnv* env, jobject object, - jstring operator_str) { - std::shared_lock lock(interface_mutex); - if (!sCallControllerInterface) { - ALOGW("%s: sCallControllerInterface is null", __func__); - return JNI_FALSE; - } - const char* operator_name = env->GetStringUTFChars(operator_str, nullptr); - bt_status_t status = - sCallControllerInterface->UpdateBearerName((uint8_t*)operator_name); - if (status != BT_STATUS_SUCCESS) { - ALOGE("Failed updateBearerNameNative, status: %d", status); - } - env->ReleaseStringUTFChars(operator_str, operator_name); - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static jboolean updateBearerTechnologyNative(JNIEnv* env, jobject object, - jint bearer_tech) { - std::shared_lock lock(interface_mutex); - if (!sCallControllerInterface) { - ALOGW("%s: sCallControllerInterface is null", __func__); - return JNI_FALSE; - } - bt_status_t status = sCallControllerInterface->UpdateBearerTechnology(bearer_tech); - if (status != BT_STATUS_SUCCESS) { - ALOGE("Failed updateBearerTechnologyNative, status: %d", status); - } - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static jboolean updateSupportedBearerListNative(JNIEnv* env, jobject object, - jstring bearer_list) { - std::shared_lock lock(interface_mutex); - if (!sCallControllerInterface) { - ALOGW("%s: sCallControllerInterface is null", __func__); - return JNI_FALSE; - } - const char* list_bearer_string = env->GetStringUTFChars(bearer_list, nullptr); - bt_status_t status = sCallControllerInterface->UpdateSupportedBearerList((uint8_t*)list_bearer_string); - if (status != BT_STATUS_SUCCESS) { - ALOGE("Failed updateSupportedBearerListNative, status: %d", status); - } - env->ReleaseStringUTFChars(bearer_list, list_bearer_string); - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - - -static jboolean callControlPointOpcodeSupportedNative(JNIEnv* env, jobject object, - jint feature) { - std::shared_lock lock(interface_mutex); - if (!sCallControllerInterface) { - ALOGW("%s: sCallControllerInterface is null", __func__); - return JNI_FALSE; - } - bt_status_t status = sCallControllerInterface->CallControlOptionalOpSupported(feature); - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static jboolean updateStatusFlagsNative(JNIEnv* env, jobject object, - jint flags) { - std::shared_lock lock(interface_mutex); - if (!sCallControllerInterface) { - ALOGW("%s: sCallControllerInterface is null", __func__); - return JNI_FALSE; - } - bt_status_t status = sCallControllerInterface->UpdateStatusFlags(flags); - - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static jboolean updateSignalStatusNative(JNIEnv* env, jobject object, - jint signal) { - std::shared_lock lock(interface_mutex); - if (!sCallControllerInterface) { - ALOGW("%s: sCallControllerInterface is null", __func__); - return JNI_FALSE; - } - bt_status_t status = sCallControllerInterface->UpdateSignalStatus(signal); - if (status != BT_STATUS_SUCCESS) { - ALOGE("FAILED updateSignalStatusNative, status: %d", status); - } - return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} -static jboolean updateIncomingCallNative(JNIEnv* env, jobject object, - jint index, jstring uri_str) { - std::shared_lock lock(interface_mutex); - if (!sCallControllerInterface) { - ALOGW("%s: sCallControllerInterface is null", __func__); - return JNI_FALSE; - } - const char* uri = env->GetStringUTFChars(uri_str, nullptr); - sCallControllerInterface->UpdateIncomingCall(index, (uint8_t*)uri); - env->ReleaseStringUTFChars(uri_str, uri); - return JNI_TRUE; -} - -static jboolean callControlResponseNative(JNIEnv* env, jobject object, - jint op, jint index, jint status, jbyteArray address) { - std::shared_lock lock(interface_mutex); - if (!sCallControllerInterface) { - ALOGW("%s: sCallControllerInterface is null", __func__); - return JNI_FALSE; - } - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - RawAddress* tmpraw = (RawAddress*)addr; - bt_status_t ret_status = - sCallControllerInterface->CallControlResponse(op, index, status, *tmpraw); - if (ret_status != BT_STATUS_SUCCESS) { - ALOGE("Failed to send callControlResponseNative, status: %d", ret_status); - } - return (ret_status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE; -} - -static jboolean setActiveDeviceNative(JNIEnv* env, jobject object, - jint set_id, jbyteArray address) { - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sCallControllerInterface) return JNI_FALSE; - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - RawAddress* tmpraw = (RawAddress*)addr; - sCallControllerInterface->SetActiveDevice(*tmpraw, set_id); - env->ReleaseByteArrayElements(address, addr, 0); - - return JNI_TRUE; -} - -static jboolean callStateNative(JNIEnv* env, jobject object, jint len, - jbyteArray callList) { - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - - jbyte* cList = env->GetByteArrayElements(callList, NULL); - if (!cList) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - uint16_t array_len = (uint16_t)env->GetArrayLength(callList); - - std::vector vect_val(cList, cList + array_len); - - if (!sCallControllerInterface) { - ALOGW("%s: sCallControllerInterface is null", __func__); - return JNI_FALSE; - } - sCallControllerInterface->CallState(len, std::move(vect_val)); - env->ReleaseByteArrayElements(callList, cList, 0); - return JNI_TRUE; -} - -static jboolean contentControlIdNative(JNIEnv* env, jobject object, - jint ccid) { - - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sCallControllerInterface) return JNI_FALSE; - - sCallControllerInterface->ContentControlId(ccid); - return JNI_TRUE; -} - -static jboolean disconnectNative(JNIEnv* env, jobject object, - jbyteArray address) { - - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sCallControllerInterface) return JNI_FALSE; - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - RawAddress* tmpraw = (RawAddress*)addr; - - sCallControllerInterface->Disconnect(*tmpraw); - env->ReleaseByteArrayElements(address, addr, 0); - return JNI_TRUE; -} - -static JNINativeMethod sMethods[] = { - {"classInitNative", "()V", (void*)classInitNative}, - {"initializeNative", "(Ljava/lang/String;IZ)V", (void*)initializeNative}, - {"cleanupNative", "()V", (void*)cleanupNative}, - {"updateBearerNameNative", "(Ljava/lang/String;)Z", (void*)updateBearerNameNative}, - {"updateBearerTechnologyNative", "(I)Z", (void*)updateBearerTechnologyNative}, - {"updateSupportedBearerListNative", "(Ljava/lang/String;)Z", (void*)updateSupportedBearerListNative}, - {"updateSignalStatusNative", "(I)Z", (void*)updateSignalStatusNative}, - {"updateStatusFlagsNative", "(I)Z", (void*)updateStatusFlagsNative}, - {"updateIncomingCallNative", "(ILjava/lang/String;)Z", (void*)updateIncomingCallNative}, - {"callControlResponseNative", "(III[B)Z", (void*)callControlResponseNative}, - {"callStateNative", "(I[B)Z", (void*)callStateNative}, - {"callControlPointOpcodeSupportedNative", "(I)Z", (void*)callControlPointOpcodeSupportedNative}, - {"setActiveDeviceNative", "(I[B)Z", (void*)setActiveDeviceNative}, - {"contentControlIdNative", "(I)Z", (void*)contentControlIdNative}, - {"disconnectNative", "([B)Z", (void*)disconnectNative}, -}; - -int register_com_android_bluetooth_call_controller(JNIEnv* env) { - return jniRegisterNativeMethods( - env, "com/android/bluetooth/cc/CCNativeInterface", - sMethods, NELEM(sMethods)); -} -} // namespace android diff --git a/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_csip_client.cpp b/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_csip_client.cpp deleted file mode 100644 index c3a8f6d68f6c884c116112280bd6d44b8b0efa27..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_csip_client.cpp +++ /dev/null @@ -1,409 +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. - * - ******************************************************************************/ - -#define LOG_TAG "BluetoothCsipClientJni" - -#define LOG_NDEBUG 0 - -#include "android_runtime/AndroidRuntime.h" -#include "com_android_bluetooth.h" -#include "hardware/bt_csip.h" -#include "utils/Log.h" - -#include -#include - -using bluetooth::Uuid; - -#define UUID_PARAMS(uuid) uuid_lsb(uuid), uuid_msb(uuid) - -static uint64_t uuid_lsb(const Uuid& uuid) { - uint64_t lsb = 0; - - auto uu = uuid.To128BitBE(); - for (int i = 8; i <= 15; i++) { - lsb <<= 8; - lsb |= uu[i]; - } - - return lsb; -} - -static uint64_t uuid_msb(const Uuid& uuid) { - uint64_t msb = 0; - - auto uu = uuid.To128BitBE(); - for (int i = 0; i <= 7; i++) { - msb <<= 8; - msb |= uu[i]; - } - - return msb; -} - -static Uuid from_java_uuid(jlong uuid_msb, jlong uuid_lsb) { - std::array uu{}; - for (int i = 0; i < 8; i++) { - uu[7 - i] = (uuid_msb >> (8 * i)) & 0xFF; - uu[15 - i] = (uuid_lsb >> (8 * i)) & 0xFF; - } - return Uuid::From128BitBE(uu); -} - -static RawAddress str2addr(JNIEnv* env, jstring address) { - RawAddress bd_addr; - const char* c_address = env->GetStringUTFChars(address, NULL); - if (!c_address) return bd_addr; - - RawAddress::FromString(std::string(c_address), bd_addr); - env->ReleaseStringUTFChars(address, c_address); - - return bd_addr; -} - -namespace android { -static jmethodID method_onCsipAppRegistered; -static jmethodID method_onConnectionStateChanged; -static jmethodID method_onNewSetFound; -static jmethodID method_onNewSetMemberFound; -static jmethodID method_onLockStatusChanged; -static jmethodID method_onLockAvailable; -static jmethodID method_onSetSirkChanged; -static jmethodID method_onSetSizeChanged; - -static const btcsip_interface_t* sBluetoothCsipInterface = NULL; -static jobject mCallbacksObj = NULL; -static std::shared_timed_mutex mCallbacks_mutex; - -static jstring bdaddr2newjstr(JNIEnv* env, const RawAddress* bda) { - char c_address[32]; - snprintf(c_address, sizeof(c_address), "%02X:%02X:%02X:%02X:%02X:%02X", - bda->address[0], bda->address[1], bda->address[2], bda->address[3], - bda->address[4], bda->address[5]); - - return env->NewStringUTF(c_address); -} - -static void classInitNative(JNIEnv* env, jclass clazz) { - method_onCsipAppRegistered = - env->GetMethodID(clazz, "onCsipAppRegistered", "(IIJJ)V"); - - method_onConnectionStateChanged = - env->GetMethodID(clazz, "onConnectionStateChanged", "(ILjava/lang/String;II)V"); - - method_onNewSetFound = - env->GetMethodID(clazz, "onNewSetFound", "(ILjava/lang/String;I[BJJZ)V"); - - method_onNewSetMemberFound = - env->GetMethodID(clazz, "onNewSetMemberFound", "(ILjava/lang/String;)V"); - - method_onLockStatusChanged = - env->GetMethodID(clazz, "onLockStatusChanged", "(IIII[Ljava/lang/String;)V"); - - method_onLockAvailable = - env->GetMethodID(clazz, "onLockAvailable", "(IILjava/lang/String;)V"); - - method_onSetSirkChanged = - env->GetMethodID(clazz, "onSetSirkChanged", "(I[BLjava/lang/String;)V"); - - method_onSetSizeChanged = - env->GetMethodID(clazz, "onSetSizeChanged", "(IILjava/lang/String;)V"); - - ALOGI("%s: succeeds", __func__); -} - -static void csip_app_registered_callback(uint8_t status, uint8_t app_id, - const bluetooth::Uuid& uuid){ - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid()) return; - - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onCsipAppRegistered, - status, app_id, UUID_PARAMS(uuid)); -} - -static void connection_state_changed_callback(uint8_t app_id, RawAddress& addr, - uint8_t state, uint8_t status){ - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid()) return; - - // address - ScopedLocalRef address(sCallbackEnv.get(), - bdaddr2newjstr(sCallbackEnv.get(), &addr)); - - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, - app_id, address.get(), state, status); -} - -static void new_set_found_callback(uint8_t set_id, RawAddress& bd_addr, uint8_t size, - uint8_t* sirk, const bluetooth::Uuid& p_srvc_uuid, - bool lock_support) { - ALOGI("%s: ", __func__); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid()) return; - - // address - ScopedLocalRef address(sCallbackEnv.get(), - bdaddr2newjstr(sCallbackEnv.get(), &bd_addr)); - - ALOGI("%s: new_set_found_callback: process sirk", __func__); - ScopedLocalRef jb(sCallbackEnv.get(), NULL); - jb.reset(sCallbackEnv->NewByteArray(16)); - sCallbackEnv->SetByteArrayRegion(jb.get(), 0, 16, (jbyte*)sirk); - - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNewSetFound, set_id, address.get(), - size, jb.get(), UUID_PARAMS(p_srvc_uuid), lock_support); -} - -static void new_set_member_found_cb(uint8_t set_id, RawAddress& bd_addr) { - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid()) return; - - // address - ScopedLocalRef address(sCallbackEnv.get(), - bdaddr2newjstr(sCallbackEnv.get(), &bd_addr)); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onNewSetMemberFound, set_id, address.get()); -} - -/** Callback for lock status changed event from stack - */ -static void lock_state_changed_callback(uint8_t app_id, uint8_t set_id, - uint8_t value, uint8_t status, - std::vector addr_list) { - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid()) return; - if (!mCallbacksObj) { - ALOGE("mCallbacksObj is NULL. Return."); - return; - } - - int i; - jstring bd_addr; - jobjectArray device_list; - jsize len = addr_list.size(); - device_list = sCallbackEnv->NewObjectArray( - len, sCallbackEnv->FindClass("java/lang/String"), 0); - - for(i = 0; i < len; i++) - { - bd_addr = sCallbackEnv->NewStringUTF(addr_list[i].ToString().c_str()); - sCallbackEnv->SetObjectArrayElement(device_list, i, bd_addr); - } - - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onLockStatusChanged, - app_id, set_id, value, status, device_list); -} - -/** Callback when lock is available on earlier denying set member - */ -static void lock_available_callback(uint8_t app_id, uint8_t set_id, - RawAddress& bd_addr) { - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid()) return; - if (!mCallbacksObj) { - ALOGE("mCallbacksObj is NULL. Return."); - return; - } - -// address - ScopedLocalRef address(sCallbackEnv.get(), - bdaddr2newjstr(sCallbackEnv.get(), &bd_addr)); - - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onLockAvailable, app_id, set_id, address.get()); -} - -/** Callback when size of coordinated set has been changed - */ -static void set_size_changed_callback(uint8_t set_id, uint8_t size, - RawAddress& bd_addr) { - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid()) return; - if (!mCallbacksObj) { - ALOGE("mCallbacksObj is NULL. Return."); - return; - } - - // address - ScopedLocalRef address(sCallbackEnv.get(), - bdaddr2newjstr(sCallbackEnv.get(), &bd_addr)); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSetSizeChanged, set_id, size, address.get()); -} - -/** Callback when SIRK of coordinated set has been changed - */ -static void set_sirk_changed_callback(uint8_t set_id, uint8_t* sirk, - RawAddress& bd_addr) { - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid()) return; - if (!mCallbacksObj) { - ALOGE("mCallbacksObj is NULL. Return."); - return; - } - - ScopedLocalRef jb(sCallbackEnv.get(), NULL); - jb.reset(sCallbackEnv->NewByteArray(24)); - sCallbackEnv->SetByteArrayRegion(jb.get(), 0, 24, (jbyte*)sirk); - - // address - ScopedLocalRef address(sCallbackEnv.get(), - bdaddr2newjstr(sCallbackEnv.get(), &bd_addr)); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSetSirkChanged, set_id, jb.get(), address.get()); -} - -static btcsip_callbacks_t sBluetoothCsipCallbacks = { - sizeof(sBluetoothCsipCallbacks), - csip_app_registered_callback, - connection_state_changed_callback, - new_set_found_callback, - new_set_member_found_cb, - lock_state_changed_callback, - lock_available_callback, - set_size_changed_callback, - set_sirk_changed_callback, -}; - -static void initNative(JNIEnv* env, jobject object) { - ALOGI("%s: initNative()", __func__); - - std::unique_lock lock(mCallbacks_mutex); - const bt_interface_t* btInf = getBluetoothInterface(); - if (btInf == NULL) { - ALOGE("Bluetooth module is not loaded"); - return; - } - - if (sBluetoothCsipInterface != NULL) { - ALOGW("Cleaning up Bluetooth CSIP CLIENT Interface before initializing..."); - sBluetoothCsipInterface->cleanup(); - sBluetoothCsipInterface = NULL; - } - - if (mCallbacksObj != NULL) { - ALOGW("Cleaning up Bluetooth CSIP callback object"); - env->DeleteGlobalRef(mCallbacksObj); - mCallbacksObj = NULL; - } - - sBluetoothCsipInterface = - (btcsip_interface_t*)btInf->get_profile_interface(BT_PROFILE_CSIP_CLIENT_ID); - if (sBluetoothCsipInterface == NULL) { - ALOGE("Failed to get Bluetooth CSIPInterface"); - return; - } - - bt_status_t status = sBluetoothCsipInterface->init(&sBluetoothCsipCallbacks); - if (status != BT_STATUS_SUCCESS) { - ALOGE("Failed to initialize Bluetooth CSIP Client, status: %d", status); - sBluetoothCsipInterface = NULL; - return; - } - - mCallbacksObj = env->NewGlobalRef(object); -} - -static void cleanupNative(JNIEnv* env, jobject object) { - ALOGI("%s: cleanupNative()", __func__); - if (!sBluetoothCsipInterface) return; - - sBluetoothCsipInterface->cleanup(); -} - -static jboolean connectSetDeviceNative(JNIEnv* env, jobject object, - jint app_id, jbyteArray address) { - if (!sBluetoothCsipInterface) return JNI_FALSE; - - ALOGI("%s: connectSetDeviceNative()", __func__); - jboolean ret = JNI_TRUE; - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - - RawAddress bd_addr; - bd_addr.FromOctets(reinterpret_cast(addr)); - sBluetoothCsipInterface->connect(app_id, &bd_addr); - return ret; -} - -static jboolean disconnectSetDeviceNative(JNIEnv* env, jobject object, - jint app_id, jbyteArray address) { - if (!sBluetoothCsipInterface) return JNI_FALSE; - - jboolean ret = JNI_TRUE; - ALOGI("%s: disconnectSetDeviceNative()", __func__); - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - - RawAddress bd_addr; - bd_addr.FromOctets(reinterpret_cast(addr)); - sBluetoothCsipInterface->disconnect(app_id, &bd_addr); - return ret; -} - -static void registerCsipAppNative(JNIEnv* env, jobject object, - jlong app_uuid_lsb, jlong app_uuid_msb) { - if (!sBluetoothCsipInterface) return; - - Uuid uuid = from_java_uuid(app_uuid_msb, app_uuid_lsb); - sBluetoothCsipInterface->register_csip_app(uuid); -} - -static void unregisterCsipAppNative(JNIEnv* env, jobject object, jint app_id) { - if (!sBluetoothCsipInterface) return; - - sBluetoothCsipInterface->unregister_csip_app(app_id); -} - -static void setLockValueNative(JNIEnv* env, jobject object, jint app_id, - jint set_id, jint value, jobjectArray devicesList) { - if (!sBluetoothCsipInterface) return; - - std::vector lock_list; - int listCount = env->GetArrayLength(devicesList); - for (int i=0; i < listCount; i++) { - jstring address = (jstring) (env->GetObjectArrayElement(devicesList, i)); - RawAddress bd_addr = str2addr(env, address); - lock_list.push_back(bd_addr); - env->DeleteLocalRef(address); - } - - sBluetoothCsipInterface->set_lock_value(app_id, set_id, value, lock_list); -} - -static JNINativeMethod sMethods[] = { - {"classInitNative", "()V", (void*)classInitNative}, - {"initNative", "()V", (void*)initNative}, - {"cleanupNative", "()V", (void*)cleanupNative}, - {"connectSetDeviceNative", "(I[B)Z", (void*)connectSetDeviceNative}, - {"disconnectSetDeviceNative", "(I[B)Z", (void*)disconnectSetDeviceNative}, - {"registerCsipAppNative", "(JJ)V", (void*)registerCsipAppNative}, - {"unregisterCsipAppNative", "(I)V", (void*)unregisterCsipAppNative}, - {"setLockValueNative", "(III[Ljava/lang/String;)V", (void*)setLockValueNative}, -}; - -int register_com_android_bluetooth_csip_client(JNIEnv* env) { - ALOGE("%s", __func__); - return jniRegisterNativeMethods( - env, "com/android/bluetooth/groupclient/GroupClientNativeInterface", - sMethods, NELEM(sMethods)); -} -} diff --git a/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_ext.h b/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_ext.h deleted file mode 100644 index c82146d7ba819c71aa5640a5471c84d6277b5194..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_ext.h +++ /dev/null @@ -1,44 +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. - * - ******************************************************************************/ - -#ifndef COM_ANDROID_BLUETOOTH_EXT -#define COM_ANDROID_BLUETOOTH_EXT - -namespace android { - -int register_com_android_bluetooth_bap_broadcast(JNIEnv* env); - -int register_com_android_bluetooth_acm(JNIEnv* env); - -int register_com_android_bluetooth_apm(JNIEnv* env); - -int register_com_android_bluetooth_csip_client(JNIEnv* env); - -int register_com_android_bluetooth_adv_audio_profiles(JNIEnv* env); - -int register_com_android_bluetooth_vcp_controller(JNIEnv* env); - -int register_com_android_bluetooth_pacs_client(JNIEnv* env); - -int register_com_android_bluetooth_mcp(JNIEnv* env); - -int register_com_android_bluetooth_call_controller(JNIEnv* env); -} - -#endif - diff --git a/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_mcp.cpp b/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_mcp.cpp deleted file mode 100644 index 5dc21227f4c97ca83068c82e8a637b9f063a2efb..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_mcp.cpp +++ /dev/null @@ -1,431 +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. - * - ******************************************************************************/ - - -#define LOG_TAG "BluetoothMCPService_jni" - -#define LOG_NDEBUG 0 - -#include -#include -#include -#include -#include -#include - - -#include "android_runtime/AndroidRuntime.h" -#include "base/logging.h" -#include "com_android_bluetooth.h" -#include "hardware/bt_mcp.h" -#include "hardware/bluetooth.h" - - - -using bluetooth::mcp_server::McpServerCallbacks; -using bluetooth::mcp_server::McpServerInterface; -using bluetooth::Uuid; -static McpServerInterface* sMcpServerInterface = nullptr; - - -namespace android { -static jmethodID method_OnConnectionStateChanged; -static jmethodID method_MediaControlPointChangedRequest; -static jmethodID method_TrackPositionChangedRequest; -static jmethodID method_PlayingOrderChangedRequest; - - -static std::shared_timed_mutex interface_mutex; - -static jobject mCallbacksObj = nullptr; -static std::shared_timed_mutex callbacks_mutex; - -class McpServerCallbacksImpl : public McpServerCallbacks { - public: - ~McpServerCallbacksImpl() = default; - - void OnConnectionStateChange(int state, const RawAddress& bd_addr) override { - LOG(INFO) << __func__; - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - ScopedLocalRef addr( - sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); - if (!addr.get()) { - LOG(ERROR) << "Failed to new jbyteArray bd addr for connection state"; - return; - } - sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), - (jbyte*)&bd_addr); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_OnConnectionStateChanged, - (jint)state, addr.get()); - } - - - void MediaControlPointChangeReq(uint8_t state, const RawAddress& bd_addr) override { - LOG(INFO) << __func__; - - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - - ScopedLocalRef addr( - sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); - if (!addr.get()) { - LOG(ERROR) << "Failed to new jbyteArray bd addr for connection state"; - return; - } - - sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), - (jbyte*)&bd_addr); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_MediaControlPointChangedRequest, - (jint)state, addr.get()); - } - - void TrackPositionChangeReq(int32_t position) override { - LOG(INFO) << __func__; - - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_TrackPositionChangedRequest, - (jint)position); - } - - void PlayingOrderChangeReq(uint32_t order) override { - LOG(INFO) << __func__; - - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_PlayingOrderChangedRequest, - (jint)order); - } -}; - - -static McpServerCallbacksImpl sMcpServerCallbacks; - -static void classInitNative(JNIEnv* env, jclass clazz) { - LOG(INFO) << __func__ << ": class init native"; - method_OnConnectionStateChanged = - env->GetMethodID(clazz, "OnConnectionStateChanged", "(I[B)V"); - LOG(INFO) << __func__ << ": class init native 1"; - method_MediaControlPointChangedRequest = - env->GetMethodID(clazz, "MediaControlPointChangedRequest", "(I[B)V"); - LOG(INFO) << __func__ << ": class init native 2"; - method_TrackPositionChangedRequest = - env->GetMethodID(clazz, "TrackPositionChangedRequest", "(I)V"); - method_PlayingOrderChangedRequest = - env->GetMethodID(clazz, "PlayingOrderChangedRequest", "(I)V"); - - LOG(INFO) << __func__ << ": succeeds"; -} - -// uuid not fixed -Uuid uuid = Uuid::FromString("00008fd1-0000-1000-8000-00805F9B34FB"); - -static void initNative(JNIEnv* env, jobject object) { - std::unique_lock interface_lock(interface_mutex); - std::unique_lock callbacks_lock(callbacks_mutex); - - const bt_interface_t* btInf = getBluetoothInterface(); - if (btInf == nullptr) { - LOG(ERROR) << "Bluetooth module is not loaded"; - return; - } - - if (sMcpServerInterface != nullptr) { - LOG(INFO) << "Cleaning up McpServer Interface before initializing..."; - sMcpServerInterface->Cleanup(); - sMcpServerInterface = nullptr; - } - - if (mCallbacksObj != nullptr) { - LOG(INFO) << "Cleaning up McpServer callback object"; - env->DeleteGlobalRef(mCallbacksObj); - mCallbacksObj = nullptr; - } - - if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) { - LOG(ERROR) << "Failed to allocate Global Ref for Mcp Controller Callbacks"; - return; - } - LOG(INFO) << "mcs callback initialized"; - sMcpServerInterface = (McpServerInterface* )btInf->get_profile_interface( - BT_PROFILE_MCP_ID); - if (sMcpServerInterface == nullptr) { - LOG(ERROR) << "Failed to get Bluetooth Hearing Aid Interface"; - return; - } - - sMcpServerInterface->Init(&sMcpServerCallbacks, uuid); -} - -static void cleanupNative(JNIEnv* env, jobject object) { - std::unique_lock interface_lock(interface_mutex); - std::unique_lock callbacks_lock(callbacks_mutex); - - const bt_interface_t* btInf = getBluetoothInterface(); - if (btInf == nullptr) { - LOG(ERROR) << "Bluetooth module is not loaded"; - return; - } - - if (sMcpServerInterface != nullptr) { - sMcpServerInterface->Cleanup(); - sMcpServerInterface = nullptr; - } - - if (mCallbacksObj != nullptr) { - env->DeleteGlobalRef(mCallbacksObj); - mCallbacksObj = nullptr; - } -} - - - -static jboolean mediaControlPointOpcodeSupportedNative(JNIEnv* env, jobject object, - jint feature) { - - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sMcpServerInterface) return JNI_FALSE; - - sMcpServerInterface->MediaControlPointOpcodeSupported(feature); - return JNI_TRUE; -} - -static jboolean mediaControlPointNative(JNIEnv* env, jobject object, - jint value) { - - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sMcpServerInterface) return JNI_FALSE; - - sMcpServerInterface->MediaControlPoint(value); - return JNI_TRUE; -} - -static jboolean mediaStateNative(JNIEnv* env, jobject object, - jint state) { - - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sMcpServerInterface) return JNI_FALSE; - - sMcpServerInterface->MediaState(state); - return JNI_TRUE; -} - -static jboolean mediaPlayerNameNative(JNIEnv* env, jobject object, - jstring playerName) { - - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sMcpServerInterface) return JNI_FALSE; - - - const char *nativeString = env->GetStringUTFChars(playerName, nullptr); - if (!nativeString) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - sMcpServerInterface->MediaPlayerName((uint8_t*)nativeString); - env->ReleaseStringUTFChars(playerName, nativeString); - return JNI_TRUE; -} - -static jboolean trackChangedNative(JNIEnv* env, jobject object, - jint status) { - - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sMcpServerInterface) return JNI_FALSE; - - sMcpServerInterface->TrackChanged((bool)status); - return JNI_TRUE; -} - -static jboolean trackPositionNative(JNIEnv* env, jobject object, - jint playPosition) { - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sMcpServerInterface) return JNI_FALSE; - - - sMcpServerInterface->TrackPosition(playPosition); - return JNI_TRUE; -} - -static jboolean trackDurationNative(JNIEnv* env, jobject object, - jint duration) { - - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sMcpServerInterface) return JNI_FALSE; - - sMcpServerInterface->TrackDuration(duration); - - return JNI_TRUE; -} - - - -static jboolean trackTitleNative(JNIEnv* env, jobject object, - jstring title) { - - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sMcpServerInterface) return JNI_FALSE; - - const char *nativeString = env->GetStringUTFChars(title, nullptr); - if (!nativeString) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - sMcpServerInterface->TrackTitle((uint8_t*)nativeString); - env->ReleaseStringUTFChars(title, nativeString); - return JNI_TRUE; -} - -static jboolean setActiveDeviceNative(JNIEnv* env, jobject object, - jint profile, jint set_id, - jbyteArray address) { - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sMcpServerInterface) return JNI_FALSE; - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - RawAddress bd_addr = RawAddress::kEmpty; - if (addr) { - bd_addr.FromOctets(reinterpret_cast(addr)); - } - if (bd_addr == RawAddress::kEmpty) { - LOG(INFO) << __func__ << " active device is null"; - } - - sMcpServerInterface->SetActiveDevice(bd_addr, set_id, profile); - env->ReleaseByteArrayElements(address, addr, 0); - return JNI_TRUE; -} - -static jboolean bondStateChangeNative(JNIEnv* env, jobject object, - jint state, jbyteArray address) { - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sMcpServerInterface) return JNI_FALSE; - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - RawAddress* tmpraw = (RawAddress*)addr; - - sMcpServerInterface->BondStateChange(*tmpraw, state); - env->ReleaseByteArrayElements(address, addr, 0); - return JNI_TRUE; -} - -static jboolean playingOrderSupportedNative(JNIEnv* env, jobject object, - jint order) { - - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sMcpServerInterface) return JNI_FALSE; - - sMcpServerInterface->PlayingOrderSupported(order); - - return JNI_TRUE; -} - -static jboolean playingOrderNative(JNIEnv* env, jobject object, - jint order) { - - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sMcpServerInterface) return JNI_FALSE; - - sMcpServerInterface->PlayingOrder(order); - - return JNI_TRUE; -} - -static jboolean contentControlIdNative(JNIEnv* env, jobject object, - jint ccid) { - - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sMcpServerInterface) return JNI_FALSE; - - sMcpServerInterface->ContentControlId(ccid); - return JNI_TRUE; -} - -static jboolean disconnectMcpNative(JNIEnv* env, jobject object, - jbyteArray address) { - - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sMcpServerInterface) return JNI_FALSE; - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - RawAddress* tmpraw = (RawAddress*)addr; - - sMcpServerInterface->DisconnectMcp(*tmpraw); - env->ReleaseByteArrayElements(address, addr, 0); - return JNI_TRUE; -} - -static JNINativeMethod sMethods[] = { - {"classInitNative", "()V", (void*)classInitNative}, - {"initNative", "()V", (void*)initNative}, - {"cleanupNative", "()V", (void*)cleanupNative}, - {"mediaStateNative", "(I)Z", (void*)mediaStateNative}, - {"mediaPlayerNameNative", "(Ljava/lang/String;)Z", (void*)mediaPlayerNameNative}, - {"mediaControlPointOpcodeSupportedNative", "(I)Z", (void*)mediaControlPointOpcodeSupportedNative}, - {"mediaControlPointNative", "(I)Z", (void*)mediaControlPointNative}, - {"trackChangedNative", "(I)Z", (void*)trackChangedNative}, - {"trackTitleNative", "(Ljava/lang/String;)Z", (void*)trackTitleNative}, - {"trackPositionNative", "(I)Z", (void*)trackPositionNative}, - {"trackDurationNative", "(I)Z", (void*)trackDurationNative}, - {"playingOrderSupportedNative", "(I)Z", (void*)playingOrderSupportedNative}, - {"playingOrderNative", "(I)Z", (void*)playingOrderNative}, - {"setActiveDeviceNative", "(II[B)Z", (void*)setActiveDeviceNative}, - {"contentControlIdNative", "(I)Z", (void*)contentControlIdNative}, - {"disconnectMcpNative", "([B)Z", (void*)disconnectMcpNative}, - {"bondStateChangeNative", "(I[B)Z", (void*)bondStateChangeNative}, -}; - - - -int register_com_android_bluetooth_mcp(JNIEnv* env) { - return jniRegisterNativeMethods( - env, "com/android/bluetooth/mcp/McpNativeInterface", - sMethods, NELEM(sMethods)); -} -} // namespace android - - diff --git a/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_pacs_client.cpp b/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_pacs_client.cpp deleted file mode 100644 index c65a5d09d20c428c0dea7182c5a297c3b14177c0..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_pacs_client.cpp +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - - * 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. - */ - -#define LOG_TAG "BluetoothPacsClienServiceJni" - -#define LOG_NDEBUG 0 - -#include "android_runtime/AndroidRuntime.h" -#include "base/logging.h" -#include "com_android_bluetooth.h" -#include "hardware/bt_pacs_client.h" - -#include -#include - -using bluetooth::bap::pacs::ConnectionState; -using bluetooth::bap::pacs::PacsClientInterface; -using bluetooth::bap::pacs::PacsClientCallbacks; - -namespace android { - -static jmethodID method_OnInitialized; -static jmethodID method_onConnectionStateChanged; -static jmethodID method_OnAudioContextAvailable; -static jmethodID method_onServiceDiscovery; - -static struct { - jclass clazz; - jmethodID constructor; - jmethodID getCodecType; - jmethodID getCodecPriority; - jmethodID getSampleRate; - jmethodID getBitsPerSample; - jmethodID getChannelMode; - jmethodID getCodecSpecific1; - jmethodID getCodecSpecific2; - jmethodID getCodecSpecific3; - jmethodID getCodecSpecific4; -} android_bluetooth_pacs_record; - -static PacsClientInterface* sPacsClientInterface = nullptr; -static std::shared_timed_mutex interface_mutex; - -static jobject mCallbacksObj = nullptr; -static std::shared_timed_mutex callbacks_mutex; - -class PacsClientCallbacksImpl : public PacsClientCallbacks { - public: - ~PacsClientCallbacksImpl() = default; - void OnInitialized(int status, - int client_id) override { - LOG(INFO) << __func__; - - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_OnInitialized, - (jint)status, (jint)client_id); - } - - void OnConnectionState(const RawAddress& bd_addr, - ConnectionState state) override { - LOG(INFO) << __func__; - - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - - ScopedLocalRef addr( - sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); - if (!addr.get()) { - LOG(ERROR) << "Failed to new jbyteArray bd addr for connection state"; - return; - } - - sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), - (jbyte*)&bd_addr); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, - addr.get(), (jint)state); - } - - void OnAudioContextAvailable(const RawAddress& bd_addr, - uint32_t available_contexts) override { - LOG(INFO) << __func__; - - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - - ScopedLocalRef addr( - sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); - if (!addr.get()) { - LOG(ERROR) << "Failed to new jbyteArray bd addr for available audio context"; - return; - } - - sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), - (jbyte*)&bd_addr); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_OnAudioContextAvailable, - addr.get(), (jint)available_contexts); - } - - void OnSearchComplete(int status, const RawAddress& address, - std::vector sink_pac_records, - std::vector src_pac_records, - uint32_t sink_locations, - uint32_t src_locations, - uint32_t available_contexts, - uint32_t supported_contexts) override { - - LOG(INFO) << __func__; - - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - - - jsize i = 0; - jobjectArray sink_pac_records_array = sCallbackEnv->NewObjectArray( - (jsize)sink_pac_records.size(), - android_bluetooth_pacs_record.clazz, nullptr); - for (auto const& cap : sink_pac_records) { - jobject capObj = sCallbackEnv->NewObject( - android_bluetooth_pacs_record.clazz, - android_bluetooth_pacs_record.constructor, - (jint)cap.codec_type, (jint)cap.codec_priority, (jint)cap.sample_rate, - (jint)cap.bits_per_sample, (jint)cap.channel_mode, - (jlong)cap.codec_specific_1, (jlong)cap.codec_specific_2, - (jlong)cap.codec_specific_3, (jlong)cap.codec_specific_4); - sCallbackEnv->SetObjectArrayElement(sink_pac_records_array, i++, capObj); - sCallbackEnv->DeleteLocalRef(capObj); - } - - i = 0; - jobjectArray src_pac_records_array = sCallbackEnv->NewObjectArray( - (jsize)src_pac_records.size(), - android_bluetooth_pacs_record.clazz, nullptr); - for (auto const& cap : src_pac_records) { - jobject capObj = sCallbackEnv->NewObject( - android_bluetooth_pacs_record.clazz, - android_bluetooth_pacs_record.constructor, - (jint)cap.codec_type, (jint)cap.codec_priority, (jint)cap.sample_rate, - (jint)cap.bits_per_sample, (jint)cap.channel_mode, - (jlong)cap.codec_specific_1, (jlong)cap.codec_specific_2, - (jlong)cap.codec_specific_3, (jlong)cap.codec_specific_4); - sCallbackEnv->SetObjectArrayElement(src_pac_records_array, i++, - capObj); - sCallbackEnv->DeleteLocalRef(capObj); - } - - ScopedLocalRef addr( - sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); - if (!addr.get()) { - LOG(ERROR) << "Failed to new jbyteArray bd addr"; - return; - } - - sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), - (jbyte*)&address); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onServiceDiscovery, - sink_pac_records_array, src_pac_records_array, (jint)sink_locations, - (jint)src_locations, (jint)available_contexts, (jint)supported_contexts, - (jint)status, addr.get()); - } -}; - -static PacsClientCallbacksImpl sPacsClientCallbacks; - -static void classInitNative(JNIEnv* env, jclass clazz) { - - jclass jniBluetoothCodecConfigClass = - env->FindClass("android/bluetooth/BluetoothCodecConfig"); - android_bluetooth_pacs_record.constructor = - env->GetMethodID(jniBluetoothCodecConfigClass, "", "(IIIIIJJJJ)V"); - android_bluetooth_pacs_record.getCodecType = - env->GetMethodID(jniBluetoothCodecConfigClass, "getCodecType", "()I"); - android_bluetooth_pacs_record.getCodecPriority = - env->GetMethodID(jniBluetoothCodecConfigClass, "getCodecPriority", "()I"); - android_bluetooth_pacs_record.getSampleRate = - env->GetMethodID(jniBluetoothCodecConfigClass, "getSampleRate", "()I"); - android_bluetooth_pacs_record.getBitsPerSample = - env->GetMethodID(jniBluetoothCodecConfigClass, "getBitsPerSample", "()I"); - android_bluetooth_pacs_record.getChannelMode = - env->GetMethodID(jniBluetoothCodecConfigClass, "getChannelMode", "()I"); - android_bluetooth_pacs_record.getCodecSpecific1 = env->GetMethodID( - jniBluetoothCodecConfigClass, "getCodecSpecific1", "()J"); - android_bluetooth_pacs_record.getCodecSpecific2 = env->GetMethodID( - jniBluetoothCodecConfigClass, "getCodecSpecific2", "()J"); - android_bluetooth_pacs_record.getCodecSpecific3 = env->GetMethodID( - jniBluetoothCodecConfigClass, "getCodecSpecific3", "()J"); - android_bluetooth_pacs_record.getCodecSpecific4 = env->GetMethodID( - jniBluetoothCodecConfigClass, "getCodecSpecific4", "()J"); - - method_OnInitialized = - env->GetMethodID(clazz, "OnInitialized", "(II)V"); - - method_onConnectionStateChanged = - env->GetMethodID(clazz, "onConnectionStateChanged", "([BI)V"); - - method_OnAudioContextAvailable = - env->GetMethodID(clazz, "OnAudioContextAvailable", "([BI)V"); - - method_onServiceDiscovery = - env->GetMethodID(clazz, "onServiceDiscovery", "([Landroid/bluetooth/BluetoothCodecConfig;" - "[Landroid/bluetooth/BluetoothCodecConfig;" - "IIIII[B)V"); - - LOG(INFO) << __func__ << ": succeeds"; -} - -static void initNative(JNIEnv* env, jobject object) { - std::unique_lock interface_lock(interface_mutex); - std::unique_lock callbacks_lock(callbacks_mutex); - - const bt_interface_t* btInf = getBluetoothInterface(); - if (btInf == nullptr) { - LOG(ERROR) << "Bluetooth module is not loaded"; - return; - } - - if (sPacsClientInterface != nullptr) { - LOG(INFO) << "Cleaning up PacsClient Interface before initializing..."; - sPacsClientInterface->Cleanup(0); - sPacsClientInterface = nullptr; - } - - if (mCallbacksObj != nullptr) { - LOG(INFO) << "Cleaning up PacsClient callback object"; - env->DeleteGlobalRef(mCallbacksObj); - mCallbacksObj = nullptr; - } - - if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) { - LOG(ERROR) << "Failed to allocate Global Ref for pacs client Callbacks"; - return; - } - - android_bluetooth_pacs_record.clazz = (jclass)env->NewGlobalRef( - env->FindClass("android/bluetooth/BluetoothCodecConfig")); - if (android_bluetooth_pacs_record.clazz == nullptr) { - ALOGE("%s: Failed to allocate Global Ref for BluetoothCodecConfig class", - __func__); - return; - } - - sPacsClientInterface = (PacsClientInterface*)btInf->get_profile_interface( - BT_PROFILE_PACS_CLIENT_ID); - if (sPacsClientInterface == nullptr) { - LOG(ERROR) << "Failed to get Bluetooth pacs client Interface"; - return; - } - - sPacsClientInterface->Init(&sPacsClientCallbacks); -} - -static void cleanupNative(JNIEnv* env, jobject object, jint client_id) { - std::unique_lock interface_lock(interface_mutex); - std::unique_lock callbacks_lock(callbacks_mutex); - - const bt_interface_t* btInf = getBluetoothInterface(); - if (btInf == nullptr) { - LOG(ERROR) << "Bluetooth module is not loaded"; - return; - } - - if (sPacsClientInterface != nullptr) { - sPacsClientInterface->Cleanup(client_id); - sPacsClientInterface = nullptr; - } - - if (mCallbacksObj != nullptr) { - env->DeleteGlobalRef(mCallbacksObj); - mCallbacksObj = nullptr; - } - env->DeleteGlobalRef(android_bluetooth_pacs_record.clazz); - android_bluetooth_pacs_record.clazz = nullptr; -} - -static jboolean connectPacsClientNative(JNIEnv* env, jobject object, - jint client_id, jbyteArray address) { - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sPacsClientInterface) return JNI_FALSE; - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - - RawAddress* tmpraw = (RawAddress*)addr; - sPacsClientInterface->Connect(client_id, *tmpraw); - env->ReleaseByteArrayElements(address, addr, 0); - return JNI_TRUE; -} - -static jboolean disconnectPacsClientNative(JNIEnv* env, jobject object, - jint client_id, jbyteArray address) { - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sPacsClientInterface) return JNI_FALSE; - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - - RawAddress* tmpraw = (RawAddress*)addr; - sPacsClientInterface->Disconnect(client_id, *tmpraw); - env->ReleaseByteArrayElements(address, addr, 0); - return JNI_TRUE; -} - -static jboolean startDiscoveryNative(JNIEnv* env, jobject object, - jint client_id, jbyteArray address) { - std::shared_lock lock(interface_mutex); - if (!sPacsClientInterface) return JNI_FALSE; - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - - RawAddress* tmpraw = (RawAddress*)addr; - sPacsClientInterface->StartDiscovery(client_id, *tmpraw); - env->ReleaseByteArrayElements(address, addr, 0); - return JNI_TRUE; -} - -static void GetAvailableAudioContextsNative(JNIEnv* env, jobject object, - jint client_id, jbyteArray address) { - std::shared_lock lock(interface_mutex); - if (!sPacsClientInterface) return; - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return; - } - - RawAddress* tmpraw = (RawAddress*)addr; - sPacsClientInterface->GetAvailableAudioContexts(client_id, *tmpraw); - env->ReleaseByteArrayElements(address, addr, 0); -} - - -static JNINativeMethod sMethods[] = { - {"classInitNative", "()V", (void*)classInitNative}, - {"initNative", "()V", (void*)initNative}, - {"cleanupNative", "(I)V", (void*)cleanupNative}, - {"connectPacsClientNative", "(I[B)Z", (void*)connectPacsClientNative}, - {"disconnectPacsClientNative", "(I[B)Z", (void*)disconnectPacsClientNative}, - {"startDiscoveryNative", "(I[B)Z", (void*)startDiscoveryNative}, - {"GetAvailableAudioContextsNative", "(I[B)Z", (void*)GetAvailableAudioContextsNative}, -}; - -int register_com_android_bluetooth_pacs_client(JNIEnv* env) { - return jniRegisterNativeMethods( - env, "com/android/bluetooth/pc/PacsClientNativeInterface", - sMethods, NELEM(sMethods)); -} -} // namespace android diff --git a/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_vcp_controller.cpp b/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_vcp_controller.cpp deleted file mode 100644 index 552fd8ad6be353a1002642e7dc56e1c0607ca727..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/jni/com_android_bluetooth_vcp_controller.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/* - *Copyright (c) 2020, The Linux Foundation. All rights reserved. - - * 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. - */ - -#define LOG_TAG "BluetoothVCPControllerJni" - -#define LOG_NDEBUG 0 - -#include "android_runtime/AndroidRuntime.h" -#include "base/logging.h" -#include "com_android_bluetooth.h" -#include "hardware/bt_vcp_controller.h" - -#include -#include - -using bluetooth::vcp_controller::ConnectionState; -using bluetooth::vcp_controller::VcpControllerCallbacks; -using bluetooth::vcp_controller::VcpControllerInterface; - -namespace android { -static jmethodID method_onConnectionStateChanged; -static jmethodID method_onVolumeStateChange; -static jmethodID method_onVolumeFlagsChange; - -static VcpControllerInterface* sVcpControllerInterface = nullptr; -static std::shared_timed_mutex interface_mutex; - -static jobject mCallbacksObj = nullptr; -static std::shared_timed_mutex callbacks_mutex; - -class VcpControllerCallbacksImpl : public VcpControllerCallbacks { - public: - ~VcpControllerCallbacksImpl() = default; - - void OnConnectionState(ConnectionState state, - const RawAddress& bd_addr) override { - LOG(INFO) << __func__; - - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - - ScopedLocalRef addr( - sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); - if (!addr.get()) { - LOG(ERROR) << "Failed to new jbyteArray bd addr for connection state"; - return; - } - - sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), - (jbyte*)&bd_addr); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onConnectionStateChanged, - (jint)state, addr.get()); - } - - - void OnVolumeStateChange(uint8_t volume, uint8_t mute, - const RawAddress& bd_addr) override { - LOG(INFO) << __func__; - - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - - ScopedLocalRef addr( - sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); - if (!addr.get()) { - LOG(ERROR) << "Failed to new jbyteArray bd addr for connection state"; - return; - } - - sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), - (jbyte*)&bd_addr); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVolumeStateChange, - (jint)volume, (jboolean)mute, addr.get()); - } - - void OnVolumeFlagsChange(uint8_t flags, - const RawAddress& bd_addr) override { - LOG(INFO) << __func__; - - std::shared_lock lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; - - ScopedLocalRef addr( - sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); - if (!addr.get()) { - LOG(ERROR) << "Failed to new jbyteArray bd addr for connection state"; - return; - } - - sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), - (jbyte*)&bd_addr); - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onVolumeFlagsChange, - (jint)flags, addr.get()); - } -}; - -static VcpControllerCallbacksImpl sVcpControllerCallbacks; - -static void classInitNative(JNIEnv* env, jclass clazz) { - method_onConnectionStateChanged = - env->GetMethodID(clazz, "onConnectionStateChanged", "(I[B)V"); - - method_onVolumeStateChange = - env->GetMethodID(clazz, "OnVolumeStateChange", "(II[B)V"); - - method_onVolumeFlagsChange = - env->GetMethodID(clazz, "OnVolumeFlagsChange", "(I[B)V"); - - LOG(INFO) << __func__ << ": succeeds"; -} - -static void initNative(JNIEnv* env, jobject object) { - std::unique_lock interface_lock(interface_mutex); - std::unique_lock callbacks_lock(callbacks_mutex); - - const bt_interface_t* btInf = getBluetoothInterface(); - if (btInf == nullptr) { - LOG(ERROR) << "Bluetooth module is not loaded"; - return; - } - - if (sVcpControllerInterface != nullptr) { - LOG(INFO) << "Cleaning up VcpController Interface before initializing..."; - sVcpControllerInterface->Cleanup(); - sVcpControllerInterface = nullptr; - } - - if (mCallbacksObj != nullptr) { - LOG(INFO) << "Cleaning up VcpController callback object"; - env->DeleteGlobalRef(mCallbacksObj); - mCallbacksObj = nullptr; - } - - if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) { - LOG(ERROR) << "Failed to allocate Global Ref for Vcp Controller Callbacks"; - return; - } - - sVcpControllerInterface = (VcpControllerInterface*)btInf->get_profile_interface( - BT_PROFILE_VOLUME_CONTROL_ID); - if (sVcpControllerInterface == nullptr) { - LOG(ERROR) << "Failed to get Bluetooth Hearing Aid Interface"; - return; - } - - sVcpControllerInterface->Init(&sVcpControllerCallbacks); -} - -static void cleanupNative(JNIEnv* env, jobject object) { - std::unique_lock interface_lock(interface_mutex); - std::unique_lock callbacks_lock(callbacks_mutex); - - const bt_interface_t* btInf = getBluetoothInterface(); - if (btInf == nullptr) { - LOG(ERROR) << "Bluetooth module is not loaded"; - return; - } - - if (sVcpControllerInterface != nullptr) { - sVcpControllerInterface->Cleanup(); - sVcpControllerInterface = nullptr; - } - - if (mCallbacksObj != nullptr) { - env->DeleteGlobalRef(mCallbacksObj); - mCallbacksObj = nullptr; - } -} - -static jboolean connectVcpNative(JNIEnv* env, jobject object, - jbyteArray address, jboolean isDirect) { - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sVcpControllerInterface) return JNI_FALSE; - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - - RawAddress* tmpraw = (RawAddress*)addr; - sVcpControllerInterface->Connect(*tmpraw, isDirect); - env->ReleaseByteArrayElements(address, addr, 0); - return JNI_TRUE; -} - -static jboolean disconnectVcpNative(JNIEnv* env, jobject object, - jbyteArray address) { - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sVcpControllerInterface) return JNI_FALSE; - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - - RawAddress* tmpraw = (RawAddress*)addr; - sVcpControllerInterface->Disconnect(*tmpraw); - env->ReleaseByteArrayElements(address, addr, 0); - return JNI_TRUE; -} - -static jboolean setAbsVolumeNative(JNIEnv* env, jobject object, - jint volume, jbyteArray address) { - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sVcpControllerInterface) return JNI_FALSE; - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - - RawAddress* tmpraw = (RawAddress*)addr; - sVcpControllerInterface->SetAbsVolume(volume, *tmpraw); - env->ReleaseByteArrayElements(address, addr, 0); - return JNI_TRUE; -} - -static jboolean muteNative(JNIEnv* env, jobject object, - jbyteArray address) { - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sVcpControllerInterface) return JNI_FALSE; - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - - RawAddress* tmpraw = (RawAddress*)addr; - sVcpControllerInterface->Mute(*tmpraw); - env->ReleaseByteArrayElements(address, addr, 0); - return JNI_TRUE; -} - -static jboolean unmuteNative(JNIEnv* env, jobject object, - jbyteArray address) { - LOG(INFO) << __func__; - std::shared_lock lock(interface_mutex); - if (!sVcpControllerInterface) return JNI_FALSE; - - jbyte* addr = env->GetByteArrayElements(address, nullptr); - if (!addr) { - jniThrowIOException(env, EINVAL); - return JNI_FALSE; - } - - RawAddress* tmpraw = (RawAddress*)addr; - sVcpControllerInterface->Unmute(*tmpraw); - env->ReleaseByteArrayElements(address, addr, 0); - return JNI_TRUE; -} - -static JNINativeMethod sMethods[] = { - {"classInitNative", "()V", (void*)classInitNative}, - {"initNative", "()V", (void*)initNative}, - {"cleanupNative", "()V", (void*)cleanupNative}, - {"connectVcpNative", "([BZ)Z", (void*)connectVcpNative}, - {"disconnectVcpNative", "([B)Z", (void*)disconnectVcpNative}, - {"setAbsVolumeNative", "(I[B)Z", (void*)setAbsVolumeNative}, - {"muteNative", "([B)Z", (void*)muteNative}, - {"unmuteNative", "([B)Z", (void*)unmuteNative}, -}; - -int register_com_android_bluetooth_vcp_controller(JNIEnv* env) { - return jniRegisterNativeMethods( - env, "com/android/bluetooth/vcp/VcpControllerNativeInterface", - sMethods, NELEM(sMethods)); -} -} // namespace android - diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/acm/AcmCodecConfig.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/acm/AcmCodecConfig.java deleted file mode 100644 index e7972e6370cf7a15818ae1d92a044366fb1ff73d..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/acm/AcmCodecConfig.java +++ /dev/null @@ -1,147 +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. - * - ******************************************************************************/ - - -package com.android.bluetooth.acm; - -import android.bluetooth.BluetoothCodecConfig; -import android.bluetooth.BluetoothCodecStatus; -import android.bluetooth.BluetoothDevice; -import android.content.Context; -import android.content.res.Resources; -import android.content.res.Resources.NotFoundException; -import android.os.SystemProperties; -import android.util.Log; -import com.android.bluetooth.R; -import com.android.bluetooth.btservice.AdapterService; - -import java.util.Arrays; -import java.util.Objects; -/* - * ACM Codec Configuration setup. - */ -class AcmCodecConfig { - private static final boolean DBG = true; - private static final String TAG = "AcmCodecConfig"; - static final int CONTEXT_TYPE_UNKNOWN = 0; - static final int CONTEXT_TYPE_MUSIC = 1; - static final int CONTEXT_TYPE_VOICE = 2; - static final int CONTEXT_TYPE_MUSIC_VOICE = 3; - - private Context mContext; - private AcmNativeInterface mAcmNativeInterface; - - private BluetoothCodecConfig[] mCodecConfigPriorities; - private int mAcmSourceCodecPriorityLC3 = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT; - - private int assigned_codec_length = 0; - AcmCodecConfig(Context context, AcmNativeInterface acmNativeInterface) { - mContext = context; - mAcmNativeInterface = acmNativeInterface; - mCodecConfigPriorities = assignCodecConfigPriorities(); - } - - BluetoothCodecConfig[] codecConfigPriorities() { - return mCodecConfigPriorities; - } - - void setCodecConfigPreference(BluetoothDevice device, - BluetoothCodecConfig newCodecConfig, - int contextType) { - //Objects.requireNonNull(codecStatus); - - /*// Check whether the codecConfig is selectable for this Bluetooth device. - BluetoothCodecConfig[] selectableCodecs = codecStatus.getCodecsSelectableCapabilities(); - if (!Arrays.asList(selectableCodecs).stream().anyMatch(codec -> - codec.isMandatoryCodec())) { - // Do not set codec preference to native if the selectableCodecs not contain mandatory - // codec. The reason could be remote codec negotiation is not completed yet. - Log.w(TAG, "setCodecConfigPreference: must have mandatory codec before changing."); - return; - } - if (!codecStatus.isCodecConfigSelectable(newCodecConfig)) { - Log.w(TAG, "setCodecConfigPreference: invalid codec " - + Objects.toString(newCodecConfig)); - return; - } - - // Check whether the codecConfig would change current codec config. - int prioritizedCodecType = getPrioitizedCodecType(newCodecConfig, selectableCodecs); - BluetoothCodecConfig currentCodecConfig = codecStatus.getCodecConfig(); - if (prioritizedCodecType == currentCodecConfig.getCodecType() - && (prioritizedCodecType != newCodecConfig.getCodecType() - || (currentCodecConfig.similarCodecFeedingParameters(newCodecConfig) - && currentCodecConfig.sameCodecSpecificParameters(newCodecConfig)))) { - // Same codec with same parameters, no need to send this request to native. - Log.w(TAG, "setCodecConfigPreference: codec not changed."); - return; - }*/ - - BluetoothCodecConfig[] codecConfigArray = new BluetoothCodecConfig[1]; - codecConfigArray[0] = newCodecConfig; - mAcmNativeInterface.setCodecConfigPreference(device, codecConfigArray, contextType, contextType); - } - - // Get the codec type of the highest priority of selectableCodecs and codecConfig. - private int getPrioitizedCodecType(BluetoothCodecConfig codecConfig, - BluetoothCodecConfig[] selectableCodecs) { - BluetoothCodecConfig prioritizedCodecConfig = codecConfig; - for (BluetoothCodecConfig config : selectableCodecs) { - if (prioritizedCodecConfig == null) { - prioritizedCodecConfig = config; - } - if (config.getCodecPriority() > prioritizedCodecConfig.getCodecPriority()) { - prioritizedCodecConfig = config; - } - } - return prioritizedCodecConfig.getCodecType(); - } - - // Assign the ACM Source codec config priorities - private BluetoothCodecConfig[] assignCodecConfigPriorities() { - Resources resources = mContext.getResources(); - if (resources == null) { - return null; - } - - int value; - mAcmSourceCodecPriorityLC3 = BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST; - - BluetoothCodecConfig codecConfig; - BluetoothCodecConfig[] codecConfigArray; - int codecCount = 0; - codecConfigArray = - new BluetoothCodecConfig[BluetoothCodecConfig.SOURCE_QVA_CODEC_TYPE_MAX]; - - codecConfig = new BluetoothCodecConfig.Builder() - .setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LC3) - .setCodecPriority(mAcmSourceCodecPriorityLC3) - .setSampleRate(BluetoothCodecConfig.SAMPLE_RATE_NONE) - .setBitsPerSample(luetoothCodecConfig.BITS_PER_SAMPLE_NONE) - .setChannelMode(BluetoothCodecConfig.CHANNEL_MODE_NONE) - .setCodecSpecific1(0) - .setCodecSpecific2(0) - .setCodecSpecific3(0) - .setCodecSpecific4(0) - .build(); - codecConfigArray[codecCount++] = codecConfig; - assigned_codec_length = codecCount; - return codecConfigArray; - } -} - diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/acm/AcmNativeInterface.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/acm/AcmNativeInterface.java deleted file mode 100644 index a7f24dcc6e8ab9ba3fd8363083e5c3195f134f45..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/acm/AcmNativeInterface.java +++ /dev/null @@ -1,238 +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. - * - ******************************************************************************/ - - -package com.android.bluetooth.acm; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothCodecConfig; -import android.bluetooth.BluetoothCodecStatus; -import android.bluetooth.BluetoothDevice; -import android.util.Log; -import java.util.List; - -import com.android.bluetooth.Utils; -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; - -/** - * ACM Native Interface to/from JNI. - */ -public class AcmNativeInterface { - private static final String TAG = "AcmNativeInterface"; - private static final boolean DBG = true; - private BluetoothAdapter mAdapter; - static final int CONTEXT_TYPE_UNKNOWN = 0; - static final int CONTEXT_TYPE_MUSIC = 1; - static final int CONTEXT_TYPE_VOICE = 2; - static final int CONTEXT_TYPE_MUSIC_VOICE = 3; - @GuardedBy("INSTANCE_LOCK") - private static AcmNativeInterface sInstance; - private static final Object INSTANCE_LOCK = new Object(); - - static { - classInitNative(); - } - - @VisibleForTesting - private AcmNativeInterface() { - mAdapter = BluetoothAdapter.getDefaultAdapter(); - if (mAdapter == null) { - Log.wtf(TAG, "No Bluetooth Adapter Available"); - } - } - - /** - * Get singleton instance. - */ - public static AcmNativeInterface getInstance() { - synchronized (INSTANCE_LOCK) { - if (sInstance == null) { - sInstance = new AcmNativeInterface(); - } - return sInstance; - } - } - - /** - * Initializes the native interface. - * - * @param maxConnectedAudioDevices maximum number of A2DP Sink devices that can be connected - * simultaneously - * @param codecConfigPriorities an array with the codec configuration - * priorities to configure. - */ - public void init(int maxConnectedAudioDevices, BluetoothCodecConfig[] codecConfigPriorities) { - initNative(maxConnectedAudioDevices, codecConfigPriorities); - } - - - /** - * Initiates ACM connection to a remote device. - * - * @param device the remote device - * @return true on success, otherwise false. - */ - public boolean connectAcm(BluetoothDevice device, int contextType, int profileType, int preferredContext) { - return connectAcmNative(getByteAddress(device), contextType, profileType, preferredContext); - } - - /** - * Disconnects ACM from a remote device. - * - * @param device the remote device - * @return true on success, otherwise false. - */ - public boolean disconnectAcm(BluetoothDevice device, int contextType) { - return disconnectAcmNative(getByteAddress(device), contextType); - } - - /** - * Sets a connected ACM group/remote as active. - * - * @param device the remote device - * @return true on success, otherwise false. - */ - public boolean setActiveDevice(BluetoothDevice device, int contextType) { - return setActiveDeviceNative(getByteAddress(device), contextType); - } - - /** - * Sends Start stream to remote group/remote for voice call. - * - * @param device the remote device - * @return true on success, otherwise false. - */ - public boolean startStream(BluetoothDevice device, int contextType) { - return startStreamNative(getByteAddress(device), contextType); - } - - /** - * Sends Stop stream to remote group/remote for voice call. - * - * @param device the remote device - * @return true on success, otherwise false. - */ - public boolean stopStream(BluetoothDevice device, int contextType) { - return stopStreamNative(getByteAddress(device), contextType); - } - - /** - * Sets the codec configuration preferences. - * - * @param device the remote Bluetooth device - * @param codecConfigArray an array with the codec configurations to - * configure. - * @return true on success, otherwise false. - */ - public boolean setCodecConfigPreference(BluetoothDevice device, BluetoothCodecConfig[] codecConfigArray, - int contextType, int preferredContext) { - return setCodecConfigPreferenceNative(getByteAddress(device), codecConfigArray, - contextType, preferredContext); - } - - public boolean ChangeCodecConfigPreference(BluetoothDevice device, - String message) { - return ChangeCodecConfigPreferenceNative(getByteAddress(device), message); - } - /** - * Cleanup the native interface. - */ - public void cleanup() { - cleanupNative(); - } - - 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(AcmStackEvent event) { - AcmService service = AcmService.getAcmService(); - if (service != null) { - service.messageFromNative(event); - } else { - Log.w(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. - - private void onConnectionStateChanged(byte[] address, int state, int contextType) { - AcmStackEvent event = - new AcmStackEvent(AcmStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - event.device = getDevice(address); - event.valueInt1 = state; - event.valueInt2 = contextType; - - if (DBG) { - Log.d(TAG, "onConnectionStateChanged: " + event); - } - sendMessageToService(event); - } - - private void onAudioStateChanged(byte[] address, int state, int contextType) { - AcmStackEvent event = new AcmStackEvent(AcmStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED); - event.device = getDevice(address); - event.valueInt1 = state; - event.valueInt2 = contextType; - - if (DBG) { - Log.d(TAG, "onAudioStateChanged: " + event); - } - sendMessageToService(event); - } - - private void onCodecConfigChanged(byte[] address, - BluetoothCodecConfig newCodecConfig, - BluetoothCodecConfig[] codecsLocalCapabilities, - BluetoothCodecConfig[] codecsSelectableCapabilities, int contextType) { - AcmStackEvent event = new AcmStackEvent(AcmStackEvent.EVENT_TYPE_CODEC_CONFIG_CHANGED); - event.device = getDevice(address); - event.codecStatus = new BluetoothCodecStatus(newCodecConfig, - codecsLocalCapabilities, - codecsSelectableCapabilities); - event.valueInt2 = contextType; - if (DBG) { - Log.d(TAG, "onCodecConfigChanged: " + event); - } - sendMessageToService(event); - } - - // Native methods that call into the JNI interface - private static native void classInitNative(); - private native void initNative(int maxConnectedAudioDevices, - BluetoothCodecConfig[] codecConfigPriorities); - private native boolean connectAcmNative(byte[] address, int contextType, int profileType, int preferredContext); - private native boolean disconnectAcmNative(byte[] address, int contextType); - private native boolean setActiveDeviceNative(byte[] address, int contextType); - private native boolean startStreamNative(byte[] address, int contextType); - private native boolean stopStreamNative(byte[] address, int contextType); - private native boolean setCodecConfigPreferenceNative(byte[] address, - BluetoothCodecConfig[] codecConfigArray, int contextType, int preferredContext); - private native boolean ChangeCodecConfigPreferenceNative(byte[] address, String Id); - private native void cleanupNative(); -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/acm/AcmService.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/acm/AcmService.java deleted file mode 100644 index ef264a11b8b1ba671c090c65386bebcd9d63b6e1..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/acm/AcmService.java +++ /dev/null @@ -1,1866 +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. - * - ******************************************************************************/ - - -package com.android.bluetooth.acm; - -import static android.Manifest.permission.BLUETOOTH_CONNECT; - -import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission; - -import android.bluetooth.BluetoothA2dp; -import android.bluetooth.BluetoothA2dp.OptionalCodecsPreferenceStatus; -import android.bluetooth.BluetoothA2dp.OptionalCodecsSupportStatus; -import android.bluetooth.BluetoothCodecConfig; -import android.bluetooth.BluetoothCodecStatus; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; -import android.bluetooth.BluetoothUuid; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.media.AudioManager; -import android.os.HandlerThread; -import android.os.Handler; -import android.os.Binder; -import android.os.IBinder; -import android.os.ParcelUuid; -import android.util.Log; -import android.os.Message; -import android.bluetooth.BluetoothGroupCallback; -import com.android.bluetooth.groupclient.GroupService; -import android.bluetooth.DeviceGroup; -import android.bluetooth.BluetoothDeviceGroup; -import com.android.bluetooth.apm.ActiveDeviceManagerService; -import com.android.bluetooth.apm.VolumeManager; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; -import android.os.SystemProperties; -import com.android.bluetooth.BluetoothMetricsProto; -import com.android.bluetooth.BluetoothStatsLog; -import com.android.bluetooth.Utils; -import android.bluetooth.BluetoothAdapter; -import com.android.bluetooth.apm.ApmConst; -import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.btservice.MetricsLogger; -import com.android.bluetooth.btservice.ProfileService; -import com.android.bluetooth.btservice.ServiceFactory; -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.ArrayUtils; -import java.util.Iterator; -import java.util.ArrayList; -import java.util.List; -import java.util.HashMap; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import com.android.bluetooth.vcp.VcpController; -/** - * Provides Bluetooth ACM profile, as a service in the Bluetooth application. - * @hide - */ -public class AcmService extends ProfileService { - private static final boolean DBG = true; - private static final String TAG = "AcmService"; - private String mAcmName; - public static final int ACM_AUDIO_UNICAST = 25; - public static final int INVALID_SET_ID = 0x10; - private static AcmService sAcmService; - private BluetoothAdapter mAdapter; - private AdapterService mAdapterService; - private HandlerThread mStateMachinesThread; - private static final int LOCK_RELEASED = 0; // (LOCK Released successfully) - private static final int LOCK_RELEASED_TIMEOUT = 1; // (LOCK Released by timeout) - private static final int ALL_LOCKS_ACQUIRED = 2; // (LOCK Acquired for all requested set members) - private static final int SOME_LOCKS_ACQUIRED_REASON_TIMEOUT = 3; // (Request timeout for some set members) - private static final int SOME_LOCKS_ACQUIRED_REASON_DISC = 4; // (Some of the set members were disconnected) - private static final int LOCK_DENIED = 5; // (Denied by one of the set members) - private static final int INVALID_REQUEST_PARAMS = 6; // (Upper layer provided invalid parameters) - private static final int LOCK_RELEASE_NOT_ALLOWED = 7; // (Response from remote (PTS)) - private static final int INVALID_VALUE = 8; - @VisibleForTesting - AcmNativeInterface mAcmNativeInterface; - @VisibleForTesting - ServiceFactory mFactory = new ServiceFactory(); - - static final int CONTEXT_TYPE_UNKNOWN = 0; - static final int CONTEXT_TYPE_MUSIC = 1; - static final int CONTEXT_TYPE_VOICE = 2; - static final int CONTEXT_TYPE_MUSIC_VOICE = 3; - static final int CONTEXT_TYPE_BROADCAST_AUDIO = 6; - - private AcmCodecConfig mAcmCodecConfig; - private final Object mAudioManagerLock = new Object(); - private final Object mBtLeaLock = new Object(); - private final Object mBtAcmLock = new Object(); - private String mLeaChannelMode = "stereo"; - private AudioManager mAudioManager; - @GuardedBy("mStateMachines") - private BluetoothDevice mGroupBdAddress = null; - private BluetoothDevice mActiveDevice = null; - private BluetoothDevice mActiveDeviceVoice = null; - private int mActiveDeviceProfile = 0; - private int mActiveDeviceVoiceProfile = 0; - private final ConcurrentMap mStateMachines = - new ConcurrentHashMap<>(); - private HashMap mAcmDevices = - new HashMap(); - - // Upper limit of all ACM devices: Bonded or Connected - private static final int MAX_ACM_STATE_MACHINES = 50; - // Upper limit of all ACM devices that are Connected or Connecting - private int mMaxConnectedAudioDevices = 1; - CsipManager mCsipManager = null; - boolean mIsCsipRegistered = false; - boolean mShoPend = false; - boolean mVoiceShoPend = false; - //volume - private int mAudioStreamMax; - private int mActiveDeviceLocalMediaVol; - private int mActiveDeviceLocalVoiceVol; - private boolean mActiveDeviceIsMuted; - private static final int VCP_MAX_VOL = 255; - private VcpController mVcpController; - - private BroadcastReceiver mBondStateChangedReceiver; - private final ReentrantReadWriteLock mAcmNativeInterfaceLock = new ReentrantReadWriteLock(); - public int mCsipAppId = -1; - - private static final int SET_EBMONO_CFG = 1; - private static final int SET_EBSTEREO_CFG = 2; - private static final int MonoCfg_Timeout = 3000; - private static final int StereoCfg_Timeout = 3000; - private Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) - { - synchronized(mBtLeaLock) { - switch (msg.what) { - case SET_EBMONO_CFG: - Log.d(TAG, "setparameters to Mono"); - synchronized (mAudioManagerLock) { - if(mAudioManager != null) - mAudioManager.setParameters("LEAMono=true"); - } - mLeaChannelMode = "mono"; - break; - case SET_EBSTEREO_CFG: - Log.d(TAG, "setparameters to stereo"); - synchronized (mAudioManagerLock) { - if(mAudioManager != null) - mAudioManager.setParameters("LEAMono=false"); - } - mLeaChannelMode = "stereo"; - break; - default: - break; - } - } - } - }; - - @Override - protected void create() { - Log.i(TAG, "create()"); - } - - @Override - protected boolean start() { - Log.i(TAG, "start()"); - String propValue; - - if (sAcmService != null) { - Log.w(TAG, "AcmService is already running"); - return true; - } - - // Step 1: Get AdapterService, AcmNativeInterface. - // None of them can be null. - mAdapter = BluetoothAdapter.getDefaultAdapter(); - mAdapterService = Objects.requireNonNull(AdapterService.getAdapterService(), - "AdapterService cannot be null when AcmService starts"); - mAcmNativeInterface = Objects.requireNonNull(AcmNativeInterface.getInstance(), - "AcmNativeInterface cannot be null when AcmService starts"); - - mAdapterService = Objects.requireNonNull(AdapterService.getAdapterService(), - "AdapterService cannot be null when StreamAudioService starts"); - - Log.i(TAG, "mAdapterService.isHostAdvAudioUnicastFeatureSupported() returned " - + mAdapterService.isHostAdvAudioUnicastFeatureSupported()); - Log.i(TAG, "mAdapterService.isHostAdvAudioStereoRecordingFeatureSupported() returned " - + mAdapterService.isHostAdvAudioStereoRecordingFeatureSupported()); - Log.i(TAG, "mAdapterService.isAdvUnicastAudioFeatEnabled() returned " - + mAdapterService.isAdvUnicastAudioFeatEnabled()); - - // SOC supports unicast, host supports unicast and stereo recording - if (mAdapterService.isHostAdvAudioUnicastFeatureSupported() && - mAdapterService.isHostAdvAudioStereoRecordingFeatureSupported() && - mAdapterService.isAdvUnicastAudioFeatEnabled()) { - - Log.i(TAG, "SOC supports unicast, host supports unicast, stereo recording"); - // set properties only if they are not set to allow user enable/disable - // the features explicitly - propValue = SystemProperties.get("persist.vendor.service.bt.bap.enable_ucast"); - - if (propValue == null || propValue.length() == 0 || !propValue.equals("false")) { - SystemProperties.set("persist.vendor.service.bt.bap.enable_ucast", "true"); - } else { - Log.i(TAG, "persist.vendor.service.bt.bap.enable_ucast is already set to " - + propValue); - } - - propValue = SystemProperties.get("persist.vendor.service.bt.recording_supported"); - if (propValue == null || propValue.length() == 0 || !propValue.equals("false")) { - SystemProperties.set("persist.vendor.service.bt.recording_supported", "true"); - Log.i(TAG, "persist.vendor.service.bt.recording_supported set to true"); - } else { - Log.i(TAG, "persist.vendor.service.bt.recording_supported is already set to " - + propValue); - } - } - - Log.i(TAG, "mAdapterService.isHostQHSFeatureSupported() returned " - + mAdapterService.isHostQHSFeatureSupported()); - - // SOC supports unicast, host supports unicast and QHS - if (mAdapterService.isHostAdvAudioUnicastFeatureSupported() && - mAdapterService.isHostQHSFeatureSupported() && - mAdapterService.isAdvUnicastAudioFeatEnabled()) { - - Log.i(TAG, "SOC supports unicast, host supports unicast, QHS"); - // set properties only if they are not set to allow user enable/disable - // the features explicitly - propValue = SystemProperties.get("persist.vendor.btstack.qhs_enable"); - - if (propValue == null || propValue.length() == 0 || !propValue.equals("false")) { - SystemProperties.set("persist.vendor.btstack.qhs_enable", "true"); - } else { - Log.i(TAG, "persist.vendor.service.bt.bap.enable_ucast is already set to " - + propValue); - } - } - - Log.i(TAG, "isHostAdvAudioLC3QFeatureSupported(): " - + mAdapterService.isHostAdvAudioLC3QFeatureSupported()); - - // SOC supports unicast, host supports unicast and LC3Q - if (mAdapterService.isHostAdvAudioUnicastFeatureSupported() && - mAdapterService.isHostAdvAudioLC3QFeatureSupported() && - mAdapterService.isAdvUnicastAudioFeatEnabled()) { - - Log.i(TAG, "host supports LC3Q"); - // set properties only if they are not set to allow user enable/disable - // the features explicitly - propValue = SystemProperties.get("persist.vendor.service.bt.is_lc3q_supported"); - - if (propValue == null || propValue.length() == 0 || !propValue.equals("false")) { - SystemProperties.set("persist.vendor.service.bt.is_lc3q_supported", "true"); - } else { - Log.i(TAG, "persist.vendor.service.bt.is_lc3q_supported is already set to " - + propValue); - } - } - - // Step 2: Get maximum number of connected audio devices - mMaxConnectedAudioDevices = mAdapterService.getMaxConnectedAudioDevices(); - Log.i(TAG, "Max connected audio devices set to " + mMaxConnectedAudioDevices); - - - String LeaChannelMode = SystemProperties.get("persist.vendor.btstack.Lea.defaultchannelmode"); - if (!LeaChannelMode.isEmpty() && "mono".equals(LeaChannelMode)) { - mLeaChannelMode = "mono"; - } - Log.d(TAG, "Default LEA ChannelMode: " + LeaChannelMode); - // Step 3: Start handler thread for state machines - mStateMachines.clear(); - mStateMachinesThread = new HandlerThread("AcmService.StateMachines"); - mStateMachinesThread.start(); - - // Step 4: Setup codec config - mAcmCodecConfig = new AcmCodecConfig(this, mAcmNativeInterface); - - if (mAdapterService.isAdvUnicastAudioFeatEnabled()) { - Log.d(TAG, "Initialize AcmNativeInterface"); - // Step 5: Initialize native interface - mAcmNativeInterface.init(mMaxConnectedAudioDevices, - mAcmCodecConfig.codecConfigPriorities()); - } - - // Step 6: Setup broadcast receivers - IntentFilter filter = new IntentFilter(); - filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); - mBondStateChangedReceiver = new BondStateChangedReceiver(); - registerReceiver(mBondStateChangedReceiver, filter); - synchronized (mAudioManagerLock) { - mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); - Objects.requireNonNull(mAudioManager, - "AudioManager cannot be null when AcmService starts"); - mAudioStreamMax = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); - } - // Step 7: Mark service as started - setAcmService(this); - - //step 8: Register CSIP module - mCsipManager = new CsipManager(); - - //step 9: Get Vcp Controller - mVcpController = VcpController.make(this); - Objects.requireNonNull(mVcpController, "mVcpController cannot be null when AcmService starts"); - return true; - } - - @Override - protected boolean stop() { - Log.i(TAG, "stop()"); - if (sAcmService == null) { - Log.w(TAG, "stop() called before start()"); - return true; - } - - // Step 9: do quit Vcp Controller - if (mVcpController != null) { - mVcpController.doQuit(); - } - - // Step 8: Mark service as stopped - setAcmService(null); - - unregisterReceiver(mBondStateChangedReceiver); - mBondStateChangedReceiver = null; - // Step 6: Cleanup native interface - mAcmNativeInterface.cleanup(); - mAcmNativeInterface = null; - - // Step 5: Clear codec config - mAcmCodecConfig = null; - - // Step 4: Destroy state machines and stop handler thread - synchronized (mStateMachines) { - for (AcmStateMachine sm : mStateMachines.values()) { - sm.doQuit(); - sm.cleanup(); - } - mStateMachines.clear(); - } - mStateMachinesThread.quitSafely(); - mStateMachinesThread = null; - - // Step 2: Reset maximum number of connected audio devices - mMaxConnectedAudioDevices = 1; - - // Step 1: Clear AdapterService, AcmNativeInterface, AudioManager - mAcmNativeInterface = null; - mAdapterService = null; - if (mAcmDevices != null) - mAcmDevices.clear(); - - mCsipManager.unregisterCsip(); - mCsipManager = null; - return true; - } - - @Override - protected void cleanup() { - Log.i(TAG, "cleanup()"); - } - - @Override - protected IProfileServiceBinder initBinder() { - return new AcmBinder(this); - } - - private class BluetoothAcmDevice { - private BluetoothDevice mGrpDevice; // group bd address - private int mState; - private int msetID; - - BluetoothAcmDevice(BluetoothDevice device, int state, int setID) { - mGrpDevice = device; - mState = state; - msetID = setID; - } - } - - private BluetoothDevice getAddressFromString(String address) { - return mAdapter.getRemoteDevice(address); - } - - public BluetoothDevice makeGroupBdAddress(BluetoothDevice device, int state, int setid) { - Log.i(TAG, " Set id : " + setid + " Num of connected acm devices: " + mAcmDevices.size()); - boolean setIdMatched = false; - if (setid == INVALID_SET_ID) { - Log.d(TAG, "Device is not part of any group"); - BluetoothAcmDevice acmDevice = new BluetoothAcmDevice(device, state, setid); - mAcmDevices.put(device, acmDevice); - mGroupBdAddress = acmDevice.mGrpDevice; - return mGroupBdAddress; - } - // BluetoothDevice bdaddr = null; - if (mAcmDevices == null) { - Log.d(TAG, "Hash Map is NULL"); - return mGroupBdAddress; - } - if (mAcmDevices.containsKey(device)) { - Log.d(TAG, "Device is available in Hash Map"); - BluetoothAcmDevice acmDevice = mAcmDevices.get(device); - mGroupBdAddress = acmDevice.mGrpDevice; - return mGroupBdAddress; - } - if (mAcmDevices.size() != 0) { - for (BluetoothDevice dm : mAcmDevices.keySet()) { - BluetoothAcmDevice d = mAcmDevices.get(dm); - if (d.msetID == setid) { - setIdMatched = true; - Log.d(TAG, "Device is part of same set ID"); - BluetoothAcmDevice acmDevice = new BluetoothAcmDevice(d.mGrpDevice, state, setid); - mAcmDevices.put(device, acmDevice); - mGroupBdAddress = acmDevice.mGrpDevice; - break; - } - } - } - if (!setIdMatched) { - Log.d(TAG, "create new group or device is not part of existing set ID"); - String address = "9E:8B:00:00:00:0"; - BluetoothDevice bdaddr = getAddressFromString(address + setid); - BluetoothAcmDevice acmDevice = new BluetoothAcmDevice(bdaddr, state, setid); - mAcmDevices.put(device, acmDevice); - mGroupBdAddress = bdaddr; - } - return mGroupBdAddress; - } - - public void handleAcmDeviceStateChange(BluetoothDevice device, int state, int setid) { - Log.d(TAG, "handleAcmDeviceStateChange: device: " + device + ", state: " + state - + " Set id : " + setid); - Log.i(TAG, " Num of connected ACM devices: " + mAcmDevices.size()); - boolean update = false; - if (device == null || mAcmDevices.size() == 0) - return; - BluetoothAcmDevice acmDevice = mAcmDevices.get(device); - //check if current active group address is same as this device group address - if (acmDevice != null && mGroupBdAddress != acmDevice.mGrpDevice) { - Log.d(TAG, "Inactive device is disconnected"); - update = true; - } - if (state == BluetoothProfile.STATE_DISCONNECTED) { - Log.d(TAG, "Remove Device from hash map"); - mAcmDevices.remove(device); - } else { - acmDevice.mState = state; - Log.d(TAG, "Update state"); - } - for (BluetoothDevice dm : mAcmDevices.keySet()) { - BluetoothAcmDevice d = mAcmDevices.get(dm); - if (d.msetID == setid) { - if (d.mState == BluetoothProfile.STATE_CONNECTED) { - update = true; - Log.d(TAG, "Atleast one member is connected"); - break; - } - } - } - if (!update) { - /*if (!mAcmNativeInterface.setActiveDevice(null, 0)) {//send unknown context type - Log.w(TAG, "setActiveDevice(null): Cannot remove active device in native layer"); - }*/ - } - } - - public static synchronized AcmService getAcmService() { - if (sAcmService == null) { - Log.w(TAG, "getAcmService(): service is null"); - return null; - } - if (!sAcmService.isAvailable()) { - Log.w(TAG, "getAcmService(): service is not available"); - return null; - } - return sAcmService; - } - - private static synchronized void setAcmService(AcmService instance) { - if (DBG) { - Log.d(TAG, "setAcmService(): set to: " + instance); - } - sAcmService = instance; - } - - public boolean connect(BluetoothDevice device, int contextType, - int profileType, int preferredContext) { - - if (DBG) { - Log.d(TAG, "connect(): " + device + " contextType: " + contextType - + " profileType: " + profileType + " preferredContext: " + preferredContext); - } - if (device.getAddress().contains("9E:8B:00:00:00")) { - Log.d(TAG, "Connect request for group"); - byte[] addrByte = Utils.getByteAddress(device); - int set_id = addrByte[5]; - List d = mCsipManager.getSetMembers(set_id); - if (d == null) { - Log.d(TAG, "No set member found"); - return false; - } - Iterator members = d.iterator(); - if (members != null) { - while (members.hasNext()) { - BluetoothDevice addr = members.next(); - Log.d(TAG, "connect member: " + addr); - synchronized (mStateMachines) { - if (!connectionAllowedCheckMaxDevices(addr)) { - // when mMaxConnectedAudioDevices is one, disconnect current device first. - if (mMaxConnectedAudioDevices == 1) { - List sinks = getDevicesMatchingConnectionStates( - new int[] {BluetoothProfile.STATE_CONNECTED, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTING}); - for (BluetoothDevice sink : sinks) { - if (sink.equals(addr)) { - Log.w(TAG, "Connecting to device " + addr + " : disconnect skipped"); - continue; - } - disconnect(sink, contextType); - } - } else { - Log.e(TAG, "Cannot connect to " + addr + " : too many connected devices"); - return false; - } - } - AcmStateMachine smConnect = getOrCreateStateMachine(addr); - if (smConnect == null) { - Log.e(TAG, "Cannot connect to " + addr + " : no state machine"); - return false; - } - Message msg = smConnect.obtainMessage(AcmStateMachine.CONNECT); - msg.obj = preferredContext; - msg.arg1 = contextType; - msg.arg2 = profileType; - smConnect.sendMessage(msg); - } - } - } - return true; - } - synchronized (mStateMachines) { - if (!connectionAllowedCheckMaxDevices(device)) { - // when mMaxConnectedAudioDevices is one, disconnect current device first. - if (mMaxConnectedAudioDevices == 1) { - List sinks = getDevicesMatchingConnectionStates( - new int[] {BluetoothProfile.STATE_CONNECTED, - BluetoothProfile.STATE_CONNECTING, - BluetoothProfile.STATE_DISCONNECTING}); - for (BluetoothDevice sink : sinks) { - if (sink.equals(device)) { - Log.w(TAG, "Connecting to device " + device + " : disconnect skipped"); - continue; - } - disconnect(sink, contextType); - } - } else { - Log.e(TAG, "Cannot connect to " + device + " : too many connected devices"); - return false; - } - } - AcmStateMachine smConnect = getOrCreateStateMachine(device); - if (smConnect == null) { - Log.e(TAG, "Cannot connect to " + device + " : no state machine"); - return false; - } - Message msg = smConnect.obtainMessage(AcmStateMachine.CONNECT); - msg.obj = preferredContext; - msg.arg1 = contextType; - msg.arg2 = profileType; - smConnect.sendMessage(msg); - return true; - } - } - - /** - * Disconnects Acm for the remote bluetooth device - * - * @param device is the device with which we would like to disconnect acm - * @return true if profile disconnected, false if device not connected over acm - */ - public boolean disconnect(BluetoothDevice device, int contextType) { - - if (DBG) { - Log.d(TAG, "disconnect(): " + device); - } - - if (device.getAddress().contains("9E:8B:00:00:00")) { - Log.d(TAG, "Disonnect request for group"); - byte[] addrByte = Utils.getByteAddress(device); - int set_id = addrByte[5]; - List d = mCsipManager.getSetMembers(set_id); - if (d == null) { - Log.d(TAG, "No set member found"); - return false; - } - Iterator members = d.iterator(); - if (members != null) { - while (members.hasNext()) { - BluetoothDevice addr = members.next(); - Log.d(TAG, "disconnect member: " + device); - synchronized (mStateMachines) { - AcmStateMachine sm = mStateMachines.get(addr); - if (sm == null) { - Log.e(TAG, "Ignored disconnect request for " + addr + " : no state machine"); - return false; - } - Message msg = sm.obtainMessage(AcmStateMachine.DISCONNECT); - msg.obj = contextType; - sm.sendMessage(msg); - } - } - return true; - } - } - synchronized (mStateMachines) { - AcmStateMachine sm = mStateMachines.get(device); - if (sm == null) { - Log.e(TAG, "Ignored disconnect request for " + device + " : no state machine"); - return false; - } - Message msg = sm.obtainMessage(AcmStateMachine.DISCONNECT); - msg.obj = contextType; - sm.sendMessage(msg); - return true; - } - } - - public List getConnectedDevices() { - - synchronized (mStateMachines) { - List devices = new ArrayList<>(); - for (AcmStateMachine sm : mStateMachines.values()) { - if (sm.isConnected()) { - devices.add(sm.getDevice()); - } - } - return devices; - } - } - - //check if it can be a list ? - public BluetoothDevice getCsipLockRequestedDevice() { - - synchronized (mStateMachines) { - BluetoothDevice device = null; - for (AcmStateMachine sm : mStateMachines.values()) { - if (sm.isCsipLockRequested()) { - device = sm.getDevice(); - } - } - return device; - } - } - - public boolean IsLockSupportAvailable(BluetoothDevice device) { - boolean isLockSupported = false; - /*int setId = mSetCoordinator.getRemoteSetId(device, ACM_UUID); - DeviceGroup set = mSetCoordinator.getDeviceGroup(setId); - isLockSupported = set.mLockSupport;*/ - //isLockSupported = mAdapterService.isCsipLockSupport(device); - Log.d(TAG, "Exclusive Access SupportAvaible for:" + device + "returns " + isLockSupported); - return isLockSupported; - } - - /** - * Check whether can connect to a peer device. - * The check considers the maximum number of connected peers. - * - * @param device the peer device to connect to - * @return true if connection is allowed, otherwise false - */ - private boolean connectionAllowedCheckMaxDevices(BluetoothDevice device) { - int connected = 0; - // Count devices that are in the process of connecting or already connected - synchronized (mStateMachines) { - for (AcmStateMachine sm : mStateMachines.values()) { - switch (sm.getConnectionState()) { - case BluetoothProfile.STATE_CONNECTING: - case BluetoothProfile.STATE_CONNECTED: - if (Objects.equals(device, sm.getDevice())) { - return true; // Already connected or accounted for - } - connected++; - break; - default: - break; - } - } - } - return (connected < mMaxConnectedAudioDevices); - } - - List getDevicesMatchingConnectionStates(int[] states) { - - List devices = new ArrayList<>(); - if (states == null) { - return devices; - } - final BluetoothDevice[] bondedDevices = mAdapterService.getBondedDevices(); - if (bondedDevices == null) { - return devices; - } - synchronized (mStateMachines) { - for (BluetoothDevice device : bondedDevices) { - /*if (!ArrayUtils.contains(mAdapterService.getRemoteUuids(device), - BluetoothUuid.ACM_SINK)) { - continue; - }*/ - int connectionState = BluetoothProfile.STATE_DISCONNECTED; - AcmStateMachine sm = mStateMachines.get(device); - if (sm != null) { - connectionState = sm.getConnectionState(); - } - for (int state : states) { - if (connectionState == state) { - devices.add(device); - break; - } - } - } - return devices; - } - } - - /** - * Get the list of devices that have state machines. - * - * @return the list of devices that have state machines - */ - @VisibleForTesting - List getDevices() { - List devices = new ArrayList<>(); - synchronized (mStateMachines) { - for (AcmStateMachine sm : mStateMachines.values()) { - devices.add(sm.getDevice()); - } - return devices; - } - } - - public int getConnectionState(BluetoothDevice device) { - - synchronized (mStateMachines) { - AcmStateMachine sm = mStateMachines.get(device); - if (sm == null) { - return BluetoothProfile.STATE_DISCONNECTED; - } - return sm.getConnectionState(); - } - } - - public int getCsipConnectionState(BluetoothDevice device) { - - synchronized (mStateMachines) { - AcmStateMachine sm = mStateMachines.get(device); - if (sm == null) { - return BluetoothProfile.STATE_DISCONNECTED; - } - return sm.getCsipConnectionState(); - } - } - - // Handle messages from native (JNI) to Java - void messageFromNative(AcmStackEvent stackEvent) { - Objects.requireNonNull(stackEvent.device, - "Device should never be null, event: " + stackEvent); - synchronized (mStateMachines) { - BluetoothDevice device = stackEvent.device; - AcmStateMachine sm = mStateMachines.get(device); - if (sm == null) { - if (stackEvent.type == AcmStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) { - switch (stackEvent.valueInt1) { - case AcmStackEvent.CONNECTION_STATE_CONNECTED: - case AcmStackEvent.CONNECTION_STATE_CONNECTING: - // Create a new state machine only when connecting to a device - if (!connectionAllowedCheckMaxDevices(device)) { - Log.e(TAG, "Cannot connect to " + device - + " : too many connected devices"); - return; - } - sm = getOrCreateStateMachine(device); - break; - default: - break; - } - } - } - if (sm == null) { - Log.e(TAG, "Cannot process stack event: no state machine: " + stackEvent); - return; - } - sm.sendMessage(AcmStateMachine.STACK_EVENT, stackEvent); - } - } - - private AcmStateMachine getOrCreateStateMachine(BluetoothDevice device) { - if (device == null) { - Log.e(TAG, "getOrCreateStateMachine failed: device cannot be null"); - return null; - } - synchronized (mStateMachines) { - AcmStateMachine sm = mStateMachines.get(device); - if (sm != null) { - return sm; - } - // Limit the maximum number of state machines to avoid DoS attack - if (mStateMachines.size() >= MAX_ACM_STATE_MACHINES) { - Log.e(TAG, "Maximum number of ACM state machines reached: " - + MAX_ACM_STATE_MACHINES); - return null; - } - if (DBG) { - Log.d(TAG, "Creating a new state machine for " + device); - } - sm = AcmStateMachine.make(device, this, mAcmNativeInterface, - mStateMachinesThread.getLooper()); - mStateMachines.put(device, sm); - return sm; - } - } - - private class BondStateChangedReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - if (!BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())) { - return; - } - int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, - BluetoothDevice.ERROR); - BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - Objects.requireNonNull(device, "ACTION_BOND_STATE_CHANGED with no EXTRA_DEVICE"); - bondStateChanged(device, state); - } - } - - /** - * Process a change in the bonding state for a device. - * - * @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}. - */ - @VisibleForTesting - void bondStateChanged(BluetoothDevice device, int bondState) { - if (DBG) { - 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) { - return; - } - synchronized (mStateMachines) { - AcmStateMachine sm = mStateMachines.get(device); - if (sm == null) { - return; - } - if (sm.getConnectionState() != BluetoothProfile.STATE_DISCONNECTED) { - return; - } - } - removeStateMachine(device); - } - - private void removeStateMachine(BluetoothDevice device) { - synchronized (mStateMachines) { - AcmStateMachine sm = mStateMachines.get(device); - if (sm == null) { - Log.w(TAG, "removeStateMachine: device " + device - + " does not have a state machine"); - return; - } - Log.i(TAG, "removeStateMachine: removing state machine for device: " + device); - sm.doQuit(); - sm.cleanup(); - mStateMachines.remove(device); - mAcmDevices.remove(device); - } - } - - void updateLeaChannelMode(int state, BluetoothDevice device) { - BluetoothDevice peerLeaDevice = null; - peerLeaDevice = getLeaPeerDevice(device); - if (peerLeaDevice == null) { - Log.d(TAG, "updateLeaChannelMode: peer device is NULL"); - return; - } - Log.d(TAG, "LeaChannelMode: " + mLeaChannelMode + "state: " + state); - synchronized(mBtLeaLock) { - if ("mono".equals(mLeaChannelMode)) { - if ((state == BluetoothA2dp.STATE_PLAYING) && (peerLeaDevice!= null) - && peerLeaDevice.isConnected() && isAcmPlayingMusic(peerLeaDevice)) { - Log.d(TAG, "updateLeaChannelMode: send delay message to set stereo "); - Message msg = mHandler.obtainMessage(SET_EBSTEREO_CFG); - mHandler.sendMessageDelayed(msg, StereoCfg_Timeout); - } else if (state == BluetoothA2dp.STATE_PLAYING) { - Log.d(TAG, "updateLeaChannelMode: setparameters to Mono"); - synchronized (mAudioManagerLock) { - if (mAudioManager != null) { - Log.d(TAG, "updateLeaChannelMode: Acquired mVariableLock"); - mAudioManager.setParameters("LeaChannelConfig=mono"); - } - } - Log.d(TAG, "updateLeaChannelMode: Released mVariableLock"); - } - if ((state == BluetoothA2dp.STATE_NOT_PLAYING) && - isAcmPlayingMusic(peerLeaDevice)) { - if (mHandler.hasMessages(StereoCfg_Timeout)) { - Log.d(TAG, "updateLeaChannelMode:remove delay message for stereo"); - mHandler.removeMessages(StereoCfg_Timeout); - } - } - } else if ("stereo".equals(mLeaChannelMode)) { - if ((state == BluetoothA2dp.STATE_PLAYING) && - (getConnectionState(peerLeaDevice) != BluetoothProfile.STATE_CONNECTED - || !isAcmPlayingMusic(peerLeaDevice))) { - Log.d(TAG, "updateLeaChannelMode: send delay message to set mono"); - Message msg = mHandler.obtainMessage(SET_EBMONO_CFG); - mHandler.sendMessageDelayed(msg, MonoCfg_Timeout); - } - if ((state == BluetoothA2dp.STATE_PLAYING) && isAcmPlayingMusic(peerLeaDevice)) { - if (mHandler.hasMessages(SET_EBMONO_CFG)) { - Log.d(TAG, "updateLeaChannelMode: remove delay message to set mono"); - mHandler.removeMessages(SET_EBMONO_CFG); - } - } - if ((state == BluetoothA2dp.STATE_NOT_PLAYING) && isAcmPlayingMusic(peerLeaDevice)) { - Log.d(TAG, "setparameters to Mono"); - synchronized (mAudioManagerLock) { - if (mAudioManager != null) - mAudioManager.setParameters("LeaChannelConfig=mono"); - } - mLeaChannelMode = "mono"; - } - } - } - } - - private BluetoothDevice getLeaPeerDevice(BluetoothDevice device) { - synchronized (mStateMachines) { - AcmStateMachine sm = mStateMachines.get(device); - if (sm == null) { - return null; - } - return sm.getPeerDevice(); - } - } - - public boolean isPeerDeviceConnected(BluetoothDevice device, int setid) { - boolean isConnected = false; - if (mAcmDevices.size() != 0) { - for (BluetoothDevice dm : mAcmDevices.keySet()) { - BluetoothAcmDevice d = mAcmDevices.get(dm); - if ((d.msetID == setid) && !Objects.equals(dm, device)) { - if (d.mState == BluetoothProfile.STATE_CONNECTED) { - isConnected = true; - Log.d(TAG, "At least one member is in connected state"); - break; - } - } - } - } - return isConnected; - } - - public boolean isPeerDeviceStreamingMusic(BluetoothDevice device, int setid) { - boolean isStreaming = false; - if (mAcmDevices.size() != 0) { - for (BluetoothDevice dm : mAcmDevices.keySet()) { - BluetoothAcmDevice d = mAcmDevices.get(dm); - if ((d.msetID == setid) && !Objects.equals(dm, device)) { - if (d.mState == BluetoothProfile.STATE_CONNECTED) { - synchronized (mBtAcmLock) { - AcmStateMachine sm = mStateMachines.get(dm); - if (sm == null) { - return false; - } - if (sm.isMusicPlaying()) { - isStreaming = true; - Log.d(TAG, "At least one member is streaming for music"); - break; - } - } - } - } - } - } - return isStreaming; - } - - public boolean isShoPendingStop() { - Log.d(TAG, "isShoPendingStop " + mShoPend); - return mShoPend; - } - - public void resetShoPendingStop() { - mShoPend = false; - } - - public boolean isVoiceShoPendingStop() { - Log.d(TAG, "isVoiceShoPendingStop " + mVoiceShoPend); - return mVoiceShoPend; - } - - public void resetVoiceShoPendingStop() { - mVoiceShoPend = false; - } - - public BluetoothDevice getVoiceActiveDevice() { - return mActiveDeviceVoice; - } - - public void removePeersFromBgWl(BluetoothDevice device, int setid) { - synchronized (mStateMachines) { - BluetoothDevice d = null; - List members = mCsipManager.getSetMembers(setid); - if (members == null) { - Log.d(TAG, "No set member found"); - return; - } - Iterator i = members.iterator(); - if (i != null) { - while (i.hasNext()) { - d = i.next(); - if (!(Objects.equals(d, device))) { - Log.d(TAG, "Device: " + d); - AcmStateMachine sm = mStateMachines.get(d); - if (sm == null) { - return; - } - sm.removeDevicefromBgWL(); - } - } - } - } - } - - public boolean isAcmPlayingMusic(BluetoothDevice device) { - if (DBG) { - Log.d(TAG, "isAcmPlayingMusic(" + device + ")"); - } - synchronized (mBtAcmLock) { - AcmStateMachine sm = mStateMachines.get(device); - if (sm == null) { - return false; - } - return sm.isMusicPlaying(); - } - } - - public boolean isAcmPlayingVoice(BluetoothDevice device) { - if (DBG) { - Log.d(TAG, "isAcmPlayingVoice(" + device + ")"); - } - synchronized (mBtAcmLock) { - AcmStateMachine sm = mStateMachines.get(device); - if (sm == null) { - return false; - } - return sm.isVoicePlaying(); - } - } - - public BluetoothDevice getGroup(BluetoothDevice device) { - Log.d(TAG, "Get group address for (" + device + ")"); - if (device.getAddress().contains("9E:8B:00:00:00")) { - Log.d(TAG, "Called for group address"); - return device; - } - BluetoothDevice dm = null; - - if (mAcmDevices != null) { - Log.d(TAG, "Hash Map is not NULL"); - BluetoothAcmDevice d = mAcmDevices.get(device); - if (d != null) - dm = d.mGrpDevice; - } - if (dm == null) { - Log.d(TAG, "Group address is NULL, make New"); - int Id = mCsipManager.getCsipSetId(device, null /*ACM_UUID*/); //TODO: UUID what to set ? - dm = makeGroupBdAddress(device, BluetoothProfile.STATE_DISCONNECTED, Id); - } - return dm; - } - - public int setActiveDevice(BluetoothDevice device, int contextType, int profileType, boolean playReq) { - - Log.d(TAG, "setActiveDevice: " + device + " contextType: " + contextType + " profileType: " + profileType + - " play req: " + playReq + " mActiveDeviceProfile: " + mActiveDeviceProfile+ " mActiveDeviceVoiceProfile: " + mActiveDeviceVoiceProfile); - - if (Objects.equals(device, mActiveDevice) && contextType == CONTEXT_TYPE_MUSIC && (mActiveDeviceProfile == profileType)) { - Log.e(TAG, "setActiveDevice(" + device + "): already set to active for media and profileType same as active profile"); - return ActiveDeviceManagerService.ALREADY_ACTIVE; - } - if (Objects.equals(device, mActiveDeviceVoice) && contextType == CONTEXT_TYPE_VOICE && (mActiveDeviceVoiceProfile == profileType)) { - Log.e(TAG, "setActiveDevice(" + device + "): already set to active for voice and profileType same as active profile"); - return ActiveDeviceManagerService.ALREADY_ACTIVE; - } - if (contextType == CONTEXT_TYPE_MUSIC) { - mShoPend = false; - if ((device == null) && (mActiveDevice != null)) { - if (mActiveDevice.getAddress().contains("9E:8B:00:00:00")) { - byte[] addrByte = Utils.getByteAddress(mActiveDevice); - int set_id = addrByte[5]; - List members = mCsipManager.getSetMembers(set_id); - if (members == null) { - Log.d(TAG, "No set member found"); - } - Iterator i = members.iterator(); - if (i != null) { - while (i.hasNext()) { - BluetoothDevice addr = i.next(); - Log.d(TAG, "isAcmPlayingMusic(addr) " + isAcmPlayingMusic(addr)); - if (isAcmPlayingMusic(addr)) { - mShoPend = true; - break; - } - } - } - } else { - Log.d(TAG, "TWM active device"); - mShoPend = isAcmPlayingMusic(mActiveDevice); - } - } - Log.d(TAG, "mShoPend " + mShoPend); - } else if (contextType == CONTEXT_TYPE_VOICE) { - mVoiceShoPend = false; - if (mActiveDeviceVoice != null) { - if (mActiveDeviceVoice.getAddress().contains("9E:8B:00:00:00")) { - byte[] addrByte = Utils.getByteAddress(mActiveDeviceVoice); - int set_id = addrByte[5]; - List members = mCsipManager.getSetMembers(set_id); - if (members == null) { - Log.d(TAG, "No set member found"); - } - Iterator i = members.iterator(); - if (i != null) { - while (i.hasNext()) { - BluetoothDevice addr = i.next(); - Log.d(TAG, "isAcmPlayingVoice(addr) " + isAcmPlayingVoice(addr)); - if (isAcmPlayingVoice(addr)) { - mVoiceShoPend = true; - break; - } - } - } - } else { - Log.d(TAG, "TWM active device"); - mVoiceShoPend = isAcmPlayingVoice(mActiveDeviceVoice); - } - } - Log.d(TAG, "mVoiceShoPend " + mVoiceShoPend); - } - Log.d(TAG, "old mActiveDevice: " + mActiveDevice + " & old mActiveDeviceVoice: " + mActiveDeviceVoice); - - if (setActiveDeviceAcm(device, contextType, profileType)) { - if (contextType == CONTEXT_TYPE_MUSIC) { - mActiveDevice = device; - mActiveDeviceProfile = profileType; - } else if (contextType == CONTEXT_TYPE_VOICE) { - mActiveDeviceVoice = device; - mActiveDeviceVoiceProfile = profileType; - } - Log.d(TAG, "new mActiveDevice: " + mActiveDevice + " & new mActiveDeviceVoice: " + mActiveDeviceVoice); - if(!playReq) { - if (mShoPend || mVoiceShoPend) { - Log.d(TAG, "setActiveDevice(" + device + "): returns with status " + ActiveDeviceManagerService.SHO_PENDING); - return ActiveDeviceManagerService.SHO_PENDING; - } else { - Log.d(TAG, "setActiveDevice(" + device + "): returns with status " + ActiveDeviceManagerService.SHO_SUCCESS); - return ActiveDeviceManagerService.SHO_SUCCESS; - } - } else { - Log.d(TAG, "setActiveDevice(" + device + "): returns with status " + ActiveDeviceManagerService.SHO_PENDING); - return ActiveDeviceManagerService.SHO_PENDING; - } - } - Log.d(TAG, "setActiveDevice(" + device + "): returns with status " + ActiveDeviceManagerService.SHO_FAILED); - mShoPend = false; - mVoiceShoPend = false; - return ActiveDeviceManagerService.SHO_FAILED; - } - - private boolean setActiveDeviceAcm(BluetoothDevice device, int contextType, int profileType) { - Log.d(TAG, "setActiveDeviceAcm: " + device); - try { - mAcmNativeInterfaceLock.readLock().lock(); - if (mAcmNativeInterface != null && !mAcmNativeInterface.setActiveDevice(device, profileType)) { - Log.e(TAG, "setActiveDevice(" + device + "): Cannot set as active in native layer"); - return false; - } - } finally { - mAcmNativeInterfaceLock.readLock().unlock(); - } - Log.d(TAG, "setActiveDeviceAcm(" + device + "): returns true"); - return true; - } - - public void setCodecConfigPreference(BluetoothDevice device, - BluetoothCodecConfig codecConfig, int contextType) { - - if (DBG) { - Log.d(TAG, "setCodecConfigPreference(" + device + "): " - + Objects.toString(codecConfig)); - } - mAcmCodecConfig.setCodecConfigPreference(device, codecConfig, contextType); - } - - public void ChangeCodecConfigPreference(BluetoothDevice device, - String mesg) { - - if (DBG) { - Log.d(TAG, "ChangeCodecConfigPreference " + device + "string: " + mesg); - } - if (device == null) - return; - mAcmName = mesg; - synchronized (mStateMachines) { - if (mAcmDevices.size() != 0) { - for (BluetoothDevice dm : mAcmDevices.keySet()) { - BluetoothAcmDevice d = mAcmDevices.get(dm); - if (Objects.equals(device, d.mGrpDevice)) { - if (d.mState == BluetoothProfile.STATE_CONNECTED) { - AcmStateMachine sm = getOrCreateStateMachine(dm); - if (sm == null) { - //TODO:handle this case - continue; - } - Message msg = sm.obtainMessage(AcmStateMachine.CODEC_CONFIG_CHANGED); - msg.obj = d.msetID; - sm.sendMessage(msg); - } - } - } - } - } - } - - public boolean StartStream(BluetoothDevice device, int contextType) { - if (DBG) { - Log.d(TAG, "startStream for " + device+ " context type: " + contextType); - } - if (device == null) - return false; - synchronized (mStateMachines) { - if (mAcmDevices.size() != 0) { - for (BluetoothDevice dm : mAcmDevices.keySet()) { - BluetoothAcmDevice d = mAcmDevices.get(dm); - if (Objects.equals(device, d.mGrpDevice)) { - if (d.mState == BluetoothProfile.STATE_CONNECTED) { - AcmStateMachine sm = getOrCreateStateMachine(dm); - if (sm == null) { - //TODO:handle this case - continue; - } - Message msg = sm.obtainMessage(AcmStateMachine.START_STREAM); - msg.obj = contextType; - sm.sendMessage(msg); - } - } - } - } - } - return true; - } - - public boolean StopStream(BluetoothDevice device, int contextType) { - if (DBG) { - Log.d(TAG, "stopStream for " + device+ " context type: " + contextType); - } - if (device == null) - return false; - synchronized (mStateMachines) { - if (mAcmDevices.size() != 0) { - for (BluetoothDevice dm : mAcmDevices.keySet()) { - BluetoothAcmDevice d = mAcmDevices.get(dm); - if (Objects.equals(device, d.mGrpDevice)) { - if (d.mState == BluetoothProfile.STATE_CONNECTED) { - AcmStateMachine sm = getOrCreateStateMachine(dm); - if (sm == null) { - //TODO:handle this case - continue; - } - Message msg = sm.obtainMessage(AcmStateMachine.STOP_STREAM); - msg.obj = contextType; - sm.sendMessage(msg); - } - } - } - } - } - return true; - } - - public void setAbsoluteVolume(BluetoothDevice grpAddr, int volumeLevel, int audioType) { - //Convert volume level to VCP level before sending. - int vcpVolume = convertToVcpVolume(volumeLevel); - BluetoothDevice activeDevice = null; - Log.d(TAG, "AudioVolumeLevel " + volumeLevel + " vcpVolume " + vcpVolume); - - if (audioType == ApmConst.AudioFeatures.MEDIA_AUDIO || - audioType == ApmConst.AudioFeatures.CALL_AUDIO) { - ActiveDeviceManagerService activeDeviceManager = - ActiveDeviceManagerService.get(this); - activeDevice = activeDeviceManager.getActiveDevice(audioType); - Log.d(TAG, "activeDevice " + activeDevice + " grpAddr " + grpAddr - + " audioType " + audioType); - if (!grpAddr.equals(activeDevice)) { - Log.e(TAG, "Ignore setAbsoluteVolume for inactive device"); - return; - } - } else if (audioType == ApmConst.AudioFeatures.BROADCAST_AUDIO) { - Log.d(TAG, "No active device, grpAddr " + grpAddr + " is broadcast device or group"); - } else { - Log.e(TAG, "Invalid audio type for set volume, ignore this request"); - return; - } - - if (audioType == ApmConst.AudioFeatures.MEDIA_AUDIO) { - mActiveDeviceLocalMediaVol = volumeLevel; - } else if (audioType == ApmConst.AudioFeatures.CALL_AUDIO) { - mActiveDeviceLocalVoiceVol = volumeLevel; - } - - if (grpAddr.getAddress().contains("9E:8B:00:00:00")) { - Log.d(TAG, "setAbsoluteVolume for group addr, send abs vol to all members"); - byte[] addrByte = Utils.getByteAddress(grpAddr); - int set_id = addrByte[5]; - List members = mCsipManager.getSetMembers(set_id); - if (members == null) { - Log.d(TAG, "No set member found"); - return; - } - Iterator i = members.iterator(); - if (i != null) { - while (i.hasNext()) { - BluetoothDevice addr = i.next(); - Log.d(TAG, "send vol to member: " + addr); - mVcpController.setAbsoluteVolume(addr, vcpVolume, audioType); - } - } - } else { - Log.d(TAG, "setAbsoluteVolume for single addr, send abs vol to " + grpAddr); - mVcpController.setAbsoluteVolume(grpAddr, vcpVolume, audioType); - } - } - - public void setMute(BluetoothDevice grpAddr, boolean enableMute) { - if (mActiveDevice == null) { - Log.d(TAG, "No active device set, this grpAddr " + grpAddr + " is broadcast group"); - } else { - Log.d(TAG, "mActiveDevice " + mActiveDevice + " grpAddr " + grpAddr); - } - - if (grpAddr.getAddress().contains("9E:8B:00:00:00")) { - Log.d(TAG, "setMute for group addr, send mute/unmute to all members"); - byte[] addrByte = Utils.getByteAddress(grpAddr); - int set_id = addrByte[5]; - List members = mCsipManager.getSetMembers(set_id); - if (members == null) { - Log.d(TAG, "No set member found"); - return; - } - Iterator i = members.iterator(); - if (i != null) { - while (i.hasNext()) { - BluetoothDevice addr = i.next(); - Log.d(TAG, "send setMute to member: " + addr); - mVcpController.setMute(addr, enableMute); - } - } - } else { - Log.d(TAG, "setMute for single addr, send mute/unmute to " + grpAddr); - mVcpController.setMute(grpAddr, enableMute); - } - } - - public void onVolumeStateChanged(BluetoothDevice device, int vol, int audioType) { - VolumeManager service = VolumeManager.get(); - //Get or Make group address - BluetoothDevice grpDev = getGroup(device); - - if (audioType == ApmConst.AudioFeatures.BROADCAST_AUDIO) { - Log.d(TAG, "volume notification for Broadcast audio"); - } else if (audioType == ApmConst.AudioFeatures.MEDIA_AUDIO) { - Log.d(TAG, "volume notification for Media audio"); - } else if (audioType == ApmConst.AudioFeatures.CALL_AUDIO) { - Log.d(TAG, "volume notification for Call audio"); - } else { - // remote volume change case - Log.d(TAG, "Volume change from remote: " + device + " vcp vol " + vol); - audioType = service.getActiveAudioType(device); - } - - //Convert vol - int audioVolume = convertToAudioStreamVolume(vol); - Log.d(TAG, "vcp vol " + vol + " audioVolume " + audioVolume); - - if (audioType == ApmConst.AudioFeatures.BROADCAST_AUDIO) { - Log.d(TAG, "update volume to APM for Broadcast audio"); - service.onVolumeChange(grpDev, audioVolume, audioType); - } else if (audioType == ApmConst.AudioFeatures.MEDIA_AUDIO) { - //Check if new vol is diff than active group vol - Log.d(TAG, "new vol: " + audioVolume + " mActiveDeviceLocalMediaVol: " + mActiveDeviceLocalMediaVol); - if (mActiveDeviceLocalMediaVol != audioVolume) { - Log.d(TAG, "new vol is different than mActiveDeviceLocalMediaVol update APM"); - service.onVolumeChange(grpDev, audioVolume, audioType); - mActiveDeviceLocalMediaVol = audioVolume; - } else { - Log.d(TAG, "local active media vol same as device new vol, ignore sending to APM"); - } - } else if (audioType == ApmConst.AudioFeatures.CALL_AUDIO) { - Log.d(TAG, "new vol: " + audioVolume + " mActiveDeviceLocalVoiceVol: " + mActiveDeviceLocalVoiceVol); - if (mActiveDeviceLocalVoiceVol != audioVolume) { - Log.d(TAG, "new vol is different than mActiveDeviceLocalVoiceVol update APM"); - service.onVolumeChange(grpDev, audioVolume, audioType); - mActiveDeviceLocalVoiceVol = audioVolume; - } else { - Log.d(TAG, "local active call vol same as device new vol, ignore sending to APM"); - } - } else { - Log.d(TAG, "No audio is streaming and is inactive device, ignore sending to APM"); - } - - //Check if this device is group device, then take lock (ignored for now) and update vol to other members as well. - applyVolToOtherMembers(device, mCsipManager.getCsipSetId(device, null /*ACM_UUID*/), vol, audioType); - } - - public void onMuteStatusChanged(BluetoothDevice device, boolean isMuted) { - VolumeManager service = VolumeManager.get(); - //Get or Make group address - BluetoothDevice grpDev = getGroup(device); - //default context type - int c_type = CONTEXT_TYPE_UNKNOWN; - - Log.d(TAG, "isMuted " + isMuted + " mActiveDeviceIsMuted " + mActiveDeviceIsMuted); - - if (!mVcpController.isBroadcastDevice(device) && ((mActiveDevice == null) || (mActiveDevice != grpDev))) { - Log.d(TAG, "unicast-mode, either Active device null or muteStatus changed for inactive device -- return"); - return; - } - - if ((mActiveDevice == null) || (mActiveDevice != grpDev)) { - Log.d(TAG, "No Active device or device is not active, seems in Broadcast mode"); - c_type = CONTEXT_TYPE_BROADCAST_AUDIO; - } else { - Log.d(TAG, "mActiveDevice " + mActiveDevice + " grpDev " + grpDev + " device " + device); - c_type = CONTEXT_TYPE_MUSIC; - } - - //Check if new mute state is diff than active group mute state - if (mActiveDeviceIsMuted != isMuted) { - Log.d(TAG, "new mute state is different than mActiveDeviceIsMuted update APM"); - service.onMuteStatusChange(grpDev, isMuted, CONTEXT_TYPE_MUSIC); - mActiveDeviceIsMuted = isMuted; - } else { - Log.d(TAG, "local active device mute state same as device new mute state, ignore sending to APM, but send to other members"); - } - - //Check if this device is group device, then take lock(ignored for now) and update mute state to other members as well. - applyMuteStateToOtherMembers(device, mCsipManager.getCsipSetId(device, null /*ACM_UUID*/), isMuted); - } - - public void setAbsVolSupport(BluetoothDevice device, boolean isAbsVolSupported, int initialVol) { - VolumeManager service = VolumeManager.get(); - //Get or Make group address - BluetoothDevice grpDev = getGroup(device); - if (grpDev == null) { - Log.d(TAG, "Group not created, return"); - return; - } - if ((mVcpController.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED) && isAbsVolSupported) { - if (!isVcpPeerDeviceConnected(device, mCsipManager.getCsipSetId(device, null /*ACM_UUID*/))) { - Log.d(TAG, "VCP Peer device not connected, this is 1st member, update support to APM "); - //get current vol from VCP and send to APM during connection. - Log.d(TAG, "VCP initialVol " + initialVol + " when connected device " + device); - Log.d(TAG, "Update APM with connection vol " + convertToAudioStreamVolume(initialVol)); - service.setAbsoluteVolumeSupport(grpDev, isAbsVolSupported, convertToAudioStreamVolume(initialVol), ApmConst.AudioProfiles.VCP); - - //get current mute state from VCP and sent to APM during connection. - Log.d(TAG, "VCP mute state " + mVcpController.isMute(device) + " when connected device " + device); - service.onMuteStatusChange(grpDev, mVcpController.isMute(device), CONTEXT_TYPE_MUSIC); - } else { - Log.d(TAG, "VCP Peer device connected, this is not 1st member, skip update to APM"); - } - } else if ((mVcpController.getConnectionState(device) == BluetoothProfile.STATE_DISCONNECTED) && !isAbsVolSupported) { - if (isVcpPeerDeviceConnected(device, mCsipManager.getCsipSetId(device, null /*ACM_UUID*/))) { - Log.d(TAG, "VCP Peer device connected, this is not last member, skip update to APM "); - } else { - Log.d(TAG, "VCP Peer device not connected, this is last member, update to APM"); - service.setAbsoluteVolumeSupport(grpDev, isAbsVolSupported, ApmConst.AudioProfiles.VCP); - } - } - } - - public boolean isVcpPeerDeviceConnected(BluetoothDevice device, int setid) { - boolean isVcpPeerConnected = false; - if (setid == INVALID_SET_ID) - return isVcpPeerConnected; - List members = mCsipManager.getSetMembers(setid); - if (members == null) { - Log.d(TAG, "No set member found"); - return isVcpPeerConnected; - } - Iterator i = members.iterator(); - if (i != null) { - while (i.hasNext()) { - BluetoothDevice addr = i.next(); - if (!Objects.equals(addr, device) && (mVcpController.getConnectionState(addr) == BluetoothProfile.STATE_CONNECTED)) { - isVcpPeerConnected = true; - Log.d(TAG, "At least one other vcp member is in connected state"); - break; - } - } - } - return isVcpPeerConnected; - } - - private int convertToAudioStreamVolume(int volume) { - // Rescale volume to match AudioSystem's volume - return (int) Math.round((double) volume * mAudioStreamMax / VCP_MAX_VOL); - } - - private int convertToVcpVolume(int volume) { - return (int) Math.ceil((double) volume * VCP_MAX_VOL / mAudioStreamMax); - } - - private void applyVolToOtherMembers(BluetoothDevice device, int setid, int volume, int audioType) { - if (setid == INVALID_SET_ID) - return; - List members = mCsipManager.getSetMembers(setid); - if (members == null) { - Log.d(TAG, "No set member found"); - return; - } - Iterator i = members.iterator(); - if (i != null) { - while (i.hasNext()) { - BluetoothDevice addr = i.next(); - if (!Objects.equals(addr, device)) { - Log.d(TAG, "send vol changed to addr " + addr); - mVcpController.setAbsoluteVolume(addr, volume, audioType); - } - } - } - } - - private void applyMuteStateToOtherMembers(BluetoothDevice device, int setid, boolean muteState) { - if (setid == INVALID_SET_ID) - return; - List members = mCsipManager.getSetMembers(setid); - if (members == null) { - Log.d(TAG, "No set member found"); - return; - } - Iterator i = members.iterator(); - if (i != null) { - while (i.hasNext()) { - BluetoothDevice addr = i.next(); - if (!Objects.equals(addr, device)) { - Log.d(TAG, "send mute state to addr " + addr); - mVcpController.setMute(addr, muteState); - } - } - } - } - - public int getVcpConnState(BluetoothDevice device) { - return mVcpController.getConnectionState(device); - } - - public int getVcpConnMode(BluetoothDevice device) { - return mVcpController.getConnectionMode(device); - } - - public boolean isVcpMute(BluetoothDevice device) { - return mVcpController.isMute(device); - } - - public String getAcmName() { - return mAcmName; - } - - private static class AcmBinder extends Binder implements IProfileServiceBinder { - AcmBinder(AcmService service) { - } - @Override - public void cleanup() { - } - } - - private BluetoothGroupCallback mBluetoothGroupCallback = new BluetoothGroupCallback() { - public void onGroupClientAppRegistered(int status, int appId) { - Log.d(TAG, "onGroupClientAppRegistered, status: " + status + "appId: " + appId); - if (status == 0) { - mCsipManager.updateAppId(appId); - mIsCsipRegistered = true; - } else { - Log.e(TAG, "DeviceGroup registeration failed, status:" + status); - } - } - - public void onConnectionStateChanged (int state, BluetoothDevice device) { - Log.d(TAG, "onConnectionStateChanged: Device: " + device + "state: " + state); - //notify statemachine about device connection state - synchronized (mStateMachines) { - AcmStateMachine sm = getOrCreateStateMachine(device); - Message msg = sm.obtainMessage(AcmStateMachine.CSIP_CONNECTION_STATE_CHANGED); - msg.obj = state; - sm.sendMessage(msg); - } - } - - public void onExclusiveAccessChanged (int setId, int value, int status, - List devices) { - Log.d(TAG, "onExclusiveAccessChanged: setId" + setId + devices + "status:" + status); - - //notify the statemachine about CSIP Lock status - switch (status) { - case ALL_LOCKS_ACQUIRED: { - synchronized (mStateMachines) { - for (BluetoothDevice device : devices) { - AcmStateMachine sm = getOrCreateStateMachine(device); - if (sm == null) { - //TODO:handle this case - continue; - } - Message msg = sm.obtainMessage(AcmStateMachine.CSIP_LOCK_STATUS_LOCKED); - msg.obj = setId; - msg.arg1 = value; - sm.sendMessage(msg); - } - } - break; - } - - case SOME_LOCKS_ACQUIRED_REASON_TIMEOUT: //check if need to handle separately - case SOME_LOCKS_ACQUIRED_REASON_DISC: { - BluetoothDevice mDevice = getCsipLockRequestedDevice(); - if (devices.contains(mDevice)) { - synchronized (mStateMachines) { - for (BluetoothDevice device : devices) { - AcmStateMachine sm = getOrCreateStateMachine(device); - if (sm == null) { - //TODO:handle this case - continue; - } - Message msg = sm.obtainMessage(AcmStateMachine.CSIP_LOCK_STATUS_PARTIAL_LOCK); - msg.obj = setId; - msg.arg1 = value; - sm.sendMessage(msg); - } - } - } else { - Log.d(TAG, "Exclusive access requested device is not present in list, release access for all devices"); - mCsipManager.setLock(setId, devices, mCsipManager.UNLOCK); - } - } break; - - case LOCK_DENIED: { - synchronized (mStateMachines) { - for (BluetoothDevice device : devices) { - AcmStateMachine sm = getOrCreateStateMachine(device); - if (sm == null) { - //TODO:handle this case - continue; - } - Message msg = sm.obtainMessage(AcmStateMachine.CSIP_LOCK_STATUS_DENIED); - msg.obj = setId; - msg.arg1 = value; - sm.sendMessage(msg); - } - } - } break; - - case LOCK_RELEASED: { - synchronized (mStateMachines) { - for (BluetoothDevice device : devices) { - AcmStateMachine sm = getOrCreateStateMachine(device); - if (sm == null) { - //TODO:handle this case - continue; - } - Message msg = sm.obtainMessage(AcmStateMachine.CSIP_LOCK_STATUS_RELEASED); - msg.obj = setId; - msg.arg1 = value; - sm.sendMessage(msg); - } - } - } break; - - case LOCK_RELEASED_TIMEOUT: { - synchronized (mStateMachines) { - for (BluetoothDevice device : devices) { - AcmStateMachine sm = getOrCreateStateMachine(device); - if (sm == null) { - //TODO:handle this case - continue; - } - Message msg = sm.obtainMessage(AcmStateMachine.CSIP_LOCK_STATUS_RELEASED); - msg.obj = setId; - msg.arg1 = value; - sm.sendMessage(msg); - } - } - } break; - - /*case INVALID_REQUEST_PARAMS: { - synchronized (mStateMachines) { - for (BluetoothDevice device : devices) { - AcmStateMachine sm = getOrCreateStateMachine(device); - if (sm == null) { - //TODO:handle this case - continue; - } - Message msg = sm.obtainMessage(AcmStateMachine.CSIP_LOCK_STATUS_INVALID_PARAM); - msg.obj = setId; - msg.arg1 = value; - sm.sendMessage(msg); - } - } - } break;*/ - - /*case LOCK_RELEASE_NOT_ALLOWED: { - synchronized (mStateMachines) { - for (BluetoothDevice device : devices) { - AcmStateMachine sm = getOrCreateStateMachine(device); - if (sm == null) { - //TODO:handle this case - continue; - } - Message msg = sm.obtainMessage(AcmStateMachine.CSIP_LOCK_STATUS_RELEASE); - msg.obj = setId; - msg.arg1 = value; - sm.sendMessage(msg); - } - } - } break;*/ - - case INVALID_VALUE: - break; - } - } - - //public void onSetMemberFound (int setId, BluetoothDevice device) { } - - //public void onSetDiscoveryStatusChanged (int setId, int status, int reason) { } - - //public void onLockAvailable (int setId, BluetoothDevice device) { } - - //public void onNewSetFound (int setId, BluetoothDevice device, UUID uuid) { } - - //public void onLockStatusFetched (int setId, int lockStatus) { } - }; - - public CsipManager getCsipManager(){ - return mCsipManager; - } - - class CsipManager { - public int LOCK = 0; - public int UNLOCK = 0; - - int mCsipAppid; - - CsipManager() { - LOCK = BluetoothDeviceGroup.ACCESS_GRANTED; - UNLOCK = BluetoothDeviceGroup.ACCESS_RELEASED; - - registerCsip(); - } - - CsipManager(BluetoothGroupCallback callbacks) { - LOCK = BluetoothDeviceGroup.ACCESS_GRANTED; - UNLOCK = BluetoothDeviceGroup.ACCESS_RELEASED; - - registerCsip(callbacks); - } - - void updateAppId(int id) { - mCsipAppid = id; - } - - int getAppId() { - return mCsipAppid; - } - - void registerCsip() { - GroupService mGroupService = GroupService.getGroupService(); - if(mGroupService != null) { - Log.i(TAG, "mGroupService is not null, register"); - mGroupService.registerGroupClientModule(mBluetoothGroupCallback); - } - } - - void registerCsip(BluetoothGroupCallback callbacks) { - GroupService mGroupService = GroupService.getGroupService(); - if(mGroupService != null) { - Log.i(TAG, "mGroupService is not null, register " + callbacks); - mGroupService.registerGroupClientModule(callbacks); - } - } - - void unregisterCsip() { - GroupService mGroupService = GroupService.getGroupService(); - if (mGroupService != null) - mGroupService.unregisterGroupClientModule(mCsipAppid); - } - - void connectCsip(BluetoothDevice device) { - GroupService mGroupService = GroupService.getGroupService(); - mGroupService.connect(mCsipAppid, device); - } - - void disconnectCsip(BluetoothDevice device) { - GroupService mGroupService = GroupService.getGroupService(); - mGroupService.disconnect(mCsipAppid, device); - } - - void setLock(int setId, List devices, int lockVal) { - GroupService mGroupService = GroupService.getGroupService(); - mGroupService.setLockValue(mCsipAppid, setId, devices, lockVal); - } - - DeviceGroup getCsipSet(int setId) { - GroupService mGroupService = GroupService.getGroupService(); - return mGroupService.getCoordinatedSet(setId); - } - - List getSetMembers(int setId) { - DeviceGroup set = getCsipSet(setId); - if(set != null) - return set.getDeviceGroupMembers(); - return null; - } - - int getCsipSetId(BluetoothDevice device, ParcelUuid uuid) { - GroupService mGroupService = GroupService.getGroupService(); - return mGroupService.getRemoteDeviceGroupId(device, uuid); - //return -1; - } - } -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/acm/AcmStackEvent.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/acm/AcmStackEvent.java deleted file mode 100644 index d2c39fbc552798310be9527238c9233a3a7d39f4..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/acm/AcmStackEvent.java +++ /dev/null @@ -1,144 +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. - * - ******************************************************************************/ - - -package com.android.bluetooth.acm; - -import android.bluetooth.BluetoothCodecStatus; -import android.bluetooth.BluetoothDevice; - -/** - * Stack event sent via a callback from JNI to Java, or generated - * internally by the ACM State Machine. - */ -public class AcmStackEvent { - // 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_AUDIO_STATE_CHANGED = 2; - public static final int EVENT_TYPE_CODEC_CONFIG_CHANGED = 3; - - // Do not modify without updating the HAL bt_acm.h files. - // Match up with btacm_connection_state_t enum of bt_acm.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 btacm_audio_state_t enum of bt_acm.h - static final int AUDIO_STATE_REMOTE_SUSPEND = 0; - static final int AUDIO_STATE_STOPPED = 1; - static final int AUDIO_STATE_STARTED = 2; - - // Match up with btacm_audio_state_t enum of bt_acm.h - static final int CONTEXT_TYPE_UNKNOWN = 0; - static final int CONTEXT_TYPE_MUSIC = 1; - static final int CONTEXT_TYPE_VOICE = 2; - static final int CONTEXT_TYPE_MUSIC_VOICE = 3; - - // Match up with btacm_audio_state_t enum of bt_acm.h - static final int PROFILE_TYPE_NONE = 0; - - public int type = EVENT_TYPE_NONE; - public BluetoothDevice device; - public int valueInt1 = 0; - public int valueInt2 = 0; - public BluetoothCodecStatus codecStatus; - - AcmStackEvent(int type) { - this.type = type; - } - - @Override - public String toString() { - // event dump - StringBuilder result = new StringBuilder(); - result.append("AcmStackEvent {type:" + eventTypeToString(type)); - result.append(", device:" + device); - result.append(", state:" + eventTypeValueIntToString(type, valueInt1)); - result.append(", context type:" + contextTypeValueIntToString(valueInt2)); - if (codecStatus != null) { - result.append(", codecStatus:" + codecStatus); - } - result.append("}"); - return result.toString(); - } - - private static String eventTypeToString(int type) { - switch (type) { - case EVENT_TYPE_NONE: - return "EVENT_TYPE_NONE"; - case EVENT_TYPE_CONNECTION_STATE_CHANGED: - return "EVENT_TYPE_CONNECTION_STATE_CHANGED"; - case EVENT_TYPE_AUDIO_STATE_CHANGED: - return "EVENT_TYPE_AUDIO_STATE_CHANGED"; - case EVENT_TYPE_CODEC_CONFIG_CHANGED: - return "EVENT_TYPE_CODEC_CONFIG_CHANGED"; - default: - return "EVENT_TYPE_UNKNOWN:" + type; - } - } - - 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; - case EVENT_TYPE_AUDIO_STATE_CHANGED: - switch (value) { - case AUDIO_STATE_REMOTE_SUSPEND: - return "REMOTE_SUSPEND"; - case AUDIO_STATE_STOPPED: - return "STOPPED"; - case AUDIO_STATE_STARTED: - return "STARTED"; - default: - break; - } - break; - default: - break; - } - return Integer.toString(value); - } - - private static String contextTypeValueIntToString(int value) { - switch (value) { - case CONTEXT_TYPE_UNKNOWN: - return "UNKNOWN"; - case CONTEXT_TYPE_MUSIC: - return "MEDIA"; - case CONTEXT_TYPE_VOICE: - return "CONVERSATIONAL"; - case CONTEXT_TYPE_MUSIC_VOICE: - return "MEDIA+CONVERSATIONAL"; - default: - return "UNKNOWN:" + value; - } - } -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/acm/AcmStateMachine.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/acm/AcmStateMachine.java deleted file mode 100644 index cb9b93fed389f313d56790f9f173b3e06807a794..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/acm/AcmStateMachine.java +++ /dev/null @@ -1,2359 +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. - * - ******************************************************************************/ - - -package com.android.bluetooth.acm; -//package com.android.bluetooth.apm; - -import android.bluetooth.BluetoothHeadset; -import android.bluetooth.BluetoothA2dp; -import android.bluetooth.BluetoothCodecConfig; -import android.bluetooth.BluetoothCodecStatus; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; -import android.content.Intent; -import android.os.Looper; -import android.os.Message; -import android.util.Log; -import com.android.internal.util.IState; -import com.android.bluetooth.BluetoothStatsLog; -import com.android.bluetooth.btservice.ProfileService; -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; -import java.util.UUID; -import android.bluetooth.BluetoothGattCallback; -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattService; -import android.bluetooth.BluetoothGattCharacteristic; -import android.bluetooth.BluetoothGattDescriptor; -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Scanner; -import android.os.SystemProperties; -import com.android.bluetooth.btservice.AdapterService; -import java.util.Objects; -import java.util.ArrayList; -import java.util.List; -import java.util.Iterator; -import com.android.bluetooth.apm.ApmConst; -import com.android.bluetooth.apm.StreamAudioService; -import com.android.bluetooth.vcp.VcpController; -import android.bluetooth.BluetoothVcp; - -final class AcmStateMachine extends StateMachine { - private static final boolean DBG = true; - private static final String TAG = "AcmStateMachine"; - private String mReconfig = ""; - public UUID uuid; - static final int CONNECT = 1; - static final int DISCONNECT = 2; - static final int CSIP_CONNECTION_STATE_CHANGED = 3; - static final int CSIP_LOCK_STATUS_LOCKED = 4; - static final int CSIP_LOCK_STATUS_PARTIAL_LOCK = 5; - static final int CSIP_LOCK_STATUS_DENIED = 6; - static final int CSIP_LOCK_STATUS_RELEASED = 7; - static final int CODEC_CONFIG_CHANGED = 8; - static final int GATT_CONNECTION_STATE_CHANGED = 9; - static final int GATT_CONNECTION_TIMEOUT = 10; - static final int START_STREAM = 11; - static final int STOP_STREAM = 12; - static final int START_STREAM_REQ = 13; - @VisibleForTesting - static final int STACK_EVENT = 101; - private static final int CONNECT_TIMEOUT = 201; - private static final int CSIP_LOCK_RELEASE_TIMEOUT = 301; - private static final int CSIP_LOCK_TIMEOUT = 401; - private static final int LE_AUDIO_AVAILABLE_LICENSED = 0x00000300; - static final int GATT_CONNECTION_TIMEOUT_MS = 30000; - static final int GATT_PEER_CONN_TIMEOUT = 8; - static final int GATT_CONN_FAILED_ESTABLISHED = 0x3E; - - @VisibleForTesting - static int sConnectTimeoutMs = 30000; // 30s - static int sCsipLockReleaseTimeoutMs = 5000; //TODO - static int sCsipLockTimeoutMs = 5000; - - private final int ACM_MAX_BYTES = 100; - - private final int CS_PARAM_NUM_BITS = 8; - private final int CS_PARAM_IND_MASK = 0xff; - private final int CS_PARAM_1ST_INDEX = 0x00; - private final int CS_PARAM_2ND_INDEX = 0x01; - private final int CS_PARAM_3RD_INDEX = 0x02; - private final int CS_PARAM_4TH_INDEX = 0x03; - private final int CS_PARAM_5TH_INDEX = 0x04; - private final int CS_PARAM_6TH_INDEX = 0x05; - private final int CS_PARAM_7TH_INDEX = 0x06; - private final int CS_PARAM_8TH_INDEX = 0x07; - - private final int CODEC_TYPE_LC3Q = 0x10; - - private static final String CODEC_NAME = "Codec"; - private static final String STREAM_MAP = "StreamMap"; - private static final String FRAME_DURATION = "FrameDuration"; - private static final String SDU_BLOCK = "Blocks_forSDU"; - private static final String RXCONFIG_INDX = "rxconfig_index"; - private static final String TXCONFIG_INDX = "txconfig_index"; - private static final String VERSION = "version"; - private static final String VENDOR_META_DATA = "vendor"; - private Disconnected mDisconnected; - private Connecting mConnecting; - private Disconnecting mDisconnecting; - private Connected mConnected; - private Streaming mStreaming; - private int mConnectionState = BluetoothProfile.STATE_DISCONNECTED; - private int mLastConnectionState = -1; - private int mMusicConnectionState = BluetoothProfile.STATE_DISCONNECTED; - private int mLastMusicConnectionState = -1; - private int mVoiceConnectionState = BluetoothProfile.STATE_DISCONNECTED; - private int mLastVoiceConnectionState = -1; - - private AcmService mAcmService; - - private AcmNativeInterface mAcmNativeInterface; - private BluetoothGatt mBluetoothGatt; - private final BluetoothDevice mDevice; - private BluetoothDevice mGroupAddress; - private boolean mIsMusicPlaying = false; - private boolean mIsVoicePlaying = false; - private VcpController mVcpController; - private BluetoothCodecStatus mMusicCodecStatus; - private BluetoothCodecStatus mVoiceCodecStatus; - - static final int CONTEXT_TYPE_UNKNOWN = 0; - static final int CONTEXT_TYPE_MUSIC = 1; - static final int CONTEXT_TYPE_VOICE = 2; - static final int CONTEXT_TYPE_MUSIC_VOICE = 3; - - private int mContextTypeToDisconnect = CONTEXT_TYPE_UNKNOWN; - private int mCurrentContextType = CONTEXT_TYPE_UNKNOWN; - private int mProfileType = 0; - private int mPreferredContext = CONTEXT_TYPE_UNKNOWN; - - private boolean IsDisconnectRequested = false; - private boolean IsReconfigRequested = false; - private int mCsipConnectionState = BluetoothProfile.STATE_DISCONNECTED; - private boolean mDeviceLocked = false; - private boolean mCsipLockRequested = false; - private boolean mIsDeviceWhitelisted = false; - private int mSetId; - private boolean mAcmMTUChangeRequested = false; - private int cached_state; - private boolean mIsUpdateProfDisConnection = false; - - AcmStateMachine(BluetoothDevice device, AcmService acmService, - AcmNativeInterface acmNativeInterface, Looper looper) { - super(TAG, looper); - setDbg(DBG); - mDevice = device; - mAcmService = acmService; - mAcmNativeInterface = acmNativeInterface; - - mDisconnected = new Disconnected(); - mConnecting = new Connecting(); - mDisconnecting = new Disconnecting(); - mConnected = new Connected(); - mStreaming = new Streaming(); - - addState(mDisconnected); - addState(mConnecting); - addState(mDisconnecting); - addState(mConnected); - addState(mStreaming); - - mCurrentContextType = CONTEXT_TYPE_UNKNOWN; - mDeviceLocked = false; - IsDisconnectRequested = false; - IsReconfigRequested = false; - mIsDeviceWhitelisted = false; - setInitialState(mDisconnected); - mSetId = -1; - cached_state = -1; - mAcmMTUChangeRequested = false; - mIsUpdateProfDisConnection = false; - - if (mBluetoothGatt != null) { - Log.e(TAG, "disconnect gatt"); - mBluetoothGatt.disconnect(); - mBluetoothGatt.close(); - mBluetoothGatt = null; - } - } - - static AcmStateMachine make(BluetoothDevice device, AcmService acmService, - AcmNativeInterface acmNativeInterface, Looper looper) { - Log.i(TAG, "make acm for device " + device); - AcmStateMachine acmSm = new AcmStateMachine(device, acmService, acmNativeInterface, - looper); - acmSm.start(); - return acmSm; - } - - public void doQuit() { - log("doQuit for device " + mDevice); - if (mIsMusicPlaying) { - // Stop if audio is still playing - log("doQuit: stopped Music playing " + mDevice); - mIsMusicPlaying = false; - StreamAudioService service = StreamAudioService.getStreamAudioService(); - if (service != null) - service.onStreamStateChange(mDevice, BluetoothA2dp.STATE_NOT_PLAYING, CONTEXT_TYPE_MUSIC); - } - if (mIsVoicePlaying) { - log("doQuit: stopped voice streaming " + mDevice); - mIsVoicePlaying = false; - StreamAudioService service = StreamAudioService.getStreamAudioService(); - if (service != null) - service.onStreamStateChange(mDevice, BluetoothA2dp.STATE_NOT_PLAYING, ApmConst.AudioFeatures.CALL_AUDIO); - } - quitNow(); - } - - public void cleanup() { - log("cleanup for device " + mDevice); - if (mBluetoothGatt != null) { - Log.e(TAG, "disconnect gatt"); - mBluetoothGatt.disconnect(); - mBluetoothGatt.close(); - mBluetoothGatt = null; - } - } - - private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { - @Override - public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { - Log.i(TAG, "onConnectionStateChange: Status: " + status + " newState: " + newState); - if (status == BluetoothGatt.GATT_SUCCESS /* || status == 0x16 */) { - if (newState == BluetoothProfile.STATE_CONNECTED) { - mBluetoothGatt.requestMtu(ACM_MAX_BYTES); - mAcmMTUChangeRequested = true; - cached_state = newState; - } else { - if (mAcmMTUChangeRequested == true) { - mAcmMTUChangeRequested = false; - } - - if (cached_state != -1) { - cached_state = -1; - } - - Message m = obtainMessage(GATT_CONNECTION_STATE_CHANGED); - m.obj = newState; - sendMessage(m); - } - } else if (status == GATT_PEER_CONN_TIMEOUT || - status == GATT_CONN_FAILED_ESTABLISHED) { - BluetoothDevice target = gatt.getDevice(); - Log.i(TAG, "[ACM] remote side disconnection, for device add in BG WL: " +target); - mBluetoothGatt.close(); - mBluetoothGatt = target.connectGatt(mAcmService, true, mGattCallback, - BluetoothDevice.TRANSPORT_LE, false, (BluetoothDevice.PHY_LE_1M_MASK | - BluetoothDevice.PHY_LE_2M_MASK | BluetoothDevice.PHY_LE_CODED_MASK), - null, true); - mIsDeviceWhitelisted = true; - } else { - mBluetoothGatt.close(); - mBluetoothGatt = null; - Log.i(TAG, "[ACM] Failed to connect GATT server."); - } - } - - @Override - public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { - log("onMtuChanged: mtu: " + mtu + - " mAcmMTUChangeRequested: " + mAcmMTUChangeRequested + - " cached_state: " + cached_state); - if (mAcmMTUChangeRequested == true) { - if (cached_state != -1) { - Message m = obtainMessage(GATT_CONNECTION_STATE_CHANGED); - m.obj = cached_state; - sendMessage(m); - mAcmMTUChangeRequested = false; - cached_state = -1; - } - } else { - log("onMtuChanged: Remote initiated trigger"); - //Do nothing - } - } - }; - - @VisibleForTesting - class Disconnected extends State { - @Override - public void enter() { - //Disconnect unicast VCP 1st - mVcpController = VcpController.getVcpController(); - if (mVcpController != null) { - Log.d(TAG, "Disconnect VCP for " + mDevice); - mVcpController.disconnect(mDevice, BluetoothVcp.MODE_UNICAST); - } else { - Log.d(TAG, "mVcpController is null"); - } - - Message currentMessage = getCurrentMessage(); - Log.i(TAG, "Enter Disconnected(" + mDevice + "): " + (currentMessage == null ? "null" - : messageWhatToString(currentMessage.what))); - synchronized (this) { - mConnectionState = BluetoothProfile.STATE_DISCONNECTED; - mMusicConnectionState = BluetoothProfile.STATE_DISCONNECTED; - mVoiceConnectionState = BluetoothProfile.STATE_DISCONNECTED; - } - removeDeferredMessages(DISCONNECT); - removeMessages(CSIP_LOCK_RELEASE_TIMEOUT); - removeMessages(GATT_CONNECTION_TIMEOUT); - StreamAudioService service = StreamAudioService.getStreamAudioService(); - if (mLastMusicConnectionState != -1) { - // Don't broadcast during startup - if (mIsMusicPlaying) { - Log.i(TAG, "Disconnected: stop music streaming: " + mDevice); - mIsMusicPlaying = false; - service.onStreamStateChange(mDevice, BluetoothA2dp.STATE_NOT_PLAYING, CONTEXT_TYPE_MUSIC); - } - if (mLastVoiceConnectionState != -1) { - if (mIsVoicePlaying) { - Log.i(TAG, "Disconnected: stop voice streaming: " + mDevice); - mIsVoicePlaying = false; - service.onStreamStateChange(mDevice, BluetoothA2dp.STATE_NOT_PLAYING, ApmConst.AudioFeatures.CALL_AUDIO); - } - } - // ensure when one device is disconnected, need to update the channel mode. - mAcmService.updateLeaChannelMode(BluetoothA2dp.STATE_NOT_PLAYING, mDevice); - //Unlock, device state changed from connected to disconnected - - Log.i(TAG, " mIsUpdateProfDisConnection: " + mIsUpdateProfDisConnection); - if (mDevice.getBondState() == BluetoothDevice.BOND_NONE || - mIsUpdateProfDisConnection) { - Log.i(TAG, "Device is unpaired/mIsUpdateProfDisConnection has been set," + - " update disconnected to APM for " + mDevice); - mIsUpdateProfDisConnection = false; - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, not last member "); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - if (mLastVoiceConnectionState != -1) - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } else { - Log.d(TAG, "Last member to disconnect"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, true); - if (mLastVoiceConnectionState != -1) - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, true); - } - mDeviceLocked = false; - //assuming disconnected state we are moving hence update AcmDevice hash map - mAcmService.handleAcmDeviceStateChange(mDevice, mConnectionState, mSetId); - } else if (mDeviceLocked) { - Log.i(TAG, "Access RELEASED for device " + mDevice); - List members = new ArrayList(); - members.add(mDevice); - mAcmService.getCsipManager().setLock(mSetId, members, mAcmService.getCsipManager().UNLOCK); - mDeviceLocked = false; - } else if (mCsipConnectionState == BluetoothProfile.STATE_CONNECTED) { - Log.i(TAG, "Device access is already RELEASED, Go for DeviceGroup Disconnect " + mDevice); - mAcmService.getCsipManager().disconnectCsip(mDevice); - } else { - if (mBluetoothGatt != null && !mIsDeviceWhitelisted) { - Log.d(TAG, "remove other devices from BG WL"); - mAcmService.removePeersFromBgWl(mDevice, mSetId); - Log.i(TAG, "Go for GATT Disconnect " + mDevice); - mBluetoothGatt.disconnect(); - } else { - Log.d(TAG, "mBluetoothGatt is NULL or device is in BG WL "); - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, not last member "); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - if (mLastVoiceConnectionState != -1) - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } else { - Log.d(TAG, "Last member to disconnect"); - if (!mIsDeviceWhitelisted) { - mAcmService.removePeersFromBgWl(mDevice, mSetId); - Log.d(TAG, "remove other devices from BG WL"); - } - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, true); - if (mLastVoiceConnectionState != -1) - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, true); - } - //assuming disconnected state we are moving hence update AcmDevice hash map - mAcmService.handleAcmDeviceStateChange(mDevice, mConnectionState, mSetId); - } - } - } - } - - @Override - public void exit() { - Message currentMessage = getCurrentMessage(); - log("Exit Disconnected(" + mDevice + "): " + (currentMessage == null ? "null" - : messageWhatToString(currentMessage.what))); - mConnectionState = BluetoothProfile.STATE_DISCONNECTED; - mLastMusicConnectionState = BluetoothProfile.STATE_DISCONNECTED; - mLastVoiceConnectionState = BluetoothProfile.STATE_DISCONNECTED; - } - - @Override - public boolean processMessage(Message message) { - log("Disconnected process message(" + mDevice + "): " - + messageWhatToString(message.what)); - - switch (message.what) { - case CONNECT: { - mCurrentContextType = message.arg1; - mProfileType = message.arg2; - mPreferredContext = (int)message.obj; - Log.i(TAG, "Connecting " + contextTypeToString(mCurrentContextType) + " to " + mDevice); - if (mAcmService.IsLockSupportAvailable(mDevice)) { - Log.d(TAG, "Exclusive Access support available, go for GATT connect"); - //if lock support available then go for CSIP connect - if (mBluetoothGatt != null) { - mBluetoothGatt.close(); - } - mBluetoothGatt = mDevice.connectGatt(mAcmService, false, mGattCallback, - BluetoothDevice.TRANSPORT_LE, false, (BluetoothDevice.PHY_LE_1M_MASK | - BluetoothDevice.PHY_LE_2M_MASK | BluetoothDevice.PHY_LE_CODED_MASK), - null, true); - - sendMessageDelayed(GATT_CONNECTION_TIMEOUT, GATT_CONNECTION_TIMEOUT_MS); - transitionTo(mConnecting); - break; - } else { - Log.d(TAG, "Exclusive Access support not available, go for GATT connect"); - if (mBluetoothGatt != null) { - mBluetoothGatt.close(); - } - mBluetoothGatt = mDevice.connectGatt(mAcmService, false, mGattCallback, - BluetoothDevice.TRANSPORT_LE, false, (BluetoothDevice.PHY_LE_1M_MASK | - BluetoothDevice.PHY_LE_2M_MASK | BluetoothDevice.PHY_LE_CODED_MASK), - null, true); - - sendMessageDelayed(GATT_CONNECTION_TIMEOUT, GATT_CONNECTION_TIMEOUT_MS); - transitionTo(mConnecting); - /*if (!mAcmNativeInterface.connectAcm(mDevice, message.arg1, message.arg2, (int)message.obj)) { - Log.e(TAG, "Disconnected: error connecting to " + mDevice); - break; - } - transitionTo(mConnecting);*/ - } - } break; - - case GATT_CONNECTION_STATE_CHANGED: { - removeMessages(GATT_CONNECTION_TIMEOUT); - int st = (int)message.obj; - if (st == BluetoothProfile.STATE_DISCONNECTED) { - Log.d(TAG, "GATT Disconnected"); - mIsDeviceWhitelisted = false; - StreamAudioService service = StreamAudioService.getStreamAudioService(); - if (mCurrentContextType == CONTEXT_TYPE_MUSIC) { - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, not last member "); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - } else { - Log.d(TAG, "Last member to disconnect MEDIA"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, true); - } - } else if (mCurrentContextType == CONTEXT_TYPE_VOICE) { - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, not last member "); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } else { - Log.d(TAG, "Last member to disconnect VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, true); - } - } else if (mCurrentContextType == CONTEXT_TYPE_MUSIC_VOICE) { - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, not last member "); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } else { - Log.d(TAG, "Last member to disconnect MEDIA+VOICE"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, true); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, true); - } - } - //assuming disconneted state we are moving hence update AcmDevice hash map - mAcmService.handleAcmDeviceStateChange(mDevice, BluetoothProfile.STATE_DISCONNECTED, mSetId); - mBluetoothGatt.close(); - } else if (st == BluetoothProfile.STATE_CONNECTED) { - mIsDeviceWhitelisted = false; - Log.d(TAG, "GATT connected from background, go for profile connection"); - AdapterService mAdapterService = AdapterService.getAdapterService(); - if (mAdapterService != null && !mAdapterService.connectAllEnabledProfiles(mDevice)) { - Log.e(TAG, "Disconnected: error connecting to " + mDevice); - break; - } - break; - } - } break; - - case DISCONNECT: - Log.w(TAG, "Disconnected: DISCONNECT ignored: " + mDevice); - break; - - case GATT_CONNECTION_TIMEOUT: { - Log.d(TAG, "GATT connection Timeout"); - break; - } - - case CSIP_CONNECTION_STATE_CHANGED: - int state = (int)message.obj; - if (state == BluetoothProfile.STATE_DISCONNECTED) - mCsipConnectionState = BluetoothProfile.STATE_DISCONNECTED; - if (mBluetoothGatt != null) - mBluetoothGatt.disconnect(); - break; - - case CSIP_LOCK_STATUS_RELEASED: { - removeMessages(CSIP_LOCK_RELEASE_TIMEOUT); - //disconnect CSIP - int value = (int)message.arg1; - Log.d(TAG, "Exclusive Access state changed:" + value); - if (value == mAcmService.getCsipManager().UNLOCK) { - if (mCsipConnectionState == BluetoothProfile.STATE_CONNECTED) { - mAcmService.getCsipManager().disconnectCsip(mDevice); - } - } - mCsipLockRequested = false; - mDeviceLocked = false; - break; - } - - case STACK_EVENT: - AcmStackEvent event = (AcmStackEvent) message.obj; - log("Disconnected: stack event: " + event); - if (!mDevice.equals(event.device)) { - Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); - } - switch (event.type) { - case AcmStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - processConnectionEvent(event.valueInt1, event.valueInt2); - break; - case AcmStackEvent.EVENT_TYPE_CODEC_CONFIG_CHANGED: - processCodecConfigEvent(event.codecStatus, event.valueInt2); - break; - default: - Log.e(TAG, "Disconnected: ignoring stack event: " + event); - break; - } - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - - // in Disconnected state - private void processConnectionEvent(int state, int contextType) { - switch (state) { - case AcmStackEvent.CONNECTION_STATE_DISCONNECTED: - Log.w(TAG, "Ignore ACM DISCONNECTED event: " + mDevice); - break; - case AcmStackEvent.CONNECTION_STATE_CONNECTING:{ - // Reject the connection and stay in Disconnected state itself - Log.w(TAG, "Incoming A2DP Connecting request rejected: " + mDevice); - mAcmNativeInterface.disconnectAcm(mDevice, contextType); - } - break; - case AcmStackEvent.CONNECTION_STATE_CONNECTED: {//Shouldn't come - Log.w(TAG, "ACM Connected from Disconnected state: " + mDevice); - // Reject the connection and stay in Disconnected state itself - Log.w(TAG, "Incoming ACM Connected request rejected: " + mDevice); - mAcmNativeInterface.disconnectAcm(mDevice, contextType); - } - break; - case AcmStackEvent.CONNECTION_STATE_DISCONNECTING: - Log.w(TAG, "Ignore ACM DISCONNECTING event: " + mDevice); - break; - default: - Log.e(TAG, "Incorrect state: " + state + " device: " + mDevice); - break; - } - } - } - - @VisibleForTesting - class Connecting extends State { - @Override - public void enter() { - //Connect unicast VCP 1st - mVcpController = VcpController.getVcpController(); - if (mVcpController != null) { - Log.d(TAG, "Connect VCP for " + mDevice); - mVcpController.connect(mDevice, BluetoothVcp.MODE_UNICAST); - } else { - Log.d(TAG, "mVcpController is null"); - } - - Message currentMessage = getCurrentMessage(); - Log.i(TAG, "Enter Connecting(" + mDevice + "): " + (currentMessage == null ? "null" - : messageWhatToString(currentMessage.what))); - sendMessageDelayed(CONNECT_TIMEOUT, sConnectTimeoutMs); - StreamAudioService service = StreamAudioService.getStreamAudioService(); - //this context type here is global context type, if not based on current - //and prev states per context, form this contextType here - synchronized (this) { - mConnectionState = BluetoothProfile.STATE_CONNECTING; - } - mSetId = mAcmService.getCsipManager().getCsipSetId(mDevice, null /*ACM_UUID*/); //TODO: UUID what to set ? - mGroupAddress = mAcmService.getGroup(mDevice); - Log.d(TAG, "Group bd address " + mGroupAddress); - mAcmService.handleAcmDeviceStateChange(mDevice, mConnectionState, mSetId); - if (mCurrentContextType == CONTEXT_TYPE_MUSIC) { - mMusicConnectionState = BluetoothProfile.STATE_CONNECTING; - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, not first member "); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - } else { - Log.d(TAG, "First member of group to connect MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, true); - } - } else if (mCurrentContextType == CONTEXT_TYPE_VOICE) { - mVoiceConnectionState = BluetoothProfile.STATE_CONNECTING; - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, not first member "); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } else { - Log.d(TAG, "First member of group to connect VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, true); - } - } else if (mCurrentContextType == CONTEXT_TYPE_MUSIC_VOICE) { - mMusicConnectionState = BluetoothProfile.STATE_CONNECTING; - mVoiceConnectionState = BluetoothProfile.STATE_CONNECTING; - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, not first member "); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } else { - Log.d(TAG, "First member of group to connect MUSIC & VOICE"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, true); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, true); - } - } - } - - @Override - public void exit() { - Message currentMessage = getCurrentMessage(); - log("Exit Connecting(" + mDevice + "): " + (currentMessage == null ? "null" - : messageWhatToString(currentMessage.what))); - if (mCurrentContextType == CONTEXT_TYPE_MUSIC) { - mLastMusicConnectionState = BluetoothProfile.STATE_CONNECTING; - } else if (mCurrentContextType == CONTEXT_TYPE_VOICE) { - mLastVoiceConnectionState = BluetoothProfile.STATE_CONNECTING; - } else if (mCurrentContextType == CONTEXT_TYPE_MUSIC_VOICE) { - mLastMusicConnectionState = BluetoothProfile.STATE_CONNECTING; - mLastVoiceConnectionState = BluetoothProfile.STATE_CONNECTING; - } - removeMessages(CONNECT_TIMEOUT); - } - - @Override - public boolean processMessage(Message message) { - log("Connecting process message(" + mDevice + "): " - + messageWhatToString(message.what)); - - switch (message.what) { - case CONNECT: - deferMessage(message); // Do we need to defer this ? It shouldn't have come. - break; - case CONNECT_TIMEOUT: { - Log.w(TAG, "Connecting connection timeout: " + mDevice); - //check if CSIP is connected - if (mCsipConnectionState == BluetoothProfile.STATE_CONNECTED) - mAcmService.getCsipManager().disconnectCsip(mDevice); - mAcmNativeInterface.disconnectAcm(mDevice, mCurrentContextType); - AcmStackEvent event = - new AcmStackEvent(AcmStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - event.device = mDevice; - event.valueInt1 = AcmStackEvent.CONNECTION_STATE_DISCONNECTED; - event.valueInt2 = mCurrentContextType; - sendMessage(STACK_EVENT, event); - break; - } - case DISCONNECT: { - // Cancel connection, shouldn't come - mContextTypeToDisconnect = (int)message.obj; - //check if disconnect is for individual context type - IState state = mDisconnected; - Log.i(TAG, "Connecting: connection canceled to " + mDevice); - mAcmNativeInterface.disconnectAcm(mDevice, mContextTypeToDisconnect); - if ((mMusicConnectionState == BluetoothProfile.STATE_CONNECTING) && - (mVoiceConnectionState == BluetoothProfile.STATE_CONNECTING)) { - if (mContextTypeToDisconnect != CONTEXT_TYPE_MUSIC_VOICE) { - /*only 1/2 contexts are being disconnected, - remain in connecting state but broadcast the connection state*/ - state = mConnecting; - } else { - //disconnect is for both context type then disconnect CSIP - if (mCsipConnectionState == BluetoothProfile.STATE_CONNECTED) - mAcmService.getCsipManager().disconnectCsip(mDevice); - } - } - processTransitionContextState(mConnecting, mDisconnected, mContextTypeToDisconnect); - StreamAudioService service = StreamAudioService.getStreamAudioService(); - if (state == mConnecting) { - if (mContextTypeToDisconnect == CONTEXT_TYPE_MUSIC) - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - else if (mContextTypeToDisconnect == CONTEXT_TYPE_VOICE) - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } else { - transitionTo(state); - } - break; - } - - case GATT_CONNECTION_STATE_CHANGED: { - removeMessages(GATT_CONNECTION_TIMEOUT); - int st = (int)message.obj; - if (st == BluetoothProfile.STATE_CONNECTED) { - mIsDeviceWhitelisted = false; - Log.d(TAG, "GATT connected, go for connect"); - if (!mAcmNativeInterface.connectAcm(mDevice, mCurrentContextType, mProfileType, mPreferredContext)) { - Log.e(TAG, "Disconnected: error connecting to " + mDevice); - break; - } - } else if (st == BluetoothProfile.STATE_DISCONNECTED) { - Log.d(TAG, "GATT Disconnected"); - mIsDeviceWhitelisted = false; - StreamAudioService service = StreamAudioService.getStreamAudioService(); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - transitionTo(mDisconnected); - } - /*if (st == BluetoothProfile.STATE_CONNECTED) { - Log.d(TAG, "GATT connected, go for DeviceGroup connect"); - mAcmService.getCsipManager().connectCsip(mDevice); - } else if (st == BluetoothProfile.STATE_DISCONNECTED) { - Log.d(TAG, "GATT Disconnected"); - StreamAudioService service = StreamAudioService.getStreamAudioService(); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - }*/ - } break; - - case GATT_CONNECTION_TIMEOUT: { - Log.d(TAG, "GATT connection Timeout"); - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Peer device is connected, add to BG WL"); - mIsDeviceWhitelisted = true; - mBluetoothGatt.close(); - - mBluetoothGatt = mDevice.connectGatt(mAcmService, true, mGattCallback, - BluetoothDevice.TRANSPORT_LE, false, (BluetoothDevice.PHY_LE_1M_MASK | - BluetoothDevice.PHY_LE_2M_MASK | BluetoothDevice.PHY_LE_CODED_MASK), - null, true); - - } else { - Log.d(TAG, "No member is in connected state, do not add in BG WL"); - mIsDeviceWhitelisted = false; - if (mBluetoothGatt != null) { - Log.e(TAG, "Disconnect gatt and make gatt instance null."); - mBluetoothGatt.disconnect(); - mBluetoothGatt.close(); - mBluetoothGatt = null; - } - } - transitionTo(mDisconnected); - break; - } - - case CSIP_CONNECTION_STATE_CHANGED: { - int state = (int)message.obj; - if (state == BluetoothProfile.STATE_CONNECTED) { - Log.e(TAG, "DeviceGroup Connected to " + mDevice); - mCsipConnectionState = BluetoothProfile.STATE_CONNECTED; - mSetId = mAcmService.getCsipManager().getCsipSetId(mDevice, null /*ACM_UUID*/); //TODO: UUID what to set ? - Iterator i = mAcmService.getCsipManager().getSetMembers(mSetId).iterator(); - List members = new ArrayList(); - if (i != null) { - while (i.hasNext()) { - BluetoothDevice device = i.next(); - if (mAcmService.getCsipConnectionState(device) == BluetoothProfile.STATE_CONNECTED) { - members.add(device); - } - } - } - //setlockvalue takes device list - mCsipLockRequested = true; - mAcmService.getCsipManager().setLock(mSetId, members, mAcmService.getCsipManager().LOCK); - } else { - Log.e(TAG, "DeviceGroup Connection failed to " + mDevice); - mCsipConnectionState = BluetoothProfile.STATE_DISCONNECTED; - mCsipLockRequested = false; - mDeviceLocked = false; - transitionTo(mDisconnected); - } - break; - } - - case CSIP_LOCK_STATUS_LOCKED: { - mCsipLockRequested = false; - int value = (int)message.arg1; - Log.d(TAG, "Exclusive Access state changed:" + value); - int setId = (int)message.obj; - int st = mAcmService.getCsipConnectionState(mDevice); - if ((mDeviceLocked && st == BluetoothProfile.STATE_CONNECTED)) { - Log.w(TAG, "Device access is already granted and DeviceGroup is in connected state"); - break; - } - if (value == mAcmService.getCsipManager().LOCK) { - mDeviceLocked = true; - if (!mAcmNativeInterface.connectAcm(mDevice, mCurrentContextType, mProfileType, mPreferredContext)) { - Log.e(TAG, "Disconnected: error connecting to " + mDevice); - mAcmService.getCsipManager().disconnectCsip(mDevice); - transitionTo(mDisconnected); - break; - } - } else { - mDeviceLocked = false; - Log.w(TAG, "Exclusive Access failed to " + setId); - transitionTo(mDisconnected); - } - break; - } - - case CSIP_LOCK_STATUS_PARTIAL_LOCK: { - //check if requested lock is from this device - if (mCsipLockRequested) { - int value = (int)message.arg1; - Log.d(TAG, "Exclusive Access state changed:" + value); - int setId = (int)message.obj; - int st = mAcmService.getCsipConnectionState(mDevice); - if (mDeviceLocked && st == BluetoothProfile.STATE_CONNECTED) { - Log.w(TAG, "Device access is already granted and DeviceGroup is in connected state"); - break; - } - if (value == mAcmService.getCsipManager().LOCK) { - mDeviceLocked = true; - if (!mAcmNativeInterface.connectAcm(mDevice, mCurrentContextType, mProfileType, mPreferredContext)) { - Log.e(TAG, "Disconnected: error connecting to " + mDevice); - mAcmService.getCsipManager().disconnectCsip(mDevice); - transitionTo(mDisconnected); - break; - } - } else { - mDeviceLocked = false; - Log.w(TAG, "Exclusive Access failed to " + setId); - transitionTo(mDisconnected); - } - mCsipLockRequested = false; - } else { - //lock is not requested from this device TODO: check if - Log.d(TAG, "Exclusive Access is not requested from this device: " + mDevice); - mDeviceLocked = true; - } - } - break; - - case CSIP_LOCK_RELEASE_TIMEOUT: - //TODO: lock release individual ? - Log.d(TAG, "Exclusive Access timeout to " + mDevice); - List set = new ArrayList(); - set.add(mDevice); - mAcmService.getCsipManager().setLock(mSetId, set, mAcmService.getCsipManager().UNLOCK); - mDeviceLocked = false; - break; - - case CSIP_LOCK_STATUS_DENIED: - //lock denied fail connection - Log.e(TAG, "DeviceGroup Connection failed to " + mDevice); - mCsipLockRequested = false; - mDeviceLocked = false; - break; - - case CSIP_LOCK_STATUS_RELEASED: - removeMessages(CSIP_LOCK_RELEASE_TIMEOUT); - mCsipLockRequested = false; - mDeviceLocked = false; - break; - - case STACK_EVENT: - AcmStackEvent event = (AcmStackEvent) message.obj; - log("Connecting: stack event: " + event); - if (!mDevice.equals(event.device)) { - Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); - } - switch (event.type) { - case AcmStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - processConnectionEvent(event.valueInt1, event.valueInt2); - break; - case AcmStackEvent.EVENT_TYPE_CODEC_CONFIG_CHANGED: - processCodecConfigEvent(event.codecStatus, event.valueInt2); - break; - case AcmStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED: - break; - default: - Log.e(TAG, "Connecting: ignoring stack event: " + event); - break; - } - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - - // in Connecting state - private void processConnectionEvent(int state, int contextType) { - IState smState; - StreamAudioService service = StreamAudioService.getStreamAudioService(); - switch (state) { - case AcmStackEvent.CONNECTION_STATE_DISCONNECTED: { - smState = mDisconnected; - Log.w(TAG, "Connecting device disconnected: " + mDevice); - if ((mMusicConnectionState == BluetoothProfile.STATE_CONNECTING) && - (mVoiceConnectionState == BluetoothProfile.STATE_CONNECTING)) { - if (contextType != CONTEXT_TYPE_MUSIC_VOICE) { - /*only 1/2 contexts are being disconnected, remain in connecting state but broadcast the connection state*/ - smState = mConnecting; - } - } - processTransitionContextState(mConnecting, mDisconnected, contextType); - if (smState == mConnecting) { - if (contextType == CONTEXT_TYPE_MUSIC) { - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - } else { - Log.d(TAG, "First member of group to connect MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, true); - } - } else if (contextType == CONTEXT_TYPE_VOICE) { - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } else { - Log.d(TAG, "First member of group to connect VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, true); - } - } - } else { - transitionTo(smState); - } - } break; - - case AcmStackEvent.CONNECTION_STATE_CONNECTED: { - // start lock release timer TODO:when CSIP support is available - //sendMessageDelayed(CSIP_LOCK_RELEASE_TIMEOUT, sCsipLockReleaseTimeoutMs); - if (contextType == CONTEXT_TYPE_MUSIC) { - mMusicConnectionState = BluetoothProfile.STATE_CONNECTED; - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - } else { - Log.d(TAG, "First member of group to connect MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, true); - } - } else if (contextType == CONTEXT_TYPE_VOICE) { - mVoiceConnectionState = BluetoothProfile.STATE_CONNECTED; - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } else { - Log.d(TAG, "First member of group to connect VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, true); - } - } - transitionTo(mConnected); - } break; - - case AcmStackEvent.CONNECTION_STATE_CONNECTING: - // Ignored - probably an event that the outgoing connection was initiated - break; - case AcmStackEvent.CONNECTION_STATE_DISCONNECTING: { - Log.w(TAG, "Connecting device disconnecting: " + mDevice); - transitionTo(mDisconnecting); - } break; - - default: - Log.e(TAG, "Incorrect event: " + state); - break; - } - } - } - - @VisibleForTesting - class Disconnecting extends State { - @Override - public void enter() { - //Disconnect unicast VCP 1st - mVcpController = VcpController.getVcpController(); - if (mVcpController != null) { - Log.d(TAG, "Disconnect VCP for " + mDevice); - mVcpController.disconnect(mDevice, BluetoothVcp.MODE_UNICAST); - } else { - Log.d(TAG, "mVcpController is null"); - } - - Message currentMessage = getCurrentMessage(); - Log.i(TAG, "Enter Disconnecting(" + mDevice + "): " + (currentMessage == null ? "null" - : messageWhatToString(currentMessage.what))); - sendMessageDelayed(CONNECT_TIMEOUT, sConnectTimeoutMs); - synchronized (this) { - mConnectionState = BluetoothProfile.STATE_DISCONNECTING; - } - mAcmService.handleAcmDeviceStateChange(mDevice, mConnectionState, mSetId); - StreamAudioService service = StreamAudioService.getStreamAudioService(); - if (mContextTypeToDisconnect == CONTEXT_TYPE_MUSIC && mMusicConnectionState != BluetoothProfile.STATE_DISCONNECTED) { - mMusicConnectionState = BluetoothProfile.STATE_DISCONNECTING; - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update MEDIA"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - } else { - Log.d(TAG, "Last member to disconnect, update MEDIA"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, true); - } - } else if (mContextTypeToDisconnect == CONTEXT_TYPE_VOICE && mVoiceConnectionState != BluetoothProfile.STATE_DISCONNECTED) { - mVoiceConnectionState = BluetoothProfile.STATE_DISCONNECTING; - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update VOICE "); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } else { - Log.d(TAG, "Last member to disconnect, update VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, true); - } - } else if (mContextTypeToDisconnect == CONTEXT_TYPE_MUSIC_VOICE && mMusicConnectionState != BluetoothProfile.STATE_DISCONNECTED - && mVoiceConnectionState != BluetoothProfile.STATE_DISCONNECTED) { - mMusicConnectionState = BluetoothProfile.STATE_DISCONNECTING; - mVoiceConnectionState = BluetoothProfile.STATE_DISCONNECTING; - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update MEDIA+VOICE"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } else { - Log.d(TAG, "Last member to disconnect, update MEDIA+VOICE"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, true); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, true); - } - } - } - - @Override - public void exit() { - Message currentMessage = getCurrentMessage(); - log("Exit Disconnecting(" + mDevice + "): " + (currentMessage == null ? "null" - : messageWhatToString(currentMessage.what))); - mLastConnectionState = BluetoothProfile.STATE_DISCONNECTING; - removeMessages(CONNECT_TIMEOUT); - } - - @Override - public boolean processMessage(Message message) { - log("Disconnecting process message(" + mDevice + "): " - + messageWhatToString(message.what)); - - switch (message.what) { - case CONNECT: - deferMessage(message); - break; - case CONNECT_TIMEOUT: { - Log.w(TAG, "Disconnecting connection timeout: " + mDevice); - mAcmNativeInterface.disconnectAcm(mDevice, mCurrentContextType); - AcmStackEvent event = - new AcmStackEvent(AcmStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - event.device = mDevice; - event.valueInt1 = AcmStackEvent.CONNECTION_STATE_DISCONNECTED; - event.valueInt2 = mCurrentContextType; - sendMessage(STACK_EVENT, event); - break; - } - case DISCONNECT: - deferMessage(message); - break; - case GATT_CONNECTION_STATE_CHANGED: - deferMessage(message); - break; - case STACK_EVENT: - AcmStackEvent event = (AcmStackEvent) message.obj; - log("Disconnecting: stack event: " + event); - if (!mDevice.equals(event.device)) { - Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); - } - switch (event.type) { - case AcmStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - processConnectionEvent(event.valueInt1, event.valueInt2); - break; - case AcmStackEvent.EVENT_TYPE_CODEC_CONFIG_CHANGED: - processCodecConfigEvent(event.codecStatus, event.valueInt2); - break; - case AcmStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED: - default: - Log.e(TAG, "Disconnecting: ignoring stack event: " + event); - break; - } - break; - - default: - return NOT_HANDLED; - } - return HANDLED; - } - - // in Disconnecting state - private void processConnectionEvent(int event, int contextType) { - IState smState; - StreamAudioService service = StreamAudioService.getStreamAudioService(); - switch (event) { - case AcmStackEvent.CONNECTION_STATE_DISCONNECTED: { - Log.w(TAG, "Disconnecting device disconnected " + mDevice); - processTransitionContextState(mDisconnecting, mDisconnected, contextType); - if (contextType == CONTEXT_TYPE_MUSIC) { - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - } else { - Log.d(TAG, "Last member to disconnect, update MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, true); - } - } else if (contextType == CONTEXT_TYPE_VOICE) { - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } else { - Log.d(TAG, "Last member to disconnect, update VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, true); - } - } - if (mMusicConnectionState == BluetoothProfile.STATE_DISCONNECTED && - mVoiceConnectionState == BluetoothProfile.STATE_DISCONNECTED) { - transitionTo(mDisconnected); - } - } break; - - case AcmStackEvent.CONNECTION_STATE_CONNECTED: { - //TODO:sendMessageDelayed(CSIP_LOCK_RELEASE_TIMEOUT, sCsipLockReleaseTimeoutMs); - // Reject the connection and stay in Disconnecting state - Log.w(TAG, "Incoming ACM Connected request rejected: " + mDevice); - mAcmNativeInterface.disconnectAcm(mDevice, contextType); - } break; - - case AcmStackEvent.CONNECTION_STATE_DISCONNECTING: - if (contextType == CONTEXT_TYPE_MUSIC) - service.onConnectionStateChange(mDevice, BluetoothProfile.STATE_DISCONNECTING, CONTEXT_TYPE_MUSIC, false); - else if (contextType == CONTEXT_TYPE_VOICE) - service.onConnectionStateChange(mDevice, BluetoothProfile.STATE_DISCONNECTING, CONTEXT_TYPE_VOICE, false); - else { - service.onConnectionStateChange(mDevice, BluetoothProfile.STATE_DISCONNECTING, CONTEXT_TYPE_MUSIC, false); - service.onConnectionStateChange(mDevice, BluetoothProfile.STATE_DISCONNECTING, CONTEXT_TYPE_VOICE, false); - } - Log.d(TAG, "Updating disconnecting state to APM " + mDevice + "contextType " + contextType); - IsDisconnectRequested = false; - // We are already disconnecting, do nothing - break; - default: - Log.e(TAG, "Incorrect event: " + event); - break; - } - } - } - - @VisibleForTesting - class Connected extends State { - @Override - public void enter() { - Message currentMessage = getCurrentMessage(); - Log.i(TAG, "Enter Connected(" + mDevice + "): " + (currentMessage == null ? "null" - : messageWhatToString(currentMessage.what))); - synchronized (this) { - mConnectionState = BluetoothProfile.STATE_CONNECTED; - } - mAcmService.handleAcmDeviceStateChange(mDevice, mConnectionState, mSetId); - StreamAudioService service = StreamAudioService.getStreamAudioService(); - service.onStreamStateChange(mDevice, BluetoothA2dp.STATE_NOT_PLAYING, CONTEXT_TYPE_MUSIC); - } - - @Override - public void exit() { - Message currentMessage = getCurrentMessage(); - log("Exit Connected(" + mDevice + "): " + (currentMessage == null ? "null" - : messageWhatToString(currentMessage.what))); - mLastConnectionState = BluetoothProfile.STATE_CONNECTED; - } - - @Override - public boolean processMessage(Message message) { - log("Connected process message(" + mDevice + "): " + messageWhatToString(message.what)); - - switch (message.what) { - case CONNECT: { - if (message.arg1 == CONTEXT_TYPE_MUSIC && mMusicConnectionState != BluetoothProfile.STATE_DISCONNECTED) - break; - if (message.arg1 == CONTEXT_TYPE_VOICE && mVoiceConnectionState != BluetoothProfile.STATE_DISCONNECTED) - break; - if (message.arg1 == CONTEXT_TYPE_MUSIC_VOICE && mVoiceConnectionState != BluetoothProfile.STATE_DISCONNECTED - && mMusicConnectionState != BluetoothProfile.STATE_DISCONNECTED) - break; - mCurrentContextType += message.arg1; - Log.i(TAG, "mCurrentContextType now is " + contextTypeToString(mCurrentContextType)); - mProfileType = message.arg2; - mPreferredContext = (int)message.obj; - Log.i(TAG, "Connecting " + contextTypeToString(message.arg1) + " to " + mDevice); - if (mAcmService.IsLockSupportAvailable(mDevice)) { - Log.d(TAG, "Exclusive Access support available, gatt should already be connected"); - //if lock support available then go for CSIP connect - //mBluetoothGatt = mDevice.connectGatt(mAcmService, false, mGattCallback, BluetoothDevice.TRANSPORT_LE, 7); - //sendMessageDelayed(GATT_CONNECTION_TIMEOUT, GATT_CONNECTION_TIMEOUT_MS); - //transitionTo(mConnecting); - //break; - } else { - Log.d(TAG, "Exclusive Access support not available, gatt should already be connected"); - //mBluetoothGatt = mDevice.connectGatt(mAcmService, false, mGattCallback, BluetoothDevice.TRANSPORT_LE, 7); - //sendMessageDelayed(GATT_CONNECTION_TIMEOUT, GATT_CONNECTION_TIMEOUT_MS); - //transitionTo(mConnecting); - } - if (!mAcmNativeInterface.connectAcm(mDevice, message.arg1, message.arg2, (int)message.obj)) { - Log.e(TAG, "Disconnected: error connecting to " + mDevice + " remain in connected"); - } - } break; - - case DISCONNECT: {//disconnect request goes individual - IsDisconnectRequested = true; - mIsDeviceWhitelisted = false; - mContextTypeToDisconnect = (int)message.obj; - IState state = mDisconnecting; - boolean disconnected_flag = false; - //check if disconnect is for individual context type - Log.i(TAG, "Disconnecting " + contextTypeToString(mContextTypeToDisconnect) + " from " + mDevice); - if (!mAcmNativeInterface.disconnectAcm(mDevice, mContextTypeToDisconnect)) { - Log.e(TAG, "error disconnecting " + contextTypeToString(mContextTypeToDisconnect) + " from " + mDevice); - transitionTo(mDisconnected); - disconnected_flag = true; - } - if ((mMusicConnectionState == BluetoothProfile.STATE_CONNECTED) && - (mVoiceConnectionState == BluetoothProfile.STATE_CONNECTED)) { - if (mContextTypeToDisconnect != CONTEXT_TYPE_MUSIC_VOICE) { - /*only 1/2 contexts are being disconnected, - remain in connected state but broadcast the connection state*/ - state = mConnected; - } - } - StreamAudioService service = StreamAudioService.getStreamAudioService(); - processTransitionContextState(mConnected, (disconnected_flag ? mDisconnected : mDisconnecting), mContextTypeToDisconnect); - if (state == mConnected) { - if (mContextTypeToDisconnect == CONTEXT_TYPE_MUSIC) { - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - } else { - Log.d(TAG, "Last member to disconnect, update MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, true); - } - } else if (mContextTypeToDisconnect == CONTEXT_TYPE_VOICE) { - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } else { - Log.d(TAG, "Last member to disconnect, update VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, true); - } - } - } else { - transitionTo(state); - } - /*mSetId = mSetCoordinator.getRemoteDeviceSetId(mDevice, null); // TODO: UUID ? - List members = new ArrayList(); - members.add(mDevice); - //setlockvalue takes device list - mCsipLockRequested = true; - mDeviceLocked = false; - mSetCoordinator.setLockValue(mAcmService.mCsipAppId, mSetId, members, BluetoothCsip.LOCK);*/ - } break; - - case CSIP_LOCK_STATUS_LOCKED: { - mCsipLockRequested = false; - int value = (int)message.arg1; - int setId = (int)message.obj; - int st = mAcmService.getCsipConnectionState(mDevice); - Log.d(TAG, "Exclusive Access state changed:" + value); - if (value == mAcmService.getCsipManager().LOCK) { - mDeviceLocked = true; - if (IsDisconnectRequested) { - Log.i(TAG, "Disconnecting " + contextTypeToString(mContextTypeToDisconnect) + " from " + mDevice); - if (!mAcmNativeInterface.disconnectAcm(mDevice, mContextTypeToDisconnect)) { // this context Type is passed in disconnect api from APM - Log.e(TAG, "error disconnecting " + contextTypeToString(mContextTypeToDisconnect) + " from " + mDevice); - transitionTo(mDisconnected); - } - transitionTo(mDisconnecting); - } else if (IsReconfigRequested) { - Log.w(TAG, "Reconfig requested Exclusive Access"); - if (!mAcmNativeInterface.ChangeCodecConfigPreference(mDevice, mReconfig)) { // this context Type is passed in disconnect api from APM - Log.e(TAG, "reconfig error " + mDevice); - break; - } - } - } - } break; - - case CSIP_CONNECTION_STATE_CHANGED: - int state = (int)message.obj; - if (state == BluetoothProfile.STATE_DISCONNECTED) - mCsipConnectionState = BluetoothProfile.STATE_DISCONNECTED; - break; - - case CSIP_LOCK_RELEASE_TIMEOUT: - //lock release individual ? - Log.d(TAG, "Exclusive Access timeout to " + mDevice); - List devices = new ArrayList(); - devices.add(mDevice); - mAcmService.getCsipManager().setLock(mSetId, devices, mAcmService.getCsipManager().UNLOCK); - mDeviceLocked = false; - break; - - case CSIP_LOCK_STATUS_RELEASED: - // ignore disconnect CSIP - removeMessages(CSIP_LOCK_RELEASE_TIMEOUT); - mDeviceLocked = false; - break; - - case CODEC_CONFIG_CHANGED: { - IsReconfigRequested = true; - mReconfig = mAcmService.getAcmName(); - if (!mAcmNativeInterface.ChangeCodecConfigPreference(mDevice, mReconfig)) { - Log.e(TAG, "reconfig error " + mDevice); - break; - } - /*int setId = (int)message.obj; - int st = mAcmService.getCsipConnectionState(mDevice); - if ((mDeviceLocked && st == BluetoothProfile.STATE_CONNECTED)) { - Log.w(TAG, "Device access is already granted and DeviceGroup is in connected state"); - if (!mAcmNativeInterface.ChangeCodecConfigPreference(mDevice, mReconfig)) { - Log.e(TAG, "reconfig error " + mDevice); - break; - } - break; - } - //mSetId = mSetCoordinator.getRemoteDeviceSetId(mDevice, null ); //TODO: UUID what to set ? - List members = new ArrayList(); - Iterator i = mAcmService.getCsipManager().getSetMembers(mSetId).iterator(); - if (i != null) { - while (i.hasNext()) { - BluetoothDevice device = i.next(); - if (mAcmService.getCsipConnectionState(device) == BluetoothProfile.STATE_CONNECTED) { - members.add(device); - } - } - } - mAcmService.getCsipManager().setLock(mSetId, members, mAcmService.getCsipManager().LOCK);*/ - } break; - - case START_STREAM: { - int value = (int)message.obj; - if (!mAcmNativeInterface.startStream(mDevice, value)) { - Log.e(TAG, "start stream error " + mDevice); - break; - } - /*int setId = (int)message.obj; - int st = mAcmService.getCsipConnectionState(mDevice); - if ((mDeviceLocked && st == BluetoothProfile.STATE_CONNECTED)) { - Log.w(TAG, "Device access is already granted and DeviceGroup is in connected state"); - if (!mAcmNativeInterface.ChangeCodecConfigPreference(mDevice, mReconfig)) { - Log.e(TAG, "reconfig error " + mDevice); - break; - } - break; - } - //mSetId = mSetCoordinator.getRemoteDeviceSetId(mDevice, null ); //TODO: UUID what to set ? - List members = new ArrayList(); - Iterator i = mAcmService.getCsipManager().getSetMembers(mSetId).iterator(); - if (i != null) { - while (i.hasNext()) { - BluetoothDevice device = i.next(); - if (mAcmService.getCsipConnectionState(device) == BluetoothProfile.STATE_CONNECTED) { - members.add(device); - } - } - } - mAcmService.getCsipManager().setLock(mSetId, members, mAcmService.getCsipManager().LOCK);*/ - } break; - - case START_STREAM_REQ: { - if (!mAcmService.isPeerDeviceStreamingMusic(mDevice, mSetId)) { - mAcmService.StartStream(mGroupAddress, CONTEXT_TYPE_VOICE); - } - } break; - - case STACK_EVENT: - AcmStackEvent event = (AcmStackEvent) message.obj; - log("Connected: stack event: " + event); - if (!mDevice.equals(event.device)) { - Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); - } - switch (event.type) { - case AcmStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - processConnectionEvent(event.valueInt1, event.valueInt2); - break; - case AcmStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED: - processAudioStateEvent(event.valueInt1, event.valueInt2); - break; - case AcmStackEvent.EVENT_TYPE_CODEC_CONFIG_CHANGED: - processCodecConfigEvent(event.codecStatus, event.valueInt2); - break; - default: - Log.e(TAG, "Connected: ignoring stack event: " + event); - break; - } - break; - - case GATT_CONNECTION_STATE_CHANGED: { - Log.e(TAG, "Connection state as disconnected " + mDevice); - removeMessages(GATT_CONNECTION_TIMEOUT); - int st = (int)message.obj; - if (st == BluetoothProfile.STATE_DISCONNECTED) { - Log.d(TAG, " GATT Disconnected"); - mIsDeviceWhitelisted = false; - mIsUpdateProfDisConnection = true; - transitionTo(mDisconnected); - } break; - } - - default: - return NOT_HANDLED; - } - return HANDLED; - } - - // in Connected state - private void processConnectionEvent(int event, int contextType) { - IState smState; - switch (event) { - case AcmStackEvent.CONNECTION_STATE_DISCONNECTED: { - StreamAudioService service = StreamAudioService.getStreamAudioService(); - mCurrentContextType -= contextType; - Log.i(TAG, "mCurrentContextType now is " + contextTypeToString(mCurrentContextType)); - processTransitionContextState(mDisconnecting, mDisconnected, contextType); - if (contextType == CONTEXT_TYPE_MUSIC) { - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - } else { - Log.d(TAG, "Last member to disconnect, update MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, true); - } - } else if (mContextTypeToDisconnect == CONTEXT_TYPE_VOICE) { - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } else { - Log.d(TAG, "Last member to disconnect, update VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, true); - } - } - } break; - - case AcmStackEvent.CONNECTION_STATE_CONNECTED: { - StreamAudioService service = StreamAudioService.getStreamAudioService(); - //TODO:sendMessageDelayed(CSIP_LOCK_RELEASE_TIMEOUT, sCsipLockReleaseTimeoutMs); - Log.w(TAG, "ACM CONNECTED event for device: " + mDevice + " context type: " + contextTypeToString(contextType)); - if (contextType == CONTEXT_TYPE_MUSIC) { - mMusicConnectionState = BluetoothProfile.STATE_CONNECTED; - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - } else { - Log.d(TAG, "First member of group to connect MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, true); - } - } else if (contextType == CONTEXT_TYPE_VOICE) { - mVoiceConnectionState = BluetoothProfile.STATE_CONNECTED; - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } else { - Log.d(TAG, "First member of group to connect VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, true); - } - } - - } break; - - case AcmStackEvent.CONNECTION_STATE_CONNECTING: { - Log.w(TAG, "Ignore ACM CONNECTED event: " + mDevice); - } break; - - case AcmStackEvent.CONNECTION_STATE_DISCONNECTING: { - if ((contextType == CONTEXT_TYPE_MUSIC) && - (mMusicConnectionState == BluetoothProfile.STATE_DISCONNECTING)) { - Log.w(TAG, "Ignore Disconnecting for media - already disconnecting"); - } else if ((contextType == CONTEXT_TYPE_VOICE) && - (mVoiceConnectionState == BluetoothProfile.STATE_DISCONNECTING)) { - Log.w(TAG, "Ignore Disconnecting for voice - already disconnecting"); - } else { - smState = mDisconnecting; - Log.w(TAG, "Connected device disconnecting: " + mDevice); - if ((mMusicConnectionState == BluetoothProfile.STATE_CONNECTED) && - (mVoiceConnectionState == BluetoothProfile.STATE_CONNECTED)) { - if (contextType != CONTEXT_TYPE_MUSIC_VOICE) { - /*only 1/2 contexts are being disconnected, - remain in connecting state but broadcast the connection state*/ - smState = mConnected; - } - } - processTransitionContextState(mConnected, mDisconnecting, contextType); - StreamAudioService service = StreamAudioService.getStreamAudioService(); - if (smState == mConnected) { - if (contextType == CONTEXT_TYPE_MUSIC) { - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - } else if (contextType == CONTEXT_TYPE_VOICE) { - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } - } else { - transitionTo(smState); - } - } - } break; - - default: - Log.e(TAG, "Connection State Device: " + mDevice + " bad event: " + event); - break; - } - } - - - // in Connected state - private void processAudioStateEvent(int state, int contextType) { - Log.i(TAG, "Connected: processAudioStateEvent: state: " + state + " mIsMusicPlaying: " + mIsMusicPlaying); - switch (state) { - case AcmStackEvent.AUDIO_STATE_STARTED: { - if (contextType == CONTEXT_TYPE_MUSIC) - mIsMusicPlaying = true; - else if (contextType == CONTEXT_TYPE_VOICE) - mIsVoicePlaying = true; - transitionTo(mStreaming); - } break; - case AcmStackEvent.AUDIO_STATE_REMOTE_SUSPEND: - case AcmStackEvent.AUDIO_STATE_STOPPED: { - StreamAudioService service = StreamAudioService.getStreamAudioService(); - synchronized (this) { - if (contextType == CONTEXT_TYPE_MUSIC) { - if (mIsMusicPlaying) { - Log.i(TAG, "Connected: stopped media playing: " + mDevice); - mIsMusicPlaying = false; - service.onStreamStateChange(mDevice, BluetoothA2dp.STATE_NOT_PLAYING, ApmConst.AudioFeatures.MEDIA_AUDIO); - } - } else if (contextType == CONTEXT_TYPE_VOICE) { - if (mIsVoicePlaying) { - Log.i(TAG, "Connected: stopped voice playing: " + mDevice); - mIsVoicePlaying = false; - service.onStreamStateChange(mDevice, BluetoothA2dp.STATE_NOT_PLAYING, ApmConst.AudioFeatures.CALL_AUDIO); - } - } - } - } break; - default: - Log.e(TAG, "Audio State Device: " + mDevice + " bad state: " + state); - break; - } - } - } - - - @VisibleForTesting - class Streaming extends State { - @Override - public void enter() { - Message currentMessage = getCurrentMessage(); - Log.i(TAG, "Enter Streaming(" + mDevice + "): " + (currentMessage == null ? "null" - : messageWhatToString(currentMessage.what))); - - if ((mMusicConnectionState == BluetoothProfile.STATE_CONNECTED)) { - removeDeferredMessages(CONNECT); - } - StreamAudioService service = StreamAudioService.getStreamAudioService(); - if (mIsMusicPlaying) { - Log.i(TAG, "start playing media: " + mDevice); - service.onStreamStateChange(mDevice, BluetoothA2dp.STATE_PLAYING, ApmConst.AudioFeatures.MEDIA_AUDIO); - mAcmService.updateLeaChannelMode(BluetoothA2dp.STATE_PLAYING, mDevice); - } else if (mIsVoicePlaying) { - Log.i(TAG, "start playing voice: " + mDevice); - service.onStreamStateChange(mDevice, BluetoothHeadset.STATE_AUDIO_CONNECTED, ApmConst.AudioFeatures.CALL_AUDIO); - setVoiceParameters(); - setCallAudioOn(true); - } - } - - @Override - public void exit() { - Message currentMessage = getCurrentMessage(); - log("Exit Streaming(" + mDevice + "): " + (currentMessage == null ? "null" - : messageWhatToString(currentMessage.what))); - StreamAudioService service = StreamAudioService.getStreamAudioService(); - if (mIsMusicPlaying) - service.onStreamStateChange(mDevice, BluetoothA2dp.STATE_NOT_PLAYING, ApmConst.AudioFeatures.MEDIA_AUDIO); - else if (mIsVoicePlaying) { - service.onStreamStateChange(mDevice, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, ApmConst.AudioFeatures.CALL_AUDIO); - setCallAudioOn(false); - } - mIsMusicPlaying = false; - mIsVoicePlaying = false; - } - - @Override - public boolean processMessage(Message message) { - log("Streaming process message(" + mDevice + "): " + messageWhatToString(message.what)); - - switch (message.what) { - case CONNECT: { - if (message.arg1 == CONTEXT_TYPE_MUSIC && mMusicConnectionState != BluetoothProfile.STATE_DISCONNECTED) - break; - if (message.arg1 == CONTEXT_TYPE_VOICE && mVoiceConnectionState != BluetoothProfile.STATE_DISCONNECTED) - break; - if (message.arg1 == CONTEXT_TYPE_MUSIC_VOICE && mVoiceConnectionState != BluetoothProfile.STATE_DISCONNECTED - && mMusicConnectionState != BluetoothProfile.STATE_DISCONNECTED) - break; - mCurrentContextType += message.arg1; - Log.i(TAG, "mCurrentContextType now is " + contextTypeToString(mCurrentContextType)); - mProfileType = message.arg2; - mPreferredContext = (int)message.obj; - Log.i(TAG, "Connecting " + contextTypeToString(message.arg1) + " to " + mDevice); - if (mAcmService.IsLockSupportAvailable(mDevice)) { - Log.d(TAG, "Exclusive Access support available, gatt should already be connected"); - //if lock support available then go for CSIP connect - //mBluetoothGatt = mDevice.connectGatt(mAcmService, false, mGattCallback, BluetoothDevice.TRANSPORT_LE, 7); - //sendMessageDelayed(GATT_CONNECTION_TIMEOUT, GATT_CONNECTION_TIMEOUT_MS); - //transitionTo(mConnecting); - //break; - } else { - Log.d(TAG, "Exclusive Access support not available, gatt should already be connected"); - //mBluetoothGatt = mDevice.connectGatt(mAcmService, false, mGattCallback, BluetoothDevice.TRANSPORT_LE, 7); - //sendMessageDelayed(GATT_CONNECTION_TIMEOUT, GATT_CONNECTION_TIMEOUT_MS); - //transitionTo(mConnecting); - } - if (!mAcmNativeInterface.connectAcm(mDevice, message.arg1, message.arg2, (int)message.obj)) { - Log.e(TAG, "Disconnected: error connecting to " + mDevice + " remain in streaming"); - } - } break; - - case DISCONNECT: {//disconnect request goes individual - IsDisconnectRequested = true; - mIsDeviceWhitelisted = false; - mContextTypeToDisconnect = (int)message.obj; - IState state = mDisconnecting; - boolean disconnected_flag = false; - //check if disconnect is for individual context type - Log.i(TAG, "Disconnecting " + contextTypeToString(mContextTypeToDisconnect) + " from " + mDevice); - if (!mAcmNativeInterface.disconnectAcm(mDevice, mContextTypeToDisconnect)) { - Log.e(TAG, "error disconnecting " + contextTypeToString(mContextTypeToDisconnect) + " from " + mDevice); - transitionTo(mDisconnected); - disconnected_flag = true; - } - if ((mMusicConnectionState == BluetoothProfile.STATE_CONNECTED) - && (mVoiceConnectionState == BluetoothProfile.STATE_CONNECTED)) { - if (mContextTypeToDisconnect != CONTEXT_TYPE_MUSIC_VOICE) { - /*only 1/2 contexts are being disconnected, - remain in connected state but broadcast the connection state*/ - state = mConnected; - } - } - StreamAudioService service = StreamAudioService.getStreamAudioService(); - processTransitionContextState(mConnected, (disconnected_flag ? mDisconnected : mDisconnecting), mContextTypeToDisconnect); - if (state == mConnected) { - if (mContextTypeToDisconnect == CONTEXT_TYPE_MUSIC) { - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - } else { - Log.d(TAG, "Last member to disconnect, update MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, true); - } - transitionTo(state); - } else if (mContextTypeToDisconnect == CONTEXT_TYPE_VOICE) { - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } else { - Log.d(TAG, "Last member to disconnect, update VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, true); - } - } - } else { - transitionTo(state); - } - /*mSetId = mSetCoordinator.getRemoteDeviceSetId(mDevice, null); // TODO: UUID ? - List members = new ArrayList(); - members.add(mDevice); - //setlockvalue takes device list - mCsipLockRequested = true; - mDeviceLocked = false; - mSetCoordinator.setLockValue(mAcmService.mCsipAppId, mSetId, members, BluetoothCsip.LOCK);*/ - } break; - - case CSIP_LOCK_STATUS_LOCKED: { - mCsipLockRequested = false; - int value = (int)message.arg1; - int setId = (int)message.obj; - int st = mAcmService.getCsipConnectionState(mDevice); - Log.d(TAG, "Exclusive Access state changed:" + value); - if (value == mAcmService.getCsipManager().LOCK) { - mDeviceLocked = true; - if (IsDisconnectRequested) { - Log.i(TAG, "Disconnecting " + contextTypeToString(mContextTypeToDisconnect) + " from " + mDevice); - if (!mAcmNativeInterface.disconnectAcm(mDevice, mContextTypeToDisconnect)) { // this context Type is passed in disconnect api from APM - Log.e(TAG, "error disconnecting " + contextTypeToString(mContextTypeToDisconnect) + " from " + mDevice); - transitionTo(mDisconnected); - } - transitionTo(mDisconnecting); - } else if (IsReconfigRequested) { - Log.w(TAG, "Reconfig requested Exclusive Access"); - if (!mAcmNativeInterface.ChangeCodecConfigPreference(mDevice, mReconfig)) { // this context Type is passed in disconnect api from APM - Log.e(TAG, "reconfig error " + mDevice); - break; - } - } - } - } break; - - case CSIP_CONNECTION_STATE_CHANGED: - int state = (int)message.obj; - if (state == BluetoothProfile.STATE_DISCONNECTED) - mCsipConnectionState = BluetoothProfile.STATE_DISCONNECTED; - break; - - case CSIP_LOCK_RELEASE_TIMEOUT: - //lock release individual ? - Log.d(TAG, "Exclusive Access timeout to " + mDevice); - List devices = new ArrayList(); - devices.add(mDevice); - mAcmService.getCsipManager().setLock(mSetId, devices, mAcmService.getCsipManager().UNLOCK); - mDeviceLocked = false; - break; - - case CSIP_LOCK_STATUS_RELEASED: - // ignore disconnect CSIP - removeMessages(CSIP_LOCK_RELEASE_TIMEOUT); - mDeviceLocked = false; - break; - - case CODEC_CONFIG_CHANGED: { - IsReconfigRequested = true; - mReconfig = mAcmService.getAcmName(); - if (!mAcmNativeInterface.ChangeCodecConfigPreference(mDevice, mReconfig)) { - Log.e(TAG, "reconfig error " + mDevice); - break; - } - /*int setId = (int)message.obj; - int st = mAcmService.getCsipConnectionState(mDevice); - if ((mDeviceLocked && st == BluetoothProfile.STATE_CONNECTED)) { - Log.w(TAG, "Device is already acquired and DeviceGroup is in connected state"); - if (!mAcmNativeInterface.ChangeCodecConfigPreference(mDevice, mReconfig)) { - Log.e(TAG, "reconfig error " + mDevice); - break; - } - break; - } - //mSetId = mSetCoordinator.getRemoteDeviceSetId(mDevice, null); //TODO: UUID what to set ? - List members = new ArrayList(); - Iterator i = mAcmService.getCsipManager().getSetMembers(setId).iterator(); - if (i != null) { - while (i.hasNext()) { - BluetoothDevice device = i.next(); - if (mAcmService.getCsipConnectionState(device) == BluetoothProfile.STATE_CONNECTED) { - members.add(device); - } - } - } - mAcmService.getCsipManager().setLock(setId, - members, mAcmService.getCsipManager().LOCK);*/ - } break; - - case STOP_STREAM: { - int value = (int)message.obj; - if (!mAcmNativeInterface.stopStream(mDevice, value)) { - Log.e(TAG, "start stream error " + mDevice); - break; - } - /*int setId = (int)message.obj; - int st = mAcmService.getCsipConnectionState(mDevice); - if ((mDeviceLocked && st == BluetoothProfile.STATE_CONNECTED)) { - Log.w(TAG, "Device access is already granted and DeviceGroup is in connected state"); - if (!mAcmNativeInterface.ChangeCodecConfigPreference(mDevice, mReconfig)) { - Log.e(TAG, "reconfig error " + mDevice); - break; - } - break; - } - //mSetId = mSetCoordinator.getRemoteDeviceSetId(mDevice, null ); //TODO: UUID what to set ? - List members = new ArrayList(); - Iterator i = mAcmService.getCsipManager().getSetMembers(mSetId).iterator(); - if (i != null) { - while (i.hasNext()) { - BluetoothDevice device = i.next(); - if (mAcmService.getCsipConnectionState(device) == BluetoothProfile.STATE_CONNECTED) { - members.add(device); - } - } - } - mAcmService.getCsipManager().setLock(mSetId, members, mAcmService.getCsipManager().LOCK);*/ - } break; - - case START_STREAM: - int value = (int)message.obj; - if (value == CONTEXT_TYPE_VOICE && mIsMusicPlaying) { - deferMessage(obtainMessage(START_STREAM_REQ, value)); - Log.wtf(TAG, "Defer START request for voice context"); - } - break; - - case STACK_EVENT: - AcmStackEvent event = (AcmStackEvent) message.obj; - log("Streaming: stack event: " + event); - if (!mDevice.equals(event.device)) { - Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); - } - switch (event.type) { - case AcmStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - processConnectionEvent(event.valueInt1, event.valueInt2); - break; - case AcmStackEvent.EVENT_TYPE_AUDIO_STATE_CHANGED: - processAudioStateEvent(event.valueInt1, event.valueInt2); - break; - case AcmStackEvent.EVENT_TYPE_CODEC_CONFIG_CHANGED: - processCodecConfigEvent(event.codecStatus, event.valueInt2); - break; - default: - Log.e(TAG, "Streaming: ignoring stack event: " + event); - break; - } - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - - // in Streaming state - private void processConnectionEvent(int event, int contextType) { - IState smState; - switch (event) { - case AcmStackEvent.CONNECTION_STATE_DISCONNECTED: { - //TODO: sendMessageDelayed(CSIP_LOCK_RELEASE_TIMEOUT, sCsipLockReleaseTimeoutMs); - Log.w(TAG, "Streaming device disconnected: " + mDevice); - StreamAudioService service = StreamAudioService.getStreamAudioService(); - mCurrentContextType -= contextType; - Log.i(TAG, "mCurrentContextType now is " + contextTypeToString(mCurrentContextType)); - processTransitionContextState(mDisconnecting, mDisconnected, contextType); - if (contextType == CONTEXT_TYPE_MUSIC) { - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - } else { - Log.d(TAG, "Last member to disconnect, update MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, true); - } - transitionTo(mConnected); - } else if (mContextTypeToDisconnect == CONTEXT_TYPE_VOICE) { - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } else { - Log.d(TAG, "Last member to disconnect, update VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, true); - } - } - } break; - - case AcmStackEvent.CONNECTION_STATE_CONNECTED: { - StreamAudioService service = StreamAudioService.getStreamAudioService(); - //TODO:sendMessageDelayed(CSIP_LOCK_RELEASE_TIMEOUT, sCsipLockReleaseTimeoutMs); - Log.w(TAG, "ACM CONNECTED event for device: " + mDevice + " context type: " + contextTypeToString(contextType)); - if (contextType == CONTEXT_TYPE_MUSIC) { - mMusicConnectionState = BluetoothProfile.STATE_CONNECTED; - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - } else { - Log.d(TAG, "First member of group to connect MUSIC"); - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, true); - } - } else if (contextType == CONTEXT_TYPE_VOICE) { - mVoiceConnectionState = BluetoothProfile.STATE_CONNECTED; - if (mAcmService.isPeerDeviceConnected(mDevice, mSetId)) { - Log.d(TAG, "Fellow device is already connected, update VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } else { - Log.d(TAG, "First member of group to connect VOICE"); - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, true); - } - } - } break; - - case AcmStackEvent.CONNECTION_STATE_CONNECTING: { - Log.w(TAG, "ACM CONNECTING event: " + mDevice); - } break; - - case AcmStackEvent.CONNECTION_STATE_DISCONNECTING: { - if ((contextType == CONTEXT_TYPE_MUSIC) && - (mMusicConnectionState == BluetoothProfile.STATE_DISCONNECTING)) { - Log.w(TAG, "Ignore Disconnecting for media - already disconnecting"); - } else if ((contextType == CONTEXT_TYPE_VOICE) && - (mVoiceConnectionState == BluetoothProfile.STATE_DISCONNECTING)) { - Log.w(TAG, "Ignore Disconnecting for voice - already disconnecting"); - } else { - smState = mDisconnecting; - Log.w(TAG, "Connected device disconnecting: " + mDevice); - if ((mMusicConnectionState == BluetoothProfile.STATE_CONNECTED) && - (mVoiceConnectionState == BluetoothProfile.STATE_CONNECTED)) { - if (contextType != CONTEXT_TYPE_MUSIC_VOICE) { - /*only 1/2 contexts are being disconnected, - remain in connecting state but broadcast the connection state*/ - smState = mConnected; - } - } - processTransitionContextState(mConnected, mDisconnecting, contextType); - StreamAudioService service = StreamAudioService.getStreamAudioService(); - if (smState == mConnected) { - if (contextType == CONTEXT_TYPE_MUSIC) { - service.onConnectionStateChange(mDevice, mMusicConnectionState, CONTEXT_TYPE_MUSIC, false); - } else if (contextType == CONTEXT_TYPE_VOICE) { - service.onConnectionStateChange(mDevice, mVoiceConnectionState, ApmConst.AudioFeatures.CALL_AUDIO, false); - } - } else { - transitionTo(smState); - } - } - } break; - - default: - Log.e(TAG, "Connection State Device: " + mDevice + " bad event: " + event); - break; - } - } - - // in Streaming state - private void processAudioStateEvent(int state, int contextType) { - Log.i(TAG, "Streaming: processAudioStateEvent: state: " + state + "mIsMusicPlaying: " + mIsMusicPlaying); - switch (state) { - case AcmStackEvent.AUDIO_STATE_STARTED: - Log.i(TAG, "Streaming: already started: " + mDevice); - break; - case AcmStackEvent.AUDIO_STATE_REMOTE_SUSPEND: - case AcmStackEvent.AUDIO_STATE_STOPPED: - synchronized (this) { - StreamAudioService service = StreamAudioService.getStreamAudioService(); - if (contextType == CONTEXT_TYPE_MUSIC) { - if (mIsMusicPlaying) { - Log.i(TAG, "Streaming: stopped media playing: " + mDevice); - mIsMusicPlaying = false; - service.onStreamStateChange(mDevice, BluetoothA2dp.STATE_NOT_PLAYING, CONTEXT_TYPE_MUSIC); - if (mAcmService.isShoPendingStop()) { - Log.i(TAG, "Streaming: SHO was pending earlier, complete now"); - mAcmService.resetShoPendingStop(); - service.onActiveDeviceChange(null, ApmConst.AudioFeatures.MEDIA_AUDIO); - } - transitionTo(mConnected); - } - } - if (contextType == CONTEXT_TYPE_VOICE) { - if (mIsVoicePlaying) { - Log.i(TAG, "Streaming: stopped voice playing: " + mDevice); - mIsVoicePlaying = false; - service.onStreamStateChange(mDevice, BluetoothHeadset.STATE_AUDIO_DISCONNECTED, ApmConst.AudioFeatures.CALL_AUDIO); - setCallAudioOn(false); - if (mAcmService.isVoiceShoPendingStop()) { - Log.i(TAG, "Voice SHO was pending earlier, complete now"); - mAcmService.resetVoiceShoPendingStop(); - service.onActiveDeviceChange(mAcmService.getVoiceActiveDevice(), ApmConst.AudioFeatures.CALL_AUDIO); - } - transitionTo(mConnected); - } - } - } - break; - default: - Log.e(TAG, "Audio State Device: " + mDevice + " bad state: " + state); - break; - } - } - } - - private String getFrameDuration() { - BluetoothCodecConfig mCodecConfig = mVoiceCodecStatus.getCodecConfig(); - long cs1 = mCodecConfig.getCodecSpecific1() >> 32 & 0xff; - if (cs1 == 0x00) { - return "7.5"; - } else { - return "10"; - } - } - - private String getLc3BlocksPerSdu() { - BluetoothCodecConfig mCodecConfig = mVoiceCodecStatus.getCodecConfig(); - long cs1 = mCodecConfig.getCodecSpecific1() >> 40 & 0xff; - return Integer.toString((int)cs1); - } - - private String getCodectype() { - BluetoothCodecConfig mCodecConfig = mVoiceCodecStatus.getCodecConfig(); - long cs3 = (mCodecConfig.getCodecSpecific3() >> - (CS_PARAM_NUM_BITS * CS_PARAM_1ST_INDEX)) & CS_PARAM_IND_MASK; - if (cs3 == CODEC_TYPE_LC3Q) { - return "LC3Q"; - } else { - return "LC3"; - } - } - - private String getLc3qValues() { - BluetoothCodecConfig mCodecConfig = mVoiceCodecStatus.getCodecConfig(); - long cs3 = mCodecConfig.getCodecSpecific3(); - long cs4 = mCodecConfig.getCodecSpecific4(); - - String vsMetaDataLc3qVal = String.join(",", new String[]{ - String.format("%02X", ((cs4 >> - (CS_PARAM_NUM_BITS * CS_PARAM_8TH_INDEX)) & CS_PARAM_IND_MASK)), - String.format("%02X", ((cs4 >> - (CS_PARAM_NUM_BITS * CS_PARAM_7TH_INDEX)) & CS_PARAM_IND_MASK)), - String.format("%02X", ((cs4 >> - (CS_PARAM_NUM_BITS * CS_PARAM_6TH_INDEX)) & CS_PARAM_IND_MASK)), - String.format("%02X", ((cs4 >> - (CS_PARAM_NUM_BITS * CS_PARAM_5TH_INDEX)) & CS_PARAM_IND_MASK)), - String.format("%02X", ((cs4 >> - (CS_PARAM_NUM_BITS * CS_PARAM_4TH_INDEX)) & CS_PARAM_IND_MASK)), - String.format("%02X", ((cs4 >> - (CS_PARAM_NUM_BITS * CS_PARAM_3RD_INDEX)) & CS_PARAM_IND_MASK)), - String.format("%02X", ((cs4 >> - (CS_PARAM_NUM_BITS * CS_PARAM_2ND_INDEX)) & CS_PARAM_IND_MASK)), - String.format("%02X", ((cs4 >> - (CS_PARAM_NUM_BITS * CS_PARAM_1ST_INDEX)) & CS_PARAM_IND_MASK)), - String.format("%02X", ((cs3 >> - (CS_PARAM_NUM_BITS * CS_PARAM_8TH_INDEX)) & CS_PARAM_IND_MASK)), - String.format("%02X", (((cs3 >> - (CS_PARAM_NUM_BITS * CS_PARAM_2ND_INDEX)) & CS_PARAM_IND_MASK) & 0x01)), - String.format("%02X", ((cs3 >> - (CS_PARAM_NUM_BITS * CS_PARAM_1ST_INDEX)) & CS_PARAM_IND_MASK)), - String.format("%02X", ((cs3 >> - (CS_PARAM_NUM_BITS * CS_PARAM_7TH_INDEX)) & CS_PARAM_IND_MASK)), - String.format("%02X", ((cs3 >> - (CS_PARAM_NUM_BITS * CS_PARAM_6TH_INDEX)) & CS_PARAM_IND_MASK)), - String.format("%02X", ((cs3 >> - (CS_PARAM_NUM_BITS * CS_PARAM_5TH_INDEX)) & CS_PARAM_IND_MASK)), - String.format("%02X", ((cs3 >> - (CS_PARAM_NUM_BITS * CS_PARAM_4TH_INDEX)) & CS_PARAM_IND_MASK)), - String.format("%02X", ((cs3 >> - (CS_PARAM_NUM_BITS * CS_PARAM_3RD_INDEX)) & CS_PARAM_IND_MASK)) - }); - Log.i(TAG, "getLc3qValues() for " + mDevice + ": " + vsMetaDataLc3qVal); - return vsMetaDataLc3qVal; - } - - private String getRxTxConfigIndex() { - BluetoothCodecConfig mCodecConfig = mVoiceCodecStatus.getCodecConfig(); - int sampleRate = mCodecConfig.getSampleRate(); - long cs1 = mCodecConfig.getCodecSpecific1() >> 0 & 0xff; - if (sampleRate == BluetoothCodecConfig.SAMPLE_RATE_8000) { - if (cs1 == 0x01) { - return "0"; - } else { - return "1"; - } - } else if (sampleRate == BluetoothCodecConfig.SAMPLE_RATE_16000) { - if (cs1 == 0x01) { - return "2"; - } else { - return "3"; - } - } else if (sampleRate == BluetoothCodecConfig.SAMPLE_RATE_32000) { - if (cs1 == 0x01) { - return "4"; - } else { - return "5"; - } - } - return "0"; - } - - private void setVoiceParameters() { - String keyValuePairs = String.join(";", new String[]{ - CODEC_NAME + "=" + "LC3", - STREAM_MAP + "=" + "(0, 0, M, 0, 1, L),(1, 0, M, 1, 1, R)", - FRAME_DURATION + "=" + getFrameDuration(), - SDU_BLOCK + "=" + getLc3BlocksPerSdu(), - RXCONFIG_INDX + "=" + getRxTxConfigIndex(), - TXCONFIG_INDX + "=" + getRxTxConfigIndex(), - VERSION + "=" + "21", - VENDOR_META_DATA + "=" + getLc3qValues() - }); - Log.i(TAG, "setVoiceParameters for " + mDevice + ": " + keyValuePairs); - StreamAudioService service = StreamAudioService.getStreamAudioService(); - service.setCallAudioParam(keyValuePairs); - } - - private void setCallAudioOn(boolean on) { - Log.i(TAG, "set Call Audio On: " + on); - StreamAudioService service = StreamAudioService.getStreamAudioService(); - service.setCallAudioOn(on); - } - - int getConnectionState() { - return mConnectionState; - } - - int getCsipConnectionState() { - return mCsipConnectionState; - } - - BluetoothDevice getDevice() { - return mDevice; - } - - BluetoothDevice getPeerDevice() { - BluetoothDevice d = null; - List members = mAcmService.getCsipManager().getSetMembers(mSetId); - if (members == null) { - Log.d(TAG, "No set member found"); - return d; - } - Iterator i = members.iterator(); - if (i != null) { - while (i.hasNext()) { - d = i.next(); - if (!(Objects.equals(d, mDevice))) { - Log.d(TAG, "Device: " + d); - break; - } - } - } - return d; - } - - void removeDevicefromBgWL() { - Log.d(TAG, "remove device from BG WL"); - if (mBluetoothGatt != null && mIsDeviceWhitelisted) { - mIsDeviceWhitelisted = false; - mBluetoothGatt.disconnect(); - } - } - - boolean isConnected() { - synchronized (this) { - return (getConnectionState() == BluetoothProfile.STATE_CONNECTED); - } - } - - boolean isCsipLockRequested() { - synchronized (this) { - return mCsipLockRequested; - } - } - - boolean isMusicPlaying() { - synchronized (this) { - return mIsMusicPlaying; - } - } - - boolean isVoicePlaying() { - synchronized (this) { - return mIsVoicePlaying; - } - } - - private void processTransitionContextState(IState prevState, IState nextState, int contextType) { - int pState = AcmStateToBluetoothProfileState(prevState); - int nState = AcmStateToBluetoothProfileState(nextState); - if (contextType == CONTEXT_TYPE_MUSIC) { - mLastMusicConnectionState = pState; - mMusicConnectionState = nState; - } else if (contextType == CONTEXT_TYPE_VOICE) { - mLastVoiceConnectionState = pState; - mVoiceConnectionState = nState; - } else if (contextType == CONTEXT_TYPE_MUSIC_VOICE) { - mLastMusicConnectionState = pState; - mLastVoiceConnectionState = pState; - mMusicConnectionState = nState; - mVoiceConnectionState = nState; - } - } - - // NOTE: This event is processed in any state - @VisibleForTesting - void processCodecConfigEvent(BluetoothCodecStatus newCodecStatus, int contextType) { - Log.d(TAG,"ProcessCodecConfigEvent: context type :" + contextType); - if (contextType == CONTEXT_TYPE_MUSIC) { - BluetoothCodecConfig mCodecConfig = newCodecStatus.getCodecConfig(); - long cs3 = mCodecConfig.getCodecSpecific3(); - cs3 |= LE_AUDIO_AVAILABLE_LICENSED; - BluetoothCodecConfig mCodecConfigLc3 = - new BluetoothCodecConfig.Builder() - .setCodecType(mCodecConfig.getCodecType()) - .setCodecPriority(mCodecConfig.getCodecPriority()) - .setSampleRate(mCodecConfig.getSampleRate()) - .setBitsPerSample(mCodecConfig.getBitsPerSample()) - .setChannelMode(mCodecConfig.getChannelMode()) - .setCodecSpecific1(mCodecConfig.getCodecSpecific1()) - .setCodecSpecific2(mCodecConfig.getCodecSpecific2()) - .setCodecSpecific3(cs3) - .setCodecSpecific4(mCodecConfig.getCodecSpecific4()) - .build(); - - mMusicCodecStatus = new BluetoothCodecStatus(mCodecConfigLc3, - newCodecStatus.getCodecsLocalCapabilities(), - newCodecStatus.getCodecsSelectableCapabilities()); - StreamAudioService service = StreamAudioService.getStreamAudioService(); - service.onMediaCodecConfigChange(mGroupAddress, mMusicCodecStatus, contextType); - } else if (contextType == CONTEXT_TYPE_VOICE) { - mVoiceCodecStatus = newCodecStatus; - } - } - - @Override - protected String getLogRecString(Message msg) { - StringBuilder builder = new StringBuilder(); - builder.append(messageWhatToString(msg.what)); - builder.append(": "); - builder.append("arg1=") - .append(msg.arg1) - .append(", arg2=") - .append(msg.arg2) - .append(", obj=") - .append(msg.obj); - return builder.toString(); - } - - private static boolean sameSelectableCodec(BluetoothCodecStatus prevCodecStatus, - BluetoothCodecStatus newCodecStatus) { - if (prevCodecStatus == null) { - return false; - } - return BluetoothCodecStatus.sameCapabilities( - prevCodecStatus.getCodecsSelectableCapabilities(), - newCodecStatus.getCodecsSelectableCapabilities()); - } - - 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 contextTypeToString(int contextType) { - switch (contextType) { - case CONTEXT_TYPE_UNKNOWN: - return "UNKNOWN"; - case CONTEXT_TYPE_MUSIC: - return "MEDIA"; - case CONTEXT_TYPE_VOICE: - return "CONVERSATIONAL"; - case CONTEXT_TYPE_MUSIC_VOICE: - return "MEDIA+CONVERSATIONAL"; - default: - break; - } - return Integer.toString(contextType); - } - - 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); - } - - /*private static String musicAudioStateToString(int state) { - switch (state) { - case BluetoothA2dp.STATE_PLAYING: - return "PLAYING"; - case BluetoothA2dp.STATE_NOT_PLAYING: - return "NOT_PLAYING"; - default: - break; - } - return Integer.toString(state); - }*/ - - private static String voiceAudioStateToString(int state) { - switch (state) { - case BluetoothHeadset.STATE_AUDIO_DISCONNECTED: - return "AUDIO_DISCONNECTED"; - case BluetoothHeadset.STATE_AUDIO_CONNECTING: - return "AUDIO_CONNECTING"; - case BluetoothHeadset.STATE_AUDIO_CONNECTED: - return "AUDIO_CONNECTED"; - case BluetoothHeadset.STATE_AUDIO_DISCONNECTING: - return "AUDIO_DISCONNECTING"; - default: - break; - } - return Integer.toString(state); - } - - private static int AcmStateToBluetoothProfileState(IState state) { - if (state instanceof Disconnected) { - return BluetoothProfile.STATE_DISCONNECTED; - } else if (state instanceof Connecting) { - return BluetoothProfile.STATE_CONNECTING; - } else if (state instanceof Connected) { - return BluetoothProfile.STATE_CONNECTED; - } else if (state instanceof Disconnecting) { - return BluetoothProfile.STATE_DISCONNECTING; - } - Log.w(TAG, "Unknown State"); - return BluetoothProfile.STATE_DISCONNECTED; - } - - public void dump(StringBuilder sb) { - ProfileService.println(sb, "mDevice: " + mDevice); - ProfileService.println(sb, " StateMachine: " + this.toString()); - ProfileService.println(sb, " mIsMusicPlaying: " + mIsMusicPlaying); - synchronized (this) { - if (mVoiceCodecStatus != null) { - ProfileService.println(sb, " Voice mCodecConfig: " + mVoiceCodecStatus.getCodecConfig()); - } - if (mMusicCodecStatus != null) { - ProfileService.println(sb, " Music mCodecConfig: " + mMusicCodecStatus.getCodecConfig()); - } - } - // Dump the state machine logs - StringWriter stringWriter = new StringWriter(); - PrintWriter printWriter = new PrintWriter(stringWriter); - super.dump(new FileDescriptor(), printWriter, new String[]{}); - printWriter.flush(); - stringWriter.flush(); - ProfileService.println(sb, " StateMachineLog:"); - Scanner scanner = new Scanner(stringWriter.toString()); - while (scanner.hasNextLine()) { - String line = scanner.nextLine(); - ProfileService.println(sb, " " + line); - } - scanner.close(); - } - - @Override - protected void log(String msg) { - if (DBG) { - super.log(msg); - } - } -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/ActiveDeviceManagerService.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/ActiveDeviceManagerService.java deleted file mode 100644 index dfcabf14f1ebc1d62f7b79b44c4d6281083d6b14..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/ActiveDeviceManagerService.java +++ /dev/null @@ -1,1444 +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. - * - ******************************************************************************/ - - -/** - * Bluetooth ActiveDeviceManagerService. There is one instance each for - * voice and media profile management.. - * - "Idle" and "Active" are steady states. - * - "Activating" and "Deactivating" are transient states until the - * SHO / Deactivation is completed. - * - * - * (Idle) - * | ^ - * SetActive | | Removed - * V | - * (Activating) (Deactivating) - * | ^ - * Activated | | setActive(NULL) / removeDevice - * V | - * (Active / Broadcasting) - * - * - */ - -package com.android.bluetooth.apm; - -import static android.Manifest.permission.BLUETOOTH_CONNECT; - -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; -import android.bluetooth.BluetoothA2dp; -import android.bluetooth.BluetoothHeadset; -import com.android.bluetooth.Utils; -import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.btservice.ActiveDeviceManager; -import com.android.bluetooth.btservice.ProfileService; -import com.android.bluetooth.a2dp.A2dpService; -import com.android.bluetooth.hearingaid.HearingAidService; -import com.android.bluetooth.hfp.HeadsetService; -import com.android.bluetooth.mcp.McpService; -import com.android.bluetooth.broadcast.BroadcastService; -import com.android.bluetooth.cc.CCService; -import android.content.Intent; -import android.content.Context; -import android.os.Looper; -import android.os.Message; -import android.os.HandlerThread; -import android.os.UserHandle; -import android.os.SystemProperties; -import android.util.Log; -import android.media.AudioManager; - -import com.android.bluetooth.BluetoothStatsLog; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.lang.Boolean; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.lang.Integer; -import java.util.Scanner; -import java.util.Objects; - -public class ActiveDeviceManagerService { - private static final boolean DBG = true; - private static final String TAG = "APM: ActiveDeviceManagerService"; - private static ActiveDeviceManagerService sActiveDeviceManager = null; - private AudioManager mAudioManager; - private HandlerThread[] thread = new HandlerThread[AudioType.SIZE]; - private ShoStateMachine[] sm = new ShoStateMachine[AudioType.SIZE]; - private ApmNativeInterface apmNative; - private Context mContext; - private boolean txStreamSuspended = false; - private final Lock lock = new ReentrantLock(); - private final Condition mediaHandoffComplete = lock.newCondition(); - private final Condition voiceHandoffComplete = lock.newCondition(); - static class Event { - static final int SET_ACTIVE = 1; - static final int ACTIVE_DEVICE_CHANGE = 2; - static final int REMOVE_DEVICE = 3; - static final int DEVICE_REMOVED = 4; - static final int ACTIVATE_TIMEOUT = 5; - static final int DEACTIVATE_TIMEOUT = 6; - static final int SUSPEND_RECORDING = 7; - static final int RESUME_RECORDING = 8; - static final int RETRY_DEACTIVATE = 9; - static final int STOP_SM = 0; - } - - public static final int SHO_SUCCESS = 0; - public static final int SHO_PENDING = 1; - public static final int SHO_FAILED = 2; - public static final int ALREADY_ACTIVE = 3; - - static final int RETRY_LIMIT = 4; - static final int ACTIVATE_TIMEOUT_DELAY = 3000; - static final int DEACTIVATE_TIMEOUT_DELAY = 2000; - static final int DEACTIVATE_TRY_DELAY = 500; - - private ActiveDeviceManagerService (Context context) { - thread[AudioType.MEDIA] = new HandlerThread("ActiveDeviceManager.MediaThread"); - thread[AudioType.MEDIA].start(); - Looper mediaLooper = thread[AudioType.MEDIA].getLooper(); - sm[AudioType.MEDIA] = new ShoStateMachine(AudioType.MEDIA, mediaLooper); - - thread[AudioType.VOICE] = new HandlerThread("ActiveDeviceManager.VoiceThread"); - thread[AudioType.VOICE].start(); - Looper voiceLooper = thread[AudioType.VOICE].getLooper(); - sm[AudioType.VOICE] = new ShoStateMachine(AudioType.VOICE, voiceLooper); - - mContext = context; - apmNative = ApmNativeInterface.getInstance(); - apmNative.init(); - - mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); - Objects.requireNonNull(mAudioManager, - "AudioManager cannot be null when ActiveDeviceManagerService starts"); - } - - public static ActiveDeviceManagerService get(Context context) { - if(sActiveDeviceManager == null) { - sActiveDeviceManager = new ActiveDeviceManagerService(context); - ActiveDeviceManagerServiceIntf.init(sActiveDeviceManager); - } - return sActiveDeviceManager; - } - - public static ActiveDeviceManagerService get() { - return sActiveDeviceManager; - } - - public boolean setActiveDevice(BluetoothDevice device, Integer mAudioType, Boolean isUIReq, Boolean playReq) { - Log.d(TAG, "setActiveDevice(" + device + ") audioType: " + mAudioType); - boolean isCallActive = false; - if(ApmConst.AudioFeatures.CALL_AUDIO == mAudioType) { - CallAudio mCallAudio = CallAudio.get(); - isCallActive = mCallAudio.isAudioOn(); - } - - synchronized(sm[mAudioType]) { - sm[mAudioType].mSHOQueue.device = device; - sm[mAudioType].mSHOQueue.isUIReq = isUIReq; - sm[mAudioType].mSHOQueue.PlayReq = (playReq || isCallActive); - sm[mAudioType].mSHOQueue.isBroadcast = false; - sm[mAudioType].mSHOQueue.isRecordingMode = false; - sm[mAudioType].mSHOQueue.isGamingMode = false; - } - - if(device != null) { - sm[mAudioType].sendMessage(Event.SET_ACTIVE); - } - else { - if (mAudioType == AudioType.MEDIA && sm[mAudioType].mState == sm[mAudioType].mBroadcasting) { - Log.d(TAG, "LE Broadcast is active, ignore REMOVE_DEVICE"); - } else { - sm[mAudioType].sendMessage(Event.REMOVE_DEVICE); - } - } - return isUIReq; - } - - public boolean setActiveDevice(BluetoothDevice device, Integer mAudioType, Boolean isUIReq) { - return setActiveDevice(device, mAudioType, isUIReq, false); - } - - public boolean setActiveDevice(BluetoothDevice device, Integer mAudioType) { - return setActiveDevice(device, mAudioType, false, false); - } - - public boolean setActiveDeviceBlocking(BluetoothDevice device, Integer mAudioType) { - Log.d(TAG, "setActiveDeviceBlocking: Enter"); - if(ApmConst.AudioFeatures.CALL_AUDIO == mAudioType) { - setActiveDevice(device, mAudioType, false, false); - try { - lock.lock(); - voiceHandoffComplete.await(); - } catch (InterruptedException e) { - Log.d(TAG, "setActiveDeviceBlocking: Unblocked because of exception: " + e); - } finally { - Log.d(TAG, "setActiveDeviceBlocking: unlock"); - lock.unlock(); - } - } - Log.d(TAG, "setActiveDeviceBlocking: Exit"); - return true; - } - - public BluetoothDevice getQueuedDevice(Integer mAudioType) { - return sm[mAudioType].mSHOQueue.device; - } - - public boolean removeActiveDevice(Integer mAudioType, Boolean forceStopAudio) { - sm[mAudioType].mSHOQueue.forceStopAudio = forceStopAudio; - setActiveDevice(null, mAudioType, false); - return true; - } - - public BluetoothDevice getActiveDevice(Integer mAudioType) { - return sm[mAudioType].Current.Device; - } - - public int getActiveProfile(Integer mAudioType) { - if(sm[mAudioType].mState == sm[mAudioType].mBroadcasting) { - // Use Current.Profile here - return ApmConst.AudioProfiles.BROADCAST_LE; - } else if(sm[mAudioType].mState == sm[mAudioType].mActive) { - return sm[mAudioType].Current.Profile; - } - return ApmConst.AudioProfiles.NONE; - } - - public boolean onActiveDeviceChange(BluetoothDevice device, Integer mAudioType) { - return onActiveDeviceChange(device, mAudioType, ApmConst.AudioProfiles.NONE); - } - - public boolean onActiveDeviceChange(BluetoothDevice device, Integer mAudioType, Integer mProfile) { - if (device != null || mProfile == ApmConst.AudioProfiles.BROADCAST_LE) { - DeviceProfileCombo mDeviceProfileCombo = new DeviceProfileCombo(device, mProfile); - sm[mAudioType].sendMessage(Event.ACTIVE_DEVICE_CHANGE, mDeviceProfileCombo); - } - else - sm[mAudioType].sendMessage(Event.DEVICE_REMOVED); - return true; - } - - public boolean enableBroadcast(BluetoothDevice device) { - synchronized(sm[AudioType.MEDIA]) { - sm[AudioType.MEDIA].mSHOQueue.device = device; - sm[AudioType.MEDIA].mSHOQueue.isBroadcast = true; - sm[AudioType.MEDIA].mSHOQueue.PlayReq = false; - } - sm[AudioType.MEDIA].sendMessage(Event.SET_ACTIVE); - return true; - } - - public boolean disableBroadcast() { - Log.d(TAG, "disableBroadcast"); - synchronized(sm[AudioType.MEDIA]) { - sm[AudioType.MEDIA].mSHOQueue.isBroadcast = false; - sm[AudioType.MEDIA].mSHOQueue.PlayReq = false; - } - if (sm[AudioType.MEDIA].mState == sm[AudioType.MEDIA].mBroadcasting) { - sm[AudioType.MEDIA].sendMessage(Event.REMOVE_DEVICE); - } - return true; - } - - public boolean enableGaming(BluetoothDevice device) { - if (sm[AudioType.MEDIA].mState == sm[AudioType.MEDIA].mGamingMode && - device.equals(getActiveDevice(AudioType.MEDIA))) { - Log.d(TAG, "Device already in Gaming Mode"); - return true; - } - - Log.d(TAG, "enableGaming"); - synchronized(sm[AudioType.MEDIA]) { - sm[AudioType.MEDIA].mSHOQueue.device = device; - sm[AudioType.MEDIA].mSHOQueue.isBroadcast = false; - sm[AudioType.MEDIA].mSHOQueue.isGamingMode = true; - sm[AudioType.MEDIA].mSHOQueue.PlayReq = false; - } - sm[AudioType.MEDIA].sendMessage(Event.SET_ACTIVE); - return true; - } - - public boolean disableGaming(BluetoothDevice device) { - if (sm[AudioType.MEDIA].mState != sm[AudioType.MEDIA].mGamingMode) { - Log.e(TAG, "Gaming Mode not active"); - return true; - } - - /*MediaAudio mMediaAudio = MediaAudio.get(); - if(mMediaAudio != null && mMediaAudio.isA2dpPlaying(device)) { - Log.w(TAG, "Gaming Stream is Active"); - return false; - }*/ - - Log.d(TAG, "disableGaming"); - synchronized(sm[AudioType.MEDIA]) { - sm[AudioType.MEDIA].mSHOQueue.device = device; - sm[AudioType.MEDIA].mSHOQueue.isGamingMode = false; - sm[AudioType.MEDIA].mSHOQueue.PlayReq = false; - sm[AudioType.MEDIA].mSHOQueue.isUIReq = true; - } - - //sm[AudioType.MEDIA].sendMessageDelayed(Event.SET_ACTIVE, DEACTIVATE_TRY_DELAY); - sm[AudioType.MEDIA].sendMessage(Event.SET_ACTIVE); - return true; - } - - public boolean enableRecording(BluetoothDevice device) { - Log.d(TAG, "enableRecording: " + device); - - MediaAudio mMediaAudio = MediaAudio.get(); - if(txStreamSuspended == false) { - Log.d(TAG, "Set A2dpSuspended=true"); - mAudioManager.setParameters("A2dpSuspended=true"); - txStreamSuspended = true; - } - - synchronized(sm[AudioType.MEDIA]) { - sm[AudioType.MEDIA].mSHOQueue.device = device; - sm[AudioType.MEDIA].mSHOQueue.isBroadcast = false; - sm[AudioType.MEDIA].mSHOQueue.isGamingMode = false; - sm[AudioType.MEDIA].mSHOQueue.isRecordingMode = true; - sm[AudioType.MEDIA].mSHOQueue.PlayReq = false; - sm[AudioType.MEDIA].mSHOQueue.isUIReq = true; - } - sm[AudioType.MEDIA].sendMessage(Event.SET_ACTIVE); - return true; - } - - public boolean disableRecording(BluetoothDevice device) { - Log.d(TAG, "disableRecording: " + device); - - synchronized(sm[AudioType.MEDIA]) { - sm[AudioType.MEDIA].mSHOQueue.device = device; - sm[AudioType.MEDIA].mSHOQueue.isRecordingMode = false; - sm[AudioType.MEDIA].mSHOQueue.PlayReq = false; - } - - if (sm[AudioType.MEDIA].mState == sm[AudioType.MEDIA].mRecordingMode) { - sm[AudioType.MEDIA].sendMessage(Event.SET_ACTIVE); - } - return true; - } - - public boolean suspendRecording(Boolean suspend) { - Log.d(TAG, "suspendRecording: " + suspend); - - if(sm[AudioType.MEDIA].mState == sm[AudioType.MEDIA].mRecordingMode) { - if(suspend) { - sm[AudioType.MEDIA].sendMessage(Event.SUSPEND_RECORDING); - } else { - sm[AudioType.MEDIA].sendMessage(Event.RESUME_RECORDING); - } - } - return true; - } - - public boolean isRecordingActive(BluetoothDevice device) { - Log.d(TAG, "isRecordingActive"); - return sm[AudioType.MEDIA].mState == sm[AudioType.MEDIA].mRecordingMode; - } - - public boolean isStableState(int mAudioType) { - State state = sm[mAudioType].mState; - return !(sm[mAudioType].mActivating == state || sm[mAudioType].mDeactivating == state); - } - - private void broadcastActiveDeviceChange(BluetoothDevice device, int mAudioType) { - if (DBG) { - Log.d(TAG, "broadcastActiveDeviceChange(" + device + ")"); - } - Intent intent; - - /*if (mAdapterService != null) - BluetoothStatsLog.write(BluetoothStatsLog.BLUETOOTH_ACTIVE_DEVICE_CHANGED, BluetoothProfile.A2DP, - mAdapterService.obfuscateAddress(device), 0);*/ - - if(mAudioType == AudioType.MEDIA) - intent = new Intent(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED); - else - intent = new Intent(BluetoothHeadset.ACTION_ACTIVE_DEVICE_CHANGED); - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - if(mAudioType == AudioType.MEDIA) { - A2dpService mA2dpService = A2dpService.getA2dpService(); - if(mA2dpService == null) { - Log.e(TAG, "A2dp Service not ready"); - return; - } - mA2dpService.sendBroadcast(intent, BLUETOOTH_CONNECT); - } else { - HeadsetService mHeadsetService = HeadsetService.getHeadsetService(); - if(mHeadsetService == null) { - Log.e(TAG, "Headset Service not ready"); - return; - } - mHeadsetService.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_CONNECT, - Utils.getTempAllowlistBroadcastOptions()); - } - } - - public void disable() { - Log.d(TAG, "disable() called"); - sm[AudioType.MEDIA].sendMessage(Event.STOP_SM); - sm[AudioType.VOICE].sendMessage(Event.STOP_SM); - } - - public void cleanup() { - sm[AudioType.VOICE].doQuit(); - sm[AudioType.MEDIA].doQuit(); - thread[AudioType.VOICE].quitSafely(); - thread[AudioType.MEDIA].quitSafely(); - thread[AudioType.VOICE] = null; - thread[AudioType.MEDIA] = null; - sActiveDeviceManager = null; - } - - private class DeviceProfileCombo { - BluetoothDevice Device; - BluetoothDevice absoluteDevice; - int Profile; - - DeviceProfileCombo(BluetoothDevice mDevice, int mProfile) { - Device = mDevice; - Profile = mProfile; - } - - DeviceProfileCombo() { - Device = null; - Profile = ApmConst.AudioProfiles.NONE; - } - } - - private final class ShoStateMachine extends StateMachine { - private static final boolean DBG = true; - private static final String TAG = "APM: ActiveDeviceManagerService"; - - static final int IDLE = 0; - static final int ACTIVATING = 1; - static final int ACTIVE = 2; - static final int DEACTIVATING = 3; - static final int BROADCAST_ACTIVE = 4; - static final int GAMING_ACTIVE = 5; - static final int RECORDING_ACTIVE = 6; - - private Idle mIdle; - private Activating mActivating; - private Active mActive; - private Deactivating mDeactivating; - private Broadcasting mBroadcasting; - private Gaming mGamingMode; - private Recording mRecordingMode; - - private DeviceProfileCombo Current; - private DeviceProfileCombo Target; - private SHOReq mTargetSHO; - private SHOReq mSHOQueue; - - private DeviceProfileMap dpm; - - private int mAudioType; - private State mState; - private State mPrevState = null; - private BluetoothDevice mPrevActiveDevice; - private int mPrevActiveProfile = ApmConst.AudioProfiles.NONE; - boolean enabled; - boolean updatePending = false; - boolean mRecordingSuspended = false; - private String sAudioType; - - ShoStateMachine (int audioType, Looper looper) { - super(TAG, looper); - setDbg(DBG); - - mIdle = new Idle(); - mActivating = new Activating(); - mActive = new Active(); - mDeactivating = new Deactivating(); - mBroadcasting = new Broadcasting(); - mGamingMode = new Gaming(); - mRecordingMode = new Recording(); - - Current = new DeviceProfileCombo(); - Target = new DeviceProfileCombo(); - mSHOQueue = new SHOReq(); - mTargetSHO = new SHOReq(); - - addState(mIdle); - addState(mActivating); - addState(mActive); - addState(mDeactivating); - addState(mBroadcasting); - addState(mGamingMode); - addState(mRecordingMode); - - mAudioType = audioType; - if(mAudioType == AudioType.MEDIA) - sAudioType = new String("MEDIA"); - else if(mAudioType == AudioType.VOICE) - sAudioType = new String("VOICE"); - - enabled = true; - setInitialState(mIdle); - start(); - } - - public void doQuit () { - Log.i(TAG, "Stopping SHO StateMachine for " + mAudioType); - sAudioType = null; - quitNow(); - } - - /* public void cleanUp { - - }*/ - - private String messageWhatToString(int msg) { - switch (msg) { - case Event.SET_ACTIVE: - return "SET ACTIVE"; - case Event.ACTIVE_DEVICE_CHANGE: - return "ACTIVE DEVICE CHANGED"; - case Event.REMOVE_DEVICE: - return "REMOVE DEVICE"; - case Event.DEVICE_REMOVED: - return "REMOVED"; - case Event.ACTIVATE_TIMEOUT: - return "SET ACTIVE TIMEOUT"; - case Event.DEACTIVATE_TIMEOUT: - return "REMOVE DEVICE TIMEOUT"; - case Event.STOP_SM: - return "STOP STATE MACHINE"; - default: - break; - } - return Integer.toString(msg); - } - - int startSho(BluetoothDevice device, int profile) { - MediaAudio mMediaAudio = MediaAudio.get(); - int ret = SHO_FAILED; - StreamAudioService streamAudioService; - Log.e(TAG, ": startSho() for device: " + device + ", for profile: " + profile); - switch (profile) { - case ApmConst.AudioProfiles.A2DP: - A2dpService a2dpService = A2dpService.getA2dpService(); - if(a2dpService != null) - // pass play status here - ret = a2dpService.setActiveDevice(device, false); - break; - case ApmConst.AudioProfiles.HFP: - HeadsetService headsetService = HeadsetService.getHeadsetService(); - if(headsetService != null) - ret = headsetService.setActiveDeviceHF(device); - break; - case ApmConst.AudioProfiles.TMAP_MEDIA: - case ApmConst.AudioProfiles.BAP_MEDIA: - streamAudioService = StreamAudioService.getStreamAudioService(); - ret = streamAudioService.setActiveDevice(device, ApmConst.AudioProfiles.BAP_MEDIA, false); - if (ret == ActiveDeviceManagerService.ALREADY_ACTIVE) { - ret = SHO_SUCCESS; - } - break; - case ApmConst.AudioProfiles.BAP_RECORDING: - streamAudioService = StreamAudioService.getStreamAudioService(); - ret = streamAudioService.setActiveDevice(device, ApmConst.AudioProfiles.BAP_RECORDING, false); - if (ret == ActiveDeviceManagerService.ALREADY_ACTIVE) { - ret = SHO_SUCCESS; - } - break; - case ApmConst.AudioProfiles.TMAP_CALL: - case ApmConst.AudioProfiles.BAP_CALL: - streamAudioService = StreamAudioService.getStreamAudioService(); - ret = streamAudioService.setActiveDevice(device, profile, false); - break; - case ApmConst.AudioProfiles.BAP_GCP: - streamAudioService = StreamAudioService.getStreamAudioService(); - ret = streamAudioService.setActiveDevice(device, ApmConst.AudioProfiles.BAP_GCP, false); - if (ret == ActiveDeviceManagerService.ALREADY_ACTIVE) { - ret = SHO_SUCCESS; - } - break; - case ApmConst.AudioProfiles.BROADCAST_LE: - //ret = SHO_SUCCESS;//broadcastService.setActiveDevice(); - BroadcastService mBroadcastService = BroadcastService.getBroadcastService(); - if (mBroadcastService != null) - ret = mBroadcastService.setActiveDevice(device); - break; - case ApmConst.AudioProfiles.HAP_BREDR: - HearingAidService hearingAidService = HearingAidService.getHearingAidService(); - ret = hearingAidService.setActiveDevice(device) ? SHO_SUCCESS : SHO_FAILED; - break; - } - return ret; - } - - class Idle extends State { - @Override - public void enter() { - synchronized (this) { - mState = mIdle; - } - Current.Device = null; - //2 Update dependent profiles - if(mPrevState != null && mPrevActiveDevice != null) { - broadcastActiveDeviceChange (null, mAudioType); - - if (mAudioType == AudioType.MEDIA && - mPrevActiveProfile != ApmConst.AudioProfiles.HAP_BREDR) { - mPrevActiveProfile = ApmConst.AudioProfiles.NONE; - MediaAudio mMediaAudio = MediaAudio.get(); - boolean suppressNoisyIntent = !mTargetSHO.forceStopAudio - && (mMediaAudio.getConnectionState(mPrevActiveDevice) - == BluetoothProfile.STATE_CONNECTED); - /*TODO: Add profile check here*/ - if(mAudioManager != null) { - log("De-Activate Device " + mPrevActiveDevice + " Noisy Intent: " + suppressNoisyIntent); - mAudioManager.handleBluetoothA2dpActiveDeviceChange( - mPrevActiveDevice, BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.A2DP, suppressNoisyIntent, -1); - } - } - - VolumeManager mVolumeManager = VolumeManager.get(); - if(mVolumeManager != null) { - mVolumeManager.onActiveDeviceChange(Current.Device, mAudioType); - } - } - - if(txStreamSuspended && mAudioType == AudioType.MEDIA) { - mAudioManager.setParameters("A2dpSuspended=false"); - txStreamSuspended = false; - } - - if(!enabled) - log("state machine stopped"); - } - - @Override - public void exit() { - mPrevState = mIdle; - mPrevActiveDevice = null; - } - - @Override - public boolean processMessage(Message message) { - log("Idle: Process Message (" + mAudioType + "): " - + messageWhatToString(message.what)); - if(!enabled) { - log("State Machine not running. Returning"); - return NOT_HANDLED; - } - - switch(message.what) { - case Event.SET_ACTIVE: - transitionTo(mActivating); - break; - - case Event.ACTIVE_DEVICE_CHANGE: - /* Might move to active here*/ - case Event.REMOVE_DEVICE: - log("Idle: Process Message Ignored"); - break; - case Event.STOP_SM: - enabled = false; - log("state machine stopped"); - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class Activating extends State { - int ret; - @Override - public void enter() { - synchronized (this) { - mState = mActivating; - updatePending = true; - - Target.Device = mSHOQueue.device; - Target.absoluteDevice = Target.Device; - mTargetSHO.copy(mSHOQueue); - mSHOQueue.reset(); - Log.w(TAG, "Activating " + sAudioType + " Device: " + Target.Device); - } - - dpm = DeviceProfileMap.getDeviceProfileMapInstance(); - if (mTargetSHO.isBroadcast) { - Target.Profile = dpm.getProfile(Target.Device, ApmConst.AudioFeatures.BROADCAST_AUDIO); - mSHOQueue.device = Current.Device; - mSHOQueue.isUIReq = false; - } else if (mTargetSHO.isRecordingMode) { - mSHOQueue.device = Current.Device; - Target.Profile = ApmConst.AudioProfiles.BAP_RECORDING; - mSHOQueue.isUIReq = false; - } else if (mTargetSHO.isGamingMode) { - /*Only single profile supports gaming Mode*/ - Target.Profile = ApmConst.AudioProfiles.BAP_GCP; - } else { - Target.Profile = dpm.getProfile(Target.Device, mAudioType); - } - - if(Target.Profile == ApmConst.AudioProfiles.BAP_CALL || - Target.Profile == ApmConst.AudioProfiles.BAP_MEDIA || - Target.Profile == ApmConst.AudioProfiles.BAP_RECORDING || - Target.Profile == ApmConst.AudioProfiles.BAP_GCP) { - StreamAudioService streamAudioService = StreamAudioService.getStreamAudioService(); - Target.Device = streamAudioService.getDeviceGroup(Target.Device); - } - - if(Target.Device == null) { - Log.e(TAG, "Target Device is null, Returning"); - transitionTo(mPrevState); - updatePending = false; - return; - } - - if(Target.Device.equals(Current.Device) && Target.Profile == Current.Profile){ - Log.d(TAG,"Target Device: " + Target.Device + " and Profile: " + Target.Profile + - " already active"); - transitionTo(mPrevState); - updatePending = false; - return; - } - - if(Current.Device == null || isSameProfile(Current.Profile, Target.Profile, mAudioType)) { - /* Single Step SHO*/ - ActivateDevice(Target, mTargetSHO); - } else { - /*Multi Step SHO*/ - ret = startSho(null, Current.Profile); - if(SHO_PENDING == ret) { - sendMessageDelayed(Event.DEACTIVATE_TIMEOUT, DEACTIVATE_TIMEOUT_DELAY); - } else if(ret == SHO_FAILED) { - mTargetSHO.retryCount = 1; - sendMessageDelayed(Event.RETRY_DEACTIVATE, DEACTIVATE_TRY_DELAY); - } else if(SHO_SUCCESS == ret) { - mPrevState = mIdle; - Current.Device = null; - ActivateDevice(Target, mTargetSHO); - } - } - } - - @Override - public void exit() { - removeMessages(Event.ACTIVATE_TIMEOUT); - mPrevState = mActivating; - } - - @Override - public boolean processMessage(Message message) { - log("Activating: Process Message (" + mAudioType + "): " - + messageWhatToString(message.what)); - - switch(message.what) { - case Event.SET_ACTIVE: - log("New SHO request while handling previous. Add to queue"); - removeDeferredMessages(Event.REMOVE_DEVICE); - removeDeferredMessages(Event.SET_ACTIVE); - deferMessage(message); - break; - - case Event.ACTIVE_DEVICE_CHANGE: - DeviceProfileCombo mDeviceProfileCombo = (DeviceProfileCombo)message.obj; - removeMessages(Event.ACTIVATE_TIMEOUT); - if (Target.Profile == ApmConst.AudioProfiles.BAP_GCP - && Target.Profile == mDeviceProfileCombo.Profile) { - Current.Device = Target.Device; - Current.Profile = Target.Profile; - transitionTo(mGamingMode); - } else if (Target.Profile == ApmConst.AudioProfiles.BROADCAST_LE - && Target.Profile == mDeviceProfileCombo.Profile) { - Current.Device = Target.Device; - Current.Profile = Target.Profile; - transitionTo(mBroadcasting); - } else if(Target.Device != null && Target.Device.equals(mDeviceProfileCombo.Device)) { - Current.Device = mDeviceProfileCombo.Device; - Current.Profile = Target.Profile; - Current.absoluteDevice = Target.absoluteDevice; - transitionTo(mActive); - } - break; - - case Event.REMOVE_DEVICE: - removeDeferredMessages(Event.REMOVE_DEVICE); - deferMessage(message); - break; - - case Event.DEVICE_REMOVED: - mPrevState = mIdle; - Current.Device = null; - removeMessages(Event.DEACTIVATE_TIMEOUT); - ActivateDevice(Target, mTargetSHO); - break; - - case Event.RETRY_DEACTIVATE: - ret = startSho(null, Current.Profile); - if(SHO_PENDING == ret) { - mTargetSHO.retryCount = 0; - sendMessageDelayed(Event.DEACTIVATE_TIMEOUT, DEACTIVATE_TIMEOUT_DELAY); - } else if(ret == SHO_FAILED) { - if(mTargetSHO.retryCount >= RETRY_LIMIT) { - updatePending = false; - transitionTo(mPrevState); - } else { - mTargetSHO.retryCount++; - sendMessageDelayed(Event.RETRY_DEACTIVATE, DEACTIVATE_TRY_DELAY); - } - } else if(SHO_SUCCESS == ret) { - mTargetSHO.retryCount = 0; - mPrevState = mIdle; - Current.Device = null; - ActivateDevice(Target, mTargetSHO); - } - break; - - case Event.ACTIVATE_TIMEOUT: - case Event.DEACTIVATE_TIMEOUT: - transitionTo(mPrevState); - break; - - case Event.STOP_SM: - deferMessage(message); - break; - - default: - return NOT_HANDLED; - } - return HANDLED; - } - - void ActivateDevice(DeviceProfileCombo mTarget, SHOReq mTargetSHO) { - ret = startSho(mTarget.Device, mTarget.Profile); - if(SHO_PENDING == ret) { - Current.Device = mTarget.Device; - Current.absoluteDevice = mTarget.absoluteDevice; - Current.Profile = mTarget.Profile; - if(mAudioType == AudioType.MEDIA) { - sendActiveDeviceMediaUpdate(Current); - } - sendMessageDelayed(Event.ACTIVATE_TIMEOUT, ACTIVATE_TIMEOUT_DELAY); - } else if(ret == SHO_FAILED) { - if (mState == mBroadcasting) { - mTargetSHO.forceStopAudio = true; - Log.d(TAG,"Previous state was broadcasting, moving to idle"); - } - updatePending = false; - transitionTo(mPrevState); - } else if(SHO_SUCCESS == ret) { - Current.Device = mTarget.Device; - Current.absoluteDevice = mTarget.absoluteDevice; - Current.Profile = mTarget.Profile; - if(mTargetSHO.isBroadcast) { - transitionTo(mBroadcasting); - } else if (mTargetSHO.isGamingMode) { - transitionTo(mGamingMode); - } else if (mTargetSHO.isRecordingMode) { - transitionTo(mRecordingMode); - } else { - transitionTo(mActive); - } - } else if(ALREADY_ACTIVE == ret) { - transitionTo(mActive); - } - } - } - - class Deactivating extends State { - int ret; - @Override - public void enter() { - synchronized (this) { - mState = mDeactivating; - } - if (mPrevState == mBroadcasting) { - mPrevState = mIdle; - } - Target.Device = null; - Target.Profile = Current.Profile; - mTargetSHO.copy(mSHOQueue); - mSHOQueue.reset(); - - ret = startSho(Target.Device, Target.Profile); - Log.d(TAG, "ret: " + ret); - if (SHO_SUCCESS == ret) { - transitionTo(mIdle); - } else if (SHO_PENDING == ret) { - sendMessageDelayed(Event.DEACTIVATE_TIMEOUT, DEACTIVATE_TIMEOUT_DELAY); - } else { - transitionTo(mPrevState); - } - } - - @Override - public void exit() { - removeMessages(Event.DEACTIVATE_TIMEOUT); - mPrevState = mDeactivating; - mPrevActiveDevice = Current.Device; - Current.Device = null; - mPrevActiveProfile = Current.Profile; - Current.Profile = ApmConst.AudioProfiles.NONE; // Add profile value here - } - - @Override - public boolean processMessage(Message message) { - log("Deactivating: Process Message (" + mAudioType + "): " - + messageWhatToString(message.what)); - - switch(message.what) { - case Event.SET_ACTIVE: - log("New SHO request while handling previous. Add to queue"); - removeDeferredMessages(Event.SET_ACTIVE); - deferMessage(message); - break; - - case Event.ACTIVE_DEVICE_CHANGE: - break; - - case Event.REMOVE_DEVICE: - break; - - case Event.DEVICE_REMOVED: - removeMessages(Event.DEACTIVATE_TIMEOUT); - transitionTo(mIdle); - break; - - case Event.DEACTIVATE_TIMEOUT: - transitionTo(mPrevState); - - case Event.STOP_SM: - deferMessage(message); - break; - - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class Active extends State { - int ret; - @Override - public void enter() { - synchronized (this) { - mState = mActive; - } - if(updatePending) { - if(mAudioType == AudioType.MEDIA) - sendActiveDeviceMediaUpdate(Current); - else if(mAudioType == AudioType.VOICE) - sendActiveDeviceVoiceUpdate(Current); - } - if(txStreamSuspended && mAudioType == AudioType.MEDIA) { - mAudioManager.setParameters("A2dpSuspended=false"); - txStreamSuspended = false; - } else if (mAudioType == AudioType.VOICE) { - lock.lock(); - voiceHandoffComplete.signal(); - lock.unlock(); - Log.d(TAG, "Voice Active: unlock by signal"); - } - } - - @Override - public void exit() { - //2 update dependent profiles - mPrevState = mActive; - mPrevActiveDevice = Current.Device; - VolumeManager mVolumeManager = VolumeManager.get(); - if(mVolumeManager != null) { - mVolumeManager.saveVolume(mAudioType); - } - } - - @Override - public boolean processMessage(Message message) { - log("Active: Process Message (" + mAudioType + "): " - + messageWhatToString(message.what)); - - switch(message.what) { - case Event.SET_ACTIVE: - if(mSHOQueue.device == null) { - Log.w(TAG, "Invalid request"); - break; - } - transitionTo(mActivating); - break; - - case Event.ACTIVE_DEVICE_CHANGE: - // might have to handle - break; - - case Event.REMOVE_DEVICE: - transitionTo(mDeactivating); - break; - - case Event.DEVICE_REMOVED: - //might have to handle - break; - - case Event.STOP_SM: - transitionTo(mDeactivating); - enabled = false; - break; - - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class Gaming extends State { - int ret; - @Override - public void enter() { - synchronized (this) { - mState = mGamingMode; - } - if(updatePending) { - sendActiveDeviceGamingUpdate(Current); - } - if(txStreamSuspended) { - mAudioManager.setParameters("A2dpSuspended=false"); - txStreamSuspended = false; - } - } - - @Override - public void exit() { - //2 update dependent profiles - mPrevState = mGamingMode; - mPrevActiveDevice = Current.Device; - VolumeManager mVolumeManager = VolumeManager.get(); - if(mVolumeManager != null) { - mVolumeManager.saveVolume(mAudioType); - } - } - - @Override - public boolean processMessage(Message message) { - log("Gaming: Process Message (" + mAudioType + "): " - + messageWhatToString(message.what)); - - switch(message.what) { - case Event.SET_ACTIVE: - if(mSHOQueue.device == null) { - Log.w(TAG, "Invalid request"); - break; - } - if(!mSHOQueue.isUIReq && Current.Device.equals(mSHOQueue.device)) { - Log.w(TAG, "Spurious request for same device. Ignore"); - mSHOQueue.reset(); - break; - } - /*MediaAudio mMediaAudio = MediaAudio.get(); - if(mMediaAudio != null && mMediaAudio.isA2dpPlaying(mSHOQueue.device)) { - if(!(mSHOQueue.isBroadcast || mSHOQueue.isRecordingMode)) { - Log.w(TAG, "Gaming streaming is on"); - break; - } - }*/ - transitionTo(mActivating); - break; - - case Event.ACTIVE_DEVICE_CHANGE: - // might have to handle - break; - - case Event.REMOVE_DEVICE: - transitionTo(mDeactivating); - break; - - case Event.DEVICE_REMOVED: - //might have to handle - break; - - case Event.STOP_SM: - transitionTo(mDeactivating); - enabled = false; - break; - - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class Broadcasting extends State { - int ret; - @Override - public void enter() { - synchronized (this) { - mState = mBroadcasting; - } - if (updatePending) { - apmNative.activeDeviceUpdate(Current.Device, Current.Profile, mAudioType); - broadcastActiveDeviceChange(Current.Device, AudioType.MEDIA); - mAudioManager.avrcpSupportsAbsoluteVolume(Current.Device.getAddress(), false); - // Update active device to null in VolumeManager while enter broadcasting state - VolumeManager mVolumeManager = VolumeManager.get(); - if(mVolumeManager != null) { - mVolumeManager.onActiveDeviceChange(null, - ApmConst.AudioFeatures.MEDIA_AUDIO); - } - int rememberedVolume = 15; - mAudioManager.handleBluetoothA2dpActiveDeviceChange( - Current.Device, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, - true, rememberedVolume); - updatePending = false; - } - if(txStreamSuspended) { - mAudioManager.setParameters("A2dpSuspended=false"); - txStreamSuspended = false; - } - } - - @Override - public void exit() { - mPrevState = mBroadcasting; - mPrevActiveDevice = Current.Device; - } - - @Override - public boolean processMessage(Message message) { - log("Broadcasting: Process Message (" + mAudioType + "): " - + messageWhatToString(message.what)); - - switch(message.what) { - case Event.SET_ACTIVE: - if(mSHOQueue.isUIReq) - transitionTo(mActivating); - break; - - case Event.ACTIVE_DEVICE_CHANGE: - break; - - case Event.REMOVE_DEVICE: - if(mSHOQueue.device == null) { - transitionTo(mDeactivating); - } else { - transitionTo(mActivating); - } - break; - - case Event.DEVICE_REMOVED: - break; - - case Event.STOP_SM: - transitionTo(mDeactivating); - enabled = false; - break; - - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - class Recording extends State { - int ret; - @Override - public void enter() { - synchronized (this) { - mState = mRecordingMode; - } - if(updatePending) { - sendActiveDeviceRecordingUpdate(Current); - } - mRecordingSuspended = false; - } - - @Override - public void exit() { - mPrevState = mRecordingMode; - mPrevActiveDevice = Current.Device; - HeadsetService hfpService = HeadsetService.getHeadsetService(); - - mAudioManager.handleBluetoothA2dpActiveDeviceChange( - mPrevActiveDevice, - BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.A2DP_SINK, - true, -1); - if(mRecordingSuspended) { - mAudioManager.setParameters("A2dpCaptureSuspend=false"); - mRecordingSuspended = false; - } - CallAudio mCallAudio = CallAudio.get(); - boolean isInCall = mCallAudio != null && - mCallAudio.isVoiceOrCallActive(); - if(isInCall) { - Log.d(TAG, " reset txStreamSuspended as call is active" ); - txStreamSuspended = false; - } - VolumeManager mVolumeManager = VolumeManager.get(); - if(mVolumeManager != null) { - mVolumeManager.saveVolume(mAudioType); - } - } - - @Override - public boolean processMessage(Message message) { - log("Recording: Process Message (" + mAudioType + "): " - + messageWhatToString(message.what)); - - switch(message.what) { - case Event.SET_ACTIVE: - if (mSHOQueue.device == null) { - transitionTo(mDeactivating); - } else { - transitionTo(mActivating); - } - break; - - case Event.ACTIVE_DEVICE_CHANGE: - break; - - case Event.REMOVE_DEVICE: - transitionTo(mDeactivating); - break; - - case Event.DEVICE_REMOVED: - //might have to handle - break; - case Event.SUSPEND_RECORDING: { - if(mRecordingSuspended) break; - mAudioManager.setParameters("A2dpCaptureSuspend=true"); - mRecordingSuspended = true; - } break; - - case Event.RESUME_RECORDING: { - if(!mRecordingSuspended) break; - mAudioManager.setParameters("A2dpCaptureSuspend=false"); - mRecordingSuspended = false; - } break; - case Event.STOP_SM: - transitionTo(mDeactivating); - enabled = false; - break; - - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - void sendActiveDeviceMediaUpdate(DeviceProfileCombo Current) { - if(Current.Profile == ApmConst.AudioProfiles.HAP_BREDR) { - if(mPrevActiveDevice != null) { - broadcastActiveDeviceChange (null, AudioType.MEDIA ); - ActiveDeviceManager mDeviceManager = AdapterService.getAdapterService().getActiveDeviceManager(); - mDeviceManager.onActiveDeviceChange(null, ApmConst.AudioFeatures.MEDIA_AUDIO); - mAudioManager.handleBluetoothA2dpActiveDeviceChange( - mPrevActiveDevice, BluetoothProfile.STATE_DISCONNECTED, - BluetoothProfile.A2DP, true, -1); - } - return; - } - apmNative.activeDeviceUpdate(Current.Device, Current.Profile, AudioType.MEDIA); - Log.d(TAG, "sendActiveDeviceMediaUpdate: mPrevActiveDevice: " - + mPrevActiveDevice + ", Current.Device: " + Current.Device); - - MediaAudio mMediaAudio = MediaAudio.get(); - mMediaAudio.refreshCurrentCodec(Current.Device); - - broadcastActiveDeviceChange (Current.absoluteDevice, AudioType.MEDIA); - ActiveDeviceManager mDeviceManager = AdapterService.getAdapterService().getActiveDeviceManager(); - mDeviceManager.onActiveDeviceChange(Current.Device, ApmConst.AudioFeatures.MEDIA_AUDIO); - if(Current.Profile == ApmConst.AudioProfiles.A2DP) { - A2dpService mA2dpService = A2dpService.getA2dpService(); - mA2dpService.broadcastActiveCodecConfig(); - } - //2 Update dependent profiles - VolumeManager mVolumeManager = VolumeManager.get(); - if(mVolumeManager != null) { - mVolumeManager.onActiveDeviceChange(Current.Device, - ApmConst.AudioFeatures.MEDIA_AUDIO); - } - - McpService mMcpService = McpService.getMcpService(); - if (mMcpService != null) { - mMcpService.SetActiveDevices(Current.absoluteDevice, Current.Profile); - } - int deviceVolume = 7; - if(mVolumeManager != null) { - deviceVolume = mVolumeManager.getActiveVolume(ApmConst.AudioFeatures.MEDIA_AUDIO); - } - if(mAudioManager != null) { - mAudioManager.handleBluetoothA2dpActiveDeviceChange( - Current.Device, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, - true, deviceVolume); - } - updatePending = false; - } - - void sendActiveDeviceGamingUpdate(DeviceProfileCombo Current) { - apmNative.activeDeviceUpdate(Current.Device, Current.Profile, AudioType.MEDIA); - - MediaAudio mMediaAudio = MediaAudio.get(); - mMediaAudio.refreshCurrentCodec(Current.Device); - - broadcastActiveDeviceChange (Current.absoluteDevice, AudioType.MEDIA); - ActiveDeviceManager mDeviceManager = AdapterService.getAdapterService().getActiveDeviceManager(); - mDeviceManager.onActiveDeviceChange(Current.Device, ApmConst.AudioFeatures.MEDIA_AUDIO); - - //2 Update dependent profiles - VolumeManager mVolumeManager = VolumeManager.get(); - int deviceVolume = 7; - if(mVolumeManager != null) { - mVolumeManager.onActiveDeviceChange(Current.Device, - ApmConst.AudioFeatures.MEDIA_AUDIO); - deviceVolume = mVolumeManager.getActiveVolume(ApmConst.AudioFeatures.MEDIA_AUDIO); - } - if(mAudioManager != null) { - mAudioManager.handleBluetoothA2dpActiveDeviceChange( - Current.Device, BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, - true, deviceVolume); - - /*Add back channel call here*/ - } - updatePending = false; - } - - void sendActiveDeviceVoiceUpdate(DeviceProfileCombo Current) { - Log.d(TAG, "sendActiveDeviceVoiceUpdate"); - if(Current.Profile == ApmConst.AudioProfiles.HAP_BREDR) { - if(mPrevActiveDevice != null) { - broadcastActiveDeviceChange (null, AudioType.VOICE); - ActiveDeviceManager mDeviceManager = AdapterService.getAdapterService().getActiveDeviceManager(); - mDeviceManager.onActiveDeviceChange(Current.Device, ApmConst.AudioFeatures.CALL_AUDIO); - } - return; - } - broadcastActiveDeviceChange (Current.absoluteDevice, AudioType.VOICE); - ActiveDeviceManager mDeviceManager = AdapterService.getAdapterService().getActiveDeviceManager(); - mDeviceManager.onActiveDeviceChange(Current.Device, ApmConst.AudioFeatures.CALL_AUDIO); - VolumeManager mVolumeManager = VolumeManager.get(); - if(mVolumeManager != null) { - mVolumeManager.onActiveDeviceChange(Current.Device, - ApmConst.AudioFeatures.CALL_AUDIO); - } - CCService ccService = CCService.getCCService(); - if (ccService != null) { - ccService.setActiveDevice(Current.absoluteDevice); - } - - if(mTargetSHO.PlayReq) { - CallAudio mCallAudio = CallAudio.get(); - mCallAudio.connectAudio(); - } - - updatePending = false; - } - - void sendActiveDeviceRecordingUpdate(DeviceProfileCombo Current) { - apmNative.activeDeviceUpdate(Current.Device, Current.Profile, AudioType.MEDIA); - - Log.d(TAG, "sendActiveDeviceRecordingUpdate: mPrevActiveDevice: " - + mPrevActiveDevice + ", Current.Device: " + Current.Device); - MediaAudio mMediaAudio = MediaAudio.get(); - mMediaAudio.refreshCurrentCodec(Current.Device); - if (mAudioManager != null) { - mAudioManager.handleBluetoothA2dpActiveDeviceChange(Current.Device, - BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP_SINK, false, -1); // TO-Check - } - updatePending = false; - } - - boolean isSameProfile (int p1, int p2, int audioType) { - if(p1 == p2) { - return true; - } - - if(audioType == AudioType.MEDIA) { - int leMediaMask = ApmConst.AudioProfiles.TMAP_MEDIA | - ApmConst.AudioProfiles.BAP_MEDIA | - ApmConst.AudioProfiles.BAP_RECORDING | - ApmConst.AudioProfiles.BAP_GCP; - if((leMediaMask & p1) > 0 && (leMediaMask & p2) > 0) { - return true; - } - } else if(audioType == AudioType.VOICE) { - int leVoiceMask = ApmConst.AudioProfiles.TMAP_CALL | ApmConst.AudioProfiles.BAP_CALL; - if((leVoiceMask & p1) > 0 && (leVoiceMask & p2) > 0) { - return true; - } - } - - return false; - } - } - - static class AudioType { - public static int VOICE = ApmConst.AudioFeatures.CALL_AUDIO; - public static int MEDIA = ApmConst.AudioFeatures.MEDIA_AUDIO; - - public static int SIZE = 2; - } - - private class SHOReq { - BluetoothDevice device; - boolean PlayReq; - int retryCount; - boolean isBroadcast; - boolean isGamingMode; - boolean isRecordingMode; - boolean isUIReq; - boolean forceStopAudio; - - void copy(SHOReq src) { - device = src.device; - PlayReq = src.PlayReq; - retryCount = src.retryCount; - isBroadcast = src.isBroadcast; - isGamingMode = src.isGamingMode; - isRecordingMode = src.isRecordingMode; - isUIReq = src.isUIReq; - forceStopAudio = src.forceStopAudio; - } - - void reset() { - device = null; - PlayReq = false; - retryCount = 0; - isBroadcast = false; - isGamingMode = false; - isRecordingMode = false; - isUIReq = false; - forceStopAudio = false; - } - } -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/ApmConst.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/ApmConst.java deleted file mode 100644 index 45fab0dfabc7649d731ba9f1d68e238fd44d0e99..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/ApmConst.java +++ /dev/null @@ -1,70 +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. - * - ******************************************************************************/ - - -package com.android.bluetooth.apm; - -public class ApmConst { - - private static boolean leAudioEnabled = false; - public static final String groupAddress = "9E:8B:00:00:00"; - - public static boolean getLeAudioEnabled() { - return leAudioEnabled; - } - - protected static void setLeAudioEnabled(boolean leAudioSupport) { - leAudioEnabled = leAudioSupport; - } - - public static class AudioFeatures { - - public static final int CALL_AUDIO = 0; - public static final int MEDIA_AUDIO = 1; - public static final int CALL_CONTROL = 2; - public static final int MEDIA_CONTROL = 3; - public static final int MEDIA_VOLUME_CONTROL = 4; - public static final int CALL_VOLUME_CONTROL = 5; - public static final int BROADCAST_AUDIO = 6; - public static final int HEARING_AID = 7; - public static final int MAX_AUDIO_FEATURES = 8; - - } - - public static class AudioProfiles { - - public static final int NONE = 0x0000; - public static final int A2DP = 0x0001; - public static final int HFP = 0x0002; - public static final int AVRCP = 0x0004; - public static final int TMAP_MEDIA = 0x0008; - public static final int BAP_MEDIA = 0x0010; - public static final int MCP = 0x0020; - public static final int CCP = 0x0040; - public static final int VCP = 0x0080; - public static final int HAP_BREDR = 0x0100; - public static final int HAP_LE = 0x0200; - public static final int BROADCAST_BREDR = 0x0400; - public static final int BROADCAST_LE = 0x0800; - public static final int TMAP_CALL = 0x1000; - public static final int BAP_CALL = 0x2000; - public static final int BAP_GCP = 0x4000; - public static final int BAP_RECORDING = 0x8000; - - } -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/ApmNativeInterface.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/ApmNativeInterface.java deleted file mode 100644 index b4370237c28d419eeda49e06b46c4b3cfb289a89..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/ApmNativeInterface.java +++ /dev/null @@ -1,131 +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. - * - ******************************************************************************/ - - -package com.android.bluetooth.apm; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.util.Log; -import java.util.List; - -import com.android.bluetooth.Utils; -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; - -/** - * A2DP Native Interface to/from JNI. - */ -public class ApmNativeInterface { - private static final String TAG = "ApmNativeInterface"; - private static final boolean DBG = true; - - @GuardedBy("INSTANCE_LOCK") - private static ApmNativeInterface sInstance; - private BluetoothAdapter mAdapter; - private static final Object INSTANCE_LOCK = new Object(); - - static { - classInitNative(); - } - - @VisibleForTesting - private ApmNativeInterface() { - mAdapter = BluetoothAdapter.getDefaultAdapter(); - if (mAdapter == null) { - Log.w(TAG, "No Bluetooth Adapter Available"); - } - } - - /** - * Get singleton instance. - */ - public static ApmNativeInterface getInstance() { - synchronized (INSTANCE_LOCK) { - if (sInstance == null) { - sInstance = new ApmNativeInterface(); - } - return sInstance; - } - } - - /** - * Initializes the native interface. - */ - public void init() { - initNative(); - } - - /** - * Cleanup the native interface. - */ - public void cleanup() { - cleanupNative(); - } - - /** - * Report new active device to stack. - * - * @param device: new active device - * @param profile: new active profile - * @return true on success, otherwise false. - */ - public boolean activeDeviceUpdate(BluetoothDevice device, int profile, int audioType) { - return activeDeviceUpdateNative(getByteAddress(device), profile, audioType); - } - - /** - * Report Content Control ID to stack. - * - * @param id: Content Control ID - * @param profile: content control profile - * @return true on success, otherwise false. - */ - public boolean setContentControl(int id, int profile) { - return setContentControlNative(id, profile); - } - - 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()); - } - - //Current logic is implemented only for CALL_AUDIO - //Proper Audio_type needs to be sent to device profile map - //for other audio features - private int getActiveProfile(byte[] address, int audio_type) { - DeviceProfileMap dpm = DeviceProfileMap.getDeviceProfileMapInstance(); - BluetoothDevice device = getDevice(address); - int profile = dpm.getProfile(device, ApmConst.AudioFeatures.CALL_AUDIO); - return profile; - } - - // Native methods that call into the JNI interface - private static native void classInitNative(); - private native void initNative(); - private native void cleanupNative(); - private native boolean activeDeviceUpdateNative(byte[] address, int profile, int audioType); - private native boolean setContentControlNative(int id, int profile); -} - diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/CallAudio.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/CallAudio.java deleted file mode 100644 index 0d846912500d10a1f8998aee2b5824b01a0666dc..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/CallAudio.java +++ /dev/null @@ -1,758 +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. - * - ******************************************************************************/ - - -package com.android.bluetooth.apm; - -import static android.Manifest.permission.BLUETOOTH_CONNECT; - -import android.bluetooth.BluetoothDevice; -import com.android.bluetooth.hfp.HeadsetService; -import com.android.bluetooth.hfp.HeadsetA2dpSync; -import com.android.bluetooth.apm.ApmConst; -import com.android.bluetooth.apm.MediaAudio; -import com.android.bluetooth.apm.CallControl; -import android.media.AudioManager; -import com.android.bluetooth.apm.ActiveDeviceManagerService; -import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.btservice.ProfileService; -import com.android.bluetooth.btservice.AdapterService; -import android.bluetooth.BluetoothHeadset; -import android.bluetooth.BluetoothProfile; -import com.android.bluetooth.Utils; -import android.content.Context; -import java.lang.Integer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import android.util.Log; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import android.content.Intent; -import android.os.UserHandle; - -public class CallAudio { - - private static CallAudio mCallAudio; - private static final String TAG = "APM: CallAudio"; - Map mCallDevicesMap; - private Context mContext; - private AudioManager mAudioManager; - private ActiveDeviceManagerService mActiveDeviceManager; - private AdapterService mAdapterService; - public static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; - public static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; - public static final String BLUETOOTH_PRIVILEGED = - android.Manifest.permission.BLUETOOTH_PRIVILEGED; - private static final int MAX_DEVICES = 200; - public boolean mVirtualCallStarted; - private CallControl mCallControl = null; - - private CallAudio(Context context) { - Log.d(TAG, "Initialization"); - mContext = context; - mCallDevicesMap = new ConcurrentHashMap(); - mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); - mActiveDeviceManager = ActiveDeviceManagerService.get(); - mAdapterService = AdapterService.getAdapterService(); - mCallControl = CallControl.get(); - } - - public static CallAudio init(Context context) { - if(mCallAudio == null) { - mCallAudio = new CallAudio(context); - CallAudioIntf.init(mCallAudio); - } - return mCallAudio; - } - - public static CallAudio get() { - return mCallAudio; - } - - public boolean connect(BluetoothDevice device) { - Log.i(TAG, "connect: " + device); - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); - if(device == null) - return false; - boolean status; - if (getConnectionPolicy(device) == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { - Log.e(TAG, "Cannot connect to " + device + " : CONNECTION_POLICY_FORBIDDEN"); - return false; - } - - DeviceProfileMap dMap = DeviceProfileMap.getDeviceProfileMapInstance(); - if (dMap == null) - return false; - - int profileID = dMap.getSupportedProfile(device, ApmConst.AudioFeatures.CALL_AUDIO); - if (profileID == ApmConst.AudioProfiles.NONE) { - Log.e(TAG, "Can Not connect to " + device + ". Device does not support call service."); - return false; - } - - CallDevice mCallDevice = mCallDevicesMap.get(device.getAddress()); - if(mCallDevice == null) { - if(mCallDevicesMap.size() >= MAX_DEVICES) - return false; - mCallDevice = new CallDevice(device, profileID); - mCallDevicesMap.put(device.getAddress(), mCallDevice); - } else if(mCallDevice.deviceConnStatus != BluetoothProfile.STATE_DISCONNECTED) { - Log.i(TAG, "Device already connected"); - return false; - } - - if((ApmConst.AudioProfiles.HFP & profileID) == ApmConst.AudioProfiles.HFP) { - HeadsetService service = HeadsetService.getHeadsetService(); - if (service == null) { - return false; - } - service.connectHfp(device); - } - - StreamAudioService mStreamService = StreamAudioService.getStreamAudioService(); - if(mStreamService != null && - (ApmConst.AudioProfiles.BAP_CALL & profileID) == ApmConst.AudioProfiles.BAP_CALL) { - mStreamService.connectLeStream(device, profileID); - } - return true; - } - - public boolean connect(BluetoothDevice device, Boolean allProfiles) { - if(allProfiles) { - DeviceProfileMap dMap = DeviceProfileMap.getDeviceProfileMapInstance(); - if (dMap == null) - return false; - - int profileID = dMap.getSupportedProfile(device, ApmConst.AudioFeatures.CALL_AUDIO); - if((ApmConst.AudioProfiles.HFP & profileID) == ApmConst.AudioProfiles.HFP) { - HeadsetService service = HeadsetService.getHeadsetService(); - if (service == null) { - return false; - } - return service.connectHfp(device); - } else { - /*Common connect for LE Media and Call handled from StreamAudioService*/ - return true; - } - } - - return connect(device); - } - - public boolean disconnect(BluetoothDevice device) { - Log.i(TAG, " disconnect: " + device); - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); - CallDevice mCallDevice; - - if(device == null) - return false; - - mCallDevice = mCallDevicesMap.get(device.getAddress()); - if(mCallDevice == null) { - Log.e(TAG, "Ignore: Device " + device + " not present in list"); - return false; - } - - if (mCallDevice.profileConnStatus[CallDevice.SCO_STREAM] != BluetoothProfile.STATE_DISCONNECTED) { - HeadsetService service = HeadsetService.getHeadsetService(); - if(service != null) { - service.disconnectHfp(device); - } - } - - if (mCallDevice.profileConnStatus[CallDevice.LE_STREAM] != BluetoothProfile.STATE_DISCONNECTED) { - StreamAudioService service = StreamAudioService.getStreamAudioService(); - if(service != null) { - service.disconnectLeStream(device, true, false); - } - } - - return true; - } - - public boolean disconnect(BluetoothDevice device, Boolean allProfiles) { - if(allProfiles) { - CallDevice mCallDevice = mCallDevicesMap.get(device.getAddress()); - if(mCallDevice == null) { - Log.e(TAG, "Ignore: Device " + device + " not present in list"); - return false; - } - if(mCallDevice.profileConnStatus[CallDevice.SCO_STREAM] != BluetoothProfile.STATE_DISCONNECTED) { - return disconnect(device); - } else { - /*Common connect for LE Media and Call handled from StreamAudioService*/ - return true; - } - } - - return disconnect(device); - } - - public boolean startScoUsingVirtualVoiceCall() { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); - Log.d(TAG, "startScoUsingVirtualVoiceCall"); - BluetoothDevice mActivedevice = null; - int profile; - mActiveDeviceManager = ActiveDeviceManagerService.get(); - if(mActiveDeviceManager != null) { - mActivedevice = mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.CALL_AUDIO); - if(mActivedevice == null) { - Log.e(TAG, "startScoUsingVirtualVoiceCall failed. Active Device is null"); - return false; - } - } else { - return false; - } - - checkA2dpState(); - - profile = mActiveDeviceManager.getActiveProfile(ApmConst.AudioFeatures.CALL_AUDIO); - switch(profile) { - case ApmConst.AudioProfiles.HFP: - HeadsetService headsetService = HeadsetService.getHeadsetService(); - if(headsetService != null) { - if(headsetService.startScoUsingVirtualVoiceCall()) { - mVirtualCallStarted = true; - return true; - } - } - break; - case ApmConst.AudioProfiles.BAP_CALL: - case ApmConst.AudioProfiles.TMAP_CALL: - StreamAudioService mStreamAudioService = StreamAudioService.getStreamAudioService(); - if(mStreamAudioService != null) { - if(mStreamAudioService.startStream(mActivedevice)) { - mVirtualCallStarted = true; - mCallControl = CallControl.get(); - if (mCallControl != null) { - mCallControl.setVirtualCallActive(true); - } - return true; - } - } - break; - default: - Log.e(TAG, "Unhandled profile"); - break; - } - - Log.e(TAG, "startScoUsingVirtualVoiceCall failed. Device: " + mActivedevice); - if(ApmConst.AudioProfiles.HFP != profile) { - HeadsetService service = HeadsetService.getHeadsetService(); - if(service != null) { - service.getHfpA2DPSyncInterface().releaseA2DP(null); - } - } - return false; - } - - public boolean stopScoUsingVirtualVoiceCall() { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); - Log.d(TAG, "stopScoUsingVirtualVoiceCall"); - BluetoothDevice mActivedevice = null; - int profile; - mActiveDeviceManager = ActiveDeviceManagerService.get(); - if(mActiveDeviceManager != null) { - mActivedevice = mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.CALL_AUDIO); - if(mActivedevice == null) { - Log.e(TAG, "stopScoUsingVirtualVoiceCall failed. Active Device is null"); - return false; - } - } else { - return false; - } - - profile = mActiveDeviceManager.getActiveProfile(ApmConst.AudioFeatures.CALL_AUDIO); - switch(profile) { - case ApmConst.AudioProfiles.HFP: - HeadsetService headsetService = HeadsetService.getHeadsetService(); - if(headsetService != null) { - mVirtualCallStarted = false; - return headsetService.stopScoUsingVirtualVoiceCall(); - } - break; - case ApmConst.AudioProfiles.BAP_CALL: - case ApmConst.AudioProfiles.TMAP_CALL: - StreamAudioService mStreamAudioService = StreamAudioService.getStreamAudioService(); - if(mStreamAudioService != null) { - mVirtualCallStarted = false; - mCallControl = CallControl.get(); - if (mCallControl != null) { - mCallControl.setVirtualCallActive(false); - } - return mStreamAudioService.stopStream(mActivedevice); - } - break; - default: - Log.e(TAG, "Unhandled profile"); - break; - } - - Log.e(TAG, "stopScoUsingVirtualVoiceCall failed. Device: " + mActivedevice); - return false; - } - - void remoteDisconnectVirtualVoiceCall(BluetoothDevice device) { - if(device == null) - return; - ActiveDeviceManagerService mActiveDeviceManager = ActiveDeviceManagerService.get(); - if(device.equals(mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.CALL_AUDIO)) && - mActiveDeviceManager.isStableState(ApmConst.AudioFeatures.CALL_AUDIO)) { - stopScoUsingVirtualVoiceCall(); - } - } - - int getProfile(BluetoothDevice mDevice) { - DeviceProfileMap dMap = DeviceProfileMap.getDeviceProfileMapInstance(); - int profileID = dMap.getProfile(mDevice, ApmConst.AudioFeatures.CALL_AUDIO); - Log.d(TAG," getProfile for device " + mDevice + " profileID " + profileID); - return profileID; - } - - void checkA2dpState() { - MediaAudio sMediaAudio = MediaAudio.get(); - BluetoothDevice sMediaActivedevice = - mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.MEDIA_AUDIO); - //if(sMediaAudio.isA2dpPlaying(sMediaActivedevice)) { - Log.d(TAG," suspendA2DP isA2dpPlaying true " + " for device " + sMediaActivedevice); - int profileID = mActiveDeviceManager.getActiveProfile( - ApmConst.AudioFeatures.CALL_AUDIO); - if(ApmConst.AudioProfiles.HFP != profileID) { - HeadsetService service = HeadsetService.getHeadsetService(); - if(service != null) { - service.getHfpA2DPSyncInterface().suspendA2DP( - HeadsetA2dpSync.A2DP_SUSPENDED_BY_CS_CALL, null); - } - } - //} - } - - public boolean connectAudio() { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); - BluetoothDevice mActivedevice = null; - boolean status = false; - - mActiveDeviceManager = ActiveDeviceManagerService.get(); - if(mActiveDeviceManager != null) { - mActivedevice = mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.CALL_AUDIO); - } - Log.i(TAG, "connectAudio: device=" + mActivedevice + ", " + Utils.getUidPidString()); - - int profileID = mActiveDeviceManager.getActiveProfile(ApmConst.AudioFeatures.CALL_AUDIO); - checkA2dpState(); - - if(ApmConst.AudioProfiles.HFP == profileID) { - HeadsetService service = HeadsetService.getHeadsetService(); - if (service == null) { - status = false; - } - status = service.connectAudio(mActivedevice); - } else if(ApmConst.AudioProfiles.BAP_CALL == profileID) { - StreamAudioService service = StreamAudioService.getStreamAudioService(); - if(service != null) { - status = service.startStream(mActivedevice); - } - } else { - Log.e(TAG, "Unhandled connect audio request for profile: " + profileID); - status = false; - } - - if(status == false) { - Log.e(TAG, "failed connect audio request for device: " + mActivedevice); - if(ApmConst.AudioProfiles.HFP != profileID) { - HeadsetService service = HeadsetService.getHeadsetService(); - if(service != null) { - service.getHfpA2DPSyncInterface().releaseA2DP(null); - } - } - } - - return status; - } - - public boolean disconnectAudio() { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); - BluetoothDevice mActivedevice = null; - boolean mStatus = false; - - if(mActiveDeviceManager != null) { - mActivedevice = mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.CALL_AUDIO); - } - Log.i(TAG, "disconnectAudio: device=" + mActivedevice + ", " + Utils.getUidPidString()); - - int profileID = mActiveDeviceManager.getActiveProfile(ApmConst.AudioFeatures.CALL_AUDIO); - - if(ApmConst.AudioProfiles.HFP == profileID) { - HeadsetService service = HeadsetService.getHeadsetService(); - if (service == null) { - mStatus = false; - } - mStatus = service.disconnectAudio(); - } else if(ApmConst.AudioProfiles.BAP_CALL == profileID) { - StreamAudioService service = StreamAudioService.getStreamAudioService(); - if(service != null) { - mStatus = service.stopStream(mActivedevice); - } - } else { - Log.e(TAG, "Unhandled disconnectAudio request for profile: " + profileID); - mStatus = true; - } - - if(ApmConst.AudioProfiles.HFP != profileID) { - HeadsetService service = HeadsetService.getHeadsetService(); - if(service != null) { - service.getHfpA2DPSyncInterface().releaseA2DP(null); - } - } - return mStatus; - } - - public boolean setConnectionPolicy(BluetoothDevice device, Integer connectionPolicy) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, - "Need BLUETOOTH_PRIVILEGED permission"); - boolean mStatus; - - Log.d(TAG, "setConnectionPolicy: device=" + device - + ", connectionPolicy=" + connectionPolicy + ", " + Utils.getUidPidString()); - - mStatus = mAdapterService.getDatabase() - .setProfileConnectionPolicy(device, BluetoothProfile.HEADSET, connectionPolicy); - - if (mStatus && - connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - connect(device); - } else if (mStatus && - connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { - disconnect(device); - } - return mStatus; - } - - public int getConnectionPolicy(BluetoothDevice device) { - if(mAdapterService != null) { - int connPolicy; - connPolicy = mAdapterService.getDatabase() - .getProfileConnectionPolicy(device, BluetoothProfile.HEADSET); - Log.d(TAG, "getConnectionPolicy: device=" + device - + ", connectionPolicy=" + connPolicy); - return connPolicy; - } else { - return BluetoothProfile.CONNECTION_POLICY_UNKNOWN; - - } - } - - public int getAudioState(BluetoothDevice device) { - if(device == null) - return BluetoothHeadset.STATE_AUDIO_DISCONNECTED; - CallDevice mCallDevice; - mCallDevice = mCallDevicesMap.get(device.getAddress()); - if (mCallDevice == null) { - Log.w(TAG, "getAudioState: device " + device + " was never connected/connecting"); - return BluetoothHeadset.STATE_AUDIO_DISCONNECTED; - } - return mCallDevice.scoStatus; - } - - private List getNonIdleAudioDevices() { - if(mCallDevicesMap.size() == 0) { - return new ArrayList<>(0); - } - - ArrayList devices = new ArrayList<>(); - for (CallDevice mCallDevice : mCallDevicesMap.values()) { - if (mCallDevice.scoStatus != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { - devices.add(mCallDevice.mDevice); - } - } - return devices; - } - - public boolean isAudioOn() { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - int numConnectedAudioDevices = getNonIdleAudioDevices().size(); - Log.d(TAG," isAudioOn: The number of audio connected devices " - + numConnectedAudioDevices); - return numConnectedAudioDevices > 0; - } - - public List getConnectedDevices() { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - Log.i(TAG, "getConnectedDevices: "); - if(mCallDevicesMap.size() == 0) { - Log.i(TAG, "no device is Connected:"); - return new ArrayList<>(0); - } - - List connectedDevices = new ArrayList<>(); - for(CallDevice mCallDevice : mCallDevicesMap.values()) { - if(mCallDevice.deviceConnStatus == BluetoothProfile.STATE_CONNECTED) { - connectedDevices.add(mCallDevice.mDevice); - } - } - Log.i(TAG, "ConnectedDevices: = " + connectedDevices.size()); - return connectedDevices; - } - - public int getConnectionState(BluetoothDevice device) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - - if(device == null) - return BluetoothProfile.STATE_DISCONNECTED; - CallDevice mCallDevice; - mCallDevice = mCallDevicesMap.get(device.getAddress()); - if(mCallDevice != null) - return mCallDevice.deviceConnStatus; - - return BluetoothProfile.STATE_DISCONNECTED; - } - - public boolean isVoiceOrCallActive() { - boolean isVoiceActive = isAudioOn() || mVirtualCallStarted; - HeadsetService mHeadsetService = HeadsetService.getHeadsetService(); - if(mHeadsetService != null) { - isVoiceActive = isVoiceActive || mHeadsetService.isScoOrCallActive(); - } - return isVoiceActive; - } - - private void broadcastConnStateChange(BluetoothDevice device, int fromState, int toState) { - Log.d(TAG,"broadcastConnectionState " + device + ": " + fromState + "->" + toState); - HeadsetService mHeadsetService = HeadsetService.getHeadsetService(); - if(mHeadsetService == null) { - Log.w(TAG,"broadcastConnectionState: HeadsetService not initialized. Return!"); - return; - } - - Intent intent = new Intent(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); - intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, fromState); - intent.putExtra(BluetoothProfile.EXTRA_STATE, toState); - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - mHeadsetService.sendBroadcastAsUser(intent, UserHandle.ALL, - BLUETOOTH_CONNECT, Utils.getTempAllowlistBroadcastOptions()); - } - - private void broadcastAudioState(BluetoothDevice device, int fromState, int toState) { - Log.d(TAG,"broadcastAudioState " + device + ": " + fromState + "->" + toState); - HeadsetService mHeadsetService = HeadsetService.getHeadsetService(); - if(mHeadsetService == null) { - Log.d(TAG,"broadcastAudioState: HeadsetService not initialized. Return!"); - return; - } - - Intent intent = new Intent(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); - intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, fromState); - intent.putExtra(BluetoothProfile.EXTRA_STATE, toState); - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - mHeadsetService.sendBroadcastAsUser(intent, UserHandle.ALL, - BLUETOOTH_CONNECT, Utils.getTempAllowlistBroadcastOptions()); - } - - public void onConnStateChange(BluetoothDevice device, Integer state, Integer profile) { - int prevState; - Log.w(TAG, "onConnStateChange: profile: " + profile + " state: " - + state + " for device " + device); - if(device == null) - return; - CallDevice mCallDevice = mCallDevicesMap.get(device.getAddress()); - - if(mCallDevice == null) { - if(state == BluetoothProfile.STATE_DISCONNECTED) - return; - if(mCallDevicesMap.size() >= MAX_DEVICES) { - return; - } - mCallDevice = new CallDevice(device, profile, state); - mCallDevicesMap.put(device.getAddress(), mCallDevice); - broadcastConnStateChange(device, BluetoothProfile.STATE_DISCONNECTED, state); - return; - } - - int profileIndex = mCallDevice.getProfileIndex(profile); - DeviceProfileMap dMap = DeviceProfileMap.getDeviceProfileMapInstance(); - prevState = mCallDevice.deviceConnStatus; - mCallDevice.profileConnStatus[profileIndex] = state; - - if(state == BluetoothProfile.STATE_DISCONNECTED) { - dMap.profileConnectionUpdate(device, ApmConst.AudioFeatures.CALL_AUDIO, profile, false); - } - - int otherProfileConnectionState = mCallDevice.profileConnStatus[(profileIndex+1)%2]; - Log.w(TAG, " otherProfileConnectionState: " + otherProfileConnectionState); - - switch(otherProfileConnectionState) { - /*Send Broadcast based on state of other profile*/ - case BluetoothProfile.STATE_DISCONNECTED: - broadcastConnStateChange(device, prevState, state); - mCallDevice.deviceConnStatus = state; - if(state == BluetoothProfile.STATE_CONNECTED) { - int supportedProfiles = dMap.getSupportedProfile(device, ApmConst.AudioFeatures.CALL_AUDIO); - if(profile == ApmConst.AudioProfiles.HFP && - (supportedProfiles & ApmConst.AudioProfiles.BAP_CALL) == ApmConst.AudioProfiles.BAP_CALL) { - Log.w(TAG, "Connect LE Voice after HFP auto connect from remote"); - StreamAudioService mStreamService = StreamAudioService.getStreamAudioService(); - if(mStreamService != null) { - mStreamService.connectLeStream(device, ApmConst.AudioProfiles.BAP_CALL); - } - } else { - ActiveDeviceManagerService mActiveDeviceManager = ActiveDeviceManagerService.get(); - mActiveDeviceManager.setActiveDevice(device, ApmConst.AudioFeatures.CALL_AUDIO); - } - } - break; - case BluetoothProfile.STATE_CONNECTING: - int preferredProfile = dMap.getProfile(device, ApmConst.AudioFeatures.CALL_AUDIO); - boolean isPreferredProfile = (preferredProfile == profile); - if(state == BluetoothProfile.STATE_CONNECTED && isPreferredProfile) { - broadcastConnStateChange(device, prevState, state); - mCallDevice.deviceConnStatus = state; - } - break; - case BluetoothProfile.STATE_DISCONNECTING: - if(state == BluetoothProfile.STATE_CONNECTING || - state == BluetoothProfile.STATE_CONNECTED) { - broadcastConnStateChange(device, prevState, state); - mCallDevice.deviceConnStatus = state; - } - break; - case BluetoothProfile.STATE_CONNECTED: - if(state == BluetoothProfile.STATE_CONNECTED) { - if(prevState != state) { - broadcastConnStateChange(device, prevState, state); - mCallDevice.deviceConnStatus = state; - } - ActiveDeviceManagerService mActiveDeviceManager = - ActiveDeviceManagerService.get(); - mActiveDeviceManager.setActiveDevice(device, ApmConst.AudioFeatures.CALL_AUDIO); - } else if(state == BluetoothProfile.STATE_DISCONNECTED) { - if(prevState != BluetoothProfile.STATE_CONNECTED) { - broadcastConnStateChange(device, prevState, BluetoothProfile.STATE_CONNECTED); - mCallDevice.deviceConnStatus = BluetoothProfile.STATE_CONNECTED; - } else { - ActiveDeviceManagerService mActiveDeviceManager = - ActiveDeviceManagerService.get(); - if(device.equals(mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.CALL_AUDIO))) { - mActiveDeviceManager.setActiveDevice(device, ApmConst.AudioFeatures.CALL_AUDIO); - } - } - } - break; - } - - if(state == BluetoothProfile.STATE_CONNECTED) { - dMap.profileConnectionUpdate(device, ApmConst.AudioFeatures.CALL_AUDIO, profile, true); - } - } - - public void onAudioStateChange(BluetoothDevice device, Integer state) { - int prevStatus; - if(device == null) - return; - CallDevice mCallDevice = mCallDevicesMap.get(device.getAddress()); - if(mCallDevice == null) { - return; - } - - if(mCallDevice.scoStatus == state) - return; - - HeadsetService service = HeadsetService.getHeadsetService(); - int profileID = mActiveDeviceManager.getActiveProfile( - ApmConst.AudioFeatures.CALL_AUDIO); - BluetoothDevice mActivedevice = mActiveDeviceManager.getActiveDevice( - ApmConst.AudioFeatures.CALL_AUDIO); - if (service != null) { - if(!(service.shouldCallAudioBeActive() || mVirtualCallStarted)) { - if(ApmConst.AudioProfiles.BAP_CALL == profileID) { - StreamAudioService mStreamAudioService = - StreamAudioService.getStreamAudioService(); - if(mStreamAudioService != null) { - Log.w(TAG, "Call not active, disconnect stream"); - mStreamAudioService.stopStream(mActivedevice); - } - } - } - } - - prevStatus = mCallDevice.scoStatus; - mCallDevice.scoStatus = state; - VolumeManager mVolumeManager = VolumeManager.get(); - mVolumeManager.updateStreamState(device, state, ApmConst.AudioFeatures.CALL_AUDIO); - broadcastAudioState(device, prevStatus, state); - if(state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { - if(ApmConst.AudioProfiles.HFP != profileID) { - if(service != null) { - service.getHfpA2DPSyncInterface().releaseA2DP(null); - } - } - //mAudioManager.setBluetoothScoOn(false); - } /*else { - mAudioManager.setBluetoothScoOn(true); - }*/ - } - - public void setAudioParam(String param) { - mAudioManager.setParameters(param); - } - - public void setBluetoothScoOn(boolean on) { - mAudioManager.setBluetoothScoOn(on); - } - - public AudioManager getAudioManager() { - return mAudioManager; - } - - class CallDevice { - BluetoothDevice mDevice; - int[] profileConnStatus = new int[2]; - int deviceConnStatus; - int scoStatus; - - public static final int SCO_STREAM = 0; - public static final int LE_STREAM = 1; - - CallDevice(BluetoothDevice device, int profile, int state) { - mDevice = device; - if(profile == ApmConst.AudioProfiles.HFP) { - profileConnStatus[SCO_STREAM] = state; - profileConnStatus[LE_STREAM] = BluetoothProfile.STATE_DISCONNECTED; - } else { - profileConnStatus[LE_STREAM] = state; - profileConnStatus[SCO_STREAM] = BluetoothProfile.STATE_DISCONNECTED; - } - deviceConnStatus = state; - scoStatus = BluetoothHeadset.STATE_AUDIO_DISCONNECTED;; - } - - CallDevice(BluetoothDevice device, int profile) { - this(device, profile, BluetoothProfile.STATE_DISCONNECTED); - } - - public int getProfileIndex(int profile) { - if(profile == ApmConst.AudioProfiles.HFP) - return SCO_STREAM; - else - return LE_STREAM; - } - } -} - diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/CallControl.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/CallControl.java deleted file mode 100644 index 40e5fd15cd00204d96315f6be69a8b0723bbec3d..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/CallControl.java +++ /dev/null @@ -1,164 +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. - * - ******************************************************************************/ - - -package com.android.bluetooth.apm; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothAdapter; -import com.android.bluetooth.hfp.HeadsetService; -import com.android.bluetooth.hfp.HeadsetSystemInterface; -import com.android.bluetooth.apm.ApmConst; -import com.android.bluetooth.cc.CCService; -import android.media.AudioManager; -import com.android.bluetooth.apm.ActiveDeviceManagerService; -import android.content.Context; -import android.content.Intent; -import android.os.UserHandle; -import android.net.Uri; -import android.telephony.PhoneNumberUtils; -import android.telecom.PhoneAccount; -import android.os.SystemProperties; - -import android.util.Log; - - -public class CallControl { - - private static CallControl mCallControl; - private static final String TAG = "CallControl"; - private static Context mContext; - private static ActiveDeviceManagerService mActiveDeviceManager; - private static boolean isCCEnabled = true; - private CallControl(Context context) { - Log.d(TAG, "Initialization"); - mContext = context; - } - - public static void init(Context context) { - if(mCallControl == null) { - mCallControl = new CallControl(context); - CallControlIntf.init(mCallControl); - } - isCCEnabled = SystemProperties.getBoolean("persist.vendor.service.bt.cc", true); - Log.d(TAG, "isCCEnabled" + isCCEnabled); - } - - public static CallControl get() { - return mCallControl; - } - - public void phoneStateChanged(Integer numActive, Integer numHeld, Integer callState, String number, - Integer type, String name, Boolean isVirtualCall) { - Log.d(TAG, "phoneStateChanged"); - if(isCCEnabled == true) { - CCService.getCCService().phoneStateChanged(numActive, numHeld,callState,number, - type, name, isVirtualCall); - } - } - - public void setVirtualCallActive(boolean state) { - if(isCCEnabled == true) { - CCService.getCCService().setVirtualCallActive(state); - } - } - - public void clccResponse(Integer index, Integer direction, Integer status, Integer mode, Boolean mpty, - String number, Integer type) { - Log.d(TAG, "clccResponse"); - if (isCCEnabled == true) { - CCService.getCCService().clccResponse(index, direction, status, mode, mpty, number, type); - } - } - - public void updateBearerTechnology(Integer tech) { - Log.d(TAG, "updateBearerTechnology"); - if (isCCEnabled == true) { - CCService.getCCService().updateBearerProviderTechnology(tech); - } - } - - public void updateSignalStatus(Integer signal) { - Log.d(TAG, "updateSignalStatus"); - if (isCCEnabled == true) { - CCService.getCCService().updateSignalStrength(signal); - } - } - - public void updateBearerName(String name) { - Log.d(TAG, "updateBearerProviderName"); - if (isCCEnabled == true) { - CCService.getCCService().updateBearerProviderName(name); - } - } - - public void updateOriginateResult(BluetoothDevice device, Integer event, Integer res) { - Log.d(TAG, "updateOriginateResult"); - if (isCCEnabled == true) { - CCService.getCCService().updateOriginateResult(device, event, res); - } - } - public static void listenForPhoneState (int events) { - Log.d(TAG, "listenForPhoneState"); - BluetoothDevice dummyDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice("CC:CC:CC:CC:CC:CC"); - HeadsetService.getHeadsetService().getSystemInterfaceObj().getHeadsetPhoneState().listenForPhoneState(dummyDevice, events); - } - - public static void answerCall (BluetoothDevice device) { - Log.d(TAG, "answerCall"); - HeadsetService.getHeadsetService().getSystemInterfaceObj().answerCall(device); - } - - public static void hangupCall (BluetoothDevice device) { - Log.d(TAG, "hangupCall"); - HeadsetService.getHeadsetService().getSystemInterfaceObj().hangupCall(device); - } - - public static void terminateCall (BluetoothDevice device, int index) { - Log.d(TAG, "terminateCall"); - HeadsetService.getHeadsetService().getSystemInterfaceObj().terminateCall(device, index); - } - - public static boolean processChld (BluetoothDevice device, int chld) { - Log.d(TAG, "processChld"); - return HeadsetService.getHeadsetService().getSystemInterfaceObj().processChld(chld); - } - - public static boolean holdCall (BluetoothDevice device, int index) { - Log.d(TAG, "holdCall"); - return HeadsetService.getHeadsetService().getSystemInterfaceObj().holdCall(index); - } - - public static boolean listCurrentCalls () { - Log.d(TAG, "listCurrentCalls"); - return HeadsetService.getHeadsetService().getSystemInterfaceObj().listCurrentCalls(); - } - - public static boolean dialOutgoingCall(BluetoothDevice fromDevice, String dialNumber) { - Log.i(TAG, "dialOutgoingCall: from " + fromDevice); - HeadsetService service = HeadsetService.getHeadsetService(); - if (service != null) { - service.dialOutgoingCallInternal(fromDevice, dialNumber); - } - return true; - } - - public static void dial (BluetoothDevice device, String dialNumber) { - dialOutgoingCall(device, dialNumber); - } - -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/DeviceProfileMap.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/DeviceProfileMap.java deleted file mode 100644 index 0901f98618174fa449682348ec2906c97b7ce646..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/DeviceProfileMap.java +++ /dev/null @@ -1,814 +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. - * - ******************************************************************************/ - - -package com.android.bluetooth.apm; - -import android.content.SharedPreferences; -import android.content.BroadcastReceiver; -import android.content.Intent; -import android.content.IntentFilter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothUuid; -import android.os.ParcelUuid; -import android.os.Parcelable; -import android.os.SystemProperties; -import android.util.Log; -import android.content.Context; -import com.android.internal.util.ArrayUtils; -import java.util.HashMap; -import java.util.Map; -import java.util.Arrays; -import java.util.ArrayList; -import java.lang.Integer; -import java.lang.Boolean; -import java.util.Objects; - -public class DeviceProfileMap { - - Map mSupportedProfileMap = new HashMap(); - Map mActiveProfileMap = new HashMap(); - Map mConnectedProfileMap = new HashMap(); - private Context mContext; - private static DeviceProfileMap DPMSingleInstance = null; - public static int [] mPreferredProfileList = new int[ApmConst.AudioFeatures.MAX_AUDIO_FEATURES]; - public static final String SUPPORTED_PROFILE_MAP = "bluetooth_supported_profile_map"; - public final String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN"; - public final String ACTION_POWER_OFF = "android.intent.action.QUICKBOOT_POWEROFF"; - private final Object mLock = new Object(); - - private static final int LeMediaProfiles = ApmConst.AudioProfiles.BAP_MEDIA - | ApmConst.AudioProfiles.TMAP_MEDIA - | ApmConst.AudioProfiles.BAP_GCP - | ApmConst.AudioProfiles.BAP_RECORDING; - - private static final int LeCallProfiles = ApmConst.AudioProfiles.BAP_CALL - | ApmConst.AudioProfiles.TMAP_CALL; - - // private constructor restricted to this class itself - private DeviceProfileMap() { - Log.w(LOGTAG, "DeviceProfileMap object creation"); - } - - // static method to create instance of Singleton class - public static DeviceProfileMap getDeviceProfileMapInstance() { - if (DPMSingleInstance == null) { - DPMSingleInstance = new DeviceProfileMap(); - DeviceProfileMapIntf.init(DPMSingleInstance); - } - return DPMSingleInstance; - } - - private static final String LOGTAG = "DeviceProfileMap"; - private SharedPreferences getSupportedProfileMap() { - return mContext.getSharedPreferences(SUPPORTED_PROFILE_MAP, Context.MODE_PRIVATE); - } - - /** - * Initialize the device profile map - */ - public synchronized boolean init(Context context) { - Log.d(LOGTAG, "init: "); - // populate the supported profile list. - mContext = context; - Map allKeys = getSupportedProfileMap().getAll(); - SharedPreferences.Editor mSupportedProfileMapEditor = getSupportedProfileMap().edit(); - - for (Map.Entry entry : allKeys.entrySet()) { - String key = entry.getKey(); - Object value = entry.getValue(); - BluetoothDevice mBluetoothDevice = BluetoothAdapter.getDefaultAdapter(). - getRemoteDevice(key); - if (value instanceof Integer && mBluetoothDevice.getBondState() - == BluetoothDevice.BOND_BONDED) { - mSupportedProfileMap.put(mBluetoothDevice, (Integer) value); - Log.d(LOGTAG, "address " + key + " from the Supported Profile Map: " + value); - } else { - Log.d(LOGTAG, "Removing " + key + " from the Supported Profile map"); - mSupportedProfileMapEditor.remove(key); - } - } - mSupportedProfileMapEditor.apply(); - //intialize the preferred profile list - int mPreferredProfileVal = - SystemProperties.getInt("persist.vendor.qcom.bluetooth.default_profiles", 0); - Log.d(LOGTAG, "init: Preferred Profile = " + mPreferredProfileVal); - int mfeature = 0; - while (mfeature < ApmConst.AudioFeatures.MAX_AUDIO_FEATURES) { - switch(mfeature) { - case ApmConst.AudioFeatures.CALL_AUDIO: - /* default preferred profile for call */ - mPreferredProfileList[mfeature] = ApmConst.AudioProfiles.HFP; - if((mPreferredProfileVal & - ApmConst.AudioProfiles.TMAP_CALL) != 0) { - mPreferredProfileList[mfeature] = ApmConst.AudioProfiles.TMAP_CALL; - } else if((mPreferredProfileVal & - ApmConst.AudioProfiles.BAP_CALL) != 0) { - mPreferredProfileList[mfeature] = ApmConst.AudioProfiles.BAP_CALL; - } - break; - case ApmConst.AudioFeatures.MEDIA_AUDIO: - mPreferredProfileList[mfeature] = ApmConst.AudioProfiles.A2DP; - if((mPreferredProfileVal & - ApmConst.AudioProfiles.TMAP_MEDIA) != 0) { - mPreferredProfileList[mfeature] = ApmConst.AudioProfiles.TMAP_MEDIA; - } else if((mPreferredProfileVal & - ApmConst.AudioProfiles.BAP_RECORDING) != 0) { - mPreferredProfileList[mfeature] = ApmConst.AudioProfiles.BAP_RECORDING; - } else if((mPreferredProfileVal & - ApmConst.AudioProfiles.BAP_MEDIA) != 0) { - mPreferredProfileList[mfeature] = ApmConst.AudioProfiles.BAP_MEDIA; - } - break; - case ApmConst.AudioFeatures.CALL_CONTROL: - mPreferredProfileList[mfeature] = ((mPreferredProfileVal & - ApmConst.AudioProfiles.CCP) != 0) ? - ApmConst.AudioProfiles.CCP : ApmConst.AudioProfiles.HFP; - break; - case ApmConst.AudioFeatures.MEDIA_CONTROL: - mPreferredProfileList[mfeature] = ((mPreferredProfileVal & - ApmConst.AudioProfiles.AVRCP) != 0) ? - ApmConst.AudioProfiles.AVRCP : ApmConst.AudioProfiles.MCP; - break; - case ApmConst.AudioFeatures.CALL_VOLUME_CONTROL: - mPreferredProfileList[mfeature] = ((mPreferredProfileVal & - (ApmConst.AudioProfiles.BAP_CALL | ApmConst.AudioProfiles.TMAP_CALL)) != 0) ? - ApmConst.AudioProfiles.VCP : ApmConst.AudioProfiles.HFP; - break; - case ApmConst.AudioFeatures.MEDIA_VOLUME_CONTROL: - mPreferredProfileList[mfeature] = ((mPreferredProfileVal & - ApmConst.AudioProfiles.AVRCP) != 0) ? - ApmConst.AudioProfiles.AVRCP : ApmConst.AudioProfiles.VCP; - break; - case ApmConst.AudioFeatures.HEARING_AID: - mPreferredProfileList[mfeature] = ((mPreferredProfileVal & - ApmConst.AudioProfiles.HAP_BREDR) != 0) ? - ApmConst.AudioProfiles.HAP_BREDR : ApmConst.AudioProfiles.HAP_LE; - break; - case ApmConst.AudioFeatures.BROADCAST_AUDIO: - mPreferredProfileList[mfeature] = ((mPreferredProfileVal & - ApmConst.AudioProfiles.BROADCAST_BREDR) != 0) ? - ApmConst.AudioProfiles.BROADCAST_BREDR : ApmConst.AudioProfiles.BROADCAST_LE; - break; - default : - break; - } - Log.w(LOGTAG, "init: Preferred Profile = " + mPreferredProfileList[mfeature] + - " for audio feature " + mfeature); - mfeature++; - } - - IntentFilter filter = new IntentFilter(); - filter.addAction(BluetoothDevice.ACTION_UUID); - filter.addAction(ACTION_SHUTDOWN); - filter.addAction(ACTION_POWER_OFF); - mContext.registerReceiver(mDeviceProfileMapReceiver, filter); - - return true; - } - - private final BroadcastReceiver mDeviceProfileMapReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action == null) { - Log.w(LOGTAG, "mDeviceProfileMapReceiver, action is null"); - return; - } - switch (action) { - case BluetoothDevice.ACTION_UUID: { - BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - Parcelable[] uuids = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID); - handleDeviceUuidEvent(device, uuids); - break; - } - case ACTION_SHUTDOWN: - case ACTION_POWER_OFF: - handleDeviceShutdown(); - break; - default: - Log.w(LOGTAG, "Unknown action " + action); - } - } - }; - - private void handleDeviceUuidEvent(BluetoothDevice device, Parcelable[] uuids) { - Log.d(LOGTAG, "UUIDs found, device: " + device); - if (uuids != null) { - ParcelUuid[] uuidsToSend = new ParcelUuid[uuids.length]; - for (int i = 0; i < uuidsToSend.length; i++) { - uuidsToSend[i] = (ParcelUuid) uuids[i]; - Log.d(LOGTAG,"index=" + i + "uuid=" + uuidsToSend[i]); - } - checkIfProfileSupported(device, uuidsToSend); - } - } - - private void checkIfProfileSupported(BluetoothDevice device, ParcelUuid[] remoteDeviceUuids) { - ParcelUuid ADV_AUDIO_T_MEDIA = - ParcelUuid.fromString("00006AD0-0000-1000-8000-00805F9B34FB"); - - ParcelUuid HEARINGAID_ADV_AUDIO = - ParcelUuid.fromString("00006AD2-0000-1000-8000-00805F9B34FB"); - - ParcelUuid ADV_AUDIO_P_MEDIA = - ParcelUuid.fromString("00006AD1-0000-1000-8000-00805F9B34FB"); - - ParcelUuid ADV_AUDIO_P_VOICE = - ParcelUuid.fromString("00006AD4-0000-1000-8000-00805F9B34FB"); - - ParcelUuid ADV_AUDIO_T_VOICE = - ParcelUuid.fromString("00006AD5-0000-1000-8000-00805F9B34FB"); - - ParcelUuid ADV_AUDIO_G_MEDIA = - ParcelUuid.fromString("12994B7E-6d47-4215-8C9E-AAE9A1095BA3"); - - ParcelUuid ADV_AUDIO_W_RECORDING = - ParcelUuid.fromString("2587DB3C-CE70-4FC9-935F-777AB4188FD7"); - - if (ArrayUtils.contains(remoteDeviceUuids, BluetoothUuid.HFP)) { - updateSupportedProfileMap(device, ApmConst.AudioProfiles.HFP); - } - if (ArrayUtils.contains(remoteDeviceUuids, BluetoothUuid.A2DP_SINK)) { - updateSupportedProfileMap(device, ApmConst.AudioProfiles.A2DP); - } - if (ArrayUtils.contains(remoteDeviceUuids, BluetoothUuid.HEARING_AID)) { - updateSupportedProfileMap(device, ApmConst.AudioProfiles.HAP_BREDR); - } - if (ArrayUtils.contains(remoteDeviceUuids, BluetoothUuid.AVRCP_CONTROLLER)) { - updateSupportedProfileMap(device, ApmConst.AudioProfiles.AVRCP); - } - if (ArrayUtils.contains(remoteDeviceUuids, ADV_AUDIO_T_MEDIA)) { - updateSupportedProfileMap(device, ApmConst.AudioProfiles.TMAP_MEDIA); - } - if (ArrayUtils.contains(remoteDeviceUuids, ADV_AUDIO_T_VOICE)) { - updateSupportedProfileMap(device, ApmConst.AudioProfiles.TMAP_CALL); - } - if (ArrayUtils.contains(remoteDeviceUuids, ADV_AUDIO_P_MEDIA)) { - updateSupportedProfileMap(device, ApmConst.AudioProfiles.BAP_MEDIA); - } - if (ArrayUtils.contains(remoteDeviceUuids, ADV_AUDIO_P_VOICE)) { - updateSupportedProfileMap(device, ApmConst.AudioProfiles.BAP_CALL); - } - if (ArrayUtils.contains(remoteDeviceUuids, ADV_AUDIO_W_RECORDING)) { - updateSupportedProfileMap(device, ApmConst.AudioProfiles.BAP_RECORDING); - } - } - - private void updateSupportedProfileMap(BluetoothDevice device, int mProfile) { - synchronized (mLock) { - int mSupportedProfileBitMap = 0; - if(!mSupportedProfileMap.containsKey(device)) { - //device is not added in supported map, add to it - Log.d(LOGTAG, "updateSupportedProfileMap: device " + device + - "is not added in supported map, add it"); - mSupportedProfileMap.put(device, mSupportedProfileBitMap); - } else { - mSupportedProfileBitMap = mSupportedProfileMap.get(device); - } - Log.d(LOGTAG, "updateSupportedProfileMap: device " + device + " for profile " - + mProfile + " mSupportedProfileBitMap " + mSupportedProfileBitMap); - mSupportedProfileBitMap = mSupportedProfileBitMap | mProfile; - mSupportedProfileMap.put(device, mSupportedProfileBitMap); - Log.d(LOGTAG, "updateSupportedProfileMap: device " + device + " for profile " - + mProfile + " mSupportedProfileBitMap " + mSupportedProfileBitMap); - } - } - - public int getAllSupportedProfile(BluetoothDevice device) { - int mSupportedProfileBitMap = 0; - synchronized (mLock) { - if(!mSupportedProfileMap.containsKey(device)) { - Log.d(LOGTAG, "No Supported Profile found for the device " + device); - } else { - mSupportedProfileBitMap = mSupportedProfileMap.get(device); - } - Log.d(LOGTAG, "getAllSupportedProfile: Supported Profile for the device " - + device + " mSupportedProfileBitMap " + Integer.toHexString(mSupportedProfileBitMap)); - } - return mSupportedProfileBitMap; - } - - public int getProfile(BluetoothDevice device, Integer mAudioFeature) { - int profileMap = getSupportedProfile(device, mAudioFeature); - int preferredProfile = profileMap; - int [] mAciveProfileArray = mActiveProfileMap.get(device); - - if(profileMap == ApmConst.AudioProfiles.NONE) - return ApmConst.AudioProfiles.NONE; - - switch(mAudioFeature) { - case ApmConst.AudioFeatures.CALL_AUDIO: - int mActiveProfileForCallAudio = mAciveProfileArray[mAudioFeature]; - if(mActiveProfileForCallAudio != ApmConst.AudioProfiles.NONE) { - //active profile is set - preferredProfile = mActiveProfileForCallAudio; - return preferredProfile; - } - - if(profileMap == ApmConst.AudioProfiles.HAP_BREDR || - profileMap == ApmConst.AudioProfiles.HAP_LE) { - preferredProfile = profileMap; - return preferredProfile; - } - - int mHFP = profileMap & ApmConst.AudioProfiles.HFP; - int mLeCall = profileMap & ApmConst.AudioProfiles.TMAP_CALL; - if(mLeCall == ApmConst.AudioProfiles.NONE) - mLeCall = profileMap & ApmConst.AudioProfiles.BAP_CALL; - - if(mHFP != ApmConst.AudioProfiles.NONE && - mLeCall != ApmConst.AudioProfiles.NONE) { - preferredProfile = mPreferredProfileList[mAudioFeature]; - } else if(mHFP != ApmConst.AudioProfiles.NONE) { - preferredProfile = mHFP; - } else { - preferredProfile = mLeCall; - } - - Log.d(LOGTAG, "getProfile: device " + device + " preferredProfile: " - + preferredProfile + " for CALL_AUDIO"); - break; - - case ApmConst.AudioFeatures.MEDIA_AUDIO: - int mActiveProfileForMediaAudio = mAciveProfileArray[mAudioFeature]; - if(mActiveProfileForMediaAudio != ApmConst.AudioProfiles.NONE) { - //active profile is set - preferredProfile = mActiveProfileForMediaAudio; - Log.d(LOGTAG, "getProfile: device " + device + " Active Profile: " - + preferredProfile + " for MEDIA_AUDIO"); - return preferredProfile; - } - - if(profileMap == ApmConst.AudioProfiles.HAP_BREDR || - profileMap == ApmConst.AudioProfiles.HAP_LE) { - preferredProfile = profileMap; - return preferredProfile; - } - - int mA2dp = profileMap & ApmConst.AudioProfiles.A2DP; - int mLeMedia = profileMap & ApmConst.AudioProfiles.TMAP_MEDIA; - if(mLeMedia == ApmConst.AudioProfiles.NONE) - mLeMedia = profileMap & ApmConst.AudioProfiles.BAP_MEDIA; - - if(mA2dp != ApmConst.AudioProfiles.NONE && - mLeMedia != ApmConst.AudioProfiles.NONE) { - preferredProfile = mPreferredProfileList[mAudioFeature]; - } else if(mA2dp != ApmConst.AudioProfiles.NONE) { - preferredProfile = mA2dp; - } else { - if((preferredProfile & ApmConst.AudioProfiles.BAP_RECORDING) - != ApmConst.AudioProfiles.NONE) - preferredProfile = mPreferredProfileList[mAudioFeature]; - else - preferredProfile = mLeMedia; - } - - Log.d(LOGTAG, "getProfile: device " + device + " preferredProfile: " - + preferredProfile + " for MEDIA_AUDIO"); - break; - } - return preferredProfile; - } - - public int getSupportedProfile(BluetoothDevice device, Integer mAudioFeature) { - int [] mAciveProfileArray; - - Log.d(LOGTAG, "getSupportedProfile: for the device " + device + " AudioFeature " + mAudioFeature); - if(!mActiveProfileMap.containsKey(device)) { - // intialize the active profile but map for the device - Log.d(LOGTAG, "getSupportedProfile: intialize the active profile map for the device " + device); - mAciveProfileArray = new int[ApmConst.AudioFeatures.MAX_AUDIO_FEATURES]; - Arrays.fill(mAciveProfileArray, ApmConst.AudioProfiles.NONE); - mActiveProfileMap.put(device, mAciveProfileArray); - } else { - mAciveProfileArray = mActiveProfileMap.get(device); - } - //get the supprted profile list - int mSupportedProfileBitMap = 0; - if(!mSupportedProfileMap.containsKey(device)) { - //device is not added in supported map, add to it - Log.d(LOGTAG, "getSupportedProfile: device " + device + " is not added in supported map, add it"); - mSupportedProfileMap.put(device, mSupportedProfileBitMap); - } else { - mSupportedProfileBitMap = mSupportedProfileMap.get(device); - } - Log.d(LOGTAG, "getSupportedProfile: supported Profiles for the device " + device - + " val = " + Integer.toHexString(mSupportedProfileBitMap)); - - switch(mAudioFeature) { - case ApmConst.AudioFeatures.CALL_AUDIO: - { - int mIsHapBREDRSupported = mSupportedProfileBitMap & ApmConst.AudioProfiles.HAP_BREDR; - int mIsHapLESupported = mSupportedProfileBitMap & ApmConst.AudioProfiles.HAP_LE; - - if(mIsHapBREDRSupported != ApmConst.AudioProfiles.NONE) { - return ApmConst.AudioProfiles.HAP_BREDR; - } else if (mIsHapLESupported != ApmConst.AudioProfiles.NONE) { - return ApmConst.AudioProfiles.HAP_LE; - } - - int mCallAudioProfile = mSupportedProfileBitMap & ( ApmConst.AudioProfiles.HFP - | ApmConst.AudioProfiles.BAP_CALL - | ApmConst.AudioProfiles.TMAP_CALL); - - Log.d(LOGTAG, "getSupportedProfile: device " + device + " supports: " - + mCallAudioProfile + " for CALL_AUDIO"); - - return mCallAudioProfile; - } - - case ApmConst.AudioFeatures.MEDIA_AUDIO: - { - int mIsHapBREDRSupported = mSupportedProfileBitMap & ApmConst.AudioProfiles.HAP_BREDR; - int mIsHapLESupported = mSupportedProfileBitMap & ApmConst.AudioProfiles.HAP_LE; - - if(mIsHapBREDRSupported != ApmConst.AudioProfiles.NONE) { - return ApmConst.AudioProfiles.HAP_BREDR; - } else if (mIsHapLESupported != ApmConst.AudioProfiles.NONE) { - return ApmConst.AudioProfiles.HAP_LE; - } - - int mMediaAudioProfile = mSupportedProfileBitMap & ( ApmConst.AudioProfiles.A2DP - | ApmConst.AudioProfiles.BAP_MEDIA - | ApmConst.AudioProfiles.TMAP_MEDIA - | ApmConst.AudioProfiles.BAP_RECORDING); - - Log.d(LOGTAG, "getSupportedProfile: device " + device + " supports: " - + mMediaAudioProfile + " for MEDIA_AUDIO"); - - return mMediaAudioProfile; - } - case ApmConst.AudioFeatures.MEDIA_CONTROL: - { - int mActiveProfileForMediaControl = mAciveProfileArray - [ApmConst.AudioFeatures.MEDIA_CONTROL]; - Log.d(LOGTAG, "getSupportedProfile: device " + device + " ActiveProfile For MediaControl " + - mActiveProfileForMediaControl); - return mActiveProfileForMediaControl; - } - case ApmConst.AudioFeatures.CALL_CONTROL: - { - int mActiveProfileForCallControl = mAciveProfileArray - [ApmConst.AudioFeatures.CALL_CONTROL]; - Log.d(LOGTAG, "getSupportedProfile: device " + device + " ActiveProfile For Call Control " + - mActiveProfileForCallControl); - return mActiveProfileForCallControl; - } - case ApmConst.AudioFeatures.MEDIA_VOLUME_CONTROL: - { - int mActiveProfileForMediaVolControl = mAciveProfileArray - [ApmConst.AudioFeatures.MEDIA_VOLUME_CONTROL]; - Log.d(LOGTAG, "getSupportedProfile: device " + device + - " ActiveProfile For Media Volume Control " + mActiveProfileForMediaVolControl); - - return mActiveProfileForMediaVolControl; - } - case ApmConst.AudioFeatures.CALL_VOLUME_CONTROL: - { - int mActiveProfileForCallVolControl = mAciveProfileArray - [ApmConst.AudioFeatures.CALL_VOLUME_CONTROL]; - Log.d(LOGTAG, "getSupportedProfile: device " + device + - " ActiveProfile For call Volume Control " + mActiveProfileForCallVolControl); - - return mActiveProfileForCallVolControl; - - } - case ApmConst.AudioFeatures.BROADCAST_AUDIO: - { - int mActiveProfileForBroadCastAudio = mAciveProfileArray - [ApmConst.AudioFeatures.BROADCAST_AUDIO]; - if(mActiveProfileForBroadCastAudio != ApmConst.AudioProfiles.NONE) { - //active profile is set - return mActiveProfileForBroadCastAudio; - } - - int mIsBroadCastBREDRSupported = mSupportedProfileBitMap & - ApmConst.AudioProfiles.BROADCAST_BREDR; - int mIsBroadCastLESupported = - mSupportedProfileBitMap & ApmConst.AudioProfiles.BROADCAST_LE; - Log.d(LOGTAG, "getSupportedProfile: device " + device + " mIsBroadCastBREDRSupported " - + mIsBroadCastBREDRSupported + " mIsBroadCastLESupported " - + mIsBroadCastLESupported); - - if((mIsBroadCastBREDRSupported != 0) && (mIsBroadCastLESupported != 0)) { - return mPreferredProfileList[ApmConst.AudioFeatures.BROADCAST_AUDIO]; - } else if (mIsBroadCastBREDRSupported != 0) { - return ApmConst.AudioProfiles.BROADCAST_BREDR; - } else if(mIsBroadCastLESupported != 0) { - return ApmConst.AudioProfiles.BROADCAST_LE; - } - break; - } - case ApmConst.AudioFeatures.HEARING_AID: - { - int mActiveProfileForHearingAid = mAciveProfileArray - [ApmConst.AudioFeatures.HEARING_AID]; - if(mActiveProfileForHearingAid != ApmConst.AudioProfiles.NONE) { - //active profile is set - return mActiveProfileForHearingAid; - } - - int mIsHAPBREDRSupported = mSupportedProfileBitMap & ApmConst.AudioProfiles.HAP_BREDR; - int mIsHAPLESupported = mSupportedProfileBitMap & ApmConst.AudioProfiles.HAP_LE; - Log.d(LOGTAG, "getSupportedProfile: device " + device + " mIsHAPBREDRSupported " - + mIsHAPBREDRSupported + " mIsHAPLESupported " + mIsHAPLESupported); - - if((mIsHAPBREDRSupported != 0) && (mIsHAPLESupported !=0)) { - return mPreferredProfileList[ApmConst.AudioFeatures.HEARING_AID]; - } else if (mIsHAPBREDRSupported != 0) { - return ApmConst.AudioProfiles.HAP_BREDR; - } else if(mIsHAPLESupported != 0) { - return ApmConst.AudioProfiles.HAP_LE; - } - break; - } - default : - { - Log.w(LOGTAG, "getSupportedProfile: no profile supported for" + - mAudioFeature + " device " + device); - return ApmConst.AudioProfiles.NONE; - } - } - return ApmConst.AudioProfiles.NONE; - } - - public void profileDescoveryUpdate (BluetoothDevice device, Integer mAudioProfile) { - int mSupportedProfileBitMap = 0; - if(mSupportedProfileMap.containsKey(device)) { - mSupportedProfileBitMap = mSupportedProfileMap.get(device); - } - - mSupportedProfileBitMap = mSupportedProfileBitMap | mAudioProfile; - mSupportedProfileMap.put(device, mSupportedProfileBitMap); - } - - public void profileConnectionUpdate(BluetoothDevice device, Integer mAudioFeature, - Integer mAudioProfile, Boolean mProfileStatus) { - int mSupportedProfileBitMap = 0; - int mConnectedProfileBitMap = 0; - int [] mAciveProfileArray; - - Log.d(LOGTAG, "profileConnectionUpdate: device : " + device + " AudioProfile " - + mAudioProfile + " ProfileStatus " + mProfileStatus); - - synchronized (mLock) { - // get the Connected profile list - if(mConnectedProfileMap.containsKey(device)) { - mConnectedProfileBitMap = mConnectedProfileMap.get(device); - } - - // get the Supported profile list - if(mSupportedProfileMap.containsKey(device)) { - mSupportedProfileBitMap = mSupportedProfileMap.get(device); - } - - if(!mActiveProfileMap.containsKey(device)) { - // intialize the active profile but map for the device - Log.d(LOGTAG, "profileConnectionUpdate: intialize the active " + - " profile map for the device " + device); - mAciveProfileArray = new int[ApmConst.AudioFeatures.MAX_AUDIO_FEATURES]; - Arrays.fill(mAciveProfileArray, ApmConst.AudioProfiles.NONE); - mActiveProfileMap.put(device, mAciveProfileArray); - } else { - mAciveProfileArray = mActiveProfileMap.get(device); - } - // update the Audio profile connection in list - if (mProfileStatus) { - mSupportedProfileBitMap = mSupportedProfileBitMap | mAudioProfile; - mConnectedProfileBitMap = mConnectedProfileBitMap | mAudioProfile; - - //update the active profile list - if(mAciveProfileArray[mAudioFeature] == ApmConst.AudioProfiles.NONE) { - mAciveProfileArray[mAudioFeature] = mAudioProfile; - } else if(mAciveProfileArray[mAudioFeature] != mAudioProfile) { - // diffrent profile connected for the same mAudioFeature need to update the active list. - int mPreferredProfile = mPreferredProfileList[mAudioFeature]; - Log.d(LOGTAG, "profileConnectionUpdate: PreferredProfile for audio feature " + - mAudioFeature + " is " + mPreferredProfile + " device " + device); - if((mPreferredProfile != ApmConst.AudioProfiles.NONE) - && (mConnectedProfileBitMap & mPreferredProfile) != 0) { - mAciveProfileArray[mAudioFeature] = mPreferredProfile; - } - } - } else { - mConnectedProfileBitMap = mConnectedProfileBitMap & ~mAudioProfile; - // profile disconnect for active profile - if(mAciveProfileArray[mAudioFeature] == mAudioProfile) { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.NONE; - // do we need to update the active profile with other connected profile for that audio feature. - switch(mAudioFeature) { - case ApmConst.AudioFeatures.CALL_AUDIO: - if(mAudioProfile == ApmConst.AudioProfiles.HFP) { - if((mConnectedProfileBitMap & ApmConst.AudioProfiles.TMAP_CALL) > 0) { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.TMAP_CALL; - } else if ((mConnectedProfileBitMap & ApmConst.AudioProfiles.BAP_CALL) > 0) { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.BAP_CALL; - } else { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.NONE; - } - } else if (mAudioProfile == ApmConst.AudioProfiles.TMAP_CALL - || mAudioProfile == ApmConst.AudioProfiles.BAP_CALL) { - if((mConnectedProfileBitMap & ApmConst.AudioProfiles.HFP) > 0) { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.HFP; - } else { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.NONE; - } - } - break; - case ApmConst.AudioFeatures.MEDIA_AUDIO: - if(mAudioProfile == ApmConst.AudioProfiles.A2DP) { - if((mConnectedProfileBitMap & ApmConst.AudioProfiles.TMAP_MEDIA) > 0) { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.TMAP_MEDIA; - } else if ((mConnectedProfileBitMap & ApmConst.AudioProfiles.BAP_MEDIA) > 0) { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.BAP_MEDIA; - } else { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.NONE; - } - } else if (mAudioProfile == ApmConst.AudioProfiles.TMAP_MEDIA - || mAudioProfile == ApmConst.AudioProfiles.BAP_MEDIA) { - if((mConnectedProfileBitMap & ApmConst.AudioProfiles.A2DP) > 0) { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.A2DP; - } else { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.NONE; - } - } - break; - case ApmConst.AudioFeatures.CALL_CONTROL: - if(mAudioProfile == ApmConst.AudioProfiles.HFP) { - if((mConnectedProfileBitMap & ApmConst.AudioProfiles.CCP) > 0) { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.CCP; - } else { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.NONE; - } - } else if (mAudioProfile == ApmConst.AudioProfiles.CCP) { - if((mConnectedProfileBitMap & ApmConst.AudioProfiles.HFP) > 0) { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.HFP; - } else { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.NONE; - } - } - break; - case ApmConst.AudioFeatures.MEDIA_CONTROL: - if(mAudioProfile == ApmConst.AudioProfiles.AVRCP) { - if((mConnectedProfileBitMap & ApmConst.AudioProfiles.MCP) > 0) { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.MCP; - } else { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.NONE; - } - } else if (mAudioProfile == ApmConst.AudioProfiles.MCP) { - if((mConnectedProfileBitMap & ApmConst.AudioProfiles.AVRCP) > 0) { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.AVRCP; - } else { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.NONE; - } - } - break; - case ApmConst.AudioFeatures.MEDIA_VOLUME_CONTROL: - if(mAudioProfile == ApmConst.AudioProfiles.AVRCP) { - if((mConnectedProfileBitMap & ApmConst.AudioProfiles.VCP) > 0) { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.VCP; - } else { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.NONE; - } - } else if (mAudioProfile == ApmConst.AudioProfiles.VCP) { - if((mConnectedProfileBitMap & ApmConst.AudioProfiles.AVRCP) > 0) { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.AVRCP; - } else { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.NONE; - } - } - break; - case ApmConst.AudioFeatures.CALL_VOLUME_CONTROL: - if(mAudioProfile == ApmConst.AudioProfiles.HFP) { - if((mConnectedProfileBitMap & ApmConst.AudioProfiles.VCP) > 0) { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.VCP; - } else { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.NONE; - } - } else if (mAudioProfile == ApmConst.AudioProfiles.VCP) { - if((mConnectedProfileBitMap & ApmConst.AudioProfiles.HFP) > 0) { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.HFP; - } else { - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.NONE; - } - } - break; - default: - mAciveProfileArray[mAudioFeature] = ApmConst.AudioProfiles.NONE; - } - } - } - - mActiveProfileMap.put(device, mAciveProfileArray); - Log.d(LOGTAG, "profileConnectionUpdate: supported Profiles for the device " + device - + " val " + Integer.toHexString(mSupportedProfileBitMap)); - Log.d(LOGTAG, "profileConnectionUpdate: connected Profiles for the device " + device - + " val " + Integer.toHexString(mConnectedProfileBitMap)); - - mConnectedProfileMap.put(device, mConnectedProfileBitMap); - mSupportedProfileMap.put(device, mSupportedProfileBitMap); - } - } - - public boolean isProfileConnected(BluetoothDevice device, Integer mAudioProfile) { - if (device == null) return false; - int mConnectedProfileBitMap = mConnectedProfileMap.get(device); - Log.d(LOGTAG, "isProfileConnected: device: " + device - + " mAudioProfile: " + mAudioProfile + " mConnectedProfileMap: " + mConnectedProfileBitMap); - - return ((mConnectedProfileBitMap & mAudioProfile) == mAudioProfile); - } - - public void setActiveProfile(BluetoothDevice device, Integer mAudioFeature, Integer mAudioProfile) { - int [] mAciveProfileArray; - Log.d(LOGTAG, "setActiveProfile: device : " + device + " AudioProfile " - + mAudioProfile + " AudioFeature " + mAudioFeature); - synchronized (mLock) { - if(!mActiveProfileMap.containsKey(device)) { - Log.d(LOGTAG, "setActiveProfile: intialize the active profile map for the device " - + device); - mAciveProfileArray = new int[ApmConst.AudioFeatures.MAX_AUDIO_FEATURES]; - Arrays.fill(mAciveProfileArray, ApmConst.AudioProfiles.NONE); - mActiveProfileMap.put(device, mAciveProfileArray); - } else { - mAciveProfileArray = mActiveProfileMap.get(device); - } - mAciveProfileArray[mAudioFeature] = mAudioProfile; - mActiveProfileMap.put(device, mAciveProfileArray); - } - } - - static int getLeMediaProfiles() { - return LeMediaProfiles; - } - - static int getLeCallProfiles() { - return LeCallProfiles; - } - - public synchronized void handleDeviceShutdown() { - Log.d(LOGTAG, "handleDeviceShutdown: started"); - - //store the supported profiles for the bonded devices - SharedPreferences.Editor pref = getSupportedProfileMap().edit(); - for (BluetoothDevice mBluetoothDevice : mSupportedProfileMap.keySet()) { - int mSupportedProfilesVal = mSupportedProfileMap.get(mBluetoothDevice); - Log.d(LOGTAG, "cleanup: supported Profiles for the device " + mBluetoothDevice - + " val = " + Integer.toHexString(mSupportedProfilesVal)); - if(mBluetoothDevice.getBondState() == BluetoothDevice.BOND_BONDED) { - pref.putInt(mBluetoothDevice.getAddress(), mSupportedProfilesVal); - } - } - pref.apply(); - mSupportedProfileMap.clear(); - mActiveProfileMap.clear(); - mConnectedProfileMap.clear(); - - Log.d(LOGTAG, "handleDeviceShutdown: Done"); - } - - public synchronized void cleanup () { - if(DPMSingleInstance == null) { - Log.w(LOGTAG, "cleanup called without initialization, Returning"); - return; - } - - Log.d(LOGTAG, "cleanup: started"); - - //store the supported profiles for the bonded devices - SharedPreferences.Editor pref = getSupportedProfileMap().edit(); - for (BluetoothDevice mBluetoothDevice : mSupportedProfileMap.keySet()) { - int mSupportedProfilesVal = mSupportedProfileMap.get(mBluetoothDevice); - Log.d(LOGTAG, "cleanup: supported Profiles for the device " + mBluetoothDevice - + " val = " + Integer.toHexString(mSupportedProfilesVal)); - if(mBluetoothDevice.getBondState() == BluetoothDevice.BOND_BONDED) { - pref.putInt(mBluetoothDevice.getAddress(), mSupportedProfilesVal); - } - } - pref.apply(); - mSupportedProfileMap.clear(); - mActiveProfileMap.clear(); - mConnectedProfileMap.clear(); - DPMSingleInstance = null; - mContext.unregisterReceiver(mDeviceProfileMapReceiver); - - Log.d(LOGTAG, "cleanup: Done"); - } -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/MediaAudio.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/MediaAudio.java deleted file mode 100644 index 057c0ebdf73c3ca73fda5bf6755c739031ed468a..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/MediaAudio.java +++ /dev/null @@ -1,1204 +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. - * - ******************************************************************************/ - - -package com.android.bluetooth.apm; - -import static android.Manifest.permission.BLUETOOTH_CONNECT; - -import android.bluetooth.BluetoothA2dp; -import android.bluetooth.BluetoothCodecConfig; -import android.bluetooth.BluetoothCodecStatus; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; -import com.android.bluetooth.Utils; -import android.bluetooth.BluetoothUuid; -import android.bluetooth.IBluetoothA2dp; - -import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.btservice.ActiveDeviceManager; -import com.android.bluetooth.btservice.ProfileService; -import com.android.bluetooth.a2dp.A2dpService; -import com.android.bluetooth.apm.ActiveDeviceManagerService; -import com.android.bluetooth.apm.ApmConst; -import com.android.bluetooth.broadcast.BroadcastService; -import com.android.bluetooth.acm.AcmService; -import android.content.Context; -import android.content.Intent; -import android.content.BroadcastReceiver; -import android.content.IntentFilter; -import android.media.AudioManager; -import android.util.Log; -import android.util.StatsLog; -import com.android.bluetooth.hfp.HeadsetService; - -import java.util.ArrayList; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import android.os.Handler; -import android.os.Message; -import android.os.SystemClock; -import android.os.SystemProperties; - -public class MediaAudio { - private static MediaAudio sMediaAudio; - private AdapterService mAdapterService; -// private BapBroadcastService mBapBroadcastService; - private ActiveDeviceManagerService mActiveDeviceManager; - private Context mContext; - BapBroadcastManager mBapBroadcastManager; - Map mMediaDevices; - - final ArrayList supported_codec = new ArrayList( List.of( - "LC3" - )); - - private BroadcastReceiver mCodecConfigReceiver; - private BroadcastReceiver mQosConfigReceiver; - public static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH; - public static final String BLUETOOTH_PRIVILEGED = - android.Manifest.permission.BLUETOOTH_PRIVILEGED; - public static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; - public static final String ACTION_UPDATE_CODEC_CONFIG = - "qti.intent.bluetooth.action.UPDATE_CODEC_CONFIG"; - public static final String CODEC_ID = - "qti.bluetooth.extra.CODEC_ID"; - public static final String CODEC_CONFIG = - "qti.bluetooth.extra.CODEC_CONFIG"; - public static final String CHANNEL_MODE = - "qti.bluetooth.extra.CHANNEL_MODE"; - public static final String ACTION_UPDATE_QOS_CONFIG = - "qti.intent.bluetooth.action.UPDATE_QOS_CONFIG"; - public static final String QOS_CONFIG = - "qti.bluetooth.extra.QOS_CONFIG"; - private static final int MAX_DEVICES = 200; - public static final String TAG = "APM: MediaAudio"; - public static final boolean DBG = true; - - private static final long AUDIO_RECORDING_MASK = 0x00030000; - private static final long AUDIO_RECORDING_OFF = 0x00010000; - private static final long AUDIO_RECORDING_ON = 0x00020000; - - private static final long GAMING_OFF = 0x00001000; - private static final long GAMING_ON = 0x00002000; - private static final long GAMING_MODE_MASK = 0x00007000; - - private static boolean mIsRecordingEnabled; - - private AudioManager mAudioManager; - - private MediaAudio(Context context) { - Log.i(TAG, "initialization"); - - mContext = context; - mMediaDevices = new ConcurrentHashMap(); - mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); - Objects.requireNonNull(mAudioManager, - "AudioManager cannot be null when A2dpService starts"); - - mAdapterService = AdapterService.getAdapterService(); - mActiveDeviceManager = ActiveDeviceManagerService.get(); - - mBapBroadcastManager = new BapBroadcastManager(); - - IntentFilter codecFilter = new IntentFilter(); - codecFilter.addAction(ACTION_UPDATE_CODEC_CONFIG); - mCodecConfigReceiver = new LeCodecConfig(); - context.registerReceiver(mCodecConfigReceiver, codecFilter); - - IntentFilter qosFilter = new IntentFilter(); - qosFilter.addAction(ACTION_UPDATE_QOS_CONFIG); - mQosConfigReceiver = new QosConfigReceiver(); - context.registerReceiver(mQosConfigReceiver, qosFilter); - - mIsRecordingEnabled = - SystemProperties.getBoolean("persist.vendor.service.bt.recording_supported", false); - - //2 Setup Codec Config here - } - - public static MediaAudio init(Context context) { - if(sMediaAudio == null) { - sMediaAudio = new MediaAudio(context); - MediaAudioIntf.init(sMediaAudio); - } - return sMediaAudio; - } - - public static MediaAudio get() { - return sMediaAudio; - } - - public boolean connect(BluetoothDevice device) { - return connect (device, false, false); - } - - public boolean connect(BluetoothDevice device, Boolean allProfile) { - return connect (device, allProfile, false); - } - - public boolean autoConnect(BluetoothDevice device) { - Log.e(TAG, "autoConnect: " + device); - return connect(device, false, true); - } - - private boolean connect(BluetoothDevice device, boolean allProfile, boolean autoConnect) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); - - Log.e(TAG, "connect: " + device + " allProfile: " + allProfile + - " autoConnect: " + autoConnect); - if (getConnectionPolicy(device) == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { - Log.e(TAG, "Cannot connect to " + device + " : CONNECTION_POLICY_FORBIDDEN"); - return false; - } - - DeviceProfileMap dMap = DeviceProfileMap.getDeviceProfileMapInstance(); - if (dMap == null) - return false; - - int peer_supported_profiles = dMap.getAllSupportedProfile(device); - boolean is_peer_support_recording = - ((peer_supported_profiles & ApmConst.AudioProfiles.BAP_RECORDING) != 0); - int profileID = dMap.getSupportedProfile(device, ApmConst.AudioFeatures.MEDIA_AUDIO); - if (profileID == ApmConst.AudioProfiles.NONE) { - Log.e(TAG, "Can Not connect to " + device + ". Device does not support media service."); - return false; - } - - MediaDevice mMediaDevice = mMediaDevices.get(device.getAddress()); - if(mMediaDevice == null) { - if(mMediaDevices.size() >= MAX_DEVICES) - return false; - mMediaDevice = new MediaDevice(device, profileID); - mMediaDevices.put(device.getAddress(), mMediaDevice); - } else if(mMediaDevice.deviceConnStatus != BluetoothProfile.STATE_DISCONNECTED) { - Log.i(TAG, "Device already connected"); - return false; - } - - if((ApmConst.AudioProfiles.A2DP & profileID) == ApmConst.AudioProfiles.A2DP) { - A2dpService service = A2dpService.getA2dpService(); - if(service != null) { - service.connectA2dp(device); - } - } - - BluetoothDevice groupDevice = device; - StreamAudioService mStreamService = StreamAudioService.getStreamAudioService(); - - if(mStreamService != null && - (ApmConst.AudioProfiles.BAP_MEDIA & profileID) == ApmConst.AudioProfiles.BAP_MEDIA) { - int defaultMediaProfile = ApmConst.AudioProfiles.BAP_MEDIA; - - /* handle common conect of call and media audio */ - if(autoConnect) { - groupDevice = mStreamService.getDeviceGroup(device); - Log.i(TAG, "Auto Connect Request. Connecting group: " + groupDevice); - } - - /*int defaultMusicProfile = dMap.getProfile(device, ApmConst.AudioFeatures.MEDIA_AUDIO); - if((ApmConst.AudioProfiles.A2DP & defaultMusicProfile) == ApmConst.AudioProfiles.A2DP) { - Log.i(TAG, "A2DP is default profile for Music, configure BAP for Gaming"); - defaultMediaProfile = ApmConst.AudioProfiles.BAP_GCP; - }*/ - - if(mIsRecordingEnabled) { - Log.i(TAG, "Add Recording profile to LE connect request"); - defaultMediaProfile = defaultMediaProfile | ApmConst.AudioProfiles.BAP_RECORDING; - } - - if(allProfile) { - int callProfileID = dMap.getSupportedProfile(device, ApmConst.AudioFeatures.CALL_AUDIO); - if((callProfileID & ApmConst.AudioProfiles.BAP_CALL) == ApmConst.AudioProfiles.BAP_CALL) { - Log.i(TAG, "Add BAP_CALL to LE connect request"); - mStreamService.connectLeStream(groupDevice, - defaultMediaProfile | ApmConst.AudioProfiles.BAP_CALL); - } else { - mStreamService.connectLeStream(groupDevice, defaultMediaProfile); - } - } else { - mStreamService.connectLeStream(groupDevice, defaultMediaProfile); - } - } - return true; - } - - public boolean disconnect(BluetoothDevice device) { - return disconnect(device, false); - } - - public boolean disconnect(BluetoothDevice device, Boolean allProfile) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); - Log.i(TAG, "Disconnect: " + device); - MediaDevice mMediaDevice = null; - - if(device == null) - return false; - - mMediaDevice = mMediaDevices.get(device.getAddress()); - if(mMediaDevice == null) { - Log.e(TAG, "Ignore: Device " + device + " not present in list"); - return false; - } - - if (mMediaDevice.profileConnStatus[MediaDevice.A2DP_STREAM] != BluetoothProfile.STATE_DISCONNECTED) { - A2dpService service = A2dpService.getA2dpService(); - if(service != null) { - service.disconnectA2dp(device); - } - } - if (mMediaDevice.profileConnStatus[MediaDevice.LE_STREAM] != BluetoothProfile.STATE_DISCONNECTED) { - StreamAudioService service = StreamAudioService.getStreamAudioService(); - if(service != null) { - DeviceProfileMap dMap = DeviceProfileMap.getDeviceProfileMapInstance(); - if (!dMap.isProfileConnected(device, ApmConst.AudioProfiles.BAP_CALL)) { - Log.d(TAG,"BAP_CALL not connected"); - allProfile = false; - } - service.disconnectLeStream(device, allProfile, true); - } - } - - return true; - } - - public List getConnectedDevices() { - Log.i(TAG, "getConnectedDevices: "); - if(mMediaDevices.size() == 0) { - return new ArrayList<>(0); - } - - List connectedDevices = new ArrayList<>(); - for(MediaDevice mMediaDevice : mMediaDevices.values()) { - if(mMediaDevice.deviceConnStatus == BluetoothProfile.STATE_CONNECTED) { - connectedDevices.add(mMediaDevice.mDevice); - } - } - return connectedDevices; - } - - public List getDevicesMatchingConnectionStates(Integer[] states) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - - Log.i(TAG, "getDevicesMatchingConnectionStates: "); - List devices = new ArrayList<>(); - if (states == null) { - return devices; - } - - BluetoothDevice [] bondedDevices = null; - bondedDevices = mAdapterService.getBondedDevices(); - if(bondedDevices == null) { - return devices; - } - - for (BluetoothDevice device : bondedDevices) { - MediaDevice mMediaDevice; - int state = BluetoothProfile.STATE_DISCONNECTED; - - DeviceProfileMap dMap = DeviceProfileMap.getDeviceProfileMapInstance(); - if(dMap == null) { - return new ArrayList<>(0); - } - if(dMap.getProfile(device, ApmConst.AudioFeatures.MEDIA_AUDIO) == ApmConst.AudioProfiles.NONE) { - continue; - } - - mMediaDevice = mMediaDevices.get(device.getAddress()); - if(mMediaDevice != null) - state = mMediaDevice.deviceConnStatus; - - for(int s: states) { - if(s == state) { - devices.add(device); - break; - } - } - } - return devices; - } - - public int getConnectionState(BluetoothDevice device) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - - if(device == null) - return BluetoothProfile.STATE_DISCONNECTED; - - MediaDevice mMediaDevice = mMediaDevices.get(device.getAddress()); - if(mMediaDevice != null) - return mMediaDevice.deviceConnStatus; - - return BluetoothProfile.STATE_DISCONNECTED; - } - - public int getPriority(BluetoothDevice device) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); - if(mAdapterService != null) { - return mAdapterService.getDatabase() - .getProfileConnectionPolicy(device, BluetoothProfile.A2DP); - } - return BluetoothProfile.PRIORITY_UNDEFINED; - } - - public boolean isA2dpPlaying(BluetoothDevice device) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); - - if(device == null) - return false; - - MediaDevice mMediaDevice = mMediaDevices.get(device.getAddress()); - if(mMediaDevice != null) { - Log.i(TAG, "isA2dpPlaying: " + mMediaDevice.streamStatus); - return (mMediaDevice.streamStatus == BluetoothA2dp.STATE_PLAYING); - } - - return false; - } - - public BluetoothCodecStatus getCodecStatus(BluetoothDevice device) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); - - Log.i(TAG, "getCodecStatus: for device: " + device); - if(device == null) - return null; - - if (mBapBroadcastManager.isBapBroadcastActive()) { - return mBapBroadcastManager.getCodecStatus(); - } - - ActiveDeviceManagerService mActiveDeviceManager = ActiveDeviceManagerService.get(); - int profile = mActiveDeviceManager.getActiveProfile(ApmConst.AudioFeatures.MEDIA_AUDIO); - if(profile != ApmConst.AudioProfiles.NONE && profile != ApmConst.AudioProfiles.A2DP) { - StreamAudioService service = StreamAudioService.getStreamAudioService(); - if(service != null) { - device = service.getDeviceGroup(device); - } - } - - MediaDevice mMediaDevice = mMediaDevices.get(device.getAddress()); - Log.i(TAG, "getCodecStatus: for mMediaDevice: " + mMediaDevice); - if(mMediaDevice == null) - return null; - - Log.i(TAG, "getCodecStatus: " + mMediaDevice.mCodecStatus); - return mMediaDevice.mCodecStatus; - } - - public void setCodecConfigPreference(BluetoothDevice mDevice, - BluetoothCodecConfig codecConfig) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - BluetoothDevice device = mDevice; - - Log.i(TAG, "setCodecConfigPreference: " + codecConfig); - if(device == null) { - if(mActiveDeviceManager != null) { - device = mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.MEDIA_AUDIO); - } - } - if(device == null) - return; - - if (codecConfig == null) { - Log.e(TAG, "setCodecConfigPreference: Codec config can't be null"); - return; - } - long cs4 = codecConfig.getCodecSpecific4(); - - if (mActiveDeviceManager.getActiveProfile(ApmConst.AudioFeatures.MEDIA_AUDIO) == - ApmConst.AudioProfiles.BROADCAST_LE) { - AcmService mAcmService = AcmService.getAcmService(); - BluetoothDevice mPrevDevice = mActiveDeviceManager.getQueuedDevice(ApmConst.AudioFeatures.MEDIA_AUDIO); - if (mPrevDevice != null && mAcmService != null) { - if ((cs4 & AUDIO_RECORDING_MASK) == AUDIO_RECORDING_ON) { - if (mAcmService.getConnectionState(mPrevDevice) == BluetoothProfile.STATE_CONNECTED) { - device = mPrevDevice; - Log.d(TAG,"Recording request, switch device to " + device); - } else { - Log.d(TAG,"Not DUMO device, ignore recording request"); - return; - } - } - } else if ((cs4 & GAMING_MODE_MASK) == GAMING_ON) { - Log.d(TAG, "Ignore gaming mode request when broadcast is active"); - return; - } - } - - DeviceProfileMap dMap = DeviceProfileMap.getDeviceProfileMapInstance(); - int supported_prfiles = dMap.getAllSupportedProfile(device); - - MediaDevice mMediaDevice = mMediaDevices.get(device.getAddress()); - boolean peer_supports_recording = - ((supported_prfiles & ApmConst.AudioProfiles.BAP_RECORDING) != 0); - - int profileIndex = mMediaDevice.getProfileIndex(ApmConst.AudioProfiles.BAP_MEDIA); - int profileIndexA2dp = mMediaDevice.getProfileIndex(ApmConst.AudioProfiles.A2DP); - boolean is_peer_connected_for_recording = - (mMediaDevice.profileConnStatus[profileIndex] == - BluetoothProfile.STATE_CONNECTED); - boolean is_peer_connected_for_a2dp = (mMediaDevice.profileConnStatus[profileIndexA2dp] == - BluetoothProfile.STATE_CONNECTED); - Log.i(TAG, "is_peer_connected_for_recording: " + is_peer_connected_for_recording + - ", is_peer_connected_for_a2dp: " + is_peer_connected_for_a2dp); - CallAudio mCallAudio = CallAudio.get(); - boolean isInCall = mCallAudio != null && mCallAudio.isVoiceOrCallActive(); - // TODO : check the FM related rx activity - if (mActiveDeviceManager != null && - peer_supports_recording && mIsRecordingEnabled && - is_peer_connected_for_recording && is_peer_connected_for_a2dp) { - if ((cs4 & AUDIO_RECORDING_MASK) == AUDIO_RECORDING_ON) { - if(!isInCall && - !mActiveDeviceManager.isRecordingActive(device)) { - mActiveDeviceManager.enableRecording(device); - } - - } else if ((cs4 & AUDIO_RECORDING_MASK) == AUDIO_RECORDING_OFF) { - if(mActiveDeviceManager.isRecordingActive(device)) { - mActiveDeviceManager.disableRecording(device); - } - } - } - - boolean isBapConnected = (mMediaDevice.profileConnStatus[mMediaDevice.LE_STREAM] - == BluetoothProfile.STATE_CONNECTED); - - if(isBapConnected) { - long mGamingStatus = (cs4 & GAMING_MODE_MASK); - if((mGamingStatus & GAMING_ON) > 0) { - Log.w(TAG, "Turning On Gaming Mode"); - mActiveDeviceManager.enableGaming(device); - return; - } else if((mGamingStatus & GAMING_OFF) > 0) { - Log.w(TAG, "Turning Off Gaming Mode"); - mActiveDeviceManager.disableGaming(device); - return; - } - } - - int profileID = dMap.getProfile(device, ApmConst.AudioFeatures.MEDIA_AUDIO); - - if(ApmConst.AudioProfiles.A2DP == profileID) { - if(codecConfig.getCodecType() == - BluetoothCodecConfig.SOURCE_CODEC_TYPE_LC3) { - return; - } - A2dpService service = A2dpService.getA2dpService(); - if(service != null) { - service.setCodecConfigPreferenceA2dp(device, codecConfig); - return; - } - }/* else if(ApmConst.AudioProfiles.BAP == profileID) { // once implemented - LeStreamService service = LeStreamService.getLeStreamService(); - if(service != null) { - service.setCodecConfigPreferenceLeStream(device, codecConfig); - return; - } - }*/ - - } - - public void enableOptionalCodecs(BluetoothDevice device) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - Log.i(TAG, "enableOptionalCodecs: "); - - BluetoothCodecStatus mCodecStatus = null; - - if (device == null) { - if(mActiveDeviceManager != null) { - device = mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.MEDIA_AUDIO); - } - } - if (device == null) { - Log.e(TAG, "enableOptionalCodecs: Invalid device"); - return; - } - - if (getSupportsOptionalCodecs(device) != BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED) { - Log.e(TAG, "enableOptionalCodecs: No optional codecs"); - return; - } - - MediaDevice mMediaDevice = mMediaDevices.get(device.getAddress()); - - A2dpService service = A2dpService.getA2dpService(); - if(service != null) { - int profileIndex = mMediaDevice.getProfileIndex(ApmConst.AudioProfiles.A2DP); - mCodecStatus = mMediaDevice.mProfileCodecStatus[profileIndex]; - if(mCodecStatus != null) { - service.enableOptionalCodecsA2dp(device, mCodecStatus.getCodecConfig()); - } - } - // 2 Should implement common codec handling when - //vendor codecs is introduced in LE Audio - } - - public void disableOptionalCodecs(BluetoothDevice device) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - Log.i(TAG, "disableOptionalCodecs: "); - BluetoothCodecStatus mCodecStatus = null; - if (device == null) { - if(mActiveDeviceManager != null) { - device = mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.MEDIA_AUDIO); - } - } - if (device == null) { - Log.e(TAG, "disableOptionalCodecs: Invalid device"); - return; - } - - if (getSupportsOptionalCodecs(device) != BluetoothA2dp.OPTIONAL_CODECS_SUPPORTED) { - Log.e(TAG, "disableOptionalCodecs: No optional codecs"); - return; - } - - MediaDevice mMediaDevice = mMediaDevices.get(device.getAddress()); - - A2dpService service = A2dpService.getA2dpService(); - if(service != null) { - int profileIndex = mMediaDevice.getProfileIndex(ApmConst.AudioProfiles.A2DP); - mCodecStatus = mMediaDevice.mProfileCodecStatus[profileIndex]; - if(mCodecStatus != null) { - service.disableOptionalCodecsA2dp(device, mCodecStatus.getCodecConfig()); - } - } - // 2 Should implement common codec handling when - //vendor codecs is introduced in LE Audio - } - - public int getSupportsOptionalCodecs(BluetoothDevice device) { - if(mAdapterService != null) - return mAdapterService.getDatabase().getA2dpSupportsOptionalCodecs(device); - return BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED; - } - - public int supportsOptionalCodecs(BluetoothDevice device) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); - if(mAdapterService.isTwsPlusDevice(device)) { - Log.w(TAG, "Disable optional codec support for TWS+ device"); - return BluetoothA2dp.OPTIONAL_CODECS_NOT_SUPPORTED; - } - return getSupportsOptionalCodecs(device); - } - - public int getOptionalCodecsEnabled(BluetoothDevice device) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); - if(mAdapterService != null) - return mAdapterService.getDatabase().getA2dpOptionalCodecsEnabled(device); - return BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN; - } - - public void setOptionalCodecsEnabled(BluetoothDevice device, Integer value) { - Log.i(TAG, "setOptionalCodecsEnabled: " + value); - mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); - if (value != BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN - && value != BluetoothA2dp.OPTIONAL_CODECS_PREF_DISABLED - && value != BluetoothA2dp.OPTIONAL_CODECS_PREF_ENABLED) { - Log.w(TAG, "Unexpected value passed to setOptionalCodecsEnabled:" + value); - return; - } - - if(mAdapterService != null) - mAdapterService.getDatabase().setA2dpOptionalCodecsEnabled(device, value); - } - - public int getConnectionPolicy(BluetoothDevice device) { - if(mAdapterService != null) - return mAdapterService.getDatabase() - .getProfileConnectionPolicy(device, BluetoothProfile.A2DP); - return BluetoothProfile.CONNECTION_POLICY_UNKNOWN; - } - - public boolean setConnectionPolicy(BluetoothDevice device, Integer connectionPolicy) { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, - "Need BLUETOOTH_PRIVILEGED permission"); - if (DBG) { - Log.d(TAG, "Saved connectionPolicy " + device + " = " + connectionPolicy); - } - boolean setSuccessfully; - setSuccessfully = mAdapterService.getDatabase() - .setProfileConnectionPolicy(device, BluetoothProfile.A2DP, connectionPolicy); - - if (setSuccessfully && connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - connect(device); - } else if (setSuccessfully - && connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { - disconnect(device); - } - return setSuccessfully; - } - - public boolean setSilenceMode(BluetoothDevice device, Boolean silence) { - if (DBG) { - Log.d(TAG, "setSilenceMode(" + device + "): " + silence); - } - BluetoothDevice mActiveDevice = mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.MEDIA_AUDIO); - if (silence && Objects.equals(mActiveDevice, device)) { - mActiveDeviceManager.removeActiveDevice(ApmConst.AudioFeatures.MEDIA_AUDIO, true); - } else if (!silence && null == - mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.MEDIA_AUDIO)) { - // Set the device as the active device if currently no active device. - mActiveDeviceManager.setActiveDevice(device, ApmConst.AudioFeatures.MEDIA_AUDIO, false); - } - return true; - } - - public void onConnStateChange(BluetoothDevice device, Integer state, Integer profile) { - Log.d(TAG, "onConnStateChange: profile: " + profile + " state: " + state + " for device " + device); - if(device == null) - return; - MediaDevice mMediaDevice = mMediaDevices.get(device.getAddress()); - - if(mMediaDevice == null) { - if(state == BluetoothProfile.STATE_DISCONNECTED) - return; - if(mMediaDevices.size() >= MAX_DEVICES) { - return; - } - mMediaDevice = new MediaDevice(device, profile, state); - mMediaDevices.put(device.getAddress(), mMediaDevice); - broadcastConnStateChange(device, BluetoothProfile.STATE_DISCONNECTED, state); - return; - } - - int profileIndex = mMediaDevice.getProfileIndex(profile); - int prevState = mMediaDevice.deviceConnStatus; - if(mMediaDevice.profileConnStatus[profileIndex] == state) { - Log.w(TAG, "Profile already in state: " + state + ". Return"); - return; - } - mMediaDevice.profileConnStatus[profileIndex] = state; - - if(state == BluetoothProfile.STATE_CONNECTED) { - DeviceProfileMap dMap = DeviceProfileMap.getDeviceProfileMapInstance(); - dMap.profileConnectionUpdate(device, ApmConst.AudioFeatures.MEDIA_AUDIO, profile, true); - refreshCurrentCodec(device); - } else if(state == BluetoothProfile.STATE_DISCONNECTED) { - DeviceProfileMap dMap = DeviceProfileMap.getDeviceProfileMapInstance(); - dMap.profileConnectionUpdate(device, ApmConst.AudioFeatures.MEDIA_AUDIO, profile, false); - } - - int otherProfileConnectionState = mMediaDevice.profileConnStatus[(profileIndex+1)%2]; - Log.w(TAG, " otherProfileConnectionState: " + otherProfileConnectionState); - - switch(otherProfileConnectionState) { - /*Send Broadcast based on state of other profile*/ - case BluetoothProfile.STATE_DISCONNECTED: - broadcastConnStateChange(device, prevState, state); - mMediaDevice.deviceConnStatus = state; - break; - case BluetoothProfile.STATE_CONNECTING: - if(state == BluetoothProfile.STATE_CONNECTED) { - broadcastConnStateChange(device, prevState, state); - mMediaDevice.deviceConnStatus = state; - } - break; - case BluetoothProfile.STATE_DISCONNECTING: - if(state == BluetoothProfile.STATE_CONNECTING || - state == BluetoothProfile.STATE_CONNECTED) { - broadcastConnStateChange(device, prevState, state); - mMediaDevice.deviceConnStatus = state; - } - break; - case BluetoothProfile.STATE_CONNECTED: - ActiveDeviceManagerService mActiveDeviceManager = - ActiveDeviceManagerService.get(); - if(mActiveDeviceManager == null) { - break; - } - - BluetoothDevice mActiveDevice = mActiveDeviceManager - .getActiveDevice(ApmConst.AudioFeatures.MEDIA_AUDIO); - - if((state == BluetoothProfile.STATE_CONNECTED) || - (state == BluetoothProfile.STATE_DISCONNECTED && - device.equals(mActiveDevice))) { - Log.w(TAG, "onConnStateChange: Trigger Media handoff for Device: " + device); - mActiveDeviceManager.setActiveDevice(device, - ApmConst.AudioFeatures.MEDIA_AUDIO); - } - break; - } - - if (profileIndex == mMediaDevice.LE_STREAM && - state == BluetoothProfile.STATE_DISCONNECTED) { - mMediaDevice.mProfileCodecStatus[profileIndex] = null; - } - } - - public void onConnStateChange(BluetoothDevice device, int state, int profile, boolean isFirstMember) { - Log.w(TAG, "onConnStateChange: state:" + state + " for device " + device + " new group: " + isFirstMember); - if((state == BluetoothProfile.STATE_CONNECTED || state == BluetoothProfile.STATE_CONNECTING) - && isFirstMember) { - StreamAudioService mStreamAudioService = StreamAudioService.getStreamAudioService(); - BluetoothDevice groupDevice = mStreamAudioService.getDeviceGroup(device); - if(groupDevice != null) { - MediaDevice mMediaDevice = mMediaDevices.get(groupDevice.getAddress()); - if(mMediaDevice == null) { - mMediaDevice = new MediaDevice(groupDevice, profile, BluetoothProfile.STATE_CONNECTED); - mMediaDevices.put(groupDevice.getAddress(), mMediaDevice); - } else { - int profileIndex = mMediaDevice.getProfileIndex(profile); - mMediaDevice.profileConnStatus[profileIndex] = BluetoothProfile.STATE_CONNECTED; - mMediaDevice.deviceConnStatus = state; - } - } - } else if(isFirstMember && (state == BluetoothProfile.STATE_DISCONNECTING || - state == BluetoothProfile.STATE_DISCONNECTED)) { - StreamAudioService mStreamAudioService = StreamAudioService.getStreamAudioService(); - BluetoothDevice groupDevice = mStreamAudioService.getDeviceGroup(device); - MediaDevice mMediaDevice = mMediaDevices.get(groupDevice.getAddress()); - int prevState = BluetoothProfile.STATE_CONNECTED; - Log.w(TAG, "onConnStateChange: mMediaDevice: " + mMediaDevice); - if(mMediaDevice != null) { - prevState = mMediaDevice.deviceConnStatus; - int profileIndex = mMediaDevice.getProfileIndex(profile); - mMediaDevice.profileConnStatus[profileIndex] = state; - mMediaDevice.deviceConnStatus = state; - Log.w(TAG, "onConnStateChange: device: " + groupDevice + " state = " + mMediaDevice.deviceConnStatus); - } - ActiveDeviceManager mDeviceManager = AdapterService.getAdapterService().getActiveDeviceManager(); - mDeviceManager.onDeviceConnStateChange(groupDevice, state, prevState, - ApmConst.AudioFeatures.MEDIA_AUDIO); - } - onConnStateChange(device, state, profile); - } - - public void onStreamStateChange(BluetoothDevice device, Integer streamStatus) { - int prevStatus; - if(device == null) - return; - MediaDevice mMediaDevice = mMediaDevices.get(device.getAddress()); - if(mMediaDevice == null) { - return; - } - - if(mMediaDevice.streamStatus == streamStatus) - return; - - prevStatus = mMediaDevice.streamStatus; - mMediaDevice.streamStatus = streamStatus; - Log.d(TAG, "onStreamStateChange update to volume manager"); - VolumeManager mVolumeManager = VolumeManager.get(); - mVolumeManager.updateStreamState(device, streamStatus, ApmConst.AudioFeatures.MEDIA_AUDIO); - broadcastStreamState(device, prevStatus, streamStatus); - } - - protected BluetoothCodecStatus convergeCodecConfig(MediaDevice mMediaDevice) { - BluetoothCodecStatus A2dpCodecStatus = mMediaDevice.mProfileCodecStatus[MediaDevice.A2DP_STREAM]; - BluetoothCodecStatus BapCodecStatus = mMediaDevice.mProfileCodecStatus[MediaDevice.LE_STREAM]; - BluetoothCodecStatus mCodecStatus = null; - - if(A2dpCodecStatus == null || - mMediaDevice.profileConnStatus[MediaDevice.A2DP_STREAM] != - BluetoothProfile.STATE_CONNECTED) { - return BapCodecStatus; - } - - if(BapCodecStatus == null || - mMediaDevice.profileConnStatus[MediaDevice.LE_STREAM] != - BluetoothProfile.STATE_CONNECTED) { - return A2dpCodecStatus; - } - - ActiveDeviceManagerService mActiveDeviceManager = ActiveDeviceManagerService.get(); - int mActiveProfile = mActiveDeviceManager.getActiveProfile(ApmConst.AudioFeatures.MEDIA_AUDIO); - int mActiveProfileIndex = mMediaDevice.getProfileIndex(mActiveProfile); - BluetoothCodecConfig mCodecConfig = mMediaDevice.mProfileCodecStatus[mActiveProfileIndex].getCodecConfig(); - - Log.d(TAG, "convergeCodecConfig: mActiveProfile: " - + mActiveProfile + ", mActiveProfileIndex: " + mActiveProfileIndex); - - BluetoothCodecConfig[] mCodecsLocalCapabilities = new BluetoothCodecConfig[ - A2dpCodecStatus.getCodecsLocalCapabilities().length + - BapCodecStatus.getCodecsLocalCapabilities().length]; - System.arraycopy(A2dpCodecStatus.getCodecsLocalCapabilities(), 0, mCodecsLocalCapabilities, 0, - A2dpCodecStatus.getCodecsLocalCapabilities().length); - System.arraycopy(BapCodecStatus.getCodecsLocalCapabilities(), 0, mCodecsLocalCapabilities, - A2dpCodecStatus.getCodecsLocalCapabilities().length, - BapCodecStatus.getCodecsLocalCapabilities().length); - - BluetoothCodecConfig[] mCodecsSelectableCapabilities = new BluetoothCodecConfig[ - A2dpCodecStatus.getCodecsSelectableCapabilities().length + - BapCodecStatus.getCodecsSelectableCapabilities().length]; - System.arraycopy(A2dpCodecStatus.getCodecsSelectableCapabilities(), 0, mCodecsSelectableCapabilities, 0, - A2dpCodecStatus.getCodecsSelectableCapabilities().length); - System.arraycopy(BapCodecStatus.getCodecsSelectableCapabilities(), 0, mCodecsSelectableCapabilities, - A2dpCodecStatus.getCodecsSelectableCapabilities().length, - BapCodecStatus.getCodecsSelectableCapabilities().length); - - mCodecStatus = new BluetoothCodecStatus(mCodecConfig, - mCodecsLocalCapabilities, mCodecsSelectableCapabilities); - return mCodecStatus; - } - - public void onCodecConfigChange(BluetoothDevice device, BluetoothCodecStatus mCodecStatus, Integer profile) { - onCodecConfigChange(device, mCodecStatus, profile, true); - } - - protected void refreshCurrentCodec(BluetoothDevice device) { - MediaDevice mMediaDevice = mMediaDevices.get(device.getAddress()); - if(mMediaDevice == null) { - return; - } - - mMediaDevice.mCodecStatus = convergeCodecConfig(mMediaDevice); - - Log.d(TAG, "refreshCurrentCodec: " + device + ", " + mMediaDevice.mCodecStatus); - - broadcastCodecStatus(device, mMediaDevice.mCodecStatus); - } - - public void onCodecConfigChange(BluetoothDevice device, - BluetoothCodecStatus codecStatus, Integer profile, Boolean updateAudio) { - Log.w(TAG, "onCodecConfigChange: for profile:" + profile + " for device " - + device + " update audio: " + updateAudio + " with status " + codecStatus); - if(device == null || codecStatus == null) - return; - - MediaDevice mMediaDevice = mMediaDevices.get(device.getAddress()); - BluetoothCodecStatus prevCodecStatus = null; - //BapBroadcastService mBapBroadcastService = BapBroadcastService.getBapBroadcastService(); - if (mMediaDevice == null && profile == ApmConst.AudioProfiles.BROADCAST_LE) { - Log.d(TAG,"LE Broadcast codec change"); - } else if(mMediaDevice == null) { - Log.e(TAG, "No entry in Device Profile map for device: " + device); - return; - } - if (mMediaDevice != null) { - int profileIndex = mMediaDevice.getProfileIndex(profile); - Log.d(TAG, "profileIndex: " + profileIndex); - - if(codecStatus.equals(mMediaDevice.mProfileCodecStatus[profileIndex])) { - Log.w(TAG, "onCodecConfigChange: Codec already updated for the device and profile"); - return; - } - - mMediaDevice.mProfileCodecStatus[profileIndex] = codecStatus; - prevCodecStatus = mMediaDevice.mCodecStatus; - - /* Check the codec status for alternate Media profile for this device */ - if(mMediaDevice.mProfileCodecStatus[(profileIndex+1)%2] != null) { - mMediaDevice.mCodecStatus = convergeCodecConfig(mMediaDevice); - } else { - mMediaDevice.mCodecStatus = codecStatus; - } - - Log.w(TAG, "BroadCasting codecstatus " + mMediaDevice.mCodecStatus + - " for device: " + device); - broadcastCodecStatus(device, mMediaDevice.mCodecStatus); - } - - if(prevCodecStatus != null && mMediaDevice != null) { - if (prevCodecStatus.getCodecConfig().equals(mMediaDevice.mCodecStatus.getCodecConfig())) { - Log.d(TAG, "Previous and current codec config are same. Return"); - return; - } - } - - ActiveDeviceManagerService mActiveDeviceManager = ActiveDeviceManagerService.get(); - if(mActiveDeviceManager != null && (!mActiveDeviceManager.isStableState(ApmConst.AudioFeatures.MEDIA_AUDIO))) { - Log.d(TAG, "SHO under progress. MM Audio will be updated after SHO completes"); - return; - } - - if(device.equals(mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.MEDIA_AUDIO)) && updateAudio) { - VolumeManager mVolumeManager = VolumeManager.get(); - int currentVolume = mVolumeManager.getActiveVolume(ApmConst.AudioFeatures.MEDIA_AUDIO); - if (profile == ApmConst.AudioProfiles.BROADCAST_LE) - currentVolume = 15; - if (mAudioManager != null) { - BluetoothDevice groupDevice = device; - if(profile == ApmConst.AudioProfiles.BAP_MEDIA) { - StreamAudioService mStreamAudioService = StreamAudioService.getStreamAudioService(); - groupDevice = mStreamAudioService.getDeviceGroup(device); - } - Log.d(TAG, "onCodecConfigChange Calling handleBluetoothA2dpActiveDeviceChange"); - mAudioManager.handleBluetoothA2dpActiveDeviceChange(groupDevice, - BluetoothProfile.STATE_CONNECTED, BluetoothProfile.A2DP, - true, currentVolume); - } - } - } - - private void broadcastConnStateChange(BluetoothDevice device, int prevState, int newState) { - A2dpService mA2dpService = A2dpService.getA2dpService(); - if (mA2dpService != null) { - Log.d(TAG, "Broadcast Conn State Change: " + prevState + "->" + newState + " for device " + device); - Intent intent = new Intent(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); - intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); - intent.putExtra(BluetoothProfile.EXTRA_STATE, newState); - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - mA2dpService.sendBroadcast(intent, BLUETOOTH_CONNECT, - Utils.getTempAllowlistBroadcastOptions()); - } - } - - private void broadcastStreamState(BluetoothDevice device, int prevStatus, int streamStatus) { - A2dpService mA2dpService = A2dpService.getA2dpService(); - if (mA2dpService != null) { - Intent intent = new Intent(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED); - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevStatus); - intent.putExtra(BluetoothProfile.EXTRA_STATE, streamStatus); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mA2dpService.sendBroadcast(intent, BLUETOOTH_CONNECT, - Utils.getTempAllowlistBroadcastOptions()); - } - } - - private void broadcastCodecStatus (BluetoothDevice device, BluetoothCodecStatus mCodecStatus) { - A2dpService mA2dpService = A2dpService.getA2dpService(); - if (mA2dpService != null) { - Intent intent = new Intent(BluetoothA2dp.ACTION_CODEC_CONFIG_CHANGED); - intent.putExtra(BluetoothCodecStatus.EXTRA_CODEC_STATUS, mCodecStatus); - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - mA2dpService.sendBroadcast(intent, BLUETOOTH_CONNECT, - Utils.getTempAllowlistBroadcastOptions()); - } - } - - public boolean isValidCodec (String mCodec) { - return supported_codec.contains(mCodec); - } - - public AudioManager getAudioManager() { - return mAudioManager; - } - - class MediaDevice { - BluetoothDevice mDevice; - int[] profileConnStatus = new int[2]; - int deviceConnStatus; - int streamStatus; - private BluetoothCodecStatus mCodecStatus; - private BluetoothCodecStatus[] mProfileCodecStatus = new BluetoothCodecStatus[2]; - - public static final int A2DP_STREAM = 0; - public static final int LE_STREAM = 1; - - MediaDevice(BluetoothDevice device, int profile, int state) { - profileConnStatus[A2DP_STREAM] = BluetoothProfile.STATE_DISCONNECTED; - profileConnStatus[LE_STREAM] = BluetoothProfile.STATE_DISCONNECTED; - mDevice = device; - if((profile & ApmConst.AudioProfiles.A2DP) != ApmConst.AudioProfiles.NONE) { - profileConnStatus[A2DP_STREAM] = state; - } - if((profile & (ApmConst.AudioProfiles.TMAP_MEDIA | ApmConst.AudioProfiles.BAP_MEDIA)) != - ApmConst.AudioProfiles.NONE) { - profileConnStatus[LE_STREAM] = state; - } - deviceConnStatus = state; - streamStatus = BluetoothA2dp.STATE_NOT_PLAYING; - } - - MediaDevice(BluetoothDevice device, int profile) { - this(device, profile, BluetoothProfile.STATE_DISCONNECTED); - } - - public int getProfileIndex(int profile) { - if(profile == ApmConst.AudioProfiles.A2DP) - return A2DP_STREAM; - else - return LE_STREAM; - } - } - - private class LeCodecConfig extends BroadcastReceiver { - /*am broadcast -a qti.intent.bluetooth.action.UPDATE_CODEC_CONFIG --es - qti.bluetooth.extra.CODEC_ID "LC3" --es qti.bluetooth.extra.CODEC_CONFIG ""*/ - - ArrayList supported_codec_config = new ArrayList( List.of( - /* config ID Sampling Freq Octets/Frame */ - "8_1", /* 8 26 */ - "8_2", /* 8 30 */ - "16_1", /* 16 30 */ - "16_2", /* 16 40 */ - "24_1", /* 24 45 */ - "24_2", /* 24 60 */ - "32_1", /* 32 60 */ - "32_2", /* 32 80 */ - "441_1",/* 44.1 98 */ - "441_2",/* 44.1 130 */ - "48_1", /* 48 75 */ - "48_2", /* 48 100 */ - "48_3", /* 48 90 */ - "48_4", /* 48 120 */ - "48_5", /* 48 117 */ - "48_6", /* 48 155 */ - "GCP_TX", - "GCP_TX_RX" - )); - - Map channel_mode = Map.of( - "NONE", 0, - "MONO", 1, - "STEREO", 2 - ); - - @Override - public void onReceive(Context context, Intent intent) { - if (!ACTION_UPDATE_CODEC_CONFIG.equals(intent.getAction())) { - return; - } - String mCodecId = intent.getStringExtra(CODEC_ID); - if(mCodecId == null || !isValidCodec(mCodecId)) { - Log.w(TAG, "Invalid Codec " + mCodecId); - return; - } - String mCodecConfig = intent.getStringExtra(CODEC_CONFIG); - if(mCodecConfig == null || !isValidCodecConfig(mCodecConfig)) { - Log.w(TAG, "Invalid Codec Config " + mCodecConfig); - return; - } - - int mChannelMode = BluetoothCodecConfig.CHANNEL_MODE_NONE; - String chMode = intent.getStringExtra(CHANNEL_MODE); - if(chMode != null && channel_mode.containsKey(chMode)) { - mChannelMode = channel_mode.get(chMode); - } - - ActiveDeviceManagerService mActiveDeviceManager - = ActiveDeviceManagerService.get(); - int profile = mActiveDeviceManager.getActiveProfile(ApmConst.AudioFeatures.MEDIA_AUDIO); - if(profile == ApmConst.AudioProfiles.BROADCAST_LE) { - /*Update Broadcast module here*/ - mBapBroadcastManager.setCodecPreference(mCodecConfig, mChannelMode); - } else if (profile == ApmConst.AudioProfiles.BAP_MEDIA) { - BluetoothDevice device = mActiveDeviceManager.getActiveDevice(ApmConst.AudioFeatures.MEDIA_AUDIO); - StreamAudioService service = StreamAudioService.getStreamAudioService(); - service.setCodecConfig(device, mCodecConfig, mChannelMode); - } - Log.i(TAG, "Codec Config Request: Codec Name: " + mCodecId + " Config ID: " - + mCodecConfig + " mChannelMode: " + mChannelMode + " for profile: " + profile); - } - - boolean isValidCodecConfig (String mCodecConfig) { - return supported_codec_config.contains(mCodecConfig); - } - } - - private class QosConfigReceiver extends BroadcastReceiver { - /*am broadcast -a qti.intent.bluetooth.action.UPDATE_QOS_CONFIG --es - qti.bluetooth.extra.CODEC_ID "LC3" --es qti.bluetooth.extra.QOS_CONFIG ""*/ - boolean enable = false; - - ArrayList supported_Qos_config = new ArrayList( List.of( - "8_1_1", - "8_2_1", - "16_1_1", - "16_2_1", - "24_1_1", - "24_2_1", - "32_1_1", - "32_2_1", - "441_1_1", - "441_2_1", - "48_1_1", - "48_2_1", - "48_3_1", - "48_4_1", - "48_5_1", - "48_6_1", - - "8_1_2", - "8_2_2", - "16_1_2", - "16_2_2", - "24_1_2", - "24_2_2", - "32_1_2", - "32_2_2", - "441_1_2", - "441_2_2", - "48_1_2", - "48_2_2", - "48_3_2", - "48_4_2", - "48_5_2", - "48_6_2" - )); - - @Override - public void onReceive(Context context, Intent intent) { - if(!enable) - return; - if (!ACTION_UPDATE_QOS_CONFIG.equals(intent.getAction())) { - return; - } - - String mCodecId = intent.getStringExtra(CODEC_ID); - if(mCodecId == null || !isValidCodec(mCodecId)) { - Log.w(TAG, "Invalid Codec " + mCodecId); - return; - } - String mQosConfig = intent.getStringExtra(QOS_CONFIG); - if(mQosConfig == null || !isValidQosConfig(mQosConfig)) { - Log.w(TAG, "Invalid QosConfig " + mQosConfig); - return; - } - - ActiveDeviceManagerService mActiveDeviceManager - = ActiveDeviceManagerService.get(); - int profile = mActiveDeviceManager.getActiveProfile(ApmConst.AudioFeatures.MEDIA_AUDIO); - if(profile == ApmConst.AudioProfiles.BROADCAST_LE) { - /*Update Broadcast module here*/ - } else if (profile == ApmConst.AudioProfiles.BAP_MEDIA) { - /*Update ACM here*/ - } - Log.i(TAG, "New Qos Config ID: " + mQosConfig + " for profile: " + profile); - } - - boolean isValidQosConfig(String mQosConfig) { - return supported_Qos_config.contains(mQosConfig); - } - } - - class BapBroadcastManager { - void setCodecPreference(String codecConfig, int channelMode) { - BroadcastService mBroadcastService = BroadcastService.getBroadcastService(); - if(mBroadcastService != null) { - mBroadcastService.setCodecPreference(codecConfig, channelMode); - } - } - - BluetoothCodecStatus getCodecStatus() { - BroadcastService mBroadcastService = BroadcastService.getBroadcastService(); - if(mBroadcastService != null) { - return mBroadcastService.getCodecStatus(); - } - return null; - } - - boolean isBapBroadcastActive() { - BroadcastService mBroadcastService = BroadcastService.getBroadcastService(); - if(mBroadcastService != null) { - return mBroadcastService.isBroadcastActive(); - } - return false; - } - } -} - diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/MediaControlManager.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/MediaControlManager.java deleted file mode 100644 index 1f197cbf2a05658ebb9b7d8c477218d04ad1582f..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/MediaControlManager.java +++ /dev/null @@ -1,211 +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. - * - ******************************************************************************/ - - -package com.android.bluetooth.apm; - -import android.os.Binder; -import android.os.HandlerThread; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.SystemProperties; -import android.util.Log; -import com.android.internal.util.ArrayUtils; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import android.content.Context; -import android.content.Intent; -import android.content.BroadcastReceiver; -import android.content.IntentFilter; -import android.media.AudioManager; -import android.media.AudioAttributes; -import android.media.AudioPlaybackConfiguration; -import android.media.MediaDescription; -import android.media.MediaMetadata; -import android.media.session.MediaSession; -import android.media.session.MediaSession.QueueItem; -import android.media.session.MediaSessionManager; -import android.media.session.PlaybackState; -import android.util.Log; -import android.util.StatsLog; - -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; - -import com.android.bluetooth.avrcp.MediaController; -import com.android.bluetooth.apm.StreamAudioService; -import com.android.bluetooth.mcp.McpService; - -public class MediaControlManager { - private static final boolean DBG = true; - private static final String TAG = "APM: MediaControlManager"; - - static MediaControlManager mMediaControlManager = null; - - PlaybackCallback mPlaybackCallbackCb; - //MediaControlCallback mMediaControlCallbackCb; - BroadcastReceiver mMediaControlReceiver; - private static Context mContext; - //private AudioManager mAudioManager; - private Handler mHandler; - private McpService mMcpService; - public static final String MusicPlayerControlServiceName = "com.android.bluetooth.mcp.McpService"; - public static final int MUSIC_PLAYER_CONTROL = McpService.MUSIC_PLAYER_CONTROL; - private MediaControlManager () { - mPlaybackCallbackCb = new PlaybackCallback(); - //mMediaControlCallbackCb = new MediaControlCallback(); - mMediaControlReceiver = new MediaControlReceiver(); - } - - public static MediaControlManager get() { - if(mMediaControlManager == null) { - mMediaControlManager = new MediaControlManager(); - } - Log.v(TAG, "get"); - return mMediaControlManager; - } - - public static void make(Context context) { - if(mMediaControlManager == null) { - mMediaControlManager = new MediaControlManager(); - mMediaControlManager.init(context); - MediaControlManagerIntf.init(mMediaControlManager); - Log.v(TAG, "init, New mMediaControlManager instance"); - } - } - - public void init(Context context) { - mContext = context; - - - - /*mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - - HandlerThread thread = new HandlerThread("MediaControlThread"); - Looper looper = thread.getLooper(); - mHandler = new Handler(looper); - mAudioManager.registerAudioPlaybackCallback(mPlaybackCallbackCb, - mHandler);*/ - - IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_PACKAGE_REMOVED); - filter.addAction(Intent.ACTION_PACKAGE_ADDED); - filter.addAction(Intent.ACTION_PACKAGE_CHANGED); - mContext.registerReceiver(mMediaControlReceiver, filter); - Log.v(TAG, "init done"); - } - - private void updateCurrentPlayer (int playerId, int browseId) { - } - - void handlePassthroughCmd(int op, int state) { - } - - private class PlaybackCallback extends AudioManager.AudioPlaybackCallback { - @Override - public void onPlaybackConfigChanged(List configs) { - super.onPlaybackConfigChanged(configs); - - /*Update Playback config*/ - } - } - - - public void onMetadataChanged(MediaMetadata metadata) { - /*Update Metadata change*/ - Log.v(TAG, "onMetadataChanged"); - mMcpService = McpService.getMcpService(); - if (mMcpService != null) { - mMcpService.updateMetaData(metadata); - } - } - - public synchronized void onPlaybackStateChanged(PlaybackState state) { - /*Update Playback State*/ - Log.v(TAG, "onPlaybackStateChanged"); - mMcpService = McpService.getMcpService(); - if (mMcpService != null) { - mMcpService.updatePlaybackState(state); - } - - } - - public synchronized void onPackageChanged(String packageName) { - Log.v(TAG, "onPackageChanged"); - mMcpService = McpService.getMcpService(); - boolean removed = false; - if (packageName == null) - removed = true; - if (mMcpService != null) { - mMcpService.updatePlayerName(packageName, removed); - } - } - public void onSessionDestroyed(String packageName) { - Log.v(TAG, "onSessionDestroyed"); - mMcpService = McpService.getMcpService(); - if (mMcpService != null) { - mMcpService.updatePlayerName(packageName, true); - } - } - - public void onQueueChanged(List queue) { - - } - - private class MediaControlReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - String packageName = null; - String action = intent.getAction(); - boolean removed = false; - Log.v(TAG, "action " + action); - if(action == null) - return; - - switch(action) { - case Intent.ACTION_PACKAGE_REMOVED: - packageName = intent.getData().getSchemeSpecificPart(); - /*handle package removed*/ - removed = true; - break; - case Intent.ACTION_PACKAGE_ADDED: - packageName = intent.getData().getSchemeSpecificPart(); - /*handle package added*/ - break; - case Intent.ACTION_PACKAGE_CHANGED: - packageName = intent.getData().getSchemeSpecificPart(); - /*handle package changed*/ - break; - default : - break; - } - mMcpService = McpService.getMcpService(); - if (mMcpService != null) { - mMcpService.updatePlayerName(packageName, removed); - } - } - } -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/StreamAudioService.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/StreamAudioService.java deleted file mode 100644 index fc42703773d236d7320d5484368cab49cc4df539..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/StreamAudioService.java +++ /dev/null @@ -1,382 +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. - * - ******************************************************************************/ - - -package com.android.bluetooth.apm; - -import static com.android.bluetooth.Utils.enforceBluetoothPermission; -import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission; - -import android.bluetooth.BluetoothCodecConfig; -import android.bluetooth.BluetoothCodecStatus; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; -import android.bluetooth.IBluetoothVcp; - -import android.os.Binder; -import android.os.HandlerThread; -import android.os.Handler; -import android.os.Message; -import android.os.SystemProperties; -import android.util.Log; - -import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.btservice.ProfileService; -import com.android.bluetooth.acm.AcmService; - -public class StreamAudioService extends ProfileService { - private static final boolean DBG = true; - private static final String TAG = "APM: StreamAudioService:"; - public static final int LE_AUDIO_UNICAST = 26; - - public static final String CoordinatedAudioServiceName = "com.android.bluetooth.acm.AcmService"; - public static final int COORDINATED_AUDIO_UNICAST = AcmService.ACM_AUDIO_UNICAST; - - private static StreamAudioService sStreamAudioService; - private ActiveDeviceManagerService mActiveDeviceManager; - private MediaAudio mMediaAudio; - private VolumeManager mVolumeManager; - private final Object mVolumeManagerLock = new Object(); - @Override - protected void create() { - Log.i(TAG, "create()"); - } - - private static final int BAP = 0x01; - private static final int GCP = 0x02; - private static final int WMCP = 0x04; - private static final int VMCP = 0x08; - private static final int BAP_CALL = 0x10; - - private static final int MEDIA_CONTEXT = 1; - private static final int VOICE_CONTEXT = 2; - - @Override - protected boolean start() { - if(sStreamAudioService != null) { - Log.i(TAG, "StreamAudioService already started"); - return true; - } - Log.i(TAG, "start()"); - - ApmConst.setLeAudioEnabled(true); - ApmConstIntf.init(); - - setStreamAudioService(this); - - mActiveDeviceManager = ActiveDeviceManagerService.get(this); - mMediaAudio = MediaAudio.init(this); - - DeviceProfileMap dpm = DeviceProfileMap.getDeviceProfileMapInstance(); - dpm.init(this); - CallAudio mCallAudio = CallAudio.init(this); - synchronized (mVolumeManagerLock) { - mVolumeManager = VolumeManager.init(this); - } - - Log.i(TAG, "start() complete"); - return true; - } - - @Override - protected boolean stop() { - Log.w(TAG, "stop() called"); - if (sStreamAudioService == null) { - Log.w(TAG, "stop() called before start()"); - return true; - } - - if (mActiveDeviceManager != null) { - mActiveDeviceManager.disable(); - mActiveDeviceManager.cleanup(); - } - - DeviceProfileMap dMap = DeviceProfileMap.getDeviceProfileMapInstance(); - dMap.cleanup(); - return true; - } - - @Override - protected void cleanup() { - Log.i(TAG, "cleanup()"); - synchronized (mVolumeManagerLock) { - mVolumeManager.cleanup(); - mVolumeManager = null; - } - setStreamAudioService(null); - } - - public boolean connectLeStream(BluetoothDevice device, int profile) { - AcmService mAcmService = AcmService.getAcmService(); - int mContext = getContext(profile); - - if(mContext == 0) { - Log.e(TAG, "No valid context for profiles passed"); - return false; - } - return mAcmService.connect(device, mContext, getAcmProfileID(profile), MEDIA_CONTEXT); - //return mAcmService.connect(device, VOICE_CONTEXT, BAP_CALL, VOICE_CONTEXT); - //return mAcmService.connect(device, MEDIA_CONTEXT, BAP|WMCP, MEDIA_CONTEXT); - } - - public boolean disconnectLeStream(BluetoothDevice device, boolean callAudio, boolean mediaAudio) { - AcmService mAcmService = AcmService.getAcmService(); - if(callAudio && mediaAudio) - return mAcmService.disconnect(device, VOICE_CONTEXT | MEDIA_CONTEXT); - //return mAcmService.disconnect(device, VOICE_CONTEXT); - //return mAcmService.disconnect(device, MEDIA_CONTEXT); - else if(mediaAudio) - return mAcmService.disconnect(device, MEDIA_CONTEXT); - else if(callAudio) - return mAcmService.disconnect(device, VOICE_CONTEXT); - - return false; - } - - public boolean startStream(BluetoothDevice device) { - AcmService mAcmService = AcmService.getAcmService(); - return mAcmService.StartStream(device, VOICE_CONTEXT); - } - - public boolean stopStream(BluetoothDevice device) { - AcmService mAcmService = AcmService.getAcmService(); - return mAcmService.StopStream(device, VOICE_CONTEXT); - } - - public int setActiveDevice(BluetoothDevice device, int profile, boolean playReq) { - AcmService mAcmService = AcmService.getAcmService(); - if (mAcmService == null && device == null) { - Log.w(TAG, ": device is null, fake success."); - return mActiveDeviceManager.SHO_SUCCESS; - } - - if(ApmConst.AudioProfiles.BAP_MEDIA == profile) { - return mAcmService.setActiveDevice(device, MEDIA_CONTEXT, BAP, playReq); - } else if(ApmConst.AudioProfiles.BAP_GCP == profile){ - return mAcmService.setActiveDevice(device, MEDIA_CONTEXT, GCP, playReq); - } else if(ApmConst.AudioProfiles.BAP_RECORDING == profile){ - return mAcmService.setActiveDevice(device, MEDIA_CONTEXT, WMCP, playReq); - } else { - return mAcmService.setActiveDevice(device, VOICE_CONTEXT, BAP_CALL, playReq); - //return mAcmService.setActiveDevice(device, MEDIA_CONTEXT, BAP, playReq); - } - } - - public void setCodecConfig(BluetoothDevice device, String codecID, int channelMode) { - AcmService mAcmService = AcmService.getAcmService(); - mAcmService.ChangeCodecConfigPreference(device, codecID); - } - - public BluetoothDevice getDeviceGroup(BluetoothDevice device){ - AcmService mAcmService = AcmService.getAcmService(); - return mAcmService.getGroup(device); - } - - public void onConnectionStateChange(BluetoothDevice device, int state, int audioType, boolean primeDevice) { - MediaAudio mMediaAudio = MediaAudio.get(); - CallAudio mCallAudio = CallAudio.get(); - int profile = ApmConst.AudioFeatures.MAX_AUDIO_FEATURES; - if(audioType == ApmConst.AudioFeatures.CALL_AUDIO) { - mCallAudio.onConnStateChange(device, state, ApmConst.AudioProfiles.BAP_CALL); - } else if(audioType == ApmConst.AudioFeatures.MEDIA_AUDIO) { - boolean isCsipDevice = (device != null) && - getDeviceGroup(device).getAddress().contains(ApmConst.groupAddress); - if(isCsipDevice) - mMediaAudio.onConnStateChange(device, state, ApmConst.AudioProfiles.BAP_MEDIA, primeDevice); - else - mMediaAudio.onConnStateChange(device, state, ApmConst.AudioProfiles.BAP_MEDIA); - } - } - - public void onStreamStateChange(BluetoothDevice device, int state, int audioType) { - MediaAudio mMediaAudio = MediaAudio.get(); - CallAudio mCallAudio = CallAudio.get(); - if(audioType == ApmConst.AudioFeatures.MEDIA_AUDIO) - mMediaAudio.onStreamStateChange(device, state); - else if(audioType == ApmConst.AudioFeatures.CALL_AUDIO) - mCallAudio.onAudioStateChange(device, state); - } - - public void onActiveDeviceChange(BluetoothDevice device, int audioType) { - if (mActiveDeviceManager != null) - mActiveDeviceManager.onActiveDeviceChange(device, audioType); - } - - public void onMediaCodecConfigChange(BluetoothDevice device, BluetoothCodecStatus codecStatus, int audioType) { - MediaAudio mMediaAudio = MediaAudio.get(); - mMediaAudio.onCodecConfigChange(device, codecStatus, ApmConst.AudioProfiles.BAP_MEDIA); - } - - public void onMediaCodecConfigChange(BluetoothDevice device, BluetoothCodecStatus codecStatus, int audioType, boolean updateAudio) { - MediaAudio mMediaAudio = MediaAudio.get(); - mMediaAudio.onCodecConfigChange(device, codecStatus, ApmConst.AudioProfiles.BAP_MEDIA, updateAudio); - } - - public void setCallAudioParam(String param) { - CallAudio mCallAudio = CallAudio.get(); - mCallAudio.setAudioParam(param); - } - - public void setCallAudioOn(boolean on) { - CallAudio mCallAudio = CallAudio.get(); - mCallAudio.setBluetoothScoOn(on); - } - - public int getVcpConnState(BluetoothDevice device) { - synchronized (mVolumeManagerLock) { - if (mVolumeManager == null) - return BluetoothProfile.STATE_DISCONNECTED; - return mVolumeManager.getConnectionState(device); - } - } - - public int getConnectionMode(BluetoothDevice device) { - synchronized (mVolumeManagerLock) { - if (mVolumeManager == null) - return BluetoothProfile.STATE_DISCONNECTED; - return mVolumeManager.getConnectionMode(device); - } - } - - public void setAbsoluteVolume(BluetoothDevice device, int volume) { - synchronized (mVolumeManagerLock) { - if (mVolumeManager != null) - mVolumeManager.updateBroadcastVolume(device, volume); - } - } - - public int getAbsoluteVolume(BluetoothDevice device) { - synchronized (mVolumeManagerLock) { - if (mVolumeManager == null) - return 7; - return mVolumeManager.getBassVolume(device); - } - } - - public void setMute(BluetoothDevice device, boolean muteStatus) { - synchronized (mVolumeManagerLock) { - if (mVolumeManager != null) - mVolumeManager.setMute(device, muteStatus); - } - } - - public boolean isMute(BluetoothDevice device) { - synchronized (mVolumeManagerLock) { - if (mVolumeManager == null) - return false; - return mVolumeManager.getMuteStatus(device); - } - } - - private int getContext(int profileID) { - int context = 0; - if((DeviceProfileMap.getLeMediaProfiles() & profileID) > 0) { - context = (context|MEDIA_CONTEXT); - } - - if((DeviceProfileMap.getLeCallProfiles() & profileID) > 0) { - context = (context|VOICE_CONTEXT); - } - return context; - } - - private int getAcmProfileID (int ProfileID) { - int AcmProfileID = 0; - if((ApmConst.AudioProfiles.BAP_MEDIA & ProfileID) == ApmConst.AudioProfiles.BAP_MEDIA) - AcmProfileID = BAP; - if((ApmConst.AudioProfiles.BAP_CALL & ProfileID) == ApmConst.AudioProfiles.BAP_CALL) - AcmProfileID = AcmProfileID | BAP_CALL; - if((ApmConst.AudioProfiles.BAP_GCP & ProfileID) == ApmConst.AudioProfiles.BAP_GCP) - AcmProfileID = AcmProfileID | GCP; - if((ApmConst.AudioProfiles.BAP_RECORDING & ProfileID) == ApmConst.AudioProfiles.BAP_RECORDING) - AcmProfileID = AcmProfileID | WMCP; - return AcmProfileID; - } - - @Override - protected IProfileServiceBinder initBinder() { - return new LeAudioUnicastBinder(this); - } - - private static class LeAudioUnicastBinder extends IBluetoothVcp.Stub implements IProfileServiceBinder { - - StreamAudioService mService; - LeAudioUnicastBinder(StreamAudioService service) { - mService = service; - } - - @Override - public void cleanup() { - } - - @Override - public int getConnectionState(BluetoothDevice device) { - if(mService == null) - return BluetoothProfile.STATE_DISCONNECTED; - return mService.getVcpConnState(device); - } - - @Override - public int getConnectionMode(BluetoothDevice device) { - if(mService != null) { - return mService.getConnectionMode(device); - } - return 0; - } - - @Override - public void setAbsoluteVolume(BluetoothDevice device, int volume) { - if(mService != null) { - mService.setAbsoluteVolume(device, volume); - } - } - - @Override - public int getAbsoluteVolume(BluetoothDevice device) { - if(mService == null) - return 7; - return mService.getAbsoluteVolume(device); - } - - @Override - public void setMute (BluetoothDevice device, boolean enableMute) { - if(mService != null) { - mService.setMute(device, enableMute); - } - } - - @Override - public boolean isMute(BluetoothDevice device) { - if(mService != null) { - return mService.isMute(device); - } - return false; - } - } - - public static StreamAudioService getStreamAudioService() { - return sStreamAudioService; - } - - private static synchronized void setStreamAudioService(StreamAudioService instance) { - if (DBG) { - Log.d(TAG, "setStreamAudioService(): set to: " + instance); - } - sStreamAudioService = instance; - } -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/VolumeManager.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/VolumeManager.java deleted file mode 100644 index a57195778cce4018af93b4d8fa2be26463c71fa8..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/apm/VolumeManager.java +++ /dev/null @@ -1,779 +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. - * - ******************************************************************************/ - - -package com.android.bluetooth.apm; - -import android.bluetooth.BleBroadcastAudioScanAssistManager; -import android.bluetooth.BleBroadcastSourceInfo; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; -import android.bluetooth.BluetoothA2dp; -import android.bluetooth.BluetoothHeadset; -import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.a2dp.A2dpService; -import com.android.bluetooth.avrcp.Avrcp_ext; -import com.android.bluetooth.acm.AcmService; -import com.android.bluetooth.bc.BCService; -import com.android.bluetooth.hfp.HeadsetService; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.media.AudioManager; -import android.util.Log; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.List; -import java.util.Map; - -public class VolumeManager { - public static final String TAG = "APM: VolumeManager"; - private static VolumeManager mVolumeManager = null; - private DeviceVolume mMedia; - private DeviceVolume mCall; - private DeviceVolume mBroadcast; - private DeviceProfileMap dpm; - private MediaAudio mMediaAudio; - private CallAudio mCallAudio; - private static Context mContext; - BroadcastReceiver mVolumeManagerReceiver; - Map AbsVolumeSupport; - - public static final String CALL_VOLUME_MAP = "bluetooth_call_volume_map"; - public static final String MEDIA_VOLUME_MAP = "bluetooth_media_volume_map"; - public static final String BROADCAST_VOLUME_MAP = "bluetooth_broadcast_volume_map"; - public final String ACTION_SHUTDOWN = "android.intent.action.ACTION_SHUTDOWN"; - public final String ACTION_POWER_OFF = "android.intent.action.QUICKBOOT_POWEROFF"; - - private VolumeManager() { - mCall = new DeviceVolume(mContext, CALL_VOLUME_MAP); - mMedia = new DeviceVolume(mContext, MEDIA_VOLUME_MAP); - mBroadcast = new DeviceVolume(mContext, BROADCAST_VOLUME_MAP); - - dpm = DeviceProfileMap.getDeviceProfileMapInstance(); - mMediaAudio = MediaAudio.get(); - mCallAudio = CallAudio.get(); - - AbsVolumeSupport = new ConcurrentHashMap(); - - mVolumeManagerReceiver = new VolumeManagerReceiver(); - IntentFilter filter = new IntentFilter(); - filter.addAction(AudioManager.VOLUME_CHANGED_ACTION); - filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); - filter.addAction(ACTION_SHUTDOWN); - filter.addAction(ACTION_POWER_OFF); - filter.addAction(BleBroadcastAudioScanAssistManager.ACTION_BROADCAST_SOURCE_INFO); - mContext.registerReceiver(mVolumeManagerReceiver, filter); - } - - public static VolumeManager init (Context context) { - mContext = context; - - if(mVolumeManager == null) { - mVolumeManager = new VolumeManager(); - VolumeManagerIntf.init(mVolumeManager); - } - - return mVolumeManager; - } - - public void cleanup() { - Log.i(TAG, "cleanup"); - handleDeviceShutdown(); - synchronized (mVolumeManager) { - mCall = null; - mMedia = null; - mBroadcast = null; - mContext.unregisterReceiver(mVolumeManagerReceiver); - mVolumeManagerReceiver = null; - AbsVolumeSupport.clear(); - AbsVolumeSupport = null; - mVolumeManager = null; - } - } - - public static VolumeManager get() { - return mVolumeManager; - } - - private DeviceVolume VolumeType(int mAudioType) { - if(ApmConst.AudioFeatures.CALL_AUDIO == mAudioType) { - return mCall; - } else if(ApmConst.AudioFeatures.MEDIA_AUDIO == mAudioType) { - return mMedia; - } else if(ApmConst.AudioFeatures.BROADCAST_AUDIO == mAudioType) { - return mBroadcast; - } - return null; - } - - public int getConnectionMode(BluetoothDevice device) { - AcmService mAcmService = AcmService.getAcmService(); - if(mAcmService == null) { - return -1; - } - return mAcmService.getVcpConnMode(device); - } - - public void setMediaAbsoluteVolume (Integer volume) { - if(mMedia.mDevice == null) { - Log.e (TAG, "setMediaAbsoluteVolume: No Device Active for Media. Ignore"); - return; - } - mMedia.updateVolume(volume); - - if(ApmConst.AudioProfiles.AVRCP == mMedia.mProfile) { - Avrcp_ext mAvrcp = Avrcp_ext.get(); - if(mAvrcp != null) { - Log.i (TAG, "setMediaAbsoluteVolume: Updating new volume to AVRCP: " + volume); - mAvrcp.setAbsoluteVolume(volume); - } - } else if(ApmConst.AudioProfiles.VCP == mMedia.mProfile) { - AcmService mAcmService = AcmService.getAcmService(); - if(mAcmService != null) { - Log.i (TAG, "setMediaAbsoluteVolume: Updating new volume to VCP: " + volume); - mMedia.updateVolume(volume); - mAcmService.setAbsoluteVolume(mMedia.mDevice, volume, ApmConst.AudioFeatures.MEDIA_AUDIO); - } - } - } - - public void updateMediaStreamVolume (Integer volume) { - if(mMedia.mDevice == null) { - Log.e (TAG, "updateMediaStreamVolume: No Device Active for Media. Ignore"); - return; - } - - if(mMedia.mSupportAbsoluteVolume) { - /* Ignore: Will update volume via API call */ - return; - } - mMedia.updateVolume(volume); - } - - public void updateBroadcastVolume (BluetoothDevice device, int volume) { - int callAudioState = mCallAudio.getAudioState(device); - boolean isCall = (callAudioState == BluetoothHeadset.STATE_AUDIO_CONNECTING || - callAudioState == BluetoothHeadset.STATE_AUDIO_CONNECTED); - if (isCall) { - Log.e(TAG, "Call in progress, ignore volume change"); - return; - } - - mBroadcast.updateVolume(device, volume); - AcmService mAcmService = AcmService.getAcmService(); - BluetoothDevice mGroupDevice = mAcmService.getGroup(device); - mAcmService.setAbsoluteVolume(mGroupDevice, volume, ApmConst.AudioFeatures.BROADCAST_AUDIO); - mBroadcast.updateVolume(mGroupDevice, volume); - } - - public void setMute(BluetoothDevice device, boolean muteStatus) { - AcmService mAcmService = AcmService.getAcmService(); - BluetoothDevice mGroupDevice = mAcmService.getGroup(device); - mAcmService.setMute(mGroupDevice, muteStatus); - } - - public void restoreCallVolume (Integer volume) { - if(mCall.mDevice == null) { - Log.e (TAG, "restoreCallVolume: No Device Active for Call. Ignore"); - return; - } - - if(ApmConst.AudioProfiles.HFP == mCall.mProfile) { - // Ignore restoring call volume for HFP case - Log.w (TAG, "restoreCallVolume: Ignore restore call volume for HFP"); - } else if(ApmConst.AudioProfiles.VCP == mCall.mProfile) { - AcmService mAcmService = AcmService.getAcmService(); - if(mAcmService != null) { - Log.i (TAG, "restoreCallVolume: Updating new volume to VCP: " + volume); - mCall.updateVolume(volume); - mAcmService.setAbsoluteVolume(mCall.mDevice, volume, ApmConst.AudioFeatures.CALL_AUDIO); - } - // TODO: Restore call volume to MM-Audio also - } - } - - public void setCallVolume (Intent intent) { - if(mCall.mDevice == null) { - Log.e (TAG, "setCallVolume: No Device Active for Call. Ignore"); - return; - } - - int volume = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0); - if(ApmConst.AudioProfiles.HFP == mCall.mProfile) { - Log.i (TAG, "setCallVolume: Updating new volume to HFP: " + volume); - HeadsetService headsetService = HeadsetService.getHeadsetService(); - headsetService.setIntentScoVolume(intent); - } else if(ApmConst.AudioProfiles.VCP == mCall.mProfile) { - Log.i (TAG, "setCallVolume: mCall volume: " + mCall.mVolume + ", volume: " + volume); - // Avoid updating same call volume after remote volume change - if (volume == mCall.mVolume) { - Log.w (TAG, "setCallVolume: Ignore updating same call volume to remote"); - return; - } - AcmService mAcmService = AcmService.getAcmService(); - if(mAcmService != null) { - Log.i (TAG, "setCallVolume: Updating new volume to VCP: " + volume); - mCall.updateVolume(volume); - mAcmService.setAbsoluteVolume(mCall.mDevice, volume, ApmConst.AudioFeatures.CALL_AUDIO); - } - } - } - - public int getConnectionState(BluetoothDevice device) { - AcmService mAcmService = AcmService.getAcmService(); - return mAcmService.getVcpConnState(device); - } - - public void onConnStateChange(BluetoothDevice device, Integer state, Integer profile) { - Log.d (TAG, "onConnStateChange: state: " + state + " Profile: " + profile); - if (device == null) { - Log.e (TAG, "onConnStateChange: device is null. Ignore"); - return; - } - - AcmService mAcmService = AcmService.getAcmService(); - BluetoothDevice mGroupDevice; - if(mAcmService != null) { - mGroupDevice = mAcmService.getGroup(device); - } else { - mGroupDevice = device; - } - - if (mGroupDevice.equals(mMedia.mDevice)) { - mMedia.mProfile = - dpm.getProfile(mGroupDevice, ApmConst.AudioFeatures.MEDIA_VOLUME_CONTROL); - } - if (mGroupDevice.equals(mCall.mDevice)) { - mCall.mProfile = - dpm.getProfile(mGroupDevice, ApmConst.AudioFeatures.CALL_VOLUME_CONTROL); - } - - if (state == BluetoothProfile.STATE_CONNECTED) { - int audioType = getActiveAudioType(device); - if (ApmConst.AudioFeatures.MEDIA_AUDIO == audioType && mMedia.mProfile == profile) { - Log.d (TAG, "onConnStateChange: Media is streaming or active, update media volume"); - setMediaAbsoluteVolume(mMedia.mVolume); - } else if (ApmConst.AudioFeatures.CALL_AUDIO == audioType && - mCall.mProfile == profile) { - Log.d (TAG, "onConnStateChange: Call is streaming, update call volume"); - restoreCallVolume(mCall.mVolume); - } else if (ApmConst.AudioFeatures.BROADCAST_AUDIO == audioType) { - Log.d (TAG, "onConnStateChange: Broadcast is streaming, update broadcast volume"); - updateBroadcastVolume(device, getBassVolume(device)); - } - } - } - - public void onVolumeChange(Integer volume, Integer audioType, Boolean showUI) { - int flag = showUI ? AudioManager.FLAG_SHOW_UI : 0; - if(audioType == ApmConst.AudioFeatures.CALL_AUDIO){ - mCall.updateVolume(volume); - mCallAudio.getAudioManager().setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO, - volume, flag); - } else if(audioType == ApmConst.AudioFeatures.MEDIA_AUDIO) { - mMedia.updateVolume(volume); - mMediaAudio.getAudioManager().setStreamVolume(AudioManager.STREAM_MUSIC, volume, - flag | AudioManager.FLAG_BLUETOOTH_ABS_VOLUME); - } - } - - public void onVolumeChange(BluetoothDevice device, Integer volume, Integer audioType) { - if ((VolumeType(audioType) == mCall && device.equals(mCall.mDevice)) || - (VolumeType(audioType) == mMedia && device.equals(mMedia.mDevice))) { - onVolumeChange(volume, audioType, true); - } else { - mBroadcast.updateVolume(device, volume); - } - } - - public void onMuteStatusChange(BluetoothDevice device, boolean isMute, int audioType) { - } - - - public void onActiveDeviceChange(BluetoothDevice device, int audioType) { - if(device == null) { - synchronized(mVolumeManager) { - if(VolumeType(audioType) != null) - VolumeType(audioType).reset(); - } - } else { - int mProfile = dpm.getProfile(device, audioType == ApmConst.AudioFeatures.CALL_AUDIO? - ApmConst.AudioFeatures.CALL_VOLUME_CONTROL:ApmConst.AudioFeatures.MEDIA_VOLUME_CONTROL); - DeviceVolume mDeviceVolume = VolumeType(audioType); - mDeviceVolume.updateDevice(device, mProfile); - Log.i(TAG, "ActiveDeviceChange: device: " + mDeviceVolume.mDevice + ". AudioType: " + audioType); - if(mDeviceVolume.equals(mMedia)) { - int mAbsVolSupportProfiles = AbsVolumeSupport.getOrDefault(device.getAddress(), 0); - boolean isAbsSupported = ((mProfile & mAbsVolSupportProfiles) != 0) ? true : false; - Log.i(TAG, "isAbsoluteVolumeSupport: " + isAbsSupported); - mDeviceVolume.mSupportAbsoluteVolume = isAbsSupported; - mMediaAudio.getAudioManager().avrcpSupportsAbsoluteVolume ( - device.getAddress(), isAbsSupported); - - Log.i(TAG, "ActiveDeviceChange: Profile: " + mProfile + ". New Volume: " + mDeviceVolume.mVolume); - if (!isBroadcastAudioSynced(device) || - (mMediaAudio.isA2dpPlaying(device) && mMediaAudio.getAudioManager().isMusicActive())) { - setMediaAbsoluteVolume(mDeviceVolume.mVolume); - } - } - } - } - - public void updateStreamState(BluetoothDevice device, Integer streamState, Integer audioType) { - boolean isMusicActive = false; - if (device == null) { - Log.e (TAG, "updateStreamState: device is null. Ignore"); - return; - } - if (audioType == ApmConst.AudioFeatures.MEDIA_AUDIO && - streamState == BluetoothA2dp.STATE_PLAYING) { - isMusicActive = mMediaAudio.getAudioManager().isMusicActive(); - } - Log.d(TAG, "updateStreamState, device: " + device + " type: " + audioType - + " streamState: " + streamState + " isMusicActive: " + isMusicActive); - - AcmService mAcmService = AcmService.getAcmService(); - BluetoothDevice mGroupDevice; - if(mAcmService != null) { - mGroupDevice = mAcmService.getGroup(device); - } else { - mGroupDevice = device; - } - - if ((audioType == ApmConst.AudioFeatures.MEDIA_AUDIO && - streamState == BluetoothA2dp.STATE_NOT_PLAYING) || - (audioType == ApmConst.AudioFeatures.CALL_AUDIO && - streamState == BluetoothHeadset.STATE_AUDIO_DISCONNECTED)) { - if (isBroadcastAudioSynced(device)) { - handleBroadcastAudioSynced(device); - } - } else if (audioType == ApmConst.AudioFeatures.MEDIA_AUDIO && - streamState == BluetoothA2dp.STATE_PLAYING && isMusicActive) { - if (mGroupDevice.equals(mMedia.mDevice)) { - Log.d(TAG, "Restore volume for A2dp streaming"); - setMediaAbsoluteVolume(mMedia.mVolume); - } - } else if (audioType == ApmConst.AudioFeatures.CALL_AUDIO && - streamState == BluetoothHeadset.STATE_AUDIO_CONNECTED) { - if (mGroupDevice.equals(mCall.mDevice)) { - Log.d(TAG, "Restore volume for call"); - restoreCallVolume(mCall.mVolume); - } - } - } - - public int getActiveAudioType(BluetoothDevice device) { - int callAudioState = mCallAudio.getAudioState(device); - boolean isCall = (callAudioState == BluetoothHeadset.STATE_AUDIO_CONNECTING || - callAudioState == BluetoothHeadset.STATE_AUDIO_CONNECTED); - int audioType = -1; - - if (device == null) { - Log.e (TAG, "getActiveAudioType: device is null. Ignore"); - return audioType; - } - - AcmService mAcmService = AcmService.getAcmService(); - BluetoothDevice mGroupDevice; - if(mAcmService != null) { - mGroupDevice = mAcmService.getGroup(device); - } else { - mGroupDevice = device; - } - - if (mMediaAudio.isA2dpPlaying(device) && - mMediaAudio.getAudioManager().isMusicActive()) { - if (mGroupDevice.equals(mMedia.mDevice)) { - Log.d(TAG, "Active Media audio is streaming"); - audioType = ApmConst.AudioFeatures.MEDIA_AUDIO; - } - } else if (isCall) { - if (mGroupDevice.equals(mCall.mDevice)) { - Log.d(TAG, "Active Call audio is streaming"); - audioType = ApmConst.AudioFeatures.CALL_AUDIO; - } - } else if (isBroadcastAudioSynced(device)) { - Log.d(TAG, "Broadcast audio is streaming"); - audioType = ApmConst.AudioFeatures.BROADCAST_AUDIO; - } else { - Log.d(TAG, "None of audio is streaming"); - ActiveDeviceManagerService activeDeviceManager = - ActiveDeviceManagerService.get(mContext); - BluetoothDevice activeDevice = - activeDeviceManager.getActiveDevice(ApmConst.AudioFeatures.MEDIA_AUDIO); - if (mGroupDevice.equals(mMedia.mDevice) && mGroupDevice.equals(activeDevice)) { - Log.d(TAG, "Peer is Media active, set for media type by default"); - audioType = ApmConst.AudioFeatures.MEDIA_AUDIO; - } else { - Log.d(TAG, "Inactive peer, unknow audio type"); - } - } - - Log.d(TAG, "getActiveAudioType: ret " + audioType); - return audioType; - } - - /*Should be called by AVRCP and VCP after every connection*/ - public void setAbsoluteVolumeSupport(BluetoothDevice device, Boolean isSupported, - Integer initVol, Integer profile) { - setAbsoluteVolumeSupport(device, isSupported, profile); - } - - public void setAbsoluteVolumeSupport(BluetoothDevice device, Boolean isSupported, - Integer profile) { - Log.i(TAG, "setAbsoluteVolumeSupport device " + device + " profile " + profile - + " isSupported " + isSupported); - if(device == null) - return; - - int mProfile = dpm.getProfile(device, ApmConst.AudioFeatures.MEDIA_VOLUME_CONTROL); - int mAbsVolSupportProfiles = AbsVolumeSupport.getOrDefault(device.getAddress(), 0); - if (isSupported) { - mAbsVolSupportProfiles = mAbsVolSupportProfiles | profile; - } else { - mAbsVolSupportProfiles = mAbsVolSupportProfiles & ~profile; - } - - if(device.equals(mMedia.mDevice)) { - boolean isAbsSupported = ((mProfile & mAbsVolSupportProfiles) != 0) ? true : false; - Log.i(TAG, "Update abs volume support: " + isAbsSupported); - mMedia.mSupportAbsoluteVolume = isAbsSupported; - mMediaAudio.getAudioManager().avrcpSupportsAbsoluteVolume ( - device.getAddress(), isAbsSupported); - - if(mMedia.mProfile == ApmConst.AudioProfiles.NONE) { - mMedia.mProfile = mProfile; - Log.i(TAG, "setAbsoluteVolumeSupport: Profile: " + mMedia.mProfile); - } - } - AbsVolumeSupport.put(device.getAddress(), mAbsVolSupportProfiles); - } - - public void saveVolume(Integer audioType) { - VolumeType(audioType).saveVolume(); - } - - public int getSavedVolume(BluetoothDevice device, Integer audioType) { - return VolumeType(audioType).getSavedVolume(device); - } - - public int getActiveVolume(Integer audioType) { - return VolumeType(audioType).mVolume; - } - - public int getBassVolume(BluetoothDevice device) { - AcmService mAcmService = AcmService.getAcmService(); - BluetoothDevice mGroupDevice = mAcmService.getGroup(device); - int volume = mBroadcast.getVolume(mGroupDevice); - Log.i(TAG, "getBassVolume: " + device + " volume: " + volume); - return volume; - } - - public boolean getMuteStatus(BluetoothDevice device) { - AcmService mAcmService = AcmService.getAcmService(); - if(mAcmService == null) { - return false; - } - return mAcmService.isVcpMute(device); - } - - boolean isBroadcastAudioSynced(BluetoothDevice device) { - BCService mBCService = BCService.getBCService(); - if (mBCService == null || device == null) return false; - List srcInfos = - mBCService.getAllBroadcastSourceInformation(device); - if (srcInfos == null || srcInfos.size() == 0) { - Log.e(TAG, "source Infos not available"); - return false; - } - - for (int i=0; i mBassVolMap; - - Context mContext; - private String mAudioTypeStr; - public static final int SAFE_VOL = 7; - public String mVolumeMap; - - DeviceVolume(Context context, String map) { - this.reset(); - mContext = context; - mVolumeMap = map; - mSupportAbsoluteVolume = false; - - if(map == "bluetooth_call_volume_map") { - mAudioTypeStr = "Call"; - } - else if(map == "bluetooth_media_volume_map") { - mAudioTypeStr = "Media"; - } - else { - mAudioTypeStr = "Broadcast"; - mBassVolMap = new ConcurrentHashMap(); - } - - Map allKeys = getVolumeMap().getAll(); - SharedPreferences.Editor pref = getVolumeMap().edit(); - for (Map.Entry entry : allKeys.entrySet()) { - String key = entry.getKey(); - Object value = entry.getValue(); - BluetoothDevice d = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(key); - - if (value instanceof Integer && d.getBondState() == BluetoothDevice.BOND_BONDED) { - if (mAudioTypeStr.equals("Broadcast")) { - mBassVolMap.put(key, (Integer) value); - Log.w(TAG, "address " + key + " from the broadcast volume map volume :" + value); - } - } else { - Log.w(TAG, "Removing " + key + " from the " + mAudioTypeStr + " volume map"); - pref.remove(key); - } - } - pref.apply(); - } - - void updateDevice (BluetoothDevice device, int profile) { - mDevice = device; - mProfile = profile; - - mVolume = getSavedVolume(device); - Log.i (TAG, "New " + mAudioTypeStr + " device: " + mDevice + " Vol: " + mVolume); - } - - int getSavedVolume (BluetoothDevice device) { - int mSavedVolume; - SharedPreferences pref = getVolumeMap(); - mSavedVolume = pref.getInt(device.getAddress(), SAFE_VOL); - return mSavedVolume; - } - - void updateVolume (int volume) { - mVolume = volume; - } - - void updateVolume (BluetoothDevice device, int volume) { - if(mAudioTypeStr.equals("Broadcast")) { - Log.i(TAG, "updateVolume, device " + device + " volume: " + volume); - mBassVolMap.put(device.getAddress(), volume); - } - } - int getVolume(BluetoothDevice device) { - if(device == null) { - Log.e (TAG, "Null Device passed"); - return 7; - } - if(mAudioTypeStr.equals("Broadcast")) { - if(mBassVolMap.containsKey(device.getAddress())) { - return mBassVolMap.getOrDefault(device.getAddress(), 7); - } else { - int mSavedVolume = getSavedVolume(device); - mBassVolMap.put(device.getAddress(), mSavedVolume); - Log.i(TAG, "get saved volume, device " + device + " volume: " + mSavedVolume); - return mSavedVolume; - } - } - return 7; - } - private SharedPreferences getVolumeMap() { - return mContext.getSharedPreferences(mVolumeMap, Context.MODE_PRIVATE); - } - - public void saveVolume() { - if(mAudioTypeStr.equals("Broadcast")) { - saveBroadcastVolume(); - return; - } - - if(mDevice == null) { - Log.e (TAG, "saveVolume: No Device Active for " + mAudioTypeStr + ". Ignore"); - return; - } - - SharedPreferences.Editor pref = getVolumeMap().edit(); - pref.putInt(mDevice.getAddress(), mVolume); - pref.apply(); - Log.i (TAG, "Saved " + mAudioTypeStr + " Volume: " + mVolume + " for device: " + mDevice); - } - - public void saveBroadcastVolume() { - SharedPreferences.Editor pref = getVolumeMap().edit(); - for(Map.Entry itr : mBassVolMap.entrySet()) { - pref.putInt(itr.getKey(), itr.getValue()); - } - pref.apply(); - } - - public void saveVolume(BluetoothDevice device) { - if(device == null) { - Log.e (TAG, "Null Device passed"); - return; - } - if(mAudioTypeStr.equals("Broadcast")) { - int mVol = mBassVolMap.getOrDefault(device.getAddress(), 7); - SharedPreferences.Editor pref = getVolumeMap().edit(); - pref.putInt(device.getAddress(), mVol); - pref.apply(); - } - } - - void removeDevice(BluetoothDevice device) { - if(mAudioTypeStr.equals("Broadcast")) { - Log.i (TAG, "Remove device " + device + " from broadcast volume map "); - mBassVolMap.remove(device.getAddress()); - } - SharedPreferences.Editor pref = getVolumeMap().edit(); - pref.remove(device.getAddress()); - pref.apply(); - } - - void reset () { - Log.i (TAG, "Reset " + mAudioTypeStr + " Device: " + mDevice); - mDevice = null; - mVolume = SAFE_VOL; - mProfile = ApmConst.AudioProfiles.NONE; - } - } - - private class VolumeManagerReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if(action == null) - return; - - switch(action) { - case AudioManager.VOLUME_CHANGED_ACTION: - int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1); - int volumeValue = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0); - if(streamType == AudioManager.STREAM_BLUETOOTH_SCO) { - setCallVolume(intent); - } else { - updateMediaStreamVolume(volumeValue); - } - break; - - case BluetoothDevice.ACTION_BOND_STATE_CHANGED: - int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, - BluetoothDevice.ERROR); - BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - if(device == null) - return; - - if(state == BluetoothDevice.BOND_NONE) { - handleDeviceUnbond(device); - } - break; - - case BleBroadcastAudioScanAssistManager.ACTION_BROADCAST_SOURCE_INFO: - BleBroadcastSourceInfo sourceInfo = intent.getParcelableExtra( - BleBroadcastSourceInfo.EXTRA_SOURCE_INFO); - device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - - if (device == null || sourceInfo == null) { - Log.w (TAG, "Bluetooth Device or Source info is null"); - break; - } - - if (sourceInfo.getAudioSyncState() == - BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED) { - handleBroadcastAudioSynced(device); - } - break; - - case ACTION_SHUTDOWN: - case ACTION_POWER_OFF: - handleDeviceShutdown(); - break; - } - } - } -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/bassclient/BCService.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/bassclient/BCService.java deleted file mode 100644 index ebcbf81b541a79ee03421157f76918316f4aa71c..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/bassclient/BCService.java +++ /dev/null @@ -1,1691 +0,0 @@ -/* - * Copyright (c) 2020 The Linux Foundation. All rights reserved. - * - * 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. - */ - -package com.android.bluetooth.bc; - -import static android.Manifest.permission.BLUETOOTH_CONNECT; - - -import android.app.ActivityManager; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; -import android.bluetooth.IBluetoothSyncHelper; -import android.bluetooth.IBluetoothManager; -import android.bluetooth.IBleBroadcastAudioScanAssistCallback; -import android.bluetooth.BluetoothSyncHelper; -import android.bluetooth.BleBroadcastSourceInfo; -import android.bluetooth.BleBroadcastSourceChannel; -import android.bluetooth.BleBroadcastAudioScanAssistManager; -import android.bluetooth.BleBroadcastAudioScanAssistCallback; - -import android.content.Context; -import android.content.Intent; -import android.os.Binder; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.os.Process; -import android.os.RemoteException; -import android.os.HandlerThread; -import android.util.Log; -import android.os.ParcelUuid; -import android.bluetooth.BluetoothUuid; -import java.util.ArrayList; -import android.os.ServiceManager; - -import android.bluetooth.le.ScanResult; -import android.bluetooth.le.ScanRecord; -import android.bluetooth.le.PeriodicAdvertisingCallback; -import android.bluetooth.le.PeriodicAdvertisingManager; -import android.bluetooth.le.PeriodicAdvertisingReport; - -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothGattCallback; -import android.bluetooth.BluetoothGattCharacteristic; -import android.bluetooth.BluetoothGattDescriptor; - -import com.android.bluetooth.BluetoothMetricsProto; -import com.android.bluetooth.Utils; -import com.android.bluetooth.btservice.MetricsLogger; -import com.android.bluetooth.btservice.ProfileService; -import com.android.internal.annotations.VisibleForTesting; -import com.android.bluetooth.btservice.AdapterService; -//*_CSIP -//CSIP related imports -import com.android.bluetooth.groupclient.GroupService; -import android.bluetooth.BluetoothGroupCallback; -import android.bluetooth.DeviceGroup; -//_CSIP*/ - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.UUID; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.HashMap; -import java.util.Objects; -import java.util.NoSuchElementException; -import android.os.SystemProperties; - - -import com.android.internal.util.ArrayUtils; -/** @hide */ -public class BCService extends ProfileService { - private static final boolean DBG = true; - private static final String TAG = BCService.class.getSimpleName(); - - private static final ParcelUuid CAS_UUID = null;//ParcelUuid.fromString("000089FF-0000-1000-8000-00805F9B34FB"); - - public static final String BC_ID = "0000184F-0000-1000-8000-00805F9B34FB"; - public static final String BS_ID = "00001852-0000-1000-8000-00805F9B34FB"; - private static BCService sBCService; - private static final int MAX_BASS_CLIENT_STATE_MACHINES = 10; - private static final int MAX_BASS_CLIENT_CSET_MEMBERS = 10; - private final Map mStateMachines = - new HashMap<>(); - private HandlerThread mStateMachinesThread; - private final Map mSetManagers = - new HashMap<>(); - private HandlerThread mSetManagerThread; - - private AdapterService mAdapterService; - - private Map> mAppCallbackMap = - new HashMap>(); - - private BassUtils bassUtils = null; - public static final int INVALID_SYNC_HANDLE = -1; - public static final int INVALID_ADV_SID = -1; - public static final int INVALID_ADV_ADDRESS_TYPE = -1; - public static final int INVALID_ADV_INTERVAL = -1; - public static final int INVALID_BROADCAST_ID = -1; - private Map mActiveSourceMap; - - //*_CSIP - //CSET interfaces - private GroupService mSetCoordinator = GroupService.getGroupService(); - public int mCsipAppId = -1; - private int mQueuedOps = 0; - //_CSIP*/ - - /*Caching the PAresults from Broadcast source*/ - /*This is stored at service so that each device state machine can access - and use it as needed. Once the periodic sync in cancelled, this data will bre - removed to ensure stable data won't used*/ - /*broadcastSrcDevice, syncHandle*/ - private Map mSyncHandleMap; - /*syncHandle, parsed BaseData data*/ - private Map mSyncHandleVsBaseInfo; - /*bcastSrcDevice, corresponding PAResultsMap*/ - private Map mPAResultsMap; - public class PAResults { - public BluetoothDevice mDevice; - public int mAddressType; - public int mAdvSid; - public int mSyncHandle; - public byte metaDataLength; - public byte[] metaData; - public int mPAInterval; - public int mBroadcastId; - - PAResults(BluetoothDevice device, int addressType, - int syncHandle, int advSid, int paInterval, int broadcastId) { - mDevice = device; - mAddressType = addressType; - mAdvSid = advSid; - mSyncHandle = syncHandle; - mPAInterval = paInterval; - mBroadcastId = broadcastId; - } - - public void updateSyncHandle(int syncHandle) { - mSyncHandle = syncHandle; - } - - public void updateAdvSid(int advSid) { - mAdvSid = advSid; - } - - public void updateAddressType(int addressType) { - mAddressType = addressType; - } - - public void updateAdvInterval(int advInterval) { - mPAInterval = advInterval; - } - - public void updateBroadcastId(int broadcastId) { - mBroadcastId = broadcastId; - } - - public void print() { - log("-- PAResults --"); - log("mDevice:" + mDevice); - log("mAddressType:" + mAddressType); - log("mAdvSid:" + mAdvSid); - log("mSyncHandle:" + mSyncHandle); - log("mPAInterval:" + mPAInterval); - log("mBroadcastId:" + mBroadcastId); - log("-- END: PAResults --"); - } - }; - - public void updatePAResultsMap(BluetoothDevice device, int addressType, int syncHandle, int advSid, int advInterval, int bId) { - log("updatePAResultsMap: device: " + device); - log("updatePAResultsMap: syncHandle: " + syncHandle); - log("updatePAResultsMap: advSid: " + advSid); - log("updatePAResultsMap: addressType: " + addressType); - log("updatePAResultsMap: advInterval: " + advInterval); - log("updatePAResultsMap: broadcastId: " + bId); - log("mSyncHandleMap" + mSyncHandleMap); - log("mPAResultsMap" + mPAResultsMap); - //Cache the SyncHandle - if (mSyncHandleMap != null) { - Integer i = new Integer(syncHandle); - mSyncHandleMap.put(device, i); - } - if (mPAResultsMap != null) { - PAResults paRes = mPAResultsMap.get(device); - if (paRes == null) { - log("PAResmap: add >>>"); - paRes = new PAResults (device, addressType, - syncHandle, advSid, advInterval, bId); - if (paRes != null) { - paRes.print(); - mPAResultsMap.put(device, paRes); - } - } else { - if (advSid != INVALID_ADV_SID) { - paRes.updateAdvSid(advSid); - } - if (syncHandle != INVALID_SYNC_HANDLE) { - paRes.updateSyncHandle(syncHandle); - } - if (addressType != INVALID_ADV_ADDRESS_TYPE) { - paRes.updateAddressType(addressType); - } - if (advInterval != INVALID_ADV_INTERVAL) { - paRes.updateAdvInterval(advInterval); - } - if (bId != INVALID_BROADCAST_ID) { - paRes.updateBroadcastId(bId); - } - log("PAResmap: update >>>"); - paRes.print(); - mPAResultsMap.replace(device, paRes); - } - } - log(">>mPAResultsMap" + mPAResultsMap); - } - - public PAResults getPAResults(BluetoothDevice device) { - PAResults res = null; - if (mPAResultsMap != null) { - res = mPAResultsMap.get(device); - } else { - Log.e(TAG, "getPAResults: mPAResultsMap is null"); - } - return res; - } - public PAResults clearPAResults(BluetoothDevice device) { - PAResults res = null; - if (mPAResultsMap != null) { - res = mPAResultsMap.remove(device); - } else { - Log.e(TAG, "getPAResults: mPAResultsMap is null"); - } - return res; - } - - public void updateBASE(int syncHandlemap, BaseData base) { - if (mSyncHandleVsBaseInfo != null) { - log("updateBASE : mSyncHandleVsBaseInfo>>"); - mSyncHandleVsBaseInfo.put(syncHandlemap, base); - } else { - Log.e(TAG, "updateBASE: mSyncHandleVsBaseInfo is null"); - } - } - - public BaseData getBASE(int syncHandlemap) { - BaseData base = null; - if (mSyncHandleVsBaseInfo != null) { - log("getBASE : syncHandlemap::" + syncHandlemap); - base = mSyncHandleVsBaseInfo.get(syncHandlemap); - } else { - Log.e(TAG, "getBASE: mSyncHandleVsBaseInfo is null"); - } - log("getBASE returns" + base); - return base; - } - - public void clearBASE(int syncHandlemap) { - if (mSyncHandleVsBaseInfo != null) { - log("clearBASE : mSyncHandleVsBaseInfo>>"); - mSyncHandleVsBaseInfo.remove(syncHandlemap); - } else { - Log.e(TAG, "updateBASE: mSyncHandleVsBaseInfo is null"); - } - } - - public void setActiveSyncedSource(BluetoothDevice scanDelegator, BluetoothDevice sourceDevice) { - log("setActiveSyncedSource: scanDelegator" + scanDelegator + ":: sourceDevice:" + sourceDevice); - if (sourceDevice == null) { - mActiveSourceMap.remove(scanDelegator); - } else { - mActiveSourceMap.put(scanDelegator, sourceDevice); - } - } - - public BluetoothDevice getActiveSyncedSource(BluetoothDevice scanDelegator) { - BluetoothDevice currentSource = mActiveSourceMap.get(scanDelegator); - log("getActiveSyncedSource: scanDelegator" + scanDelegator + "returning " + currentSource); - return currentSource; - } - - @Override - protected IProfileServiceBinder initBinder() { - return new BluetoothSyncHelperBinder(this); - } - - //*_CSIP - private BluetoothGroupCallback mBluetoothGroupCallback = new BluetoothGroupCallback() { - public void onGroupClientAppRegistered(int status, int appId) { - log("onCsipAppRegistered:" + status + "appId: " + appId); - if (status == 0) { - mCsipAppId = appId; - } else { - Log.e(TAG, "Csip registeration failed, status:" + status); - } - } - - public void onConnectionStateChanged (int state, BluetoothDevice device) { - log("onConnectionStateChanged: Device: " + device + "state: " + state); - //notify the statemachine about CSIP connection - synchronized (mStateMachines) { - BassClientStateMachine stateMachine = getOrCreateStateMachine(device); - Message m = stateMachine.obtainMessage(BassClientStateMachine.CSIP_CONNECTION_STATE_CHANGED); - m.obj = state; - stateMachine.sendMessage(m); - } - } - - public void onNewGroupFound (int setId, BluetoothDevice device, UUID uuid) { } - public void onGroupDiscoveryStatusChanged (int setId, int status, int reason) { } - public void onGroupDeviceFound (int setId, BluetoothDevice device) { } - public void onExclusiveAccessChanged (int setId, int value, int status, List devices) { - log("onLockStatusChanged: setId" + setId + devices + "status:" + status); - BassCsetManager setMgr = null; - setMgr = getOrCreateCSetManager(setId, null); - if (setMgr == null) { - return; - } - log ("sending Lock status to setId:" + setId); - Message m = setMgr.obtainMessage(BassCsetManager.LOCK_STATE_CHANGED); - m.obj = devices; - m.arg1 = value; - setMgr.sendMessage(m); - } - public void onExclusiveAccessStatusFetched (int setId, int lockStatus) { } - public void onExclusiveAccessAvailable (int setId, BluetoothDevice device) { } - }; - //_CSIP*/ - - @Override - protected boolean start() { - if (DBG) { - Log.d(TAG, "start()"); - } - mAdapterService = Objects.requireNonNull(AdapterService.getAdapterService(), - "AdapterService cannot be null when BCService starts"); - mStateMachines.clear(); - mStateMachinesThread = new HandlerThread("BCService.StateMachines"); - mStateMachinesThread.start(); - - mSetManagers.clear(); - mSetManagerThread = new HandlerThread("BCService.SetManagers"); - mSetManagerThread.start(); - - setBCService(this); - bassUtils = new BassUtils(this); - //Saving PSync stuff for future addition - mSyncHandleMap = new HashMap(); - mPAResultsMap = new HashMap(); - mSyncHandleVsBaseInfo = new HashMap(); - mActiveSourceMap = new HashMap(); - - //*_CSIP - //CSET initialization - mSetCoordinator = GroupService.getGroupService(); - if (mSetCoordinator != null) { - mSetCoordinator.registerGroupClientModule(mBluetoothGroupCallback); - } - //_CSIP*/ - /*_PACS - mPacsClientService = PacsClientService.getPacsClientService(); - _PACS*/ - - ///*_GAP - //GAP registeration for Bass UUID notification - if (mAdapterService != null) { - log("register for BASS UUID notif"); - ParcelUuid bassUuid = new ParcelUuid(BassClientStateMachine.BASS_UUID); - mAdapterService.registerUuidSrvcDisc(bassUuid); - } - //_GAP*/ - return true; - } - - @Override - protected boolean stop() { - if (DBG) { - Log.d(TAG, "stop()"); - } - - synchronized (mStateMachines) { - for (BassClientStateMachine sm : mStateMachines.values()) { - sm.doQuit(); - sm.cleanup(); - } - mStateMachines.clear(); - } - - if (mStateMachinesThread != null) { - mStateMachinesThread.quitSafely(); - mStateMachinesThread = null; - } - - if (mSetManagerThread != null) { - mSetManagerThread.quitSafely(); - mSetManagerThread = null; - } - - setBCService(null); - - if (mAppCallbackMap != null) { - mAppCallbackMap.clear(); - mAppCallbackMap = null; - } - - if (mSyncHandleMap != null) { - mSyncHandleMap.clear(); - mSyncHandleMap = null; - } - - if (mActiveSourceMap != null) { - mActiveSourceMap.clear(); - mActiveSourceMap = null; - } - //*_CSIP - if (mSetCoordinator != null && mCsipAppId != -1) { - //mSetCoordinator.unregisterGroupClientModule(mCsipAppId); - } - //_CSIP*/ - return true; - } - - @Override - public boolean onUnbind(Intent intent) { - Log.d(TAG, "Need to unregister app"); - //unregisterApp(); - return super.onUnbind(intent); - } - - /** - * Get the BCService instance - * @return BCService instance - */ - public static synchronized BCService getBCService() { - if (sBCService == null) { - Log.w(TAG, "getBCService(): service is NULL"); - return null; - } - - if (!sBCService.isAvailable()) { - Log.w(TAG, "getBCService(): service is not available"); - return null; - } - return sBCService; - } - - public BassUtils getBassUtils() { - return bassUtils; - } - - public BluetoothDevice getDeviceForSyncHandle(int syncHandle) { - BluetoothDevice dev = null; - if (mSyncHandleMap != null) { - for (Map.Entry entry : mSyncHandleMap.entrySet()) { - Integer value = entry.getValue(); - if (value == syncHandle) { - dev = entry.getKey(); - } - } - } - return dev; - } - - private static synchronized void setBCService(BCService instance) { - if (DBG) { - Log.d(TAG, "setBCService(): set to: " + instance); - } - sBCService = instance; - } - - /** - * Connects the bass profile to the passed in device - * - * @param device is the device with which we will connect the Bass profile - * @return true if BAss profile successfully connected, false otherwise - */ - public boolean connect(BluetoothDevice device) { - if (DBG) { - Log.d(TAG, "connect(): " + device); - } - if (device == null) { - return false; - } - - if (getConnectionPolicy(device) == BluetoothProfile.CONNECTION_POLICY_UNKNOWN) { - return false; - } - synchronized (mStateMachines) { - BassClientStateMachine stateMachine = getOrCreateStateMachine(device); - - stateMachine.sendMessage(BassClientStateMachine.CONNECT); - } - return true; - } - - /** - * Disconnects Bassclient profile for the passed in device - * - * @param device is the device with which we want to disconnected the BAss client profile - * @return true if Bass client profile successfully disconnected, false otherwise - */ - public boolean disconnect(BluetoothDevice device) { - - if (DBG) { - Log.d(TAG, "disconnect(): " + device); - } - if (device == null) { - return false; - } - - synchronized (mStateMachines) { - BassClientStateMachine stateMachine = getOrCreateStateMachine(device); - - stateMachine.sendMessage(BassClientStateMachine.DISCONNECT); - } - return true; - } - - List getConnectedDevices() { - - synchronized (mStateMachines) { - List devices = new ArrayList<>(); - for (BassClientStateMachine sm : mStateMachines.values()) { - if (sm.isConnected()) { - devices.add(sm.getDevice()); - } - } - log("getConnectedDevices: " + devices); - return devices; - } - } - - /** - * Check whether 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 okToConnect(BluetoothDevice device) { - // Check if this is an incoming connection in Quiet mode. - if (mAdapterService.isQuietModeEnabled()) { - Log.e(TAG, "okToConnect: cannot connect to " + device + " : quiet mode enabled"); - return false; - } - // Check connection policy and accept or reject the connection. - int connectionPolicy = getConnectionPolicy(device); - 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) { - Log.w(TAG, "okToConnect: return false, bondState=" + bondState); - return false; - } else if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_UNKNOWN - && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - // Otherwise, reject the connection if connectionPolicy is not valid. - Log.w(TAG, "okToConnect: return false, connectionPolicy=" + connectionPolicy); - return false; - } - return true; - } - - List getDevicesMatchingConnectionStates(int[] states) { - - ArrayList devices = new ArrayList<>(); - if (states == null) { - return devices; - } - final BluetoothDevice[] bondedDevices = mAdapterService.getBondedDevices(); - if (bondedDevices == null) { - return devices; - } - synchronized (mStateMachines) { - for (BluetoothDevice device : bondedDevices) { - final ParcelUuid[] featureUuids = device.getUuids(); - if (!ArrayUtils.contains(featureUuids, new ParcelUuid(BassClientStateMachine.BASS_UUID))) { - continue; - } - int connectionState = BluetoothProfile.STATE_DISCONNECTED; - BassClientStateMachine sm = getOrCreateStateMachine(device); - if (sm != null) { - connectionState = sm.getConnectionState(); - } - for (int state : states) { - if (connectionState == state) { - devices.add(device); - break; - } - } - } - return devices; - } - } - - public int getConnectionState(BluetoothDevice device) { - synchronized (mStateMachines) { - BassClientStateMachine sm = getOrCreateStateMachine(device); - if (sm == null) { - log("getConnectionState returns STATE_DISC"); - return BluetoothProfile.STATE_DISCONNECTED; - } - return sm.getConnectionState(); - } - } - - /** - * Set the connectionPolicy of the Hearing Aid profile. - * - * @param device the remote device - * @param connectionPolicy the connection policy of the profile - * @return true on success, otherwise false - */ - public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) { - - if (DBG) { - Log.d(TAG, "Saved connectionPolicy " + device + " = " + connectionPolicy); - } - boolean setSuccessfully; - setSuccessfully = mAdapterService.getDatabase() - .setProfileConnectionPolicy(device, BluetoothProfile.BC_PROFILE, connectionPolicy); - if (setSuccessfully && connectionPolicy == BluetoothProfile.CONNECTION_POLICY_ALLOWED) { - connect(device); - } else if (setSuccessfully - && connectionPolicy == BluetoothProfile.CONNECTION_POLICY_FORBIDDEN) { - disconnect(device); - } - return setSuccessfully; - } - - /** - * Get the connection policy of the profile. - * - *

The connection policy can be any of: - * {@link BluetoothProfile#CONNECTION_POLICY_ALLOWED}, - * {@link BluetoothProfile#CONNECTION_POLICY_FORBIDDEN}, - * {@link BluetoothProfile#CONNECTION_POLICY_UNKNOWN} - * - * @param device Bluetooth device - * @return connection policy of the device - * @hide - */ - public int getConnectionPolicy(BluetoothDevice device) { - - return mAdapterService.getDatabase() - .getProfileConnectionPolicy(device, BluetoothProfile.BC_PROFILE); - } - - public void sendBroadcastSourceSelectedCallback(BluetoothDevice device, List bChannels, int status){ - ArrayList cbs = mAppCallbackMap.get(device); - if (cbs == null) { - Log.e(TAG, "no App callback for this device" + device); - return; - } - for (IBleBroadcastAudioScanAssistCallback cb : cbs) { - try { - cb.onBleBroadcastAudioSourceSelected(device, status, bChannels); - } catch (RemoteException e) { - Log.e(TAG, "Exception while calling sendBroadcastSourceSelectedCallback"); - } - } - } - - public void sendAddBroadcastSourceCallback(BluetoothDevice device, byte srcId, int status){ - ArrayList cbs = mAppCallbackMap.get(device); - if (cbs == null) { - Log.e(TAG, "no App callback for this device" + device); - return; - } - for (IBleBroadcastAudioScanAssistCallback cb : cbs) { - try { - cb.onBleBroadcastAudioSourceAdded(device, srcId, status); - } catch (RemoteException e) { - Log.e(TAG, "Exception while calling onBleBroadcastAudioSourceAdded"); - } - } - } - - public void sendUpdateBroadcastSourceCallback(BluetoothDevice device, byte sourceId, int status){ - ArrayList cbs = mAppCallbackMap.get(device); - if (cbs == null) { - Log.e(TAG, "no App callback for this device" + device); - return; - } - - for (IBleBroadcastAudioScanAssistCallback cb : cbs) { - try { - cb.onBleBroadcastAudioSourceUpdated(device, sourceId, status); - } catch (RemoteException e) { - Log.e(TAG, "Exception while calling onBleBroadcastAudioSourceUpdated"); - } - } - } - public void sendRemoveBroadcastSourceCallback(BluetoothDevice device, byte sourceId, int status){ - ArrayList cbs = mAppCallbackMap.get(device); - if (cbs == null) { - Log.e(TAG, "no App callback for this device" + device); - return; - } - - for (IBleBroadcastAudioScanAssistCallback cb : cbs) { - try { - cb.onBleBroadcastAudioSourceRemoved(device, sourceId, status); - } catch (RemoteException e) { - Log.e(TAG, "Exception while calling onBleBroadcastAudioSourceRemoved"); - } - } - } - public void sendSetBroadcastPINupdatedCallback(BluetoothDevice device, byte sourceId, int status){ - ArrayList cbs = mAppCallbackMap.get(device); - if (cbs == null) { - Log.e(TAG, "no App callback for this device" + device); - return; - } - - for (IBleBroadcastAudioScanAssistCallback cb : cbs) { - try { - cb.onBleBroadcastPinUpdated(device, sourceId, status); - } catch (RemoteException e) { - Log.e(TAG, "Exception while calling onBleBroadcastPinUpdated"); - } - } - } - - public void registerAppCallback (BluetoothDevice device, IBleBroadcastAudioScanAssistCallback cb) { - - Log.i(TAG, "registerAppCallback" + device); - - ArrayList cbs = mAppCallbackMap.get(device); - if (cbs == null) { - Log.i(TAG, "registerAppCallback: entry exists"); - cbs = new ArrayList(); - } - cbs.add(cb); - mAppCallbackMap.put(device, cbs); - return; - } - - public void unregisterAppCallback (BluetoothDevice device, IBleBroadcastAudioScanAssistCallback cb) { - - Log.i(TAG, "unregisterAppCallback" + device); - - ArrayList cbs = mAppCallbackMap.get(device); - if (cbs == null) { - Log.i(TAG, "unregisterAppCallback: cb list is null"); - return; - } else { - boolean ret = cbs.remove(cb); - Log.i(TAG, "unregisterAppCallback: ret value of removal from list:" + ret); - } - if (cbs.size() != 0) { - mAppCallbackMap.replace(device, cbs); - } else { - Log.i(TAG, "unregisterAppCallback: Remove the cmplete entry"); - mAppCallbackMap.remove(device); - } - return; - } - - public boolean searchforLeAudioBroadcasters (BluetoothDevice device) { - - Log.i(TAG, "searchforLeAudioBroadcasters on behalf of" + device); - ArrayList cbs = mAppCallbackMap.get(device); - if (cbs == null) { - Log.e(TAG, "no App callback for this device" + device); - return false; - } - boolean ret = false; - if (bassUtils != null) { - ret = bassUtils.searchforLeAudioBroadcasters(device, cbs); - } else { - Log.e(TAG, "searchforLeAudioBroadcasters :Null Bass Util Handle" + device); - ret = false; - } - return ret; - } - - public boolean stopSearchforLeAudioBroadcasters (BluetoothDevice device) { - - Log.i(TAG, "stopsearchforLeAudioBroadcasters on behalf of" + device); - ArrayList cbs = mAppCallbackMap.get(device); - if (cbs == null) { - Log.e(TAG, "no App callback for this device" + device); - } - boolean ret = false; - if (bassUtils != null) { - ret = bassUtils.stopSearchforLeAudioBroadcasters(device, cbs); - } else { - Log.e(TAG, "stopsearchforLeAudioBroadcasters :Null Bass Util Handle" + device); - ret = false; - } - return ret; - } - - public boolean selectBroadcastSource (BluetoothDevice device, ScanResult scanRes, boolean isGroupOp, boolean auto) { - - Log.i(TAG, "selectBroadcastSource for " + device + "isGroupOp:" + isGroupOp); - Log.i(TAG, "ScanResult " + scanRes); - - if (scanRes == null) { - Log.e(TAG, "selectBroadcastSource: null Scan results"); - return false; - } - List listOfDevices = new ArrayList(); - listOfDevices.add(device); - if (isRoomForBroadcastSourceAddition(listOfDevices) == false) { - sendBroadcastSourceSelectedCallback(device, null, - BleBroadcastAudioScanAssistCallback.BASS_STATUS_NO_EMPTY_SLOT); - return false; - } - //dummy BleSourceInfo from scanRes - BleBroadcastSourceInfo scanResSI = new BleBroadcastSourceInfo (scanRes.getDevice(), - BassClientStateMachine.INVALID_SRC_ID, - (byte)scanRes.getAdvertisingSid(), - BleBroadcastSourceInfo.BROADCASTER_ID_INVALID, - scanRes.getAddressType(), - BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_INVALID, - BleBroadcastSourceInfo.BROADCAST_ASSIST_ENC_STATE_INVALID, - null, - (byte)0, - BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED, - null, - null); - if (isValidBroadcastSourceAddition(listOfDevices, scanResSI) == false) { - sendBroadcastSourceSelectedCallback(device, - null, BleBroadcastAudioScanAssistCallback.BASS_STATUS_DUPLICATE_ADDITION); - return false; - } - startScanOffloadInternal(device, isGroupOp); - synchronized (mStateMachines) { - BassClientStateMachine sm = getOrCreateStateMachine(device); - if (sm == null) { - return false; - } - Message m = sm.obtainMessage(BassClientStateMachine.SELECT_BCAST_SOURCE); - m.obj = scanRes; - if (auto) { - m.arg1 = sm.AUTO; - } else { - m.arg1 = sm.USER; - } - if (isGroupOp) { - m.arg2 = sm.GROUP_OP; - } else { - m.arg2 = sm.NON_GROUP_OP; - } - sm.sendMessage(m); - } - return true; - } - - public synchronized void notifyOperationCompletion(BluetoothDevice device, int pendingOperation) { - log("notifyOperationCompletion: " + device + "pendingOperation: " + - BassClientStateMachine.messageWhatToString(pendingOperation)); - //synchronized (mStateMachines) { - switch (pendingOperation) { - case BassClientStateMachine.START_SCAN_OFFLOAD: - case BassClientStateMachine.STOP_SCAN_OFFLOAD: - case BassClientStateMachine.ADD_BCAST_SOURCE: - case BassClientStateMachine.UPDATE_BCAST_SOURCE: - case BassClientStateMachine.REMOVE_BCAST_SOURCE: - case BassClientStateMachine.SET_BCAST_CODE: - if (mQueuedOps > 0) { - mQueuedOps = mQueuedOps - 1; - } else { - log("not a queued op, Internal op"); - return; - } - break; - default: - { - log("notifyOperationCompletion: unhandled case"); - return; - } - } - //} - if (mQueuedOps == 0) { - log("notifyOperationCompletion: all ops are done!"); - //trigger unlock with last device - triggerUnlockforCSet(device); - } - - } - - public synchronized boolean startScanOffload (BluetoothDevice masterDevice, List devices) { - - Log.i(TAG, "startScanOffload for " + devices); - for (BluetoothDevice dev : devices) { - BassClientStateMachine stateMachine = getOrCreateStateMachine(dev); - if (stateMachine == null) { - continue; - } - stateMachine.sendMessage(BassClientStateMachine.START_SCAN_OFFLOAD); - mQueuedOps = mQueuedOps + 1; - } - return true; - } - - public synchronized boolean stopScanOffload (BluetoothDevice masterDevice, List devices) { - - Log.i(TAG, "stopScanOffload for " + devices); - for (BluetoothDevice dev : devices) { - BassClientStateMachine stateMachine = getOrCreateStateMachine(dev); - if (stateMachine == null) { - continue; - } - stateMachine.sendMessage(BassClientStateMachine.STOP_SCAN_OFFLOAD); - mQueuedOps = mQueuedOps + 1; - } - - return true; - } - - public boolean isLocalBroadcasting() { - return bassUtils.isLocalLEAudioBroadcasting(); - } - - private boolean isValidBroadcastSourceAddition(List devices, - BleBroadcastSourceInfo srcInfo) { - boolean ret = true; - - //run through all the device, if it is not valid - //to even one device to add this source, return failure - for (BluetoothDevice dev : devices) { - List currentSourceInfos = - getAllBroadcastSourceInformation(dev); - if (currentSourceInfos == null) { - log("currentSourceInfos is null for " + dev); - continue; - } - for (int i=0; i devices) { - boolean isRoomAvail = false; - - //run through all the device, if it is not valid - //to even one device to add this source, return failure - for (BluetoothDevice dev : devices) { - isRoomAvail = false; - List currentSourceInfos = - getAllBroadcastSourceInformation(dev); - for (int i=0; i devices, BleBroadcastSourceInfo srcInfo - ) { - - Log.i(TAG, "addBroadcastSource for " + devices + - "SourceInfo " + srcInfo); - if (srcInfo == null) { - Log.e(TAG, "addBroadcastSource: null SrcInfo"); - return false; - } - if (isRoomForBroadcastSourceAddition(devices) == false) { - sendAddBroadcastSourceCallback(masterDevice, - BassClientStateMachine.INVALID_SRC_ID, BleBroadcastAudioScanAssistCallback.BASS_STATUS_NO_EMPTY_SLOT); - triggerUnlockforCSet(masterDevice); - return false; - } - - if (isValidBroadcastSourceAddition(devices, srcInfo) == false) { - sendAddBroadcastSourceCallback(masterDevice, - BassClientStateMachine.INVALID_SRC_ID, BleBroadcastAudioScanAssistCallback.BASS_STATUS_DUPLICATE_ADDITION); - triggerUnlockforCSet(masterDevice); - return false; - } - for (BluetoothDevice dev : devices) { - BassClientStateMachine stateMachine = getOrCreateStateMachine(dev); - if (stateMachine == null) { - Log.w(TAG, "addBroadcastSource: device seem to be not avaiable, proceed"); - continue; - } - Message m = stateMachine.obtainMessage(BassClientStateMachine.ADD_BCAST_SOURCE); - m.obj = srcInfo; - stateMachine.sendMessage(m); - mQueuedOps = mQueuedOps + 1; - } - return true; - } - - private byte getSrcIdForCSMember(BluetoothDevice masterDevice, BluetoothDevice memberDevice, byte masterSrcId) { - byte targetSrcId = -1; - List masterSrcInfos = getAllBroadcastSourceInformation(masterDevice); - List memberSrcInfos = getAllBroadcastSourceInformation(memberDevice); - if (masterSrcInfos == null || masterSrcInfos.size() == 0 || - memberSrcInfos == null || memberSrcInfos.size() == 0) { - Log.e(TAG, "master or member source Infos not available"); - return targetSrcId; - } - if (masterDevice.equals(memberDevice)) { - log("master: " + masterDevice + "member:memberDevice"); - return masterSrcId; - } - BluetoothDevice masterSrcDevice = null; - for (int i=0; i devices, - BleBroadcastSourceInfo srcInfo - ) { - - int status = BleBroadcastAudioScanAssistCallback.BASS_STATUS_INVALID_SOURCE_ID; - Log.i(TAG, "updateBroadcastSource for " + devices + - "masterDevice " + masterDevice + - "SourceInfo " + srcInfo); - - if (srcInfo == null) { - Log.e(TAG, "updateBroadcastSource: null SrcInfo"); - return false; - } - - for (BluetoothDevice dev : devices) { - if (getSrcIdForCSMember(masterDevice, dev, srcInfo.getSourceId()) == -1) { - if (devices.size() > 1) { - status = BleBroadcastAudioScanAssistCallback.BASS_STATUS_INVALID_GROUP_OP; - } else { - status = BleBroadcastAudioScanAssistCallback.BASS_STATUS_INVALID_SOURCE_ID; - } - sendRemoveBroadcastSourceCallback(masterDevice, BassClientStateMachine.INVALID_SRC_ID, - status); - triggerUnlockforCSet(masterDevice); - return false; - } - } - - for (BluetoothDevice dev : devices) { - BassClientStateMachine stateMachine = getOrCreateStateMachine(dev); - if (stateMachine == null) { - Log.w(TAG, "updateBroadcastSource: Device seem to be not avaiable"); - continue; - } - byte targetSrcId = getSrcIdForCSMember(masterDevice, dev, srcInfo.getSourceId()); - srcInfo.setSourceId(targetSrcId); - - Message m = stateMachine.obtainMessage(BassClientStateMachine.UPDATE_BCAST_SOURCE); - m.obj = srcInfo; - m.arg1 = stateMachine.USER; - stateMachine.sendMessage(m); - mQueuedOps = mQueuedOps + 1; - } - - return true; - } - - public synchronized boolean setBroadcastCode (BluetoothDevice masterDevice, List devices, - BleBroadcastSourceInfo srcInfo - ) { - - int status = BleBroadcastAudioScanAssistCallback.BASS_STATUS_INVALID_SOURCE_ID; - Log.i(TAG, "setBroadcastCode for " + devices + - "masterDevice" + masterDevice + - "Broadcast PIN" + srcInfo.getBroadcastCode()); - - if (srcInfo == null) { - Log.e(TAG, "setBroadcastCode: null SrcInfo"); - return false; - } - - for (BluetoothDevice dev : devices) { - if (getSrcIdForCSMember(masterDevice, dev, srcInfo.getSourceId()) == -1) { - if (devices.size() > 1) { - status = BleBroadcastAudioScanAssistCallback.BASS_STATUS_INVALID_GROUP_OP; - } else { - status = BleBroadcastAudioScanAssistCallback.BASS_STATUS_INVALID_SOURCE_ID; - } - sendRemoveBroadcastSourceCallback(masterDevice, BassClientStateMachine.INVALID_SRC_ID, - status); - triggerUnlockforCSet(masterDevice); - return false; - } - } - - for (BluetoothDevice dev : devices) { - BassClientStateMachine stateMachine = getOrCreateStateMachine(dev); - if (stateMachine == null) { - Log.w(TAG, "setBroadcastCode: Device seem to be not avaiable"); - continue; - } - - byte targetSrcId = getSrcIdForCSMember(masterDevice, dev, srcInfo.getSourceId()); - srcInfo.setSourceId(targetSrcId); - - Message m = stateMachine.obtainMessage(BassClientStateMachine.SET_BCAST_CODE); - m.obj = srcInfo; - m.arg1 = stateMachine.FRESH; - stateMachine.sendMessage(m); - mQueuedOps = mQueuedOps + 1; - } - - return true; - } - - public synchronized boolean removeBroadcastSource (BluetoothDevice masterDevice, List devices, - byte sourceId - ) { - - int status = BleBroadcastAudioScanAssistCallback.BASS_STATUS_INVALID_SOURCE_ID; - Log.i(TAG, "removeBroadcastSource for " + devices + - "masterDevice " + masterDevice + - "removeBroadcastSource: sourceId:" + sourceId); - - if (sourceId == BassClientStateMachine.INVALID_SRC_ID) { - Log.e(TAG, "removeBroadcastSource: Invalid source Id"); - return false; - } - - - for (BluetoothDevice dev : devices) { - if (getSrcIdForCSMember(masterDevice, dev, sourceId) == -1) { - if (devices.size() > 1) { - status = BleBroadcastAudioScanAssistCallback.BASS_STATUS_INVALID_GROUP_OP; - } else { - status = BleBroadcastAudioScanAssistCallback.BASS_STATUS_INVALID_SOURCE_ID; - } - sendRemoveBroadcastSourceCallback(masterDevice, BassClientStateMachine.INVALID_SRC_ID, - status); - triggerUnlockforCSet(masterDevice); - return false; - } - } - - for (BluetoothDevice dev : devices) { - BassClientStateMachine stateMachine = getOrCreateStateMachine(dev); - if (stateMachine == null) { - Log.w(TAG, "setBroadcastCode: Device seem to be not avaiable"); - continue; - } - - Message m = stateMachine.obtainMessage(BassClientStateMachine.REMOVE_BCAST_SOURCE); - m.arg1 = getSrcIdForCSMember(masterDevice, dev, sourceId); - log("removeBroadcastSource: send message to SM " + dev); - stateMachine.sendMessage(m); - mQueuedOps = mQueuedOps + 1; - } - - return true; - } - - void triggerUnlockforCSet (BluetoothDevice device) { - //get setId - int setId = getCsetId(device); - BassCsetManager setMgr = getOrCreateCSetManager(setId, device); - if (setMgr == null) { - Log.e(TAG, "triggerUnlockforCSet: setMgr is NULL"); - return; - } - //Sending UnLock to - log ("sending Unlock to device:" + device); - Message m = setMgr.obtainMessage(BassCsetManager.UNLOCK); - setMgr.sendMessage(m); - } - public List getAllBroadcastSourceInformation (BluetoothDevice device - ) { - Log.i(TAG, "getAllBroadcastSourceInformation for " + device); - synchronized (mStateMachines) { - BassClientStateMachine sm = getOrCreateStateMachine(device); - if (sm == null) { - return null; - } - return sm.getAllBroadcastSourceInformation(); - } - } - - private BassClientStateMachine getOrCreateStateMachine(BluetoothDevice device) { - if (device == null) { - Log.e(TAG, "getOrCreateStateMachine failed: device cannot be null"); - return null; - } - synchronized (mStateMachines) { - BassClientStateMachine sm = mStateMachines.get(device); - if (sm != null) { - return sm; - } - // Limit the maximum number of state machines to avoid DoS attack - if (mStateMachines.size() >= MAX_BASS_CLIENT_STATE_MACHINES) { - Log.e(TAG, "Maximum number of Bassclient state machines reached: " - + MAX_BASS_CLIENT_STATE_MACHINES); - return null; - } - if (DBG) { - Log.d(TAG, "Creating a new state machine for " + device); - } - sm = BassClientStateMachine.make(device, this, - mStateMachinesThread.getLooper()); - mStateMachines.put(device, sm); - return sm; - } - } - - private BassCsetManager getOrCreateCSetManager(int setId, BluetoothDevice masterDevice) { - if (setId == -1) { - Log.e(TAG, "getOrCreateCSetManager failed: invalid setId"); - return null; - } - synchronized (mSetManagers) { - BassCsetManager sm = mSetManagers.get(setId); - log("getOrCreateCSetManager: hashmap Entry:" + sm); - if (sm != null) { - return sm; - } - // Limit the maximum number of set manager state machines - if (mStateMachines.size() >= MAX_BASS_CLIENT_CSET_MEMBERS) { - Log.e(TAG, "Maximum number of Bassclient cset members reached: " - + MAX_BASS_CLIENT_CSET_MEMBERS); - return null; - } - if (DBG) { - Log.d(TAG, "Creating a new set Manager for " + setId); - } - sm = BassCsetManager.make(setId, masterDevice, this, - mSetManagerThread.getLooper()); - mSetManagers.put(setId, sm); - return sm; - } - } - - public boolean isLockSupportAvailable(BluetoothDevice device) { - boolean isLockAvail = false; - boolean forceNoCsip = SystemProperties.getBoolean("persist.vendor.service.bt.forceNoCsip", false); - if (forceNoCsip) { - log("forceNoCsip is set"); - return isLockAvail; - } - //*_CSIP - isLockAvail = mAdapterService.isGroupExclAccessSupport(device); - //_CSIP*/ - - log("isLockSupportAvailable for:" + device + "returns " + isLockAvail); - return isLockAvail; - } - - private int getCsetId(BluetoothDevice device) { - int setId = 1; - //*_CSIP - setId = mSetCoordinator.getRemoteDeviceGroupId(device, CAS_UUID); - //_CSIP*/ - log("getCsetId return:" + setId); - return setId; - } - public boolean stopScanOffloadInternal (BluetoothDevice device, boolean isGroupOp) { - boolean ret = false; - log("stopScanOffloadInternal: device: " + device - + "isGroupOp" + isGroupOp); - /* Even If the request is for Grouoop, If Lock support not avaiable - * for that device, go ahead and treat this as single device operation - */ - if (isGroupOp && isLockSupportAvailable(device) == true) { - int setId = getCsetId(device); - synchronized (mSetManagers) { - BassCsetManager setMgr = getOrCreateCSetManager(setId, device); - if (setMgr == null) { - return false; - } - Message m = setMgr.obtainMessage(BassCsetManager.BASS_GRP_STOP_SCAN_OFFLOAD); - setMgr.sendMessage(m); - //queue req and return true - ret = true; - } - } else { - List listOfDevices = new ArrayList(); - listOfDevices.add(device); - ret = stopScanOffload(device, listOfDevices); - } - return ret; - } - - public boolean startScanOffloadInternal (BluetoothDevice device, boolean isGroupOp) { - boolean ret = false; - log("startScanOffloadInternal: device: " + device - + "isGroupOp" + isGroupOp); - /* Even If the request is for Grouoop, If Lock support not avaiable - * for that device, go ahead and treat this as single device operation - */ - if (isGroupOp&& isLockSupportAvailable(device) == true) { - int setId = getCsetId(device); - synchronized (mSetManagers) { - BassCsetManager setMgr = getOrCreateCSetManager(setId, device); - if (setMgr == null) { - return false; - } - Message m = setMgr.obtainMessage(BassCsetManager.BASS_GRP_START_SCAN_OFFLOAD); - setMgr.sendMessage(m); - //queue req and return true - ret = true; - } - } else { - List listOfDevices = new ArrayList(); - listOfDevices.add(device); - ret = startScanOffload(device, listOfDevices); - } - return ret; - } - - public boolean addBroadcastSourceInternal (BluetoothDevice device, BleBroadcastSourceInfo srcInfo, - boolean isGroupOp) { - boolean ret = false; - log("addBroadcastSourceInternal: device: " + device - + "srcInfo" + srcInfo - + "isGroupOp" + isGroupOp); - /* Even If the request is for Group, If Lock support not avaiable - * for that device, go ahead and treat this as single device operation - */ - if (isGroupOp && isLockSupportAvailable(device) == true) { - int setId = getCsetId(device); - synchronized (mSetManagers) { - BassCsetManager setMgr = getOrCreateCSetManager(setId, device); - if (setMgr == null) { - return false; - } - Message m = setMgr.obtainMessage(BassCsetManager.BASS_GRP_ADD_BCAST_SOURCE); - m.obj = srcInfo; - setMgr.sendMessage(m); - //queue req and return true - ret = true; - } - } else { - List listOfDevices = new ArrayList(); - listOfDevices.add(device); - ret = addBroadcastSource(device, listOfDevices, srcInfo); - } - return ret; - } - - public boolean updateBroadcastSourceInternal (BluetoothDevice device, BleBroadcastSourceInfo srcInfo, - boolean isGroupOp - ) { - boolean ret = false; - log("updateBroadcastSourceInternal: device: " + device - + "srcInfo" + srcInfo - + "isGroupOp" + isGroupOp); - /* Even If the request is for Grouoop, If Lock support not avaiable - * for that device, go ahead and treat this as single device operation - */ - if (isGroupOp && isLockSupportAvailable(device) == true) { - int setId = getCsetId(device); - synchronized (mSetManagers) { - BassCsetManager setMgr = getOrCreateCSetManager(setId, device); - if (setMgr == null) { - return false; - } - Message m = setMgr.obtainMessage(BassCsetManager.BASS_GRP_UPDATE_BCAST_SOURCE); - m.obj = srcInfo; - setMgr.sendMessage(m); - //queue req and return true - ret = true; - } - } else { - List listOfDevices = new ArrayList(); - listOfDevices.add(device); - ret = updateBroadcastSource(device, listOfDevices, srcInfo); - } - return ret; - } - - protected boolean setBroadcastCodeInternal (BluetoothDevice device, BleBroadcastSourceInfo srcInfo, - boolean isGroupOp - ) { - boolean ret = false; - log("setBroadcastCodeInternal: device: " + device - + "srcInfo" + srcInfo - + "isGroupOp" + isGroupOp); - /* Even If the request is for Grouoop, If Lock support not avaiable - * for that device, go ahead and treat this as single device operation - */ - if (isGroupOp && isLockSupportAvailable(device) == true) { - int setId = getCsetId(device); - synchronized (mSetManagers) { - BassCsetManager setMgr = getOrCreateCSetManager(setId, device); - if (setMgr == null) { - return false; - } - Message m = setMgr.obtainMessage(BassCsetManager.BASS_GRP_SET_BCAST_CODE); - m.obj = srcInfo; - setMgr.sendMessage(m); - //queue req and return true - ret = true; - } - } else { - List listOfDevices = new ArrayList(); - listOfDevices.add(device); - ret = setBroadcastCode(device, listOfDevices, srcInfo); - } - return ret; - } - - public boolean removeBroadcastSourceInternal (BluetoothDevice device, byte sourceId, boolean isGroupOp - ) { - boolean ret = false; - /* Even If the request is for Grouoop, If Lock support not avaiable - * for that device, go ahead and treat this as single device operation - */ - if (isGroupOp && isLockSupportAvailable(device) == true) { - int setId = getCsetId(device); - synchronized (mSetManagers) { - BassCsetManager setMgr = getOrCreateCSetManager(setId, device); - if (setMgr == null) { - return false; - } - Message m = setMgr.obtainMessage(BassCsetManager.BASS_GRP_REMOVE_BCAST_SOURCE); - m.arg1 = sourceId; - setMgr.sendMessage(m); - //queue req and return true - ret = true; - } - } else { - List listOfDevices = new ArrayList(); - listOfDevices.add(device); - ret = removeBroadcastSource(device, listOfDevices, sourceId); - } - return ret; - } - - static void log(String msg) { - if (BassClientStateMachine.BASS_DBG) { - Log.d(TAG, msg); - } - } - - /** - * Binder object: must be a static class or memory leak may occur - */ - @VisibleForTesting - static class BluetoothSyncHelperBinder extends IBluetoothSyncHelper.Stub - implements IProfileServiceBinder { - private BCService mService; - - private BCService getService() { - if (!Utils.checkCallerIsSystemOrActiveUser(TAG)) { - return null; - } - - if (mService != null && mService.isAvailable()) { - return mService; - } - return null; - } - - BluetoothSyncHelperBinder(BCService svc) { - mService = svc; - } - - @Override - public void cleanup() { - mService = null; - } - - @Override - public boolean connect(BluetoothDevice device) { - BCService service = getService(); - if (service == null) { - return false; - } - return service.connect(device); - } - - @Override - public boolean disconnect(BluetoothDevice device) { - BCService service = getService(); - if (service == null) { - return false; - } - return service.disconnect(device); - } - - @Override - public List getConnectedDevices() { - BCService service = getService(); - if (service == null) { - return new ArrayList<>(); - } - return service.getConnectedDevices(); - } - - @Override - public List getDevicesMatchingConnectionStates(int[] states) { - BCService service = getService(); - if (service == null) { - return new ArrayList<>(); - } - return service.getDevicesMatchingConnectionStates(states); - } - - @Override - public int getConnectionState(BluetoothDevice device) { - BCService service = getService(); - if (service == null) { - return BluetoothProfile.STATE_DISCONNECTED; - } - return service.getConnectionState(device); - } - - @Override - public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) { - BCService service = getService(); - if (service == null) { - return false; - } - return service.setConnectionPolicy(device, connectionPolicy); - } - - @Override - public int getConnectionPolicy(BluetoothDevice device) { - BCService service = getService(); - if (service == null) { - return BluetoothProfile.CONNECTION_POLICY_UNKNOWN; - } - return service.getConnectionPolicy(device); - } - @Override - public boolean searchforLeAudioBroadcasters (BluetoothDevice device) { - BCService service = getService(); - if (service == null) { - return false; - } - return service.searchforLeAudioBroadcasters(device); - } - - @Override - public boolean stopSearchforLeAudioBroadcasters (BluetoothDevice device) { - BCService service = getService(); - if (service == null) { - return false; - } - return service.stopSearchforLeAudioBroadcasters(device); - } - - @Override - public boolean selectBroadcastSource (BluetoothDevice device, ScanResult scanRes, boolean isGroupOp) { - BCService service = getService(); - if (service == null) { - return false; - } - return service.selectBroadcastSource(device, scanRes, isGroupOp, false); - } - - @Override - public void registerAppCallback(BluetoothDevice device, IBleBroadcastAudioScanAssistCallback cb) { - BCService service = getService(); - if (service == null) { - return; - } - service.registerAppCallback(device, cb); - } - - @Override - public void unregisterAppCallback(BluetoothDevice device, IBleBroadcastAudioScanAssistCallback cb) { - BCService service = getService(); - if (service == null) { - return; - } - service.unregisterAppCallback(device, cb); - } - - @Override - public boolean startScanOffload(BluetoothDevice device, boolean isGroupOp) { - BCService service = getService(); - if (service == null) { - return false; - } - return service.startScanOffloadInternal(device, isGroupOp); - } - - @Override - public boolean stopScanOffload(BluetoothDevice device, boolean isGroupOp) { - BCService service = getService(); - if (service == null) { - return false; - } - return service.stopScanOffloadInternal(device, isGroupOp); - } - - @Override - public boolean addBroadcastSource(BluetoothDevice device, BleBroadcastSourceInfo srcInfo - , boolean isGroupOp) { - BCService service = getService(); - if (service == null) { - return false; - } - return service.addBroadcastSourceInternal(device, srcInfo, isGroupOp); - } - - @Override - public boolean updateBroadcastSource (BluetoothDevice device, - BleBroadcastSourceInfo srcInfo, - boolean isGroupOp) { - BCService service = getService(); - if (service == null) { - return false; - } - return service.updateBroadcastSourceInternal(device, srcInfo, isGroupOp); - } - - @Override - public boolean setBroadcastCode (BluetoothDevice device, - BleBroadcastSourceInfo srcInfo, - boolean isGroupOp) { - BCService service = getService(); - if (service == null) { - return false; - } - return service.setBroadcastCodeInternal(device, srcInfo, isGroupOp); - } - - @Override - public boolean removeBroadcastSource (BluetoothDevice device, - byte sourceId, - boolean isGroupOp) { - BCService service = getService(); - if (service == null) { - return false; - } - return service.removeBroadcastSourceInternal(device, sourceId, isGroupOp); - } - @Override - public List getAllBroadcastSourceInformation (BluetoothDevice device - ) { - BCService service = getService(); - if (service == null) { - return null; - } - return service.getAllBroadcastSourceInformation(device); - } - } -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/bassclient/BaseData.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/bassclient/BaseData.java deleted file mode 100644 index b004afa669eaa0093fd9d0df640306a21acb7f86..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/bassclient/BaseData.java +++ /dev/null @@ -1,861 +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. - * - ******************************************************************************/ - -package com.android.bluetooth.bc; - -import java.util.List; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Iterator; -import android.os.Message; -import android.util.Log; -import java.util.UUID; -import java.util.Collection; -import android.os.UserHandle; - -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Scanner; -import java.util.Map; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Set; -import java.lang.String; -import java.lang.StringBuffer; -import java.lang.Integer; - -import java.nio.ByteBuffer; -import java.lang.Byte; -import java.util.stream.IntStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectOutputStream; -import java.io.IOException; - -import android.bluetooth.BleBroadcastSourceInfo; -import android.bluetooth.BleBroadcastSourceChannel; -///*_BMS -import com.android.bluetooth.broadcast.BroadcastService.BisInfo; -import com.android.bluetooth.broadcast.BroadcastService.MetadataLtv; -//_BMS*/ - -/** - * Helper class to parase the Broadcast Announcement BASE data - */ -final class BaseData { - private static final String TAG = "Bassclient-BaseData"; - BaseInformation levelOne = new BaseInformation(); - ArrayList levelTwo = new ArrayList(); - ArrayList levelThree = new ArrayList(); - int mNumBISIndicies; - public static byte UNKNOWN_CODEC = (byte)0xFE; - - public class BaseInformation { - public byte[] presentationDelay = new byte[3]; //valid only if level=1 - public byte[] codecId = new byte[5]; //valid only if level=1 - public byte codecConfigLength; - public byte[] codecConfigInfo; - public byte metaDataLength; - public byte[] metaData; - public byte numSubGroups; - public byte[] bisIndicies; //valid only if level = 2 - public byte index; //valid only if level=3 and level=2 (as subgroup Id) - public int subGroupId; - public int level;//differentiate different levels of BASE data - public LinkedHashSet keyCodecCfgDiff; - public LinkedHashSet keyMetadataDiff; - public String diffText; - public String description; - - public byte[] consolidatedCodecId; - public Set consolidatedMetadata; - public Set consolidatedCodecInfo; - public HashMap consolidatedUniqueCodecInfo; - public HashMap consolidatedUniqueMetadata; - - BaseInformation() { - presentationDelay = new byte[3]; - codecId = new byte[5]; - codecConfigLength = 0; - codecConfigInfo = null; - metaDataLength = 0; - metaData = null; - numSubGroups = 0; - bisIndicies = null; - index = (byte)0xFF; - level = 0; - - keyCodecCfgDiff = new LinkedHashSet(); - keyMetadataDiff = new LinkedHashSet(); - - consolidatedMetadata = new LinkedHashSet(); - consolidatedCodecInfo = new LinkedHashSet(); - consolidatedCodecId = new byte[5]; - consolidatedUniqueMetadata = new HashMap(); - consolidatedUniqueCodecInfo = new HashMap(); - diffText = new String(""); - description = new String(""); - log("BaseInformation is Initialized"); - } - - boolean isCodecIdUnknown() { - return (codecId != null && codecId[4] == (byte)BaseData.UNKNOWN_CODEC); - } - - void printConsolidated() { - log("**BEGIN: BIS consolidated Information**"); - log("BIS index:" + index); - log("CodecId:" + Arrays.toString(consolidatedCodecId)); - - /*if (consolidatedCodecInfo != null) { - Iterator itr = consolidatedCodecInfo.iterator(); - for (int k=0; itr.hasNext(); k++) { - log("consolidatedCodecInfo:[" + k + "]:" + Arrays.toString(itr.next().getBytes())); - } - } - - if (consolidatedMetadata != null) { - Iterator itr = consolidatedMetadata.iterator(); - for (int k=0; itr.hasNext(); k++) { - log("consolidatedMetadata:[" + k + "]:" + Arrays.toString(itr.next().getBytes())); - } - }*/ - - if (consolidatedUniqueCodecInfo != null) { - for (Map.Entry entry : consolidatedUniqueCodecInfo.entrySet()) { - log("consolidatedUniqueCodecInfo:[" + entry.getKey() + "]:" + Arrays.toString(entry.getValue().getBytes())); - } - } - - if (consolidatedUniqueMetadata != null) { - for (Map.Entry entry : consolidatedUniqueMetadata.entrySet()) { - log("consolidatedUniqueMetadata:[" + entry.getKey() + "]:" + Arrays.toString(entry.getValue().getBytes())); - } - } - log("**END: BIS consolidated Information****"); - } - void print() { - log("**BEGIN: Base Information**"); - log("**Level: " + level + "***"); - if (level == 1) { - log("presentationDelay: " + Arrays.toString(presentationDelay)); - } - if (level == 2) { - log("codecId: " + Arrays.toString(codecId)); - } - if (level == 2 || level == 3) { - log("codecConfigLength: " + codecConfigLength); - log("subGroupId: " + subGroupId); - } - if (codecConfigLength != (byte)0) { - log("codecConfigInfo: " + Arrays.toString(codecConfigInfo)); - } - if (level == 2) { - log("metaDataLength: " + metaDataLength); - if (metaDataLength != (byte)0) { - log("metaData: " + Arrays.toString(metaData)); - } - if (level == 1 || level == 2) - log("numSubGroups: " + numSubGroups); - } - if (level == 2) { - log("Level2: Key Metadata differentiators"); - if (keyMetadataDiff != null) { - Iterator itr = keyMetadataDiff.iterator(); - for (int k=0; itr.hasNext(); k++) { - log("keyMetadataDiff:[" + k + "]:" + Arrays.toString(itr.next().getBytes())); - } - } - log("END: Level2: Key Metadata differentiators"); - - log("Level2: Key CodecConfig differentiators"); - if (keyCodecCfgDiff != null) { - Iterator itr = keyCodecCfgDiff.iterator(); - for (int k=0; itr.hasNext(); k++) { - log("LEVEL2: keyCodecCfgDiff:[" + k + "]:" + Arrays.toString(itr.next().getBytes())); - } - } - log("END: Level2: Key CodecConfig differentiators"); - //log("bisIndicies: " + Arrays.toString(bisIndicies)); - log("LEVEL2: diffText: " + diffText); - } - if (level == 3) { - log("Level3: Key CodecConfig differentiators"); - if (keyCodecCfgDiff != null) { - Iterator itr = keyCodecCfgDiff.iterator(); - for (int k=0; itr.hasNext(); k++) { - log("LEVEL3: keyCodecCfgDiff:[" + k + "]:" + Arrays.toString(itr.next().getBytes())); - } - } - log("END: Level3: Key CodecConfig differentiators"); - log("index: " + index); - log("LEVEL3: diffText: " + diffText); - } - log("**END: Base Information****"); - } - }; - ///*_BMS - BaseData(int numSubGroups, List colocatedBisInfo, Map metaInfo) { - if (metaInfo == null || colocatedBisInfo == null) { - - Log.e(TAG, "BaseData Contruction with Invalid parameters"); - throw new IllegalArgumentException("Basedata: Parameters can't be null"); - } - levelOne = new BaseInformation(); - levelTwo = new ArrayList(); - levelThree = new ArrayList(); - - levelOne.level = 1; - levelOne.numSubGroups = (byte)numSubGroups; - - //create the level Two and update the Metadata Info - for (int i=0; i(); - levelThree = new ArrayList(); - mNumBISIndicies = 0; - log("members initialized"); - log("BASE input" + Arrays.toString(serviceData)); - - //Parse Level 1 base - levelOne.level = 1; - int level1Idx = 0; - System.arraycopy(serviceData, level1Idx, levelOne.presentationDelay,0, 3); - level1Idx = level1Idx + 3; - - levelOne.numSubGroups = serviceData[level1Idx++]; - levelOne.print(); - log("levelOne subgroups" + levelOne.numSubGroups); - - int level2Idx = level1Idx; - for (int i =0; i<(int)levelOne.numSubGroups; i++) { - log("parsing subgroup" + i); - BaseInformation b = new BaseInformation(); - - b.level = 2; - b.subGroupId = i; - b.numSubGroups = serviceData[level2Idx++]; - if (serviceData[level2Idx] == (byte)UNKNOWN_CODEC) { - //Place It in the last byte of codecID - System.arraycopy(serviceData, level2Idx, b.codecId, 4, 1); - level2Idx = level2Idx + 1; - log("codecId is FE"); - } else { - System.arraycopy(serviceData, level2Idx, b.codecId, 0, 5); - level2Idx = level2Idx + 5; - } - - b.codecConfigLength = serviceData[level2Idx++]; - if (b.codecConfigLength != 0) { - b.codecConfigInfo = new byte[(int)b.codecConfigLength]; - System.arraycopy(serviceData, level2Idx, b.codecConfigInfo, 0, (int)b.codecConfigLength); - level2Idx = level2Idx + (int)b.codecConfigLength; - } - b.metaDataLength = serviceData[level2Idx++]; - if (b.metaDataLength != 0) { - b.metaData = new byte[(int)b.metaDataLength]; - System.arraycopy(serviceData, level2Idx, b.metaData, 0, (int)b.metaDataLength); - level2Idx = level2Idx + (int)b.metaDataLength; - } - mNumBISIndicies = mNumBISIndicies + b.numSubGroups; - levelTwo.add(b); - b.print(); - } - //Parse Level 3 Base - int level3Index = level2Idx; - for (int k=0; k uniqueMds = new HashMap (); - Map uniqueCcis = new HashMap (); - - Set Csfs = levelThree.get(i).consolidatedCodecInfo; - - if (Csfs.size() > 0) { - Iterator itr = Csfs.iterator(); - for (int j=0; itr.hasNext(); j++) { - byte[] ltvEntries = itr.next().getBytes(); - - int k = 0; - byte length = ltvEntries[k++]; - byte[] ltv = new byte[length+1]; - ltv[0] = length; - System.arraycopy(ltvEntries, k, ltv, 1, length); - - // - int type = (int)ltv[1]; - String s = uniqueCcis.get(type); - String ltvS = new String(ltv); - if (s == null) { - uniqueCcis.put(type, ltvS); - } else { - //if same type exists - //replace - uniqueCcis.replace(type, ltvS); - } - } - } - - Set Mds = levelThree.get(i).consolidatedMetadata; - if (Mds.size() > 0) { - Iterator itr = Mds.iterator(); - for (int j=0; itr.hasNext(); j++) { - byte[] ltvEntries = itr.next().getBytes(); - - int k = 0; - byte length = ltvEntries[k++]; - byte[] ltv = new byte[length+1]; - ltv[0] = length; - System.arraycopy(ltvEntries, k, ltv, 1, length); - - /*CHECK: This can be straight PUT, there wont be dups in Metadata with new BASE*/ - int type = (int)ltv[1]; - String s = uniqueCcis.get(type); - String ltvS = new String(ltv); - if (s == null) { - uniqueMds.put(type, ltvS); - } else { - //if same type exists - //replace - uniqueMds.replace(type, ltvS); - } - } - } - - levelThree.get(i).consolidatedUniqueMetadata = new HashMap(uniqueMds); - levelThree.get(i).consolidatedUniqueCodecInfo = new HashMap(uniqueCcis); - - } - } - - void consolidateBaseofLevelThree(int parentSubgroup, int startIdx, int numNodes) { - - for (int i=startIdx; i(levelTwo.get(parentSubgroup).consolidatedMetadata); - - //log("Parent Cons Info>>"); - //levelTwo.get(parentSubgroup).printConsolidated(); - //CCI clone from Parent - levelThree.get(i).consolidatedCodecInfo = new LinkedHashSet(levelTwo.get(parentSubgroup).consolidatedCodecInfo); - //log("before " + i); - //levelThree.get(i).printConsolidated(); - //Append Level 2 Codec Config - if (levelThree.get(i).codecConfigLength != 0) { - log("append level 3 cci to level 3 cons:" + i); - String s = new String(levelThree.get(i).codecConfigInfo); - levelThree.get(i).consolidatedCodecInfo.add(s); - } - //log("after " + i); - //levelThree.get(i).printConsolidated(); - //log("Parent Cons Info>>"); - //levelTwo.get(parentSubgroup).printConsolidated(); - } - - } - - public int getNumberOfIndicies() { - return mNumBISIndicies; - } - - public byte getNumberOfSubgroupsofBIG() { - byte ret = 0; - if (levelOne != null) { - ret = levelOne.numSubGroups; - } - return ret; - } - - public ArrayList getBISIndexInfos() { - return levelThree; - } - List getBroadcastChannels() { - List bChannels = new ArrayList(); - for (int k=0; k pickAllBroadcastChannels() { - List bChannels = new ArrayList(); - for (int k=0; k itr = levelTwo.get(i).keyMetadataDiff.iterator(); - for (int k=0; itr.hasNext(); k++) { - levelTwo.get(i).diffText = levelTwo.get(i).diffText.concat(getMetadataString(itr.next().getBytes())); - levelTwo.get(i).diffText = levelTwo.get(i).diffText.concat("_"); - } - } - if (levelTwo.get(i).keyCodecCfgDiff != null) { - Iterator itr = levelTwo.get(i).keyCodecCfgDiff.iterator(); - for (int k=0; itr.hasNext(); k++) { - levelTwo.get(i).diffText = levelTwo.get(i).diffText.concat(getCodecParamString(itr.next().getBytes())); - levelTwo.get(i).diffText = levelTwo.get(i).diffText.concat("_"); - } - } - } - - for (int i=0; i itr = levelThree.get(i).keyCodecCfgDiff.iterator(); - for (int k=0; itr.hasNext(); k++) { - levelThree.get(i).diffText = levelThree.get(i).diffText.concat(getCodecParamString(itr.next().getBytes())); - levelThree.get(i).diffText = levelThree.get(i).diffText.concat("_"); - } - } - } - - //Concat and update the Description - int startIdx = 0; - int children = 0; - for (int i=0; i uniqueCodecIds = new LinkedHashSet(); - Set uniqueCsfs = new LinkedHashSet(); - Set uniqueMetadatas = new LinkedHashSet(); - - log("updateUniquenessForLevelTwo"); - - int startIdx = 0; - int children = 0; - for (int i=0; i uniqueCodecParams = new LinkedHashSet(); - Set uniqueMetadataParams = new LinkedHashSet(); - - if (uniqueCodecIds.size() > 0) log("LevelTwo: UniqueCodecIds"); - - if (uniqueCsfs.size() > 0) { - log("LevelTwo: uniqueCsfs"); - //uniqueCodecParams = - Iterator itr = uniqueCsfs.iterator(); - for (int i=0; itr.hasNext(); i++) { - byte[] ltvEntries = itr.next().getBytes(); - - int k = 0; - byte length = ltvEntries[k++]; - byte[] ltv = new byte[length+1]; - ltv[0] = length; - System.arraycopy(ltvEntries, k, ltv, 1, length); - //This should ensure Duplicate entries at this level - String s = new String(ltvEntries); - uniqueCodecParams.add(s); - } - } - if (uniqueMetadatas.size() > 0) { - log("LevelTwo: uniqueMetadatas"); - //uniqueMetadataParams = new LinkedHashSet(); - Iterator itr = uniqueMetadatas.iterator(); - for (int i=0; itr.hasNext(); i++) { - byte[] ltvEntries = itr.next().getBytes(); - - int k = 0; - byte length = ltvEntries[k++]; - byte[] ltv = new byte[length+1]; - ltv[0] = length; - System.arraycopy(ltvEntries, k, ltv, 1, length); - //This should ensure Duplicate entries at this level - String s = new String(ltvEntries); - uniqueMetadataParams.add(s); - } - } - - //run though the nodes and update KEY differentiating factors - if (uniqueCodecParams != null) { - Iterator itr = uniqueCodecParams.iterator(); - int i = 0; - for (int k=0; itr.hasNext(); k++) { - levelTwo.get(i).keyCodecCfgDiff.add(itr.next()); - i = (i+1)%(numNodes); - } - } - - //run though the nodes and update KEY differentiating factors - if (uniqueMetadataParams != null) { - Iterator itr = uniqueMetadataParams.iterator(); - int i = 0; - for (int k=0; itr.hasNext(); k++) { - levelTwo.get(i).keyMetadataDiff.add(itr.next()); - i = (i+1)%(numNodes); - } - } - - /*log("Level2: Uniqueness among subgroups"); - if (uniqueCodecParams != null) { - Iterator itr = uniqueCodecParams.iterator(); - for (int k=0; itr.hasNext(); k++) { - log("UniqueCodecParams:[" + k + "]" + Arrays.toString(itr.next().getBytes())); - } - } - if (uniqueMetadataParams != null) { - Iterator itr = uniqueMetadataParams.iterator(); - for (int k=0; itr.hasNext(); k++) { - log("uniqueMetadataParams:["+ k + "]" + Arrays.toString(itr.next().getBytes())); - } - } - log("END: Level2: Uniqueness among subgroups"); - */ - } - void updateUniquenessForLevelThree(int parentSubgroup, int startIdx, int numNodes) { - //Set uniqueCodecIds = new LinkedHashSet(); - Set uniqueCsfs = new LinkedHashSet(); - //Set uniqueMetadatas = new LinkedHashSet(); - - log("updateUniquenessForLevelThree: startIdx" + startIdx + "numNodes" + numNodes); - for (int i=startIdx; i uniqueCodecParams = new LinkedHashSet(); - if (uniqueCsfs.size() > 0) { - log("LevelThree: uniqueCsfs"); - //uniqueCodecParams = - Iterator itr = uniqueCsfs.iterator(); - for (int i=0; itr.hasNext(); i++) { - byte[] ltvEntries = itr.next().getBytes(); - - int k = 0; - byte length = ltvEntries[k++]; - byte[] ltv = new byte[length+1]; - ltv[0] = length; - System.arraycopy(ltvEntries, k, ltv, 1, length); - //This should ensure Duplicate entries at this level - String s = new String(ltvEntries); - uniqueCodecParams.add(s); - } - } - //run though the nodes and update KEY differentiating factors - if (uniqueCodecParams != null) { - Iterator itr = uniqueCodecParams.iterator(); - int i = startIdx; - for (int k=0; itr.hasNext(); k++) { - levelThree.get(i).keyCodecCfgDiff.add(itr.next()); - i = (i+1)%(startIdx+numNodes); - } - } - /* - log("Level3: Uniqueness among children of " + parentSubgroup + "th Subgroup"); - if (uniqueCodecParams != null) { - Iterator itr = uniqueCodecParams.iterator(); - for (int k=0; itr.hasNext(); k++) { - log("UniqueCodecParams:[" + k + "]" + Arrays.toString(itr.next().getBytes())); - - } - } - log("END: Level3: Uniqueness among children of " + parentSubgroup + "th Subgroup"); - */ - } - - void print() { - levelOne.print(); - log("----- Level TWO BASE ----"); - for (int i=0; i(Disconnecting) - * | ^ - * CONNECTED | | DISCONNECT - * V | - * (Connected) - * | ^ - * GATT_TXN | | GATT_TXN_DONE/GATT_TXN_TIMEOUT - * V | - * (ConnectedProcessing) - * 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. - * - Whenever there is any Gatt Write/read, State machine will moved "ConnectedProcessing" and - * all other requests (add, update, remove source) operations will be deferred in "ConnectedProcessing" state - * - Once the gatt transaction is done (or after a specified timeout of no response), State machine will - * move back to "Connected" and try to process the deferred requests as needed - * - * DISCONNECT - * (Connecting) ---------------> (Disconnecting) - * <--------------- - * CONNECT - * - */ - -package com.android.bluetooth.bc; - -import static android.Manifest.permission.BLUETOOTH_CONNECT; - -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothUuid; -import android.bluetooth.BluetoothProfile; -import android.bluetooth.BluetoothGattCallback; -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothGattCharacteristic; -import android.bluetooth.BluetoothGattDescriptor; -import android.bluetooth.le.ScanResult; -import android.bluetooth.le.ScanRecord; -import android.bluetooth.le.ScanCallback; -import android.bluetooth.BluetoothGattService; -import android.bluetooth.BluetoothSyncHelper; -import android.bluetooth.BleBroadcastSourceInfo; -import android.bluetooth.BleBroadcastSourceChannel; -import android.bluetooth.BleBroadcastAudioScanAssistManager; -import android.bluetooth.IBleBroadcastAudioScanAssistCallback; -import android.bluetooth.BleBroadcastAudioScanAssistCallback; -import com.android.bluetooth.Utils; - -//CSIP related imports -///*_CSIP -import com.android.bluetooth.groupclient.GroupService; -import android.bluetooth.BluetoothGroupCallback; -import android.bluetooth.DeviceGroup; -//_CSIP*/ - -///*_VCP -import android.bluetooth.BluetoothVcp; -import com.android.bluetooth.vcp.VcpController; -//_VCP*/ - -import android.bluetooth.le.BluetoothLeScanner; -import android.bluetooth.le.PeriodicAdvertisingCallback; -import android.bluetooth.le.PeriodicAdvertisingManager; -import android.bluetooth.le.PeriodicAdvertisingReport; - -import android.bluetooth.IBluetoothManager; -import android.os.ServiceManager; -import android.os.IBinder; - -import java.util.List; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Iterator; -import android.content.Intent; -import android.os.Looper; -import android.os.Message; -import android.util.Log; -import java.util.UUID; -import java.util.Collection; -import android.os.UserHandle; -import java.lang.IllegalArgumentException; - -import com.android.bluetooth.btservice.ProfileService; -/*_PACS -import com.android.bluetooth.pacsclient.PacsClientService; -_PACS*/ - -import com.android.bluetooth.btservice.ServiceFactory; -///*_BMS -import com.android.bluetooth.broadcast.BroadcastService; -//_BMS*/ - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Scanner; -import java.util.Map; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Set; -import java.lang.String; -import java.lang.StringBuffer; -import java.lang.Integer; - -import java.nio.ByteBuffer; -import java.lang.Byte; -import java.util.stream.IntStream; -import android.os.SystemProperties; -import android.os.ParcelUuid; - - -final class BassClientStateMachine extends StateMachine { - private static final String TAG = "BassClientStateMachine"; - public static final boolean BASS_DBG = true; - //public static final boolean BASS_DBG = Log.isLoggable(TAG, Log.DEBUG); - - private boolean mIsWhitelist = false; - - static final int BCAST_RECEIVER_STATE_LENGTH = 15; - static final int CONNECT = 1; - static final int DISCONNECT = 2; - static final int CONNECTION_STATE_CHANGED = 3; - static final int GATT_TXN_PROCESSED = 4; - static final int READ_BASS_CHARACTERISTICS= 5; - static final int START_SCAN_OFFLOAD = 6; - static final int STOP_SCAN_OFFLOAD = 7; - static final int SELECT_BCAST_SOURCE = 8; - static final int ADD_BCAST_SOURCE = 9; - static final int UPDATE_BCAST_SOURCE = 10; - static final int SET_BCAST_CODE = 11; - static final int REMOVE_BCAST_SOURCE = 12; - static final int GATT_TXN_TIMEOUT = 13; - static final int PSYNC_ACTIVE_TIMEOUT = 14; - public static final int CSIP_CONNECTION_STATE_CHANGED = 15; - static final int CONNECT_TIMEOUT = 16; - - //30 secs time out for all gatt writes - static final int GATT_TXN_TIMEOUT_MS = 30000; - - //3 min time out for keeping PSYNC active - static final int PSYNC_ACTIVE_TIMEOUT_MS = 3*60000; - //2 secs time out achieving psync - static final int PSYNC_TIMEOUT = 200; - - int NUM_OF_BROADCAST_RECEIVER_STATES = 0; - - private final Disconnected mDisconnected; - private final Connected mConnected; - private final Connecting mConnecting; - private final Disconnecting mDisconnecting; - private final ConnectedProcessing mConnectedProcessing; - private int mLastConnectionState = -1; - private static int mConnectTimeoutMs = 30000; - private boolean mMTUChangeRequested = false; - private boolean mDiscoveryInitiated = false; - - private BCService mService; - private final BluetoothDevice mDevice; - private BluetoothGatt mBluetoothGatt = null; - - //BASS Characteristics UUID - public static final UUID BASS_UUID = UUID.fromString("0000184F-0000-1000-8000-00805F9B34FB"); - private static final UUID BASS_BCAST_AUDIO_SCAN_CTRL_POINT = UUID.fromString("00002BC7-0000-1000-8000-00805F9B34FB"); - private static final UUID BASS_BCAST_RECEIVER_STATE = UUID.fromString("00002BC8-0000-1000-8000-00805F9B34FB"); - private static final UUID CLIENT_CHARACTERISTIC_CONFIG = UUID.fromString( - "00002902-0000-1000-8000-00805f9b34fb"); - private List mBroadcastReceiverStates; - private BluetoothGattCharacteristic mBroadcastScanControlPoint; - /*key is combination of sourceId, Address and advSid for this hashmap*/ - private final Map mBleBroadcastSourceInfos; - private boolean mFirstTimeBisDiscovery = false; - private int mPASyncRetryCounter = 0; - private ScanResult mScanRes = null; - - BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - private ServiceFactory mFactory = new ServiceFactory(); - ///*_BMS - private BroadcastService mBAService = null; - //_BMS*/ - - private final byte[] REMOTE_SCAN_STOP = {00}; - private final byte[] REMOTE_SCAN_START = {01}; - private byte BASS_ADD_SOURCE_OPCODE = 0x02; - private byte BASS_UPDATE_SOURCE_OPCODE = 0x03; - private byte BASS_SET_BCAST_PIN_OPCODE = 0x04; - private byte BASS_REMOVE_SOURCE_OPCODE = 0x05; - - private static int num_of_recever_states = 0; - private static int PIN_CODE_CMD_LEN = 18; - private final int BASS_MAX_BYTES = 100; - private int mPendingOperation = -1; - private byte mPendingSourceId = -1; - public static byte INVALID_SRC_ID = -1; - private int GATT_TXN_TOUT_ERROR = -1; - private BleBroadcastSourceInfo mSetBroadcastPINSrcInfo = null; - private boolean mSetBroadcastCodePending = false; - - //types of command for set broadcast PIN operation - public int FRESH = 1; - private int QUEUED = 2; - - //types of command for select and add Broadcast source operations - public int AUTO = 1; - public int USER = 2; - - //types of operation for Select source to determine - //if psync achieved on behalf of single device or multiple devices - public int GROUP_OP = 1; - public int NON_GROUP_OP = 0; - - public static int BROADCAST_ASSIST_ADDRESS_TYPE_PUBLIC = 0; - - //Service data Octet0 - private static int BROADCAST_ADV_ADDRESS_DONT_MATCHES_EXT_ADV_ADDRESS = 0x00000001; - private static int BROADCAST_ADV_ADDRESS_DONT_MATCHES_SOURCE_ADV_ADDRESS = 0x00000002; - - //Psync and PAST interfaces - private PeriodicAdvertisingManager mPeriodicAdvManager; - private static UUID BASIC_AUDIO_UUID = UUID.fromString("00001851-0000-1000-8000-00805F9B34FB"); - private boolean mAutoAssist = false; - private boolean mNoReverse = false; - private boolean mAutoTriggerred = false; - private boolean mSyncingOnBehalfOfGroup = false; - private boolean mNoStopScanOffload = false; - - //CSET interfaces - ///*_CSIP - private GroupService mSetCoordinator = GroupService.getGroupService(); - private boolean mCsipConnected = false; - //_CSIP*/ - - private boolean mPacsAvail = false; - private boolean mDefNoPAS = false; - private boolean mNoPast = false; - private boolean mNoCSIPReconn = false; - private boolean mPublicAddrForcSrc = false; - private boolean mForceSB = false; - private boolean mVcpForBroadcast = false; - - private int BROADCAST_SOURCE_ID_LENGTH = 3; - private byte mTempSourceId = 0; - //broadcast receiver state indicies - private static final int BCAST_RCVR_STATE_SRC_ID_IDX = 0; - private static final int BCAST_RCVR_STATE_SRC_ADDR_TYPE_IDX = 1; - private static final int BCAST_RCVR_STATE_SRC_ADDR_START_IDX = 2; - private static final int BCAST_RCVR_STATE_SRC_BCAST_ID_START_IDX = 9; - private static final int BCAST_RCVR_STATE_SRC_ADDR_SIZE = 6; - private static final int BCAST_RCVR_STATE_SRC_ADV_SID_IDX = 8; - private static final int BCAST_RCVR_STATE_PA_SYNC_IDX = 12; - private static final int BCAST_RCVR_STATE_ENC_STATUS_IDX = 13; - private static final int BCAST_RCVR_STATE_BADCODE_START_IDX = 14; - private static final int BCAST_RCVR_STATE_BADCODE_SIZE = 16; - - - private static final int BCAST_RCVR_STATE_BIS_SYNC_START_IDX = 10; - private static final int BCAST_RCVR_STATE_BIS_SYNC_SIZE = 4; - private static final int BCAST_RCVR_STATE_METADATA_LENGTH_IDX = 15; - private static final int BCAST_RCVR_STATE_METADATA_START_IDX = 16; - BassClientStateMachine(BluetoothDevice device, BCService svc, - Looper looper) { - super(TAG + "(" + device.toString() + ")", looper); - mDevice = device; - mService = svc; - - mDisconnected = new Disconnected(); - mDisconnecting = new Disconnecting(); - mConnected = new Connected(); - mConnecting = new Connecting(); - mConnectedProcessing = new ConnectedProcessing(); - - addState(mDisconnected); - addState(mDisconnecting); - addState(mConnected); - addState(mConnecting); - addState(mConnectedProcessing); - - setInitialState(mDisconnected); - mBroadcastReceiverStates = new ArrayList(); - mBleBroadcastSourceInfos = new HashMap(); - - //PSYNC and PAST instances - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - if (mBluetoothAdapter != null) { - mPeriodicAdvManager = mBluetoothAdapter.getPeriodicAdvertisingManager(); - } - ///*_BMS - mBAService = BroadcastService.getBroadcastService(); - //_BMS*/ - - mNoReverse = SystemProperties.getBoolean("persist.vendor.service.bt.nReverse", false); - mAutoAssist = SystemProperties.getBoolean("persist.vendor.service.bt.autoassist", false); - mIsWhitelist = SystemProperties.getBoolean("persist.vendor.service.bt.wl", true); - mDefNoPAS = SystemProperties.getBoolean("persist.vendor.service.bt.defNoPAS", false); - mNoPast = SystemProperties.getBoolean("persist.vendor.service.bt.noPast", false); - mNoCSIPReconn = SystemProperties.getBoolean("persist.vendor.service.bt.noCsipRec", false); - mPublicAddrForcSrc = SystemProperties.getBoolean("persist.vendor.service.bt.pAddrForcSource", true); - mForceSB = SystemProperties.getBoolean("persist.vendor.service.bt.forceSB", false); - mVcpForBroadcast = SystemProperties.getBoolean("persist.vendor.service.bt.vcpForBroadcast", true); - } - - static BassClientStateMachine make(BluetoothDevice device, BCService svc, - Looper looper) { - Log.d(TAG, "make for device " + device); - BassClientStateMachine BassclientSm = new BassClientStateMachine(device, svc, - looper); - BassclientSm.start(); - return BassclientSm; - } - - public void doQuit() { - log("doQuit for device " + mDevice); - quitNow(); - } - - public void cleanup() { - log("cleanup for device " + mDevice); - clearCharsCache(); - - if (mBluetoothGatt != null) { - log("disconnect gatt"); - mBluetoothGatt.disconnect(); - mBluetoothGatt.close(); - mBluetoothGatt = null; - } - mPendingOperation = -1; - mPendingSourceId = -1; - } - - BleBroadcastSourceInfo getBroadcastSourceInfoForSourceDevice (BluetoothDevice srcDevice) { - List currentSourceInfos = - getAllBroadcastSourceInformation(); - BleBroadcastSourceInfo srcInfo = null; - for (int i=0; i currentSourceInfos = - getAllBroadcastSourceInformation(); - BleBroadcastSourceInfo srcInfo = null; - for (int i=0; i bmsAdvDataMap = record.getServiceData(); - if (bmsAdvDataMap != null) { - for (Map.Entry entry : bmsAdvDataMap.entrySet()) { - log("ParcelUUid = " + entry.getKey() + - ", Value = " + entry.getValue()); - } - } else { - log("bmsAdvDataMap is null"); - if (mAutoTriggerred == false) { - mService.sendBroadcastSourceSelectedCallback(mDevice, null, - BleBroadcastAudioScanAssistCallback.BASS_STATUS_INVALID_SOURCE_SELECTED); - cancelActiveSync(srcDevice); - } else { - mAutoTriggerred = false; - } - } - ParcelUuid basicAudioUuid = new ParcelUuid(BASIC_AUDIO_UUID); - byte[] bmsAdvData = record.getServiceData(basicAudioUuid); - if (bmsAdvData != null) { - //ByteBuffer bb = ByteBuffer.wrap(bmsAdvData); - parseBaseData(mDevice, syncHandle, bmsAdvData); - - } else { - Log.e(TAG, "No service data in Scan record"); - if (mAutoTriggerred == false) { - mService.sendBroadcastSourceSelectedCallback(mDevice, null, - BleBroadcastAudioScanAssistCallback.BASS_STATUS_INVALID_SOURCE_SELECTED); - cancelActiveSync(srcDevice); - } else { - mAutoTriggerred = false; - } - } - } - - /*Local Public address based check - Use this prior to addition of Broadcast source*/ - boolean isLocalBroadcastSource (BluetoothDevice device) - { - BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); - boolean ret = btAdapter.getAddress().equals(device.getAddress()); - - log("isLocalBroadcastSource returns" +ret); - return ret; - } - - private boolean isValidBroadcastSourceInfo(BleBroadcastSourceInfo srcInfo) { - boolean ret = true; - List currentSourceInfos = - getAllBroadcastSourceInformation(); - Log.i(TAG, "input srcInfo: " + srcInfo); - for (int i=0; i listOfUuids = scanRecord.getServiceData(); - if (listOfUuids != null) { - if(listOfUuids.containsKey(ParcelUuid.fromString(BassUtils.BAAS_UUID))) { - byte[] bId = listOfUuids.get(ParcelUuid.fromString(BassUtils.BAAS_UUID)); - broadcastId = (0x00FF0000 & (bId[0] << 16)); - broadcastId |= (0x0000FF00 & (bId[1] << 8)); - broadcastId |= (0x000000FF & bId[2]); - } - } - mService.updatePAResultsMap(scanRes.getDevice(), scanRes.getAddressType(), - BCService.INVALID_SYNC_HANDLE, BCService.INVALID_ADV_SID, - scanRes.getPeriodicAdvertisingInterval(), - broadcastId); - } - } - else { - log("colocated case"); - if (autoTriggerred) { - log("should never happen!!!"); - //ignore - mAutoTriggerred = false; - } - ///*_BMS - if (mBAService == null || mBAService.isBroadcastActive() != true) { - Log.e(TAG, "colocated source handle unavailable OR not in streaming"); - mService.sendBroadcastSourceSelectedCallback(mDevice, null, - BleBroadcastAudioScanAssistCallback.BASS_STATUS_COLOCATED_SRC_UNAVAILABLE); - mService.stopScanOffloadInternal(mDevice, false); - return false; - } - String colocatedAddress = null; - int colocatedAddressType; - if (mPublicAddrForcSrc == true) { - colocatedAddress = BluetoothAdapter.getDefaultAdapter().getAddress(); - colocatedAddressType = BROADCAST_ASSIST_ADDRESS_TYPE_PUBLIC; - } else { - colocatedAddress = mBAService.BroadcastGetAdvAddress(); - colocatedAddressType = mBAService.BroadcastGetAdvAddrType(); - } - int paInterval = 0x0000FFFF; - paInterval = mBAService.BroadcastGetAdvInterval(); - - if (colocatedAddress == null) { - log("colocatedAddress is null"); - mService.sendBroadcastSourceSelectedCallback(mDevice, null, - BleBroadcastAudioScanAssistCallback.BASS_STATUS_COLOCATED_SRC_UNAVAILABLE); - mService.stopScanOffloadInternal(mDevice, false); - return false; - } - BluetoothDevice colocatedSrcDevice = - BluetoothAdapter.getDefaultAdapter().getRemoteDevice(colocatedAddress); - log("caching local Broacast details: " + colocatedSrcDevice); - - //advSid is same as advHandle for collocated case - byte[] broadcast_id = mBAService.getBroadcastId(); - broadcastId = (0x00FF0000 & (broadcast_id[2] << 16)); - broadcastId |= (0x0000FF00 & (broadcast_id[1] << 8)); - broadcastId |= (0x000000FF & broadcast_id[0]); - - mService.updatePAResultsMap(colocatedSrcDevice, colocatedAddressType, - mBAService.BroadcatGetAdvHandle(), - mBAService.BroadcatGetAdvHandle(), - paInterval, - broadcastId); - BaseData localBase = new BaseData(mBAService.getNumSubGroups(), - mBAService.BroadcastGetBisInfo(), - mBAService.BroadcastGetMetaInfo()); - localBase.printConsolidated(); - //Use advHandle to cahce Base - mService.updateBASE(mBAService.BroadcatGetAdvHandle(), localBase); - mService.sendBroadcastSourceSelectedCallback(mDevice, localBase.getBroadcastChannels(), - BleBroadcastAudioScanAssistCallback.BASS_STATUS_SUCCESS); - //_BMS*/ - } - return true; - } - - private void cancelActiveSync(BluetoothDevice sourceDev) { - log("cancelActiveSync"); - boolean isCancelSyncNeeded = false; - BluetoothDevice activeSyncedSrc = mService.getActiveSyncedSource(mDevice); - if (activeSyncedSrc != null ) { - if (sourceDev == null) { - isCancelSyncNeeded = true; - } else if(activeSyncedSrc.equals(sourceDev)) { - isCancelSyncNeeded = true; - } - } - if (isCancelSyncNeeded) { - removeMessages(PSYNC_ACTIVE_TIMEOUT); - try { - log("calling unregisterSync"); - mPeriodicAdvManager.unregisterSync(mPeriodicAdvCallback); - } catch (IllegalArgumentException ex) { - Log.w(TAG, "unregisterSync:IllegalArguementException"); - //ignore - } - mService.clearPAResults(activeSyncedSrc); - mService.setActiveSyncedSource(mDevice, null); - if (mNoStopScanOffload != true) { - //trigger scan stop here - mService.stopScanOffloadInternal(mDevice, false); - } - } - mNoStopScanOffload = false; - } - - /* Internal periodc Advertising manager callback - * - */ - private PeriodicAdvertisingCallback mPeriodicAdvCallback = new PeriodicAdvertisingCallback() { - @Override - public void onSyncEstablished(int syncHandle, BluetoothDevice device, - int advertisingSid, int skip, int timeout, - int status) { - log ("onSyncEstablished" + "syncHandle" + syncHandle + - "device" + device + "advertisingSid" + advertisingSid + - "skip" + skip + "timeout" + timeout + "status" + - status); - //turn off the LeScan once sync estd - mService.getBassUtils().leScanControl(false); - if (status == BluetoothGatt.GATT_SUCCESS) { - //upates syncHandle, advSid - mService.updatePAResultsMap(device, - BCService.INVALID_ADV_ADDRESS_TYPE, - syncHandle, advertisingSid, - BCService.INVALID_ADV_INTERVAL, - BCService.INVALID_BROADCAST_ID); - sendMessageDelayed(PSYNC_ACTIVE_TIMEOUT, PSYNC_ACTIVE_TIMEOUT_MS); - mService.setActiveSyncedSource(mDevice, device); - } else { - log("failed to sync to PA" + mPASyncRetryCounter); - mScanRes = null; - if (mAutoTriggerred == false) { - mService.sendBroadcastSourceSelectedCallback(mDevice, null, - BleBroadcastAudioScanAssistCallback.BASS_STATUS_SOURCE_UNAVAILABLE); - mService.stopScanOffloadInternal(mDevice, false); - } - mAutoTriggerred = false; - } - } - @Override - public void onPeriodicAdvertisingReport(PeriodicAdvertisingReport report) { - log( "onPeriodicAdvertisingReport"); - //Parse the BIS indicies from report's service data - if (mFirstTimeBisDiscovery) { - parseScanRecord(report.getSyncHandle(),report.getData()); - mFirstTimeBisDiscovery = false; - } - } - @Override - public void onSyncLost(int syncHandle) { - log( "OnSyncLost" + syncHandle); - BluetoothDevice srcDevice = mService.getDeviceForSyncHandle(syncHandle); - cancelActiveSync(srcDevice); - } - - public void onSyncTransfered(BluetoothDevice device, int status) { - log("sync transferred:" + device + " : " + status); - } - }; - - private void broadcastReceiverState(BleBroadcastSourceInfo state, int index, int max_num_srcInfos) { - log("broadcastReceiverState: " + mDevice); - - Intent intent = new Intent(BleBroadcastAudioScanAssistManager.ACTION_BROADCAST_SOURCE_INFO); - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); - intent.putExtra(BleBroadcastSourceInfo.EXTRA_SOURCE_INFO, state); - intent.putExtra(BleBroadcastSourceInfo.EXTRA_SOURCE_INFO_INDEX, index); - intent.putExtra(BleBroadcastSourceInfo.EXTRA_MAX_NUM_SOURCE_INFOS, max_num_srcInfos); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - mService.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_CONNECT, - Utils.getTempAllowlistBroadcastOptions()); - } - - private static boolean isEmpty(final byte[] data){ - return IntStream.range(0, data.length).parallel().allMatch(i -> data[i] == 0); - } - - private void processPASyncState(BleBroadcastSourceInfo srcInfo) { - log("processPASyncState" + srcInfo); - int serviceData = 0; - if (srcInfo == null) { - Log.e(TAG, "processPASyncState: srcInfo is null"); - return; - } - if (srcInfo.getMetadataSyncState() == BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_SYNCINFO_REQ) { - log("Initiate PAST procedure"); - BCService.PAResults res = mService.getPAResults(srcInfo.getSourceDevice()); - if (isAddedBroadcastSourceIsLocal(srcInfo.getSourceDevice()) && - mService.isLocalBroadcasting()) { - if (res == null) { - log("Populate colocated PA and initiate PAST"); - - int colocatedAddressType; - if (mPublicAddrForcSrc == true) { - colocatedAddressType = BROADCAST_ASSIST_ADDRESS_TYPE_PUBLIC; - } else { - colocatedAddressType = mBAService.BroadcastGetAdvAddrType(); - } - int broadcastId; - byte[] broadcast_id = mBAService.getBroadcastId(); - broadcastId = (0x00FF0000 & (broadcast_id[2] << 16)); - broadcastId |= (0x0000FF00 & (broadcast_id[1] << 8)); - broadcastId |= (0x000000FF & broadcast_id[0]); - mService.updatePAResultsMap(srcInfo.getSourceDevice(), colocatedAddressType, - mBAService.BroadcatGetAdvHandle(), - mBAService.BroadcatGetAdvHandle(), - mBAService.BroadcastGetAdvInterval(), - broadcastId); - } - res = mService.getPAResults(srcInfo.getSourceDevice()); - } - if (res != null) { - int syncHandle = res.mSyncHandle; - log("processPASyncState: syncHandle" + res.mSyncHandle); - if (mNoPast == false && syncHandle != BCService.INVALID_SYNC_HANDLE) { - if (isAddedBroadcastSourceIsLocal(srcInfo.getSourceDevice())) { - log("Collocated Case Initiate PAST for :" + mDevice + "syncHandle:" + syncHandle + - "serviceData" + serviceData); - serviceData = 0x000000FF & srcInfo.getSourceId(); - serviceData = serviceData << 8; - //advA matches EXT_ADV_ADDRESS - //but not matches source address (as we would have written pAddr) - serviceData = serviceData & (~BROADCAST_ADV_ADDRESS_DONT_MATCHES_EXT_ADV_ADDRESS); - serviceData = serviceData | (BROADCAST_ADV_ADDRESS_DONT_MATCHES_SOURCE_ADV_ADDRESS); - try { - mPeriodicAdvManager.transferSetInfo(mDevice, serviceData, syncHandle,mPeriodicAdvCallback); - } catch (IllegalArgumentException ex) { - Log.w(TAG, "transferSetInfo: IllegalArgumentException : PAST failure"); - //ignore - } - } else { - serviceData = 0x000000FF & srcInfo.getSourceId(); - serviceData = serviceData << 8; - //advA matches EXT_ADV_ADDRESS - //also matches source address (as we would have written) - serviceData = serviceData & (~BROADCAST_ADV_ADDRESS_DONT_MATCHES_EXT_ADV_ADDRESS); - serviceData = serviceData & (~BROADCAST_ADV_ADDRESS_DONT_MATCHES_SOURCE_ADV_ADDRESS); - log("Initiate PAST for :" + mDevice + "syncHandle:" + syncHandle + - "serviceData" + serviceData); - mPeriodicAdvManager.transferSync(mDevice, serviceData, syncHandle); - } - } - } else { - Log.e(TAG, "There is no valid sync handle for this Source"); - if (mAutoAssist) { - //initiate Auto Assist procedure for this device - mService.getBassUtils().triggerAutoAssist (srcInfo); - } - } - } - else if (srcInfo.getAudioSyncState() == BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED || - srcInfo.getMetadataSyncState() == BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_NO_PAST) { - //Cancel the existing sync and Invalidate the sync handle - if (isAddedBroadcastSourceIsLocal(srcInfo.getSourceDevice()) == false) { - if (mSyncingOnBehalfOfGroup == false) { - //Cancel the Sync only If it is NOT syced on behalf of group. - //group based sync will be kept active PSYNC_ACTIVE_TIMEOUT seconds so that - //all group members can get back in sync - log("Unregister sync as It is non colocated"); - cancelActiveSync(srcInfo.getSourceDevice()); - } - } else { - //trigger scan stop here - mService.stopScanOffloadInternal(mDevice, false); - } - } - } - - /*Actual OTA advertising address based check - Use this after the addition of Broadcast source*/ - private boolean isAddedBroadcastSourceIsLocal (BluetoothDevice device) - { - if (device == null) { - Log.e(TAG, "device handle is null"); - return false; - } - String localBroadcasterAddr = null; - ///*_BMS - if (mPublicAddrForcSrc) { - localBroadcasterAddr = BluetoothAdapter.getDefaultAdapter().getAddress(); - } else { - if (mBAService == null) { - mBAService = BroadcastService.getBroadcastService(); - } - if (mBAService == null || mBAService.isBroadcastActive() != true) { - Log.e(TAG, "isAddedBroadcastSourceIsLocal: colocated source handle is unavailable"); - return false; - } - localBroadcasterAddr = mBAService.BroadcastGetAdvAddress(); - } - //_BMS*/ - boolean ret = false; - if (localBroadcasterAddr == null) { - Log.e(TAG, "isAddedBroadcastSourceIsLocal: localBroadcasterAddr is null"); - ret = false; - } else { - ret = localBroadcasterAddr.equals(device.getAddress()); - } - log("isAddedBroadcastSourceIsLocal returns" +ret); - return ret; - } - - private void checkAndUpdateBroadcastCode(BleBroadcastSourceInfo srcInfo) { - if (isAddedBroadcastSourceIsLocal(srcInfo.getSourceDevice())) { - if (mForceSB == true || - srcInfo.getEncryptionStatus() == BleBroadcastSourceInfo.BROADCAST_ASSIST_ENC_STATE_PIN_NEEDED) { - //query the Encryption Key from BMS and update - ///*_BMS - byte[] colocatedBcastCode = mBAService.GetEncryptionKey(null); - if (mBAService.isBroadcastStreamingEncrypted() == false) { - Log.e(TAG, "seem to be Unencrypted colocated broadcast"); - //do nothing - return; - } - log("colocatedBcastCode is " + colocatedBcastCode); - //queue a fresh command to update the - Message m = obtainMessage(BassClientStateMachine.SET_BCAST_CODE); - m.obj = srcInfo; - m.arg1 = FRESH; - log("checkAndUpdateBroadcastCode: src device: " + srcInfo.getSourceDevice()); - sendMessage(m); - //_BMS*/ - } - } else { - log("checkAndUpdateBroadcastCode"); - //non colocated case, Broadcast PIN should have been updated from lyaer - //If there is pending one process it Now - if (srcInfo.getEncryptionStatus() == BleBroadcastSourceInfo.BROADCAST_ASSIST_ENC_STATE_PIN_NEEDED && - mSetBroadcastCodePending == true) { - //Make a QUEUED command - log("Update the Broadcast now"); - Message m = obtainMessage(BassClientStateMachine.SET_BCAST_CODE); - m.obj = mSetBroadcastPINSrcInfo; - m.arg1 = QUEUED; - - sendMessage(m); - mSetBroadcastCodePending = false; - mSetBroadcastPINSrcInfo = null; - } - } - } - - private List getListOfBisIndicies(int bisIndicies, int subGroupId, byte[] metaData) { - List bcastIndicies = new ArrayList(); - int index =0; - log("getListOfBisIndicies:" + bisIndicies); - while (bisIndicies != 0) { - if ((bisIndicies & 0x00000001) == 0x00000001) { - BleBroadcastSourceChannel bI = - new BleBroadcastSourceChannel(index, Integer.toString(index), true, subGroupId, metaData); - bcastIndicies.add(bI); - log("Adding BIS index for :" + index); - } - bisIndicies = bisIndicies>>1; - index++; - } - return bcastIndicies; - - } - - private void processBroadcastReceiverState (byte[] receiverState, BluetoothGattCharacteristic characteristic) { - int index = -1; - boolean isEmptyEntry = false; - BleBroadcastSourceInfo srcInfo = null; - - log("processBroadcastReceiverState:: characteristic:" + characteristic); - - byte sourceId = 0; - if (receiverState.length > 0) - sourceId = receiverState[BCAST_RCVR_STATE_SRC_ID_IDX]; - log("processBroadcastReceiverState: receiverState length: " + receiverState.length); - if (receiverState.length == 0 || - isEmpty(Arrays.copyOfRange(receiverState, 1, receiverState.length-1))) { - log("This is an Empty Entry"); - if (mPendingOperation == REMOVE_BCAST_SOURCE) { - srcInfo = new BleBroadcastSourceInfo(mPendingSourceId); - } else if (receiverState.length == 0) { - if (mBleBroadcastSourceInfos != null) { - mTempSourceId = (byte)mBleBroadcastSourceInfos.size(); - } - if (mTempSourceId < NUM_OF_BROADCAST_RECEIVER_STATES) { - mTempSourceId++; - srcInfo = new BleBroadcastSourceInfo(mTempSourceId); - } else { - Log.e(TAG, "reached the remote supported max SourceInfos"); - return; - } - } - isEmptyEntry = true; - //just create an Empty entry - if (srcInfo.isEmptyEntry()) { - log("An empty entry has been created"); - } - } - else { - byte sourceAddressType = receiverState[BCAST_RCVR_STATE_SRC_ADDR_TYPE_IDX]; - byte[] sourceAddress = new byte[BCAST_RCVR_STATE_SRC_ADDR_SIZE]; - System.arraycopy(receiverState, BCAST_RCVR_STATE_SRC_ADDR_START_IDX, sourceAddress, 0, BCAST_RCVR_STATE_SRC_ADDR_SIZE); - byte sourceAdvSid = receiverState[BCAST_RCVR_STATE_SRC_ADV_SID_IDX]; - - byte[] broadcastIdBytes = new byte[BROADCAST_SOURCE_ID_LENGTH]; - System.arraycopy(receiverState, BCAST_RCVR_STATE_SRC_BCAST_ID_START_IDX, broadcastIdBytes, 0, BROADCAST_SOURCE_ID_LENGTH); - int broadcastId = (0x00FF0000 & (broadcastIdBytes[2] << 16)); - broadcastId |= (0x0000FF00 & (broadcastIdBytes[1] << 8)); - broadcastId |= (0x000000FF & broadcastIdBytes[0]); - - BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); - BluetoothDevice device = btAdapter.getRemoteDevice(reverseBytes(sourceAddress)); - byte metaDataSyncState = receiverState[BCAST_RCVR_STATE_PA_SYNC_IDX]; - - - byte encyptionStatus = receiverState[BCAST_RCVR_STATE_ENC_STATUS_IDX]; - byte[] badBroadcastCode = null; - byte badBroadcastCodeLen = 0; - byte numSubGroups = 0; - byte[] metadataLength = null; - byte[] metaData = null; - if (encyptionStatus == BleBroadcastSourceInfo.BROADCAST_ASSIST_ENC_STATE_BADCODE) { - badBroadcastCode = new byte[BCAST_RCVR_STATE_BADCODE_SIZE]; - System.arraycopy(receiverState, BCAST_RCVR_STATE_BADCODE_START_IDX, badBroadcastCode, 0, BCAST_RCVR_STATE_BADCODE_SIZE); - badBroadcastCode = reverseBytes(badBroadcastCode); - badBroadcastCodeLen = BCAST_RCVR_STATE_BADCODE_SIZE; - } - numSubGroups = receiverState[BCAST_RCVR_STATE_BADCODE_START_IDX + badBroadcastCodeLen]; - int offset = BCAST_RCVR_STATE_BADCODE_START_IDX + badBroadcastCodeLen + 1; - //Map of Bis Status - Map> bisIndexList = new HashMap>(); - //Map for Metada - Map metadataList = new HashMap(); - metadataLength = new byte[numSubGroups]; - byte audioSyncState = 0; - for (int i = 0; i < numSubGroups; i++) { - byte[] audioSyncIndex = new byte[BCAST_RCVR_STATE_BIS_SYNC_SIZE]; - System.arraycopy(receiverState, offset, audioSyncIndex, 0, BCAST_RCVR_STATE_BIS_SYNC_SIZE); - offset = offset + BCAST_RCVR_STATE_BIS_SYNC_SIZE; - log("BIS index byte array: "); - BassUtils.printByteArray(audioSyncIndex); - ByteBuffer wrapped = ByteBuffer.wrap(reverseBytes(audioSyncIndex)); - int audioBisIndex = wrapped.getInt(); - if (audioBisIndex == 0xFFFFFFFF) { - log("Remote failed to sync to BIS"); - audioSyncState = 0x00; - audioBisIndex = 0; - } else { - //Bits (0-30)=> (1-31) - audioBisIndex = audioBisIndex << 1; - log("BIS index converted: " + audioBisIndex); - if (audioBisIndex != 0){ - //If any BIS is in sync, Set Audio state as ON - audioSyncState = 0x01; - } - } - - metadataLength[i] = receiverState[offset++]; - if (metadataLength[i] != 0) { - log("metadata of length: " + metadataLength[i] + "is avaialble"); - metaData = new byte[metadataLength[i]]; - System.arraycopy(receiverState, offset, metaData, 0, metadataLength[i]); - offset = offset + metadataLength[i]; - metaData = reverseBytes(metaData); - metadataList.put(i, metaData); - } - bisIndexList.put(i, getListOfBisIndicies(audioBisIndex, i, metaData)); - } - srcInfo = new BleBroadcastSourceInfo(device, - sourceId, - sourceAdvSid, - broadcastId, - (int)sourceAddressType, - (int)metaDataSyncState, - (int)encyptionStatus, - badBroadcastCode, - numSubGroups, - (int)audioSyncState, - bisIndexList, - metadataList - ); - } - BleBroadcastSourceInfo oldSourceInfo = mBleBroadcastSourceInfos.get(characteristic.getInstanceId()); - if (oldSourceInfo == null) { - log("Initial Read and Populating values"); - if (mBleBroadcastSourceInfos.size() == NUM_OF_BROADCAST_RECEIVER_STATES) { - Log.e(TAG, "reached the Max SourceInfos"); - return; - } - mBleBroadcastSourceInfos.put(characteristic.getInstanceId(), srcInfo); - checkAndUpdateBroadcastCode(srcInfo); - processPASyncState(srcInfo); - } else { - log("old sourceInfo: " + oldSourceInfo); - log("new sourceInfo: " + srcInfo); - mBleBroadcastSourceInfos.replace(characteristic.getInstanceId(), srcInfo); - if (oldSourceInfo.isEmptyEntry() == true) { - log("New Source Addition"); - sendPendingCallbacks(ADD_BCAST_SOURCE, - srcInfo.getSourceId(), BluetoothGatt.GATT_SUCCESS); - checkAndUpdateBroadcastCode(srcInfo); - processPASyncState(srcInfo); - } else { - if (isEmptyEntry) { - BluetoothDevice removedDevice = oldSourceInfo.getSourceDevice(); - log("sourceInfo removal" + removedDevice); - cancelActiveSync(removedDevice); - sendPendingCallbacks(REMOVE_BCAST_SOURCE, - srcInfo.getSourceId(), BluetoothGatt.GATT_SUCCESS); - } else { - log("update to an existing srcInfo"); - sendPendingCallbacks(UPDATE_BCAST_SOURCE, - srcInfo.getSourceId(),BluetoothGatt.GATT_SUCCESS); - processPASyncState(srcInfo); - checkAndUpdateBroadcastCode(srcInfo); - } - } - } - index = srcInfo.getSourceId(); - if (index == -1) { - log("processBroadcastReceiverState: invalid index"); - return; - } - broadcastReceiverState(srcInfo, index, NUM_OF_BROADCAST_RECEIVER_STATES); - } - // Implements callback methods for GATT events that the app cares about. For example, - // connection change and services discovered. - private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { - @Override - public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { - boolean isStateChanged = false; - log( "onConnectionStateChange : Status=" + status + "newState" + newState); - if (newState == BluetoothProfile.STATE_CONNECTED && getConnectionState() != BluetoothProfile.STATE_CONNECTED) { - isStateChanged = true; - Log.w(TAG, "Bassclient Connected from Disconnected state: " + mDevice); - if (mService.okToConnect(mDevice)) { - log("Bassclient Connected to: " + mDevice); - if (mBluetoothGatt != null) { - log( "Attempting to start service discovery:" + - mBluetoothGatt.discoverServices()); - mDiscoveryInitiated = true; - } - } else { - if (mBluetoothGatt != null) { - // Reject the connection - Log.w(TAG, "Bassclient Connect request rejected: " + mDevice); - mBluetoothGatt.disconnect(); - mBluetoothGatt.close(); - mBluetoothGatt = null; - //force move to disconnected - newState = BluetoothProfile.STATE_DISCONNECTED; - } - } - } else if (newState == BluetoothProfile.STATE_DISCONNECTED && - getConnectionState() != BluetoothProfile.STATE_DISCONNECTED) { - isStateChanged = true; - log( "Disconnected from Bass GATT server."); - } - if (isStateChanged) { - Message m = obtainMessage(CONNECTION_STATE_CHANGED); - m.obj = newState; - sendMessage(m); - } - } - @Override - public void onServicesDiscovered(BluetoothGatt gatt, int status) { - log("onServicesDiscovered:" + status); - if (mDiscoveryInitiated == true) { - mDiscoveryInitiated = false; - if (status == BluetoothGatt.GATT_SUCCESS && mBluetoothGatt != null) { - mBluetoothGatt.requestMtu(BASS_MAX_BYTES); - mMTUChangeRequested = true; - } else { - Log.w(TAG, "onServicesDiscovered received: " + status - + "mBluetoothGatt" + mBluetoothGatt); - } - } else { - log("remote initiated callback"); - //do nothing - } - } - @Override - public void onCharacteristicRead(BluetoothGatt gatt, - BluetoothGattCharacteristic characteristic, - int status) { - log( "onCharacteristicRead:: status: " + status + "char:" + characteristic); - - if (status == BluetoothGatt.GATT_SUCCESS && - characteristic.getUuid().equals(BASS_BCAST_RECEIVER_STATE)) { - log( "onCharacteristicRead: BASS_BCAST_RECEIVER_STATE: status" + status); - logByteArray("Received ", characteristic.getValue(), 0, - characteristic.getValue().length); - if (characteristic.getValue() == null) { - Log.e(TAG, "Remote receiver state is NULL"); - return; - } - processBroadcastReceiverState(characteristic.getValue(), characteristic); - } - // switch to receiving notifications after initial characteristic read - BluetoothGattDescriptor desc = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG); - if (mBluetoothGatt != null && desc != null) { - log("Setting the value for Desc"); - mBluetoothGatt.setCharacteristicNotification(characteristic, true); - desc.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); - mBluetoothGatt.writeDescriptor(desc); - } else { - Log.w(TAG, "CCC for " + characteristic + "seem to be not present"); - //atleast move the SM to stable state - Message m = obtainMessage(GATT_TXN_PROCESSED); - m.arg1 = status; - sendMessage(m); - } - } - - @Override - public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, - int status) { - log("onDescriptorWrite"); - if (status == BluetoothGatt.GATT_SUCCESS && - descriptor.getUuid().equals(CLIENT_CHARACTERISTIC_CONFIG)) { - log("CCC write resp"); - } - - //Move the SM to connected so further reads happens - Message m = obtainMessage(GATT_TXN_PROCESSED); - m.arg1 = status; - sendMessage(m); - } - - @Override - public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) - { - log("onMtuChanged: mtu:" + mtu); - if (mMTUChangeRequested == true && mBluetoothGatt != null) { - acquireAllBassChars(); - mMTUChangeRequested = false; - } else { - log("onMtuChanged is remote initiated trigger, mBluetoothGatt:" + mBluetoothGatt); - //Do nothing - } - } - - @Override - public void onCharacteristicChanged(BluetoothGatt gatt, - BluetoothGattCharacteristic characteristic) { - log( "onCharacteristicChanged :: " - + characteristic.getUuid().toString()); - if (characteristic.getUuid().equals(BASS_BCAST_RECEIVER_STATE)) { - log( "onCharacteristicChanged is rcvr State :: " - + characteristic.getUuid().toString()); - if (characteristic.getValue() == null) { - Log.e(TAG, "Remote receiver state is NULL"); - return; - } - logByteArray("onCharacteristicChanged: Received ", characteristic.getValue(), 0, - characteristic.getValue().length); - processBroadcastReceiverState(characteristic.getValue(), characteristic); - } - } - - @Override - public void onCharacteristicWrite(BluetoothGatt gatt, - BluetoothGattCharacteristic characteristic, int status) { - log( "onCharacteristicWrite: " - + characteristic.getUuid().toString() - + "status:" + status); - if (status == 0 && - characteristic.getUuid().equals(BASS_BCAST_AUDIO_SCAN_CTRL_POINT)) { - log( "BASS_BCAST_AUDIO_SCAN_CTRL_POINT is written successfully"); - } - Message m = obtainMessage(GATT_TXN_PROCESSED); - m.arg1 = status; - sendMessage(m); - } - }; - - public List getAllBroadcastSourceInformation() { - log( "getAllBroadcastSourceInformation"); - List list = new ArrayList(mBleBroadcastSourceInfos.values()); - return list; - } - - void acquireAllBassChars() { - clearCharsCache(); - BluetoothGattService service = null; - if (mBluetoothGatt != null) { - log("getting Bass Service handle"); - service = mBluetoothGatt.getService(BASS_UUID); - } - if (service != null) { - log( "found BASS_SERVICE"); - List allChars = service.getCharacteristics(); - int numOfChars = allChars.size(); - NUM_OF_BROADCAST_RECEIVER_STATES = numOfChars-1; - log( "Total number of chars" + numOfChars); - //static var to keep track of read callbacks - num_of_recever_states = NUM_OF_BROADCAST_RECEIVER_STATES; - for (int i = 0; i < allChars.size(); i++) { - if (allChars.get(i).getUuid().equals(BASS_BCAST_AUDIO_SCAN_CTRL_POINT)) { - mBroadcastScanControlPoint = allChars.get(i); - log( "Index of ScanCtrlPoint:" + i); - } else { - log( "Reading " + i + "th ReceiverState"); - mBroadcastReceiverStates.add(allChars.get(i)); - Message m = obtainMessage(READ_BASS_CHARACTERISTICS); - m.obj = allChars.get(i); - sendMessage(m); - } - } - } else { - Log.e(TAG, "acquireAllBassChars: BASS service not found"); - } - } - - void clearCharsCache() { - if (mBroadcastReceiverStates != null) { - mBroadcastReceiverStates.clear(); - } - if (mBroadcastScanControlPoint != null) { - mBroadcastScanControlPoint = null; - } - num_of_recever_states = 0; - if (mBleBroadcastSourceInfos != null) { - mBleBroadcastSourceInfos.clear(); - } - mPendingOperation = -1; - } - - @VisibleForTesting - class Disconnected extends State { - @Override - public void enter() { - log( "Enter Disconnected(" + mDevice + "): " + messageWhatToString( - getCurrentMessage().what)); - clearCharsCache(); - mTempSourceId = 0; - removeDeferredMessages(DISCONNECT); - - if (mLastConnectionState == -1) { - log( "no Broadcast of initial profile state "); - } else { - if (mPacsAvail == true) { - /*_PACS - PacsClientService mPacsClientService = PacsClientService.getPacsClientService(); - if (mPacsClientService != null) { - log("trigger disconnect to Pacs"); - mPacsClientService.disconnect(mDevice); - } else { - Log.e(TAG, "PACs interface is null"); - } - _PACS*/ - } - - ///*_VCP - if (mVcpForBroadcast) { - VcpController vcpController = VcpController.getVcpController(); - if (vcpController != null) { - log("trigger disconnect to Vcp Renderer"); - if (!vcpController.disconnect(mDevice, BluetoothVcp.MODE_BROADCAST)) { - log("Disconnect Vcp failed"); - } - } else { - Log.e(TAG, "VcpController interface is null"); - } - } - //_VCP*/ - broadcastConnectionState(mDevice, mLastConnectionState, - BluetoothProfile.STATE_DISCONNECTED); - } - } - - @Override - public void exit() { - log("Exit Disconnected(" + mDevice + "): " + messageWhatToString( - getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_DISCONNECTED; - } - - @Override - public boolean processMessage(Message message) { - log("Disconnected process message(" + mDevice + "): " + messageWhatToString( - message.what)); - - switch (message.what) { - case CONNECT: - log("Connecting to " + mDevice); - if (mBluetoothGatt != null) { - Log.d(TAG, "clear off, pending wl connection"); - mBluetoothGatt.disconnect(); - mBluetoothGatt.close(); - mBluetoothGatt = null; - } - - if ((mBluetoothGatt = mDevice.connectGatt(mService, mIsWhitelist, mGattCallback, - BluetoothDevice.TRANSPORT_LE, false, (BluetoothDevice.PHY_LE_1M_MASK | - BluetoothDevice.PHY_LE_2M_MASK | BluetoothDevice.PHY_LE_CODED_MASK), - null, true)) == null) { - Log.e(TAG, "Disconnected: error connecting to " + mDevice); - break; - } else { - transitionTo(mConnecting); - } - break; - case DISCONNECT: - Log.w(TAG, "Disconnected: DISCONNECT ignored: " + mDevice); - break; - case CONNECTION_STATE_CHANGED: - int state = (int)message.obj; - Log.w(TAG, "connection state changed:" + state); - if (state == BluetoothProfile.STATE_CONNECTED) { - log("remote/wl connection, ensure csip is up as well"); - if (mNoCSIPReconn == false && mService != null && - mService.isLockSupportAvailable(mDevice)) { - /////*_CSIP - mCsipConnected = false; - mSetCoordinator.connect(mService.mCsipAppId, mDevice); - transitionTo(mConnecting); - break; - ////_CSIP*/ - } else { - transitionTo(mConnected); - } - } else { - Log.w(TAG, "Disconected: Connection failed to " + mDevice); - } - break; - case PSYNC_ACTIVE_TIMEOUT: - cancelActiveSync(null); - break; - default: - log("DISCONNECTED: not handled message:" + message.what); - return NOT_HANDLED; - } - return HANDLED; - } - } - - @VisibleForTesting - class Connecting extends State { - @Override - public void enter() { - log( "Enter Connecting(" + mDevice + "): " + messageWhatToString( - getCurrentMessage().what)); - sendMessageDelayed(CONNECT_TIMEOUT, mDevice, mConnectTimeoutMs); - broadcastConnectionState(mDevice, mLastConnectionState, - BluetoothProfile.STATE_CONNECTING); - } - - @Override - public void exit() { - log("Exit Connecting(" + mDevice + "): " + messageWhatToString( - getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_CONNECTING; - removeMessages(CONNECT_TIMEOUT); - } - - @Override - public boolean processMessage(Message message) { - log("Connecting process message(" + mDevice + "): " + messageWhatToString( - message.what)); - - switch (message.what) { - case CONNECT: - log("Already Connecting to " + mDevice); - log("Ignore this connection request " + mDevice); - break; - case DISCONNECT: - Log.w(TAG, "Connecting: DISCONNECT deferred: " + mDevice); - deferMessage(message); - break; - case READ_BASS_CHARACTERISTICS: - Log.w(TAG, "defer READ_BASS_CHARACTERISTICS requested!: " + mDevice); - deferMessage(message); - break; - case CSIP_CONNECTION_STATE_CHANGED: - int state = (int)message.obj; - if (state == BluetoothProfile.STATE_CONNECTED) { - ///*_CSIP - if (mCsipConnected == true) { - Log.e(TAG, "CSIP is already up, ignore this DUP event"); - break; - } - mCsipConnected = true; - Log.d(TAG, "Csip connected"); - transitionTo(mConnected); - } else { - Log.w(TAG, "CSIP Connection failed to " + mDevice); - if (mBluetoothGatt != null) { - //disc bass - mBluetoothGatt.disconnect(); - mBluetoothGatt.close(); - mBluetoothGatt = null; - } - transitionTo(mDisconnected); - } - - break; - case CONNECTION_STATE_CHANGED: - state = (int)message.obj; - Log.w(TAG, "Connecting: connection state changed:" + state); - if (state == BluetoothProfile.STATE_CONNECTED) { - if (mService != null && - mService.isLockSupportAvailable(mDevice)) { - ///*_CSIP - //If Lock support available & connect to csip - mCsipConnected = false; - mSetCoordinator.connect(mService.mCsipAppId, mDevice); - break; - //_CSIP*/ - } else { - transitionTo(mConnected); - } - } else { - Log.w(TAG, "Connection failed to " + mDevice); - transitionTo(mDisconnected); - } - break; - case CONNECT_TIMEOUT: - Log.w(TAG, "CONNECT_TIMEOUT"); - BluetoothDevice device = (BluetoothDevice) message.obj; - if (!mDevice.equals(device)) { - Log.e(TAG, "Unknown device timeout " + device); - break; - } - transitionTo(mDisconnected); - break; - case PSYNC_ACTIVE_TIMEOUT: - deferMessage(message); - break; - default: - log("CONNECTING: not handled message:" + message.what); - return NOT_HANDLED; - } - return HANDLED; - } - } - - private byte[] reverseBytes(byte[] a) { - if (mNoReverse) { - log("no reverse is enabled>"); - return a; - } - for(int i=0; i bisIndicies, int subGroupId) { - int audioBisIndex = 0; - if (bisIndicies != null) { - for (int i=0; i>> 8); - res[11] = (byte)((paRes.mBroadcastId & 0x0000000000FF0000) >>> 16); - if (mDefNoPAS == false && - srcInfo.getMetadataSyncState() == BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC) { - res[12] = (byte)(0x01); - } else { - log("setting PA sync to ZERO"); - res[12] = (byte)0x00; - } - - res[13] = (byte)(paRes.mPAInterval & 0x00000000000000FF); - res[14] = (byte)((paRes.mPAInterval & 0x000000000000FF00)>>>8); - - res[15] = base_.getNumberOfSubgroupsofBIG(); - - int offset = 16; - for (int i=0; i>>8); - res[offset++] = (byte)((bisIndexValue & 0x0000000000FF0000)>>>16); - res[offset++] = (byte)((bisIndexValue & 0x00000000FF000000)>>>24); - - res[offset++] = metaDataLength[i]; - if (metaDataLength[i] != 0) { - if (isLocalBroadcastSource(broadcastSource) == false) { - byte[] revMetadata = reverseBytes(base_.getMetadata(i)); - System.arraycopy(revMetadata, 0, res, offset, metaDataLength[i]); - } else { - System.arraycopy(base_.getMetadata(i), 0, res, offset, metaDataLength[i]); - } - } - offset = offset + metaDataLength[i]; - } - - log("ADD_BCAST_SOURCE in Bytes"); - BassUtils.printByteArray(res); - return res; - } - - private byte[] convertSourceInfoToUpdateSourceByteArray(BleBroadcastSourceInfo srcInfo) { - byte[] res; - int updateSourceFixedLength = 6; - BCService.PAResults paRes = null; - BleBroadcastSourceInfo existingSI = getBroadcastSourceInfoForSourceId(srcInfo.getSourceId()); - if (existingSI == null) { - log("no existing SI for update source op"); - return null; - } - - byte numSubGroups = existingSI.getNumberOfSubGroups(); - //on Modify source, dont update any Metadata - byte metaDataLength = 0; - res = new byte [updateSourceFixedLength + numSubGroups*5]; - - res[0] = BASS_UPDATE_SOURCE_OPCODE; - res[1] = srcInfo.getSourceId(); - - if (srcInfo.getMetadataSyncState() == BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC) { - res[2] = (byte)(0x01); - } else { - res[2] = (byte)0x00; - } - //update these from existing SI - BluetoothDevice existingSrcDevice = existingSI.getSourceDevice(); - if (isAddedBroadcastSourceIsLocal(existingSrcDevice)) { - int paInterval = 0x0000FFFF; - paInterval = mBAService.BroadcastGetAdvInterval(); - res[4] = (byte)((paInterval & 0x000000000000FF00)>>>8); - res[3] = (byte)(paInterval & 0x00000000000000FF); - } else { - //for non-c mmodify op, set PA Interval as UNKNOWN - res[4] = (byte)0xFF; - res[3] = (byte)0xFF; - } - //For modify op, just set number of Subgroups as UNKNOWN - //ZERO is treated as UNKNOWN - res[5] = numSubGroups; - - int offset = 6; - int bisIndexValue = 0; - Map bisIndexList = existingSI.getBisIndexList(); - if (srcInfo.getAudioSyncState() == BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED) { - //Force BIS index value to NO_PREF for modify SRC - bisIndexValue = 0xFFFFFFFF; - } else { - bisIndexValue = 0x00000000; - } - log("UPDATE_BCAST_SOURCE b4: bisIndexValue : " + bisIndexValue); - //If there is an empty List, set NO pref all subgroups - if (bisIndexList == null || bisIndexList.size() == 0) { - bisIndexValue = 0xFFFFFFFF; - } - for (int i=0; i>>8); - res[offset++] = (byte)((bisIndexValue & 0x0000000000FF0000)>>>16); - res[offset++] = (byte)((bisIndexValue & 0x00000000FF000000)>>>24); - - res[offset++] = metaDataLength; - } - log("UPDATE_BCAST_SOURCE in Bytes"); - BassUtils.printByteArray(res); - return res; - } - - private byte[] convertAsciitoValues (byte[] val) { - byte[] ret = new byte[val.length]; - for (int i=0; i< val.length; i++) { - ret[i] = (byte)(val[i] - (byte)'0'); - } - log("convertAsciitoValues: returns:" + Arrays.toString(val)); - return ret; - } - - private byte[] convertSourceInfoToSetBroadcastCodeByteArray(BleBroadcastSourceInfo srcInfo) { - - byte[] res = new byte[PIN_CODE_CMD_LEN]; - res[0] = BASS_SET_BCAST_PIN_OPCODE; - res[1] = srcInfo.getSourceId(); - log("convertSourceInfoToSetBroadcastCodeByteArray: Source device : " + srcInfo.getSourceDevice()); - byte[] actualPIN = null; - //srcInfo.getSourceDevice() will be NULL if this request coming from SDK - // srcInfo.getSourceDevice() will have valid Source device only If this is - //collocated device - if (srcInfo.getSourceDevice() != null && - isAddedBroadcastSourceIsLocal(srcInfo.getSourceDevice())) { - //colocated Source addition - //query the Encryption Key from BMS and update - ///*_BMS - actualPIN = mBAService.GetEncryptionKey(null); - //_BMS*/ - log("colocatedBcastCode is " + Arrays.toString(actualPIN)); - } else { - //Can Keep as ASCII as is - String reversePIN = new StringBuffer(srcInfo.getBroadcastCode()).reverse().toString(); - actualPIN = reversePIN.getBytes(); - } - if (actualPIN == null) { - Log.e(TAG, "actual PIN is null"); - return null; - } else { - log( "byte array broadcast Code:" + Arrays.toString(actualPIN)); - log( "pinLength:" + actualPIN.length); - - //Fill the PIN code in the Last Position - System.arraycopy(actualPIN, 0, res, ((PIN_CODE_CMD_LEN)-actualPIN.length), actualPIN.length); - - log("SET_BCAST_PIN in Bytes"); - BassUtils.printByteArray(res); - } - return res; - } - - private boolean IsItRightTimeToUpdateBroadcastPIN(byte srcId) { - Collection srcInfos = mBleBroadcastSourceInfos.values(); - Iterator iterator = srcInfos.iterator(); - boolean ret = false; - if (mForceSB) { - log("force SB is set"); - return true; - } - while (iterator.hasNext()) { - BleBroadcastSourceInfo sI = iterator.next(); - if (sI == null) { - log("src Info is null"); - continue; - } - if (srcId == sI.getSourceId() && - sI.getEncryptionStatus() == BleBroadcastSourceInfo.BROADCAST_ASSIST_ENC_STATE_PIN_NEEDED) { - ret = true; - break; - } - } - log("IsItRightTimeToUpdateBroadcastPIN returning:" + ret); - return ret; - } - - @VisibleForTesting - class Connected extends State { - @Override - public void enter() { - log( "Enter Connected(" + mDevice + "): " - + messageWhatToString(getCurrentMessage().what)); - - removeDeferredMessages(CONNECT); - if (mLastConnectionState == BluetoothProfile.STATE_CONNECTED) { - log("CONNECTED->CONNTECTED: Ignore"); - } else { - broadcastConnectionState(mDevice, mLastConnectionState, - BluetoothProfile.STATE_CONNECTED); - //initialize PACs for this devices - if (mPacsAvail == true) { - /* - PacsClientService mPacsClientService = PacsClientService.getPacsClientService(); - if (mPacsClientService != null) { - log("trigger connect to Pacs"); - mPacsClientService.connect(mDevice); - } else { - Log.e(TAG, "PACs interface is null"); - } - */ - } - - ///*_VCP - if (mVcpForBroadcast) { - VcpController vcpController = VcpController.getVcpController(); - if (vcpController != null) { - log("trigger connect to Vcp Renderer"); - if (!vcpController.connect(mDevice, BluetoothVcp.MODE_BROADCAST)) { - log("Connect vcp failed"); - } - } else { - Log.e(TAG, "VcpController interface is null"); - } - } - //_VCP*/ - } - } - - @Override - public void exit() { - log("Exit Connected(" + mDevice + "): " - + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_CONNECTED; - } - - @Override - public boolean processMessage(Message message) { - log("Connected process message(" + mDevice + "): " - + messageWhatToString(message.what)); - BleBroadcastSourceInfo srcInfo; - switch (message.what) { - case CONNECT: - Log.w(TAG, "Connected: CONNECT ignored: " + mDevice); - break; - case DISCONNECT: - log("Disconnecting from " + mDevice); - if (mBluetoothGatt != null) { - mBluetoothGatt.disconnect(); - mBluetoothGatt.close(); - mBluetoothGatt = null; - //transitionTo(mDisconnecting); - cancelActiveSync(null); - //Trigger the CSip disconnection, dont worry about pass/failure - if (mCsipConnected && mSetCoordinator != null) { - mSetCoordinator.disconnect(mService.mCsipAppId, mDevice); - mCsipConnected = false; - } - transitionTo(mDisconnected); - } else { - log("mBluetoothGatt is null"); - } - break; - case CONNECTION_STATE_CHANGED: - int state = (int)message.obj; - Log.w(TAG, "Connected:connection state changed:" + state); - if (state == BluetoothProfile.STATE_CONNECTED) { - Log.w(TAG, "device is already connected to Bass" + mDevice); - } else { - Log.w(TAG, "unexpected disconnected from " + mDevice); - cancelActiveSync(null); - ///*_CSIP - //Trigger the CSip disconnection, dont worry about pass/failure - if (mCsipConnected) { - mSetCoordinator.disconnect(mService.mCsipAppId, mDevice); - mCsipConnected = false; - } - //_CSIP*/ - transitionTo(mDisconnected); - } - break; - case READ_BASS_CHARACTERISTICS: - BluetoothGattCharacteristic characteristic = (BluetoothGattCharacteristic)message.obj; - if (mBluetoothGatt != null) { - mBluetoothGatt.readCharacteristic(characteristic); - transitionTo(mConnectedProcessing); - } else { - Log.e(TAG, "READ_BASS_CHARACTERISTICS is ignored, Gatt handle is null"); - } - break; - case START_SCAN_OFFLOAD: - if (mBluetoothGatt != null && - mBroadcastScanControlPoint != null) { - mBroadcastScanControlPoint.setValue(REMOTE_SCAN_START); - mBluetoothGatt.writeCharacteristic(mBroadcastScanControlPoint); - mPendingOperation = message.what; - transitionTo(mConnectedProcessing); - } else { - log("no Bluetooth Gatt handle, may need to fetch write"); - } - break; - case STOP_SCAN_OFFLOAD: - if (mBluetoothGatt != null && - mBroadcastScanControlPoint != null) { - mBroadcastScanControlPoint.setValue(REMOTE_SCAN_STOP); - mBluetoothGatt.writeCharacteristic(mBroadcastScanControlPoint); - mPendingOperation = message.what; - transitionTo(mConnectedProcessing); - } else { - log("no Bluetooth Gatt handle, may need to fetch write"); - } - break; - case SELECT_BCAST_SOURCE: - ScanResult scanRes = (ScanResult)message.obj; - boolean auto = ((int) message.arg1) == AUTO; - boolean isGroupOp = ((int) message.arg2) == GROUP_OP; - selectBroadcastSource(scanRes, isGroupOp, auto); - break; - case ADD_BCAST_SOURCE: - srcInfo = (BleBroadcastSourceInfo)message.obj; - log("Adding Broadcast source" + srcInfo); - byte[] addSourceInfo = convertSourceInfoToAddSourceByteArray(srcInfo); - if (addSourceInfo == null) { - Log.e(TAG, "add source: source Info is NULL"); - break; - } - if (mBluetoothGatt != null && - mBroadcastScanControlPoint != null) { - mBroadcastScanControlPoint.setValue(addSourceInfo); - mBluetoothGatt.writeCharacteristic(mBroadcastScanControlPoint); - mPendingOperation = message.what; - transitionTo(mConnectedProcessing); - sendMessageDelayed(GATT_TXN_TIMEOUT, GATT_TXN_TIMEOUT_MS); - } else { - Log.e(TAG, "ADD_BCAST_SOURCE: no Bluetooth Gatt handle, Fatal"); - sendPendingCallbacks(ADD_BCAST_SOURCE,INVALID_SRC_ID, - BleBroadcastAudioScanAssistCallback.BASS_STATUS_FATAL); - } - break; - case UPDATE_BCAST_SOURCE: - srcInfo = (BleBroadcastSourceInfo)message.obj; - mAutoTriggerred = ((int) message.arg1) == AUTO; - log("Updating Broadcast source" + srcInfo); - byte[] updateSourceInfo = convertSourceInfoToUpdateSourceByteArray(srcInfo); - if (updateSourceInfo == null) { - Log.e(TAG, "update source: source Info is NULL"); - break; - } - if (mBluetoothGatt != null && - mBroadcastScanControlPoint != null) { - mBroadcastScanControlPoint.setValue(updateSourceInfo); - mBluetoothGatt.writeCharacteristic(mBroadcastScanControlPoint); - mPendingOperation = message.what; - mPendingSourceId = srcInfo.getSourceId(); - transitionTo(mConnectedProcessing); - sendMessageDelayed(GATT_TXN_TIMEOUT, GATT_TXN_TIMEOUT_MS); - } else { - Log.e(TAG, "UPDATE_BCAST_SOURCE: no Bluetooth Gatt handle, Fatal"); - sendPendingCallbacks(UPDATE_BCAST_SOURCE,INVALID_SRC_ID, - BleBroadcastAudioScanAssistCallback.BASS_STATUS_FATAL); - } - break; - case SET_BCAST_CODE: - srcInfo = (BleBroadcastSourceInfo)message.obj; - int cmdType = message.arg1; - log("SET_BCAST_CODE srcInfo: " + srcInfo); - - if (cmdType != QUEUED && - IsItRightTimeToUpdateBroadcastPIN(srcInfo.getSourceId()) != true) { - mSetBroadcastCodePending = true; - mSetBroadcastPINSrcInfo = srcInfo; - log("Ignore SET_BCAST now, but store it for later"); - //notify so that lock release happens as SET_BCAST_CODE - //queued for future - mService.notifyOperationCompletion(mDevice,SET_BCAST_CODE); - } else { - byte[] setBroadcastPINcmd = convertSourceInfoToSetBroadcastCodeByteArray(srcInfo); - if (setBroadcastPINcmd == null) { - Log.e(TAG, "SET_BCAST_CODE: Broadcast code is NULL"); - break; - } - if (mBluetoothGatt != null && - mBroadcastScanControlPoint != null) { - mBroadcastScanControlPoint.setValue(setBroadcastPINcmd); - mBluetoothGatt.writeCharacteristic(mBroadcastScanControlPoint); - mPendingOperation = message.what; - mPendingSourceId = srcInfo.getSourceId(); - transitionTo(mConnectedProcessing); - sendMessageDelayed(GATT_TXN_TIMEOUT, GATT_TXN_TIMEOUT_MS); - } else { - Log.e(TAG, "SET_BCAST_CODE: no Bluetooth Gatt handle, Fatal"); - sendPendingCallbacks(SET_BCAST_CODE,INVALID_SRC_ID, - BleBroadcastAudioScanAssistCallback.BASS_STATUS_FATAL); - - } - } - break; - case REMOVE_BCAST_SOURCE: - byte sourceId = (byte)message.arg1; - BluetoothDevice audioSrc = (BluetoothDevice)message.obj; - log("Removing Broadcast source: audioSource:" + audioSrc + "sourceId:" + sourceId); - byte[] removeSourceInfo = new byte [2]; - removeSourceInfo[0] = BASS_REMOVE_SOURCE_OPCODE; - removeSourceInfo[1] = sourceId; - if (mBluetoothGatt != null && - mBroadcastScanControlPoint != null) { - mBroadcastScanControlPoint.setValue(removeSourceInfo); - mBluetoothGatt.writeCharacteristic(mBroadcastScanControlPoint); - mPendingOperation = message.what; - mPendingSourceId = sourceId; - transitionTo(mConnectedProcessing); - sendMessageDelayed(GATT_TXN_TIMEOUT, GATT_TXN_TIMEOUT_MS); - } else { - Log.e(TAG, "REMOVE_BCAST_SOURCE: no Bluetooth Gatt handle, Fatal"); - sendPendingCallbacks(REMOVE_BCAST_SOURCE,INVALID_SRC_ID, - BleBroadcastAudioScanAssistCallback.BASS_STATUS_FATAL); - - } - break; - case PSYNC_ACTIVE_TIMEOUT: - cancelActiveSync(null); - break; - default: - log("CONNECTED: not handled message:" + message.what); - return NOT_HANDLED; - } - return HANDLED; - } - } - - - void sendPendingCallbacks(int pendingOp, byte sourceId, int status) { - if (status != 0) { - //Notify service only In case of failure cases - //Success case would have been notified through State machine anyways - mService.notifyOperationCompletion(mDevice, pendingOp); - } - switch (pendingOp) { - case START_SCAN_OFFLOAD: - if (status != 0) { - if (mAutoTriggerred == false) { - log("notify the app only if start Scan offload fails"); - //shouldnt happen in general - mService.sendBroadcastSourceSelectedCallback(mDevice, null, status); - cancelActiveSync(null); - } else { - mAutoTriggerred = false; - } - } - break; - case ADD_BCAST_SOURCE: - if (status != 0) { - sourceId = INVALID_SRC_ID; - cancelActiveSync(null); - //stop Scan offload for colocated case - mService.stopScanOffloadInternal(mDevice, false); - } - mService.sendAddBroadcastSourceCallback(mDevice, sourceId, status); - break; - case UPDATE_BCAST_SOURCE: - if (mAutoTriggerred == false) { - mService.sendUpdateBroadcastSourceCallback(mDevice, sourceId, status); - } else { - mAutoTriggerred = false; - } - break; - case REMOVE_BCAST_SOURCE: - mService.sendRemoveBroadcastSourceCallback(mDevice, sourceId, status); - break; - case SET_BCAST_CODE: - mService.sendSetBroadcastPINupdatedCallback(mDevice, sourceId, status); - break; - default: - { - log("sendPendingCallbacks: unhandled case"); - } - } - } - @VisibleForTesting - class ConnectedProcessing extends State { - @Override - public void enter() { - log( "Enter ConnectedProcessing(" + mDevice + "): " + messageWhatToString( - getCurrentMessage().what)); - } - - @Override - public void exit() { - log("Exit ConnectedProcessing(" + mDevice + "): " + messageWhatToString( - getCurrentMessage().what)); - } - @Override - public boolean processMessage(Message message) { - log("ConnectedProcessing process message(" + mDevice + "): " + messageWhatToString( - message.what)); - switch (message.what) { - case CONNECT: - Log.w(TAG, "CONNECT request is ignored" + mDevice); - break; - case DISCONNECT: - Log.w(TAG, "DISCONNECT requested!: " + mDevice); - if (mBluetoothGatt != null) { - mBluetoothGatt.disconnect(); - mBluetoothGatt.close(); - mBluetoothGatt = null; - cancelActiveSync(null); - //Trigger the CSIP disconnection, dont worry about pass/failure - if (mCsipConnected && mSetCoordinator != null) { - mSetCoordinator.disconnect(mService.mCsipAppId, mDevice); - mCsipConnected = false; - } - transitionTo(mDisconnected); - } else { - log("mBluetoothGatt is null"); - } - break; - case READ_BASS_CHARACTERISTICS: - Log.w(TAG, "defer READ_BASS_CHARACTERISTICS requested!: " + mDevice); - deferMessage(message); - break; - case CONNECTION_STATE_CHANGED: - int state = (int)message.obj; - Log.w(TAG, "ConnectedProcessing: connection state changed:" + state); - if (state == BluetoothProfile.STATE_CONNECTED) { - Log.w(TAG, "should never happen from this state"); - } else { - Log.w(TAG, "Unexpected disconnection " + mDevice); - transitionTo(mDisconnected); - } - break; - case GATT_TXN_PROCESSED: - removeMessages(GATT_TXN_TIMEOUT); - int status = (int)message.arg1; - log( "GATT transaction processed for" + mDevice); - mService.notifyOperationCompletion(mDevice, mPendingOperation); - if (status == BluetoothGatt.GATT_SUCCESS) { - if (mPendingOperation == SET_BCAST_CODE) { - //If Pending operation is SET_BCAST_CODE - //send callback to notify BCAST is updated - //This is needed only for SET_BCAST operation - sendPendingCallbacks(mPendingOperation, - mPendingSourceId, BleBroadcastAudioScanAssistCallback.BASS_STATUS_SUCCESS); - } - } else { - //any failure to write operation - //will be converted to corresponding - //callback with failure status - sendPendingCallbacks(mPendingOperation, - mPendingSourceId, BleBroadcastAudioScanAssistCallback.BASS_STATUS_FAILURE); - } - transitionTo(mConnected); - break; - case GATT_TXN_TIMEOUT: - log( "GATT transaction timedout for" + mDevice); - mService.notifyOperationCompletion(mDevice, mPendingOperation); - sendPendingCallbacks(mPendingOperation, - mPendingSourceId, BleBroadcastAudioScanAssistCallback.BASS_STATUS_TXN_TIMEOUT); - mPendingOperation = -1; - transitionTo(mConnected); - mPendingSourceId = -1; - break; - case START_SCAN_OFFLOAD: - case STOP_SCAN_OFFLOAD: - case SELECT_BCAST_SOURCE: - case ADD_BCAST_SOURCE: - case SET_BCAST_CODE: - case REMOVE_BCAST_SOURCE: - case PSYNC_ACTIVE_TIMEOUT: - log("defer the message:" + message.what + "so that it will be processed later"); - deferMessage(message); - break; - default: - log("CONNECTEDPROCESSING: not handled message:" + message.what); - return NOT_HANDLED; - } - return HANDLED; - } - } - - - @VisibleForTesting - class Disconnecting extends State { - @Override - public void enter() { - log( "Enter Disconnecting(" + mDevice + "): " + messageWhatToString( - getCurrentMessage().what)); - sendMessageDelayed(CONNECT_TIMEOUT, mDevice, mConnectTimeoutMs); - broadcastConnectionState(mDevice, mLastConnectionState, - BluetoothProfile.STATE_DISCONNECTING); - } - @Override - public void exit() { - log("Exit Disconnecting(" + mDevice + "): " + messageWhatToString( - getCurrentMessage().what)); - removeMessages(CONNECT_TIMEOUT); - mLastConnectionState = BluetoothProfile.STATE_DISCONNECTING; - } - @Override - public boolean processMessage(Message message) { - log("Disconnecting process message(" + mDevice + "): " + messageWhatToString( - message.what)); - switch (message.what) { - case CONNECT: - log("Disconnecting to " + mDevice); - log("deferring this connection request " + mDevice); - deferMessage(message); - break; - case DISCONNECT: - Log.w(TAG, "Already disconnecting: DISCONNECT ignored: " + mDevice); - break; - case CONNECTION_STATE_CHANGED: - int state = (int)message.obj; - Log.w(TAG, "Disconnecting: connection state changed:" + state); - if (state == BluetoothProfile.STATE_CONNECTED) { - Log.e(TAG, "should never happen from this state"); - transitionTo(mConnected); - } else { - Log.w(TAG, "disconnection successfull to " + mDevice); - cancelActiveSync(null); - transitionTo(mDisconnected); - ///*_CSIP - //Trigger the CSip disconnection, dont worry about pass/failure - if (mCsipConnected) { - mSetCoordinator.disconnect(mService.mCsipAppId, mDevice); - mCsipConnected = false; - } - //_CSIP*/ - } - break; - case CONNECT_TIMEOUT: - Log.w(TAG, "CONNECT_TIMEOUT"); - - BluetoothDevice device = (BluetoothDevice) message.obj; - if (!mDevice.equals(device)) { - Log.e(TAG, "Unknown device timeout " + device); - break; - } - transitionTo(mDisconnected); - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - } - - - void broadcastConnectionState(BluetoothDevice device, int fromState, int toState) { - log( "broadcastConnectionState " + device + ": " + fromState + "->" + toState); - if (fromState == BluetoothProfile.STATE_CONNECTED && - toState == BluetoothProfile.STATE_CONNECTED) { - log("CONNECTED->CONNTECTED: Ignore"); - return; - } - Intent intent = new Intent(BluetoothSyncHelper.ACTION_CONNECTION_STATE_CHANGED); - intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, fromState); - intent.putExtra(BluetoothProfile.EXTRA_STATE, toState); - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - mService.sendBroadcastAsUser(intent, UserHandle.ALL, - BLUETOOTH_CONNECT, Utils.getTempAllowlistBroadcastOptions()); - } - - int getConnectionState() { - String currentState = "Unknown"; - if (getCurrentState() != null) { - currentState = getCurrentState().getName(); - } - switch (currentState) { - case "Disconnected": - log("Disconnected"); - return BluetoothProfile.STATE_DISCONNECTED; - case "Disconnecting": - log("Disconnecting"); - return BluetoothProfile.STATE_DISCONNECTING; - case "Connecting": - log("Connecting"); - return BluetoothProfile.STATE_CONNECTING; - case "Connected": - case "ConnectedProcessing": - log("connected"); - return BluetoothProfile.STATE_CONNECTED; - default: - Log.e(TAG, "Bad currentState: " + currentState); - return BluetoothProfile.STATE_DISCONNECTED; - } - } - - BluetoothDevice getDevice() { - return mDevice; - } - - synchronized boolean isConnected() { - return getCurrentState() == mConnected; - } - - public static String messageWhatToString(int what) { - switch (what) { - case CONNECT: - return "CONNECT"; - case DISCONNECT: - return "DISCONNECT"; - case CONNECTION_STATE_CHANGED: - return "CONNECTION_STATE_CHANGED"; - case GATT_TXN_PROCESSED: - return "GATT_TXN_PROCESSED"; - case READ_BASS_CHARACTERISTICS: - return "READ_BASS_CHARACTERISTICS"; - case START_SCAN_OFFLOAD: - return "START_SCAN_OFFLOAD"; - case STOP_SCAN_OFFLOAD: - return "STOP_SCAN_OFFLOAD"; - case ADD_BCAST_SOURCE: - return "ADD_BCAST_SOURCE"; - case SELECT_BCAST_SOURCE: - return "SELECT_BCAST_SOURCE"; - case UPDATE_BCAST_SOURCE: - return "UPDATE_BCAST_SOURCE"; - case SET_BCAST_CODE: - return "SET_BCAST_CODE"; - case REMOVE_BCAST_SOURCE: - return "REMOVE_BCAST_SOURCE"; - case PSYNC_ACTIVE_TIMEOUT: - return "PSYNC_ACTIVE_TIMEOUT"; - case CSIP_CONNECTION_STATE_CHANGED: - return "CSIP_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); - } - - public void dump(StringBuilder sb) { - ProfileService.println(sb, "mDevice: " + mDevice); - ProfileService.println(sb, " StateMachine: " + this); - // Dump the state machine logs - StringWriter stringWriter = new StringWriter(); - PrintWriter printWriter = new PrintWriter(stringWriter); - super.dump(new FileDescriptor(), printWriter, new String[]{}); - printWriter.flush(); - stringWriter.flush(); - ProfileService.println(sb, " StateMachineLog:"); - Scanner scanner = new Scanner(stringWriter.toString()); - while (scanner.hasNextLine()) { - String line = scanner.nextLine(); - ProfileService.println(sb, " " + line); - } - scanner.close(); - } - - @Override - protected void log( String msg) { - if (BASS_DBG) { - super.log(msg); - } - } - - private static void logByteArray(String prefix, byte[] value, int offset, int count) { - StringBuilder builder = new StringBuilder(prefix); - for (int i = offset; i < count; i++) { - builder.append(String.format("0x%02X", value[i])); - if (i != value.length - 1) { - builder.append(", "); - } - } - Log.d(TAG, builder.toString()); - } -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/bassclient/BassCsetManager.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/bassclient/BassCsetManager.java deleted file mode 100644 index fd2be7c6623ca3745cf2ea13b993b791c7294b94..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/bassclient/BassCsetManager.java +++ /dev/null @@ -1,592 +0,0 @@ -/* - * Copyright (c) 2020 The Linux Foundation. All rights reserved. - * - * 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. - */ - -/** - * Bass CSET managet StateMachine. There is one instance per Coordinated "set Id". - * - "Idle" and "Locked" are steady states. - * - "Locking" is a transient states until the - * Locking confirmation comes from upper layers. - * - Once lock is acquired, profile dont try to unlock - * - * (Idle) - * | ^ - * LOCK | | UNLOCK - * V | - * (Locking)<->(Unlocking) - * | ^ - * ON_LOCK | | ON_UNLOCK - * V | - * (Locked) - * - * - */ - -package com.android.bluetooth.bc; - -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothUuid; -import android.bluetooth.BluetoothProfile; -import android.bluetooth.BluetoothGattCallback; -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothGattCharacteristic; -import android.bluetooth.BluetoothGattDescriptor; -import android.bluetooth.le.ScanResult; -import android.bluetooth.le.ScanRecord; -import android.bluetooth.le.ScanCallback; -import android.bluetooth.BluetoothGattService; -import android.bluetooth.BluetoothSyncHelper; -import android.bluetooth.BleBroadcastSourceInfo; -import android.bluetooth.BleBroadcastSourceChannel; -import android.bluetooth.BleBroadcastAudioScanAssistManager; -import android.bluetooth.IBleBroadcastAudioScanAssistCallback; -import android.bluetooth.le.BluetoothLeScanner; -import android.bluetooth.le.PeriodicAdvertisingCallback; -import android.bluetooth.le.PeriodicAdvertisingManager; -import android.bluetooth.le.PeriodicAdvertisingReport; - -///*_CSIP -//CSET -import android.bluetooth.BluetoothDeviceGroup; -import com.android.bluetooth.groupclient.GroupService; -//_CSIP*/ - -import android.bluetooth.IBluetoothManager; -import android.os.ServiceManager; -import android.os.IBinder; - -import java.util.List; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Iterator; -import android.content.Intent; -import android.os.Looper; -import android.os.Message; -import android.util.Log; -import java.util.UUID; -import java.util.Collection; -import android.os.UserHandle; - -import com.android.bluetooth.btservice.ProfileService; -import com.android.bluetooth.btservice.ServiceFactory; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Scanner; -import java.util.Map; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Set; -import java.lang.String; -import java.lang.StringBuffer; -import java.lang.Integer; - -import java.nio.ByteBuffer; -import java.lang.Byte; -import java.util.stream.IntStream; -import android.os.SystemProperties; -import android.os.ParcelUuid; - -final class BassCsetManager extends StateMachine { - private static final String TAG = "BassCsetManager"; - - //Considered as Coordinated ops - static final int BASS_GRP_START_SCAN_OFFLOAD = 6; - static final int BASS_GRP_STOP_SCAN_OFFLOAD = 7; - static final int BASS_GRP_ADD_BCAST_SOURCE = 9; - static final int BASS_GRP_UPDATE_BCAST_SOURCE = 10; - static final int BASS_GRP_SET_BCAST_CODE = 11; - static final int BASS_GRP_REMOVE_BCAST_SOURCE = 12; - - static final int LOCK = 17; - static final int UNLOCK = 18; - static final int LOCK_STATE_CHANGED = 3; - static final int LOCK_TIMEOUT = 4; - static final int ON_CSIP_CONNECTED = 5; - - //10 secs time out for all gatt writes - static final int LOCK_TIMEOUT_MS = 10000; - - - @VisibleForTesting - private static final int CONNECT_TIMEOUT = 201; - - private final Idle mIdle; - private final Locking mLocking; - private final Locked mLocked; - private final LockedProcessing mLockedProcessing; - private final Unlocking mUnlocking; - - private BCService mBCService; - private final BluetoothDevice mDevice; - private final int mSetId; - private List mMemberDevices = null; - - ///*_CSIP - //CSIP Locking Interfaces - private GroupService mSetCoordinator = GroupService.getGroupService(); - //_CSIP*/ - - BassCsetManager(int setId, BluetoothDevice masterDevice, BCService svc, - Looper looper) { - super(TAG, looper); - mSetId = setId; - mBCService = svc; - - mIdle = new Idle(); - mLocked = new Locked(); - mLockedProcessing = new LockedProcessing(); - mLocking = new Locking(); - mUnlocking = new Unlocking(); - - addState(mIdle); - addState(mLocking); - addState(mLocked); - addState(mLockedProcessing); - addState(mUnlocking); - - setInitialState(mIdle); - mDevice = masterDevice; - mMemberDevices = new ArrayList(); - - } - - static BassCsetManager make(int setId, BluetoothDevice masterDevice, BCService svc, - Looper looper) { - Log.d(TAG, "make for setId, setId " + setId + ": masterDevice" + masterDevice); - BassCsetManager BassclientSm = new BassCsetManager(setId, masterDevice, svc, - looper); - BassclientSm.start(); - return BassclientSm; - } - - public void doQuit() { - log("doQuit for device " + mDevice); - quitNow(); - } - - public void cleanup() { - log("cleanup for device " + mDevice); - } - - @VisibleForTesting - class Idle extends State { - @Override - public void enter() { - log( "Enter Idle(" + mSetId + "): " + messageWhatToString( - getCurrentMessage().what)); - mMemberDevices = null; - - } - - @Override - public void exit() { - log("Exit Idle(" + mSetId + "): " + messageWhatToString( - getCurrentMessage().what)); - } - - @Override - public boolean processMessage(Message message) { - log("Idle process message(" + mSetId + "): " + messageWhatToString( - message.what)); - - switch (message.what) { - case BASS_GRP_START_SCAN_OFFLOAD: - case BASS_GRP_STOP_SCAN_OFFLOAD: - case BASS_GRP_ADD_BCAST_SOURCE: - case BASS_GRP_UPDATE_BCAST_SOURCE: - case BASS_GRP_SET_BCAST_CODE: - case BASS_GRP_REMOVE_BCAST_SOURCE: - //defer the meesage and move to Locked - deferMessage(message); - //Intentional miss of break - case LOCK: - //treat Connect & Lock as same request - log("Locking to " + mSetId); - //get CSIP connection status for BluetoothDevice - //if CSIP disconnected: start Connect Procedure (mostly hpns only at first time) - //if CSIP connected: start Lock Procedure - ///*_CSIP - mSetCoordinator.setLockValue(mBCService.mCsipAppId, mSetId, null, BluetoothDeviceGroup.ACCESS_GRANTED); - //_CSIP*/ - transitionTo(mLocking); - - //transitionTo(mLocked); - break; - case UNLOCK: - Log.w(TAG, "Idle: UNLOCK ignored: " + mSetId); - break; - case LOCK_STATE_CHANGED: - //This most likely not happen - ///*_CSIP - int value = (int)message.arg1; - List devices = (List)message.obj; - Log.w(TAG, "Lock state changed:" + value); - if (value == BluetoothDeviceGroup.ACCESS_GRANTED) { - transitionTo(mLocked); - } else { - Log.w(TAG, "Idle: Lock failed to " + mSetId); - } - //_CSIP*/ - break; - case ON_CSIP_CONNECTED: - //starts the Lock procedure - //Only reason why we Connect is to Lock - // - //Dont transition the state - default: - log("Idle: not handled message:" + message.what); - return NOT_HANDLED; - } - return HANDLED; - } - } - - @VisibleForTesting - class Locking extends State { - @Override - public void enter() { - log( "Enter Locking(" + mSetId + "): " + messageWhatToString( - getCurrentMessage().what)); - } - - @Override - public void exit() { - log("Exit Locking(" + mSetId + "): " + messageWhatToString( - getCurrentMessage().what)); - } - - @Override - public boolean processMessage(Message message) { - log("Locking process message(" + mSetId + "): " + messageWhatToString( - message.what)); - - switch (message.what) { - - case BASS_GRP_START_SCAN_OFFLOAD: - case BASS_GRP_STOP_SCAN_OFFLOAD: - case BASS_GRP_ADD_BCAST_SOURCE: - case BASS_GRP_UPDATE_BCAST_SOURCE: - case BASS_GRP_SET_BCAST_CODE: - case BASS_GRP_REMOVE_BCAST_SOURCE: - //defer the meesage and move to Locked - deferMessage(message); - break; - case LOCK: - log("Already Locking to " + mSetId); - log("Ignore this Lock request " + mSetId); - break; - case UNLOCK: - Log.w(TAG, "Locking: UNLOCK deferred: " + mSetId); - deferMessage(message); - break; - case LOCK_STATE_CHANGED: - ///*_CSIP - int value = (int)message.arg1; - Log.w(TAG, "Lock state changed:" + value); - if (value == BluetoothDeviceGroup.ACCESS_GRANTED) { - List devices = (List)message.obj; - mMemberDevices = devices; - transitionTo(mLocked); - } else { - Log.w(TAG, "Locking: Unlocked to " + mSetId); - transitionTo(mIdle); - } - //_CSIP*/ - break; - case ON_CSIP_CONNECTED: - //starts the Lock procedure - //Only reason why we Connect is to Lock - // - //Dont transition the state - break; - default: - log("LOCKING: not handled message:" + message.what); - return NOT_HANDLED; - } - return HANDLED; - } - } - - @VisibleForTesting - class Locked extends State { - @Override - public void enter() { - log( "Enter Locked(" + mSetId + "): " - + messageWhatToString(getCurrentMessage().what)); - - removeDeferredMessages(LOCK); - - } - - @Override - public void exit() { - log("Exit Locked(" + mSetId + "): " - + messageWhatToString(getCurrentMessage().what)); - } - - @Override - public boolean processMessage(Message message) { - log("Locked process message(" + mSetId + "): " - + messageWhatToString(message.what)); - BleBroadcastSourceInfo srcInfo; - switch (message.what) { - case LOCK: - Log.w(TAG, "Locked: Lock ignored: " + mSetId); - break; - case UNLOCK: - log("Unlocking from " + mDevice); - //trigger unlock procedure - ///*_CSIP - mSetCoordinator.setLockValue(mBCService.mCsipAppId, mSetId, null, BluetoothDeviceGroup.ACCESS_RELEASED); - transitionTo(mUnlocking); - //_CSIP*/ - - //transitionTo(mIdle); - break; - case LOCK_STATE_CHANGED: - ///*_CSIP - int value = (int)message.arg1; - List devices = (List)message.obj; - Log.w(TAG, "Lock state changed:" + value); - if (value == BluetoothDeviceGroup.ACCESS_GRANTED) { - transitionTo(mLocked); - } else { - Log.w(TAG, "Locking: Unlocked to " + mSetId); - transitionTo(mIdle); - } - //_CSIP*/ - break; - case BASS_GRP_START_SCAN_OFFLOAD: - if (mBCService != null) { - log("START_SCAN_OFFLOAD: " + mMemberDevices); - mBCService.startScanOffload(mDevice, mMemberDevices); - transitionTo(mLockedProcessing); - } else { - log("no Bassclient service handle"); - } - break; - case BASS_GRP_STOP_SCAN_OFFLOAD: - if (mBCService != null) { - log("STOP_SCAN_OFFLOAD: " + mMemberDevices); - mBCService.stopScanOffload(mDevice, mMemberDevices); - transitionTo(mLockedProcessing); - } else { - log("no Bassclient service handle"); - } - break; - case BASS_GRP_ADD_BCAST_SOURCE: - srcInfo = (BleBroadcastSourceInfo)message.obj; - if (mBCService != null) { - mBCService.addBroadcastSource(mDevice, mMemberDevices, srcInfo); - transitionTo(mLockedProcessing); - } else { - log("no Bassclient service handle"); - } - break; - case BASS_GRP_UPDATE_BCAST_SOURCE: - srcInfo = (BleBroadcastSourceInfo)message.obj; - if (mBCService != null) { - mBCService.updateBroadcastSource(mDevice, mMemberDevices, srcInfo); - transitionTo(mLockedProcessing); - } else { - log("no Bassclient service handle"); - } - break; - case BASS_GRP_SET_BCAST_CODE: - srcInfo = (BleBroadcastSourceInfo)message.obj; - if (mBCService != null) { - mBCService.setBroadcastCode(mDevice, mMemberDevices, srcInfo); - transitionTo(mLockedProcessing); - } else { - log("no Bassclient service handle"); - } - break; - case BASS_GRP_REMOVE_BCAST_SOURCE: - byte sourceId = (byte)message.arg1; - if (mBCService != null) { - mBCService.removeBroadcastSource(mDevice, mMemberDevices, sourceId); - transitionTo(mLockedProcessing); - } else { - log("no Bassclient service handle"); - } - break; - default: - log("Locked: not handled message:" + message.what); - return NOT_HANDLED; - } - return HANDLED; - } - } - - @VisibleForTesting - class LockedProcessing extends State { - @Override - public void enter() { - log( "Enter LockedProcessing(" + mSetId + "): " - + messageWhatToString(getCurrentMessage().what)); - } - - @Override - public void exit() { - log("Exit LockedProcessing(" + mSetId + "): " - + messageWhatToString(getCurrentMessage().what)); - } - - @Override - public boolean processMessage(Message message) { - log("LockedProcessing process message(" + mSetId + "): " - + messageWhatToString(message.what)); - BleBroadcastSourceInfo srcInfo; - switch (message.what) { - case UNLOCK: - log("LockedProcessing: UNLOCK defer " + mDevice); - deferMessage(message); - transitionTo(mLocked); - break; - case LOCK_STATE_CHANGED: - int value = (int)message.arg1; - Log.w(TAG, "Locking state changed:" + value); - //Should never happen - break; - case LOCK: - log("LockedProcessing: LOCK ignore " + mDevice); - break; - case BASS_GRP_START_SCAN_OFFLOAD: - case BASS_GRP_STOP_SCAN_OFFLOAD: - case BASS_GRP_ADD_BCAST_SOURCE: - case BASS_GRP_UPDATE_BCAST_SOURCE: - case BASS_GRP_SET_BCAST_CODE: - case BASS_GRP_REMOVE_BCAST_SOURCE: - //defer the meesage and move to Locked - if (hasDeferredMessages(UNLOCK)) { - //If Unlock is in pending list, remove it - //Override the UNLOCK with this new operation - log("removing the unlock message, as there is another req"); - removeDeferredMessages(UNLOCK); - } - deferMessage(message); - break; - default: - log("LockedProcessing: not handled message:" + message.what); - return NOT_HANDLED; - } - return HANDLED; - } - } - - - @VisibleForTesting - class Unlocking extends State { - @Override - public void enter() { - log( "Enter Unlocking(" + mSetId + "): " - + messageWhatToString(getCurrentMessage().what)); - - //removeDeferredMessages(LOCK); - - } - - @Override - public void exit() { - log("Exit Unlocking(" + mSetId + "): " - + messageWhatToString(getCurrentMessage().what)); - } - - @Override - public boolean processMessage(Message message) { - log("Locked process message(" + mSetId + "): " - + messageWhatToString(message.what)); - BleBroadcastSourceInfo srcInfo; - switch (message.what) { - case UNLOCK: - log("Unlocking: UNLOCK ignored from " + mDevice); - break; - case LOCK_STATE_CHANGED: - ///*_CSIP - int value = (int)message.arg1; - Log.w(TAG, "Locking state changed:" + value); - if (value == BluetoothDeviceGroup.ACCESS_RELEASED) { - mMemberDevices = null; - transitionTo(mIdle); - } else { - Log.w(TAG, "UnLocking: failed to " + mSetId); - //keep that back in Locked? - transitionTo(mLocked); - // - } - //_CSIP*/ - break; - case LOCK: - case BASS_GRP_START_SCAN_OFFLOAD: - case BASS_GRP_STOP_SCAN_OFFLOAD: - case BASS_GRP_ADD_BCAST_SOURCE: - case BASS_GRP_UPDATE_BCAST_SOURCE: - case BASS_GRP_SET_BCAST_CODE: - case BASS_GRP_REMOVE_BCAST_SOURCE: - //defer the meesage and move to Locked - deferMessage(message); - break; - default: - log("Locked: not handled message:" + message.what); - return NOT_HANDLED; - } - return HANDLED; - } - } - - - private static String messageWhatToString(int what) { - switch (what) { - case LOCK: - return "LOCK"; - case UNLOCK: - return "UNLOCK"; - case LOCK_STATE_CHANGED: - return "LOCK_STATE_CHANGED"; - case BASS_GRP_START_SCAN_OFFLOAD: - return "BASS_GRP_START_SCAN_OFFLOAD"; - case BASS_GRP_STOP_SCAN_OFFLOAD: - return "BASS_GRP_STOP_SCAN_OFFLOAD"; - case BASS_GRP_ADD_BCAST_SOURCE: - return "BASS_GRP_ADD_BCAST_SOURCE"; - case BASS_GRP_UPDATE_BCAST_SOURCE: - return "BASS_GRP_UPDATE_BCAST_SOURCE"; - case BASS_GRP_SET_BCAST_CODE: - return "BASS_GRP_SET_BCAST_CODE"; - case BASS_GRP_REMOVE_BCAST_SOURCE: - return "BASS_GRP_REMOVE_BCAST_SOURCE"; - default: - break; - } - return Integer.toString(what); - } - - @Override - protected void log( String msg) { - if (BassClientStateMachine.BASS_DBG) { - super.log(msg); - } - } -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/bassclient/BassUtils.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/bassclient/BassUtils.java deleted file mode 100644 index 9289198a44f4fc1d542bdd3a3649b7e99b72a60a..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/bassclient/BassUtils.java +++ /dev/null @@ -1,506 +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. - * - ******************************************************************************/ - -package com.android.bluetooth.bc; - -import java.util.List; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Iterator; -import android.os.Looper; -import android.os.Message; -import android.util.Log; -import java.util.UUID; -import java.util.Collection; -import android.os.UserHandle; - -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; -import java.nio.charset.StandardCharsets; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Scanner; -import java.util.Map; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Set; -import java.lang.String; -import java.lang.StringBuffer; -import java.lang.Integer; - -import java.nio.ByteBuffer; -import java.lang.Byte; -import java.util.stream.IntStream; -import java.util.NoSuchElementException; - -import android.bluetooth.le.ScanResult; -import android.bluetooth.le.ScanSettings; -import android.bluetooth.le.ScanFilter; -import android.bluetooth.le.ScanCallback; -import android.bluetooth.le.ScanRecord; -import android.bluetooth.le.BluetoothLeScanner; -import java.util.UUID; -import android.os.Handler; -import android.os.ParcelUuid; -import android.os.SystemProperties; -import android.os.RemoteException; - -import android.bluetooth.BleBroadcastSourceInfo; -import android.bluetooth.BleBroadcastSourceChannel; -//import android.bluetooth.BluetoothBroadcast; -import android.bluetooth.BluetoothProfile; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import com.android.bluetooth.btservice.ServiceFactory; -///*_BMS -import com.android.bluetooth.broadcast.BroadcastService; -//_BMS*/ -import android.bluetooth.BluetoothCodecConfig; -/*_PACS -import com.android.bluetooth.pacsclient.PacsClientService; -_PACS*/ -import android.bluetooth.IBleBroadcastAudioScanAssistCallback; - -/** - * Bass Utility functions - */ - -final class BassUtils { - private static final String TAG = "BassUtils"; - /*LE Scan related members*/ - private boolean mBroadcastersAround = false; - private BluetoothAdapter mBluetoothAdapter = null; - private BluetoothLeScanner mLeScanner = null; - private BCService mBCService = null; - - ///*_BMS - private BroadcastService mBAService = null; - //_BMS*/ - public static final String BAAS_UUID = "00001852-0000-1000-8000-00805F9B34FB"; - private boolean mIsLocalBMSNotified = false; - private ServiceFactory mFactory = new ServiceFactory(); - //Using ArrayList as KEY to hashmap. May be not risk - //in this case as It is used to track the callback to cancel Scanning later - private final Map, ScanCallback> mLeAudioSourceScanCallbacks; - private final Map mBassAutoAssist; - - private static final int AA_START_SCAN = 1; - private static final int AA_SCAN_SUCCESS = 2; - private static final int AA_SCAN_FAILURE = 3; - private static final int AA_SCAN_TIMEOUT = 4; - //timeout for internal scan - private static final int AA_SCAN_TIMEOUT_MS = 1000; - - /** - * Stanadard Codec param types - */ - static final int LOCATION = 3; - //sample rate - static final int SAMPLE_RATE = 1; - //frame duration - static final int FRAME_DURATION = 2; - //Octets per frame - static final int OCTETS_PER_FRAME = 8; - /*_PACS - private PacsClientService mPacsClientService = PacsClientService.getPacsClientService(); - _PACS*/ - BassUtils (BCService service) { - mBCService = service; - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - mLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); - mLeAudioSourceScanCallbacks = new HashMap, ScanCallback>(); - mBassAutoAssist = new HashMap(); - ///*_BMS - mBAService = BroadcastService.getBroadcastService(); - //_BMS*/ - } - - private ScanCallback mPaSyncScanCallback = new ScanCallback() { - @Override - public void onScanResult(int callbackType, ScanResult result) { - log( "onScanResult:" + result); - } - }; - - void cleanUp () { - - if (mLeAudioSourceScanCallbacks != null) { - mLeAudioSourceScanCallbacks.clear(); - } - - if (mBassAutoAssist != null) { - mBassAutoAssist.clear(); - } - } - - boolean leScanControl(boolean on) { - log("leScanControl:" + on); - mLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); - if (mLeScanner == null) { - Log.e(TAG, "LeScan handle not available"); - return false; - } - - if (on) { - mLeScanner.startScan(mPaSyncScanCallback); - } else { - mLeScanner.stopScan(mPaSyncScanCallback); - } - - return true; - } - - /* private helper to check if the Local BLE Broadcast happening Or not */ - public boolean isLocalLEAudioBroadcasting() { - boolean ret = false; - /*String localLeABroadcast = SystemProperties.get("persist.vendor.btstack.isLocalLeAB"); - if (!localLeABroadcast.isEmpty() && "true".equals(localLeABroadcast)) { - ret = true; - } - log("property isLocalLEAudioBroadcasting returning " + ret);*/ - ///*_Broadcast - if (mBAService == null) { - mBAService = BroadcastService.getBroadcastService(); - } - if (mBAService != null) { - ret = mBAService.isBroadcastActive(); - //ret = mBAService.isBroadcastStreaming(); - log("local broadcast streaming:" + ret); - } else { - log("BroadcastService is Null"); - } - //_Broadcast*/ - log("isLocalLEAudioBroadcasting returning " + ret); - return ret; - } - - Handler mAutoAssistScanHandler = new Handler() { - public void handleMessage(Message msg) { - super.handleMessage(msg); - switch (msg.what) { - case AA_START_SCAN: - BluetoothDevice dev = (BluetoothDevice) msg.obj; - Message m = obtainMessage(AA_SCAN_TIMEOUT); - m.obj = dev; - sendMessageDelayed(m, AA_SCAN_TIMEOUT_MS); - searchforLeAudioBroadcasters(dev, null); - break; - case AA_SCAN_SUCCESS: - //Able to find to desired desired Source Device - ScanResult scanRes = (ScanResult) msg.obj; - dev = scanRes.getDevice(); - stopSearchforLeAudioBroadcasters(dev,null); - mBCService.selectBroadcastSource(dev, scanRes, false, true); - break; - case AA_SCAN_FAILURE: - //Not able to find the given source - //ignore - break; - case AA_SCAN_TIMEOUT: - dev = (BluetoothDevice)msg.obj; - stopSearchforLeAudioBroadcasters(dev, null); - break; - } - } - }; - private void notifyLocalBroadcastSourceFound(ArrayList cbs) { - BluetoothDevice localDev = - BluetoothAdapter.getDefaultAdapter().getRemoteDevice(mBluetoothAdapter.getAddress()); - String localName = BluetoothAdapter.getDefaultAdapter().getName(); - ScanRecord record = null; - if (localName != null) { - byte name_len = (byte)localName.length(); - byte[] bd_name = localName.getBytes(StandardCharsets.US_ASCII); - byte[] name_key = new byte[] {++name_len, 0x09 }; //0x09 TYPE:Name - byte[] scan_r = new byte[name_key.length + bd_name.length]; - System.arraycopy(name_key, 0, scan_r, 0, name_key.length); - System.arraycopy(bd_name, 0, scan_r, name_key.length, bd_name.length); - record = ScanRecord.parseFromBytes(scan_r); - log ("Local name populated in fake Scan res:" + record.getDeviceName()); - } - ScanResult scanRes = new ScanResult(localDev, - 1, 1, 1,2, 0, 0, 0, record, 0); - if (cbs != null) { - for (IBleBroadcastAudioScanAssistCallback cb : cbs) { - try { - cb.onBleBroadcastSourceFound(scanRes); - } catch (RemoteException e) { - Log.e(TAG, "Exception while calling onBleBroadcastSourceFound"); - } - } - } - } - public boolean searchforLeAudioBroadcasters (BluetoothDevice srcDevice, - ArrayList cbs - ) { - log( "searchforLeAudioBroadcasters: "); - BluetoothLeScanner scanner = mBluetoothAdapter.getBluetoothLeScanner(); - mIsLocalBMSNotified = false; - if (scanner == null) { - Log.e(TAG, "startLeScan: cannot get BluetoothLeScanner"); - return false; - } - synchronized (mLeAudioSourceScanCallbacks) { - if (mLeAudioSourceScanCallbacks.containsKey(cbs)) { - Log.e(TAG, "LE Scan has already started"); - return false; - } - ScanCallback scanCallback = new ScanCallback() { - @Override - public void onScanResult(int callbackType, ScanResult result) { - log( "onScanResult:" + result); - if (callbackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) { - // Should not happen. - Log.e(TAG, "LE Scan has already started"); - return; - } - ScanRecord scanRecord = result.getScanRecord(); - //int pInterval = result.getPeriodicAdvertisingInterval(); - if (scanRecord != null) { - Map listOfUuids = scanRecord.getServiceData(); - if (listOfUuids != null) { - //ParcelUuid bmsUuid = new ParcelUuid(BroadcastService.BAAS_UUID); - //boolean isBroadcastSource = listOfUuids.containsKey(bmsUuid); - boolean isBroadcastSource = listOfUuids.containsKey(ParcelUuid.fromString(BAAS_UUID)); - log( "isBroadcastSource:" + isBroadcastSource); - if (isBroadcastSource) { - log( "Broadcast Source Found:" + result.getDevice()); - if (cbs != null) { - for (IBleBroadcastAudioScanAssistCallback cb : cbs) { - try { - cb.onBleBroadcastSourceFound(result); - } catch (RemoteException e) { - Log.e(TAG, "Exception while calling onBleBroadcastSourceFound"); - } - } - } else { - if (srcDevice.equals(result.getDevice())) { - log("matching src Device found"); - Message msg = mAutoAssistScanHandler.obtainMessage(AA_SCAN_SUCCESS); - msg.obj = result; - mAutoAssistScanHandler.sendMessage(msg); - } - } - } else { - log( "Broadcast Source UUID not preset, ignore"); - } - } else { - Log.e(TAG, "Ignore no UUID"); - return; - } - } else { - Log.e(TAG, "Scan record is null, ignoring this Scan res"); - return; - } - //Before starting LE Scan, Call local APIs to find out if the local device - //is Broadcaster, then generate callback for Local device - if (!mIsLocalBMSNotified && isLocalLEAudioBroadcasting()) { - //Create a DUMMY scan result for colocated case - notifyLocalBroadcastSourceFound(cbs); - mIsLocalBMSNotified = true; - } - } - - public void onScanFailed(int errorCode) { - Log.e(TAG, "Scan Failure:" + errorCode); - } - }; - if (mBluetoothAdapter != null) { - if (cbs != null) { - mLeAudioSourceScanCallbacks.put(cbs, scanCallback); - } else { - //internal auto assist trigger remember it - //based on device - mBassAutoAssist.put(srcDevice, scanCallback); - } - - ScanSettings settings = new ScanSettings.Builder().setCallbackType( - ScanSettings.CALLBACK_TYPE_ALL_MATCHES) - .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) - .setLegacy(false) - .build(); - ScanFilter.Builder filterBuilder = new ScanFilter.Builder(); - ScanFilter srcFilter = filterBuilder.setServiceUuid( - ParcelUuid.fromString(BAAS_UUID)).build(); - List filters = new ArrayList(); - if (!mIsLocalBMSNotified && isLocalLEAudioBroadcasting()) { - //Create a DUMMY scan result for colocated case - notifyLocalBroadcastSourceFound(cbs); - mIsLocalBMSNotified = true; - } - scanner.startScan(filters, settings, scanCallback); - return true; - } else { - Log.e(TAG, "searchforLeAudioBroadcasters: Adapter is NULL"); - return false; - } - } - } - public boolean stopSearchforLeAudioBroadcasters(BluetoothDevice srcDev, - ArrayList cbs) { - log( "stopSearchforLeAudioBroadcasters()"); - BluetoothLeScanner scanner = mBluetoothAdapter.getBluetoothLeScanner(); - if (scanner == null) { - return false; - } - ScanCallback scanCallback = null; - if (cbs != null) { - scanCallback = mLeAudioSourceScanCallbacks.remove(cbs); - } else { - scanCallback = mLeAudioSourceScanCallbacks.remove(srcDev); - } - - if (scanCallback == null) { - log( "scan not started yet"); - return false; - } - scanner.stopScan(scanCallback); - return true; - } - - private int convertConfigurationSRToCapabilitySR(byte sampleRate) { - int ret = BluetoothCodecConfig.SAMPLE_RATE_NONE; - switch (sampleRate) { - case 1: - ret = BluetoothCodecConfig.SAMPLE_RATE_NONE; break; - case 2: - ret = BluetoothCodecConfig.SAMPLE_RATE_NONE; break; - case 3: - ret = BluetoothCodecConfig.SAMPLE_RATE_NONE; break; - case 4: - //ret = BluetoothCodecConfig.SAMPLE_RATE_32000; break; - case 5: - ret = BluetoothCodecConfig.SAMPLE_RATE_44100; break; - case 6: - ret = BluetoothCodecConfig.SAMPLE_RATE_48000; break; - } - log("convertConfigurationSRToCapabilitySR returns:" + ret); - return ret; - } - - private boolean isSampleRateSupported(BluetoothDevice device, byte sampleRate) { - boolean ret = false; - /*_PACS - BluetoothCodecConfig[] supportedConfigs = mPacsClientService.getSinkPacs(device); - int actualSampleRate = convertConfigurationSRToCapabilitySR(sampleRate); - - if (actualSampleRate == BluetoothCodecConfig.SAMPLE_RATE_NONE) { - return false; - } - - for (int i=0; i selectBises(BluetoothDevice device, - BleBroadcastSourceInfo srcInfo, BaseData base) { - boolean noPref = SystemProperties.getBoolean("persist.vendor.service.bt.bass_no_pref", false); - if (noPref) { - log("No pref selected"); - return null; - } else { - /*_PACS - mPacsClientService = PacsClientService.getPacsClientService(); - List bChannels = new ArrayList(); - //if (mPacsClientService == null) { - log("selectBises: Pacs Service is null, pick BISes apropriately"); - //Pacs not available - if (base != null) { - bChannels = base.pickAllBroadcastChannels(); - } else { - bChannels = null; - } - return bChannels; - //} - if (mPacsClientService != null) { - int supportedLocations = 1/*mPacsClientService.getSinkLocations(device); - ArrayList broadcastedCodecInfo = base.getBISIndexInfos(); - if (broadcastedCodecInfo != null) { - for (int i=0; i consolidatedUniqueCodecInfo = broadcastedCodecInfo.get(i).consolidatedUniqueCodecInfo; - byte index = broadcastedCodecInfo.get(i).index; - if (consolidatedUniqueCodecInfo != null) { - - - byte[] bisChannelLocation = consolidatedUniqueCodecInfo.get(LOCATION).getBytes(); - byte[] locationValue = new byte[4]; - System.arraycopy(bisChannelLocation, 2, locationValue, 0, 4); - log ("locationValue>>> "); - printByteArray(locationValue); - ByteBuffer wrapped = ByteBuffer.wrap(locationValue); - int bisLocation = wrapped.getInt(); - log("bisLocation: " + bisLocation); - int reversebisLoc = Integer.reverseBytes(bisLocation); - log("reversebisLoc: " + reversebisLoc); - - byte[] bisSampleRate = consolidatedUniqueCodecInfo.get(SAMPLE_RATE).getBytes(); - byte bisSR = bisSampleRate[2]; - - //using bitwise operand as Location can be bitmask - if (isSampleRateSupported(device, bisSR) && (reversebisLoc & supportedLocations) == supportedLocations) { - log("matching location: bisLocation " + reversebisLoc + ":: " + supportedLocations); - BleBroadcastSourceChannel bc = new BleBroadcastSourceChannel(index, String.valueOf(index), true); - bChannels.add(bc); - } - } - } - } - } - - if (bChannels != null && bChannels.size() == 0) { - log("selectBises: no channel are selected"); - bChannels = null; - - } - return bChannels; - _PACS*/ - } - return null; - } - - public void triggerAutoAssist (BleBroadcastSourceInfo srcInfo) { - //searchforLeAudioBroadcasters (srcInfo.getSourceDevice(), null, AUTO_ASSIST_SCAN_TIMEOUT); - BluetoothDevice dev = srcInfo.getSourceDevice(); - - Message msg = mAutoAssistScanHandler.obtainMessage(AA_START_SCAN); - msg.obj = srcInfo.getSourceDevice(); - mAutoAssistScanHandler.sendMessage(msg); - } - - static void log(String msg) { - if (BassClientStateMachine.BASS_DBG) { - Log.d(TAG, msg); - } - } - - static void printByteArray(byte[] array) { - log("Entire byte Array as string: " + Arrays.toString(array)); - log("printitng byte by bte"); - for (int i=0; i mBisInfo; - MapmMetaInfo = Collections.synchronizedMap(new HashMap<>());; - private String mAdvAddress; - private int mAdvAddressType; - private BluetoothLeAdvertiser mAdvertiser; - private BluetoothCodecStatus mCodecStatus; - private BluetoothCodecConfig mCodecConfig; - private BluetoothCodecConfig mHapCodecConfig; - private BroadcastCodecConfig mBroadcastCodecConfig; - private BroadcastAdvertiser mBroadcastAdvertiser; - private int mBroadcastConfigSettings; - private BluetoothAdapter mBluetoothAdapter; - private BluetoothDevice mBroadcastDevice = null; - private boolean mBroadcastDeviceIsActive = false; - TrackMetadata mTrackMetadata; - private String mBroadcastAddress = "FA:CE:FA:CE:FA:CE"; - ActiveDeviceManagerService mActiveDeviceManager; - public static UUID BROADCAST_AUDIO_UUID = UUID.fromString("00001852-0000-1000-8000-00805F9B34FB"); - public static UUID BASIC_AUDIO_UUID = UUID.fromString("00001851-0000-1000-8000-00805F9B34FB"); - private BroadcastBase mBroadcastBase; - private MediaAudio mMediaAudio; - private boolean new_codec_id = false; - private static int mSecPhy = 1; - private static int mTxPowerLevel = 1; - private static int mPaInt; - private boolean mNewVersion = false; - List broadcast_supported_config = new ArrayList(List.of("16_2", "24_2", "48_1", "48_2", "48_3", "48_4", "48_5", "48_6")); - private static final int MSG_ENABLE_BROADCAST = 1; - private static final int MSG_DISABLE_BROADCAST = 2; - private static final int MSG_SET_ENCRYPTION_KEY = 3; - private static final int MSG_GET_ENCRYPTION_KEY = 4; - private static final int MSG_SET_BROADCAST_ACTIVE = 5; - private static final int MSG_UPDATE_BROADCAST_ADV_SET = 6; - private static final int MSG_ADV_DATA_SET = 7; - private static final int MSG_SET_AUDIO_PATH = 8; - private static final int MSG_RESET_ENCRYPTION_FLAG_TIMEOUT = 9; - private static final int MSG_FROM_NATIVE_CODEC_STATE = 10; - private static final int MSG_FROM_NATIVE_BROADCAST_STATE = 11; - private static final int MSG_FROM_NATIVE_ENCRYPTION_KEY = 12; - private static final int MSG_FROM_NATIVE_BROADCAST_AUDIO_STATE = 13; - private static final int MSG_FROM_NATIVE_SETUP_BIG = 14; - private static final int MSG_UPDATE_BROADCAST_STATE = 15; - private static final int MSG_FROM_NATIVE_BROADCAST_ID = 16; - @Override - protected IProfileServiceBinder initBinder() { - return new BluetoothBroadcastBinder(this); - } - - @Override - protected void create() { - Log.i(TAG, "create()"); - } - - @Override - protected boolean start() { - Log.i(TAG, "start()"); - if (sBroadcastService != null) { - Log.w(TAG, "Broadcastervice is already running"); - return true; - } - if (mHandler != null) - mHandler = null; - mAdapterService = Objects.requireNonNull(AdapterService.getAdapterService(), - "AdapterService cannot be null when A2dpService starts"); - - mBroadcastNativeInterface = Objects.requireNonNull(mBroadcastNativeInterface.getInstance(), - "BroadcastNativeInterface cannot be null when BroadcastService starts"); - mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); - Objects.requireNonNull(mAudioManager, - "AudioManager cannot be null when A2dpService starts"); - HandlerThread thread = new HandlerThread("BroadcastHandler"); - mBroadcastConfigSettings = SystemProperties.getInt("persist.vendor.btstack.bap_ba_setting", 4); - mBroadcastCodecConfig = new BroadcastCodecConfig(); - String PartialSimulcast = SystemProperties.get("persist.vendor.btstack.partial_simulcast"); - if (!PartialSimulcast.isEmpty() && "true".equals(PartialSimulcast)) { - mPartialSimulcast = true; - mNumSubGrps = 2; - mNumBises = 4; - //mHapCodecConfig = new BroadcastCodecConfig(mPartialSimulcast); - } - String mNewCodecId = SystemProperties.get("persist.vendor.btstack.new_lc3_id"); - if (mNewCodecId.isEmpty() || "true".equals(mNewCodecId) || - "6".equals(mNewCodecId)) { - new_codec_id = true; - } - /* Property to set seconday advertising phy to 1M or 2M. 2M is selected by default - * if propety is not set - */ - mSecPhy = SystemProperties.getInt("persist.vendor.btstack.secphy", 2); - mTxPowerLevel = SystemProperties.getInt("persist.vendor.service.bt.txpower", 9); - mPD = SystemProperties.getInt("persist.vendor.service.bt.presentation_delay", 40); - mPaInt = SystemProperties.getInt("persist.vendor.btstack.pa_interval", 360); - mNewVersion = SystemProperties.getBoolean("persist.vendor.service.bt.new_ba_version", true); - int offload_mode = 1; //offload - mBroadcastNativeInterface.init(1, mCodecConfig,offload_mode); - thread.start(); - IntentFilter filter = new IntentFilter(); - filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); - mAdapterService.registerReceiver(mBroadcastReceiver, filter); - Looper looper = thread.getLooper(); - mHandler = new BroadcastMessageHandler(looper); - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - mBroadcastBase = new BroadcastBase(); - mBisInfo = new ArrayList<>(); - //mBroadcastAdvertiser = new BroadcastAdvertiser(); - setBroadcastService(this); - mBroadcastDevice = mAdapter.getRemoteDevice(mBroadcastAddress); - mTrackMetadata = new TrackMetadata(null); - - mActiveDeviceManager = ActiveDeviceManagerService.get(this); - DeviceProfileMap dpm = DeviceProfileMap.getDeviceProfileMapInstance(); - dpm.profileConnectionUpdate(mBroadcastDevice, ApmConst.AudioFeatures.BROADCAST_AUDIO, ApmConst.AudioProfiles.BROADCAST_LE, true); - - //Get current codec and call native init - return true; - } - private void initialize_advertiser() { - Log.d(TAG,"initalize_advertiser"); - mBroadcastAdvertiser = new BroadcastAdvertiser(); - GetEncryptionKeyFromNative(); - } - private void startAdvTest() { - //Log.d(TAG,"startAdvTest!!!"); - boolean ba_test = SystemProperties.getBoolean("persist.vendor.btstack.batest",false); - if (ba_test) { - Log.d(TAG,"startAdvTest!!!"); - EnableBroadcast(null); - } - } - private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { - int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,BluetoothAdapter.ERROR); - Log.d(TAG,"action: " + action + " state: " + state); - if (state == BluetoothAdapter.STATE_ON) { - initialize_advertiser(); - startAdvTest(); - } else if (state == BluetoothAdapter.STATE_TURNING_OFF) { - if (sBroadcastService != null) - cleanup_broadcast(); - } - } - } - }; - @Override - protected boolean stop() { - Log.i(TAG, "stop()"); - if (sBroadcastService == null) { - Log.w(TAG, "stop() called before start()"); - return true; - } - notifyBroadcastEnabled(false); - if (mIsAdvertising) { - mBroadcastAdvertiser.stopBroadcastAdvertising(); - } - mAdapterService = null; - mBroadcastNativeInterface = null; - mAudioManager = null; - mIsAdvertising = false; - Looper looper = mHandler.getLooper(); - if (looper != null) { - looper.quit(); - } - setBroadcastService(null); - return true; - } - - @Override - protected void cleanup() { - Log.i(TAG, "cleanup()"); - } - public static synchronized BroadcastService getBroadcastService() { - if (sBroadcastService == null) { - Log.w(TAG, "getBroadcastService(): service is null"); - return null; - } - if (!sBroadcastService.isAvailable()) { - Log.w(TAG, "getBroadcastService(): service is not available"); - return null; - } - return sBroadcastService; - } - - /** Handles Broadcast messages. */ - private final class BroadcastMessageHandler extends Handler { - private BroadcastMessageHandler(Looper looper) { - super(looper); - } - @Override - public void handleMessage(Message msg) { - Log.v(TAG, "BroadcastMessageHandler: received message=" + msg.what); - int prev_state; - switch (msg.what) { - case MSG_ENABLE_BROADCAST: - //int prev_state; - synchronized (mBroadcastLock) { - if (VDBG) { - Log.i(TAG, "Setting broadcast state to ENABLING"); - } - prev_state = mBroadcastState; - mBroadcastState = BluetoothBroadcast.STATE_ENABLING; - } - broadcastState(mBroadcastState, prev_state); - mBroadcastNativeInterface.enableBroadcast(mCodecConfig); - break; - case MSG_DISABLE_BROADCAST: - //int prev_state; - goingDown = true; - if (!mIsAdvertising) { - Log.e(TAG, "Broadcast is not advertising"); - break; - } - synchronized(mBroadcastLock) { - if (VDBG) { - Log.i(TAG,"Disabling broadcast, setting state to DISABLING"); - } - prev_state = mBroadcastState; - mBroadcastState = BluetoothBroadcast.STATE_DISABLING; - } - broadcastState(mBroadcastState, prev_state); - mBroadcastNativeInterface.disableBroadcast(mAdvertisingSet.getAdvertiserId()); - //mBroadcastAdvertiser.stopBroadcastAdvertising(); - break; - case MSG_SET_ENCRYPTION_KEY: - //int length = msg.arg1; - mBroadcastNativeInterface.SetEncryptionKey(mEncryptionEnabled, mEncryptionLength); - if (mEncryptionLength == 0) { - for(int i = 0; i < mDefaultEncryptionLength; i++) { - BigBroadcastCode[i] = 0x00; - } - broadcastEncryptionkeySet(); - } - break; - case MSG_GET_ENCRYPTION_KEY: { - mEncryptionString = mBroadcastNativeInterface.GetEncryptionKey(); - if (mEncryptionString == null) { - Log.e(TAG,"MSG_GET_ENCRYPTION_KEY: mEncryptionString null"); - for (int i = 0; i < mDefaultEncryptionLength; i++) { - BigBroadcastCode[i] = 0x00; - } - break; - } - mEncKey= mEncryptionString.getBytes(); - Log.i(TAG, "mEncryptionString: " + mEncryptionString); - System.arraycopy(mEncKey, 0, BigBroadcastCode, 0, mEncKey.length); - if (mEncKey.length < mDefaultEncryptionLength) { - for (int i = mEncKey.length; i < mDefaultEncryptionLength; i++) { - BigBroadcastCode[i] = 0x00; - } - } - for (int i = 0;i < mDefaultEncryptionLength/2; i++) { - byte temp = BigBroadcastCode[i]; - BigBroadcastCode[i] = BigBroadcastCode[(mDefaultEncryptionLength -1) - i]; - BigBroadcastCode[(mDefaultEncryptionLength -1) - i] = temp; - } - for (int i = 0; i < 16; i++) { - Log.i(TAG,"BigBroadcastCode["+ i + "] = " + BigBroadcastCode[i]); - } - //TODO: Stub to test encryption key creation, to be removed - //Log.i(TAG,"calling setencryptionkey"); - //mBroadcastNativeInterface.SetEncryptionKey(4); - broadcastEncryptionkeySet(); - } - break; - case MSG_UPDATE_BROADCAST_ADV_SET: - break; - case MSG_SET_BROADCAST_ACTIVE: - // Call native layer to set broadcast active - //mBroadcastNativeInterface.setActiveDevice(true, mAdvertisingSet.getAdvertiserId()); - //setActiveDevice(mBroadcastDevice); - notifyBroadcastEnabled(true); - break; - case MSG_RESET_ENCRYPTION_FLAG_TIMEOUT: - Log.i(TAG,"Setting mEncKeyRefreshed to false"); - mEncKeyRefreshed = false; - break; - case MSG_FROM_NATIVE_BROADCAST_STATE: - synchronized(mBroadcastLock) { - prev_state = mBroadcastState; - mBroadcastState = msg.arg1; - if (VDBG) { - Log.i(TAG,"New broadcast state: " + mBroadcastState); - } - } - if (mBroadcastState == BluetoothBroadcast.STATE_DISABLED) { - if (goingDown) { - notifyBroadcastEnabled(false); - } - mBIGHandle = -1; - mBroadcastAdvertiser.stopBroadcastAdvertising(); - break; - } - if (prev_state != mBroadcastState) - broadcastState(mBroadcastState, prev_state); - break; - case MSG_ADV_DATA_SET: - synchronized (mBroadcastLock) { - if (VDBG) { - Log.i(TAG, "Setting broadcast state to ENABLING"); - } - prev_state = mBroadcastState; - mBroadcastState = BluetoothBroadcast.STATE_ENABLED; - } - broadcastState(mBroadcastState, prev_state); - break; - case MSG_SET_AUDIO_PATH: - //mBroadcastNativeInterface.SetupAudioPath(true,mAdvertisingSet.getAdvertiserId(),mBIGHandle,mNumBises,bis_handles); - break; - case MSG_FROM_NATIVE_CODEC_STATE: - mCodecStatus = (BluetoothCodecStatus)msg.obj; - if (IsCodecConfigChanged(mCodecStatus.getCodecConfig())) { - mBroadcastCodecConfig.updateBroadcastCodecConfig(mCodecStatus.getCodecConfig()); - mBroadcastBase.populateBase(); - mBroadcastAdvertiser.updatePAwithBase(); - } - broadcastCodecConfig(mCodecStatus); - mMediaAudio = MediaAudio.get(); - mMediaAudio.onCodecConfigChange(mBroadcastDevice, mCodecStatus, ApmConst.AudioProfiles.BROADCAST_LE); - break; - case MSG_FROM_NATIVE_ENCRYPTION_KEY: { - mEncryptionString = (String)msg.obj; - Log.d(TAG,"mEncryptionString: " + mEncryptionString); - mEncKey= mEncryptionString.getBytes(); - System.arraycopy(mEncKey, 0, BigBroadcastCode, 0, mEncKey.length); - if (mEncKey.length < mDefaultEncryptionLength) { - for (int i = mEncKey.length; i < mDefaultEncryptionLength; i++) { - BigBroadcastCode[i] = 0x00; - } - } - for (int i = 0; i < mEncKey.length; i++) { - Log.d(TAG,"mEnc[" + i +"] = " + mEncKey[i]); - } - for (int i = 0;i < mDefaultEncryptionLength/2; i++) { - byte temp = BigBroadcastCode[i]; - BigBroadcastCode[i] = BigBroadcastCode[(mDefaultEncryptionLength - 1) - i]; - BigBroadcastCode[(mDefaultEncryptionLength - 1) - i] = temp; - } - //Broadcast encyption key set - broadcastEncryptionkeySet(); - } - break; - case MSG_FROM_NATIVE_SETUP_BIG: - int setup = msg.arg1; - boolean set = (setup == 1); - if (set) { - Log.d(TAG, "BIG created: " + mBIGHandle + "with no of bises: " + mNumBises); - mNumBises = mNumBises * mNumSubGrps; - mBroadcastBase.populateBase(); - mBroadcastAdvertiser.updatePAwithBase(); - } else { - Log.d(TAG, "BIG terminated"); - mBIGHandle = -1; - //Clean up mBisInfo List - mBisInfo.clear(); - mMetaInfo.clear(); - } - break; - case MSG_FROM_NATIVE_BROADCAST_AUDIO_STATE: - int prevState = mBroadcastAudioState; - mBroadcastAudioState = msg.arg1; - if (prevState != mBroadcastAudioState) - broadcastAudioState(mBroadcastAudioState, prevState); - break; - case MSG_FROM_NATIVE_BROADCAST_ID: - if (mBroadcastAdvertiser != null) { - mBroadcastAdvertiser.startBroadcastAdvertising(); - } else { - Log.e(TAG,"Did not receive adatper state change intent, turning off Broadcast"); - prev_state = mBroadcastState; - mBroadcastState = BluetoothBroadcast.STATE_DISABLED; - broadcastState(mBroadcastState, prev_state); - } - break; - case MSG_UPDATE_BROADCAST_STATE: - prev_state = msg.arg1; - mBroadcastState = BluetoothBroadcast.STATE_DISABLED; - Log.d(TAG,"MSG_UPDATE_BROADCAST_STATE"); - broadcastState(mBroadcastState, prev_state); - break; - default: - Log.e(TAG,"unknown message msg.what = " + msg.what); - break; - } - Log.d(TAG,"Exit handleMessage"); - } - } - - private void updateBroadcastStateToHfp(int state) { - if (DBG) { - Log.d(TAG,"updateBroadcastStateToHfp"); - } - HeadsetService hfpService = HeadsetService.getHeadsetService(); - if (hfpService != null) { - hfpService.updateBroadcastState(state); - } - } - private void broadcastState(int state, int prev_state) { - if (DBG) { - Log.d(TAG, "Broadcasting broadcastState: " + state); - } - Intent intent = new Intent(BluetoothBroadcast.ACTION_BROADCAST_STATE_CHANGED); - intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prev_state); - intent.putExtra(BluetoothProfile.EXTRA_STATE, state); - sendBroadcast(intent, BLUETOOTH_CONNECT, Utils.getTempAllowlistBroadcastOptions()); - updateBroadcastStateToHfp(state); - } - private void broadcastCodecConfig(BluetoothCodecStatus codecStatus) { - if (DBG) { - Log.d(TAG, "Broacasting broadcastCodecConfig" + codecStatus); - } - Intent intent = new Intent(BluetoothA2dp.ACTION_CODEC_CONFIG_CHANGED); - intent.putExtra(BluetoothCodecStatus.EXTRA_CODEC_STATUS, codecStatus); - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mBroadcastDevice); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - //sendBroadcast(intent, BLUETOOTH_CONNECT); - } - - private void broadcastEncryptionkeySet() { - if (DBG) { - Log.d(TAG, "broadcastEncryptionkeySet"); - } - Intent intent = new Intent(BluetoothBroadcast.ACTION_BROADCAST_ENCRYPTION_KEY_GENERATED); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - sendBroadcast(intent, BLUETOOTH_CONNECT, Utils.getTempAllowlistBroadcastOptions()); - } - - private void broadcastAudioState(int newState, int prevState) { - Log.d(TAG, "broadcastAudioState: State:" + audioStateToString(prevState) - + "->" + audioStateToString(newState)); - Intent intent = new Intent(BluetoothBroadcast.ACTION_BROADCAST_AUDIO_STATE_CHANGED); - intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); - intent.putExtra(BluetoothProfile.EXTRA_STATE, newState); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - sendBroadcast(intent, BLUETOOTH_CONNECT, Utils.getTempAllowlistBroadcastOptions()); - } - - private static String audioStateToString(int state) { - switch (state) { - case BluetoothBroadcast.STATE_PLAYING: - return "PLAYING"; - case BluetoothBroadcast.STATE_NOT_PLAYING: - return "NOT_PLAYING"; - default: - break; - } - return Integer.toString(state); - } - private boolean IsCodecConfigChanged(BluetoothCodecConfig config) { - return (mCodecConfig.getSampleRate() != config.getSampleRate() || - mCodecConfig.getChannelMode() != config.getChannelMode() || - mCodecConfig.getCodecSpecific1() != config.getCodecSpecific1() || - mCodecConfig.getCodecSpecific2() != config.getCodecSpecific2()); - } - private boolean isCodecValid(BluetoothCodecConfig mCodecConfig) { - if (mCodecConfig.getCodecType() != BluetoothCodecConfig.SOURCE_CODEC_TYPE_LC3) { - return false; - } - return true; - } - - private boolean isCodecConfigValid(String config_id) { - if (broadcast_supported_config.contains(config_id)) { - Log.d(TAG,"isCodecConfigValid: config supported"); - return true; - } - Log.d(TAG,"isCodecConfigValid: config not supported"); - return false; - } - - private boolean isEncrytionLengthValid(int enc_length) { - if (enc_length == 4 || enc_length == 16) { - return true; - } - return false; - } - - private BluetoothCodecConfig buildCodecConfig(String config_id, int channel) { - //BluetoothCodecConfig cc; - int index = broadcast_supported_config.indexOf(config_id); - int sr; - long codecspecific1, codecspecific2; - String isMono = SystemProperties.get("persist.vendor.btstack.enable.broadcast_mono"); - Log.d(TAG,"buildCodecConfig:" + config_id + " index: " + index); - switch(index) { - case 0: //16_2 - sr = BluetoothCodecConfig.SAMPLE_RATE_16000; - //ch_mode = BluetoothCodecConfig.CHANNEL_MODE_STEREO; - codecspecific1 = 1001;//32kbps - codecspecific2 = 1; - break; - case 1: //24_2 - sr = BluetoothCodecConfig.SAMPLE_RATE_24000; - //ch_mode = BluetoothCodecConfig.CHANNEL_MODE_STEREO; - codecspecific1 = 1002;//48kbps - codecspecific2 = 1; - break; - case 2: //48_1 - sr = BluetoothCodecConfig.SAMPLE_RATE_48000; - //ch_mode = BluetoothCodecConfig.CHANNEL_MODE_STEREO; - codecspecific1 = 1004;//80kbps - codecspecific2 = 0; - break; - case 3: //48_2 - sr = BluetoothCodecConfig.SAMPLE_RATE_48000; - //ch_mode = BluetoothCodecConfig.CHANNEL_MODE_STEREO; - codecspecific1 = 1004;//80kbps - codecspecific2 = 1; - break; - case 4: //48_3 - sr = BluetoothCodecConfig.SAMPLE_RATE_48000; - //ch_mode = BluetoothCodecConfig.CHANNEL_MODE_STEREO; - codecspecific1 = 1006;//96kbps - codecspecific2 = 0; - break; - case 5: //48_4 - sr = BluetoothCodecConfig.SAMPLE_RATE_48000; - //ch_mode = BluetoothCodecConfig.CHANNEL_MODE_STEREO; - codecspecific1 = 1006;//96kbps - codecspecific2 = 1; - break; - case 6: //48_5 - sr = BluetoothCodecConfig.SAMPLE_RATE_48000; - //ch_mode = BluetoothCodecConfig.CHANNEL_MODE_STEREO; - codecspecific1 = 1007;//124kbps - codecspecific2 = 0; - break; - case 7: //48_6 - sr = BluetoothCodecConfig.SAMPLE_RATE_48000; - //ch_mode = BluetoothCodecConfig.CHANNEL_MODE_STEREO; - codecspecific1 = 1007;//124kbps - codecspecific2 = 1; - break; - - default: - sr = BluetoothCodecConfig.SAMPLE_RATE_48000; - //ch_mode = BluetoothCodecConfig.CHANNEL_MODE_STEREO; - codecspecific1 = 1007;//80kbps - codecspecific2 = 1; - break; - } - //if (isMono.isEmpty() || isMono.equals("mono")) { - // ch_mode = BluetoothCodecConfig.CHANNEL_MODE_MONO; - //} - BluetoothCodecConfig cc = - new BluetoothCodecConfig.Builder() - .setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LC3) - .setCodecPriority(BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT) - .setSampleRate(sr) - .setBitsPerSample(BluetoothCodecConfig.BITS_PER_SAMPLE_24) - .setChannelMode(channel) - .setCodecSpecific1(codecspecific1) - .setCodecSpecific2(codecspecific2) - .setCodecSpecific3(0) - .setCodecSpecific4(0) - .build(); - return cc; - } - private static synchronized void setBroadcastService(BroadcastService instance) { - if (DBG) { - Log.d(TAG, "setBroadcastService(): set to: " + instance); - } - sBroadcastService = instance; - } - - private void cleanup_broadcast() { - if (DBG) Log.d (TAG, "cleanup_broadcast"); - synchronized (mBroadcastLock) { - if (mIsAdvertising) { - if (mBroadcastNativeInterface != null) - mBroadcastNativeInterface.disableBroadcast(mAdvertisingSet.getAdvertiserId()); - mBroadcastAdvertiser.stopBroadcastAdvertising(); - int prev_state = mBroadcastState; - mBroadcastState = BluetoothBroadcast.STATE_DISABLED; - broadcastState(mBroadcastState, prev_state); - } - } - } - public boolean EnableBroadcast(String packageName) { - if (DBG) Log.d (TAG, "EnableBroadcast"); - - if (mBroadcastState != BluetoothBroadcast.STATE_DISABLED) { - return false; - } - Message msg = mHandler.obtainMessage(MSG_ENABLE_BROADCAST); - mHandler.sendMessage(msg); - return true; - } - public boolean DisableBroadcast(String packageName) { - if (DBG) Log.d (TAG, "DisableBroadcast: state " + mBroadcastState); - - if (mBroadcastState == BluetoothBroadcast.STATE_DISABLING || - mBroadcastState == BluetoothBroadcast.STATE_DISABLED) { - return true; - } else if (mBroadcastState != BluetoothBroadcast.STATE_ENABLED && - mBroadcastState != BluetoothBroadcast.STATE_STREAMING) { - Log.d(TAG,"Broadcast is not enabled yet"); - return false; - } - Message msg = mHandler.obtainMessage(MSG_DISABLE_BROADCAST); - mHandler.sendMessage(msg); - return true; - } - public boolean SetEncryption(boolean enable, int enc_len, - boolean use_existing, String packageName) { - if (DBG) Log.d (TAG,"SetEncryption"); - - mEncryptionEnabled = enable; - if (enable) { - if (!isEncrytionLengthValid(enc_len)) { - if (DBG) Log.d (TAG,"SetEncryption: invalid encrytion length requested"); - return false; - } - } else { - Log.d(TAG,"Selected unencrypted"); - enc_len = 0; - } - if (!use_existing) { - Log.d (TAG,"Generate new ecrytpion key of lenght = " + enc_len); - mEncryptionLength = enc_len; - if (mBroadcastState == BluetoothBroadcast.STATE_ENABLED || - mBroadcastState == BluetoothBroadcast.STATE_STREAMING) { - mEncKeyRefreshed = true; - Message msg = mHandler.obtainMessage(MSG_RESET_ENCRYPTION_FLAG_TIMEOUT); - mHandler.sendMessageDelayed(msg, 1000); - } - Message msg = mHandler.obtainMessage(MSG_SET_ENCRYPTION_KEY); - mHandler.sendMessage(msg); - } - return true; - } - - public byte[] GetEncryptionKey(String packageName) { - if (DBG) Log.d (TAG,"GetBroadcastEncryptionKey: package name = " + packageName); - - return BigBroadcastCode; - } - - public int GetBroadcastStatus(String packageName) { - if (DBG) Log.d (TAG,"GetBroadcastStatus: state = " + mBroadcastState + " package name = " + packageName); - return mBroadcastState; - } - - public boolean isBroadcastActive() { - if (mBroadcastDeviceIsActive == false) { - Log.d (TAG,"isBroadcastActive: Broadcast is turned to off"); - return false; - } - if (DBG) Log.d (TAG,"isBroadcastActive"); - return ((mBroadcastState == BluetoothBroadcast.STATE_ENABLED) || - (mBroadcastState == BluetoothBroadcast.STATE_STREAMING)); - } - - public BluetoothDevice getBroadcastDevice() { - if (DBG) Log.d (TAG,"getBroadcastDevice"); - return mBroadcastDevice; - } - - public String getBroadcastAddress() { - if (DBG) Log.d (TAG,"getBroadcastAddress"); - return mBroadcastAddress; - } - - public byte[] getBroadcastId() { - Log.d(TAG,"getBroadcastId: " + mBroadcastID); - return mBroadcastID; - } - - public boolean isBroadcastStreamingEncrypted() { - return mEncryptionEnabled; - } - - public boolean isBroadcastStreaming() { - return (mBroadcastState == BluetoothBroadcast.STATE_STREAMING); - } - - public String BroadcastGetAdvAddress() { - if (DBG) Log.d (TAG,"BroadcastGetAdvAddress: " + mAdvAddress); - return mAdvAddress; - } - - public int getNumSubGroups() { - if (DBG) Log.d (TAG,"getNumSubGroups: " + mNumSubGrps); - return mNumSubGrps; - } - - public int BroadcastGetAdvAddrType() { - return mAdvAddressType; - } - - public int BroadcatGetAdvHandle() { - //check if advertising - return mAdvertisingSet.getAdvertiserId(); - } - - public int BroadcastGetAdvInterval() { - return mPaInt; - } - public List BroadcastGetBisInfo() { - if (isBroadcastStreaming()) { - return mBisInfo; - } - Log.d(TAG,"BroadcastGetBisInfo: Broadcast is not active"); - return mBisInfo; - } - - public Map BroadcastGetMetaInfo() { - if (isBroadcastStreaming()) { - return mMetaInfo; - } - Log.d(TAG,"BroadcastGetMetaInfo: Broadcast is not active"); - return mMetaInfo; - } - public byte[] BroadcastGetMetadata() { - if (isBroadcastStreaming()) { - return mBroadcastBase.getMetadataContext(); - } - Log.d(TAG,"BroadcastGetMetadata: Broadcast is not active"); - return mBroadcastBase.getMetadataContext(); - } - public void setCodecPreference(String config_id, int ch_mode) { - if (isCodecConfigValid(config_id)) { - setCodecPreference(buildCodecConfig(config_id, ch_mode)); - } - } - public void setCodecPreference(BluetoothCodecConfig newConfig) { - if (DBG) Log.d (TAG, "setCodecPreference"); - if (newConfig.getCodecType() != BluetoothCodecConfig.SOURCE_CODEC_TYPE_LC3) { - Log.e(TAG, "setCodecPreference: Invalid codec for broadcast mode: " + newConfig.getCodecType()); - return; - } - //mBroadcastCodecConfig.updateCodecConfig(newConfig); - if (mBroadcastState != BluetoothBroadcast.STATE_DISABLED) - mBroadcastNativeInterface.setCodecConfigPreference(mAdvertisingSet.getAdvertiserId(),newConfig); - } - - public void GetEncryptionKeyFromNative() { - Log.e(TAG,"GetEncryptionKeyFromNative"); - Message msg = mHandler.obtainMessage(MSG_GET_ENCRYPTION_KEY); - mHandler.sendMessage(msg); - } - private void setup_isodatapath(int adv_id, int big_handle,int num_bises, int[] bises) { - } - /* LE HAP broadcast hooks */ - public boolean startHAPBroadcast() { - if (isBroadcastActive()) { - //TODO: update codec config with HAP HQ mode - //Terminate BIG if created - //Notify codec config change to stack - //Create BIG and update BASE - } else { - //TODO: update codec config with HAP HQ mode - //Start Adv - //Existing encryption key will be used for HAP as only music streaming is supported - //Announcement content type will not be covered - } - return true; - } - public boolean stopHAPBroadcast() { - //TODO: DisableAudioPath - //Terminate BIG - //update state to disabling - //stop Adv - //reset codec config to default config - return true; - } - public void removeActiveDevice() { - if (DBG) Log.d (TAG,"removeActiveDevice"); - //int [] bis_handles = {-1, -1}; - if (mBroadcastDeviceIsActive == false) { - Log.d (TAG,"removeActiveDevice: mBADeviceIsActive is false, already removed"); - return; - } - mBroadcastDeviceIsActive = false; - synchronized (mBroadcastLock) { - if (mIsAdvertising && - (mBroadcastState == BluetoothBroadcast.STATE_ENABLED || - mBroadcastState == BluetoothBroadcast.STATE_STREAMING)) { - mBroadcastNativeInterface.disableBroadcast(mAdvertisingSet.getAdvertiserId()); - //mBroadcastAdvertiser.stopBroadcastAdvertising(); - } - if (!mBroadcastNativeInterface.setActiveDevice(false, mAdvertisingSet.getAdvertiserId())) { - Log.d(TAG,"SetActiveNative failed"); - } - } - //notifyBroadcastEnabled(false); - } - - public BluetoothCodecStatus getCodecStatus() { - if (DBG) Log.d (TAG,"getCodecStatus"); - BluetoothCodecConfig[] mBroadcastCodecConfig = {mCodecConfig}; - return (new BluetoothCodecStatus(mCodecConfig, mBroadcastCodecConfig, mBroadcastCodecConfig)); - } - public int setActiveDevice(BluetoothDevice device) { - if (DBG) Log.d (TAG,"setActiveDevice"); - if (device == null) { - removeActiveDevice(); - return ActiveDeviceManagerService.SHO_SUCCESS; - } - if (!Objects.equals(device, mBroadcastDevice)) { - Log.d(TAG,"setActiveDevice: Not a Broadcast device"); - return ActiveDeviceManagerService.SHO_FAILED; - } - if (!mBroadcastNativeInterface.setActiveDevice(true, mAdvertisingSet.getAdvertiserId())) { - Log.d(TAG,"SetActiveNative failed"); - return ActiveDeviceManagerService.SHO_FAILED; - } - mBroadcastDeviceIsActive = true; - - return ActiveDeviceManagerService.SHO_SUCCESS; - } - - public void notifyBroadcastEnabled(boolean enabled) { - if (DBG) Log.d (TAG,"notifyBroadcastEnabled: " + enabled); - ActiveDeviceManagerService activeDeviceManager = ActiveDeviceManagerService.get(); - if(activeDeviceManager == null) { - Log.e(TAG,"ActiveDeviceManagerService not started. Return"); - return; - } - if (enabled) - activeDeviceManager.enableBroadcast(mBroadcastDevice); - else - activeDeviceManager.disableBroadcast(); - } - - public void updateMetadataFromAvrcp(MediaMetadata data) { - if (DBG) Log.d (TAG,"updateMetadataFromAvrcp"); - mTrackMetadata = new TrackMetadata(data); - } - public void messageFromNative(BroadcastStackEvent event) { - if (DBG) Log.d (TAG,"messageFromNative: event " + event); - switch(event.type) { - case BroadcastStackEvent.EVENT_TYPE_BROADCAST_STATE_CHANGED: - { - Message msg = - mHandler.obtainMessage(MSG_FROM_NATIVE_BROADCAST_STATE, - event.valueInt, event.advHandle); - mHandler.sendMessage(msg); - } - break; - case BroadcastStackEvent.EVENT_TYPE_BROADCAST_AUDIO_STATE_CHANGED: - { - Message msg = - mHandler.obtainMessage(MSG_FROM_NATIVE_BROADCAST_AUDIO_STATE, - event.valueInt, event.advHandle); - mHandler.sendMessage(msg); - } - break; - case BroadcastStackEvent.EVENT_TYPE_CODEC_CONFIG_CHANGED: - { - Message msg = - mHandler.obtainMessage(MSG_FROM_NATIVE_CODEC_STATE); - msg.obj = event.codecStatus; - mHandler.sendMessage(msg); - } - break; - case BroadcastStackEvent.EVENT_TYPE_ENC_KEY_GENERATED: - { - Message msg = - mHandler.obtainMessage(MSG_FROM_NATIVE_ENCRYPTION_KEY); - msg.obj = event.key; - mHandler.sendMessage(msg); - } - break; - case BroadcastStackEvent.EVENT_TYPE_SETUP_BIG: - { - mBIGHandle = event.bigHandle; - if (event.valueInt == 1) - mNumBises = event.NumBises; - Message msg = - mHandler.obtainMessage(MSG_FROM_NATIVE_SETUP_BIG,event.valueInt, event.advHandle); - mHandler.sendMessage(msg); - } - break; - case BroadcastStackEvent.EVENT_TYPE_BROADCAST_ID_GENERATED: - { - Message msg = - mHandler.obtainMessage(MSG_FROM_NATIVE_BROADCAST_ID); - for (int i = 0; i < mBroadcastIdLength; i++) { - mBroadcastID[i] = (byte)event.BroadcastId[i]; - Log.d(TAG,"mBroadcastID["+i+"]" + " = " + mBroadcastID[i]); - } - mHandler.sendMessage(msg); - } - break; - default: - Log.e (TAG,"messageFromNative: Invalid"); - } - } - class TrackMetadata { - private String title; - private String artistName; - private String albumName; - private String genre; - private long playingTimeMs; - - public TrackMetadata(MediaMetadata data) { - if (data == null) return; - artistName = stringOrBlank(data.getString(MediaMetadata.METADATA_KEY_ARTIST)); - albumName = stringOrBlank(data.getString(MediaMetadata.METADATA_KEY_ALBUM)); - title = data.getString(MediaMetadata.METADATA_KEY_TITLE); - genre = stringOrBlank(data.getString(MediaMetadata.METADATA_KEY_GENRE)); - playingTimeMs = data.getLong(MediaMetadata.METADATA_KEY_DURATION); - } - private String stringOrBlank(String s) { - return s == null ? new String() : s; - } - } - class BroadcastAdvertiser { - public BroadcastAdvertiser() { - Log.i(TAG,"BroadcastAdvertiser"); - mCallback = new BroadcastAdvertiserCallback(); - mAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser(); - if (mAdvertiser == null) { - Log.e(TAG, "BroadcastAdvertiser: mAdvertiser is null"); - } - } - public void startBroadcastAdvertising() { - Log.i(TAG,"startBroadcastAdvertising"); - if (mAdvertiser == null) { - Log.e(TAG,"startBroadcastAdvertising: Advertiser is null"); - int prev_state = mBroadcastState; - mBroadcastState = BluetoothBroadcast.STATE_DISABLED; - broadcastState(mBroadcastState, prev_state); - return; - } - AdvertisingSetParameters.Builder adv_param = - new AdvertisingSetParameters.Builder(); - adv_param.setLegacyMode(false); - adv_param.setConnectable(false); - adv_param.setScannable(false); - adv_param.setInterval(AdvertisingSetParameters.INTERVAL_MIN); //100msec - adv_param.setTxPowerLevel(mTxPowerLevel); - adv_param.setPrimaryPhy(1); - adv_param.setSecondaryPhy(mSecPhy); - AdvertiseData AdvData = new AdvertiseData.Builder() - .setIncludeDeviceName(true) - .addServiceData(new ParcelUuid(BROADCAST_AUDIO_UUID), mBroadcastID).build(); - PeriodicAdvertisingParameters.Builder periodic_param = new PeriodicAdvertisingParameters.Builder(); - periodic_param.setIncludeTxPower(true); - periodic_param.setInterval(mPaInt); - AdvertiseData PeriodicData = new AdvertiseData.Builder().addServiceData(new ParcelUuid(BASIC_AUDIO_UUID), new byte[0]).build(); - Log.i(TAG,"Calling startAdvertisingSet"); - mAdvertiser.startAdvertisingSet(adv_param.build(), AdvData, null, periodic_param.build(), PeriodicData, 0, 0, mCallback); - } - public void stopBroadcastAdvertising() { - Log.i(TAG,"stopBroadcastAdvertising"); - if (mAdvertiser != null) - mAdvertiser.stopAdvertisingSet(mCallback); - } - - public void updatePAwithBase() { - Log.i(TAG,"updatePAwithBase"); - AdvertiseData PeriodicData = new AdvertiseData.Builder().addServiceData(new ParcelUuid(BASIC_AUDIO_UUID), mBroadcastBase.getBroadcastBaseInfo()).build(); - mAdvertisingSet.setPeriodicAdvertisingData(PeriodicData); - } - } - - private class BroadcastAdvertiserCallback extends AdvertisingSetCallback { - @Override - public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower, - int status) { - Log.i(TAG, "onAdvertisingSetStarted status " + status - + " advertisingSet: " + advertisingSet + " txPower " + txPower); - if (status != BluetoothGatt.GATT_SUCCESS) { - Log.e(TAG,"Failed to start Broadcast Advertisement"); - int prev_state = mBroadcastState; - mBroadcastState = BluetoothBroadcast.STATE_DISABLED; - broadcastState(mBroadcastState,prev_state); - } - if (status == BluetoothGatt.GATT_SUCCESS) { - mAdvertisingSet = advertisingSet; - mIsAdvertising = true; - int prev_state = mBroadcastState; - mBroadcastState = BluetoothBroadcast.STATE_ENABLED; - Log.i(TAG,"onAdvertisingSetStarted: adv_id = " + advertisingSet.getAdvertiserId() + "copied id = " + mAdvertisingSet.getAdvertiserId()); - broadcastState(mBroadcastState,prev_state); - if (mHandler.hasMessages(MSG_RESET_ENCRYPTION_FLAG_TIMEOUT)) { - Message msg = - mHandler.obtainMessage(MSG_SET_BROADCAST_ACTIVE); - mHandler.sendMessageDelayed(msg,600); - } else { - notifyBroadcastEnabled(true); - } - int mChMode = mCodecConfig.getChannelMode(); - switch (mChMode) { - case BluetoothCodecConfig.CHANNEL_MODE_MONO: - case BluetoothCodecConfig.CHANNEL_MODE_JOINT_STEREO: - mNumBises = 1 * mNumSubGrps; - break; - case BluetoothCodecConfig.CHANNEL_MODE_STEREO: - mNumBises = 2 * mNumSubGrps; - break; - default: - Log.e(TAG,"channel mode unknown"); - } - mBroadcastBase.populateBase(); - mBroadcastAdvertiser.updatePAwithBase(); - mAdvertisingSet.getOwnAddress(); - } - } - - @Override - public void onAdvertisingSetStopped(AdvertisingSet advertisingSet) { - Log.i(TAG, "onAdvertisingSetStopped advertisingSet: " + advertisingSet); - mIsAdvertising = false; - int prev_state = mBroadcastState; - if (!goingDown && mBroadcastDeviceIsActive) { - Log.d(TAG,"onAdvertisingSetStopped: Unexpected Broadcast turn off"); - notifyBroadcastEnabled(false); - } - if (goingDown) { - Message msg = mHandler.obtainMessage(MSG_UPDATE_BROADCAST_STATE, - BluetoothBroadcast.STATE_DISABLING); - mHandler.sendMessageDelayed(msg,500); - goingDown = false; - } else { - mBroadcastState = BluetoothBroadcast.STATE_DISABLED; - broadcastState(mBroadcastState, prev_state); - } - } - - @Override - public void onAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enable, - int status) { - Log.i(TAG, "onAdvertisingEnabled advertisingSet: " + advertisingSet - + " status " + status + " enable: " + enable); - } - - @Override - public void onAdvertisingDataSet(AdvertisingSet advertisingSet, int status) { - Log.i(TAG, "onAdvertisingDataSet advertisingSet: " + advertisingSet - + " status " + status); - if (status == BluetoothGatt.GATT_SUCCESS) { - Log.i(TAG, "onAdvertisingDataSet: Base Info updated"); - } - } - @Override - public void onAdvertisingParametersUpdated(AdvertisingSet advertisingSet, - int txPower, int status) { - Log.i(TAG, "onAdvertisingParametersUpdated advertisingSet: " + advertisingSet - + " status " + status + " txPower " + txPower); - } - - @Override - public void onOwnAddressRead(AdvertisingSet advertisingSet, int addressType, - String address) { - Log.i(TAG, "onOwnAddressRead advertisingSet: " + advertisingSet - + " address " + address + " addressType " + addressType); - mAdvAddress = address; - mAdvAddressType = addressType; - } - - } - class BroadcastBase { - private final int LC3_SAMPLE_RATE_8000 = 0x01; - private final int LC3_SAMPLE_RATE_16000 = 0x02; - private final int LC3_SAMPLE_RATE_24000 = 0x03; - private final int LC3_SAMPLE_RATE_32000 = 0x04; - private final int LC3_SAMPLE_RATE_44100 = 0x05; - private final int LC3_SAMPLE_RATE_48000 = 0x06; - - int presentationDelay = 0x009C40; - byte [] mPresentationDelay = new byte[3]; - byte [] mCodecId = new byte[5]; - byte [] mCodecSpecificLength = new byte[1]; - byte [] mCodecSpecificSampleRate = new byte[3]; - byte [] mCodecSpecificFrameDuration = new byte[3]; - byte [] mCodecSpecificAudioLocation = new byte[6]; - byte [] mCodecSpecificOctetsPerFrame = new byte[3]; - byte [] mCodecSpecificBlocksPerSdu = new byte[3]; - byte [] mCodecSpecificLengthL2 = new byte[1]; - byte [] mCodecSpecificSampleRateL2 = new byte[3]; - byte [] mCodecSpecificFrameDurationL2 = new byte[3]; - byte [] mCodecSpecificAudioLocationL2 = new byte[6]; - byte [] mCodecSpecificOctetsPerFrameL2 = new byte[3]; - byte [] mCodecSpecificBlocksPerSduL2 = new byte[3]; - byte [] mMetadataLength = new byte[1]; - byte [] mMetadataContext = new byte[3]; - byte [] mNumSubgroups = new byte[1]; - byte [] mL2CodecID = new byte[1]; - byte [] mL2CodecSpecificLength = new byte[1]; - byte [] mL2mMetadataLength = new byte[1]; - byte [] mL2NumBises = new byte[1]; - byte [] mL2BisIndices = new byte[2]; - byte [] mL3BisIndex = new byte[1]; - byte [] mL3CodecSpecificLength = new byte[1]; - byte [] mL3CodecSpecificAudioLocation = new byte[6]; - byte mSampleRateLength = 2; - byte mSampleRateType = 0x01; - byte mFrameDurationLength = 2; - byte mFrameDurationType = 0x02; - byte mFrameDuration_7_5 = 0x00;//7.5 msec - byte mFrameDuration_10 = 0x01;//10msec - byte mAudioLocationLength = 5; - byte mAudioLocationType = 0x03; - byte mAudioLocationLeft = 0x01; - byte mAudioLocationRight = 0x02; - byte mAudioLocationCentre = 0x04; - byte mOctetsPerFrameLength = 3; - byte mOctestPerFrameType = 0x04; - byte mBlocksPerSduLength = 2; - byte mBlocksPerSduType = 0x05; - long LC3_CODEC_ID_OLD = 0x0000000001; - long LC3_CODEC_ID = 0x0000000006; - byte mCodecConfigLength = 0x10; //to be changed - byte mMediaContextType = 0x10; - byte [] BroadcastBaseArray = null; - //Metadata AD type - //Metadata - public BroadcastBase() { - //mccid = 0; - //int presentationDelay = 0x000014; - if (mPD == 20) { - Log.d(TAG,"Presentation Delay is set to 20msec"); - presentationDelay = 0x004E20; - } - if (mNewVersion) { - mPresentationDelay = intTobyteArray(presentationDelay, 3); - mNumSubgroups[0] = (byte)mNumSubGrps; - } else { - mPresentationDelay = intTobyteArray(presentationDelay, 3); - if (new_codec_id) { - mCodecId = longTobyteArray(LC3_CODEC_ID,5); - } else { - mCodecId = longTobyteArray(LC3_CODEC_ID_OLD,5); - } - mCodecSpecificLength[0] = mCodecConfigLength; - mCodecSpecificSampleRate = updateSampleRate(); - mCodecSpecificFrameDuration = updateFrameDuration(); - mCodecSpecificAudioLocation = updateAudioLocation(0); - mCodecSpecificOctetsPerFrame = updateOctetsPerFrame(); - mMetadataLength[0] = (byte)0x03; - int index = 0; - mMetadataContext[index++] = (byte)0x02; //length - mMetadataContext[index++] = (byte)mMediaContextType; //Type - mMetadataContext[index++] = (byte)0x01; //Value Music - mNumSubgroups[0] = (byte)mNumSubGrps; // only one set of broadcast is supported. - } - } - public byte [] getBroadcastBaseInfo() { - return BroadcastBaseArray; - } - public void updateBIGhandle(int handle) { - mBIGHandle = handle; - } - - public byte[] getMetadataContext() { - return mMetadataContext; - } - - public int getNumSubGroups() { - return mNumSubgroups[0]; - } - public byte [] updateSampleRate() { - int SR = mCodecConfig.getSampleRate(); - byte bytevalue; - switch (SR) { - case BluetoothCodecConfig.SAMPLE_RATE_48000: - if (mNewVersion) { - bytevalue = (byte)0x08; - } else { - bytevalue = (byte)0x06; - } - break; - case BluetoothCodecConfig.SAMPLE_RATE_44100: - if (mNewVersion) { - bytevalue = (byte)0x07; - } else { - bytevalue = (byte)0x05; - } - break; - case BluetoothCodecConfig.SAMPLE_RATE_32000: - if (mNewVersion) { - bytevalue = (byte)0x06; - } else { - bytevalue = (byte)0x04; - } - break; - case BluetoothCodecConfig.SAMPLE_RATE_24000: - if (mNewVersion) { - bytevalue = (byte)0x05; - } else { - bytevalue = (byte)0x03; - } - break; - case BluetoothCodecConfig.SAMPLE_RATE_16000: - if (mNewVersion) { - bytevalue = (byte)0x03; - } else { - bytevalue = (byte)0x02; - } - break; - case BluetoothCodecConfig.SAMPLE_RATE_8000: - bytevalue = (byte)0x01; - break; - default: - if (mNewVersion) { - bytevalue = (byte)0x08; - } else { - bytevalue = (byte)0x06; - } - } - byte [] ltv = {mSampleRateLength, mSampleRateType, bytevalue}; - return ltv; - } - public byte[] updateOctetsPerFrame() { - long bitrate = (int) mCodecConfig.getCodecSpecific1(); - long frameDuration = (int) mCodecConfig.getCodecSpecific2(); - byte bytevalue; - //Update OctetsPerFrame based on frame duration - switch ((int)bitrate) { - case 1001: - if (frameDuration == 0) { //7.5msec - bytevalue = (byte)30; - } else { //10msec - bytevalue = (byte)40; - } - break; - case 1002: - if (frameDuration == 0) { - bytevalue = (byte)45; - } else { - bytevalue = (byte)60; - } - break; - case 1004: - if (frameDuration == 0) { - bytevalue = (byte)75; - } else { - bytevalue = (byte)100; - } - break; - case 1006: - if (frameDuration == 0) { - bytevalue = (byte)90; - } else { - bytevalue = (byte)120; - } - break; - case 1007: - if (frameDuration == 0) { - bytevalue = (byte)117; - } else { - bytevalue = (byte)155; - } - break; - default: - bytevalue = (byte)100; - } - Log.d(TAG,"updateOctetsPerFrame: " + bytevalue); - byte [] ltv = {mOctetsPerFrameLength, mOctestPerFrameType, bytevalue, 0x00}; - return ltv; - } - private byte[] updateBlocksPerSdu() { - byte[] ltv = {mBlocksPerSduLength, mBlocksPerSduType,0x01}; - return ltv; - } - - public byte [] updateHAPSampleRate() { - int SR = mCodecConfig.getSampleRate(); - byte bytevalue; - switch (SR) { - case BluetoothCodecConfig.SAMPLE_RATE_16000: - bytevalue = (byte)0x02; - break; - case BluetoothCodecConfig.SAMPLE_RATE_24000: - bytevalue = (byte)0x03; - default: - bytevalue = (byte)0x02; - } - byte[] ltv = {mSampleRateLength, mSampleRateType, bytevalue}; - return ltv; - } - public byte [] updateHapOctetsPerFrame() { - long bitrate = mCodecConfig.getCodecSpecific1(); - long frameDuration = (int) mCodecConfig.getCodecSpecific2(); - byte bytevalue; - //Update OctetsPerFrame based on frame duration - switch((int)bitrate) { - case 1001: - if (frameDuration == 0) { //7.5msec - bytevalue = (byte)30; - } else { //10msec - bytevalue = (byte)40; - } - break; - case 1002: - if (frameDuration == 0) { - bytevalue = (byte)45; - } else { - bytevalue = (byte)60; - } - break; - default: - bytevalue = (byte)40; - } - byte [] ltv = {mOctetsPerFrameLength, mOctestPerFrameType, bytevalue, 0x00}; - return ltv; - } - public byte [] updateAudioLocation(int bis_index) { - int ch_mode = mCodecConfig.getChannelMode(); - byte ch = 0; - if (bis_index == 0) { - // stereo - if (ch_mode == BluetoothCodecConfig.CHANNEL_MODE_STEREO || - ch_mode == BluetoothCodecConfig.CHANNEL_MODE_JOINT_STEREO) - ch = (byte)0x03; - else if (ch_mode == BluetoothCodecConfig.CHANNEL_MODE_MONO) - ch = (byte)0x00; - } else { - if (ch_mode == BluetoothCodecConfig.CHANNEL_MODE_STEREO) { - int bises = (mNumBises/((int)mNumSubgroups[0])); - ch = (byte)(mAudioLocationRight - (bis_index % bises)); - } else if (ch_mode == BluetoothCodecConfig.CHANNEL_MODE_JOINT_STEREO) { - ch = (byte)0x03; - } else if (ch_mode == BluetoothCodecConfig.CHANNEL_MODE_MONO) { - ch = (byte)0x00; - } - } - byte [] loc = {mAudioLocationLength, mAudioLocationType, ch, 0x00, 0x00, 0x00}; - return loc; - } - public byte[] updateFrameDuration() { - byte mFD = mFrameDuration_10; - if (mCodecConfig.getCodecSpecific2() == 0) { - Log.d(TAG,"updateFrameDuration: 7.5msec"); - mFD = mFrameDuration_7_5; - } else { - Log.d(TAG,"updateFrameDuration: 10 msec"); - } - byte[] ltv = {mFrameDurationLength,mFrameDurationType,mFD}; - return ltv; - } - public byte[] intTobyteArray(int intValue, int bytelen) { - byte [] val = new byte[bytelen]; - for (int i = 0; i < bytelen; i++) { - val[(bytelen - 1) -i] = (byte)((intValue >> (8 *(bytelen - (i + 1)))) & 0x000000FF); - } - return val; - } - public byte [] longTobyteArray(long longValue, int bytelen) { - byte [] val = new byte[bytelen]; - for (int i = 0; i < bytelen; i++) { - val[(bytelen - 1) -i] = (byte)((longValue >> (8 *(bytelen - (i + 1)))) & 0x00000000000000FF); - } - return val; - } - public int calculateBisPerGroup() { - int mChMode = mCodecConfig.getChannelMode(); - int numbis = 2; - switch (mChMode) { - case BluetoothCodecConfig.CHANNEL_MODE_MONO: - case BluetoothCodecConfig.CHANNEL_MODE_JOINT_STEREO: - Log.d(TAG,"BisPerGroup is 1"); - numbis = 1; - break; - case BluetoothCodecConfig.CHANNEL_MODE_STEREO: - Log.d(TAG,"BisPerGroup is 2"); - numbis = 2; - break; - default: - Log.e(TAG,"channel mode unknown"); - } - return numbis; - } - public void populateBase() { - if (DBG) Log.d(TAG,"populateBase"); - byte [] baseL1 = populate_level1_base(); - byte [] baseL2 = populate_level2_base(); - ByteArrayOutputStream ByteStr = new ByteArrayOutputStream(); - ByteStr.write(baseL1, 0, baseL1.length); - ByteStr.write(baseL2, 0, baseL2.length); - if (!mNewVersion) { - byte [] baseL3 = populate_level3_base(); - ByteStr.write(baseL3, 0, baseL3.length); - } - BroadcastBaseArray = ByteStr.toByteArray(); - } - private byte [] populate_level1_base() { - ByteArrayOutputStream ByteStr = new ByteArrayOutputStream(); - if (mNewVersion) { - mPresentationDelay = intTobyteArray(presentationDelay, 3); - mNumSubgroups[0] = (byte)mNumSubGrps;//calculate based on num bises and channel mode - ByteStr.write(mPresentationDelay, 0, mPresentationDelay.length); - ByteStr.write(mNumSubgroups, 0, mNumSubgroups.length); - } else { - mPresentationDelay = intTobyteArray(presentationDelay, 3); - if (new_codec_id) { - mCodecId = longTobyteArray(LC3_CODEC_ID,5); - } else { - mCodecId = longTobyteArray(LC3_CODEC_ID_OLD,5); - } - mCodecSpecificLength[0] = mCodecConfigLength; - mCodecSpecificSampleRate = updateSampleRate(); - mCodecSpecificFrameDuration = updateFrameDuration(); - mCodecSpecificAudioLocation = updateAudioLocation(0); - mCodecSpecificOctetsPerFrame = updateOctetsPerFrame(); - mMetadataLength[0] = (byte)0x03; - byte [] mediacontext = {2, mMediaContextType, (byte)0x01}; - mNumSubgroups[0] = (byte)mNumSubGrps;//calculate based on num bises and channel mode - - ByteStr.write(mPresentationDelay, 0, mPresentationDelay.length); - ByteStr.write(mCodecId, 0, mCodecId.length); - ByteStr.write(mCodecSpecificLength, 0, mCodecSpecificLength.length); - ByteStr.write(mCodecSpecificSampleRate, 0, mCodecSpecificSampleRate.length); - ByteStr.write(mCodecSpecificFrameDuration, 0, mCodecSpecificFrameDuration.length); - ByteStr.write(mCodecSpecificAudioLocation, 0, mCodecSpecificAudioLocation.length); - ByteStr.write(mCodecSpecificOctetsPerFrame, 0, mCodecSpecificOctetsPerFrame.length); - ByteStr.write(mMetadataLength, 0, mMetadataLength.length); - ByteStr.write(mMetadataContext, 0, mMetadataContext.length); - ByteStr.write(mNumSubgroups, 0, mNumSubgroups.length); - } - return ByteStr.toByteArray(); - } - private byte [] populate_level2_base() { - Log.d(TAG,"populate_level2_base, subgroup = " + mNumSubgroups[0]); - ByteArrayOutputStream ByteStr = new ByteArrayOutputStream(); - byte [] metalength = new byte[1]; - int bisPerGroup = calculateBisPerGroup();//mNumBises/mNumSubGrps; - byte [] numBises = new byte[1]; - numBises = intTobyteArray(bisPerGroup,1); - byte [] bisInd = new byte[bisPerGroup]; - if (mNewVersion) { - byte[] mcid = new byte[1]; - if (new_codec_id) { - mcid = longTobyteArray(LC3_CODEC_ID,5); - } else { - mcid = longTobyteArray(LC3_CODEC_ID_OLD,5); - } - mMetadataLength[0] = (byte)0x04; - byte [] mediacontext = {3, 2, (byte)0x04, (byte)0x00}; - int codecConfigLength = 0x13; - mCodecSpecificLength = intTobyteArray(codecConfigLength, 1); - for (int i = 0; i < mNumSubgroups[0]; i++) { - if (mPartialSimulcast) { - if (i < (mNumSubgroups[0] / 2)) { - //High quality - ByteStr.write(numBises, 0, numBises.length); - ByteStr.write(mcid, 0, mcid.length); - mCodecSpecificSampleRate = updateSampleRate(); - mCodecSpecificFrameDuration = updateFrameDuration(); - mCodecSpecificAudioLocation = updateAudioLocation(0); - mCodecSpecificOctetsPerFrame = updateOctetsPerFrame(); - mCodecSpecificBlocksPerSdu= updateBlocksPerSdu(); - ByteStr.write(mCodecSpecificLength, 0, mCodecSpecificLength.length); - ByteStr.write(mCodecSpecificSampleRate, 0, mCodecSpecificSampleRate.length); - ByteStr.write(mCodecSpecificFrameDuration, 0, mCodecSpecificFrameDuration.length); - ByteStr.write(mCodecSpecificAudioLocation, 0, mCodecSpecificAudioLocation.length); - ByteStr.write(mCodecSpecificOctetsPerFrame, 0, mCodecSpecificOctetsPerFrame.length); - ByteStr.write(mCodecSpecificBlocksPerSdu, 0, mCodecSpecificBlocksPerSdu.length); - ByteStr.write(mMetadataLength, 0, mMetadataLength.length); - ByteStr.write(mediacontext, 0, mediacontext.length); - byte[] level3 = populate_level3_new_base(i, mcid, mCodecSpecificSampleRate, - mCodecSpecificFrameDuration, - mCodecSpecificOctetsPerFrame, - mCodecSpecificBlocksPerSdu, - mediacontext); - ByteStr.write(level3, 0, level3.length); - mMetaInfo.put(i,new MetadataLtv(mediacontext)); - } else { - //Low quality - ByteStr.write(numBises, 0, numBises.length); - ByteStr.write(mcid, 0, mcid.length); - mCodecSpecificSampleRateL2= updateHAPSampleRate(); - mCodecSpecificFrameDurationL2= updateFrameDuration(); - mCodecSpecificAudioLocationL2= updateAudioLocation(0); - mCodecSpecificOctetsPerFrameL2= updateHapOctetsPerFrame(); - mCodecSpecificBlocksPerSduL2= updateBlocksPerSdu(); - ByteStr.write(mCodecSpecificLength, 0, mCodecSpecificLength.length); - ByteStr.write(mCodecSpecificSampleRateL2, 0, mCodecSpecificSampleRateL2.length); - ByteStr.write(mCodecSpecificFrameDurationL2, 0, mCodecSpecificFrameDurationL2.length); - ByteStr.write(mCodecSpecificAudioLocationL2, 0, mCodecSpecificAudioLocationL2.length); - ByteStr.write(mCodecSpecificOctetsPerFrameL2, 0, mCodecSpecificOctetsPerFrameL2.length); - ByteStr.write(mCodecSpecificBlocksPerSduL2, 0, mCodecSpecificBlocksPerSduL2.length); - ByteStr.write(mMetadataLength, 0, mMetadataLength.length); - ByteStr.write(mediacontext, 0, mediacontext.length); - byte[] level3 = populate_level3_new_base(i, mcid, mCodecSpecificSampleRateL2, - mCodecSpecificFrameDurationL2, - mCodecSpecificOctetsPerFrameL2, - mCodecSpecificBlocksPerSduL2, - mediacontext); - ByteStr.write(level3, 0, level3.length); - mMetaInfo.put(i,new MetadataLtv(mediacontext)); - } - } else { - ByteStr.write(numBises, 0, numBises.length); - ByteStr.write(mcid, 0, mcid.length); - mCodecSpecificLengthL2 = intTobyteArray(codecConfigLength, 1); - mCodecSpecificSampleRateL2 = updateSampleRate(); - mCodecSpecificFrameDurationL2 = updateFrameDuration(); - mCodecSpecificAudioLocationL2 = updateAudioLocation(0); - mCodecSpecificOctetsPerFrameL2 = updateOctetsPerFrame(); - mCodecSpecificBlocksPerSduL2 = updateBlocksPerSdu(); - - ByteStr.write(mCodecSpecificLengthL2, 0, mCodecSpecificLengthL2.length); - ByteStr.write(mCodecSpecificSampleRateL2, 0, mCodecSpecificSampleRateL2.length); - ByteStr.write(mCodecSpecificFrameDurationL2, 0, mCodecSpecificFrameDurationL2.length); - ByteStr.write(mCodecSpecificAudioLocationL2, 0, mCodecSpecificAudioLocationL2.length); - ByteStr.write(mCodecSpecificOctetsPerFrameL2, 0, mCodecSpecificOctetsPerFrameL2.length); - ByteStr.write(mCodecSpecificBlocksPerSduL2, 0, mCodecSpecificBlocksPerSduL2.length); - ByteStr.write(mMetadataLength, 0, mMetadataLength.length); - ByteStr.write(mediacontext, 0, mediacontext.length); - byte[] level3 = populate_level3_new_base(0, mcid, mCodecSpecificSampleRateL2, - mCodecSpecificFrameDurationL2, - mCodecSpecificOctetsPerFrameL2, - mCodecSpecificBlocksPerSduL2, - mediacontext); - ByteStr.write(level3, 0, level3.length); - mMetaInfo.put(i,new MetadataLtv(mediacontext)); - } - } - } else { - for (int i = 0; i < mNumSubgroups[0]; i++) { - if (mPartialSimulcast) { - if (i < (mNumSubgroups[0] / 2)) { - //High quality - byte[] mcid = new byte[1]; - mcid = intTobyteArray(0xFE,1); - mL2CodecSpecificLength = intTobyteArray(0,1);//(byte) 0; - ByteStr.write(mcid, 0, mcid.length); - ByteStr.write(mL2CodecSpecificLength, 0, mL2CodecSpecificLength.length); - } else { - //Low quality - byte[] mcid = new byte[5]; - if (new_codec_id) { - mcid = longTobyteArray(LC3_CODEC_ID,5); - } else { - mcid = longTobyteArray(LC3_CODEC_ID_OLD,5); - } - mCodecSpecificLengthL2 = intTobyteArray(mCodecConfigLength, 1); - mCodecSpecificSampleRateL2 = updateHAPSampleRate(); - mCodecSpecificFrameDurationL2 = updateFrameDuration(); - mCodecSpecificAudioLocationL2 = updateAudioLocation(0); - mCodecSpecificOctetsPerFrameL2 = updateHapOctetsPerFrame(); - ByteStr.write(mcid, 0, mcid.length); - ByteStr.write(mL2CodecSpecificLength, 0, mL2CodecSpecificLength.length); - ByteStr.write(mCodecSpecificSampleRateL2, 0, mCodecSpecificSampleRateL2.length); - ByteStr.write(mCodecSpecificFrameDurationL2, 0, mCodecSpecificFrameDurationL2.length); - ByteStr.write(mCodecSpecificAudioLocationL2, 0, mCodecSpecificAudioLocationL2.length); - ByteStr.write(mCodecSpecificOctetsPerFrameL2, 0, mCodecSpecificOctetsPerFrameL2.length); - } - metalength = intTobyteArray(0, 1);//(byte)0; - for (int j = 0; j < bisPerGroup;j++) { - bisInd[j] = (byte)(1 + (bisPerGroup * i) + j); - } - ByteStr.write(metalength, 0, metalength.length); - ByteStr.write(numBises, 0, numBises.length); - ByteStr.write(bisInd, 0, bisInd.length); - } else { - byte [] mcid = new byte[1]; - mcid = intTobyteArray(0xFE,1);//(byte)0xFE; - mL2CodecSpecificLength = intTobyteArray(0,1);//(byte)0; - metalength = intTobyteArray(0,1);//(byte)0; - for (int j = 0; j < bisPerGroup;j++) { - bisInd[j] = (byte)(1 + (bisPerGroup * i) + j); - } - ByteStr.write(mcid, 0, mcid.length); - ByteStr.write(mL2CodecSpecificLength, 0, mL2CodecSpecificLength.length); - ByteStr.write(metalength, 0, metalength.length); - ByteStr.write(numBises, 0, numBises.length); - ByteStr.write(bisInd, 0, bisInd.length); - } - } - } - return ByteStr.toByteArray(); - } - private byte[] populate_level3_base() { - ByteArrayOutputStream ByteStr = new ByteArrayOutputStream(); - for (int i = 0; i < mNumBises; i++) { - byte[] index = new byte[1]; - byte [] configlength = new byte[1]; - index[0] = (byte)(1 + i); //fetch from mAdvertisingSet - configlength[0] = (byte)6; - byte [] config = updateAudioLocation(i+1); - ByteStr.write(index, 0, index.length); - ByteStr.write(configlength,0, configlength.length); - ByteStr.write(config, 0, config.length); - mBisInfo.add(new BisInfo((int)index[0], mCodecId, mCodecSpecificSampleRate, mCodecSpecificFrameDuration, - config, mCodecSpecificOctetsPerFrame, mMetadataContext)); - } - return ByteStr.toByteArray(); - } - private byte[] populate_level3_new_base(int subGroupId, byte[] codecId, byte[] SampleRate, - byte[] frameDuration, byte[] octetsPerFrame, byte[] BlocksPerSdu, - byte[] mMetadata) { - ByteArrayOutputStream ByteStr = new ByteArrayOutputStream(); - int bisPerGroup = calculateBisPerGroup(); - for (int i = 0; i < bisPerGroup; i++) { - byte[] index = new byte[1]; - byte [] configlength = new byte[1]; - index[0] = (byte)(1 + i + (bisPerGroup * subGroupId)); - configlength[0] = (byte)6; - byte [] config = updateAudioLocation(i+1); - ByteStr.write(index, 0, index.length); - ByteStr.write(configlength,0, configlength.length); - ByteStr.write(config, 0, config.length); - mBisInfo.add(new BisInfo((int)index[0], codecId, SampleRate, frameDuration, config, - octetsPerFrame, BlocksPerSdu, mMetadata, subGroupId)); - } - return ByteStr.toByteArray(); - } - } - public class BisInfo { - public int BisIndex; - public byte [] mCodecId = new byte[5]; - public CodecConfigLtv BisCodecConfig; - public MetadataLtv BisMetadata; - public int mSubGroupId; - public BisInfo(int index, byte[] codecId, byte[] CodecSpecificSampleRate, byte[] CodecSpecificFrameDuration, - byte[] CodecSpecificAudioLocation, byte[] CodecSpecificOctetsPerFrame, byte[] AudioContext) { - BisIndex = index; - mCodecId = codecId; - BisCodecConfig = new CodecConfigLtv(CodecSpecificSampleRate, CodecSpecificFrameDuration, - CodecSpecificAudioLocation, CodecSpecificOctetsPerFrame); - BisMetadata = new MetadataLtv(AudioContext); - mSubGroupId = -1; - } - public BisInfo (int index, byte[] codecId, byte[] CodecSpecificSampleRate, byte[] CodecSpecificFrameDuration, - byte[] CodecSpecificAudioLocation, byte[] CodecSpecificOctetsPerFrame, - byte[] CodecSpecificBlocksPerSdu, byte[] AudioContext, int subGroupId) { - BisIndex = index; - mCodecId = codecId; - BisCodecConfig = new CodecConfigLtv(CodecSpecificSampleRate, CodecSpecificFrameDuration, - CodecSpecificAudioLocation, CodecSpecificBlocksPerSdu, - CodecSpecificOctetsPerFrame); - BisMetadata = new MetadataLtv(AudioContext); - mSubGroupId = subGroupId; - } - } - public class CodecConfigLtv{ - byte [] mCodecSpecificSampleRate; - byte [] mCodecSpecificFrameDuration; - byte [] mCodecSpecificAudioLocation; - byte [] mCodecSpecificOctetsPerFrame; - byte [] mCodecSpecificBlocksPerSdu; - public CodecConfigLtv(byte[] CodecSpecificSampleRate, - byte[] CodecSpecificFrameDuration, - byte[] CodecSpecificAudioLocation, - byte[] CodecSpecificOctetsPerFrame) { - mCodecSpecificSampleRate = CodecSpecificSampleRate; - mCodecSpecificFrameDuration = CodecSpecificFrameDuration; - mCodecSpecificAudioLocation = CodecSpecificAudioLocation; - mCodecSpecificOctetsPerFrame = CodecSpecificOctetsPerFrame; - } - public CodecConfigLtv(byte[] CodecSpecificSampleRate, - byte[] CodecSpecificFrameDuration, - byte[] CodecSpecificAudioLocation, - byte[] CodecSpecificOctetsPerFrame, - byte [] CodecSpecificBlocksPerSdu) { - mCodecSpecificSampleRate = CodecSpecificSampleRate; - mCodecSpecificFrameDuration = CodecSpecificFrameDuration; - mCodecSpecificAudioLocation = CodecSpecificAudioLocation; - mCodecSpecificOctetsPerFrame = CodecSpecificOctetsPerFrame; - mCodecSpecificBlocksPerSdu = CodecSpecificBlocksPerSdu; - } - public byte[] getByteArray() { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - try { - outputStream.write(mCodecSpecificSampleRate); - outputStream.write(mCodecSpecificFrameDuration); - outputStream.write(mCodecSpecificAudioLocation); - outputStream.write(mCodecSpecificOctetsPerFrame); - if (mNewVersion) { - outputStream.write(mCodecSpecificBlocksPerSdu); - } - } catch (IOException e) { - Log.e(TAG, "getBytes: ioexception caught!" + e); - return null; - } - return outputStream.toByteArray( ); - } - } - public class MetadataLtv { - byte[] mAudioContext; - public MetadataLtv(byte[] audiocontext) { - mAudioContext = audiocontext; - } - public byte[] getByteArray() { - return mAudioContext; - } - } - class BroadcastCodecConfig { - public BroadcastCodecConfig() { - //Default configuration - int sr, ch_mode; - long codecspecific1; - switch(mBroadcastConfigSettings) { - case 1: - sr = BluetoothCodecConfig.SAMPLE_RATE_16000; - ch_mode = BluetoothCodecConfig.CHANNEL_MODE_MONO; - codecspecific1 = 1001;//32kbps - break; - case 2: - sr = BluetoothCodecConfig.SAMPLE_RATE_16000; - ch_mode = BluetoothCodecConfig.CHANNEL_MODE_STEREO; - codecspecific1 = 1001;//32kbps - break; - case 3: - sr = BluetoothCodecConfig.SAMPLE_RATE_48000; - ch_mode = BluetoothCodecConfig.CHANNEL_MODE_MONO; - codecspecific1 = 1004;//80kbps - break; - case 4: - sr = BluetoothCodecConfig.SAMPLE_RATE_48000; - ch_mode = BluetoothCodecConfig.CHANNEL_MODE_STEREO; - codecspecific1 = 1004;//80kbps - break; - case 5: - sr = BluetoothCodecConfig.SAMPLE_RATE_48000; - ch_mode = BluetoothCodecConfig.CHANNEL_MODE_MONO; - codecspecific1 = 1006;//96kbps - break; - case 6: - sr = BluetoothCodecConfig.SAMPLE_RATE_48000; - ch_mode = BluetoothCodecConfig.CHANNEL_MODE_STEREO; - codecspecific1 = 1006;//96 - break; - case 7: - sr = BluetoothCodecConfig.SAMPLE_RATE_48000; - ch_mode = BluetoothCodecConfig.CHANNEL_MODE_MONO; - codecspecific1 = 1007;//124 - break; - case 8: - default: - sr = BluetoothCodecConfig.SAMPLE_RATE_48000; - ch_mode = BluetoothCodecConfig.CHANNEL_MODE_STEREO; - codecspecific1 = 1007; - break; - - } - mCodecConfig = new BluetoothCodecConfig.Builder() - .setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LC3) - .setCodecPriority(BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT) - .setSampleRate(sr) - .setBitsPerSample(BluetoothCodecConfig.BITS_PER_SAMPLE_24) - .setChannelMode(ch_mode) - .setCodecSpecific1(codecspecific1) - .setCodecSpecific2(1) - .setCodecSpecific3(0) - .setCodecSpecific4(0) - .build(); - if (mPartialSimulcast) { - mHapCodecConfig = new BluetoothCodecConfig.Builder() - .setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LC3) - .setCodecPriority(BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT) - .setSampleRate(BluetoothCodecConfig.SAMPLE_RATE_16000) - .setBitsPerSample(BluetoothCodecConfig.BITS_PER_SAMPLE_24) - .setChannelMode(BluetoothCodecConfig.CHANNEL_MODE_STEREO) - .setCodecSpecific1(1000) - .setCodecSpecific2(1) - .setCodecSpecific3(0) - .setCodecSpecific4(0) - .build(); - } - } - public void updateBroadcastCodecConfig(BluetoothCodecConfig newConfig) { - if (DBG) Log.d(TAG, "updateBroadcastCodecConfig: " + newConfig); - mCodecConfig = newConfig; - int mChMode = mCodecConfig.getChannelMode(); - switch (mChMode) { - case BluetoothCodecConfig.CHANNEL_MODE_MONO: - case BluetoothCodecConfig.CHANNEL_MODE_JOINT_STEREO: - mNumBises = 1 * mNumSubGrps; - break; - case BluetoothCodecConfig.CHANNEL_MODE_STEREO: - mNumBises = 2 * mNumSubGrps; - break; - default: - Log.e(TAG,"channel mode unknown"); - } - } - } - - /** - * Binder object: must be a static class or memory leak may occur. - */ - @VisibleForTesting - static class BluetoothBroadcastBinder extends IBluetoothBroadcast.Stub - implements IProfileServiceBinder { - private BroadcastService mService; - - private BroadcastService getService() { - if (!Utils.checkCallerIsSystemOrActiveUser(TAG)) { - return null; - } - - if (mService != null && mService.isAvailable()) { - return mService; - } - return null; - } - - BluetoothBroadcastBinder(BroadcastService svc) { - mService = svc; - } - - @Override - public void cleanup() { - mService = null; - } - @Override - public boolean SetBroadcast(boolean enable, String packageName) { - BroadcastService service = getService(); - if (service == null) { - return false; - } - if (enable) { - return service.EnableBroadcast(packageName); - } - else { - return service.DisableBroadcast(packageName); - } - //return false; - } - - @Override - public boolean SetEncryption(boolean enable, int enc_len, boolean use_existing, - String packageName) { - BroadcastService service = getService(); - if (service == null) { - return false; - } - return service.SetEncryption(enable, enc_len, use_existing, packageName); - } - - @Override - public byte[] GetEncryptionKey(String packageName) { - BroadcastService service = getService(); - if (service == null) { - return null; - } - return service.GetEncryptionKey(packageName); - } - @Override - public int GetBroadcastStatus(String packageName) { - BroadcastService service = getService(); - if (service == null) { - return BluetoothBroadcast.STATE_DISABLED; - } - return service.GetBroadcastStatus(packageName); - } - } -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/broadcast/BroadcastStackEvent.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/broadcast/BroadcastStackEvent.java deleted file mode 100644 index a1b5596d5af0b842ba04f80a5c96e85a89610eb8..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/broadcast/BroadcastStackEvent.java +++ /dev/null @@ -1,120 +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. - * - ******************************************************************************/ - -package com.android.bluetooth.broadcast; - -import android.bluetooth.BluetoothCodecStatus; -import android.bluetooth.BluetoothBroadcast; -/** - * Stack event sent via a callback from JNI to Java, or generated. - */ -public class BroadcastStackEvent { - // Event types for STACK_EVENT message (coming from native) - private static final int EVENT_TYPE_NONE = 0; - public static final int EVENT_TYPE_BROADCAST_STATE_CHANGED = 1; - public static final int EVENT_TYPE_BROADCAST_AUDIO_STATE_CHANGED = 2; - public static final int EVENT_TYPE_ENC_KEY_GENERATED = 3; - public static final int EVENT_TYPE_CODEC_CONFIG_CHANGED = 4; - public static final int EVENT_TYPE_SETUP_BIG = 5; - public static final int EVENT_TYPE_BROADCAST_ID_GENERATED = 6; - - public static final int STATE_IDLE = 0; - public static final int STATE_CONFIGURED = 1; - public static final int STATE_STREAMING = 2; - - public static final int STATE_STOPPED = 0; - public static final int STATE_STARTED = 1; - - public int type = EVENT_TYPE_NONE; - public int advHandle = 0; - public int valueInt = 0; - public int bigHandle = 0; - public int NumBises = 0; - public int[] BisHandles; - public byte[] BroadcastId = new byte[3]; - public String key; - public BluetoothCodecStatus codecStatus; - - BroadcastStackEvent(int type) { - this.type = type; - } - - @Override - public String toString() { - // event dump - StringBuilder result = new StringBuilder(); - result.append("BroadcastStackEvent {type:" + eventTypeToString(type)); - result.append(", value1:" + eventTypeValueIntToString(type, valueInt)); - if (codecStatus != null) { - result.append(", codecStatus:" + codecStatus); - } - result.append("}"); - return result.toString(); - } - - private static String eventTypeToString(int type) { - switch (type) { - case EVENT_TYPE_NONE: - return "EVENT_TYPE_NONE"; - case EVENT_TYPE_BROADCAST_STATE_CHANGED: - return "EVENT_TYPE_BROADCAST_STATE_CHANGED"; - case EVENT_TYPE_BROADCAST_AUDIO_STATE_CHANGED: - return "EVENT_TYPE_BROADCAST_AUDIO_STATE_CHANGED"; - case EVENT_TYPE_ENC_KEY_GENERATED: - return "EVENT_TYPE_ENC_KEY_GENERATED"; - case EVENT_TYPE_CODEC_CONFIG_CHANGED: - return "EVENT_TYPE_CODEC_CONFIG_CHANGED"; - case EVENT_TYPE_SETUP_BIG: - return "EVENT_TYPE_SETUP_BIG"; - default: - return "EVENT_TYPE_UNKNOWN:" + type; - } - } - - private static String eventTypeValueIntToString(int type, int value) { - switch (type) { - case EVENT_TYPE_BROADCAST_STATE_CHANGED: - switch (value) { - case BluetoothBroadcast.STATE_DISABLED: - return "DISABLED"; - case BluetoothBroadcast.STATE_ENABLING: - return "ENABLING"; - case BluetoothBroadcast.STATE_ENABLED: - return "CONFIGURED"; - case BluetoothBroadcast.STATE_STREAMING: - return "STREAMING"; - default: - break; - } - break; - case EVENT_TYPE_BROADCAST_AUDIO_STATE_CHANGED: - switch(value) { - case BluetoothBroadcast.STATE_PLAYING: - return "PLAYING"; - case BluetoothBroadcast.STATE_NOT_PLAYING: - return "NOT PLAYING"; - default: - break; - } - default: - break; - } - return Integer.toString(value); - } -} - diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/cc/CCHalConstants.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/cc/CCHalConstants.java deleted file mode 100644 index eb4df0bcb2d21c94395def01daccdefc716c974a..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/cc/CCHalConstants.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - *Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. - */ - -/* - * Copyright 2012 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.cc; - -/* - * @hide - */ -public final class CCHalConstants { - static final int NETWORK_STATE_NOT_AVAILABLE = 0; - static final int NETWORK_STATE_AVAILABLE = 1; - - static final int SERVICE_TYPE_HOME = 0; - static final int SERVICE_TYPE_ROAMING = 1; - - static final int CALL_STATE_ACTIVE = 0; - static final int CALL_STATE_HELD = 1; - static final int CALL_STATE_DIALING = 2; - static final int CALL_STATE_ALERTING = 3; - static final int CALL_STATE_INCOMING = 4; - static final int CALL_STATE_WAITING = 5; - static final int CALL_STATE_IDLE = 6; - static final int CALL_STATE_DISCONNECTED = 7; - - //Call State as expected by Stack/CC - static final int CCS_STATE_INCOMING = 0x00; - static final int CCS_STATE_DIALING = 0x01; - static final int CCS_STATE_ALERTING = 0x02; - static final int CCS_STATE_ACTIVE = 0x03; - static final int CCS_STATE_LOCAL_HELD= 0x04; - static final int CCS_STATE_REMOTELY_HELD= 0x05; - static final int CCS_STATE_LOCAL_REMOTE_HELD= 0x06; - static final int CCS_STATE_DISCONNECTED = 0x07; - - static final int BTCC_OP_ACCEPT = 0; - static final int BTCC_OP_TERMINATE = 1; - static final int BTCC_OP_LOCAL_HLD = 2; - static final int BTCC_OP_LOCAL_RETRIEVE = 3; - static final int BTCC_OP_ORIGINATE = 4; - static final int BTCC_OP_JOIN = 5; - - static final int BTCC_OP_SUCCESS = 0x00; - static final int BTCC_OP_NOT_POSSIBLE = 0x02; - - //default call index for failures - static final int BTCC_DEF_INDEX_FOR_FAILURES = 0; - - static int getCCsCallState(int telephonyCallState) { - int ret = 0xFF; - switch(telephonyCallState) { - case CALL_STATE_ACTIVE: ret = CCS_STATE_ACTIVE; break; - case CALL_STATE_HELD: ret = CCS_STATE_LOCAL_HELD; break; - case CALL_STATE_DIALING: ret = CCS_STATE_DIALING; break; - case CALL_STATE_ALERTING: ret = CCS_STATE_ALERTING; break; - case CALL_STATE_INCOMING: ret = CCS_STATE_INCOMING; break; - case CALL_STATE_DISCONNECTED: ret = CCS_STATE_DISCONNECTED; break; - //this means second Incoming call is waiting - case CALL_STATE_WAITING: ret = CCS_STATE_INCOMING; break; - default: break; - } - return ret; - } - - public static String operationToString(int what) { - switch (what) { - case BTCC_OP_ACCEPT : - return "BTCC_OP_ACCEPT"; - case BTCC_OP_TERMINATE : - return "BTCC_OP_TERMINATE"; - case BTCC_OP_LOCAL_HLD : - return "BTCC_OP_LOCAL_HLD"; - case BTCC_OP_LOCAL_RETRIEVE : - return "BTCC_OP_LOCAL_RETRIEVE"; - case BTCC_OP_ORIGINATE : - return "BTCC_OP_ORIGINATE"; - case BTCC_OP_JOIN : - return "BTCC_OP_JOIN"; - default: - break; - } - return Integer.toString(what); - } -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/cc/CCNativeInterface.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/cc/CCNativeInterface.java deleted file mode 100644 index 1e93c62fc4a7814ddebe3ade3dce9f263e5b697f..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/cc/CCNativeInterface.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - *Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. - */ - -/* - * Copyright 2017 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. - */ - -/* - * Defines the native interface that is used by state machine/service to - * send or receive messages from the native stack. This file is registered - * for the native methods in the corresponding JNI C++ file. - */ -package com.android.bluetooth.cc; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.util.Log; -import java.util.ArrayList; -import java.util.List; - -import com.android.bluetooth.Utils; -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; -import java.nio.charset.StandardCharsets; - -/** - * Ccp Native Interface to/from JNI. - */ -public class CCNativeInterface { - private static final String TAG = "CCNativeInterface"; - private static final boolean DBG = true; - private BluetoothAdapter mAdapter; - - @GuardedBy("INSTANCE_LOCK") - private static CCNativeInterface sInstance; - private static final Object INSTANCE_LOCK = new Object(); - - static { - classInitNative(); - } - - private CCNativeInterface() { - mAdapter = BluetoothAdapter.getDefaultAdapter(); - if (mAdapter == null) { - Log.w(TAG, "No Bluetooth Adapter Available"); - } - } - - /** - * This class is a singleton because native library should only be loaded once - * - * @return default instance - */ - public static CCNativeInterface getInstance() { - synchronized (INSTANCE_LOCK) { - if (sInstance == null) { - sInstance = new CCNativeInterface(); - } - return sInstance; - } - } - - /** - * Initialize native stack - * - * @param ccsClients maximum number of CCS clients that can be connected simultaneously - * @param inbandRingingEnabled whether in-band ringing is enabled on this AG - */ - @VisibleForTesting - public void init(int maxCcsClients, boolean inbandRingingEnabled) { - initializeNative("00008fd1-0000-1000-8000-00805F9B34FB", maxCcsClients, inbandRingingEnabled); - } - - /** - * Cleanup the native interface. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void cleanup() { - cleanupNative(); - } - - /** - * Disconnects Call control from a remote device. - * - * @param device the remote device - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean disconnect(BluetoothDevice device) { - return disconnectNative(getByteAddress(device)); - } - /** - * update CC optional supported feature - * @param feature - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean callControlOptionalFeatures(int feature) { - return callControlPointOpcodeSupportedNative(feature); - } - - /** - * Sets the CC call state - * @param state - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean callState(ArrayList callList) { - int len = callList.size(); - byte[] cStateListBytes = new byte[len*3]; - for (int i=0; i mCallStateList = null; - private HashMap mPrevCallStateList = null; - private Queue mLccTobeQueued = null; - private Queue mLccWaitForResponseQ = null; - - private static final int FLAGS_DIRECTION_BIT = 0x0001; - private static final int CC_SIGNAL_STRENGTH_FACTOR = 20; - - private static final int CC_CONTENT_CONTROL_ID = 77; - private static final int CC_OPTIONAL_LOCAL_HOLD_FEAT = 0x01; - private static final int CC_OPTIONAL_JOIN_FEAT = 0x02; - private static final int CALL_CONTROL_OPTIONAL_FEATURES = CC_OPTIONAL_LOCAL_HOLD_FEAT|CC_OPTIONAL_JOIN_FEAT; - //native event - static final int EVENT_TYPE_CONNECTION_STATE_CHANGED = 1; - static final int EVENT_TYPE_CALL_CONTROL_POINT_CHANGED = 2; - //CC to JNI update - static final int UPDATE_BEARER_NAME = 3; - static final int UPDATE_BEARER_TECH = 4; - static final int UPDATE_STATUS_FLAGS = 5; - static final int UPDATE_SIGNAL_STRENGTH = 6; - static final int UPDATE_BEARERLIST_SUPPORTED = 7; - static final int UPDATE_CONTENT_CONTROL_ID = 8; - static final int UPDATE_CALL_STATE = 9; - static final int UPDATE_CALL_CONTROL_OPCODES_SUPPORTED = 10; - static final int UPDATE_CALL_CONTROL_RESPONSE = 11; - static final int UPDATE_INCOMING_CALL = 12; - static final int PROCESS_CALL_STATE = 13; - static final int PROCESS_PHONE_STATE_CHANGED = 14; - static final int ACTIVE_DEVICE_CHANGED = 15; - - @Override - protected IProfileServiceBinder initBinder() { - return new CcBinder(this); - } - - @Override - protected void create() { - Log.i(TAG, "create()"); - if (mCreated) { - throw new IllegalStateException("create() called twice"); - } - mCreated = true; - } - - @Override - protected void cleanup() { - Log.i(TAG, "cleanup()"); - if (mNativeInterface != null) { - mNativeInterface.cleanup(); - } - } - - @Override - protected boolean start() { - Log.i(TAG, "start()"); - if (sCCService != null) { - Log.w(TAG, "CCService is already running"); - return true; - } - if (DBG) { - Log.d(TAG, "Create CCService Instance"); - } - - mContext = this; - mAdapterService = Objects.requireNonNull(AdapterService.getAdapterService(), - "AdapterService cannot be null when CCService starts"); - mNativeInterface = Objects.requireNonNull(CCNativeInterface.getInstance(), - "CcNativeInterface cannot be null when CcService starts"); - // Step 2: Get maximum number of connected audio devices - mMaxConnectedAudioDevices = mAdapterService.getMaxConnectedAudioDevices(); - Log.i(TAG, "Max connected audio devices set to " + mMaxConnectedAudioDevices); - - if (mHandler != null) { - mHandler = null; - } - HandlerThread thread = new HandlerThread("BluetoothCCSHandler"); - thread.start(); - Looper looper = thread.getLooper(); - mHandler = new CcsMessageHandler(looper); - //APM's CallControl and CallAudio initialization - CallControl.init(mContext); - mCallAudio = CallAudio.init(mContext); - mNativeInterface.init(mMaxConnectedAudioDevices,InBandRingtoneSupport); - Log.d(TAG, "cc native init done"); - IntentFilter filter = new IntentFilter(); - //mSystemInterface = HeadsetService.getSystemInterfaceObj(); - filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); - mBondStateChangedReceiver = new BondStateChangedReceiver(); - mContext.registerReceiver(mBondStateChangedReceiver, filter); - mCallStateList = new HashMap<> (); - mPrevCallStateList = new HashMap<> (); - mLccWaitForResponseQ = new LinkedList<> (); - mLccTobeQueued = new LinkedList<> (); - mActiveDevMgrService = ActiveDeviceManagerService.get(); - setCCService(this); - return true; - } - - @Override - protected boolean stop() { - Log.i(TAG, "stop()"); - if (sCCService == null) { - Log.w(TAG, "stop() called before start()"); - return true; - } - // Step 8: Mark service as stopped - setCCService(null); - // Cleanup native interface - mNativeInterface.cleanup(); - mNativeInterface = null; - mContext.unregisterReceiver(mBondStateChangedReceiver); - // Clear AdapterService - mAdapterService = null; - mMaxConnectedAudioDevices = 1; - mCallOriginatedDevice = null; - CallControl.listenForPhoneState(PhoneStateListener.LISTEN_NONE); - return true; - } - - private static synchronized void setCCService(CCService instance) { - if (DBG) { - Log.d(TAG, "setCCService(): set to: " + instance); - } - sCCService = instance; - } - - public static synchronized CCService getCCService() { - if (sCCService == null) { - Log.w(TAG, "getCCService(): service is null"); - return null; - } - return sCCService; - } - - public boolean updateBearerProviderName(String name) { - Message msg = mHandler.obtainMessage(); - msg.what = UPDATE_BEARER_NAME; - msg.obj = name; - mHandler.sendMessage(msg); - return true; - } - public boolean updateBearerProviderTechnology (int tech_type) { - Message msg = mHandler.obtainMessage(); - msg.what = UPDATE_BEARER_TECH; - msg.arg1 = tech_type; - mHandler.sendMessage(msg); - return true; - } - - public boolean updateSignalStrength(int signal) { - Message msg = mHandler.obtainMessage(); - msg.what = UPDATE_SIGNAL_STRENGTH; - msg.arg1 = signal*CC_SIGNAL_STRENGTH_FACTOR; - mHandler.sendMessage(msg); - return true; - } - - public boolean updateSupportedBearerList(String supportedBearers) { - Message msg = mHandler.obtainMessage(); - msg.what = UPDATE_BEARERLIST_SUPPORTED ; - msg.obj = supportedBearers; - mHandler.sendMessage(msg); - return true; - } - - public void updateOriginateResult(BluetoothDevice device, int event, int res) { - if (mCallOriginatedDevice == null || device != mCallOriginatedDevice) { - Log.e(TAG, "Originate resp ignored, as there is no Orginate req"); - return; - } - if (res != 1) { - mCallOriginatedDevice = null; - updateCallControlResponse(CCHalConstants.BTCC_OP_ORIGINATE, - CCHalConstants.BTCC_DEF_INDEX_FOR_FAILURES, - CCHalConstants.BTCC_OP_NOT_POSSIBLE, device); - } - } - - public boolean updateContentControlID(int ccid) { - Message msg = mHandler.obtainMessage(); - msg.what = UPDATE_CONTENT_CONTROL_ID; - msg.arg1 = ccid; - mHandler.sendMessage(msg); - mCCId = ccid; - return true; - } - - public boolean updateStatusFlags(int statusFlags) { - Message msg = mHandler.obtainMessage(); - msg.what = UPDATE_STATUS_FLAGS; - msg.arg1 = statusFlags; - mHandler.sendMessage(msg); - return true; - } - - public boolean updateCallControlOptionalFeatures(int feature) { - Message msg = mHandler.obtainMessage(); - msg.what = UPDATE_CALL_CONTROL_OPCODES_SUPPORTED; - msg.arg1 = feature; - mHandler.sendMessage(msg); - return true; - } - - public boolean updateCallControlResponse(int op, int index, int status, BluetoothDevice device) { - Message msg = mHandler.obtainMessage(); - msg.what = UPDATE_CALL_CONTROL_RESPONSE ; - msg.arg1 = op; - msg.arg2 = index; - msg.obj = status; - mHandler.sendMessage(msg); - return true; - } - - private boolean updateIncomingCall(int index, String uri) { - Message msg = mHandler.obtainMessage(); - msg.what = UPDATE_INCOMING_CALL ; - msg.arg1 = index; - msg.obj = uri; - mHandler.sendMessage(msg); - return true; - } - - boolean isVirtualCallStarted() { - - return mVirtualCallStarted; - } - - public void setVirtualCallActive(boolean state) { - Log.i(TAG, "setVirtualCallActive: " + state); - if (state == true) { - startScoUsingVirtualVoiceCall(); - } else { - stopScoUsingVirtualVoiceCall(); - } - } - - private void disaptchFakeCallState (CallControlState state) { - if (state != null) { - mCallStateList.put(state.mIndex, state); - } - Message msg = mHandler.obtainMessage(); - msg.what = PROCESS_CALL_STATE; - Collection values = mCallStateList.values(); - ArrayList listOfValues = new ArrayList<>(values); - msg.obj = listOfValues; - mHandler.sendMessage(msg); - } - - boolean startScoUsingVirtualVoiceCall() { - - Log.i(TAG, "startScoUsingVirtualVoiceCall: " + Utils.getUidPidString()); - mVirtualCallStarted = true; - // Send fake call states to mimic outgoing calls - - mCallStateList.clear(); - CallControlState alertingState = new CallControlState(1,CCHalConstants.CALL_STATE_ALERTING,FLAGS_DIRECTION_BIT); - disaptchFakeCallState(alertingState); - CallControlState activeState = new CallControlState(1,CCHalConstants.CALL_STATE_ACTIVE,FLAGS_DIRECTION_BIT); - disaptchFakeCallState(activeState); - return true; - } - - boolean stopScoUsingVirtualVoiceCall() { - - Log.i(TAG, "stopScoUsingVirtualVoiceCall: " + Utils.getUidPidString()); - // 1. Check if virtual call has already started - if (!mVirtualCallStarted) { - Log.w(TAG, "stopScoUsingVirtualVoiceCall: virtual call not started"); - return false; - } - mVirtualCallStarted = false; - // 2. Send fake call states to mimic it ias outgoing calls - - mCallStateList.clear(); - CallControlState disConnectedState = new CallControlState(1,CCHalConstants.CCS_STATE_DISCONNECTED,FLAGS_DIRECTION_BIT); - disaptchFakeCallState(disConnectedState); - return true; - } - - private void updateCallState(ArrayList listOfValues) { - Log.d(TAG, "updateCallState"); - Message msg = mHandler.obtainMessage(); - msg.what = UPDATE_CALL_STATE; - msg.obj = listOfValues; - mHandler.sendMessage(msg); - } - - public void processAndUpdateCallState(ArrayList listOfValues) { - int flags = 0; - - for (CallControlState state : listOfValues) { - Log.i(TAG, "processAndUpdateCallState: direction" + state.mDirection); - if (state.mDirection == 1) { - //Incoming call: off the direction bit - flags = (flags & (~FLAGS_DIRECTION_BIT)); - } else { - //Outgoing call: on the direction bit - flags = (flags | FLAGS_DIRECTION_BIT); - } - state.mFlags = flags; - String uri = ""; - String uri_str = "tel:"; - Log.i(TAG, "processAndUpdateCallState: index = " + state.mIndex); - if (state.mState == CCHalConstants.CALL_STATE_ACTIVE) { - mLatestActiveCallIndex = state.mIndex; - } else if (state.mState == CCHalConstants.CALL_STATE_HELD) { - mLatestHeldCallIndex = state.mIndex; - } - if (state.mState == CCHalConstants.CALL_STATE_INCOMING) { - if (state.mNumber != null) { - uri = uri_str.concat(state.mNumber); - } - Log.i(TAG, "processAndUpdateCallState: inc uri = " + uri); - updateIncomingCall(state.mIndex, uri); - } - } - updateCallState(listOfValues); - } - - private void compareAndUpdateWithPrevCallList (HashMap currentCallStateList) { - Log.d(TAG, "compareAndUpdateWithPrevCallList"); - for (Integer key: mPrevCallStateList.keySet()) { - if (currentCallStateList.containsKey(key) == false) { - //create a fake disconnected for that index - if (mPrevCallStateList.get(key).mState != CCHalConstants.CALL_STATE_DISCONNECTED) { - Log.d(TAG, "inserting DISC state fake!"); - CallControlState fakeDiscForDisappeared = - new CallControlState(key,CCHalConstants.CALL_STATE_DISCONNECTED, mPrevCallStateList.get(key).mFlags); - mCallStateList.put(key, fakeDiscForDisappeared); - } - } - } - mPrevCallStateList.putAll(mCallStateList); - } - - public void clccResponse(int index, int direction, int call_status, int mode, boolean mpty, - String number, int type) { - Log.d(TAG, "clccResponse"); - if (index != 0) { - CallControlState state = new CallControlState(index, direction, call_status, number); - mCallStateList.put(index, state); - } else { - //update the call state to stack as 0 indicates end of call list - compareAndUpdateWithPrevCallList(mCallStateList); - Message msg = mHandler.obtainMessage(); - msg.what = PROCESS_CALL_STATE; - Collection values = mCallStateList.values(); - ArrayList listOfValues = new ArrayList<>(values); - msg.obj = listOfValues; - mHandler.sendMessage(msg); - if (!mLccWaitForResponseQ.isEmpty()) { - mLccWaitForResponseQ.remove(); - } - if (!mLccTobeQueued.isEmpty()) { - mLccTobeQueued.remove(); - getBlcc(); - } - } - } - - private void getBlcc() { - Log.d(TAG, "getBlcc"); - if (mLccTobeQueued.isEmpty()) { - if (CallControl.listCurrentCalls() == true) { - mLccWaitForResponseQ.add(1); - Log.d(TAG, "getBlcc: successfully sent"); - //telephony should always respond with clccresponse - mCallStateList.clear(); - } - } else { - mLccTobeQueued.add(1); - } - } - - private boolean processCallStateChange(CallControlState state) { - Message msg = mHandler.obtainMessage(); - msg.what = PROCESS_PHONE_STATE_CHANGED; - msg.obj = state; - mHandler.sendMessage(msg); - return true; - } - - boolean isInbandRingingEnabled() { - boolean returnVal; - - returnVal = BluetoothHeadset.isInbandRingingSupported(this) && !SystemProperties.getBoolean( - DISABLE_INBAND_RINGING_PROPERTY, true); - Log.d(TAG, "isInbandRingingEnabled returning: " + returnVal); - return returnVal; - } - - boolean isCallAudioNeeded(CallControlState state) { - boolean ret = false; - if (isInbandRingingEnabled() && state.mState == CCHalConstants.CALL_STATE_INCOMING) { - ret = true; - } else if (mCallAudio != null && mCallAudio.isAudioOn() == false && - (state.mState == CCHalConstants.CALL_STATE_ALERTING || - mPrevTelephonyState != null && mPrevTelephonyState.mNumActive == 0 && - state.mNumActive == 1)) { - - ret = true; - } - return ret; - } - - public boolean phoneStateChanged(int numActive, int numHeld, int callState, String number, int type, - String name, boolean isVirtualCall) { - Log.d(TAG, "phoneStateChanged: " + - "callState: " + callState + - "number:" + number + - "numActive:" + numActive + - "isVirtualCall:" + isVirtualCall); - CallControlState currentTelephonyState = new CallControlState(numActive, numHeld,callState, number, type, name); - - if (isCallAudioNeeded(currentTelephonyState)) { - if (mCallAudio != null) { - mCallAudio.connectAudio(); - } else { - Log.e(TAG, "no CallAudio handle"); - } - } - - if (mPrevTelephonyState != null && mPrevTelephonyState.mNumActive == 1 - && currentTelephonyState.mNumActive == 0 && currentTelephonyState.mNumHeld == 0) { - if (mPrevTelephonyState.mNumHeld == 0 && currentTelephonyState.mNumHeld == 1) { - Log.d(TAG, "special case where Active call moved to HOLD"); - } else { - if (mCallAudio != null) { - mCallAudio.disconnectAudio(); - } else { - Log.e(TAG, "no CallAudio handle for disc Call handling"); - } - } - } - - if (callState == CCHalConstants.CALL_STATE_DIALING) { - //ignore this as it is fake Telephony event - return true; - } - - // Should stop all other audio mode in this case - if ((numActive + numHeld) > 0 || callState != CCHalConstants.CALL_STATE_IDLE) { - if (!isVirtualCall && mVirtualCallStarted) { - // stop virtual voice call if there is an incoming Telecom call update - stopScoUsingVirtualVoiceCall(); - } - processCallStateChange(currentTelephonyState); - mPrevTelephonyState = currentTelephonyState; - } else { - // ignore CS non-call state update when virtual call started - if (!isVirtualCall && mVirtualCallStarted) { - Log.i(TAG, "Ignore CS non-call state update"); - return true; - } - } - return true; - } - - public BluetoothDevice getActiveDevice() { - return mActiveDevice; - } - - public int getContentControlID() { - return mCCId; - } - - public boolean setActiveDevice(BluetoothDevice device) { - Message msg = mHandler.obtainMessage(); - msg.what = ACTIVE_DEVICE_CHANGED; - msg.obj = device; - mHandler.sendMessage(msg); - return true; - } - - private boolean setActiveDeviceRemoteTrigger(BluetoothDevice device) { - boolean ret = false; - if (mActiveDevMgrService != null) { - ret = mActiveDevMgrService.setActiveDeviceBlocking(device, ApmConst.AudioFeatures.CALL_AUDIO); - } - Log.d(TAG, "setActiveDevice returns" + ret); - return ret; - } - - private boolean isActiveDevice(BluetoothDevice device) { - boolean ret = false; - if (mActiveDevMgrService != null) { - ret = (device == mActiveDevMgrService.getActiveDevice(ApmConst.AudioFeatures.CALL_AUDIO)); - } - Log.d(TAG, "isActiveDevice returns" + ret); - return ret; - } - - public boolean onCallControlPointChangedRequest(int op, int[] call_indices, int count, String dialNumber, BluetoothDevice device ) { - Log.d(TAG, " onCallControlPointChangedRequest opcode : " + CCHalConstants.operationToString(op)) ; - switch(op) { - case CCHalConstants.BTCC_OP_ACCEPT: { - setActiveDeviceRemoteTrigger (device); - CallControl.answerCall(device); - break; - } - case CCHalConstants.BTCC_OP_TERMINATE: { - int callIndex = call_indices[0]; - Log.d(TAG, "callIndex: " + callIndex); - CallControl.terminateCall(device, callIndex); - break; - } - case CCHalConstants.BTCC_OP_LOCAL_HLD:{ - int callIndex = call_indices[0]; - int res; - int idx = CCHalConstants.BTCC_DEF_INDEX_FOR_FAILURES; - Log.d(TAG, "callIndex: " + callIndex); - if (CallControl.holdCall(device, callIndex) == true) { - res = CCHalConstants.BTCC_OP_SUCCESS; - idx = callIndex; - } else { - res = CCHalConstants.BTCC_OP_NOT_POSSIBLE; - idx = CCHalConstants.BTCC_DEF_INDEX_FOR_FAILURES; - } - updateCallControlResponse(op, idx, res, device); - break; - } - case CCHalConstants.BTCC_OP_LOCAL_RETRIEVE: { - //Analogus to SWAP as stack would have - //already validated the input index is in HELD state - int chld = 2; - int res; - int idx = CCHalConstants.BTCC_DEF_INDEX_FOR_FAILURES; - if (CallControl.processChld(device, chld) == true) { - res = CCHalConstants.BTCC_OP_SUCCESS; - idx = call_indices[0]; - } else { - res = CCHalConstants.BTCC_OP_NOT_POSSIBLE; - idx = CCHalConstants.BTCC_DEF_INDEX_FOR_FAILURES; - } - updateCallControlResponse(op, idx, res, device); - break; - } - case CCHalConstants.BTCC_OP_ORIGINATE: { - Log.d(TAG, "Orignate: from Device: " + device + "dialString: " + dialNumber); - if (dialNumber == null) { - Log.e(TAG, "null dial string"); - break; - } - if (mCallOriginatedDevice != null) { - Log.d(TAG, "Originate is pending from device: " + mCallOriginatedDevice); - updateCallControlResponse(op, CCHalConstants.BTCC_DEF_INDEX_FOR_FAILURES, - CCHalConstants.BTCC_OP_NOT_POSSIBLE, device); - break; - } else { - setActiveDeviceRemoteTrigger (device); - String[] result = dialNumber.split(":"); - if (CallControl.dialOutgoingCall(device, result[1]) == true) { - mCallOriginatedDevice = device; - } else { - updateCallControlResponse(op, CCHalConstants.BTCC_DEF_INDEX_FOR_FAILURES, - CCHalConstants.BTCC_OP_NOT_POSSIBLE, device); - } - } - break; - } - case CCHalConstants.BTCC_OP_JOIN: { - //Stack would have validate to ensure the input indicies - //are valid candidates for JOIN op - int chld = 3; - int res; - int idx = CCHalConstants.BTCC_DEF_INDEX_FOR_FAILURES; - if (CallControl.processChld(device, chld) == true) { - res = CCHalConstants.BTCC_OP_SUCCESS; - idx = call_indices[0]; - } else { - res = CCHalConstants.BTCC_OP_NOT_POSSIBLE; - idx = CCHalConstants.BTCC_DEF_INDEX_FOR_FAILURES; - } - updateCallControlResponse(op, idx, res, device); - break; - } - } - return true; - } - - public void onCallControlInitialized(int status) { - Log.v(TAG, "CallControlInitializedCallback: status=" + status); - if (status == 0) { - //Initialize Telephony and APM related Initialization - CallControl.listenForPhoneState(PhoneStateListener.LISTEN_SERVICE_STATE|PhoneStateListener.LISTEN_SERVICE_STATE); - updateContentControlID(CC_CONTENT_CONTROL_ID); - updateSupportedBearerList("tel"); - updateCallControlOptionalFeatures(CALL_CONTROL_OPTIONAL_FEATURES); - } - } - - - public void onConnectionStateChanged(BluetoothDevice device, int status) { - Log.v(TAG, "onConnectionStateChanged: address=" + device.toString()); - } - - private class BondStateChangedReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - if (!BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())) { - return; - } - int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, - BluetoothDevice.ERROR); - BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - Objects.requireNonNull(device, "ACTION_BOND_STATE_CHANGED with no EXTRA_DEVICE"); - bondStateChanged(device, state); - } - } - - void bondStateChanged(BluetoothDevice device, int bondState) { - if (DBG) { - 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) { - return; - } - - } - - private boolean callListContainsDialingCall(ArrayList listOfValues) { - boolean ret = false; - for (CallControlState state : listOfValues) { - if (state.mState == CCHalConstants.CALL_STATE_DIALING - || state.mState == CCHalConstants.CALL_STATE_ALERTING) { - ret = true; - break; - } - } - return ret; - } - - /** Handles CCS messages. */ - private final class CcsMessageHandler extends Handler { - private CcsMessageHandler(Looper looper) { - super(looper); - } - @Override - public void handleMessage(Message msg) { - if (DBG) Log.v(TAG, "CcsMessageHandler: received message=" + messageWhatToString(msg.what)); - ArrayList listOfValues = null; - switch (msg.what) { - case UPDATE_BEARER_NAME: - String bName = (String)msg.obj; - mNativeInterface.updateBearerProviderName(bName); - break; - case UPDATE_BEARER_TECH: - int tech_type = (int)msg.arg1; - mNativeInterface.updateBearerTechnology(tech_type); - break; - case UPDATE_SIGNAL_STRENGTH: - int signal = (int)msg.arg1; - mNativeInterface.updateSignalStrength(signal); - break; - case UPDATE_STATUS_FLAGS: - int statusFlags = (int)msg.arg1; - mNativeInterface.updateStatusFlags(statusFlags); - break; - case UPDATE_BEARERLIST_SUPPORTED : - String bSList = (String)msg.obj; - mNativeInterface.updateSupportedBearerList(bSList); - break; - case UPDATE_CONTENT_CONTROL_ID: - int ccid = (int)msg.arg1; - mNativeInterface.contentControlId(ccid); - break; - case UPDATE_CALL_STATE: - listOfValues = (ArrayList)msg.obj; - Log.d(TAG, "Call list size : " + listOfValues.size()); - boolean status = mNativeInterface.callState(listOfValues); - if (mCallOriginatedDevice != null && callListContainsDialingCall(listOfValues)) { - Log.e(TAG, "push the pending Originate response"); - //Stack will pick the right index - updateCallControlResponse(CCHalConstants.BTCC_OP_ORIGINATE, - CCHalConstants.BTCC_DEF_INDEX_FOR_FAILURES, - CCHalConstants.BTCC_OP_SUCCESS, mCallOriginatedDevice); - mCallOriginatedDevice = null; - } - break; - case UPDATE_CALL_CONTROL_OPCODES_SUPPORTED : - int feature = (int)msg.arg1; - mNativeInterface.callControlOptionalFeatures(feature); - break; - case UPDATE_CALL_CONTROL_RESPONSE : - int op = (int)msg.arg1; - int ind = (int)msg.arg2; - int st = (int)msg.obj; - mNativeInterface.callControlResponse(op, ind, st, null); - break; - case UPDATE_INCOMING_CALL : - int index = (int)msg.arg1; - String uri = (String)msg.obj; - mNativeInterface.updateIncomingCall(index, uri); - break; - case PROCESS_PHONE_STATE_CHANGED: - getBlcc(); - break; - case PROCESS_CALL_STATE: - listOfValues = (ArrayList)msg.obj; - processAndUpdateCallState(listOfValues); - break; - case ACTIVE_DEVICE_CHANGED: - BluetoothDevice device = (BluetoothDevice)msg.obj; - mNativeInterface.setActiveDevice(device,-1); - break; - case EVENT_TYPE_CONNECTION_STATE_CHANGED: - break; - default: - Log.e(TAG, "unknown message! msg.what=" + messageWhatToString(msg.what)); - break; - } - Log.v(TAG, "Exit handleMessage"); - } -} - - public static String messageWhatToString(int what) { - switch (what) { - case UPDATE_BEARER_NAME : - return "UPDATE_BEARER_NAME"; - case UPDATE_BEARER_TECH : - return "UPDATE_BEARER_TECH"; - case UPDATE_SIGNAL_STRENGTH : - return "UPDATE_SIGNAL_STRENGTH"; - case UPDATE_BEARERLIST_SUPPORTED : - return "UPDATE_BEARERLIST_SUPPORTED"; - case UPDATE_CONTENT_CONTROL_ID : - return "UPDATE_CONTENT_CONTROL_ID"; - case UPDATE_CALL_STATE : - return "UPDATE_CALL_STATE"; - case UPDATE_CALL_CONTROL_OPCODES_SUPPORTED : - return "UPDATE_CALL_CONTROL_OPCODES_SUPPORTED "; - case UPDATE_CALL_CONTROL_RESPONSE : - return "UPDATE_CALL_CONTROL_RESPONSE"; - case UPDATE_INCOMING_CALL : - return "UPDATE_INCOMING_CALL"; - case PROCESS_CALL_STATE : - return "PROCESS_CALL_STATE"; - case UPDATE_STATUS_FLAGS: - return "UPDATE_STATUS_FLAGS"; - default: - break; - } - return Integer.toString(what); - } - - /** - * Binder object: must be a static class or memory leak may occur. - */ - - static class CcBinder extends Binder implements IProfileServiceBinder { - private CCService mService; - - private CCService getService() { - if (!Utils.checkCallerIsSystemOrActiveUser(TAG)) { - return null; - } - - if (mService != null && mService.isAvailable()) { - return mService; - } - return null; - } - - CcBinder(CCService svc) { - mService = svc; - } - - @Override - public void cleanup() { - mService = null; - } - } -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/cc/CallControlState.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/cc/CallControlState.java deleted file mode 100644 index 2feb65a971a5f683b6b64c1ed1bbb57adce5f5ec..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/cc/CallControlState.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - *Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. - */ -/* - * Copyright 2012 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.cc; - -import java.util.Objects; -import java.util.Arrays; - -/** - * A blob of data representing an overall call state on the phone - */ -class CallControlState { - - int mIndex; - /** - * Number of active calls - */ - int mNumActive; - /** - * Number of held calls - */ - int mNumHeld; - /** - * Current call setup state - */ - int mState; - /** - * Currently active call's phone number - */ - String mNumber; - /** - * Phone number type - */ - int mType; - - /** - * flags to define direction, information witheld by network or server. - */ - int mFlags; - - /** - * Caller display name - */ - String mName; - - int mDirection; - - CallControlState(int numActive, int numHeld, int callState, String number, int type, - String name) { - mNumActive = numActive; - mNumHeld = numHeld; - mState = callState; - mNumber = number; - mType = type; - mName = name; - } - CallControlState(int index, int callState, int flags) { - mIndex = index; - mState = callState; - mFlags = flags; - } - CallControlState(int index, int direction, int callState, String number) { - mIndex = index; - mDirection = direction; - mState = callState; - mNumber = number; - } - -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/groupclient/GroupAppMap.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/groupclient/GroupAppMap.java deleted file mode 100644 index 13375e49f816f381997dfe106716a406a01a7318..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/groupclient/GroupAppMap.java +++ /dev/null @@ -1,178 +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. - * - ******************************************************************************/ - -package com.android.bluetooth.groupclient; - -import android.bluetooth.IBluetoothGroupCallback; -import android.bluetooth.BluetoothGroupCallback; - -import android.os.Binder; -import android.os.IBinder; -import android.os.IInterface; -import android.os.RemoteException; -import android.util.Log; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Collections; -import java.util.concurrent.ConcurrentHashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; -import java.util.UUID; - -/* This class keeps track of registered GroupClient applications and - * managing callbacks to be given to appropriate app or module */ - -public class GroupAppMap { - - private static final String TAG = "BluetoothGroupAppMap"; - - class GroupClientApp { - /* The UUID of the application */ - public UUID uuid; - - /* The id of the application */ - public int appId; - - /* flag to determine if Bluetooth module has registered. */ - public boolean isLocal; - - /* Callbacks to be given to application */ - public IBluetoothGroupCallback appCb; - - /* Callbacks to be given to registered Bluetooth modules*/ - public BluetoothGroupCallback mCallback; - - public boolean isRegistered; - - /** Death receipient */ - private IBinder.DeathRecipient mDeathRecipient; - - GroupClientApp(UUID uuid, boolean isLocal, IBluetoothGroupCallback appCb, - BluetoothGroupCallback localCallbacks) { - this.uuid = uuid; - this.isLocal = isLocal; - this.appCb = appCb; - this.mCallback = localCallbacks; - this.isRegistered = true; - appUuids.add(uuid); - } - - /** - * To link death recipient - */ - void linkToDeath(IBinder.DeathRecipient deathRecipient) { - try { - IBinder binder = ((IInterface) appCb).asBinder(); - binder.linkToDeath(deathRecipient, 0); - mDeathRecipient = deathRecipient; - } catch (RemoteException e) { - Log.e(TAG, "Unable to link deathRecipient for appId: " + appId); - } - } - - } - - List mApps = Collections.synchronizedList(new ArrayList()); - - ArrayList appUuids = new ArrayList(); - - /** - * Add an entry to the application list. - */ - GroupClientApp add(UUID uuid, boolean isLocal, IBluetoothGroupCallback appCb, - BluetoothGroupCallback localCallback) { - synchronized (mApps) { - GroupClientApp app = new GroupClientApp(uuid, isLocal, appCb, localCallback); - mApps.add(app); - return app; - } - } - - /** - * Remove the entry for a given UUID - */ - void remove(UUID uuid) { - synchronized (mApps) { - Iterator i = mApps.iterator(); - while (i.hasNext()) { - GroupClientApp entry = i.next(); - if (entry.uuid.equals(uuid)) { - entry.isRegistered = false; - i.remove(); - break; - } - } - } - } - - /** - * Remove the entry for a given application ID. - */ - void remove(int appId) { - synchronized (mApps) { - Iterator i = mApps.iterator(); - while (i.hasNext()) { - GroupClientApp entry = i.next(); - if (entry.appId == appId) { - entry.isRegistered = false; - i.remove(); - break; - } - } - } - } - - /** - * Get GroupClient application by UUID. - */ - GroupClientApp getByUuid(UUID uuid) { - synchronized (mApps) { - Iterator i = mApps.iterator(); - while (i.hasNext()) { - GroupClientApp entry = i.next(); - if (entry.uuid.equals(uuid)) { - return entry; - } - } - } - Log.e(TAG, "App not found for UUID " + uuid); - return null; - } - - /** - * Get a GroupClient application by appId. - */ - GroupClientApp getById(int appId) { - synchronized (mApps) { - Iterator i = mApps.iterator(); - while (i.hasNext()) { - GroupClientApp entry = i.next(); - if (entry.appId == appId) { - return entry; - } - } - } - Log.e(TAG, "GroupClient App not found for appId " + appId); - return null; - } -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/groupclient/GroupClientNativeInterface.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/groupclient/GroupClientNativeInterface.java deleted file mode 100644 index ce1076f480a4c362a80402310cc637dff794b19e..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/groupclient/GroupClientNativeInterface.java +++ /dev/null @@ -1,251 +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. - * - ******************************************************************************/ - -package com.android.bluetooth.groupclient; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import java.util.ArrayList; -import java.util.List; -import android.util.Log; -import java.util.UUID; - -import com.android.bluetooth.Utils; -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; - -/** - * CSIP Client Native Interface to/from JNI. - */ -public class GroupClientNativeInterface { - private static final String TAG = "BluetoothGroupNativeIntf"; - private static final boolean DBG = true; - private BluetoothAdapter mAdapter; - - @GuardedBy("INSTANCE_LOCK") - private static GroupClientNativeInterface sInstance; - private static final Object INSTANCE_LOCK = new Object(); - - static { - classInitNative(); - } - - private GroupClientNativeInterface() { - mAdapter = BluetoothAdapter.getDefaultAdapter(); - if (mAdapter == null) { - Log.wtfStack(TAG, "No Bluetooth Adapter Available"); - } - } - - /** - * Get singleton instance. - */ - public static GroupClientNativeInterface getInstance() { - synchronized (INSTANCE_LOCK) { - if (sInstance == null) { - sInstance = new GroupClientNativeInterface(); - } - return sInstance; - } - } - - /** - * Initializes the native interface. - * - * priorities to configure. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void init() { - initNative(); - } - - /** - * Cleanup the native interface. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void cleanup() { - cleanupNative(); - } - - /** - * Register CSIP app with the stack code. - * - * @param appUuidLsb lsb of app uuid. - * @param appUuidMsb msb of app uuid. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void registerCsipApp(long appUuidLsb, long appUuidMsb) { - registerCsipAppNative(appUuidLsb, appUuidMsb); - } - - /** - * Register CSIP app with the stack code. - * - * @param appId ID of the application to be unregistered. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void unregisterCsipApp(int appId) { - unregisterCsipAppNative(appId); - } - - /** - * Change lock value of the coordinated set member - * - * @param appId ID of the application which is requesting change in lock status - * @param setId Identifier of the set - * @param devices List of bluetooth devices for whick lock status change is required - * @param value Lock/Unlock value - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void setLockValue(int appId, int setId, List devices, - int value) { - int i = 0; - int size = ((devices != null) ? devices.size() : 0); - String[] devicesList = new String[size]; - if (size > 0) { - for (BluetoothDevice device: devices) { - devicesList[i++] = device.toString(); - } - } - setLockValueNative(appId, setId, value, devicesList); - } - - /** - * Initiates Csip connection to a remote device. - * - * @param device the remote device - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean connectSetDevice(int appId, BluetoothDevice device) { - return connectSetDeviceNative(appId, getByteAddress(device)); - } - - /** - * Disconnects Csip from a remote device. - * - * @param device the remote device - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean disconnectSetDevice(int appId, BluetoothDevice device) { - return disconnectSetDeviceNative(appId, getByteAddress(device)); - } - - - 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 onCsipAppRegistered (int status, int appId, - long uuidLsb, long uuidMsb) { - UUID uuid = new UUID(uuidMsb, uuidLsb); - - GroupService service = GroupService.getGroupService(); - if (service != null) { - service.onCsipAppRegistered(status, appId, uuid); - } - } - - private void onConnectionStateChanged(int appId, String bdAddr, - int state, int status) { - BluetoothDevice device = BluetoothAdapter.getDefaultAdapter() - .getRemoteDevice(bdAddr); - - GroupService service = GroupService.getGroupService(); - if (service != null) { - service.onConnectionStateChanged (appId, device, state, status); - } - } - - private void onNewSetFound (int setId, String bdAddr, int size, byte[] sirk, - long uuidLsb, long uuidMsb, boolean lockSupport) { - UUID uuid = new UUID(uuidMsb, uuidLsb); - BluetoothDevice device = BluetoothAdapter.getDefaultAdapter() - .getRemoteDevice(bdAddr); - - GroupService service = GroupService.getGroupService(); - if (service != null) { - service.onNewSetFound(setId, device, size, sirk, uuid, lockSupport); - } - } - - private void onNewSetMemberFound (int setId, String bdAddr) { - BluetoothDevice device = - BluetoothAdapter.getDefaultAdapter().getRemoteDevice(bdAddr); - - GroupService service = GroupService.getGroupService(); - if (service != null) { - service.onNewSetMemberFound(setId, device); - } - } - - private void onLockStatusChanged (int appId, int setId, int value, - int status, String[] bdAddr) { - List lockMembers = new ArrayList(); - for (String address: bdAddr) { - lockMembers.add(mAdapter.getRemoteDevice(address.toUpperCase())); - } - - GroupService service = GroupService.getGroupService(); - if (service != null) { - service.onLockStatusChanged(appId, setId, value, status, lockMembers); - } - } - - private void onLockAvailable (int appId, int setId, String address) { - BluetoothDevice device = mAdapter.getRemoteDevice(address); - GroupService service = GroupService.getGroupService(); - if (service != null) { - service.onLockAvailable(appId, setId, device); - } - } - - private void onSetSizeChanged (int setId, int size, String address) { - BluetoothDevice device = mAdapter.getRemoteDevice(address); - GroupService service = GroupService.getGroupService(); - if (service != null) { - service.onSetSizeChanged(setId, size, device); - } - } - - private void onSetSirkChanged(int setId, byte[] sirk, String address) { - BluetoothDevice device = mAdapter.getRemoteDevice(address); - GroupService service = GroupService.getGroupService(); - if (service != null) { - service.onSetSirkChanged(setId, sirk, device); - } - } - - // Native methods that call JNI interface - private static native void classInitNative(); - private native void initNative(); - private native void cleanupNative(); - private native void registerCsipAppNative(long appUuidLsb, long appUuidMsb); - private native void unregisterCsipAppNative(int appId); - private native void setLockValueNative(int appId, int setId, int value, String[] devicesList); - private native boolean connectSetDeviceNative(int appId, byte[] address); - private native boolean disconnectSetDeviceNative(int appId, byte[] address); -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/groupclient/GroupScanner.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/groupclient/GroupScanner.java deleted file mode 100644 index bc192b2f3cf2448bf439354b255c784942b30078..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/groupclient/GroupScanner.java +++ /dev/null @@ -1,529 +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. - * - ******************************************************************************/ - - -package com.android.bluetooth.groupclient; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDeviceGroup; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothUuid; -import android.bluetooth.le.BluetoothLeScanner; -import android.bluetooth.le.ScanCallback; -import android.bluetooth.le.ScanFilter; -import android.bluetooth.le.ScanRecord; -import android.bluetooth.le.ScanResult; -import android.bluetooth.le.ScanSettings; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; - -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; -import android.os.ParcelUuid; -import android.os.SystemProperties; - -import android.util.Log; - -import com.android.bluetooth.btservice.AdapterService; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.HashSet; -import java.util.List; -import java.util.UUID; - -import javax.crypto.Cipher; -import javax.crypto.spec.SecretKeySpec; -import javax.crypto.spec.IvParameterSpec; - -/** - * Class that handles Bluetooth LE Scan results for Set member discovery. - * It performs scan result resolution for set identification. - * - * @hide - */ -public class GroupScanner { - private static final boolean DBG = true; - private static final boolean VDBG = GroupService.VDBG; - private static final String TAG = "BluetoothGroupScanner"; - - // messages for handling filtered PSRI Scan results - private static final int MSG_HANDLE_LE_SCAN_RESULT = 0; - - // message for starting coordinated set discovery - private static final int MSG_START_SET_DISCOVERY = 1; - - // message to stop coordinated set discovery - private static final int MSG_STOP_SET_DISCOVERY = 2; - - // message when set member discovery timeout happens - private static final int MSG_SET_MEMBER_DISC_TIMEOUT = 3; - - // message to handle PSRI from EIR packet - private static final int MSG_HANDLE_EIR_RESPONSE = 4; - - // PSRI Service AD Type - private final ParcelUuid PSRI_SERVICE_ADTYPE_UUID - = BluetoothUuid.parseUuidFrom(new byte[]{0x2E, 0x00}); - - private static final int PSRI_LEN = 6; - private static final int PSRI_SPLIT_LEN = 3; // 24 bits - private static final int AES_128_IO_LEN = 16; - - // Set Member Discovery timeout - private static final int SET_MEMBER_DISCOVERY_TIMEOUT = 10000; // 10 sec - - private BluetoothAdapter mBluetoothAdapter; - private BluetoothDevice mCurrentDevice; - private BluetoothLeScanner mScanner; - private GroupService mGroupService; - private volatile CsipHandler mHandler; - private Handler mainHandler; - private boolean mScanResolution; - private int mDiscoveryStoppedReason; - private CsipLeScanCallback mCsipScanCallback; - - // parameters for set discovery - private int mSetId; - private byte[] mSirk; - private int mTransport; - private int mSetSize; - private int mTotalDiscovered; - - private int mScanType = 1; - - // filter out duplicate scans - ArrayList scannedDevices = new ArrayList(); - - GroupScanner(GroupService service) { - mGroupService = service; - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - - // register receiver for Bluetooth State change - IntentFilter filter = new IntentFilter(); - filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); - mGroupService.registerReceiver(mReceiver, filter); - - mainHandler = new Handler(mGroupService.getMainLooper()); - HandlerThread thread = new HandlerThread("CsipScanHandlerThread"); - thread.start(); - mHandler = new CsipHandler(thread.getLooper()); - mCsipScanCallback = new CsipLeScanCallback(); - ScanRecord.DATA_TYPE_GROUP_AD_TYPE = 0x2E; - /* Testing: Property used for deciding scan and filter type. To be removed */ - mScanType = SystemProperties.getInt( - "persist.vendor.service.bt.csip.scantype", 1); - } - - // Handler for CSIP scan operations and set member resolution. - private class CsipHandler extends Handler { - CsipHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - if (VDBG) Log.v(TAG, "msg.what = " + msg.what); - - switch (msg.what) { - case MSG_HANDLE_LE_SCAN_RESULT: - // start processing scan result - int callBackType = msg.arg1; - ScanResult result = (ScanResult) msg.obj; - mCurrentDevice = result.getDevice(); - - /* In case of DUMO device if advertisement is coming from other RPA */ - if (mCurrentDevice.getBondState() == BluetoothDevice.BOND_BONDED) { - return; - } - - // skip scanresult if already processed for this device - if (scannedDevices.contains(mCurrentDevice)) { - if (VDBG) { - Log.w(TAG, "duplicate scanned result or Device" - + mCurrentDevice + " Group info already resolved. Ignore"); - } - return; - } - - scannedDevices.add(mCurrentDevice); - ScanRecord record = result.getScanRecord(); - - // get required service data with PSRI AD Type - byte[] srvcData = null; - /* for debugging purpose */ - if (mScanType == 2) { - srvcData = record.getServiceData(PSRI_SERVICE_ADTYPE_UUID); - } else { - srvcData = record.getGroupIdentifierData(); - } - if (srvcData == null || srvcData.length != PSRI_LEN) { - Log.e(TAG, "Group info with incorrect length found " - + "in advertisement of " + mCurrentDevice); - return; - } - - startPsriResolution(srvcData); - break; - - case MSG_HANDLE_EIR_RESPONSE: - EirData eirData = (EirData)msg.obj; - mCurrentDevice = eirData.curDevice; - byte[] eirGroupData = eirData.groupData; - - // skip eir if already processed for this device - if (scannedDevices.contains(mCurrentDevice)) { - if (VDBG) { - Log.w(TAG, "duplicate eir or Device" - + mCurrentDevice + " PSRI already resolved. Ignore"); - } - return; - } - - scannedDevices.add(mCurrentDevice); - if (eirGroupData == null || eirGroupData.length != PSRI_LEN) { - Log.e(TAG, "PSRI data with incorrect length found " - + "in EIR of " + mCurrentDevice); - return; - } - startPsriResolution(eirGroupData); - break; - - // High priority msg received in front of the message queue - case MSG_SET_MEMBER_DISC_TIMEOUT: - mDiscoveryStoppedReason = BluetoothDeviceGroup.DISCOVERY_STOPPED_BY_TIMEOUT; - case MSG_STOP_SET_DISCOVERY: - handleStopSetDiscovery(); - break; - - // High priority msg received in front of the message queue - case MSG_START_SET_DISCOVERY: - handleStartSetDiscovery(); - break; - - default: - Log.e(TAG, "Unknown message : " + msg.what); - } - } - } - - /* BroadcastReceiver for BT ON State intent for registering BLE Scanner */ - private final BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action == null) { - Log.e(TAG, "Received intent with null action"); - return; - } - - switch (action) { - case BluetoothAdapter.ACTION_STATE_CHANGED: - mScanner = mBluetoothAdapter.getBluetoothLeScanner(); - break; - } - - } - }; - - /* Scan results callback */ - private class CsipLeScanCallback extends ScanCallback { - @Override - public void onScanResult(int callBackType, ScanResult result) { - if (VDBG) Log.v(TAG, "onScanResult callBackType : " + callBackType); - if (mHandler != null && mScanResolution) { - mHandler.sendMessage(mHandler.obtainMessage(MSG_HANDLE_LE_SCAN_RESULT, - callBackType, 0, result)); - } else { - if (VDBG) Log.e(TAG, "onScanResult mHandler is null" + - " or Scan Resolution is stopped"); - } - } - - public void onScanFailed(int errorCode) { - mScanResolution = false; - Log.e(TAG, "Scan failed. Error code: " + new Integer(errorCode).toString()); - } - } - - /* EIR Data */ - private class EirData { - private BluetoothDevice curDevice; - private byte[] groupData; - - EirData(BluetoothDevice device, byte[] data) { - curDevice = device; - groupData = data; - } - } - - /* API that handles PSRI received from EIR */ - public void handleEIRGroupData(BluetoothDevice device, byte[] data) { - if (VDBG) Log.v(TAG, "handleEirData: device: " + device); - if (mHandler != null && mScanResolution) { - EirData eirData = new EirData(device, data); - mHandler.sendMessage(mHandler.obtainMessage(MSG_HANDLE_EIR_RESPONSE, eirData)); - } else { - if (VDBG) Log.e(TAG, "handleEirData mHandler is null" + - " or Inquiry Scan Resolution is stopped"); - } - } - - /* API to start set discovery by starting either LE scan or BREDR Inquiry */ - void startSetDiscovery(int setId, byte[] sirk, int transport, - int size, List setDevices) { - Log.d(TAG, "startGroupDiscovery: groupId: " + setId + ", group size = " - + size + ", Total discovered = " + setDevices.size() - + " Transport = " + transport); - - // check if set discovery is already in progress - if (mScanResolution) { - Log.e(TAG, "Group discovery is already in progress for Group Id: " + mSetId - + ". Ignore this request"); - return; - } - - // mark parameters of the set to be discovered - mSetId = setId; - mTransport = transport; - mSetSize = size; - mTotalDiscovered = setDevices.size(); - mSirk = Arrays.copyOf(sirk, AES_128_IO_LEN); - reverseByteArray(mSirk); - - // clear scanned arrayList and add already found set members to it - scannedDevices.clear(); - scannedDevices.addAll(setDevices); - - //post message in the front of message queue - mHandler.sendMessageAtFrontOfQueue( - mHandler.obtainMessage(MSG_START_SET_DISCOVERY)); - } - - /* API to start discovery with required settings and transport */ - void handleStartSetDiscovery() { - Log.d(TAG, "handleStartGroupDiscovery"); - mScanResolution = true; - - if (mTransport == BluetoothDevice.DEVICE_TYPE_CLASSIC) { - // start BREDR inquiry (unfiltered) - mBluetoothAdapter.startDiscovery(); - } else { - // Confiigure scan filter and start filtered scan for PSRI data - ScanSettings.Builder settingBuilder = new ScanSettings.Builder(); - List filters = new ArrayList(); - byte[] psri = {}; - - mScanType = SystemProperties.getInt( - "persist.vendor.service.bt.csip.scantype", 1); - - // for debugging purpose only - if (mScanType == 2) { - filters.add(new ScanFilter.Builder().setServiceData( - PSRI_SERVICE_ADTYPE_UUID, psri).build()); - } else if (mScanType == 1) { - filters.add(new ScanFilter.Builder().setGroupBasedFiltering(true) - .build()); - } - settingBuilder.setScanMode(ScanSettings.SCAN_MODE_BALANCED) - .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) - .setLegacy(false); - - // start BLE filtered Scan - if (mScanType != 0) { - Log.i(TAG, " filtered scan started");// debug - mScanner.startScan(filters, settingBuilder.build(), mCsipScanCallback); - } else { - Log.i(TAG, " Unfiltered scan started");// debug - mScanner.startScan(mCsipScanCallback); - } - } - - // Start Set Member discovery timeout of 10 sec - mHandler.removeMessages(MSG_SET_MEMBER_DISC_TIMEOUT); - mHandler.sendMessageDelayed( - mHandler.obtainMessage(MSG_SET_MEMBER_DISC_TIMEOUT), - SET_MEMBER_DISCOVERY_TIMEOUT); - } - - /* to stop set discorvey procedure - stop LE scan or BREDR inquiry */ - void stopSetDiscovery(int setId, int reason) { - Log.d(TAG, "stopGroupDiscovery"); - - mDiscoveryStoppedReason = reason; - - //post message in the front of message queue - mHandler.sendMessageAtFrontOfQueue( - mHandler.obtainMessage(MSG_STOP_SET_DISCOVERY)); - } - - /* handles actions to be taken once set discovery is needed to be stopped*/ - void handleStopSetDiscovery() { - Log.d(TAG, "handleStopGroupDiscovery"); - mScanResolution = false; - - if (mTransport == BluetoothDevice.DEVICE_TYPE_LE || - mTransport == BluetoothDevice.DEVICE_TYPE_DUAL) { - mScanner.stopScan(mCsipScanCallback); - } else { - mBluetoothAdapter.cancelDiscovery(); - } - - // remove all the queued scan results and set member discovery timeout message - mHandler.removeMessages(MSG_HANDLE_LE_SCAN_RESULT); - mHandler.removeMessages(MSG_SET_MEMBER_DISC_TIMEOUT); - - // Give callback to service to route it to requesting application - mainHandler.post(new Runnable() { - @Override - public void run() { - mGroupService.onSetDiscoveryCompleted( - mSetId, mTotalDiscovered, mDiscoveryStoppedReason); - } - }); - } - - /* Starts resolution of PSRI data received in scan results */ - void startPsriResolution(byte[] psri) { - Log.d(TAG, "startGroupResolution"); - - if (VDBG) printByteArrayInHex(psri, "GroupInfo"); - // obtain remote hash and random number - byte[] remoteHash = new byte[PSRI_SPLIT_LEN]; - byte[] randomNumber = new byte[PSRI_SPLIT_LEN]; - - // Get remote hash from first 24 bits of PSRI - System.arraycopy(psri, 0, remoteHash, 0, PSRI_SPLIT_LEN); - // Get random number from last 24 bits of PSRI - System.arraycopy(psri, PSRI_SPLIT_LEN, randomNumber, 0, PSRI_SPLIT_LEN); - - byte[] localHash = computeLocalHash(randomNumber); - - if (VDBG) { - printByteArrayInHex(localHash, "localHash"); - printByteArrayInHex(remoteHash, "remoteHash"); - } - - if (localHash != null) { - validateSetMember(localHash, remoteHash); - } - } - - /* computes local hash from received random number and SIRK */ - byte[] computeLocalHash(byte[] randomNumber) { - byte[] localHash = new byte[AES_128_IO_LEN]; - byte[] randomNumber128 = new byte[AES_128_IO_LEN]; - System.arraycopy(randomNumber, 0, randomNumber128, 0, PSRI_SPLIT_LEN); - - reverseByteArray(randomNumber128); - - if (VDBG) { - // for debugging - printByteArrayInHex(mSirk, "reversed GroupIRK"); - printByteArrayInHex(randomNumber128, "reverse randomNumber"); - } - - try { - SecretKeySpec skeySpec = new SecretKeySpec(mSirk, "AES"); - Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding"); - cipher.init(Cipher.ENCRYPT_MODE, skeySpec); - localHash = cipher.doFinal(randomNumber128); - reverseByteArray(localHash); - if (VDBG) printByteArrayInHex(localHash, "after AES 128 encryption"); - return Arrays.copyOfRange(localHash, 0, PSRI_SPLIT_LEN); - } catch (Exception e) { - Log.e(TAG, "Exception while generating local hash: " + e); - } - return null; - } - - /* to validate that if remote belongs to a given coordinated set*/ - void validateSetMember(byte[] localHash, byte[] remoteHash) { - if (!Arrays.equals(localHash, remoteHash)) { - return; - } - Log.d(TAG, "New Group device discovered: " + mCurrentDevice); - mTotalDiscovered++; - - // give set member found callback on main thread - mainHandler.post(new Runnable() { - @Override - public void run() { - mGroupService.onSetMemberFound(mSetId, mCurrentDevice); - } - }); - - //check if all set members have been discovered - if (mSetSize > 0 && mTotalDiscovered >= mSetSize) { - // to immediatly ignore processing scan results after completion - mScanResolution = false; - mDiscoveryStoppedReason = BluetoothDeviceGroup.DISCOVERY_COMPLETED; - mHandler.sendMessageAtFrontOfQueue( - mHandler.obtainMessage(MSG_STOP_SET_DISCOVERY)); - } else { - // restart set member discovery timeout - mHandler.removeMessages(MSG_SET_MEMBER_DISC_TIMEOUT); - mHandler.sendMessageDelayed( - mHandler.obtainMessage(MSG_SET_MEMBER_DISC_TIMEOUT), - SET_MEMBER_DISCOVERY_TIMEOUT); - } - - } - - /* cleanup tasks on BT OFF*/ - void cleanup() { - mGroupService.unregisterReceiver(mReceiver); - } - - // returns reversed byte array - void reverseByteArray(byte[] byte_arr) { - int size = byte_arr.length; - for (int i = 0; i < size/2; i++) { - byte b = byte_arr[i]; - byte_arr[i] = byte_arr[size - 1 - i]; - byte_arr[size - 1 - i] = b; - } - } - - public static byte[] hexStringToByteArray(String str) { - byte[] b = new byte[str.length() / 2]; - for (int i = 0; i < b.length; i++) { - int index = i * 2; - int val = Integer.parseInt(str.substring(index, index + 2), 16); - b[i] = (byte) val; - } - return b; - } - - // print byte array in hexadecimal format - void printByteArrayInHex(byte[] data, String name) { - final StringBuilder hex = new StringBuilder(); - for(byte b : data) { - hex.append(String.format("%02x", b)); - } - Log.i(TAG, name + ": " + hex); - } -} - diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/groupclient/GroupService.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/groupclient/GroupService.java deleted file mode 100644 index 5f8ba52e512087862b2d58539f5f0416412b3990..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/groupclient/GroupService.java +++ /dev/null @@ -1,1107 +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. - * - ******************************************************************************/ - - -package com.android.bluetooth.groupclient; - -import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission; -import android.bluetooth.BluetoothDeviceGroup; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; -import android.bluetooth.BluetoothUuid; -import android.bluetooth.DeviceGroup; -import android.bluetooth.IBluetoothDeviceGroup; -import android.bluetooth.IBluetoothGroupCallback; -import android.bluetooth.BluetoothGroupCallback; -import android.content.AttributionSource; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.HandlerThread; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.ParcelUuid; -import android.os.SystemProperties; - -import android.util.Log; - -import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.btservice.Config; -import com.android.bluetooth.btservice.ProfileService; -import com.android.bluetooth.btservice.ServiceFactory; -import com.android.bluetooth.Utils; - -import java.util.ArrayList; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.UUID; - -/** - * Provides Bluetooth CSIP Client profile, as a service in the Bluetooth application. - * @hide - */ -public class GroupService extends ProfileService { - private static final boolean DBG = true; - private static final String TAG = "BluetoothGroupService"; - protected static final boolean VDBG = true;//Log.isLoggable(TAG, Log.VERBOSE); - - private GroupScanner mGroupScanner; - - private static GroupService sGroupService; - - private AdapterService mAdapterService; - - GroupClientNativeInterface mGroupNativeInterface; - - GroupAppMap mAppMap = new GroupAppMap(); - - private static CopyOnWriteArrayList mCoordinatedSets - = new CopyOnWriteArrayList(); - - private static HashMap setSirkMap = new HashMap(); - - private static final int INVALID_APP_ID = 0x10; - private static final int INVALID_SET_ID = 0x10; - private static final UUID EMPTY_UUID = UUID.fromString("00000000-0000-0000-0000-000000000000"); - - /* parameters to hold details for ongoing set discovery and pending set discovery */ - private SetDiscoveryRequest mCurrentSetDisc = null; - private SetDiscoveryRequest mPendingSetDisc = null; - - /* Constants for Coordinated set properties */ - private static final String SET_ID = "SET_ID"; - private static final String INCLUDING_SRVC = "INCLUDING_SRVC"; - private static final String SIZE = "SIZE"; - private static final String SIRK = "SIRK"; - private static final String LOCK_SUPPORT = "LOCK_SUPPORT"; - - private class SetDiscoveryRequest { - private int mAppId = INVALID_APP_ID; - private int mSetId = INVALID_SET_ID; - private boolean mDiscInProgress = false; - - SetDiscoveryRequest() { - mAppId = INVALID_APP_ID; - mSetId = INVALID_SET_ID; - mDiscInProgress = false; - } - - SetDiscoveryRequest(int appId, int setId, boolean inProgress) { - mAppId = appId; - mSetId = setId; - mDiscInProgress = inProgress; - } - } - - private final BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action == null) { - Log.e(TAG, "Received intent with null action"); - return; - } - - switch (action) { - case BluetoothDevice.ACTION_BOND_STATE_CHANGED: - BluetoothDevice device = intent.getParcelableExtra( - BluetoothDevice.EXTRA_DEVICE); - int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, - BluetoothDevice.ERROR); - if (bondState == BluetoothDevice.BOND_NONE) { - int setId = getRemoteDeviceGroupId(device, null); - if (setId < BluetoothDeviceGroup.INVALID_GROUP_ID) { - Log.i(TAG, " Group Device "+ device + - " unpaired. Group ID: " + setId); - removeSetMemberFromCSet(setId, device); - } - } - break; - } - - } - }; - - - @Override - protected IProfileServiceBinder initBinder() { - return new GroupBinder(this); - } - - @Override - protected boolean start() { - if (DBG) { - Log.d(TAG, "start()"); - } - - mGroupNativeInterface = Objects.requireNonNull(GroupClientNativeInterface.getInstance(), - "GroupClientNativeInterface cannot be null when GroupService starts"); - - mAdapterService = Objects.requireNonNull(AdapterService.getAdapterService(), - "AdapterService cannot be null when GroupService starts"); - - mGroupScanner = new GroupScanner(this); - - mGroupNativeInterface.init(); - setGroupService(this); - - // register receiver for Bluetooth State change - IntentFilter filter = new IntentFilter(); - filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); - registerReceiver(mReceiver, filter); - - return true; - } - - private static synchronized void setGroupService(GroupService instance) { - if (DBG) { - Log.d(TAG, "setGroupService(): set to: " + instance); - } - sGroupService = instance; - } - - protected boolean stop() { - if (DBG) { - Log.d(TAG, "stop()"); - } - - if (mGroupScanner != null) { - mGroupScanner.cleanup(); - } - - if (sGroupService == null) { - Log.w(TAG, "stop() called already.."); - return true; - } - - unregisterReceiver(mReceiver); - - // Cleanup native interface - mGroupNativeInterface.cleanup(); - mGroupNativeInterface = null; - - // Mark service as stopped - setGroupService(null); - - // cleanup initializations - mGroupScanner = null; - mAdapterService = null; - - return true; - } - - @Override - protected void cleanup() { - if (DBG) { - Log.d(TAG, "cleanup()"); - } - - // Cleanup native interface - if (mGroupNativeInterface != null) { - mGroupNativeInterface.cleanup(); - mGroupNativeInterface = null; - } - - // cleanup initializations - mGroupScanner = null; - mAdapterService = null; - } - - /** - * Get the GroupService instance - * @return GroupService instance - */ - public static synchronized GroupService getGroupService() { - if (sGroupService == null) { - Log.w(TAG, "getGroupService(): service is NULL"); - return null; - } - - if (!sGroupService.isAvailable()) { - Log.w(TAG, "getGroupService(): service is not available"); - return null; - } - - return sGroupService; - } - - /* API to load coordinated set from bonded device on BT ON */ - public static void loadDeviceGroupFromBondedDevice ( - BluetoothDevice device, String setDetails) { - String[] csets = setDetails.split(" "); - if (VDBG) Log.v(TAG, " Device is part of " + csets.length + " device groups"); - - for (String setInfo: csets) { - String[] setProperties = setInfo.split("~"); - int setId = INVALID_SET_ID, size = 0; - UUID inclSrvcUuid = UUID.fromString("00000000-0000-0000-0000-000000000000"); - boolean lockSupport = false; - - for (String property: setProperties) { - if (VDBG) Log.v(TAG, "Property = " + property); - String[] propSplit = property.split(":"); - if (propSplit[0].equals(SET_ID)) { - setId = Integer.parseInt(propSplit[1]); - } else if (propSplit[0].equals(INCLUDING_SRVC)) { - inclSrvcUuid = UUID.fromString(propSplit[1]); - } else if (propSplit[0].equals(SIZE)) { - size = Integer.parseInt(propSplit[1]); - } else if (propSplit[0].equals(SIRK) && setId != 16) { - setSirkMap.put(setId, GroupScanner.hexStringToByteArray(propSplit[1])); - } else if (propSplit[0].equals(LOCK_SUPPORT)) { - lockSupport = Boolean.parseBoolean(propSplit[1]); - } - } - - DeviceGroup set = getCoordinatedSet(setId, false); - if (set == null) { - List members = new ArrayList(); - members.add(device); - set = new DeviceGroup(setId, size, members, - new ParcelUuid(inclSrvcUuid), lockSupport); - mCoordinatedSets.add(set); - } else { - if (!set.getDeviceGroupMembers().contains(device)) { - set.getDeviceGroupMembers().add(device); - } - } - if (VDBG) Log.v(TAG, "Device " + device + " loaded in Group ("+ setId +")" - + " Devices: " + set.getDeviceGroupMembers()); - } - } - - /* API to accept PSRI data from EIR packet */ - public void handleEIRGroupData(BluetoothDevice device, String data) { - mGroupScanner.handleEIRGroupData(device, data.getBytes()); - } - - public static void setAdvanceAudioSupport() { - Log.d(TAG, "setAdvanceAudioSupport: Setting support from LEA Module"); - - if (SystemProperties.get("persist.vendor.service.bt.adv_audio_mask").isEmpty()) { - SystemProperties.set("persist.vendor.service.bt.adv_audio_mask", - String.valueOf(Config.ADV_AUDIO_UNICAST_FEAT_MASK | - Config.ADV_AUDIO_BCA_FEAT_MASK | - Config.ADV_AUDIO_BCS_FEAT_MASK)); - } - } - - private static class GroupBinder - extends IBluetoothDeviceGroup.Stub implements IProfileServiceBinder { - private GroupService mService; - - private GroupService getService() { - if (mService != null && mService.isAvailable()) { - return mService; - } - return null; - } - - GroupBinder(GroupService service) { - if (DBG) { - Log.v(TAG, "GroupBinder()"); - } - mService = service; - } - - @Override - public void cleanup() { - mService = null; - } - - @Override - public void connect(int appId, BluetoothDevice device, AttributionSource source) { - if (DBG) { - Log.d(TAG, "connect Device " + device); - } - - GroupService service = getService(); - if (service == null || !Utils.checkConnectPermissionForDataDelivery( - service, source, "connect")) { - return; - } - service.connect(appId, device); - } - - @Override - public void disconnect(int appId, BluetoothDevice device, AttributionSource source) { - if (DBG) { - Log.d(TAG, "disconnect Device " + device); - } - - GroupService service = getService(); - if (service == null || !Utils.checkConnectPermissionForDataDelivery( - service, source, "disconnect")) { - return; - } - service.disconnect(appId, device); - } - - @Override - public void registerGroupClientApp(ParcelUuid uuid, - IBluetoothGroupCallback callback, AttributionSource source) { - if (VDBG) { - Log.d(TAG, "registerGroupClientApp"); - } - GroupService service = getService(); - if (service == null || !Utils.checkConnectPermissionForDataDelivery( - service, source, "registerGroupClientApp")) { - return; - } - service.registerGroupClientApp(uuid.getUuid(), callback, null); - } - - @Override - public void unregisterGroupClientApp(int appId, AttributionSource source) { - if (VDBG) { - Log.d(TAG, "unregisterGroupClientApp"); - } - GroupService service = getService(); - if (service == null || !Utils.checkConnectPermissionForDataDelivery( - service, source, "unregisterGroupClientApp")) { - return; - } - service.unregisterGroupClientApp(appId); - } - - @Override - public void setExclusiveAccess(int appId, int groupId, List devices, - int value, AttributionSource source) { - if (VDBG) { - Log.d(TAG, "setExclusiveAccess"); - } - GroupService service = getService(); - if (service == null || !Utils.checkConnectPermissionForDataDelivery( - service, source, "setExclusiveAccess")) { - return; - } - service.setLockValue(appId, groupId, devices, value); - } - - @Override - public void startGroupDiscovery(int appId, int groupId - , AttributionSource source) throws RemoteException { - if (VDBG) { - Log.d(TAG, "startGroupDiscovery"); - } - GroupService service = getService(); - if (service == null || !Utils.checkConnectPermissionForDataDelivery(service, - source, "startGroupDiscovery")) { - return; - } - service.startSetDiscovery(appId, groupId); - } - - @Override - public void stopGroupDiscovery(int appId, int groupId, AttributionSource source) { - if (VDBG) { - Log.d(TAG, "stopGroupDiscovery"); - } - GroupService service = getService(); - if (service == null || !Utils.checkConnectPermissionForDataDelivery( - service, source, "stopGroupDiscovery")) { - return; - } - enforceBluetoothPrivilegedPermission(service); - service.stopSetDiscovery(appId, groupId); - } - - @Override - public void getExclusiveAccessStatus(int appId, int groupId, - List devices, AttributionSource source) { - if (DBG) { - Log.d(TAG, "getExclusiveAccessStatus"); - } - GroupService service = getService(); - if (service == null || !Utils.checkConnectPermissionForDataDelivery( - service, source, "getExclusiveAccessStatus")) { - return; - } - enforceBluetoothPrivilegedPermission(service); - } - - @Override - public List getDiscoveredGroups(boolean mPublicAddr - , AttributionSource source) { - if (DBG) { - Log.d(TAG, "getDiscoveredGroups"); - } - GroupService service = getService(); - if (service == null || !Utils.checkConnectPermissionForDataDelivery( - service, source, "getDiscoveredGroups")) { - return null; - } - return service.getDiscoveredCoordinatedSets(mPublicAddr); - } - - @Override - public DeviceGroup getDeviceGroup(int setId, boolean mPublicAddr, - AttributionSource source) { - if (DBG) { - Log.d(TAG, "getDeviceGroup"); - } - GroupService service = getService(); - if (service == null || !Utils.checkConnectPermissionForDataDelivery( - service, source, "getDeviceGroup")) { - return null; - } - return (service.getCoordinatedSet(setId, mPublicAddr)); - } - - @Override - public int getRemoteDeviceGroupId (BluetoothDevice device, ParcelUuid uuid, - boolean mPublicAddr, AttributionSource source) { - if (DBG) { - Log.d(TAG, "getRemoteDeviceGroupId"); - } - GroupService service = getService(); - if (service == null || !Utils.checkConnectPermissionForDataDelivery( - service, source, "getRemoteDeviceGroupId")) { - return INVALID_SET_ID; - } - return service.getRemoteDeviceGroupId(device, uuid, mPublicAddr); - } - - @Override - public boolean isGroupDiscoveryInProgress (int setId, AttributionSource source) { - if (DBG) { - Log.d(TAG, "isGroupDiscoveryInProgress"); - } - GroupService service = getService(); - if (service == null || !Utils.checkScanPermissionForDataDelivery( - service, source, "isGroupDiscoveryInProgress")) { - return false; - } - return service.isSetDiscoveryInProgress(setId); - } - }; - - /** - * DeathReceipient handler to unregister applications those are - * disconnected ungracefully (ie. crash or forced close). - */ - class GroupAppDeathRecipient implements IBinder.DeathRecipient { - int mAppId; - - GroupAppDeathRecipient(int appId) { - mAppId = appId; - Log.i(TAG, "GroupAppDeathRecipient"); - } - - @Override - public void binderDied() { - if (DBG) { - Log.d(TAG, "Binder is dead - unregistering app (" + mAppId + ")!"); - } - - mAppMap.remove(mAppId); - unregisterGroupClientApp(mAppId); - } - - } - - /* for registration of other Bluetooth profile in Bluetooth App Space*/ - public void registerGroupClientModule(BluetoothGroupCallback callback) { - Log.d(TAG, "registerGroupClientModule"); - - UUID uuid; - - if (mGroupNativeInterface == null) return; - // Generate an unique UUID for Bluetooth Modules which is not used by others apps - do { - uuid = UUID.randomUUID(); - } while(mAppMap.appUuids.contains(uuid)); - - registerGroupClientApp(uuid, null, callback); - } - - /* Registers CSIP App or module with CSIP native layer */ - public void registerGroupClientApp(UUID uuid, IBluetoothGroupCallback appCb, - BluetoothGroupCallback localCallback) { - if (DBG) { - Log.d(TAG, "registerGroupClientApp: UUID = " + uuid.toString()); - } - - boolean isLocal = false; - if (localCallback != null) { - isLocal = true; - } - - mAppMap.add(uuid, isLocal, appCb, localCallback); - mGroupNativeInterface.registerCsipApp(uuid.getLeastSignificantBits(), - uuid.getMostSignificantBits()); - } - - /* Unregisters Bluetooth module (BT profile) with CSIP*/ - public void unregisterGroupClientModule(int appId) { - unregisterGroupClientApp(appId); - } - - /* Unregisters App/Module with CSIP*/ - public void unregisterGroupClientApp(int appId) { - if (DBG) { - Log.d(TAG, "unregisterGroupClientApp: appId = " + appId); - } - - if (mGroupNativeInterface == null) return; - mAppMap.remove(appId); - mGroupNativeInterface.unregisterCsipApp(appId); - } - - /* API to request change in lock value */ - public void setLockValue(int appId, int setId, List devices, - int value) { - if (DBG) { - Log.d(TAG, "setExclusiveAccess: appId = " + appId + ", setId: " + setId + - ", value = " + value + ", set Members = " + devices); - } - - if (mGroupNativeInterface == null) return; - // appId and setId validation is done at stack layer - mGroupNativeInterface.setLockValue(appId, setId, devices, value); - } - - /* Starts the set members discovery for the requested coordinated set */ - public void startSetDiscovery(int appId, int setId) throws RemoteException { - if (DBG) { - Log.d(TAG, "startGroupDiscovery. setId = " + setId + " Initiating appId = " + appId); - } - - // Get Apllication details - GroupAppMap.GroupClientApp app = mAppMap.getById(appId); - if (app == null) { - Log.e(TAG, "Application not found for appId: " + appId); - return; - } - - DeviceGroup cSet = getCoordinatedSet(setId, true); - if (cSet == null || !setSirkMap.containsKey(setId)) { - Log.e(TAG, "Invalid Group Id: " + setId); - mCurrentSetDisc = null; - app.appCb.onGroupDiscoveryStatusChanged(setId, BluetoothDeviceGroup.GROUP_DISCOVERY_STOPPED, - BluetoothDeviceGroup.DISCOVERY_NOT_STARTED_INVALID_PARAMS); - return; - } - - /* check if all set members are already discovered */ - int setSize = cSet.getDeviceGroupSize(); - if (setSize != 0 && cSet.getTotalDiscoveredGroupDevices() >= setSize) { - app.appCb.onGroupDiscoveryStatusChanged(setId, - BluetoothDeviceGroup.GROUP_DISCOVERY_STOPPED, - BluetoothDeviceGroup.DISCOVERY_COMPLETED); - return; - } - - if (mCurrentSetDisc != null && mCurrentSetDisc.mDiscInProgress) { - Log.e(TAG, "Group Discovery is already in Progress for Group: " - + mCurrentSetDisc.mSetId + " from AppId: " + mCurrentSetDisc.mAppId - + " Stop current Group discovery"); - mPendingSetDisc = new SetDiscoveryRequest(appId, setId, false); - mGroupScanner.stopSetDiscovery(mCurrentSetDisc.mSetId, 0); - return; - } else if (mCurrentSetDisc == null) { - mCurrentSetDisc = new SetDiscoveryRequest(appId, setId, false); - } - - int transport; - byte[] sirk; - - sirk = setSirkMap.get(setId); - - /*TODO: Optimize logic if device type is UNKNOWN */ - try { - BluetoothDevice device = cSet.getDeviceGroupMembers().get(0); - transport = device.getType(); - } catch (IndexOutOfBoundsException e) { - Log.e(TAG, "Invalid Group- No device found : " + e); - mCurrentSetDisc = null; - return; - } - - mGroupScanner.startSetDiscovery(setId, sirk, transport, - cSet.getDeviceGroupSize(), cSet.getDeviceGroupMembers()); - mCurrentSetDisc.mDiscInProgress = true; - - try { - if (app.appCb != null) { - app.appCb.onGroupDiscoveryStatusChanged(setId, - BluetoothDeviceGroup.GROUP_DISCOVERY_STARTED, - BluetoothDeviceGroup.DISCOVERY_STARTED_BY_APPL); - } - } catch (RemoteException e) { - Log.e(TAG, "Exception : " + e); - } - } - - /* Stops the set members discovery for the requested coordinated set */ - public void stopSetDiscovery(int appId, int setId) { - if (DBG) { - Log.d(TAG, "stopGroupDiscovery: appId = " + appId + " groupId = " + setId); - } - - // Get Apllication details - GroupAppMap.GroupClientApp app = mAppMap.getById(appId); - - if (app == null) { - Log.e(TAG, "Application not found for appId: " + appId); - return; - } - - // check if requesting app is stopping the discovery - if (mCurrentSetDisc == null || mCurrentSetDisc.mAppId != appId) { - Log.e(TAG, " Either no discovery in progress or Stop Request from" - + " App which has not started Group Discovery"); - return; - } - - mGroupScanner.stopSetDiscovery(setId, BluetoothDeviceGroup.DISCOVERY_STOPPED_BY_APPL); - } - - /* Reading lock status of coordinated set for ordered access procedure */ - public void getLockStatus(int setId, List devices) { - //TODO: Future enhancement - } - - /* To connect to Coordinated Set Device */ - public void connect (int appId, BluetoothDevice device) { - Log.d(TAG, "connect Device: " + device + ", appId: " + appId); - if (mGroupNativeInterface == null) return; - mGroupNativeInterface.connectSetDevice(appId, device); - } - - /* To disconnect from Coordinated Set Device */ - public void disconnect (int appId, BluetoothDevice device) { - Log.d(TAG, "disconnect Device: " + device + ", appId: " + appId); - if (mGroupNativeInterface == null) return; - mGroupNativeInterface.disconnectSetDevice(appId, device); - } - - public List getDiscoveredCoordinatedSets() { - return getDiscoveredCoordinatedSets(true); - } - - /* returns all discovered coordinated sets */ - public List getDiscoveredCoordinatedSets(boolean mPublicAddr) { - if (DBG) { - Log.d(TAG, "getDiscoveredGroups"); - } - - /* Add logic to replace random addresses to public addresses if requested */ - // Iterate on coordinated sets - // check address type. Replace with public if requested - if (mPublicAddr) { - List coordinatedSets = new ArrayList(); - AdapterService adapterService = Objects.requireNonNull( - AdapterService.getAdapterService(), - "AdapterService cannot be null"); - for (DeviceGroup set: mCoordinatedSets) { - DeviceGroup cSet = new DeviceGroup( - set.getDeviceGroupId(), set.getDeviceGroupSize(), - new ArrayList(), - set.getIncludingServiceUUID(), set.isExclusiveAccessSupported()); - for (BluetoothDevice device: set.getDeviceGroupMembers()) { - BluetoothDevice publicDevice = device; - if (adapterService.isIgnoreDevice(device)) { - publicDevice = adapterService.getIdentityAddress(device); - } - cSet.getDeviceGroupMembers().add(publicDevice); - } - coordinatedSets.add(cSet); - } - return coordinatedSets; - } - - return mCoordinatedSets; - } - - public static DeviceGroup getCoordinatedSet(int setId) { - return getCoordinatedSet(setId, true); - } - - /* returns requested coordinated set */ - public static DeviceGroup getCoordinatedSet(int setId, boolean mPublicAddr) { - if (DBG) { - Log.d(TAG, "getDeviceGroup : groupId = " + setId - + " mPublicAddr: " + mPublicAddr); - } - - AdapterService adapterService = Objects.requireNonNull( - AdapterService.getAdapterService(), "AdapterService cannot be null"); - - for (DeviceGroup cSet: mCoordinatedSets) { - if (cSet.getDeviceGroupId() == setId) { - if (!mPublicAddr) { - return cSet; - - // Public addresses are requested. Replace address with public addr - } else { - DeviceGroup set = new DeviceGroup( - cSet.getDeviceGroupId(), cSet.getDeviceGroupSize(), - new ArrayList(), - cSet.getIncludingServiceUUID(), cSet.isExclusiveAccessSupported()); - for (BluetoothDevice device: cSet.getDeviceGroupMembers()) { - if (device.getBondState() == BluetoothDevice.BOND_BONDED) { - BluetoothDevice publicDevice = device; - if (adapterService.isIgnoreDevice(device)) { - publicDevice = adapterService.getIdentityAddress(device); - } - set.getDeviceGroupMembers().add(publicDevice); - } - } - return set; - } - } - } - - return null; - } - - public boolean isSetDiscoveryInProgress (int setId) { - if (DBG) { - Log.d(TAG, "isGroupDiscoveryInProgress: groupId = " + setId); - } - - if (mCurrentSetDisc != null && mCurrentSetDisc.mSetId == setId - && mCurrentSetDisc.mDiscInProgress) - return true; - return false; - } - - public int getRemoteDeviceGroupId (BluetoothDevice device, ParcelUuid uuid) { - return getRemoteDeviceGroupId(device, uuid, true); - } - - public int getRemoteDeviceGroupId (BluetoothDevice device, ParcelUuid uuid, - boolean mPublicAddr) { - if (DBG) { - Log.d(TAG, "getRemoteDeviceGroupId: device = " + device + " uuid = " + uuid - + ", mPublicAddr = " + mPublicAddr); - } - - if (mAdapterService == null) { - Log.e(TAG, "AdapterService instance is NULL. Return."); - return INVALID_SET_ID; - } - - BluetoothDevice setDevice = null; - if (mPublicAddr && mAdapterService.isIgnoreDevice(device)) { - setDevice = mAdapterService.getIdentityAddress(device); - } - - if (uuid == null) { - uuid = new ParcelUuid(EMPTY_UUID); - } - - for (DeviceGroup cSet: mCoordinatedSets) { - if ((cSet.getDeviceGroupMembers().contains(device) || - cSet.getDeviceGroupMembers().contains(setDevice)) - && cSet.getIncludingServiceUUID().equals(uuid)) { - return cSet.getDeviceGroupId(); - } - } - - return INVALID_SET_ID; - } - - /* This API is called when pairing with LE Audio capable set member fails or - * when set member is unpaired. Removing the set member from list gives option - * to user to rediscover it */ - public void removeSetMemberFromCSet(int setId, BluetoothDevice device) { - Log.d(TAG, "removeDeviceFromDeviceGroup: setId = " + setId + ", Device: " + device); - - DeviceGroup cSet = getCoordinatedSet(setId, false); - if (cSet != null) { - cSet.getDeviceGroupMembers().remove(device); - if (cSet.getDeviceGroupMembers().size() == 0) { - Log.i(TAG, "Last device unpaired. Removing Device Group from database"); - mCoordinatedSets.remove(cSet); - return; - } - } - - cSet = getCoordinatedSet(setId, true); - if (cSet != null) { - cSet.getDeviceGroupMembers().remove(device); - if (cSet.getDeviceGroupMembers().size() == 0) { - Log.i(TAG, "Last device unpaired. Removing Device Group from database"); - mCoordinatedSets.remove(cSet); - } - } - } - - public void printAllCoordinatedSets() { - if (VDBG) { - for (DeviceGroup set: mCoordinatedSets) { - Log.i(TAG, "GROUP_ID: " + set.getDeviceGroupId() - + ", size = " + set.getDeviceGroupSize() - + ", discovered = " + set.getTotalDiscoveredGroupDevices() - + ", Including Srvc Uuid = "+ set.getIncludingServiceUUID() - + ", devices = " + set.getDeviceGroupMembers()); - } - } - } - - /* Callback received from CSIP native layer when an APP/module has been registered */ - protected void onCsipAppRegistered (int status, int appId, UUID uuid) { - Log.d(TAG, "onGroupClientAppRegistered: appId: " + appId + ", UUID: " + uuid.toString()); - - GroupAppMap.GroupClientApp app = mAppMap.getByUuid(uuid); - - if (app == null) { - Log.e(TAG, "Application not found for UUID: " + uuid.toString()); - return; - } - - app.appId = appId; - // Give callback to the application that app has been registered - try { - if (app.isRegistered && app.isLocal) { - app.mCallback.onGroupClientAppRegistered(status, appId); - } else if (app.isRegistered && !app.isLocal) { - app.linkToDeath(new GroupAppDeathRecipient(appId)); - app.appCb.onGroupClientAppRegistered(status, appId); - } - } catch (RemoteException e) { - Log.e(TAG, "Exception : " + e); - } - } - - /* When CSIP Profile connection state has been changed */ - protected void onConnectionStateChanged(int appId, BluetoothDevice device, - int state, int status) { - Log.d(TAG, "onConnectionStateChanged: appId: " + appId + ", device: " + device - + ", State: " + state + ", Status: " + status); - - GroupAppMap.GroupClientApp app = mAppMap.getById(appId); - - if (app == null) { - Log.e(TAG, "Application not found for appId: " + appId); - return; - } - - try { - if (app.isRegistered && app.isLocal) { - app.mCallback.onConnectionStateChanged(state, device); - } else if (app.isRegistered && !app.isLocal) { - app.appCb.onConnectionStateChanged(state, device); - } - } catch (RemoteException e) { - Log.e(TAG, "Exception : " + e); - } - } - - /* When a new set member is discovered as a part of Set Discovery procedure */ - protected void onSetMemberFound (int setId, BluetoothDevice device) { - Log.d(TAG, "onGroupDeviceFound: groupId: " + setId + ", device: " + device); - for (DeviceGroup cSet: mCoordinatedSets) { - if (cSet.getDeviceGroupId() == setId - && !cSet.getDeviceGroupMembers().contains(device)) { - cSet.getDeviceGroupMembers().add(device); - break; - } - } - - // Give callback to adapterservice to initiate bonding if required - mAdapterService.processGroupMember(setId, device); - - // Give callback to the application that started Set Discovery - GroupAppMap.GroupClientApp app = mAppMap.getById(mCurrentSetDisc.mAppId); - - if (app == null) { - Log.e(TAG, "Application not found for appId: " + mCurrentSetDisc.mAppId); - return; - } - - try { - if (app.appCb != null) { - app.appCb.onGroupDeviceFound(setId, device); - } - } catch (RemoteException e) { - Log.e(TAG, "Exception : " + e); - } - } - - /* When set discovery procedure has been completed */ - protected void onSetDiscoveryCompleted (int setId, - int totalDiscovered, int reason) { - Log.d(TAG, "onGroupDiscoveryCompleted: groupId: " + setId + ", totalDiscovered = " - + totalDiscovered + "reason: " + reason); - - // mark Set Discovery procedure as completed - mCurrentSetDisc.mDiscInProgress = false; - // Give callback to the application that Set Discovery has been completed - GroupAppMap.GroupClientApp app = mAppMap.getById(mCurrentSetDisc.mAppId); - - if (app == null) { - Log.e(TAG, "Application not found for appId: " + mCurrentSetDisc.mAppId); - return; - } - - try { - if (app.appCb != null) { - app.appCb.onGroupDiscoveryStatusChanged(setId, - BluetoothDeviceGroup.GROUP_DISCOVERY_STOPPED, reason); - } - - DeviceGroup cSet = getCoordinatedSet(setId, false); - if (VDBG && cSet != null) { - Log.i(TAG, "Device Group: groupId" + setId + ", devices: " - + cSet.getDeviceGroupMembers()); - } - - if (mPendingSetDisc != null) { - mCurrentSetDisc = mPendingSetDisc; - mPendingSetDisc = null; - startSetDiscovery(mCurrentSetDisc.mAppId, mCurrentSetDisc.mSetId); - } else { - mCurrentSetDisc = null; - } - } catch (RemoteException e) { - Log.e(TAG, "Exception : " + e); - } - } - - /* Callback received from CSIP native layer when a new Coordinated set has been - * identified with remote device */ - protected void onNewSetFound(int setId, BluetoothDevice device, int size, - byte[] sirk, UUID pSrvcUuid, boolean lockSupport) { - Log.d(TAG, "onNewGroupFound: Address : " + device + ", groupId: " + setId - + ", size: " + size + ", uuid: " + pSrvcUuid.toString()); - - // Form Coordinated Set Object and store in ArrayList - List devices = new ArrayList(); - devices.add(device); - DeviceGroup cSet = new DeviceGroup(setId, size, devices, - new ParcelUuid(pSrvcUuid), lockSupport); - mCoordinatedSets.add(cSet); - - // Store sirk in hashmap of setId, sirk - setSirkMap.put(setId, sirk); - - // Give Callback to all registered application - try { - for (GroupAppMap.GroupClientApp app: mAppMap.mApps) { - if (app.isRegistered && !app.isLocal) { - if (app.appCb != null)//temp check - app.appCb.onNewGroupFound(setId, device, new ParcelUuid(pSrvcUuid)); - } - } - } catch (RemoteException e) { - Log.e(TAG, "Exception : " + e); - } - } - - /* Callback received from CSIP native layer when undiscovered set member is connected */ - protected void onNewSetMemberFound (int setId, BluetoothDevice device) { - Log.d(TAG, "onNewGroupDeviceFound: groupId = " + setId + ", Device = " + device); - - if (mAdapterService == null) { - Log.e(TAG, "AdapterService instance is NULL. Return."); - return; - } - - if (mAdapterService.isIgnoreDevice(device)) { - device = mAdapterService.getIdentityAddress(device); - } - // check if this device is already part of an already existing coordinated set - /* Scenario: When a device was not discovered during initial set discovery - * procedure and later user had explicitely paired with this device - * from pair new device UI option. Not required to send onSetMemberFound - * callback to application*/ - if (setSirkMap.containsKey(setId)) { - for (DeviceGroup cSet: mCoordinatedSets) { - if (cSet.getDeviceGroupId() == setId && - (!cSet.getDeviceGroupMembers().contains(device))) { - cSet.getDeviceGroupMembers().add(device); - break; - } - } - return; - } - } - - /* callback received when lock status is changed for requested coordinated set*/ - protected void onLockStatusChanged (int appId, int setId, int value, int status, - List devices) { - Log.d(TAG, "onExclusiveAccessChanged: appId = " + appId + ", groupId = " + setId + - ", value = " + value + ", status = " + status + ", devices = " + devices); - GroupAppMap.GroupClientApp app = mAppMap.getById(appId); - - if (app == null) { - Log.e(TAG, "Application not found for appId: " + appId); - return; - } - - try { - if (app.isRegistered && app.isLocal) { - app.mCallback.onExclusiveAccessChanged(setId, value, status, devices); - } else if (app.isRegistered && !app.isLocal) { - app.appCb.onExclusiveAccessChanged(setId, value, status, devices); - } - } catch (RemoteException e) { - Log.e(TAG, "Exception : " + e); - } - } - - /* Callback received when earlier denied lock is now available */ - protected void onLockAvailable (int appId, int setId, BluetoothDevice device) { - Log.d(TAG, "onExclusiveAccessAvailable: Remote(" + device + "), Group Id: " - + setId + ", App Id: " + appId); - - GroupAppMap.GroupClientApp app = mAppMap.getById(appId); - if (app == null) { - Log.e(TAG, "Application not found for appId: " + appId); - return; - } - - try { - if (app.isRegistered && app.isLocal) { - app.mCallback.onExclusiveAccessAvailable(setId, device); - } else if (app.isRegistered && !app.isLocal) { - app.appCb.onExclusiveAccessAvailable(setId, device); - } - } catch (RemoteException e) { - Log.e(TAG, "Exception : " + e); - } - - } - - /* Callback received when set size has been changed */ - /* TODO: Scanarios are unknown. Actions are to be decided */ - protected void onSetSizeChanged (int setId, int size, BluetoothDevice device) { - Log.d(TAG, "onGroupSizeChanged: Group Id: " + setId + ", New Size: " + size + - ", Notifying device: " + device); - - // TODO: Logic to be incorporated once use case is understood - } - - /* Callback received when set SIRK has been changed */ - /* TODO: Scanarios are unknown. Actions are to be decided */ - protected void onSetSirkChanged(int setId, byte[] sirk, BluetoothDevice device) { - Log.d(TAG, "onGroupIdChanged Group Id: " + setId + ", Notifying device: " + device); - - // TODO: Logic to be incorporated once use case is understood - } - -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/mcp/McpNativeInterface.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/mcp/McpNativeInterface.java deleted file mode 100644 index b850ce9e3955269fbc2e546cb3a6dfa4c6631743..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/mcp/McpNativeInterface.java +++ /dev/null @@ -1,274 +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. - * - ******************************************************************************/ - - -package com.android.bluetooth.mcp; - -import android.bluetooth.BluetoothAdapter; -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; - -/** - * Mcp Native Interface to/from JNI. - */ -public class McpNativeInterface { - private static final String TAG = "McpNativeInterface"; - private static final boolean DBG = true; - private BluetoothAdapter mAdapter; - @GuardedBy("INSTANCE_LOCK") - private static McpNativeInterface sInstance; - private static final Object INSTANCE_LOCK = new Object(); - - static { - classInitNative(); - } - - private McpNativeInterface() { - mAdapter = BluetoothAdapter.getDefaultAdapter(); - if (mAdapter == null) { - Log.wtfStack(TAG, "No Bluetooth Adapter Available"); - } - } - - /** - * Get singleton instance. - */ - public static McpNativeInterface getInstance() { - synchronized (INSTANCE_LOCK) { - if (sInstance == null) { - sInstance = new McpNativeInterface(); - } - return sInstance; - } - } - - /** - * Initializes the native interface. - * - * priorities to configure. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void init() { - initNative(); - } - - /** - * Cleanup the native interface. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void cleanup() { - cleanupNative(); - } - - - /** - * update MCP media supported feature - * @param feature - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean mediaControlPointOpcodeSupported(int feature) { - return mediaControlPointOpcodeSupportedNative(feature); - } - - /** - * update MCP media supported feature current value - * @param value - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean mediaControlPoint(int value) { - return mediaControlPointNative(value); - } - - /** - * Sets the Mcp media state - * @param state - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean mediaState(int state) { - return mediaStateNative(state); - } - - /** - * update MCP media player name - * @param player name - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean mediaPlayerName(String playeName) { - return mediaPlayerNameNative(playeName); - } - /** - * update track change notification - * @param track id - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean trackChanged(int status) { - return trackChangedNative(status); - } - /** - * update MCP track position - * @param position - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean trackPosition(int position) { - return trackPositionNative(position); - } - - /** - * update MCP track duration - * @param duration - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean trackDuration(int duration) { - return trackDurationNative(duration); - } - /** - * update MCP track title - * @param title - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean trackTitle(String title) { - return trackTitleNative(title); - } - /** - * update playing order support of media - * @param order - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean playingOrderSupported(int order) { - return playingOrderSupportedNative(order); - } - /** - * update playing order value of media - * @param value - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean playingOrder(int value) { - return playingOrderNative(value); - } - /** - * update active device - * @param device - * @param setId - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean setActiveDevice(BluetoothDevice device, int setId, int profile) { - return setActiveDeviceNative(profile, setId, getByteAddress(device)); - } - /** - * Sets Mcp media content control id - * @param ccid - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean contentControlId(int ccid) { - - return contentControlIdNative(ccid); - } - /** - * Disconnect Mcp disconnect device - * @param device - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean disconnectMcp(BluetoothDevice device) { - return disconnectMcpNative(getByteAddress(device)); - } - - /** - * Disconnect Mcp disconnect device - * @param device - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean bondStateChange(BluetoothDevice device, int state) { - return bondStateChangeNative(state, getByteAddress(device)); - } - - 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()); - } - - // Callbacks from the native stack back into the Java framework. - // All callbacks are routed via the Service which will disambiguate which - private void OnConnectionStateChanged(int state, byte[] address) { - if (DBG) { - Log.d(TAG, "OnConnectionStateChanged: " + state); - } - BluetoothDevice device = getDevice(address); - - McpService service = McpService.getMcpService(); - if (service != null) - service.onConnectionStateChanged(device, state); - } - - private void MediaControlPointChangedRequest(int state, byte[] address) { - BluetoothDevice device = getDevice(address); - if (DBG) { - Log.d(TAG, "MediaControlPointChangedReq: " + state); - } - McpService service = McpService.getMcpService(); - if (service != null) - service.onMediaControlPointChangeReq(device, state); - } - - private void TrackPositionChangedRequest(int position) { - if (DBG) { - Log.d(TAG, "TrackPositionChangedRequest: " + position); - } - McpService service = McpService.getMcpService(); - if (service != null) - service.onTrackPositionChangeReq(position); - } - - private void PlayingOrderChangedRequest(int order) { - if (DBG) { - Log.d(TAG, "PlayingOrderChangedRequest: " + order); - } - McpService service = McpService.getMcpService(); - if (service != null) - service.onPlayingOrderChangeReq(order); - } - - // Native methods that call into the JNI interface - private static native void classInitNative(); - private native void initNative(); - private native void cleanupNative(); - private native boolean mediaControlPointOpcodeSupportedNative(int feature); - private native boolean mediaControlPointNative(int value); - private native boolean mediaStateNative(int state); - private native boolean mediaPlayerNameNative(String playerName); - private native boolean trackChangedNative(int status); - private native boolean trackPositionNative(int position); - private native boolean trackDurationNative(int duration); - private native boolean trackTitleNative(String title); - private native boolean playingOrderSupportedNative(int order); - private native boolean playingOrderNative(int value); - private native boolean setActiveDeviceNative(int profile, int setId, byte[] address); - private native boolean contentControlIdNative(int ccid); - private native boolean disconnectMcpNative(byte[] address); - private native boolean bondStateChangeNative(int state, byte[] address); -} - diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/mcp/McpService.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/mcp/McpService.java deleted file mode 100644 index 316338296e1054510cde13f4f8519b2915b4a929..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/mcp/McpService.java +++ /dev/null @@ -1,842 +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. - * - ******************************************************************************/ - - -package com.android.bluetooth.mcp; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; -import com.android.bluetooth.btservice.ProfileService; -import android.bluetooth.BluetoothUuid; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.Intent; -import android.content.IntentFilter; -import android.media.AudioManager; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.ParcelUuid; -import android.os.SystemProperties; -import android.os.UserManager; -import android.util.Log; -import android.os.Message; -import android.os.Binder; -import android.os.IBinder; - -import com.android.bluetooth.BluetoothMetricsProto; -import com.android.bluetooth.Utils; -import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.apm.ActiveDeviceManagerService; -import com.android.bluetooth.apm.ApmConst; -import com.android.bluetooth.acm.AcmService; -import com.android.bluetooth.btservice.MetricsLogger; -import com.android.bluetooth.btservice.ProfileService; -import com.android.bluetooth.btservice.ServiceFactory; -import com.android.internal.annotations.VisibleForTesting; -import android.media.session.PlaybackState; -import android.media.MediaDescription; -import android.media.MediaMetadata; -import com.android.bluetooth.apm.MediaControlManager; -import android.view.KeyEvent; -import java.util.Map; -import java.util.HashMap; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.TimeUnit; -import android.media.session.MediaSessionManager; -import com.android.internal.util.ArrayUtils; -/** - * Provides Bluetooth MCP profile as a service in the Bluetooth application. - * @hide - */ -public class McpService extends ProfileService { - - private static final String TAG = "McpService"; - private static final boolean DBG = true; - public static final int MUSIC_PLAYER_CONTROL = 28; - private static McpService sMcpService; - private BroadcastReceiver mBondStateChangedReceiver; - - private BluetoothDevice mActiveDevice; - private AdapterService mAdapterService; - private McpNativeInterface mNativeInterface; - private static McpService sInstance = null; - private Context mContext; - private McsMessageHandler mHandler; - private int mMaxConnectedAudioDevices = 1; - private String mActiveMediaPlayerName = new String(""); - - public static final String ACTION_CONNECTION_STATE_CHANGED = - "com.android.bluetooth.mcp.action.CONNECTION_STATE_CHANGED"; - //native event - static final int EVENT_TYPE_CONNECTION_STATE_CHANGED = 1; - static final int EVENT_TYPE_MEDIA_CONTROL_POINT_CHANGED = 2; - static final int EVENT_TYPE_TRACK_POSITION_CHANGED = 3; - static final int EVENT_TYPE_PLAYING_ORDER_CHANGED = 4; - //MCP to JNI update - static final int MEDIA_STATE_UPDATE = 5; - static final int MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_UPDATE = 6; - static final int MEDIA_CONTROL_POINT_UPDATE = 7; - static final int MEDIA_PLAYER_NAME_UPDATE = 8; - static final int TRACK_CHANGED_UPDATE = 9; - static final int TRACK_TITLE_UPDATE = 10; - static final int TRACK_POSITION_UPDATE = 11; - static final int TRACK_DURATION_UPDATE = 12; - static final int PLAYING_ORDER_SUPPORT_UPDATE = 13; - static final int PLAYING_ORDER_UPDATE = 14; - static final int CONTENT_CONTROL_ID_UPDATE = 15; - static final int ACTIVE_DEVICE_CHANGE = 16; - static final int BOND_STATE_CHANGE = 17; - static final int MEDIA_CONTROL_MANAGER_INIT = 18; - - static final int PLAYSTATUS_ERROR = -1; - static final int PLAYSTATUS_STOPPED = 0; - static final int PLAYSTATUS_PLAYING = 1; - static final int PLAYSTATUS_PAUSED = 2; - static final int PLAYSTATUS_SEEK = 3; - - - //super set of supported player supported feature - static final int MCP_MEDIA_CONTROL_SUP_PLAY = 1<<0; - static final int MCP_MEDIA_CONTROL_SUP_PAUSE = 1<<1; - static final int MCP_MEDIA_CONTROL_SUP_FAST_REWIND = 1<<2; - static final int MCP_MEDIA_CONTROL_SUP_FAST_FORWARD = 1<<3; - static final int MCP_MEDIA_CONTROL_SUP_STOP = 1<<4; - static final int MCP_MEDIA_CONTROL_SUP_PREV_TRACK = 1<<11; - static final int MCP_MEDIA_CONTROL_SUP_NEXT_TRACK = 1<<12; - - //media control point opcodes - static final int MCP_MEDIA_CONTROL_OPCODE_PLAY = 0x01; - static final int MCP_MEDIA_CONTROL_OPCODE_PAUSE = 0x02; - static final int MCP_MEDIA_CONTROL_OPCODE_FAST_REWIND = 0x03; - static final int MCP_MEDIA_CONTROL_OPCODE_FAST_FORWARD = 0x04; - static final int MCP_MEDIA_CONTROL_OPCODE_STOP = 0x05; - static final int MCP_MEDIA_CONTROL_OPCODE_PREV_TRACK = 0x30; - static final int MCP_MEDIA_CONTROL_OPCODE_NEXT_TRACK = 0x31; - - //as there is not supported api to fetch player details - static final int DEFAULT_MEDIA_PLAYER_SUPPORTED_FEATURE = 0x181F; - static final int DEFAULT_PLAYER_SUPPORTED_FEATURE = 0x0001; // Single once default - static final int DEFAULT_PLAYING_ORDER = 0x01; // Single Once default - private int mState = -1; - private int mCurrOpCode = -1; - private int mSupportedControlPoint = -1; - private int mControlPoint = -1; - private int mSupportedPlayingOrder = -1; - private int mPlayingOrder = -1; - private int mCcid = -1; - private int mTrackPosition = 0xFFFF; - private int mTrackDuration = 0xFFFF; - private String mPlayerName = null; - private String mTrackTitle = null; - private MediaControlManager mMediaControlManager; - private MediaSessionManager mMediaSessionManager; - /*private class MusicPlayerDetail { - private int state; - private int featureSupported; - private int mSetFeature; - private int playingOrderFeatureSupported; - private int currentPlayingOrder; - private int ccid; - private int mTrackPosition; - private int currentTrackDuration; - private String playerName; - - public MusicPlayerDetail() { - - } - };*/ - //HashMap mMusicPlayerMap = new HashMap(); - @Override - protected IProfileServiceBinder initBinder() { - return new McpBinder(this); - } - - @Override - protected void create() { - Log.i(TAG, "create()"); - } - - @Override - protected void cleanup() { - Log.i(TAG, "cleanup()"); - } - - @Override - protected boolean start() { - Log.i(TAG, "start()"); - if (sMcpService != null) { - Log.w(TAG, "McpService is already running"); - return true; - } - if (DBG) { - Log.d(TAG, " Create McpService Instance"); - } - - mContext = this; - mAdapterService = Objects.requireNonNull(AdapterService.getAdapterService(), - "AdapterService cannot be null when McpService starts"); - mNativeInterface = Objects.requireNonNull(McpNativeInterface.getInstance(), - "McpNativeInterface cannot be null when McpService starts"); - // Step 2: Get maximum number of connected audio devices - mMaxConnectedAudioDevices = mAdapterService.getMaxConnectedAudioDevices(); - Log.i(TAG, "Max connected audio devices set to " + mMaxConnectedAudioDevices); - //handle to synchronized tx and rx message - if (mHandler != null) { - mHandler = null; - } - HandlerThread thread = new HandlerThread("BluetoothMCSHandler"); - thread.start(); - Looper looper = thread.getLooper(); - mHandler = new McsMessageHandler(looper); - mNativeInterface.init(); - Log.d(TAG, "mcp native init done"); - IntentFilter filter = new IntentFilter(); - - filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); - mBondStateChangedReceiver = new BondStateChangedReceiver(); - mContext.registerReceiver(mBondStateChangedReceiver, filter); - setMcpService(this); - mMediaSessionManager = (MediaSessionManager) this.getSystemService( - this.MEDIA_SESSION_SERVICE); - //MediaControlManager.make(this); - Message msg = mHandler.obtainMessage(); - msg.what = MEDIA_CONTROL_MANAGER_INIT; - msg.obj = this; - mHandler.sendMessageDelayed(msg, 100); - return true; - } - - @Override - protected boolean stop() { - Log.i(TAG, "stop()"); - if (sMcpService == null) { - Log.w(TAG, "stop() called before start()"); - return true; - } - // Step 8: Mark service as stopped - setMcpService(null); - // Cleanup native interface - mNativeInterface.cleanup(); - mNativeInterface = null; - mContext.unregisterReceiver(mBondStateChangedReceiver); - // Clear AdapterService - mAdapterService = null; - mMaxConnectedAudioDevices = 1; - return true; - } - - private static void setMcpService(McpService instance) { - if (DBG) { - Log.d(TAG, "setMcpService(): set to: " + instance); - } - sMcpService = instance; - } - /** - * Get the McpService instance - * @return McpService instance - */ - - public synchronized static McpService getMcpService() { - if (sMcpService == null) { - Log.w(TAG, "getMcpService(): service is null"); - return null; - } - return sMcpService; - } - - public synchronized static void clearMcpInstance () { - Log.v(TAG, "clearing MCP instatnce"); - sInstance = null; - Log.v(TAG, "After clearing MCP instatnce "); - } - - public synchronized boolean MediaControlPointOpcodeUpdate(int feature) { - Message msg = mHandler.obtainMessage(); - msg.what = MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_UPDATE; - msg.arg1 = feature; - mHandler.sendMessage(msg); - return true; - } - - public synchronized boolean MediaControlPointUpdate(int value) { - Message msg = mHandler.obtainMessage(); - msg.what = MEDIA_CONTROL_POINT_UPDATE; - msg.arg1 = value; - mHandler.sendMessage(msg); - return true; - } - - private synchronized boolean MediaStateUpdate(int state) { - Message msg = mHandler.obtainMessage(); - msg.what = MEDIA_STATE_UPDATE; - msg.arg1 = state; - mHandler.sendMessage(msg); - return true; - } - - private synchronized boolean MediaPlayerNameUpdate(String name) { - Message msg = mHandler.obtainMessage(); - msg.what = MEDIA_PLAYER_NAME_UPDATE; - msg.obj = name; - mHandler.sendMessage(msg); - return true; - } - - private synchronized boolean PlayingOrderSupportedUpdate(int support) { - Message msg = mHandler.obtainMessage(); - msg.what = PLAYING_ORDER_SUPPORT_UPDATE; - msg.arg1 = support; - mHandler.sendMessage(msg); - return true; - } - - private synchronized boolean PlayingOrderUpdate(int support) { - Message msg = mHandler.obtainMessage(); - msg.what = PLAYING_ORDER_UPDATE; - msg.arg1 = support; - mHandler.sendMessage(msg); - return true; - } - - private synchronized boolean TrackChangedUpdate(int status) { - Message msg = mHandler.obtainMessage(); - msg.what = TRACK_CHANGED_UPDATE; - msg.arg1 = status; - mHandler.sendMessage(msg); - return true; - } - - private synchronized boolean TrackTitleUpdate(String title) { - Message msg = mHandler.obtainMessage(); - msg.what = TRACK_TITLE_UPDATE; - msg.obj = title; - mHandler.sendMessage(msg); - return true; - } - - private synchronized boolean TrackDurationUpdate(int duration) { - Message msg = mHandler.obtainMessage(); - msg.what = TRACK_DURATION_UPDATE; - msg.arg1 = duration; - mHandler.sendMessage(msg); - return true; - } - - private synchronized boolean TrackPositionUpdate(int position) { - Message msg = mHandler.obtainMessage(); - msg.what = TRACK_POSITION_UPDATE; - msg.arg1 = position; - mHandler.sendMessage(msg); - return true; - } - - private synchronized boolean ContentControlID(int ccid) { - Message msg = mHandler.obtainMessage(); - msg.what = CONTENT_CONTROL_ID_UPDATE; - msg.arg1 = ccid; - mHandler.sendMessage(msg); - return true; - } - - private synchronized int convertPlayStateToPlayStatus(PlaybackState state) { - int playStatus = PLAYSTATUS_ERROR; - switch (state.getState()) { - case PlaybackState.STATE_PLAYING: - playStatus = PLAYSTATUS_PLAYING; - break; - - case PlaybackState.STATE_CONNECTING: - case PlaybackState.STATE_NONE: - playStatus = PLAYSTATUS_STOPPED; - break; - - case PlaybackState.STATE_PAUSED: - case PlaybackState.STATE_BUFFERING: - case PlaybackState.STATE_STOPPED: - playStatus = PLAYSTATUS_PAUSED; - break; - - case PlaybackState.STATE_FAST_FORWARDING: - case PlaybackState.STATE_SKIPPING_TO_NEXT: - case PlaybackState.STATE_SKIPPING_TO_QUEUE_ITEM: - case PlaybackState.STATE_REWINDING: - case PlaybackState.STATE_SKIPPING_TO_PREVIOUS: - playStatus = PLAYSTATUS_SEEK; - break; - - case PlaybackState.STATE_ERROR: - playStatus = PLAYSTATUS_ERROR; - break; - - } - return playStatus; - } - - - /** - * Get the active device. - * - * @return the active device or null if no device is active - */ - public synchronized BluetoothDevice getActiveDevice() { - return mActiveDevice; - } - - public synchronized int getControlContentID() { - int ccid = 1; - return ccid; - } - - public synchronized void onConnectionStateChanged(BluetoothDevice device, int status) { - Log.v(TAG, "onConnectionStateChanged: address=" + device.toString()); - if (status == 0) - return; - Message msg = mHandler.obtainMessage(); - msg.what = EVENT_TYPE_CONNECTION_STATE_CHANGED; - msg.obj = device; - msg.arg2 = status; - mHandler.sendMessage(msg); - return; - } - - public synchronized boolean onMediaControlPointChangeReq(BluetoothDevice device, int state) { - Message msg = mHandler.obtainMessage(); - msg.what = EVENT_TYPE_MEDIA_CONTROL_POINT_CHANGED; - msg.obj = device; - msg.arg1 = state; - mHandler.sendMessage(msg); - return true; - } - - public synchronized boolean onTrackPositionChangeReq(int position) { - Message msg = mHandler.obtainMessage(); - msg.what = EVENT_TYPE_TRACK_POSITION_CHANGED; - msg.arg1 = position; - mHandler.sendMessage(msg); - return true; - } - - public synchronized boolean onPlayingOrderChangeReq(int order) { - Message msg = mHandler.obtainMessage(); - msg.what = EVENT_TYPE_PLAYING_ORDER_CHANGED; - msg.arg1 = order; - mHandler.sendMessage(msg); - return true; - } - - public synchronized boolean SetActiveDevices(BluetoothDevice device, int profile) { - Message msg = mHandler.obtainMessage(); - msg.what = ACTIVE_DEVICE_CHANGE; - msg.obj = device; - msg.arg1 = 0; // it will use to send mark two earbud address in one gp - msg.arg2 = profile; - mHandler.sendMessage(msg); - return true; - } - - public synchronized boolean OnMediaPlayerUpdate(int feature, int state, - int playingOrderSupport, int playingOrder, String playerName) { - Log.w(TAG, "OnMediaPlayerUpdate for player " + playerName); - ContentControlID(getControlContentID()); - /* - if (mMusicPlayerMap.containsKey(playerName)) { - Log.v(TAG, "Player is already there"); - } else { - newPlayer = new MusicPlayerDetail(); - mMusicPlayerMap.add(newPlayer, playerName); - }*/ - - MediaPlayerNameUpdate(playerName); - MediaStateUpdate(state); - //added default value as there is no api for gettiting supported feature from player - MediaControlPointOpcodeUpdate(DEFAULT_MEDIA_PLAYER_SUPPORTED_FEATURE); - PlayingOrderSupportedUpdate(DEFAULT_PLAYER_SUPPORTED_FEATURE); - PlayingOrderUpdate(DEFAULT_PLAYING_ORDER); - return true; - } - - public synchronized boolean OnMediaStateUpdate(int state) { - Log.w(TAG, "OnMediaStateUpdate state " + state); - MediaStateUpdate(state); - return true; - } - - public synchronized boolean OnTrackUpdate(int status, int duration, String title) { - Log.w(TAG, "OnTrackUpdate title " + title + " duration " + duration); - TrackChangedUpdate(status); - if (status != 0) { - TrackTitleUpdate(title); - TrackDurationUpdate(duration); - } - return true; - } - - public synchronized boolean OnTrackPositionUpdate(int position) { - Log.w(TAG, "OnTrackPositionUpdate position " + position); - TrackPositionUpdate(position); - return true; - } - - public synchronized boolean OnPlayingOrderUpdate(int order) { - Log.w(TAG, "OnPlayingOrderUpdate order " + order); - PlayingOrderUpdate(order); - return true; - } - //As apm is not implemented callback for apm above mention function - //implemented workaround - public synchronized void updateMetaData(MediaMetadata data) { - Log.w(TAG, "updateMetaData data " + data); - if (data == null) { - return; - } - //length //TBD to convert into int - int duration = (int)data.getLong(MediaMetadata.METADATA_KEY_DURATION); - String title = data.getString(MediaMetadata.METADATA_KEY_TITLE); - if (title != null && !(title.equals(mTrackTitle))) { - TrackChangedUpdate(1); - TrackTitleUpdate(title); - } - if (duration != mTrackDuration) - TrackDurationUpdate(duration); - } - - public synchronized void updatePlaybackState(PlaybackState playbackState) { - Log.w(TAG, "updatePlaybackState state " + playbackState); - int state = (int)convertPlayStateToPlayStatus(playbackState); - - if (state != PLAYSTATUS_ERROR && mState != state) { - if (state == PLAYSTATUS_STOPPED) - state = PLAYSTATUS_PAUSED; - MediaStateUpdate(state); - if (mCurrOpCode != -1) { - MediaControlPointUpdate(mCurrOpCode); - mCurrOpCode = -1; - } - } - int position = (int)playbackState.getPosition(); - - if (position != mTrackPosition) - TrackPositionUpdate(position); - float speed = playbackState.getPlaybackSpeed(); //for playback speed - } - - public synchronized void updatePlayerName(String packageName, boolean removed) { - Log.w(TAG, "updatePlayerName pkg " + packageName + " removed " + removed); - String name = null; - boolean changed = true; - int tCcid = 0; - int tPlayersupport = 0; - int tMediasupport = 0; - if ((removed && packageName == null ) || - removed && packageName.equals(mPlayerName)) { - //no active media player - MediaStateUpdate(PLAYSTATUS_STOPPED); - name = new String(""); - } else if (packageName != null && !packageName.equals(mPlayerName)) { - name = packageName; - tCcid = getControlContentID(); - tPlayersupport = DEFAULT_PLAYER_SUPPORTED_FEATURE; - tMediasupport = DEFAULT_MEDIA_PLAYER_SUPPORTED_FEATURE; - } else { - Log.d(TAG, "player name is same no need to update " + packageName); - changed = false; - } - if (changed) { - Log.d(TAG, "sending player change update"); - MediaControlPointOpcodeUpdate(tMediasupport); - PlayingOrderSupportedUpdate(tPlayersupport); - MediaPlayerNameUpdate(name); - ContentControlID(tCcid); - } - } - - private int McpPassthroughToKeyCode(int operation) { - mCurrOpCode = operation; - switch (operation) { - case MCP_MEDIA_CONTROL_OPCODE_PLAY: - return KeyEvent.KEYCODE_MEDIA_PLAY; - case MCP_MEDIA_CONTROL_OPCODE_PAUSE: - return KeyEvent.KEYCODE_MEDIA_PAUSE; - case MCP_MEDIA_CONTROL_OPCODE_FAST_REWIND: - return KeyEvent.KEYCODE_MEDIA_REWIND; - case MCP_MEDIA_CONTROL_OPCODE_FAST_FORWARD: - return KeyEvent.KEYCODE_MEDIA_FAST_FORWARD; - case MCP_MEDIA_CONTROL_OPCODE_STOP: - return KeyEvent.KEYCODE_MEDIA_STOP; - case MCP_MEDIA_CONTROL_OPCODE_PREV_TRACK: - return KeyEvent.KEYCODE_MEDIA_PREVIOUS; - case MCP_MEDIA_CONTROL_OPCODE_NEXT_TRACK: - return KeyEvent.KEYCODE_MEDIA_NEXT; - - // Fallthrough for all unknown key mappings - default: - mCurrOpCode = -1; - Log.d(TAG, "unknown passthrough"); - return KeyEvent.KEYCODE_UNKNOWN; - } - } - - private class BondStateChangedReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - if (!BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())) { - return; - } - int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, - BluetoothDevice.ERROR); - BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - Objects.requireNonNull(device, "ACTION_BOND_STATE_CHANGED with no EXTRA_DEVICE"); - if (sInstance != null) - bondStateChanged(device, state); - } - } - - /** - * Process a change in the bonding state for a device. - * - * @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}. - */ - @VisibleForTesting - void bondStateChanged(BluetoothDevice device, int bondState) { - if (DBG) { - 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) { - return; - } - //update to lower layer - Message msg = mHandler.obtainMessage(); - msg.what = BOND_STATE_CHANGE; - msg.obj = device; - msg.arg1 = bondState; - mHandler.sendMessage(msg); - return; - } - private boolean isMcpOnlyDevice(BluetoothDevice device) { - ParcelUuid ASCS_UUID = - ParcelUuid.fromString("0000184E-0000-1000-8000-00805F9B34FB"); - AdapterService adapterService = AdapterService.getAdapterService(); - boolean ascsSupported = - ArrayUtils.contains(adapterService.getRemoteUuids(device), ASCS_UUID); - AcmService mAcmService = AcmService.getAcmService(); - if (mAcmService != null) { - if (ascsSupported && - mAcmService.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED) { - return false; - } - } - Log.d(TAG,"McpOnly device"); - return true; - } - /** Handles MCS messages. */ - private final class McsMessageHandler extends Handler { - private McsMessageHandler(Looper looper) { - super(looper); - } - @Override - public synchronized void handleMessage(Message msg) { - if (DBG) Log.v(TAG, "McsMessageHandler: received message=" + msg.what); - - switch (msg.what) { - - case ACTIVE_DEVICE_CHANGE: - if (DBG) Log.v(TAG, "ACTIVE_DEVICE_CHANGE msg: " + (BluetoothDevice)msg.obj + " msg2 : " + msg.arg1); - mActiveDevice = (BluetoothDevice)msg.obj; - mNativeInterface.setActiveDevice((BluetoothDevice)msg.obj, msg.arg1, msg.arg2); - break; - - case BOND_STATE_CHANGE: - if (DBG) Log.v(TAG, "BOND_STATE_CHANGE msg: " + (BluetoothDevice)msg.obj + " msg2 : " + msg.arg1); - mNativeInterface.bondStateChange((BluetoothDevice)msg.obj, msg.arg2); - break; - - case PLAYING_ORDER_SUPPORT_UPDATE: - if (DBG) Log.v(TAG, "PLAYING_ORDER_SUPPORT_UPDATE msg: " + msg.arg1); - mSupportedPlayingOrder = msg.arg1; - mNativeInterface.playingOrder(msg.arg1); - break; - - case PLAYING_ORDER_UPDATE: - if (DBG) Log.v(TAG, "PLAYING_ORDER_UPDATE msg: " + msg.arg1); - mPlayingOrder = msg.arg1; - mNativeInterface.playingOrder(msg.arg1); - break; - - case MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_UPDATE: - if (DBG) Log.v(TAG, "MEDIA_CONTROL_POINT_OPCODES_SUPPORTED_UPDATE msg: " + msg.arg1); - mSupportedControlPoint = msg.arg1; - mNativeInterface.mediaControlPointOpcodeSupported(msg.arg1); - break; - - case MEDIA_CONTROL_POINT_UPDATE: - if (DBG) Log.v(TAG, "MEDIA_CONTROL_POINT_UPDATE msg: " + msg.arg1); - mControlPoint = msg.arg1; - mNativeInterface.mediaControlPoint(msg.arg1); - break; - - case MEDIA_PLAYER_NAME_UPDATE: - if (DBG) Log.v(TAG, "MEDIA_PLAYER_NAME_UPDATE msg: " + (String)msg.obj); - String name = (String)msg.obj; - mPlayerName = name; - if (name == null) - name = new String(""); - mNativeInterface.mediaPlayerName(name); - break; - - case MEDIA_STATE_UPDATE: - if (DBG) Log.v(TAG, "MEDIA_STATE_UPDATE msg: " + msg.arg1); - mState = msg.arg1; - mNativeInterface.mediaState(msg.arg1); - break; - - case TRACK_CHANGED_UPDATE: - if (DBG) Log.v(TAG, "TRACK_CHANGED_UPDATE msg: " + msg.arg1); - mNativeInterface.trackChanged(msg.arg1); - break; - - case TRACK_DURATION_UPDATE: - if (DBG) Log.v(TAG, "TRACK_DURATION_UPDATE msg: " + msg.arg1); - mTrackDuration = msg.arg1; - mNativeInterface.trackDuration(msg.arg1); - break; - - case TRACK_POSITION_UPDATE: - if (DBG) Log.v(TAG, "TRACK_POSITION_UPDATE msg: " + msg.arg1); - mTrackPosition = msg.arg1; - mNativeInterface.trackPosition(msg.arg1); - break; - - case TRACK_TITLE_UPDATE: - if (DBG) Log.v(TAG, "TRACK_TITLE_UPDATE msg: " + (String)msg.obj); - String title = (String)msg.obj; - mTrackTitle = title; - mNativeInterface.trackTitle(title); - break; - - - case CONTENT_CONTROL_ID_UPDATE: - if (DBG) Log.v(TAG, "CONTENT_CONTROL_ID_UPDATE msg: " + msg.arg1); - mCcid = msg.arg1; - mNativeInterface.contentControlId(mCcid); - break; - - case EVENT_TYPE_CONNECTION_STATE_CHANGED: - if (DBG) Log.v(TAG, "EVENT_TYPE_CONNECTION_STATE_CHANGED msg: " + msg.arg1); - //update to APM - break; - - case EVENT_TYPE_MEDIA_CONTROL_POINT_CHANGED: - if (DBG) Log.v(TAG, "EVENT_TYPE_MEDIA_CONTROL_POINT_CHANGED msg: " + msg.arg1); - BluetoothDevice mMcpDevice = (BluetoothDevice)msg.obj; - int code = McpPassthroughToKeyCode(msg.arg1); - - if (code != KeyEvent.KEYCODE_UNKNOWN) { - Log.w(TAG, "Valid passthrough, dispatch to media player"); - } - if (code == KeyEvent.KEYCODE_MEDIA_PLAY && - !Objects.equals(mMcpDevice, mActiveDevice) && !isMcpOnlyDevice(mMcpDevice)) { - ActiveDeviceManagerService mActiveDeviceManager = ActiveDeviceManagerService.get(); - if (mActiveDeviceManager != null) { - mActiveDeviceManager.setActiveDevice(mMcpDevice, ApmConst.AudioFeatures.MEDIA_AUDIO, false, true); - } - } - - // WAR- For FF/Rewind UC - if (code == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD || - code == KeyEvent.KEYCODE_MEDIA_REWIND) { - if (mState != PLAYSTATUS_SEEK) { - mState = PLAYSTATUS_SEEK; - MediaStateUpdate(mState); - MediaControlPointUpdate(mCurrOpCode); - mCurrOpCode = -1; - Log.w(TAG, "Update Playstate as seeking for FF/Rewind opcode"); - } - } else { - if (mState == PLAYSTATUS_SEEK) { // To-Do - } - } - - KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, code); - mMediaSessionManager.dispatchMediaKeyEvent(event, false); - event = new KeyEvent(KeyEvent.ACTION_UP, code); - mMediaSessionManager.dispatchMediaKeyEvent(event, false); - break; - - case EVENT_TYPE_PLAYING_ORDER_CHANGED: - if (DBG) Log.v(TAG, "EVENT_TYPE_PLAYING_ORDER_CHANGED msg: " + msg.arg1); - //update to APM - break; - - case EVENT_TYPE_TRACK_POSITION_CHANGED: - if (DBG) Log.v(TAG, "EVENT_TYPE_TRACK_POSITION_CHANGED msg: " + msg.arg1); - //update to APM - break; - - case MEDIA_CONTROL_MANAGER_INIT: - if (DBG) Log.v(TAG, "MEDIA_CONTROL_MANAGER_INIT"); - Context context = (Context)msg.obj; - MediaControlManager.make(context); - break; - - default: - Log.e(TAG, "unknown message! msg.what=" + msg.what); - break; - } - Log.v(TAG, "Exit handleMessage"); - } - } - - /** - * Binder object: must be a static class or memory leak may occur. - */ - - static class McpBinder extends Binder implements IProfileServiceBinder { - private McpService mService; - - private McpService getService() { - if (!Utils.checkCallerIsSystemOrActiveUser(TAG)) { - return null; - } - - if (mService != null && mService.isAvailable()) { - return mService; - } - return null; - } - - McpBinder(McpService svc) { - mService = svc; - } - - @Override - public synchronized void cleanup() { - mService = null; - } - } -} - - diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/pacsclient/PCService.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/pacsclient/PCService.java deleted file mode 100644 index f0847716f341415bdd9a1424b7132ee7b301c9da..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/pacsclient/PCService.java +++ /dev/null @@ -1,528 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/* - * 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. - */ - -package com.android.bluetooth.pc; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothCodecConfig; -import android.bluetooth.BluetoothProfile; -import android.bluetooth.BluetoothUuid; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.ParcelUuid; -import android.os.SystemProperties; -import android.os.UserManager; -import android.util.Log; - -import com.android.bluetooth.BluetoothMetricsProto; -import com.android.bluetooth.Utils; -import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.btservice.MetricsLogger; -import com.android.bluetooth.btservice.ProfileService; -import com.android.bluetooth.btservice.ServiceFactory; -import com.android.internal.annotations.VisibleForTesting; - -import java.util.Map; -import java.util.HashMap; -import java.util.List; -import java.util.Objects; - -public class PCService extends ProfileService{ - private static final String TAG = "PCService"; - private static final boolean DBG = true; - private static final int MAX_PACS_STATE_MACHINES = 50; - - private HandlerThread mStateMachinesThread; - private final HashMap mStateMachines = - new HashMap<>(); - private BroadcastReceiver mBondStateChangedReceiver; - - private AdapterService mAdapterService; - private PacsClientNativeInterface mNativeInterface; - private static PCService sInstance = null; - - public static final String ACTION_CONNECTION_STATE_CHANGED = - "com.android.bluetooth.pacs.action.CONNECTION_STATE_CHANGED"; - - /** - * Get the PCService instance. Returns null if the service hasn't been initialized. - */ - public static PCService get() { - return sInstance; - } - - @Override - protected IProfileServiceBinder initBinder() { - return null; - } - - @Override - protected void create() { - if (DBG) { - Log.d(TAG, "create()"); - } - } - - protected boolean start() { - - if (DBG) { - Log.d(TAG, "start()"); - } - if (sInstance != null) { - Log.w(TAG, "PCService is already running"); - return true; - } - - mAdapterService = Objects.requireNonNull(AdapterService.getAdapterService(), - "AdapterService cannot be null when PCService starts"); - mNativeInterface = Objects.requireNonNull(PacsClientNativeInterface.getInstance(), - "PacsClientNativeInterface cannot be null when PCService starts"); - - // Start handler thread for state machines - mStateMachines.clear(); - mStateMachinesThread = new HandlerThread("PCService.StateMachines"); - mStateMachinesThread.start(); - mNativeInterface.init(); - sInstance = this; - - IntentFilter filter = new IntentFilter(); - filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); - mBondStateChangedReceiver = new BondStateChangedReceiver(); - registerReceiver(mBondStateChangedReceiver, filter); - - return true; - } - - @Override - protected boolean stop() { - if (DBG) { - Log.d(TAG, "stop()"); - } - if (sInstance == null) { - Log.w(TAG, "stop() called before start()"); - return true; - } - - unregisterReceiver(mBondStateChangedReceiver); - - // Mark service as stopped - sInstance = null; - - // Destroy state machines and stop handler thread - synchronized (mStateMachines) { - for (PacsClientStateMachine sm : mStateMachines.values()) { - sm.doQuit(); - sm.cleanup(); - } - mStateMachines.clear(); - } - - if (mStateMachinesThread != null) { - mStateMachinesThread.quitSafely(); - mStateMachinesThread = null; - } - - // Cleanup native interface - mNativeInterface.cleanup(); - mNativeInterface = null; - - // Clear AdapterService - mAdapterService = null; - return true; - } - - @Override - protected void cleanup() { - if (DBG) { - Log.d(TAG, "cleanup()"); - } - } - - /** - * Get the PCService instance - * @return PCService instance - */ - public static synchronized PCService getPCService() { - if (sInstance == null) { - Log.w(TAG, "getPCService(): service is NULL"); - return null; - } - - return sInstance; - } - - /** - * Connects the pacs profile to the passed in device - * - * @param device is the device with which we will connect the pacs profile - * @return true if pacs profile successfully connected, false otherwise - */ - - public boolean connect(BluetoothDevice device) { - if (DBG) { - Log.d(TAG, "connect(): " + device); - } - if (device == null) { - return false; - } - - synchronized (mStateMachines) { - PacsClientStateMachine smConnect = getOrCreateStateMachine(device); - if (smConnect == null) { - Log.e(TAG, "Cannot connect to " + device + " : no state machine"); - return false; - } - smConnect.sendMessage(PacsClientStateMachine.CONNECT); - } - - return true; - } - - /** - * Disconnects pacs profile for the passed in device - * - * @param device is the device with which we want to disconnected the pacs profile - * @return true if pacs profile successfully disconnected, false otherwise - */ - - public boolean disconnect(BluetoothDevice device) { - if (DBG) { - Log.d(TAG, "disconnect(): " + device); - } - if (device == null) { - return false; - } - synchronized (mStateMachines) { - PacsClientStateMachine stateMachine = mStateMachines.get(device); - if (stateMachine == null) { - Log.w(TAG, "disconnect: device " + device + " not ever connected/connecting"); - return false; - } - int connectionState = stateMachine.getConnectionState(); - if (connectionState != BluetoothProfile.STATE_CONNECTED - && connectionState != BluetoothProfile.STATE_CONNECTING) { - Log.w(TAG, "disconnect: device " + device - + " not connected/connecting, connectionState=" + connectionState); - return false; - } - stateMachine.sendMessage(PacsClientStateMachine.DISCONNECT); - } - return true; - } - - /** - * start pacs disocvery for the passed in device - * - * @param device is the device with which we want to dicscoer the pacs - * @return true if pacs discovery is successfull, false otherwise - */ - - public boolean startPacsDiscovery(BluetoothDevice device) { - synchronized (mStateMachines) { - Log.i(TAG, "startPacsDiscovery: device=" + device + ", " + Utils.getUidPidString()); - final PacsClientStateMachine stateMachine = mStateMachines.get(device); - if (stateMachine == null) { - Log.w(TAG, "startPacsDiscovery: device " + device + " was never connected/connecting"); - return false; - } - if (stateMachine.getConnectionState() != BluetoothProfile.STATE_CONNECTED) { - Log.w(TAG, "startPacsDiscovery: profile not connected"); - return false; - } - stateMachine.sendMessage(PacsClientStateMachine.START_DISCOVERY); - } - return true; - } - - /** - * get sink pacs for the passed in device - * - * @param device is the device with which we want to get sink pacs - * @return sink pacs - */ - - public BluetoothCodecConfig[] getSinkPacs(BluetoothDevice device) { - synchronized (mStateMachines) { - final PacsClientStateMachine stateMachine = mStateMachines.get(device); - if (stateMachine == null) { - Log.e(TAG, "Failed to get Sink Pacs"); - return null; - } - return stateMachine.getSinkPacs(); - } - } - - /** - * get src pacs for the passed in device - * - * @param device is the device with which we want to get src pacs - * @return src pacs - */ - - public BluetoothCodecConfig[] getSrcPacs(BluetoothDevice device) { - synchronized (mStateMachines) { - final PacsClientStateMachine stateMachine = mStateMachines.get(device); - if (stateMachine == null) { - Log.e(TAG, "Failed to get Src Pacs"); - return null; - } - return stateMachine.getSinkPacs(); - } - } - - /** - * get sink locations for the passed in device - * - * @param device is the device with which we want to get sink location - * @return sink locations - */ - - public int getSinklocations(BluetoothDevice device) { - synchronized (mStateMachines) { - final PacsClientStateMachine stateMachine = mStateMachines.get(device); - if (stateMachine == null) { - Log.e(TAG, "Failed to get sink locations"); - return -1; - } - return stateMachine.getSinklocations(); - } - } - - /** - * get src locations for the passed in device - * - * @param device is the device with which we want to get src location - * @return src locations - */ - - public int getSrclocations(BluetoothDevice device) { - synchronized (mStateMachines) { - final PacsClientStateMachine stateMachine = mStateMachines.get(device); - if (stateMachine == null) { - Log.e(TAG, "Failed to get src locations"); - return -1; - } - return stateMachine.getSrclocations(); - } - } - - /** - * get available contexts for the passed in device - * - * @param device is the device with which we want to get available contexts - * @return avaialable contexts - */ - - public int getAvailableContexts(BluetoothDevice device) { - synchronized (mStateMachines) { - final PacsClientStateMachine stateMachine = mStateMachines.get(device); - if (stateMachine == null) { - Log.e(TAG, "Failed to get available contexts"); - return -1; - } - return stateMachine.getAvailableContexts(); - } - } - - /** - * get supported contexts for the passed in device - * - * @param device is the device with which we want to get supported contexts - * @return supported contexts - */ - - public int getSupportedContexts(BluetoothDevice device) { - synchronized (mStateMachines) { - final PacsClientStateMachine stateMachine = mStateMachines.get(device); - if (stateMachine == null) { - Log.e(TAG, "Failed to get supported contexts"); - return -1; - } - return stateMachine.getSupportedContexts(); - } - } - - /** - * Get the current connection state of the profile - * - * @param device is the remote bluetooth device - * @return {@link BluetoothProfile#STATE_DISCONNECTED} if this profile is disconnected, - * {@link BluetoothProfile#STATE_CONNECTING} if this profile is being connected, - * {@link BluetoothProfile#STATE_CONNECTED} if this profile is connected, or - * {@link BluetoothProfile#STATE_DISCONNECTING} if this profile is being disconnected - */ - public int getConnectionState(BluetoothDevice device) { - synchronized (mStateMachines) { - PacsClientStateMachine sm = mStateMachines.get(device); - if (sm == null) { - return BluetoothProfile.STATE_DISCONNECTED; - } - return sm.getConnectionState(); - } - } - - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean okToConnect(BluetoothDevice device) { - - int bondState = mAdapterService.getBondState(device); - if (bondState != BluetoothDevice.BOND_BONDED) { - Log.w(TAG, "okToConnect: return false, bondState=" + bondState); - return false; - } - return true; - } - - void messageFromNative(PacsClientStackEvent stackEvent) { - Objects.requireNonNull(stackEvent.device, - "Device should never be null, event: " + stackEvent); - - synchronized (mStateMachines) { - BluetoothDevice device = stackEvent.device; - PacsClientStateMachine sm = mStateMachines.get(device); - if (sm == null) { - if (stackEvent.type == PacsClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) { - switch (stackEvent.valueInt1) { - case PacsClientStackEvent.CONNECTION_STATE_CONNECTED: - case PacsClientStackEvent.CONNECTION_STATE_CONNECTING: - sm = getOrCreateStateMachine(device); - break; - default: - break; - } - } - } - if (sm == null) { - Log.e(TAG, "Cannot process stack event: no state machine: " + stackEvent); - return; - } - sm.sendMessage(PacsClientStateMachine.STACK_EVENT, stackEvent); - } - } - - void onConnectionStateChangedFromStateMachine(BluetoothDevice device, - int newState, int prevState) { - Log.d(TAG, "onConnectionStateChangedFromStateMachine for device: " + device - + " newState: " + newState); - - synchronized (mStateMachines) { - if (newState == BluetoothProfile.STATE_DISCONNECTED) { - int bondState = mAdapterService.getBondState(device); - if (bondState == BluetoothDevice.BOND_NONE) { - removeStateMachine(device); - } - } else if (newState == BluetoothProfile.STATE_CONNECTED) { - Log.d(TAG, "PacsClient get connected with renderer device: " + device); - } - } - } - - private class BondStateChangedReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - if (!BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())) { - return; - } - int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, - BluetoothDevice.ERROR); - BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - Objects.requireNonNull(device, "ACTION_BOND_STATE_CHANGED with no EXTRA_DEVICE"); - bondStateChanged(device, state); - } - } - - /** - * Process a change in the bonding state for a device. - * - * @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}. - */ - @VisibleForTesting - void bondStateChanged(BluetoothDevice device, int bondState) { - if (DBG) { - 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) { - return; - } - - synchronized (mStateMachines) { - PacsClientStateMachine sm = mStateMachines.get(device); - if (sm == null) { - return; - } - if (sm.getConnectionState() != BluetoothProfile.STATE_DISCONNECTED) { - return; - } - removeStateMachine(device); - } - } - - private void removeStateMachine(BluetoothDevice device) { - synchronized (mStateMachines) { - PacsClientStateMachine sm = mStateMachines.get(device); - if (sm == null) { - Log.w(TAG, "removeStateMachine: device " + device - + " does not have a state machine"); - return; - } - Log.i(TAG, "removeStateMachine: removing state machine for device: " + device); - sm.doQuit(); - sm.cleanup(); - mStateMachines.remove(device); - } - } - - private PacsClientStateMachine getOrCreateStateMachine(BluetoothDevice device) { - if (device == null) { - Log.e(TAG, "getOrCreateStateMachine failed: device cannot be null"); - return null; - } - synchronized (mStateMachines) { - PacsClientStateMachine sm = mStateMachines.get(device); - if (sm != null) { - return sm; - } - if (mStateMachines.size() >= MAX_PACS_STATE_MACHINES) { - Log.e(TAG, "Maximum number of PACS state machines reached: " - + MAX_PACS_STATE_MACHINES); - return null; - } - if (DBG) { - Log.d(TAG, "Creating a new state machine for " + device); - } - sm = PacsClientStateMachine.make(device, this, - mNativeInterface, mStateMachinesThread.getLooper()); - mStateMachines.put(device, sm); - return sm; - } - } - -} - diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/pacsclient/PacsClientNativeInterface.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/pacsclient/PacsClientNativeInterface.java deleted file mode 100644 index b7a4c516b15ccb4361bb7e5d047ba1d0c4f1b0f0..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/pacsclient/PacsClientNativeInterface.java +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/* - * 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. - */ - -/* - * Defines the native interface that is used by state machine/service to - * send or receive messages from the native stack. This file is registered - * for the native methods in the corresponding JNI C++ file. - */ -package com.android.bluetooth.pc; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothCodecConfig; -import android.util.Log; - -import com.android.bluetooth.Utils; -import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; - -/** - * PacsClient Native Interface to/from JNI. - */ -public class PacsClientNativeInterface { - private static final String TAG = "PacsClientNativeInterface"; - private static final boolean DBG = true; - private BluetoothAdapter mAdapter; - private int pacs_client_id = -1; - - @GuardedBy("INSTANCE_LOCK") - private static PacsClientNativeInterface sInstance; - private static final Object INSTANCE_LOCK = new Object(); - - static { - classInitNative(); - } - - private PacsClientNativeInterface() { - mAdapter = BluetoothAdapter.getDefaultAdapter(); - if (mAdapter == null) { - Log.wtf(TAG, "No Bluetooth Adapter Available"); - } - } - - /** - * Get singleton instance. - */ - public static PacsClientNativeInterface getInstance() { - synchronized (INSTANCE_LOCK) { - if (sInstance == null) { - sInstance = new PacsClientNativeInterface(); - } - return sInstance; - } - } - - /** - * Initializes the native interface. - * - * priorities to configure. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void init() { - initNative(); - } - - /** - * Cleanup the native interface. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void cleanup() { - cleanupNative(pacs_client_id); - pacs_client_id = -1; - } - - /** - * Initiates PacsClient connection to a remote device. - * - * @param device the remote device - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean connectPacsClient(BluetoothDevice device) { - return connectPacsClientNative(pacs_client_id, getByteAddress(device)); - } - - /** - * Disconnects PacsClient from a remote device. - * - * @param device the remote device - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean disconnectPacsClient(BluetoothDevice device) { - return disconnectPacsClientNative(pacs_client_id, getByteAddress(device)); - } - - /** - * Trigger service discovery for pacs - * - * @param device the remote device - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean startDiscoveryNative(BluetoothDevice device) { - return startDiscoveryNative(pacs_client_id, getByteAddress(device)); - } - - /** - * get available audio contexts. - * - * @param device the remote device - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean GetAvailableAudioContexts(BluetoothDevice device) { - return GetAvailableAudioContextsNative(pacs_client_id, getByteAddress(device)); - } - - private BluetoothDevice getDevice(byte[] address) { - if (mAdapter != null) { - return mAdapter.getRemoteDevice(address); - } else { - return null; - } - } - - 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(PacsClientStackEvent event) { - PCService service = PCService.getPCService(); - 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. - - private void OnInitialized(int state, int client_id) { - pacs_client_id = client_id; - } - - private void onConnectionStateChanged(byte[] address, int state) { - PacsClientStackEvent event = - new PacsClientStackEvent(PacsClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - event.device = getDevice(address); - event.valueInt1 = state; - - if (DBG) { - Log.d(TAG, "onConnectionStateChanged: " + event); - } - sendMessageToService(event); - } - - private void OnAudioContextAvailable(byte[] address, int available_contexts) { - PacsClientStackEvent event = - new PacsClientStackEvent(PacsClientStackEvent.EVENT_TYPE_AUDIO_CONTEXT_AVAIL); - event.device = getDevice(address); - event.valueInt1 = available_contexts; - - if (DBG) { - Log.d(TAG, "OnAudioContextAvailable: " + event); - } - sendMessageToService(event); - } - - private void onServiceDiscovery(BluetoothCodecConfig[] sink_pacs_array, - BluetoothCodecConfig[] src_pacs_array, - int sink_locations, int src_locations, - int available_contexts, int supported_contexts, - int status, byte[] address) { - if (status != 0) { - Log.e(TAG, "onServiceDiscovery: Failed" + status); - return; - } - PacsClientStackEvent event = new PacsClientStackEvent( - PacsClientStackEvent.EVENT_TYPE_SERVICE_DISCOVERY); - event.device = getDevice(address); - event.sinkCodecConfig = sink_pacs_array; - event.srcCodecConfig = src_pacs_array; - event.valueInt1 = sink_locations; - event.valueInt2 = src_locations; - event.valueInt3 = available_contexts; - event.valueInt4 = supported_contexts; - if (DBG) { - Log.d(TAG, "onServiceDiscovery: " + event); - } - for (BluetoothCodecConfig codecConfig : - sink_pacs_array) { - Log.d(TAG, "sink_pacs_array: " + codecConfig); - } - for (BluetoothCodecConfig codecConfig : - src_pacs_array) { - Log.d(TAG, "src_pacs_array: " + codecConfig); - } - if (DBG) { - Log.d(TAG, "sink locs: " + sink_locations + "src locs:" + src_locations); - Log.d(TAG, "avail ctxts: " + available_contexts + "supp ctxts: " + supported_contexts); - } - - sendMessageToService(event); - } - - // Native methods that call into the JNI interface - private static native void classInitNative(); - private native void initNative(); - private native void cleanupNative(int client_id); - private native boolean connectPacsClientNative(int client_id, byte[] address); - private native boolean disconnectPacsClientNative(int client_id, byte[] address); - private native boolean startDiscoveryNative(int client_id, byte[] address); - private native boolean GetAvailableAudioContextsNative(int client_id, byte[] address); -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/pacsclient/PacsClientStackEvent.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/pacsclient/PacsClientStackEvent.java deleted file mode 100644 index ff1be613fd57a3eacbb85c4983e5aa39ec7cc3e8..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/pacsclient/PacsClientStackEvent.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/* - * 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. - */ - -package com.android.bluetooth.pc; - -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothCodecConfig; - - -/** - * Stack event sent via a callback from JNI to Java, or generated - * internally by the Pacs Cleint State Machine. - */ -public class PacsClientStackEvent { - // Event types for STACK_EVENT message (coming from native) - private static final int EVENT_TYPE_NONE = 0; - public static final int EVENT_TYPE_INITIALIZED = 1; - public static final int EVENT_TYPE_CONNECTION_STATE_CHANGED = 2; - public static final int EVENT_TYPE_SERVICE_DISCOVERY = 3; - public static final int EVENT_TYPE_AUDIO_CONTEXT_AVAIL = 4; - - // Do not modify without updating the HAL bt_pacs_client.h files. - // Match up with enum class ConnectionState of bt_pacs_client.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 BluetoothCodecConfig[] sinkCodecConfig; - public BluetoothCodecConfig[] srcCodecConfig; - public int valueInt1; - public int valueInt2; - public int valueInt3; - public int valueInt4; - - PacsClientStackEvent(int type) { - this.type = type; - } - - @Override - public String toString() { - // event dump - StringBuilder result = new StringBuilder(); - result.append("PacsClientStackEvent {type:" + eventTypeToString(type)); - result.append(", device:" + device); - result.append(", value1:" + valueInt1); - result.append(", value2:" + valueInt2); - result.append(", value3:" + valueInt3); - result.append(", value4:" + valueInt4); - if (sinkCodecConfig != null) { - result.append(", sinkCodecConfig:" + sinkCodecConfig); - } - if (srcCodecConfig != null) { - result.append(", srcCodecConfig:" + srcCodecConfig); - } - result.append("}"); - return result.toString(); - } - - private static String eventTypeToString(int type) { - switch (type) { - case EVENT_TYPE_NONE: - return "EVENT_TYPE_NONE"; - case EVENT_TYPE_CONNECTION_STATE_CHANGED: - return "EVENT_TYPE_CONNECTION_STATE_CHANGED"; - case EVENT_TYPE_INITIALIZED: - return "EVENT_TYPE_INITIALIZED"; - case EVENT_TYPE_AUDIO_CONTEXT_AVAIL: - return "EVENT_TYPE_AUDIO_CONTEXT_AVAIL"; - case EVENT_TYPE_SERVICE_DISCOVERY: - return "EVENT_TYPE_SERVICE_DISCOVERY"; - default: - return "EVENT_TYPE_UNKNOWN:" + type; - } - } -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/pacsclient/PacsClientStateMachine.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/pacsclient/PacsClientStateMachine.java deleted file mode 100644 index 23ff16eac5b54b111dac5b934e49ecf1efb9a3d6..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/pacsclient/PacsClientStateMachine.java +++ /dev/null @@ -1,703 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/* - * 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. - */ - -/** - * Bluetooth PacsClient 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.pc; - -import static android.Manifest.permission.BLUETOOTH_CONNECT; - -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; -import com.android.bluetooth.Utils; -import android.bluetooth.BluetoothCodecConfig; -import android.content.Intent; -import android.os.Looper; -import android.os.Message; -import android.util.Log; -import android.content.Context; - -import com.android.bluetooth.btservice.ProfileService; -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Scanner; - -final class PacsClientStateMachine extends StateMachine { - private static final boolean DBG = false; - private static final String TAG = "PacsClientStateMachine"; - - static final int CONNECT = 1; - static final int DISCONNECT = 2; - static final int START_DISCOVERY = 3; - static final int GET_AVAILABLE_CONTEXTS = 4; - @VisibleForTesting - static final int STACK_EVENT = 101; - private static final int 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 mLastConnectionState = -1; - - private PCService mService; - private PacsClientNativeInterface mNativeInterface; - private BluetoothCodecConfig[] mSinkPacsConfig; - private BluetoothCodecConfig[] mSrcPacsConfig; - private int mSinkLocations; - private int mSrcLocations; - private int mAvailableContexts; - private int mSupportedContexts; - private Context mContext; - - private final BluetoothDevice mDevice; - - PacsClientStateMachine(BluetoothDevice device, PCService svc, - PacsClientNativeInterface nativeInterface, Looper looper) { - super(TAG, looper); - mDevice = device; - mService = svc; - mNativeInterface = nativeInterface; - - mDisconnected = new Disconnected(); - mConnecting = new Connecting(); - mDisconnecting = new Disconnecting(); - mConnected = new Connected(); - - addState(mDisconnected); - addState(mConnecting); - addState(mDisconnecting); - addState(mConnected); - - setInitialState(mDisconnected); - } - - static PacsClientStateMachine make(BluetoothDevice device, PCService svc, - PacsClientNativeInterface nativeInterface, Looper looper) { - Log.i(TAG, "make for device " + device); - PacsClientStateMachine PacsClientSm = new PacsClientStateMachine(device, svc, - nativeInterface, looper); - PacsClientSm.start(); - return PacsClientSm; - } - - public void doQuit() { - log("doQuit for device " + mDevice); - quitNow(); - } - - public void cleanup() { - log("cleanup for device " + mDevice); - } - - @VisibleForTesting - class Disconnected extends State { - @Override - public void enter() { - Log.i(TAG, "Enter Disconnected(" + mDevice + "): " + messageWhatToString( - getCurrentMessage().what)); - - removeDeferredMessages(DISCONNECT); - - if (mLastConnectionState != -1) { - // Don't broadcast during startup - broadcastConnectionState(BluetoothProfile.STATE_DISCONNECTED, - mLastConnectionState); - } - cleanupDevice(); - } - - @Override - public void exit() { - Log.i(TAG, "Exit Disconnected(" + mDevice + "): " + messageWhatToString( - getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_DISCONNECTED; - } - - @Override - public boolean processMessage(Message message) { - log("Disconnected process message(" + mDevice + "): " + messageWhatToString( - message.what)); - - switch (message.what) { - case CONNECT: - log("Connecting to " + mDevice); - if (!mNativeInterface.connectPacsClient(mDevice)) { - Log.e(TAG, "Disconnected: error connecting to " + mDevice); - break; - } - if (mService.okToConnect(mDevice)) { - transitionTo(mConnecting); - } else { - // Reject the request and stay in Disconnected state - Log.w(TAG, "Outgoing PacsClient Connecting request rejected: " + mDevice); - } - break; - case DISCONNECT: - Log.w(TAG, "Disconnected: DISCONNECT ignored: " + mDevice); - break; - case STACK_EVENT: - PacsClientStackEvent event = (PacsClientStackEvent) message.obj; - if (DBG) { - Log.d(TAG, "Disconnected: stack event: " + event); - } - if (!mDevice.equals(event.device)) { - Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); - } - switch (event.type) { - case PacsClientStackEvent.EVENT_TYPE_INITIALIZED: - if(event.valueInt1 != 0) { - Log.e(TAG, "Disconnected: error initializing PACS"); - return NOT_HANDLED; - } - Log.d(TAG, "PACS Initialized succesfully (DISCONNECTED)"); - break; - case PacsClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - processConnectionEvent(event.valueInt1); - break; - default: - Log.e(TAG, "Disconnected: ignoring stack event: " + event); - break; - } - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - - // in Disconnected state - private void processConnectionEvent(int state) { - switch (state) { - case PacsClientStackEvent.CONNECTION_STATE_DISCONNECTED: - Log.w(TAG, "Ignore PacsClient DISCONNECTED event: " + mDevice); - break; - case PacsClientStackEvent.CONNECTION_STATE_CONNECTING: - if (mService.okToConnect(mDevice)) { - Log.i(TAG, "Incoming PacsClient Connecting request accepted: " + mDevice - + "state: " + state); - transitionTo(mConnecting); - } else { - // Reject the connection and stay in Disconnected state itself - Log.w(TAG, "Incoming PacsClient Connecting request rejected: " + mDevice - + "state: " + state); - mNativeInterface.disconnectPacsClient(mDevice); - } - break; - case PacsClientStackEvent.CONNECTION_STATE_CONNECTED: - Log.w(TAG, "PacsClient Connected from Disconnected state: " + mDevice - + "state: " + state); - if (mService.okToConnect(mDevice)) { - Log.i(TAG, "Incoming PacsClient Connected request accepted: " + mDevice - + "state: " + state); - transitionTo(mConnected); - } else { - // Reject the connection and stay in Disconnected state itself - Log.w(TAG, "Incoming PacsClient Connected request rejected: " + mDevice - + "state: " + state); - mNativeInterface.disconnectPacsClient(mDevice); - } - break; - case PacsClientStackEvent.CONNECTION_STATE_DISCONNECTING: - Log.w(TAG, "Ignore PacsClient DISCONNECTING event: " + mDevice - + "state: " + state); - break; - default: - Log.e(TAG, "Incorrect state: " + state + " device: " + mDevice - + "state: " + state); - break; - } - } - } - - @VisibleForTesting - class Connecting extends State { - @Override - public void enter() { - Log.i(TAG, "Enter Connecting(" + mDevice + "): " - + messageWhatToString(getCurrentMessage().what)); - sendMessageDelayed(CONNECT_TIMEOUT, sConnectTimeoutMs); - broadcastConnectionState(BluetoothProfile.STATE_CONNECTING, mLastConnectionState); - } - - @Override - public void exit() { - Log.i(TAG, "Exit Connecting(" + mDevice + "): " - + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_CONNECTING; - removeMessages(CONNECT_TIMEOUT); - } - - @Override - public boolean processMessage(Message message) { - log("Connecting process message(" + mDevice + "): " - + messageWhatToString(message.what)); - - switch (message.what) { - case CONNECT: - deferMessage(message); - break; - case CONNECT_TIMEOUT: - Log.w(TAG, "Connecting connection timeout: " + mDevice); - mNativeInterface.disconnectPacsClient(mDevice); - PacsClientStackEvent disconnectEvent = - new PacsClientStackEvent( - PacsClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - disconnectEvent.device = mDevice; - disconnectEvent.valueInt1 = PacsClientStackEvent.CONNECTION_STATE_DISCONNECTED; - sendMessage(STACK_EVENT, disconnectEvent); - break; - case DISCONNECT: - log("Connecting: connection canceled to " + mDevice); - mNativeInterface.disconnectPacsClient(mDevice); - transitionTo(mDisconnected); - break; - case START_DISCOVERY: - case GET_AVAILABLE_CONTEXTS: - deferMessage(message); - break; - case STACK_EVENT: - PacsClientStackEvent event = (PacsClientStackEvent) message.obj; - log("Connecting: stack event: " + event); - if (!mDevice.equals(event.device)) { - Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); - } - switch (event.type) { - case PacsClientStackEvent.EVENT_TYPE_INITIALIZED: - if(event.valueInt1 != 0) { - Log.e(TAG, "Disconnected: error initializing PACS"); - return NOT_HANDLED; - } - Log.d(TAG, "PACS Initialized succesfully (CONNECTING)"); - break; - case PacsClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - processConnectionEvent(event.valueInt1); - break; - case PacsClientStackEvent.EVENT_TYPE_SERVICE_DISCOVERY: - case PacsClientStackEvent.EVENT_TYPE_AUDIO_CONTEXT_AVAIL: - deferMessage(message); - break; - default: - Log.e(TAG, "Disconnected: ignoring stack event: " + event); - break; - } - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - - // in Connecting state - private void processConnectionEvent(int state) { - switch (state) { - case PacsClientStackEvent.CONNECTION_STATE_DISCONNECTED: - Log.w(TAG, "Connecting device disconnected: " + mDevice); - transitionTo(mDisconnected); - break; - case PacsClientStackEvent.CONNECTION_STATE_CONNECTED: - transitionTo(mConnected); - break; - case PacsClientStackEvent.CONNECTION_STATE_CONNECTING: - break; - case PacsClientStackEvent.CONNECTION_STATE_DISCONNECTING: - Log.w(TAG, "Connecting interrupted: device is disconnecting: " + mDevice); - transitionTo(mDisconnecting); - break; - default: - Log.e(TAG, "Incorrect state: " + state); - break; - } - } - } - - @VisibleForTesting - class Disconnecting extends State { - @Override - public void enter() { - Log.i(TAG, "Enter Disconnecting(" + mDevice + "): " - + messageWhatToString(getCurrentMessage().what)); - sendMessageDelayed(CONNECT_TIMEOUT, sConnectTimeoutMs); - broadcastConnectionState(BluetoothProfile.STATE_DISCONNECTING, mLastConnectionState); - } - - @Override - public void exit() { - Log.i(TAG, "Exit Disconnecting(" + mDevice + "): " - + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_DISCONNECTING; - removeMessages(CONNECT_TIMEOUT); - } - - @Override - public boolean processMessage(Message message) { - log("Disconnecting process message(" + mDevice + "): " - + messageWhatToString(message.what)); - - switch (message.what) { - case CONNECT: - deferMessage(message); - break; - case CONNECT_TIMEOUT: { - Log.w(TAG, "Disconnecting connection timeout: " + mDevice); - mNativeInterface.disconnectPacsClient(mDevice); - PacsClientStackEvent disconnectEvent = - new PacsClientStackEvent( - PacsClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - disconnectEvent.device = mDevice; - disconnectEvent.valueInt1 = PacsClientStackEvent.CONNECTION_STATE_DISCONNECTED; - sendMessage(STACK_EVENT, disconnectEvent); - break; - } - case START_DISCOVERY: - case GET_AVAILABLE_CONTEXTS: - case DISCONNECT: - deferMessage(message); - break; - case STACK_EVENT: - PacsClientStackEvent event = (PacsClientStackEvent) message.obj; - log("Disconnecting: stack event: " + event); - if (!mDevice.equals(event.device)) { - Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); - } - switch (event.type) { - case PacsClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - processConnectionEvent(event.valueInt1); - break; - case PacsClientStackEvent.EVENT_TYPE_SERVICE_DISCOVERY: - case PacsClientStackEvent.EVENT_TYPE_AUDIO_CONTEXT_AVAIL: - deferMessage(message); - break; - default: - Log.e(TAG, "Disconnected: ignoring stack event: " + event); - break; - } - - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - - // in Disconnecting state - private void processConnectionEvent(int state) { - switch (state) { - case PacsClientStackEvent.CONNECTION_STATE_DISCONNECTED: - Log.i(TAG, "Disconnected: " + mDevice); - transitionTo(mDisconnected); - break; - case PacsClientStackEvent.CONNECTION_STATE_CONNECTED: - if (mService.okToConnect(mDevice)) { - Log.w(TAG, "Disconnecting interrupted: device is connected: " + mDevice); - transitionTo(mConnected); - } else { - // Reject the connection and stay in Disconnecting state - Log.w(TAG, "Incoming PacsClient Connected request rejected: " + mDevice); - mNativeInterface.disconnectPacsClient(mDevice); - } - break; - case PacsClientStackEvent.CONNECTION_STATE_CONNECTING: - if (mService.okToConnect(mDevice)) { - Log.i(TAG, "Disconnecting interrupted: try to reconnect: " + mDevice); - transitionTo(mConnecting); - } else { - // Reject the connection and stay in Disconnecting state - Log.w(TAG, "Incoming PacsClient Connecting request rejected: " + mDevice); - mNativeInterface.disconnectPacsClient(mDevice); - } - break; - case PacsClientStackEvent.CONNECTION_STATE_DISCONNECTING: - break; - default: - Log.e(TAG, "Incorrect state: " + state); - break; - } - } - } - - @VisibleForTesting - class Connected extends State { - @Override - public void enter() { - Log.i(TAG, "Enter Connected(" + mDevice + "): " - + messageWhatToString(getCurrentMessage().what)); - removeDeferredMessages(CONNECT); - mNativeInterface.startDiscoveryNative(mDevice); - broadcastConnectionState(BluetoothProfile.STATE_CONNECTED, mLastConnectionState); - } - - @Override - public void exit() { - Log.i(TAG, "Exit Connected(" + mDevice + "): " - + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_CONNECTED; - } - - @Override - public boolean processMessage(Message message) { - log("Connected process message(" + mDevice + "): " - + messageWhatToString(message.what)); - - switch (message.what) { - case CONNECT: - Log.w(TAG, "Connected: CONNECT ignored: " + mDevice); - break; - case DISCONNECT: - log("Disconnecting from " + mDevice); - if (!mNativeInterface.disconnectPacsClient(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); - break; - case START_DISCOVERY: - log("sending start discovery to " + mDevice); - if (!mNativeInterface.startDiscoveryNative(mDevice)) { - Log.e(TAG, "connected: error sending startdiscovery to " + mDevice); - } - break; - case GET_AVAILABLE_CONTEXTS: - log("get available audio conxtes from " + mDevice); - mNativeInterface.GetAvailableAudioContexts(mDevice); - break; - case STACK_EVENT: - PacsClientStackEvent event = (PacsClientStackEvent) message.obj; - log("Connected: stack event: " + event); - if (!mDevice.equals(event.device)) { - Log.wtf(TAG, "Device(" + mDevice + "): event mismatch: " + event); - } - switch (event.type) { - case PacsClientStackEvent.EVENT_TYPE_INITIALIZED: - deferMessage(message); - break; - case PacsClientStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - processConnectionEvent(event.valueInt1); - break; - case PacsClientStackEvent.EVENT_TYPE_SERVICE_DISCOVERY: - processPacsRecordEvent(event.sinkCodecConfig, event.srcCodecConfig, - event.valueInt1, event.valueInt2, - event.valueInt3, event.valueInt4); - break; - case PacsClientStackEvent.EVENT_TYPE_AUDIO_CONTEXT_AVAIL: - mAvailableContexts = event.valueInt1; - break; - default: - Log.e(TAG, "Disconnected: ignoring stack event: " + event); - break; - } - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - - // in Connected state - private void processConnectionEvent(int state) { - switch (state) { - case PacsClientStackEvent.CONNECTION_STATE_DISCONNECTED: - Log.i(TAG, "Disconnected from " + mDevice); - transitionTo(mDisconnected); - break; - case PacsClientStackEvent.CONNECTION_STATE_DISCONNECTING: - Log.i(TAG, "Disconnecting from " + mDevice); - transitionTo(mDisconnecting); - break; - default: - Log.e(TAG, "Connection State Device: " + mDevice + " bad state: " + state); - break; - } - } - - private void processPacsRecordEvent(BluetoothCodecConfig[] sinkCodecConfig, - BluetoothCodecConfig[] srcCodecConfig, - int sink_locations, int src_locations, - int available_contexts, int supported_contexts) { - mSinkPacsConfig = sinkCodecConfig; - mSrcPacsConfig = srcCodecConfig; - mSinkLocations = sink_locations; - mSrcLocations = src_locations; - mAvailableContexts = available_contexts; - mSupportedContexts = supported_contexts; - } - } - - 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; - } - } - - BluetoothDevice getDevice() { - return mDevice; - } - - synchronized boolean isConnected() { - return getCurrentState() == mConnected; - } - - - private void cleanupDevice() { - log("cleanup device " + mDevice); - mSinkLocations = -1; - mSrcLocations = -1; - mAvailableContexts = -1; - mSupportedContexts = -1; - } - - BluetoothCodecConfig[] getSinkPacs() { - synchronized (this) { - return mSinkPacsConfig; - } - } - - BluetoothCodecConfig[] getSrcPacs() { - synchronized (this) { - return mSrcPacsConfig; - } - } - - int getSinklocations() { - synchronized (this) { - return mSinkLocations; - } - } - - int getSrclocations() { - synchronized (this) { - return mSrcLocations; - } - } - - int getAvailableContexts() { - synchronized (this) { - return mAvailableContexts; - } - } - - int getSupportedContexts() { - synchronized (this) { - return mSupportedContexts; - } - } - - // This method does not check for error condition (newState == prevState) - private void broadcastConnectionState(int newState, int prevState) { - log("Connection state " + mDevice + ": " + profileStateToString(prevState) - + "->" + profileStateToString(newState)); - mService.onConnectionStateChangedFromStateMachine(mDevice, newState, prevState); - Intent intent = new Intent(PCService.ACTION_CONNECTION_STATE_CHANGED); - intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); - intent.putExtra(BluetoothProfile.EXTRA_STATE, newState); - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - mService.sendBroadcast(intent, BLUETOOTH_CONNECT, Utils.getTempAllowlistBroadcastOptions()); - } - - 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); - } - - @Override - protected void log(String msg) { - if (DBG) { - super.log(msg); - } - } -} diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/vcp/VcpController.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/vcp/VcpController.java deleted file mode 100644 index ab29aa0317812deac66962e37f26f2d7e8495d1f..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/vcp/VcpController.java +++ /dev/null @@ -1,733 +0,0 @@ -/* - *Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/* - * 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. - */ - -package com.android.bluetooth.vcp; - -import static android.Manifest.permission.BLUETOOTH_CONNECT; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; -import android.bluetooth.BluetoothUuid; -import android.bluetooth.BluetoothVcp; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.ParcelUuid; -import android.os.SystemProperties; -import android.os.UserManager; -import android.util.Log; - -import com.android.bluetooth.apm.ApmConst; -import com.android.bluetooth.apm.DeviceProfileMap; -import com.android.bluetooth.apm.VolumeManager; -import com.android.bluetooth.acm.AcmService; -import com.android.bluetooth.BluetoothMetricsProto; -import com.android.bluetooth.Utils; -import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.btservice.MetricsLogger; -import com.android.bluetooth.btservice.ProfileService; -import com.android.bluetooth.btservice.ServiceFactory; -import com.android.bluetooth.groupclient.GroupService; -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.ArrayUtils; - -import java.util.ArrayList; -import java.util.Map; -import java.util.HashMap; -import java.util.List; -import java.util.Objects; - -public class VcpController { - private static final String TAG = "VcpController"; - private static final boolean DBG = true; - private static final int MAX_VCP_STATE_MACHINES = 50; - private static final int VCP_MIN_VOL = 0; - private static final int VCP_MAX_VOL = 255; - private static final String ACTION_CONNECT_DEVICE = - "com.android.bluetooth.vcp.test.action.CONNECT_DEVICE"; - private static final String ACTION_DISCONNECT_DEVICE = - "com.android.bluetooth.vcp.test.action.DISCONNECT_DEVICE"; - - private HandlerThread mStateMachinesThread; - private final HashMap mStateMachines = - new HashMap<>(); - private HashMap mConnectionMode = new HashMap(); - private BroadcastReceiver mBondStateChangedReceiver; - - private AdapterService mAdapterService; - private VcpControllerNativeInterface mNativeInterface; - private DeviceProfileMap mDpm; - private AcmService mAcmService; - private static VcpController sInstance = null; - private Context mContext; - private boolean mPtsTest = false; - private final BroadcastReceiver mVcpControllerTestReceiver = new VcpControllerTestReceiver(); - - private VcpController(Context context) { - if (DBG) { - Log.d(TAG, "Create VcpController Instance"); - } - - mContext = context; - mAdapterService = Objects.requireNonNull(AdapterService.getAdapterService(), - "AdapterService cannot be null when VcpController starts"); - mNativeInterface = Objects.requireNonNull(VcpControllerNativeInterface.getInstance(), - "VcpControllerNativeInterface cannot be null when VcpController starts"); - - // Start handler thread for state machines - mStateMachines.clear(); - mStateMachinesThread = new HandlerThread("VcpController.StateMachines"); - mStateMachinesThread.start(); - mNativeInterface.init(); - - IntentFilter filter = new IntentFilter(); - filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); - mBondStateChangedReceiver = new BondStateChangedReceiver(); - mContext.registerReceiver(mBondStateChangedReceiver, filter); - - if (mAdapterService.isAdvBCAAudioFeatEnabled()) { - Log.d(TAG, "Adv BCA Audio supported, enable VCP for broadcast"); - SystemProperties.set("persist.vendor.service.bt.vcpForBroadcast", "true"); - } else { - SystemProperties.set("persist.vendor.service.bt.vcpForBroadcast", "false"); - } - mPtsTest = SystemProperties.getBoolean("persist.vendor.service.bt.vcp_controller.pts", false); - if (mPtsTest) { - Log.d(TAG, "Register for VcpControllerTestReceiver"); - IntentFilter filter2 = new IntentFilter(); - filter2.addAction(ACTION_CONNECT_DEVICE); - filter2.addAction(ACTION_DISCONNECT_DEVICE); - context.registerReceiver(mVcpControllerTestReceiver, filter2); - } - } - - /** - * Make VcpController instance and Initialize - * - * @param context: application context - * @return VcpController instance - */ - public static VcpController make(Context context) { - Log.v(TAG, "make"); - - if(sInstance == null) { - sInstance = new VcpController(context); - } - Log.v(TAG, "Exit make"); - return sInstance; - } - - /** - * Get the VcpController instance, which provides the public APIs - * to volume control operation via VCP connection - * - * @return VcpController instance - */ - public static synchronized VcpController getVcpController() { - if (sInstance == null) { - Log.w(TAG, "getVcpController(): service is NULL"); - return null; - } - - return sInstance; - } - - public static void clearVcpInstance () { - Log.v(TAG, "clearing VCP instatnce"); - sInstance = null; - Log.v(TAG, "After clearing VCP instatnce "); - } - - public synchronized void doQuit() { - if (DBG) { - Log.d(TAG, "doQuit()"); - } - if (sInstance == null) { - Log.w(TAG, "doQuit() called before make()"); - return; - } - - // Cleanup native interface - mNativeInterface.cleanup(); - mNativeInterface = null; - mContext.unregisterReceiver(mBondStateChangedReceiver); - if (mPtsTest) { - mContext.unregisterReceiver(mVcpControllerTestReceiver); - } - - // Mark service as stopped - sInstance = null; - - // Destroy state machines and stop handler thread - synchronized (mStateMachines) { - for (VcpControllerStateMachine sm : mStateMachines.values()) { - sm.doQuit(); - sm.cleanup(); - } - mStateMachines.clear(); - } - - if (mStateMachinesThread != null) { - mStateMachinesThread.quitSafely(); - mStateMachinesThread = null; - } - - // Clear AdapterService - mAdapterService = null; - } - - /** - * Connect with the remote device for unicast or broadcast mode. - * - * @param device: the remote device to connect - * @param mode: connection mode: can be any of - * {@link #BluetoothVcp.MODE_UNICAST} or {@link #BluetoothVcp.MODE_BROADCAST} - * - * @return true if connect is accepted, false if connect request is rejected. - */ - public boolean connect(BluetoothDevice device, int mode) { - if (DBG) { - Log.d(TAG, "connect(): " + device + ", mode: " + mode); - } - if (device == null) { - return false; - } - - synchronized (mStateMachines) { - VcpControllerStateMachine smConnect = getOrCreateStateMachine(device); - if (smConnect == null) { - Log.e(TAG, "Cannot connect to " + device + " : no state machine"); - } - - int preConnMode; - if (mConnectionMode.containsKey(device)) { - preConnMode = mConnectionMode.get(device); - if ((preConnMode & mode) == 0) { - int connMode = preConnMode | mode; - mConnectionMode.put(device, connMode); - broadcastConnectionModeChanged(device, connMode); - } - } else { - preConnMode = BluetoothVcp.MODE_NONE; - mConnectionMode.put(device, mode); - broadcastConnectionModeChanged(device, mode); - } - - if (smConnect.getConnectionState() != BluetoothProfile.STATE_CONNECTED) { - smConnect.sendMessage(VcpControllerStateMachine.CONNECT, device); - } else { - if (preConnMode == BluetoothVcp.MODE_BROADCAST && - mode == BluetoothVcp.MODE_UNICAST) { - Log.d(TAG, "VCP connection from BROADCAST-ONLY to UNICAST_BROADCAST: " + device); - } - } - } - - return true; - } - - /** - * Disconnect with the remote device for unicast or broadcast mode. - * - * @param device: the remote device to connect - * @param mode: connection mode: can be any of - * {@link #BluetoothVcp.MODE_UNICAST} or {@link #BluetoothVcp.MODE_BROADCAST} - * - * @return true if disconnect is accepted, false if disconnect is rejected. - */ - public boolean disconnect(BluetoothDevice device, int mode) { - if (DBG) { - Log.d(TAG, "disconnect(): " + device + ", mode: " + mode); - } - if (device == null) { - return false; - } - - synchronized (mStateMachines) { - int preConnMode = getConnectionMode(device); - int connMode = BluetoothVcp.MODE_NONE; - - if ((preConnMode & mode) != 0) { - connMode = preConnMode & ~mode; - broadcastConnectionModeChanged(device, connMode); - } else { - Log.d(TAG, "disconnect ignore as Vcp is not connected for mode: " + mode); - return false; - } - - if (connMode == BluetoothVcp.MODE_NONE) { - mConnectionMode.remove(device); - VcpControllerStateMachine stateMachine = mStateMachines.get(device); - if (stateMachine == null) { - Log.w(TAG, "disconnect: device " + device + " not ever connected/connecting"); - return false; - } - int connectionState = stateMachine.getConnectionState(); - if (connectionState != BluetoothProfile.STATE_CONNECTED - && connectionState != BluetoothProfile.STATE_CONNECTING) { - Log.w(TAG, "disconnect: device " + device - + " not connected/connecting, connectionState=" + connectionState); - return false; - } - stateMachine.sendMessage(VcpControllerStateMachine.DISCONNECT, device); - } else { - mConnectionMode.put(device, connMode); - } - } - return true; - } - - /** - * Set absolute volume to remote device via VCP connection - * - * @param device: remote device instance - * @param volume: requested volume settings for remote device - * @return true if set abs volume requst is accepted, false if set - * abs volume request is rejected - */ - public boolean setAbsoluteVolume(BluetoothDevice device, int volume, int audioType) { - synchronized (mStateMachines) { - Log.i(TAG, "setAbsVolume: device=" + device + ", " + Utils.getUidPidString()); - final VcpControllerStateMachine stateMachine = mStateMachines.get(device); - - if (stateMachine == null) { - Log.w(TAG, "setAbsVolume: device " + device + " was never connected/connecting"); - return false; - } - - if (stateMachine.getConnectionState() != BluetoothProfile.STATE_CONNECTED) { - Log.w(TAG, "setAbsVolume: profile not connected"); - return false; - } - - stateMachine.sendMessage(VcpControllerStateMachine.SET_VOLUME, volume, audioType, device); - } - return true; - } - - /** - * Mute or unmute remote device via VCP connection - * - * @param device: remote device instance - * @param enableMute: true if mute, false if unmute - * @return true if mute requst is accepted, false if mute - * request is rejected - */ - public boolean setMute(BluetoothDevice device, boolean enableMute) { - synchronized (mStateMachines) { - Log.i(TAG, "setMute: device=" + device + ", " + "enableMute: " + enableMute); - final VcpControllerStateMachine stateMachine = mStateMachines.get(device); - if (stateMachine == null) { - Log.w(TAG, "setMute: device " + device + " was never connected/connecting"); - return false; - } - if (stateMachine.getConnectionState() != BluetoothProfile.STATE_CONNECTED) { - Log.w(TAG, "setMute: profile not connected"); - return false; - } - if (enableMute) { - stateMachine.sendMessage(VcpControllerStateMachine.MUTE, device); - } else { - stateMachine.sendMessage(VcpControllerStateMachine.UNMUTE, device); - } - } - return true; - } - - /** - * Get current absolute volume of the remote device - * - * @param device: remote device instance - * @return current absolute volume of the remote device - */ - public int getAbsoluteVolume(BluetoothDevice device) { - synchronized (mStateMachines) { - final VcpControllerStateMachine stateMachine = mStateMachines.get(device); - if (stateMachine == null) { - return -1; - } - return stateMachine.getVolume(); - } - } - - /** - * Get mute status of remote device - * - * @param device: remote device instance - * @return current mute status of the remote device: - * true if mute status, false if unmute status - */ - public boolean isMute(BluetoothDevice device) { - synchronized (mStateMachines) { - final VcpControllerStateMachine stateMachine = mStateMachines.get(device); - if (stateMachine == null) { - return false; - } - return stateMachine.isMute(); - } - } - - /** - * Get the current connection state of the VCP - * - * @param device is the remote bluetooth device - * @return {@link BluetoothProfile#STATE_DISCONNECTED} if VCP is disconnected, - * {@link BluetoothProfile#STATE_CONNECTING} if VCP is being connected, - * {@link BluetoothProfile#STATE_CONNECTED} if VCP is connected, or - * {@link BluetoothProfile#STATE_DISCONNECTING} if VCP is being disconnected - */ - public int getConnectionState(BluetoothDevice device) { - synchronized (mStateMachines) { - VcpControllerStateMachine sm = mStateMachines.get(device); - if (sm == null) { - return BluetoothProfile.STATE_DISCONNECTED; - } - return sm.getConnectionState(); - } - } - - /** - * Get current VCP Connection mode - * - * @param device: remote device instance - * @return current connection mode of VCP: - * {@link #BluetoothVcp.MODE_NONE} if none VCP connection - * {@link #BluetoothVcp.MODE_UNICAST} if VCP is connected for unicast - * {@link #BluetoothVcp.MODE_BROADCAST} if VCP is connected for broadcast - * {@link #BluetoothVcp.MODE_UNICAST_BROADCAST} if VCP is connected - * for both unicast and broadcast - */ - public int getConnectionMode(BluetoothDevice device) { - synchronized (mStateMachines) { - if (mConnectionMode.containsKey(device)) { - return mConnectionMode.get(device); - } - return BluetoothVcp.MODE_NONE; - } - } - - /** - * Check if VCP is connected for broadcast mode - * - * @param device: remote device instance - * @return true if VCP is connected for broadcast or uncast-broadcast - * return false if VCP is connected for unicast-only - */ - public boolean isBroadcastDevice(BluetoothDevice device) { - if (device == null) - return false; - - synchronized (mStateMachines) { - if (mConnectionMode.containsKey(device)) { - if ((mConnectionMode.get(device) & BluetoothVcp.MODE_BROADCAST) != 0) { - return true; - } - } - } - return false; - } - - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean okToConnect(BluetoothDevice device) { - // Check if this is an incoming connection in Quiet mode. - if (mAdapterService.isQuietModeEnabled()) { - Log.e(TAG, "okToConnect: cannot connect to " + device + " : quiet mode enabled"); - return false; - } - - int bondState = mAdapterService.getBondState(device); - if (bondState != BluetoothDevice.BOND_BONDED) { - Log.w(TAG, "okToConnect: return false, bondState=" + bondState); - return false; - } - return true; - } - - void messageFromNative(VcpStackEvent stackEvent) { - Objects.requireNonNull(stackEvent.device, - "Device should never be null, event: " + stackEvent); - - synchronized (mStateMachines) { - BluetoothDevice device = stackEvent.device; - VcpControllerStateMachine sm = mStateMachines.get(device); - if (sm == null) { - if (stackEvent.type == VcpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED) { - switch (stackEvent.valueInt1) { - case VcpStackEvent.CONNECTION_STATE_CONNECTED: - case VcpStackEvent.CONNECTION_STATE_CONNECTING: - sm = getOrCreateStateMachine(device); - break; - default: - break; - } - } - } - if (sm == null) { - Log.e(TAG, "Cannot process stack event: no state machine: " + stackEvent); - return; - } - sm.sendMessage(VcpControllerStateMachine.STACK_EVENT, stackEvent); - } - } - - int getCsipSetId(BluetoothDevice device, ParcelUuid uuid) { - GroupService csipService = GroupService.getGroupService(); - if (csipService != null) { - return csipService.getRemoteDeviceGroupId(device, uuid); - } else { - return -1; - } - } - - void onConnectionStateChangedFromStateMachine(BluetoothDevice device, - int newState, int prevState) { - Log.d(TAG, "onConnectionStateChangedFromStateMachine for device: " + device - + " newState: " + newState); - - if (device == null) { - Log.d(TAG, "device is null "); - return; - } - - mDpm = DeviceProfileMap.getDeviceProfileMapInstance(); - mAcmService = AcmService.getAcmService(); - BluetoothDevice grpDevice; - if (mAcmService != null) { - grpDevice = mAcmService.getGroup(device); - } else { - Log.w(TAG, "AcmService is null"); - grpDevice = device; - } - - synchronized (mStateMachines) { - if (newState == BluetoothProfile.STATE_DISCONNECTED) { - int bondState = mAdapterService.getBondState(device); - if (bondState == BluetoothDevice.BOND_NONE) { - removeStateMachine(device); - } - - if (mAcmService != null && - (mAcmService.isVcpPeerDeviceConnected(device, getCsipSetId(device, null)))) { - Log.d(TAG, "VCP Peer device connected, this is not last member, skip update to APM "); - } else { - ///* Update VCP profile disconnected to APM/ACM - Log.d(TAG, "All group members are disconnected, update to APM"); - if (mDpm != null) { - mDpm.profileConnectionUpdate(grpDevice, - ApmConst.AudioFeatures.MEDIA_VOLUME_CONTROL, ApmConst.AudioProfiles.VCP, false); - - mDpm.profileConnectionUpdate(grpDevice, - ApmConst.AudioFeatures.CALL_VOLUME_CONTROL, ApmConst.AudioProfiles.VCP, false); - } - } - setAbsVolumeSupport(device, false, -1); - updateConnState(device, newState); - //*/ - Log.d(TAG, "VCP get disconnected with renderer device: " + device); - } else if (newState == BluetoothProfile.STATE_CONNECTED) { - Log.d(TAG, "VCP get connected with renderer device: " + device); - - if (mAcmService != null && - (mAcmService.isVcpPeerDeviceConnected(device, getCsipSetId(device, null)))) { - Log.d(TAG, "VCP Peer device connected, this is not first connected member, skip update to APM "); - } else { - ///* Update VCP profile connected to APM/ACM - Log.d(TAG, "The first connected memeber, update to APM"); - if (mDpm != null) { - mDpm.profileConnectionUpdate(grpDevice, - ApmConst.AudioFeatures.MEDIA_VOLUME_CONTROL, ApmConst.AudioProfiles.VCP, true); - - mDpm.profileConnectionUpdate(grpDevice, - ApmConst.AudioFeatures.CALL_VOLUME_CONTROL, ApmConst.AudioProfiles.VCP, true); - } - } - // Set Abs Volume Support with true until get initial volume of remote - //*/ - } - } - } - - void setAbsVolumeSupport(BluetoothDevice device, boolean isAbsVolSupported, int initial_volume) { - mAcmService = AcmService.getAcmService(); - if (mAcmService != null) { - Log.d(TAG, "Update Abs Volume Support to upper layer "); - mAcmService.setAbsVolSupport(device, isAbsVolSupported, initial_volume); - } - } - - void notifyVolumeChanged(BluetoothDevice device, int volume, int audioType) { - Log.d(TAG, "notify volume changed for renderer device: " + device + " audioType: " + audioType); - // Notify ACM volume changed for device - mAcmService = AcmService.getAcmService(); - if (mAcmService != null) { - mAcmService.onVolumeStateChanged(device, volume, audioType); - } - Intent intent = new Intent(BluetoothVcp.ACTION_VOLUME_CHANGED); - intent.putExtra(BluetoothVcp.EXTRA_VOLUME, volume); - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - mContext.sendBroadcast(intent, BLUETOOTH_CONNECT, - Utils.getTempAllowlistBroadcastOptions()); - } - - void notifyMuteChanged(BluetoothDevice device, boolean mute) { - Log.d(TAG, "notify mute changed for renderer device: " + device + " mute: " + mute); - // Notify ACM mute changed - mAcmService = AcmService.getAcmService(); - if (mAcmService != null) { - mAcmService.onMuteStatusChanged (device, mute); - } - Intent intent = new Intent(BluetoothVcp.ACTION_MUTE_CHANGED); - intent.putExtra(BluetoothVcp.EXTRA_MUTE, mute); - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - mContext.sendBroadcast(intent, BLUETOOTH_CONNECT, - Utils.getTempAllowlistBroadcastOptions()); - } - - void broadcastConnectionModeChanged(BluetoothDevice device, int mode) { - Log.d(TAG, "broadccast connection mode changed for device: " + device + ", mode: " + mode); - Intent intent = new Intent(BluetoothVcp.ACTION_CONNECTION_MODE_CHANGED); - intent.putExtra(BluetoothVcp.EXTRA_MODE, mode); - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - mContext.sendBroadcast(intent, BLUETOOTH_CONNECT, - Utils.getTempAllowlistBroadcastOptions()); - } - - public void updateConnState(BluetoothDevice device, int newState) { - Log.d(TAG, "updateConnState: device: " + device + ", state: " + newState); - VolumeManager mVolumeManager = VolumeManager.get(); - mVolumeManager.onConnStateChange(device, newState, ApmConst.AudioProfiles.VCP); - } - - private class BondStateChangedReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - if (!BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())) { - return; - } - int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, - BluetoothDevice.ERROR); - BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - Objects.requireNonNull(device, "ACTION_BOND_STATE_CHANGED with no EXTRA_DEVICE"); - bondStateChanged(device, state); - } - } - - /** - * Process a change in the bonding state for a device. - * - * @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}. - */ - @VisibleForTesting - void bondStateChanged(BluetoothDevice device, int bondState) { - if (DBG) { - 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) { - return; - } - - synchronized (mStateMachines) { - VcpControllerStateMachine sm = mStateMachines.get(device); - if (sm == null) { - return; - } - if (sm.getConnectionState() != BluetoothProfile.STATE_DISCONNECTED) { - return; - } - mConnectionMode.remove(device); - removeStateMachine(device); - } - } - - private void removeStateMachine(BluetoothDevice device) { - synchronized (mStateMachines) { - VcpControllerStateMachine sm = mStateMachines.get(device); - if (sm == null) { - Log.w(TAG, "removeStateMachine: device " + device - + " does not have a state machine"); - return; - } - Log.i(TAG, "removeStateMachine: removing state machine for device: " + device); - sm.doQuit(); - sm.cleanup(); - mStateMachines.remove(device); - } - } - - private VcpControllerStateMachine getOrCreateStateMachine(BluetoothDevice device) { - if (device == null) { - Log.e(TAG, "getOrCreateStateMachine failed: device cannot be null"); - return null; - } - synchronized (mStateMachines) { - VcpControllerStateMachine sm = mStateMachines.get(device); - if (sm != null) { - return sm; - } - if (mStateMachines.size() >= MAX_VCP_STATE_MACHINES) { - Log.e(TAG, "Maximum number of VCP state machines reached: " - + MAX_VCP_STATE_MACHINES); - return null; - } - if (DBG) { - Log.d(TAG, "Creating a new state machine for " + device); - } - sm = VcpControllerStateMachine.make(device, this, mContext, - mNativeInterface, mStateMachinesThread.getLooper()); - mStateMachines.put(device, sm); - return sm; - } - } - - private class VcpControllerTestReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - if (action.equals(ACTION_CONNECT_DEVICE)) { - Log.d(TAG, "Receive ACTION_CONNECT_DEVICE"); - int mode = intent.getIntExtra(BluetoothVcp.EXTRA_MODE, 0); - BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - connect(device, mode); - } else if (action.equals(ACTION_DISCONNECT_DEVICE)) { - Log.d(TAG, "Receive ACTION_DISCONNECT_DEVICE"); - int mode = intent.getIntExtra(BluetoothVcp.EXTRA_MODE, 0); - BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - disconnect(device, mode); - } - } - } -} - diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/vcp/VcpControllerNativeInterface.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/vcp/VcpControllerNativeInterface.java deleted file mode 100644 index 89cc69bf01d5f8b12a952524841e6571aace36ff..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/vcp/VcpControllerNativeInterface.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - *Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/* - * 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. - */ - -/* - * Defines the native interface that is used by state machine/service to - * send or receive messages from the native stack. This file is registered - * for the native methods in the corresponding JNI C++ file. - */ -package com.android.bluetooth.vcp; - -import android.bluetooth.BluetoothAdapter; -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; - -/** - * Vcp Controller Native Interface to/from JNI. - */ -public class VcpControllerNativeInterface { - private static final String TAG = "VcpControllerNativeInterface"; - private static final boolean DBG = true; - private BluetoothAdapter mAdapter; - - @GuardedBy("INSTANCE_LOCK") - private static VcpControllerNativeInterface sInstance; - private static final Object INSTANCE_LOCK = new Object(); - - static { - classInitNative(); - } - - private VcpControllerNativeInterface() { - mAdapter = BluetoothAdapter.getDefaultAdapter(); - if (mAdapter == null) { - Log.wtfStack(TAG, "No Bluetooth Adapter Available"); - } - } - - /** - * Get singleton instance. - */ - public static VcpControllerNativeInterface getInstance() { - synchronized (INSTANCE_LOCK) { - if (sInstance == null) { - sInstance = new VcpControllerNativeInterface(); - } - return sInstance; - } - } - - /** - * Initializes the native interface. - * - * priorities to configure. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void init() { - initNative(); - } - - /** - * Cleanup the native interface. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public void cleanup() { - cleanupNative(); - } - - /** - * Initiates Vcp connection to a remote device. - * - * @param device the remote device - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean connectVcp(BluetoothDevice device, boolean isDirect) { - return connectVcpNative(getByteAddress(device), isDirect); - } - - /** - * Disconnects Vcp from a remote device. - * - * @param device the remote device - * @return true on success, otherwise false. - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean disconnectVcp(BluetoothDevice device) { - return disconnectVcpNative(getByteAddress(device)); - } - - /** - * Sets the Vcp Abs volume - * @param volume - */ - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean setAbsVolume(int volume, BluetoothDevice device) { - return setAbsVolumeNative(volume, getByteAddress(device)); - } - - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean mute(BluetoothDevice device) { - return muteNative(getByteAddress(device)); - } - - @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean unmute(BluetoothDevice device) { - return unmuteNative(getByteAddress(device)); - } - - 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(VcpStackEvent event) { - VcpController service = VcpController.getVcpController(); - 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. - private void onConnectionStateChanged(int state, byte[] address) { - VcpStackEvent event = - new VcpStackEvent(VcpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); - event.device = getDevice(address); - event.valueInt1 = state; - - if (DBG) { - Log.d(TAG, "onConnectionStateChanged: " + event); - } - sendMessageToService(event); - } - - private void OnVolumeStateChange(int volume, int mute, byte[] address) { - VcpStackEvent event = new VcpStackEvent( - VcpStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED); - event.device = getDevice(address); - event.valueInt1 = volume; - event.valueInt2 = mute; - - if (DBG) { - Log.d(TAG, "OnVolumeStateChange: " + event); - } - sendMessageToService(event); - } - - private void OnVolumeFlagsChange(int flags, byte[] address) { - VcpStackEvent event = new VcpStackEvent( - VcpStackEvent.EVENT_TYPE_VOLUME_FLAGS_CHANGED); - event.device = getDevice(address); - event.valueInt1 = flags; - - if (DBG) { - Log.d(TAG, "OnVolumeFlagsChange: " + event); - } - sendMessageToService(event); - } - - // Native methods that call into the JNI interface - private static native void classInitNative(); - private native void initNative(); - private native void cleanupNative(); - private native boolean connectVcpNative(byte[] address, boolean isDirect); - private native boolean disconnectVcpNative(byte[] address); - private native boolean setAbsVolumeNative(int volume, byte[] address); - private native boolean muteNative(byte[] address); - private native boolean unmuteNative(byte[] address); -} - diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/vcp/VcpControllerStateMachine.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/vcp/VcpControllerStateMachine.java deleted file mode 100644 index fc35753ddc46668412af77cbfdb26a237adac6c4..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/vcp/VcpControllerStateMachine.java +++ /dev/null @@ -1,1046 +0,0 @@ -/* - *Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/* - * 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. - */ - -/** - * Bluetooth VCP 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.vcp; - -import static android.Manifest.permission.BLUETOOTH_CONNECT; - -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; -import com.android.bluetooth.Utils; -import android.bluetooth.BluetoothVcp; -import android.content.Context; -import android.content.Intent; -import android.os.Looper; -import android.os.Message; -import android.util.Log; - -import com.android.bluetooth.btservice.ProfileService; -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.State; -import com.android.internal.util.StateMachine; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Scanner; - -final class VcpControllerStateMachine extends StateMachine { - private static final boolean DBG = true; - private static final String TAG = "VcpControllerStateMachine"; - - static final int CONNECT = 1; - static final int DISCONNECT = 2; - static final int SET_VOLUME = 3; - static final int MUTE = 4; - static final int UNMUTE = 5; - - @VisibleForTesting - static final int STACK_EVENT = 101; - private static final int CONNECT_TIMEOUT = 201; - private static final int SET_ABS_VOL_TIMEOUT = 202; - private static final int CHANGE_MUTE_TIMEOUT = 203; - - private static final int UNMUTE_STATE = 0; - private static final int MUTE_STATE = 1; - private static final int VOLUME_SETTING_NOT_PERSISTED = 0x00; - private static final int VOLUME_SETTING_PERSISTED = 0x01; - - private static final int MAX_ERROR_RETRY_TIMES = 3; - private static final int VCP_MAX_VOL = 255; - // The default VCP volume 0x77 (119) - private static final int VCP_DEFAULT_VOL = 119; - private static final int CMD_TIMEOUT_DELAY = 2000; - - - // 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 mLastConnectionState = -1; - - private VcpController mVcpController; - private VcpControllerNativeInterface mNativeInterface; - private Context mContext; - - /* Current remote volume */ - private int mRemoteVolume; - /* Requested volume in progress of Native Layer setAbsVolume */ - private int mRequestedVolume; - /* Cached new volume if has a requested volume in progress */ - private int mCachedVolume; - private int mAbsVolRetryTimes; - private boolean mAbsVolSetInProgress; - - /* Current remote mute state */ - private int mMuteState; - /* Requested mute state in progress of Native Layer mute/unMute */ - private int mRequestedMuteState; - /* Cached new mute state if has a requested mute state in progress */ - private int mCachedMuteState; - private int mChangeMuteRetryTimes; - private boolean mMuteChangeInProgress; - - private int mVolumeFlags; - private final BluetoothDevice mDevice; - private int mVolumeControlAudioType; - private int mCachedVolumeControlAudioType; - - VcpControllerStateMachine(BluetoothDevice device, VcpController svc, Context context, - VcpControllerNativeInterface nativeInterface, Looper looper) { - super(TAG, looper); - mDevice = device; - mVcpController = svc; - mContext = context; - mNativeInterface = nativeInterface; - - mDisconnected = new Disconnected(); - mConnecting = new Connecting(); - mDisconnecting = new Disconnecting(); - mConnected = new Connected(); - - addState(mDisconnected); - addState(mConnecting); - addState(mDisconnecting); - addState(mConnected); - - setInitialState(mDisconnected); - } - - static VcpControllerStateMachine make(BluetoothDevice device, VcpController svc, - Context context, VcpControllerNativeInterface nativeInterface, Looper looper) { - Log.i(TAG, "make for device " + device); - VcpControllerStateMachine VcpControllerSm = - new VcpControllerStateMachine(device, svc, context, nativeInterface, looper); - VcpControllerSm.start(); - return VcpControllerSm; - } - - public void doQuit() { - log("doQuit for device " + mDevice); - quitNow(); - } - - public void cleanup() { - log("cleanup for device " + mDevice); - } - - @VisibleForTesting - class Disconnected extends State { - @Override - public void enter() { - Log.i(TAG, "Enter Disconnected(" + mDevice + "): " + messageWhatToString( - getCurrentMessage().what)); - - removeDeferredMessages(DISCONNECT); - if (mLastConnectionState != -1) { - // Don't broadcast during startup - broadcastConnectionState(BluetoothProfile.STATE_DISCONNECTED, - mLastConnectionState); - } - - cleanupDevice(); - } - - @Override - public void exit() { - log("Exit Disconnected(" + mDevice + "): " + messageWhatToString( - getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_DISCONNECTED; - } - - @Override - public boolean processMessage(Message message) { - log("Disconnected process message(" + mDevice + "): " + messageWhatToString( - message.what)); - - switch (message.what) { - case CONNECT: - BluetoothDevice device = (BluetoothDevice) message.obj; - log("Connecting to " + device); - - if (!mDevice.equals(device)) { - Log.e(TAG, "CONNECT failed, device=" + device + ", currentDev=" + mDevice); - break; - } - - if (!mNativeInterface.connectVcp(mDevice, true)) { - Log.e(TAG, "Disconnected: error connecting to " + mDevice); - break; - } - - transitionTo(mConnecting); - break; - case DISCONNECT: - Log.w(TAG, "Disconnected: DISCONNECT ignored: " + mDevice); - break; - case STACK_EVENT: - VcpStackEvent event = (VcpStackEvent) message.obj; - if (DBG) { - Log.d(TAG, "Disconnected: stack event: " + event); - } - if (!mDevice.equals(event.device)) { - Log.wtfStack(TAG, "Device(" + mDevice + "): event mismatch: " + event); - break; - } - switch (event.type) { - case VcpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - processConnectionEvent(event.valueInt1); - break; - default: - Log.e(TAG, "Disconnected: ignoring stack event: " + event); - break; - } - break; - default: - Log.e(TAG, "Unexpected msg " + messageWhatToString(message.what) - + ": " + message); - return NOT_HANDLED; - } - return HANDLED; - } - - // in Disconnected state - private void processConnectionEvent(int state) { - switch (state) { - case VcpStackEvent.CONNECTION_STATE_DISCONNECTED: - Log.w(TAG, "Ignore VCP DISCONNECTED event: " + mDevice); - break; - case VcpStackEvent.CONNECTION_STATE_CONNECTING: - Log.i(TAG, "Incoming VCP Connecting request accepted: " + mDevice); - if (mVcpController.okToConnect(mDevice)) { - transitionTo(mConnecting); - } else { - // Reject the connection and stay in Disconnected state itself - Log.w(TAG, "Incoming VCP Connecting request rejected: " + mDevice); - mNativeInterface.disconnectVcp(mDevice); - } - break; - case VcpStackEvent.CONNECTION_STATE_CONNECTED: - Log.w(TAG, "VCP Connected from Disconnected state: " + mDevice); - if (mVcpController.okToConnect(mDevice)) { - Log.i(TAG, "Incoming VCP Connected request accepted: " + mDevice); - transitionTo(mConnected); - } else { - // Reject the connection and stay in Disconnected state itself - Log.w(TAG, "Incoming VCP Connected request rejected: " + mDevice); - mNativeInterface.disconnectVcp(mDevice); - } - break; - case VcpStackEvent.CONNECTION_STATE_DISCONNECTING: - Log.w(TAG, "Ignore VCP DISCONNECTING event: " + mDevice); - break; - default: - Log.e(TAG, "Incorrect state: " + state + " device: " + mDevice); - break; - } - } - } - - @VisibleForTesting - class Connecting extends State { - @Override - public void enter() { - Log.i(TAG, "Enter Connecting(" + mDevice + "): " - + messageWhatToString(getCurrentMessage().what)); - sendMessageDelayed(CONNECT_TIMEOUT, mDevice, sConnectTimeoutMs); - broadcastConnectionState(BluetoothProfile.STATE_CONNECTING, mLastConnectionState); - } - - @Override - public void exit() { - log("Exit Connecting(" + mDevice + "): " - + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_CONNECTING; - removeMessages(CONNECT_TIMEOUT); - } - - @Override - public boolean processMessage(Message message) { - log("Connecting process message(" + mDevice + "): " - + messageWhatToString(message.what)); - - switch (message.what) { - case CONNECT: - deferMessage(message); - break; - case CONNECT_TIMEOUT: - Log.w(TAG, "Connecting connection timeout: " + mDevice); - mNativeInterface.disconnectVcp(mDevice); - // We timed out trying to connect, transition to Disconnected state - BluetoothDevice device = (BluetoothDevice) message.obj; - if (!mDevice.equals(device)) { - Log.e(TAG, "Unknown device timeout " + device); - break; - } - Log.w(TAG, "CONNECT_TIMEOUT"); - transitionTo(mDisconnected); - break; - case DISCONNECT: - log("Connecting: connection canceled to " + mDevice); - mNativeInterface.disconnectVcp(mDevice); - transitionTo(mDisconnected); - break; - case SET_VOLUME: - case MUTE: - case UNMUTE: - case SET_ABS_VOL_TIMEOUT: - case CHANGE_MUTE_TIMEOUT: - deferMessage(message); - break; - case STACK_EVENT: - VcpStackEvent event = (VcpStackEvent) message.obj; - log("Connecting: stack event: " + event); - if (!mDevice.equals(event.device)) { - Log.wtfStack(TAG, "Device(" + mDevice + "): event mismatch: " + event); - } - switch (event.type) { - case VcpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - processConnectionEvent(event.valueInt1); - break; - default: - Log.e(TAG, "Connecting: ignoring stack event: " + event); - break; - } - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - - // in Connecting state - private void processConnectionEvent(int state) { - switch (state) { - case VcpStackEvent.CONNECTION_STATE_DISCONNECTED: - Log.w(TAG, "Connecting device disconnected: " + mDevice); - transitionTo(mDisconnected); - break; - case VcpStackEvent.CONNECTION_STATE_CONNECTED: - transitionTo(mConnected); - break; - case VcpStackEvent.CONNECTION_STATE_CONNECTING: - break; - case VcpStackEvent.CONNECTION_STATE_DISCONNECTING: - Log.w(TAG, "Connecting interrupted: device is disconnecting: " + mDevice); - transitionTo(mDisconnecting); - break; - default: - Log.e(TAG, "Incorrect state: " + state); - break; - } - } - } - - @VisibleForTesting - class Disconnecting extends State { - @Override - public void enter() { - Log.i(TAG, "Enter Disconnecting(" + mDevice + "): " - + messageWhatToString(getCurrentMessage().what)); - sendMessageDelayed(CONNECT_TIMEOUT, mDevice, sConnectTimeoutMs); - broadcastConnectionState(BluetoothProfile.STATE_DISCONNECTING, mLastConnectionState); - } - - @Override - public void exit() { - log("Exit Disconnecting(" + mDevice + "): " - + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_DISCONNECTING; - removeMessages(CONNECT_TIMEOUT); - } - - @Override - public boolean processMessage(Message message) { - log("Disconnecting process message(" + mDevice + "): " - + messageWhatToString(message.what)); - - switch (message.what) { - case CONNECT: - deferMessage(message); - break; - case CONNECT_TIMEOUT: { - Log.w(TAG, "Disconnecting connection timeout: " + mDevice); - mNativeInterface.disconnectVcp(mDevice); - // We timed out trying to connect, transition to Disconnected state - BluetoothDevice device = (BluetoothDevice) message.obj; - if (!mDevice.equals(device)) { - Log.e(TAG, "Unknown device timeout " + device); - break; - } - transitionTo(mDisconnected); - Log.w(TAG, "CONNECT_TIMEOUT"); - break; - } - case DISCONNECT: - deferMessage(message); - break; - case SET_VOLUME: - case MUTE: - case UNMUTE: - case SET_ABS_VOL_TIMEOUT: - case CHANGE_MUTE_TIMEOUT: - deferMessage(message); - break; - case STACK_EVENT: - VcpStackEvent event = (VcpStackEvent) message.obj; - log("Disconnecting: stack event: " + event); - if (!mDevice.equals(event.device)) { - Log.wtfStack(TAG, "Device(" + mDevice + "): event mismatch: " + event); - } - switch (event.type) { - case VcpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - processConnectionEvent(event.valueInt1); - break; - default: - Log.e(TAG, "Disconnecting: ignoring stack event: " + event); - break; - } - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - - // in Disconnecting state - private void processConnectionEvent(int state) { - switch (state) { - case VcpStackEvent.CONNECTION_STATE_DISCONNECTED: - Log.i(TAG, "Disconnected: " + mDevice); - transitionTo(mDisconnected); - break; - case VcpStackEvent.CONNECTION_STATE_CONNECTED: - if (mVcpController.okToConnect(mDevice)) { - Log.w(TAG, "Disconnecting interrupted: device is connected: " + mDevice); - transitionTo(mConnected); - } else { - // Reject the connection and stay in Disconnecting state - Log.w(TAG, "Incoming VCP Connected request rejected: " + mDevice); - mNativeInterface.disconnectVcp(mDevice); - } - break; - case VcpStackEvent.CONNECTION_STATE_CONNECTING: - if (mVcpController.okToConnect(mDevice)) { - Log.i(TAG, "Disconnecting interrupted: try to reconnect: " + mDevice); - transitionTo(mConnecting); - } else { - // Reject the connection and stay in Disconnecting state - Log.w(TAG, "Incoming VCP Connecting request rejected: " + mDevice); - mNativeInterface.disconnectVcp(mDevice); - } - break; - case VcpStackEvent.CONNECTION_STATE_DISCONNECTING: - break; - default: - Log.e(TAG, "Incorrect state: " + state); - break; - } - } - } - - @VisibleForTesting - class Connected extends State { - @Override - public void enter() { - Log.i(TAG, "Enter Connected(" + mDevice + "): " - + messageWhatToString(getCurrentMessage().what)); - removeDeferredMessages(CONNECT); - broadcastConnectionState(BluetoothProfile.STATE_CONNECTED, mLastConnectionState); - } - - @Override - public void exit() { - log("Exit Connected(" + mDevice + "): " - + messageWhatToString(getCurrentMessage().what)); - mLastConnectionState = BluetoothProfile.STATE_CONNECTED; - } - - @Override - public boolean processMessage(Message message) { - log("Connected process message(" + mDevice + "): " - + messageWhatToString(message.what)); - - switch (message.what) { - case CONNECT: { - Log.w(TAG, "Connected: CONNECT ignored: " + mDevice); - break; - } - case DISCONNECT: { - log("Disconnecting from " + mDevice); - if (!mNativeInterface.disconnectVcp(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); - break; - } - case SET_VOLUME: { - BluetoothDevice device = (BluetoothDevice) message.obj; - if (!mDevice.equals(device)) { - Log.w(TAG, "SET_VOLUME failed " + device - + " is not currentDevice"); - break; - } - log("Set volume for " + device); - - processSetAbsVolume(message.arg1, message.arg2); - break; - } - case MUTE: { - BluetoothDevice device = (BluetoothDevice) message.obj; - if (!mDevice.equals(device)) { - Log.w(TAG, "Mute failed " + device - + " is not currentDevice"); - break; - } - log("Mute for " + device); - - processSetMute(); - break; - } - case UNMUTE: { - BluetoothDevice device = (BluetoothDevice) message.obj; - if (!mDevice.equals(device)) { - Log.w(TAG, "Unmute failed " + device - + " is not currentDevice"); - break; - } - log("Unmute for " + device); - - processSetUnmute(); - break; - } - case SET_ABS_VOL_TIMEOUT: { - BluetoothDevice device = (BluetoothDevice) message.obj; - if (!mDevice.equals(device)) { - Log.w(TAG, "Set abs vol timeout failed " + device - + " is not currentDevice"); - break; - } - - mAbsVolSetInProgress = false; - if (mAbsVolRetryTimes >= MAX_ERROR_RETRY_TIMES) { - Log.w(TAG, "Set abs vol retry exceed max times"); - mRequestedVolume = -1; - mAbsVolRetryTimes = 0; - break; - } else { - mAbsVolRetryTimes += 1; - if (mNativeInterface.setAbsVolume(mRequestedVolume, mDevice)) { - sendMessageDelayed(SET_ABS_VOL_TIMEOUT, mDevice, - CMD_TIMEOUT_DELAY); - mAbsVolSetInProgress = true; - } else { - mRequestedVolume = -1; - mAbsVolRetryTimes = 0; - Log.e(TAG, "Set absolute volume failed for device: " + mDevice); - } - } - break; - } - case CHANGE_MUTE_TIMEOUT: { - BluetoothDevice device = (BluetoothDevice) message.obj; - if (!mDevice.equals(device)) { - Log.w(TAG, "Mute timeout failed " + device - + " is not currentDevice"); - break; - } - - mMuteChangeInProgress = false; - if (mChangeMuteRetryTimes >= MAX_ERROR_RETRY_TIMES) { - Log.w(TAG, "Mute retry exceed max times"); - mChangeMuteRetryTimes = 0; - mRequestedMuteState = -1; - break; - } else { - mChangeMuteRetryTimes += 1; - boolean ret; - if (mRequestedMuteState == MUTE_STATE) { - ret = mNativeInterface.mute(mDevice); - } else { - ret = mNativeInterface.unmute(mDevice); - } - - if (ret) { - sendMessageDelayed(CHANGE_MUTE_TIMEOUT, mDevice, - CMD_TIMEOUT_DELAY); - mMuteChangeInProgress = true; - } else { - mChangeMuteRetryTimes = 0; - mRequestedMuteState = -1; - Log.e(TAG, "Change Mute failed for device: " + mDevice); - } - } - break; - } - case STACK_EVENT: - VcpStackEvent event = (VcpStackEvent) message.obj; - log("Connected: stack event: " + event); - if (!mDevice.equals(event.device)) { - Log.wtfStack(TAG, "Device(" + mDevice + "): event mismatch: " + event); - } - switch (event.type) { - case VcpStackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED: - processConnectionEvent(event.valueInt1); - break; - case VcpStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED: - processVolumeStateEvent(event.valueInt1, event.valueInt2); - break; - case VcpStackEvent.EVENT_TYPE_VOLUME_FLAGS_CHANGED: - processVolumeFlagsChanged(event.valueInt1); - break; - default: - Log.e(TAG, "Connected: ignoring stack event: " + event); - break; - } - break; - default: - return NOT_HANDLED; - } - return HANDLED; - } - - // in Connected state - private void processConnectionEvent(int state) { - switch (state) { - case VcpStackEvent.CONNECTION_STATE_DISCONNECTED: - Log.i(TAG, "Disconnected from " + mDevice); - transitionTo(mDisconnected); - break; - case VcpStackEvent.CONNECTION_STATE_DISCONNECTING: - Log.i(TAG, "Disconnecting from " + mDevice); - transitionTo(mDisconnecting); - break; - default: - Log.e(TAG, "Connection State Device: " + mDevice + " bad state: " + state); - break; - } - } - } - - private void processSetAbsVolume(int volume, int audioType) { - log("process set absolute volume"); - - if (mAbsVolSetInProgress) { - mCachedVolume = volume; - mCachedVolumeControlAudioType = audioType; - Log.w(TAG, "There is already a volume command in progress, cache volume: " + - mCachedVolume + " cached audio type: " + audioType); - return; - } - - if (mRemoteVolume == -1) { - Log.w(TAG, "remote not tell initial volume"); - return; - } - - if (mRemoteVolume == volume) { - Log.w(TAG, "Ignore set abs volume as current volume equals to requested volume"); - return; - } - - Log.d(TAG, "set abs volume for audio type: " + audioType); - if (mNativeInterface.setAbsVolume(volume, mDevice)) { - sendMessageDelayed(SET_ABS_VOL_TIMEOUT, mDevice, - CMD_TIMEOUT_DELAY); - mAbsVolSetInProgress = true; - mRequestedVolume = volume; - mVolumeControlAudioType = audioType; - mCachedVolume = -1; - } else { - Log.e(TAG, "Set absolute volume failed for device: " + mDevice); - } - } - - private void processSetMute() { - log("process mute"); - - if (mMuteChangeInProgress) { - mCachedMuteState = MUTE_STATE; - Log.w(TAG, "There is already a mute change in progress, cache mute"); - return; - } - - if (mRemoteVolume == -1) { - Log.w(TAG, "remote not tell initial volume"); - return; - } - - if (mMuteState == MUTE_STATE) { - Log.w(TAG, "Ignore mute request as current state is mute"); - return; - } - - if (mNativeInterface.mute(mDevice)) { - sendMessageDelayed(CHANGE_MUTE_TIMEOUT, mDevice, - CMD_TIMEOUT_DELAY); - mMuteChangeInProgress = true; - mRequestedMuteState = MUTE_STATE; - mCachedMuteState = -1; - } else { - Log.e(TAG, "Mute failed for device: " + mDevice); - } - } - - private void processSetUnmute() { - log("process unmute"); - - if (mMuteChangeInProgress) { - mCachedMuteState = UNMUTE_STATE; - Log.w(TAG, "There is already a mute change in progress, cache unmute"); - return; - } - - if (mRemoteVolume == -1) { - Log.w(TAG, "remote not tell initial volume"); - return; - } - - if (mMuteState == UNMUTE_STATE) { - Log.w(TAG, "Ignore unmute request as current state is unmute"); - return; - } - - if (mNativeInterface.unmute(mDevice)) { - sendMessageDelayed(CHANGE_MUTE_TIMEOUT, mDevice, - CMD_TIMEOUT_DELAY); - mMuteChangeInProgress = true; - mRequestedMuteState = UNMUTE_STATE; - mCachedMuteState = -1; - } else { - Log.e(TAG, "Unmute failed for device: " + mDevice); - } - } - - private void processVolumeStateEvent(int vcpVol, int mute) { - log("process volume state event"); - - if (mRemoteVolume == -1 || mMuteState != mute || - mMuteChangeInProgress == true) { - processMuteChanged(mute); - } - - if (mRemoteVolume == -1 || mRemoteVolume != vcpVol || - mAbsVolSetInProgress == true) { - processVolumeChanged(vcpVol); - } - } - - private void processVolumeChanged(int vcpVol) { - log("process volume setting changed"); - - if (mAbsVolSetInProgress == true) { - mAbsVolSetInProgress = false; - removeMessages(SET_ABS_VOL_TIMEOUT); - if (mRequestedVolume == vcpVol) { - mRequestedVolume = -1; - mAbsVolRetryTimes = 0; - - if ((mCachedVolume != -1) && (mCachedVolume != vcpVol)) { - mVcpController.notifyVolumeChanged(mDevice, vcpVol, mVolumeControlAudioType); - mVolumeControlAudioType = -1; - Log.w(TAG, "Set cached volume to remote"); - if (mNativeInterface.setAbsVolume(mCachedVolume, mDevice)) { - sendMessageDelayed(SET_ABS_VOL_TIMEOUT, mDevice, - CMD_TIMEOUT_DELAY); - mAbsVolSetInProgress = true; - mRequestedVolume = mCachedVolume; - mVolumeControlAudioType = mCachedVolumeControlAudioType; - mCachedVolumeControlAudioType = -1; - mCachedVolume = -1; - return; - } else { - Log.e(TAG, "Set cached volume failed for device: " + mDevice); - mCachedVolume = -1; - } - } - } else { - Log.w(TAG, "Remote changed volume not equal to requested volume"); - if (mAbsVolRetryTimes >= MAX_ERROR_RETRY_TIMES) { - Log.w(TAG, "Set abs vol retry exceed max times"); - mRequestedVolume = -1; - mAbsVolRetryTimes = 0; - } else { - mAbsVolRetryTimes += 1; - if (mNativeInterface.setAbsVolume(mRequestedVolume, mDevice)) { - sendMessageDelayed(SET_ABS_VOL_TIMEOUT, mDevice, - CMD_TIMEOUT_DELAY); - mAbsVolSetInProgress = true; - return; - } else { - Log.e(TAG, "Set absolute volume failed for device: " + mDevice); - mRequestedVolume = -1; - mAbsVolRetryTimes = 0; - } - } - } - } - - if (mRemoteVolume == -1) { - // Set initial volume if volume flags is not persisted - if ((mVolumeFlags == VOLUME_SETTING_NOT_PERSISTED)) { - int initialVolume = VCP_DEFAULT_VOL; - if (vcpVol != initialVolume) { - mRemoteVolume = vcpVol; - Log.w(TAG, "Set initial volume to remote if volume persisted flag is false"); - if (mNativeInterface.setAbsVolume(initialVolume, mDevice)) { - sendMessageDelayed(SET_ABS_VOL_TIMEOUT, mDevice, - CMD_TIMEOUT_DELAY); - mAbsVolSetInProgress = true; - mRequestedVolume = initialVolume; - mVcpController.setAbsVolumeSupport(mDevice, true, initialVolume); - mVcpController.updateConnState(mDevice, BluetoothProfile.STATE_CONNECTED); - return; - } else { - Log.e(TAG, "Set absolute volume failed for device: " + mDevice); - } - } - } - Log.w(TAG, "Set abs volume support and update initial volume to ACM"); - mRemoteVolume = vcpVol; - mVcpController.setAbsVolumeSupport(mDevice, true, vcpVol); - mVcpController.updateConnState(mDevice, BluetoothProfile.STATE_CONNECTED); - return; - } - - if (mRemoteVolume != vcpVol) { - mRemoteVolume = vcpVol; - mVcpController.notifyVolumeChanged(mDevice, vcpVol, mVolumeControlAudioType); - mVolumeControlAudioType = -1; - long pecentVolChanged = ((long)vcpVol * 100) / 0xff; - Log.w(TAG, "percent volume changed: " + pecentVolChanged + "%"); - } - } - - private void processMuteChanged(int mute) { - log("process mute changed"); - - if (mMuteChangeInProgress == true) { - mMuteChangeInProgress = false; - mChangeMuteRetryTimes = 0; - removeMessages(CHANGE_MUTE_TIMEOUT); - - if ((mCachedMuteState != -1) && (mCachedMuteState != mute)) { - Log.w(TAG, "Set cached mute state to remote"); - boolean ret; - if (mCachedMuteState == MUTE_STATE) { - ret = mNativeInterface.mute(mDevice); - } else { - ret = mNativeInterface.unmute(mDevice); - } - - if (ret) { - sendMessageDelayed(CHANGE_MUTE_TIMEOUT, mDevice, - CMD_TIMEOUT_DELAY); - mMuteChangeInProgress = true; - mRequestedMuteState = mCachedMuteState; - mCachedMuteState = -1; - return; - } - mCachedMuteState = -1; - } - } - - if (mMuteState != mute) { - mMuteState = mute; - boolean isMute = (mMuteState == MUTE_STATE) ? true : false; - mVcpController.notifyMuteChanged(mDevice, isMute); - Log.w(TAG, "Mute state changed to " + mMuteState); - } - } - - private void processVolumeFlagsChanged(int flags) { - log("process volume flags changed"); - mVolumeFlags = flags; - } - - 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; - } - } - - int getVolume() { - return mRemoteVolume; - } - - boolean isMute() { - if (mMuteState == MUTE_STATE) - return true; - else - return false; - } - - BluetoothDevice getDevice() { - return mDevice; - } - - synchronized boolean isConnected() { - return getCurrentState() == mConnected; - } - - // This method does not check for error condition (newState == prevState) - private void broadcastConnectionState(int newState, int prevState) { - log("Connection state " + mDevice + ": " + profileStateToString(prevState) - + "->" + profileStateToString(newState)); - mVcpController.onConnectionStateChangedFromStateMachine(mDevice, - newState, prevState); - - Intent intent = new Intent(BluetoothVcp.ACTION_CONNECTION_STATE_CHANGED); - intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); - intent.putExtra(BluetoothProfile.EXTRA_STATE, newState); - intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - mContext.sendBroadcast(intent, BLUETOOTH_CONNECT, - Utils.getTempAllowlistBroadcastOptions()); - } - - private void cleanupDevice() { - log("cleanup device " + mDevice); - mRemoteVolume = -1; - mRequestedVolume = -1; - mCachedVolume = -1; - mAbsVolRetryTimes = 0; - mAbsVolSetInProgress = false; - mMuteState = -1; - mRequestedMuteState = -1; - mCachedMuteState = -1; - mChangeMuteRetryTimes = 0; - mMuteChangeInProgress = false; - mVolumeFlags = -1; - mVolumeControlAudioType = -1; - mCachedVolumeControlAudioType = -1; - } - - 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"; - case SET_VOLUME: - return "SET_VOLUME"; - case MUTE: - return "MUTE"; - case UNMUTE: - return "UNMUTE"; - case SET_ABS_VOL_TIMEOUT: - return "SET_ABS_VOL_TIMEOUT"; - case CHANGE_MUTE_TIMEOUT: - return "CHANGE_MUTE_TIMEOUT"; - default: - return "UNKNOWN(" + 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); - } - - public void dump(StringBuilder sb) { - ProfileService.println(sb, "mDevice: " + mDevice); - ProfileService.println(sb, " StateMachine: " + this); - // Dump the state machine logs - StringWriter stringWriter = new StringWriter(); - PrintWriter printWriter = new PrintWriter(stringWriter); - super.dump(new FileDescriptor(), printWriter, new String[]{}); - printWriter.flush(); - stringWriter.flush(); - ProfileService.println(sb, " StateMachineLog:"); - Scanner scanner = new Scanner(stringWriter.toString()); - while (scanner.hasNextLine()) { - String line = scanner.nextLine(); - ProfileService.println(sb, " " + line); - } - scanner.close(); - } - - @Override - protected void log(String msg) { - if (DBG) { - super.log(msg); - } - } -} - diff --git a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/vcp/VcpStackEvent.java b/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/vcp/VcpStackEvent.java deleted file mode 100644 index e77f95d84831f2aa7b795a3ff63e067146a51d2e..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Bluetooth/src/com/android/bluetooth/vcp/VcpStackEvent.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - *Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/* - * 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. - */ - -package com.android.bluetooth.vcp; - -import android.bluetooth.BluetoothDevice; - -/** - * Stack event sent via a callback from JNI to Java, or generated - * internally by the VCP State Machine. - */ -public class VcpStackEvent { - // 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_VOLUME_STATE_CHANGED = 2; - public static final int EVENT_TYPE_VOLUME_FLAGS_CHANGED = 3; - - // Do not modify without updating the HAL bt_vcp.h files. - // Match up with enum class ConnectionState of bt_vcp_controller.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; - public int valueInt2; - - VcpStackEvent(int type) { - this.type = type; - } - - @Override - public String toString() { - // event dump - StringBuilder result = new StringBuilder(); - result.append("VcpStackEvent {type:" + eventTypeToString(type)); - result.append(", device:" + device); - result.append(", value1:" + valueInt1); - result.append(", value2:" + valueInt2); - result.append("}"); - return result.toString(); - } - - private static String eventTypeToString(int type) { - switch (type) { - case EVENT_TYPE_NONE: - return "EVENT_TYPE_NONE"; - case EVENT_TYPE_CONNECTION_STATE_CHANGED: - return "EVENT_TYPE_CONNECTION_STATE_CHANGED"; - case EVENT_TYPE_VOLUME_STATE_CHANGED: - return "EVENT_TYPE_VOLUME_STATE_CHANGED"; - case EVENT_TYPE_VOLUME_FLAGS_CHANGED: - return "EVENT_TYPE_VOLUME_FLAGS_CHANGED"; - default: - return "EVENT_TYPE_UNKNOWN:" + type; - } - } -} - diff --git a/le_audio/packages/apps/Settings/Android.bp b/le_audio/packages/apps/Settings/Android.bp deleted file mode 100644 index 47ec0c4b6fa02550c81f5187b557a95c55decc5e..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Settings/Android.bp +++ /dev/null @@ -1,31 +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. - * - ******************************************************************************/ - -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"], -} - -filegroup { - name: "settings-bluetooth-adva-srcs", - srcs: ["src/**/*.java"], -} diff --git a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BADevicePreferenceController.java b/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BADevicePreferenceController.java deleted file mode 100644 index 7f79465ded5ad9fd826bfe997a9d24ce751afff7..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BADevicePreferenceController.java +++ /dev/null @@ -1,144 +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. - */ -package com.android.settings.bluetooth; - -import android.content.Context; -import android.content.pm.PackageManager; - -import androidx.annotation.VisibleForTesting; -import androidx.preference.Preference; -import androidx.preference.PreferenceGroup; -import androidx.preference.PreferenceScreen; - -import com.android.settingslib.bluetooth.CachedBluetoothDevice; -import com.android.settings.bluetooth.BluetoothDeviceUpdater; -import com.android.settings.bluetooth.SavedBluetoothDeviceUpdater; -import com.android.settings.connecteddevice.dock.DockUpdater; -import com.android.settings.connecteddevice.DevicePreferenceCallback; -import com.android.settings.core.BasePreferenceController; -import com.android.settings.dashboard.DashboardFragment; -import com.android.settings.overlay.FeatureFactory; -import com.android.settingslib.core.lifecycle.LifecycleObserver; -import com.android.settingslib.core.lifecycle.Lifecycle; -import com.android.settingslib.core.lifecycle.events.OnStart; -import com.android.settingslib.core.lifecycle.events.OnStop; -import android.util.Log; -import androidx.annotation.Keep; - -@Keep -public class BADevicePreferenceController extends BasePreferenceController - implements LifecycleObserver, OnStart, OnStop, BleBroadcastSourceInfoPreferenceCallback { - - private static final String TAG = "BADevicePreferenceController"; - //Up to 3 Elements can be viewed here - private static final int MAX_DEVICE_NUM = 3; - - private PreferenceGroup mPreferenceGroup; - private BluetoothBroadcastSourceInfoEntries mBleSourceInfoUpdater; - private int mPreferenceSize; - private CachedBluetoothDevice mCachedDevice; - - public BADevicePreferenceController(Context context, Lifecycle lifecycle, String preferenceKey) { - super(context, preferenceKey); - - lifecycle.addObserver(this); - BroadcastScanAssistanceUtils.debug(TAG, "constructor: KEY" + preferenceKey); - } - - @Override - public int getAvailabilityStatus() { - return (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH) - ) - ? AVAILABLE - : CONDITIONALLY_UNAVAILABLE; - } - - @Override - public String getPreferenceKey() { - return new String("added_sources"); - } - - @Override - public void displayPreference(PreferenceScreen screen) { - BroadcastScanAssistanceUtils.debug(TAG, "displayPreference"); - super.displayPreference(screen); - mPreferenceGroup = screen.findPreference(getPreferenceKey()); - mPreferenceGroup.setVisible(false); - - if (isAvailable()) { - BroadcastScanAssistanceUtils.debug(TAG, "registering wth BleSrcInfo updaters"); - final Context context = screen.getContext(); - if (mBleSourceInfoUpdater != null) { - mBleSourceInfoUpdater.setPrefContext(context); - } - } - } - - @Override - public void onStart() { - if (mBleSourceInfoUpdater != null) { - mBleSourceInfoUpdater.registerCallback(); - } - } - - @Override - public void onStop() { - if (mBleSourceInfoUpdater != null) { - mBleSourceInfoUpdater.unregisterCallback(); - } - } - - public void init(DashboardFragment fragment, CachedBluetoothDevice device) { - BroadcastScanAssistanceUtils.debug(TAG, "Init"); - mCachedDevice = device; - mBleSourceInfoUpdater = new BluetoothBroadcastSourceInfoEntries(fragment.getContext(), - fragment, BADevicePreferenceController.this, - device); - mPreferenceSize = 0; - } - - @Override - public void onBroadcastSourceInfoAdded(Preference preference) { - BroadcastScanAssistanceUtils.debug(TAG, "onBroadcastSourceInfoAdded"); - - if (mPreferenceSize < MAX_DEVICE_NUM) { - boolean ret = mPreferenceGroup.addPreference(preference); - BroadcastScanAssistanceUtils.debug(TAG, "addPreference returns" + ret); - mPreferenceSize++; - } - updatePreferenceVisiblity(); - } - - @Override - public void onBroadcastSourceInfoRemoved(Preference preference) { - BroadcastScanAssistanceUtils.debug(TAG, "onBroadcastSourceInfoRemoved"); - mPreferenceSize--; - boolean ret = mPreferenceGroup.removePreference(preference); - BroadcastScanAssistanceUtils.debug(TAG, "removePreference returns " + ret); - updatePreferenceVisiblity(); - } - - @VisibleForTesting - void setPreferenceGroup(PreferenceGroup preferenceGroup) { - mPreferenceGroup = preferenceGroup; - } - - @VisibleForTesting - void updatePreferenceVisiblity() { - BroadcastScanAssistanceUtils.debug(TAG, "updatePreferenceVisiblity:" + mPreferenceSize); - mPreferenceGroup.setVisible(mPreferenceSize > 0); - } -} diff --git a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BleBroadcastSourceInfoDetailsController.java b/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BleBroadcastSourceInfoDetailsController.java deleted file mode 100644 index e470b29f0843a358654a212155e9578e46f5103e..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BleBroadcastSourceInfoDetailsController.java +++ /dev/null @@ -1,679 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.bluetooth; - -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BleBroadcastSourceInfo; -import android.bluetooth.BleBroadcastAudioScanAssistManager; -import android.bluetooth.BleBroadcastSourceChannel; -import android.bluetooth.BleBroadcastSourceChannel; - -import android.content.Context; -import android.text.TextUtils; -import android.util.Log; -import java.lang.String; -import androidx.annotation.VisibleForTesting; -import androidx.preference.Preference; -import androidx.preference.PreferenceCategory; -import androidx.preference.PreferenceFragmentCompat; -import androidx.preference.PreferenceScreen; -import androidx.preference.SwitchPreference; -import androidx.preference.EditTextPreference; -import androidx.preference.MultiSelectListPreference; -import com.android.settingslib.widget.ActionButtonsPreference; - -import com.android.settingslib.bluetooth.A2dpProfile; -import com.android.settingslib.bluetooth.CachedBluetoothDevice; -import com.android.settingslib.bluetooth.VendorCachedBluetoothDevice; -import com.android.settingslib.bluetooth.LocalBluetoothProfile; -import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; -import com.android.settingslib.bluetooth.LocalBluetoothManager; -import com.android.settingslib.bluetooth.MapProfile; -import com.android.settingslib.bluetooth.PanProfile; -import com.android.settingslib.bluetooth.PbapServerProfile; -import com.android.settingslib.core.lifecycle.Lifecycle; -import androidx.appcompat.app.AlertDialog; -import android.text.Html; -import android.text.TextUtils; -import android.content.DialogInterface; -import android.widget.Toast; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.HashSet; -import java.util.Arrays; -import java.util.Iterator; -import com.android.settings.R; -import java.util.Map; - -/** - * This class Broadcast Source Info details of the given Scan delegator - */ -public class BleBroadcastSourceInfoDetailsController extends BluetoothDetailsController - implements Preference.OnPreferenceClickListener, - Preference.OnPreferenceChangeListener, CachedBluetoothDevice.Callback { - private static final String TAG = "BleBroadcastSourceInfoDetailsController"; - private final String EMPTY_BD_ADDRESS = "00:00:00:00:00:00"; - - //Display controls - private static final String KEY_SOURCE_INFO_GROUP = "broadcast_source_details_category"; - private static final String KEY_SOURCE_ID = "broadcast_si_sourceId"; - private static final String KEY_SOURCE_DEVICE = "broadcast_si_source_address"; - private static final String KEY_SOURCE_ENC_STATUS = "broadcast_si_encryption_state"; - private static final String KEY_SOURCE_METADATA = "broadcast_si_metadata"; - private static final String KEY_SOURCE_METADATA_STATE = "broadcast_si_metadata_state"; - private static final String KEY_SOURCE_AUDIO_STATE = "broadcast_si_audio_state"; - - //Input Controls - private static final String KEY_SOURCE_METADATA_SWITCH = "broadcast_si_enable_metadata_sync"; - private static final String KEY_SOURCE_AUDIOSYNC_SWITCH = "broadcast_si_enable_audio_sync"; - private static final String KEY_UPDATE_BCAST_CODE = "update_broadcast_code"; - private static final String KEY_UPDATE_SOURCE_INFO = "bcast_si_update_button"; - private static final String KEY_REMOVE_SOURCE_INFO = "bcast_si_remove_button"; - - private CachedBluetoothDevice mCachedDevice; - private VendorCachedBluetoothDevice mVendorCachedDevice; - private PreferenceCategory mSourceInfoContainer; - - private Preference mSourceIdPref; - private Preference mSourceDevicePref; - private Preference mSourceEncStatusPref; - private Preference mSourceMetadataPref; - private Preference mSourceMetadataSyncStatusPref; - private MultiSelectListPreference mSourceAudioSyncStatusPref; - private SwitchPreference mSourceMetadataSyncSwitchPref; - private SwitchPreference mSourceAudioSyncSwitchPref; - private EditTextPreference mSourceUpdateBcastCodePref; - private ActionButtonsPreference mSourceUpdateSourceInfoPref; - private ActionButtonsPreference mSourceRemoveSourceInfoPref; - private boolean mIsValueChanged = false; - private BleBroadcastSourceInfo mBleBroadcastSourceInfo; - private BleBroadcastAudioScanAssistManager mScanAssistanceMgr; - private boolean isBroadcastPINUpdated = false; - private String mBroadcastCode; - private int mSourceInfoIndex; - private String EMPTY_ENTRY = "EMPTY ENTRY"; - private int mMetadataSyncState; - private int mAudioSyncState; - private boolean mIsButtonRefreshOnly = false; - private boolean mGroupOp = false; - private AlertDialog mScanAssistGroupOpDialog = null; - private List mBisIndicies; - private boolean mPAsyncCtrlNeeded = false; - - public BleBroadcastSourceInfoDetailsController(Context context, - PreferenceFragmentCompat fragment, - BleBroadcastSourceInfo bleSourceInfo, CachedBluetoothDevice device, - int sourceInfoIndex, Lifecycle lifecycle) { - super(context, fragment, device, lifecycle); - Context mContext = context; - mBleBroadcastSourceInfo = bleSourceInfo; - mCachedDevice = device; - LocalBluetoothManager mgr = Utils.getLocalBtManager(context); - LocalBluetoothProfileManager profileManager = mgr.getProfileManager(); - mVendorCachedDevice = VendorCachedBluetoothDevice.getVendorCachedBluetoothDevice(device, profileManager); - mScanAssistanceMgr = mVendorCachedDevice.getScanAssistManager(); - lifecycle.addObserver(this); - mSourceInfoIndex = sourceInfoIndex; - clearInputs(); - mPAsyncCtrlNeeded = false; - } - - private void clearInputs() - { //Keep the default state of Metadata as ON always - mMetadataSyncState = - BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC; - mAudioSyncState = - BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_INVALID; - mBroadcastCode = null; - isBroadcastPINUpdated = false; - } - - private void triggerRemoveBroadcastSource() { - if (mScanAssistanceMgr != null) { - mScanAssistanceMgr.removeBroadcastSource( - mBleBroadcastSourceInfo.getSourceId(), mGroupOp); - } - } - - private void onRemoveBroadcastSourceInfoPressed() { - BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":onRemoveBroadcastSourceInfoPressed:" + - mBleBroadcastSourceInfo); - - ///*_CSIP - if (mCachedDevice.isGroupDevice()) { - String name = mCachedDevice.getName(); - if (TextUtils.isEmpty(name)) { - name = mContext.getString(R.string.bluetooth_device); - } - String message = mContext.getString(R.string.group_remove_source_message, name); - String title = mContext.getString(R.string.group_remove_source_title); - - DialogInterface.OnClickListener groupOpListener = new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - if (mScanAssistGroupOpDialog != null) { - mScanAssistGroupOpDialog.dismiss(); - } - mGroupOp = true; - triggerRemoveBroadcastSource(); - } - }; - DialogInterface.OnClickListener nonGroupOpListener = new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - if (mScanAssistGroupOpDialog != null) { - mScanAssistGroupOpDialog.dismiss(); - } - - mGroupOp = false; - triggerRemoveBroadcastSource(); - } - }; - mGroupOp = false; - mScanAssistGroupOpDialog = BroadcastScanAssistanceUtils.showAssistanceGroupOptionsDialog(mContext, - mScanAssistGroupOpDialog, groupOpListener, nonGroupOpListener, title, Html.fromHtml(message)); - } else { - //_CSIP*/ - mGroupOp = false; - triggerRemoveBroadcastSource(); - ///*_CSIP - } - //_CSIP*/ - } - - private int getSyncState(int metadataSyncState, int audioSyncState) { - - if (audioSyncState == BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED && - metadataSyncState == BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC) { - return BleBroadcastAudioScanAssistManager.SYNC_METADATA_AUDIO; - } - - if (audioSyncState == BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED && - metadataSyncState != BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC) { - return BleBroadcastAudioScanAssistManager.SYNC_AUDIO; - } - if (audioSyncState != BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED && - metadataSyncState == BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC) { - return BleBroadcastAudioScanAssistManager.SYNC_METADATA; - } - - return -1; - } - - private void triggerUpdateBroadcastSource() { - if (mScanAssistanceMgr != null) { - if (mIsValueChanged == true) { - int syncState = getSyncState(mMetadataSyncState, mAudioSyncState); - if (syncState == -1) { - Log.e(TAG, "triggerUpdateBroadcastSource: Invalid sync Input, Ignore"); - return; - } - mScanAssistanceMgr.updateBroadcastSource( - mBleBroadcastSourceInfo.getSourceId(), - getSyncState(mMetadataSyncState, mAudioSyncState), - mBisIndicies, mGroupOp); - mIsValueChanged = false; - } - if (isBroadcastPINUpdated) { - mScanAssistanceMgr.setBroadcastCode( - mBleBroadcastSourceInfo.getSourceId(),mBroadcastCode, mGroupOp); - isBroadcastPINUpdated = false; - } - clearInputs(); - } - } - - private void onUpdateBroadcastSourceInfoPressed() { - BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + - "onUpdateBroadcastSourceInfoPressed:" + mBleBroadcastSourceInfo); - - ///*_CSIP - if (mCachedDevice.isGroupDevice()) { - String name = mCachedDevice.getName(); - if (TextUtils.isEmpty(name)) { - name = mContext.getString(R.string.bluetooth_device); - } - String message = mContext.getString(R.string.group_update_source_message, name); - String title = mContext.getString(R.string.group_update_source_title); - - DialogInterface.OnClickListener groupOpListener = new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - mGroupOp = true; - triggerUpdateBroadcastSource(); - } - }; - DialogInterface.OnClickListener nonGroupOpListener = new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - mGroupOp = false; - triggerUpdateBroadcastSource(); - } - }; - mGroupOp = false; - mScanAssistGroupOpDialog = BroadcastScanAssistanceUtils.showAssistanceGroupOptionsDialog(mContext, - mScanAssistGroupOpDialog, groupOpListener, nonGroupOpListener, title, Html.fromHtml(message)); - } else { - //_CSIP*/ - mGroupOp = false; - triggerUpdateBroadcastSource(); - ///*_CSIP - } - //_CSIP*/ - } - - @Override - protected void init(PreferenceScreen screen) { - mSourceInfoContainer = - (PreferenceCategory)screen.findPreference(getPreferenceKey()); - mSourceIdPref = (Preference)mSourceInfoContainer.findPreference( - KEY_SOURCE_ID); - mSourceDevicePref = (Preference)mSourceInfoContainer.findPreference( - KEY_SOURCE_DEVICE); - mSourceEncStatusPref = (Preference)mSourceInfoContainer.findPreference( - KEY_SOURCE_ENC_STATUS); - mSourceMetadataPref = (Preference)mSourceInfoContainer.findPreference( - KEY_SOURCE_METADATA); - mSourceMetadataSyncStatusPref = (Preference)mSourceInfoContainer.findPreference( - KEY_SOURCE_METADATA_STATE); - if (mPAsyncCtrlNeeded) { - mSourceMetadataSyncSwitchPref = (SwitchPreference)mSourceInfoContainer.findPreference( - KEY_SOURCE_METADATA_SWITCH); - - if (mSourceMetadataSyncSwitchPref != null) { - mSourceMetadataSyncSwitchPref.setOnPreferenceClickListener(this); - } - } - mSourceAudioSyncStatusPref = (MultiSelectListPreference)mSourceInfoContainer.findPreference( - KEY_SOURCE_AUDIO_STATE); - if (mSourceAudioSyncStatusPref != null) { - mSourceAudioSyncStatusPref.setOnPreferenceChangeListener(this); - } - - mSourceAudioSyncSwitchPref = (SwitchPreference)mSourceInfoContainer.findPreference( - KEY_SOURCE_AUDIOSYNC_SWITCH); - if (mSourceAudioSyncSwitchPref != null) { - mSourceAudioSyncSwitchPref.setOnPreferenceClickListener(this); - } - mSourceUpdateBcastCodePref = - (EditTextPreference)mSourceInfoContainer.findPreference( - KEY_UPDATE_BCAST_CODE); - if (mSourceUpdateBcastCodePref != null) { - mSourceUpdateBcastCodePref.setOnPreferenceClickListener(this); - mSourceUpdateBcastCodePref.setOnPreferenceChangeListener(this); - } - mSourceUpdateSourceInfoPref = - ((ActionButtonsPreference)mSourceInfoContainer.findPreference( - KEY_UPDATE_SOURCE_INFO)) - .setButton1Text(R.string.update_sourceinfo_btn_txt) - .setButton1Enabled(false) - .setButton1OnClickListener((view)->onUpdateBroadcastSourceInfoPressed()) - .setButton2Text(R.string.remove_sourceinfo_btn_txt) - .setButton2Icon(R.drawable.ic_settings_close) - .setButton2Enabled(false) - .setButton2OnClickListener((view)->onRemoveBroadcastSourceInfoPressed()); - refresh(); - } - - @Override - public void onDeviceAttributesChanged() { - //update the Local variable If the receiverState is - //updated with some values - final Map srcInfos = - mVendorCachedDevice.getAllBleBroadcastreceiverStates(); - if (srcInfos == null) { - return; - } - for (Map.Entry entry: srcInfos.entrySet()) { - Integer index = entry.getKey(); - BleBroadcastSourceInfo sourceInfo = entry.getValue(); - String toastString = null; - if (index == mSourceInfoIndex) { - BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":matching source Info"); - if (sourceInfo.isEmptyEntry()) { - BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":source info seem to be removed"); - toastString = "Source Info Removal"; - mBleBroadcastSourceInfo = sourceInfo; - } - else if (sourceInfo.equals(mBleBroadcastSourceInfo) != true) { - //toast Message - mBleBroadcastSourceInfo = sourceInfo; - BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":Update in Broadcast Source Information"); - toastString = "Source Info Update"; - } else { - BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":No Update to Source Information values"); - } - } else { - BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":Ignore this case"); - } - if (toastString != null) { - Toast toast = Toast.makeText(mContext, toastString, Toast.LENGTH_SHORT); - toast.show(); - } - } - refresh(); - } - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - String key = preference.getKey(); - BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":onPreferenceChange" + newValue); - if (key.equals(KEY_UPDATE_BCAST_CODE)) { - EditTextPreference pref = (EditTextPreference)preference; - String code = (String)newValue; - //Use different flag for Broadcast pin - isBroadcastPINUpdated = true; - mBroadcastCode = (String)newValue; - } else if (key.equals(KEY_SOURCE_AUDIO_STATE)) { - BroadcastScanAssistanceUtils.debug(TAG, ">>Checked:" +newValue); - CharSequence[] getEntriesSeqence = - ((MultiSelectListPreference)preference).getEntries(); - Set valueSet = ((MultiSelectListPreference)preference).getValues(); - - String[] selectedStrings = new String[((Set) newValue).size()]; - - //noinspection unchecked - int j =0; - for (String value : (Set) newValue) { - selectedStrings[j] = value; - for (int i=0; i>Pin code updated: " + pref.getText()); - //Use different flag for Broadcast pin - mIsValueChanged = false; - isBroadcastPINUpdated = true; - mBroadcastCode = pref.getText(); - } else { - BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":unhandled preference"); - mIsValueChanged = false; - } - BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":onPreferenceClick" + mBleBroadcastSourceInfo); - mIsButtonRefreshOnly = true; - refresh(); - return true; - } - - @Override - public void onPause() { - super.onPause(); - mCachedDevice.unregisterCallback(this); - } - - @Override - public void onResume() { - super.onResume(); - mCachedDevice.registerCallback(this); - } - - String getEncryptionStatusString(int encryptionStatus) { - - switch(encryptionStatus) { - case BleBroadcastSourceInfo.BROADCAST_ASSIST_ENC_STATE_INVALID: - return "ENCRYPTION STATE UNKNOWN"; - case BleBroadcastSourceInfo.BROADCAST_ASSIST_ENC_STATE_UNENCRYPTED: - return "UNENCRYPTED STREAMING"; - case BleBroadcastSourceInfo.BROADCAST_ASSIST_ENC_STATE_PIN_NEEDED: - return "PIN UPDATE NEEDED"; - case BleBroadcastSourceInfo.BROADCAST_ASSIST_ENC_STATE_DECRYPTING: - return "DECRYPTING SUCCESSFULLY"; - case BleBroadcastSourceInfo.BROADCAST_ASSIST_ENC_STATE_BADCODE: - return "INCORRECT BROADCAST PIN"; - } - return "ENCRYPTION STATE UNKNOWN"; - } - - String getMetadataSyncStatusString(int metadataSyncStatus) { - - switch(metadataSyncStatus) { - case BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IDLE: - return "IDLE"; - case BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_INVALID: - return "UNKNOWN"; - case BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC: - return "IN SYNC"; - case BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_NO_PAST: - return "NO PAST"; - case BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_SYNCINFO_REQ: - return "SYNCINFO NEEDED"; - case BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_SYNC_FAIL: - return "SYNC FAIL"; - } - return "UNKNOWN"; - } - - String getAudioSyncStatusString(int audioSyncStatus) { - - switch(audioSyncStatus) { - case BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_INVALID: - return "UNKNOWN"; - case BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_NOT_SYNCHRONIZED: - return "NOT IN SYNC"; - case BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED: - return "IN SYNC"; - } - return "UNKNOWN"; - } - - private boolean isPinUpdatedNeeded() { - boolean ret = false; - - if (BroadcastScanAssistanceUtils.isLocalDevice(mBleBroadcastSourceInfo.getSourceDevice())) { - BroadcastScanAssistanceUtils.debug(TAG, "Local Device, Dont allow User to update PWD"); - return false; - } - if (mBleBroadcastSourceInfo.getEncryptionStatus() - == BleBroadcastSourceInfo.BROADCAST_ASSIST_ENC_STATE_PIN_NEEDED) { - ret = true; - } - - BroadcastScanAssistanceUtils.debug(TAG, "isPinUpdatedNeeded return" + ret); - return ret; - } - - /** - * Refreshes the state of the switches for all profiles, possibly adding or removing switches as - * needed. - */ - @Override - protected void refresh() { - BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":refresh: " + mBleBroadcastSourceInfo + " mSourceIndex" + mSourceInfoIndex); - mSourceIdPref.setSummary( - String.valueOf(mBleBroadcastSourceInfo.getSourceId())); - - BluetoothDevice dev = mBleBroadcastSourceInfo.getSourceDevice(); - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - String s = null; - if (dev != null && adapter != null) { - if (adapter.getAddress().equals(dev.getAddress())) - { - s = adapter.getName() + "(Self)"; - } else { - s = dev.getAlias(); - } - if (s == null) { - s = String.valueOf(dev.getAddress()); - } - } - if (s == null || s.equals(EMPTY_BD_ADDRESS)) { - BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":NULL source device"); - s = "EMPTY_ENTRY"; - } - mSourceDevicePref.setSummary(s); - mSourceEncStatusPref.setSummary( - getEncryptionStatusString( - mBleBroadcastSourceInfo.getEncryptionStatus()) - ); - - if (mBleBroadcastSourceInfo.isEmptyEntry()) { - BroadcastScanAssistanceUtils.debug(TAG, mSourceInfoIndex + ":Source Information seem to be Empty"); - if (mPAsyncCtrlNeeded) { - mSourceMetadataSyncSwitchPref.setEnabled(false); - } - mSourceAudioSyncSwitchPref.setEnabled(false); - mSourceUpdateBcastCodePref.setEnabled(false); - //Disable 'remove and update source Info' if It is empty entry - mSourceUpdateSourceInfoPref.setButton1Enabled(false); - mSourceUpdateSourceInfoPref.setButton2Enabled(false); - mSourceAudioSyncStatusPref.setEnabled(false); - mIsValueChanged = false; - } else { - //enable the Input controls - if (mPAsyncCtrlNeeded) { - mSourceMetadataSyncSwitchPref.setEnabled(true); - } - mSourceAudioSyncSwitchPref.setEnabled(true); - mSourceUpdateBcastCodePref.setEnabled(isPinUpdatedNeeded()); - - if (mIsButtonRefreshOnly != true) { - mSourceMetadataSyncStatusPref.setSummary( - getMetadataSyncStatusString(mBleBroadcastSourceInfo.getMetadataSyncState()) - ); - mSourceAudioSyncStatusPref.setSummary( - getAudioSyncStatusString(mBleBroadcastSourceInfo.getAudioSyncState()) - ); - mBisIndicies = mBleBroadcastSourceInfo.getBroadcastChannelsSyncStatus(); - if (mBisIndicies != null) { - String[] bisNames = new String[mBisIndicies.size()]; - boolean[] bisStatuses = new boolean[mBisIndicies.size()]; - Set hashSet = new HashSet(); - for (int i=0; i createPreferenceControllers(Context context) { - ArrayList controllers = new ArrayList<>(); - - if (mCachedDevice != null && mBleBroadcastSourceInfo != null) { - Lifecycle lifecycle = getSettingsLifecycle(); - controllers.add(new BleBroadcastSourceInfoDetailsController(context, this, mBleBroadcastSourceInfo, - mCachedDevice, mSourceInfoIndex, lifecycle)); - } - return controllers; - } -} diff --git a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BleBroadcastSourceInfoPreference.java b/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BleBroadcastSourceInfoPreference.java deleted file mode 100644 index 50c4636a93e16ed8ca13faf655f196a9b1cff897..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BleBroadcastSourceInfoPreference.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (C) 2008 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.settings.bluetooth; - -import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH; - -import android.app.settings.SettingsEnums; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BleBroadcastSourceInfo; -import android.content.Context; -import android.content.DialogInterface; -import android.content.res.Resources; -import android.graphics.drawable.Drawable; -import android.os.UserManager; -import android.text.Html; -import android.text.TextUtils; -import android.util.Pair; -import android.util.TypedValue; -import android.view.View; -import android.widget.ImageView; -import android.util.Log; - -import androidx.annotation.IntDef; -import androidx.annotation.VisibleForTesting; -import androidx.appcompat.app.AlertDialog; -import androidx.preference.Preference; -import androidx.preference.PreferenceViewHolder; - -import com.android.settings.R; -import com.android.settings.overlay.FeatureFactory; -import com.android.settings.widget.GearPreference; -import com.android.settingslib.bluetooth.BluetoothUtils; -import com.android.settingslib.bluetooth.CachedBluetoothDevice; -import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.Integer; -import java.lang.String; -/** - * BleBroadcastSourceInfoPreference is the preference type used to display each - * Broadcast Source information stored in the Remote Scan delegator. - */ -public final class BleBroadcastSourceInfoPreference extends GearPreference implements - CachedBluetoothDevice.Callback { - private static final String TAG = "BleBroadcastSourceInfoPreference"; - - private static String EMPTY_BD_ADDR = "00:00:00:00:00:00"; - - @Retention(RetentionPolicy.SOURCE) - @IntDef({SortType.TYPE_DEFAULT, - SortType.TYPE_FIFO}) - public @interface SortType { - int TYPE_DEFAULT = 1; - int TYPE_FIFO = 2; - } - - private final CachedBluetoothDevice mCachedDevice; - private BleBroadcastSourceInfo mBleSourceInfo; - private final Integer mIndex; - private final long mCurrentTime; - private final int mType; - - ///private String contentDescription = null; - //@VisibleForTesting - //boolean mNeedNotifyHierarchyChanged = false; - /* Talk-back descriptions for various BT icons */ - Resources mResources; - - public BleBroadcastSourceInfoPreference(Context context, CachedBluetoothDevice device, - BleBroadcastSourceInfo sourceInfo, - Integer index, @SortType int type) { - super(context, null); - mResources = getContext().getResources(); - mIndex = index; - - mCachedDevice = device; - mBleSourceInfo = sourceInfo; - mCachedDevice.registerCallback(this); - mCurrentTime = System.currentTimeMillis(); - mType = type; - - onDeviceAttributesChanged(); - } - - - @Override - protected boolean shouldHideSecondTarget() { - return (mBleSourceInfo == null); - } - - @Override - protected int getSecondTargetResId() { - return R.layout.preference_widget_gear; - } - - CachedBluetoothDevice getCachedDevice() { - return mCachedDevice; - } - - public BleBroadcastSourceInfo getBleBroadcastSourceInfo() { - return mBleSourceInfo; - } - - public void setBleBroadcastSourceInfo(BleBroadcastSourceInfo srcInfo) { - mBleSourceInfo = srcInfo; - //refresh - onDeviceAttributesChanged(); - } - - Integer getSourceInfoIndex() { - return mIndex; - } - - @Override - protected void onPrepareForRemoval() { - super.onPrepareForRemoval(); - mCachedDevice.unregisterCallback(this); - } - - String formSyncSummaryString(BleBroadcastSourceInfo srcInfo) { - String metadataStatus = "Metadata Synced"; - String audioSyncStatus = "Audio Synced"; - - if (srcInfo.getMetadataSyncState() == BleBroadcastSourceInfo.BROADCAST_ASSIST_PA_SYNC_STATE_IN_SYNC) { - metadataStatus = "Metadata Synced"; - } else { - metadataStatus = "Metadata not synced"; - } - - if (srcInfo.getAudioSyncState() == BleBroadcastSourceInfo.BROADCAST_ASSIST_AUDIO_SYNC_STATE_SYNCHRONIZED) { - audioSyncStatus = "Audio Synced"; - } else { - audioSyncStatus = "Audio not synced"; - } - return metadataStatus + ", " + audioSyncStatus; - } - - public void onDeviceAttributesChanged() { - BluetoothDevice dev = mBleSourceInfo.getSourceDevice(); - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - String s = null; - if (dev != null && adapter != null) { - if (adapter.getAddress().equals(dev.getAddress())) - { - s = adapter.getName() + "(Self)"; - } else { - s = dev.getAlias(); - } - if (s == null) { - s = String.valueOf(dev.getAddress()); - } - } - if (s == null || s.equals(EMPTY_BD_ADDR)) { - BroadcastScanAssistanceUtils.debug(TAG, "seem to be an entry source Info"); - s = "EMPTY ENTRY"; - } - setTitle(s); - setIcon(R.drawable.ic_media_stream); - if (!mBleSourceInfo.isEmptyEntry()) { - //Show the status only If it is not an Empty Entry - setSummary(formSyncSummaryString(mBleSourceInfo)); - } else { - setSummary(""); - } - setVisible(true); - - // This could affect ordering, so notify that - notifyHierarchyChanged(); - } - - - - @Override - public boolean equals(Object o) { - if ((o == null) || !(o instanceof BleBroadcastSourceInfoPreference)) { - BroadcastScanAssistanceUtils.debug(TAG, "Not an Instance of BleBroadcastSourceInfoPreference:"); - return false; - } - BleBroadcastSourceInfo otherSrc = ((BleBroadcastSourceInfoPreference) o).mBleSourceInfo; - BroadcastScanAssistanceUtils.debug(TAG, "Comparing: " + mBleSourceInfo); - BroadcastScanAssistanceUtils.debug(TAG, "TO: " + otherSrc); - boolean ret = (mBleSourceInfo.getSourceId() == otherSrc.getSourceId()); - BroadcastScanAssistanceUtils.debug(TAG, "equals returns: " + ret); - - return ret; - } - - @Override - public int hashCode() { - return mBleSourceInfo.hashCode(); - } - - @Override - public int compareTo(Preference another) { - if (!(another instanceof BleBroadcastSourceInfoPreference)) { - // Rely on default sort - return super.compareTo(another); - } - - switch (mType) { - case SortType.TYPE_DEFAULT: - BroadcastScanAssistanceUtils.debug(TAG, ">>compareTo"); - return mIndex > ((BleBroadcastSourceInfoPreference) another).getSourceInfoIndex() ? 1 : -1; - case SortType.TYPE_FIFO: - return mCurrentTime > ((BleBroadcastSourceInfoPreference) another).mCurrentTime ? 1 : -1; - default: - return super.compareTo(another); - } - } - - void onClicked() { - Context context = getContext(); - - final MetricsFeatureProvider metricsFeatureProvider = - FeatureFactory.getFactory(context).getMetricsFeatureProvider(); - - } -} diff --git a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BleBroadcastSourceInfoPreferenceCallback.java b/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BleBroadcastSourceInfoPreferenceCallback.java deleted file mode 100644 index 8f9a4fb50fc0dd06eb249166fe832b42d1041835..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BleBroadcastSourceInfoPreferenceCallback.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.bluetooth; - -import androidx.preference.Preference; - -/** - * Callback to add or remove {@link Preference} in Ble broadcast source info - * entries. - */ -public interface BleBroadcastSourceInfoPreferenceCallback { - /** - * Called when a Ble broadcast sourc Information is added - * @param preference present the device - */ - void onBroadcastSourceInfoAdded(Preference preference); - - /** - * Called when a Ble broadast source Information is removed - * @param preference present the device - */ - void onBroadcastSourceInfoRemoved(Preference preference); -} diff --git a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BleBroadcastSourceInfoUpdater.java b/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BleBroadcastSourceInfoUpdater.java deleted file mode 100644 index 6baa20a687a103d84591fb9bb9e55f4fd5939c01..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BleBroadcastSourceInfoUpdater.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.bluetooth; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BleBroadcastSourceInfo; -import android.content.Context; -import java.util.Iterator; -import android.os.Bundle; -import android.util.Log; - -import androidx.preference.Preference; - -import com.android.settings.R; -import com.android.settings.connecteddevice.DevicePreferenceCallback; -import com.android.settings.core.SubSettingLauncher; -import com.android.settings.dashboard.DashboardFragment; -import com.android.settings.widget.GearPreference; -import com.android.settingslib.bluetooth.BluetoothCallback; -import com.android.settingslib.bluetooth.BluetoothDeviceFilter; -import com.android.settingslib.bluetooth.CachedBluetoothDevice; -import com.android.settingslib.bluetooth.VendorCachedBluetoothDevice; -import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; -import com.android.settingslib.bluetooth.LocalBluetoothManager; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.lang.Integer; - -/** - * Update the Ble broadcast source Info preference entries. It retrieves the Bluetooth broadcast source - * information using CachedBluetoothDevice object from setting library - * {@link BluetoothCallback}. It notifies the upper level whether to add/remove the preference - * through {@link BleBroadcastSourceInfoPreferenceCallback} - * - * In {@link BleBroadcastSourceInfoUpdater}, it uses {@link BluetoothDeviceFilter.Filter} to detect - * whether the {@link CachedBluetoothDevice} is relevant. - */ -public abstract class BleBroadcastSourceInfoUpdater implements CachedBluetoothDevice.Callback, - BluetoothCallback { - private static final String TAG = "BleBroadcastSourceInfoUpdater"; - private static final boolean DBG = false; - - protected final BleBroadcastSourceInfoPreferenceCallback mBleSourceInfoPreferenceCallback; - protected final Map mPreferenceMap; - protected Context mPrefContext; - protected DashboardFragment mFragment; - protected final CachedBluetoothDevice mCachedDevice; - protected final VendorCachedBluetoothDevice mVendorCachedDevice; - private LocalBluetoothManager mLocalManager; - - final GearPreference.OnGearClickListener mSourceInfoEntryListener = pref -> { - launchSourceInfoDetails(pref); - }; - - public BleBroadcastSourceInfoUpdater(Context context, DashboardFragment fragment, - BleBroadcastSourceInfoPreferenceCallback aBleSourceInfoPreferenceCallback, - CachedBluetoothDevice device) { - this(fragment, aBleSourceInfoPreferenceCallback ,device); - } - - BleBroadcastSourceInfoUpdater(DashboardFragment fragment, - BleBroadcastSourceInfoPreferenceCallback aBleSourceInfoPreferenceCallback, - CachedBluetoothDevice device) { - mCachedDevice = device; - LocalBluetoothManager mgr = Utils.getLocalBtManager(mPrefContext); - LocalBluetoothProfileManager profileManager = mgr.getProfileManager(); - mVendorCachedDevice = VendorCachedBluetoothDevice.getVendorCachedBluetoothDevice(device, profileManager); - mFragment = fragment; - mBleSourceInfoPreferenceCallback = aBleSourceInfoPreferenceCallback; - mPreferenceMap = new HashMap(); - mLocalManager = Utils.getLocalBtManager(mPrefContext); - mLocalManager.getEventManager().registerCallback(this); - } - - /** - * Register the bluetooth event callback and update the list - */ - public void registerCallback() { - mCachedDevice.registerCallback(this); - forceUpdate(); - } - - /** - * Unregister the bluetooth event callback - */ - public void unregisterCallback() { - mCachedDevice.unregisterCallback(this); - } - - @Override - public void onBluetoothStateChanged(int bluetoothState) { - BroadcastScanAssistanceUtils.debug(TAG, "onBluetoothStateChanged"); - if (bluetoothState == BluetoothAdapter.STATE_OFF) { - removeAllBleBroadcastSourceInfosFromPreference(); - } - //forceUpdate(); - } - - /** - * Force to update the list of bluetooth devices - */ - public void forceUpdate() { - if (mCachedDevice != null && - mVendorCachedDevice.getNumberOfBleBroadcastReceiverStates() > 0) { - final Map srcInfos = - mVendorCachedDevice.getAllBleBroadcastreceiverStates(); - if (srcInfos == null) { - Log.e(TAG, "srcInfos is null"); - return; - } - for (Map.Entry entry: srcInfos.entrySet()) { - update(entry.getKey(), entry.getValue()); - } - } else { - BroadcastScanAssistanceUtils.debug(TAG, "remove all the preferences as there are no rcvr states"); - removeAllBleBroadcastSourceInfosFromPreference(); - } - } - - public void removeAllBleBroadcastSourceInfosFromPreference() { - Iterator> entries = mPreferenceMap.entrySet().iterator(); - while (entries.hasNext()) { - //for (Map.Entry entry: mPreferenceMap.entrySet()) { - Map.Entry entry = entries.next(); - //removePreference(entry.getKey(), entry.getValue()); - mBleSourceInfoPreferenceCallback.onBroadcastSourceInfoRemoved(entry.getValue()); - } - mPreferenceMap.clear(); - } - - @Override - public void onDeviceAttributesChanged() { - BroadcastScanAssistanceUtils.debug(TAG, "onDeviceAttributesChanged"); - forceUpdate(); - } - - /** - * Set the context to generate the {@link Preference}, so it could get the correct theme. - */ - public void setPrefContext(Context context) { - mPrefContext = context; - } - - /** - * Update whether to show {@link CachedBluetoothDevice} in the list. - */ - protected void update(Integer index, BleBroadcastSourceInfo sourceInfo) { - addPreference(index, sourceInfo); - } - - /** - * Add the {@link Preference} that represents the {@code cachedDevice} - */ - protected void addPreference(Integer index, BleBroadcastSourceInfo sourceInfo) { - final BluetoothDevice device = sourceInfo.getSourceDevice(); - final byte sourceId = sourceInfo.getSourceId(); - if (mPreferenceMap.containsKey(index) == false) { - BroadcastScanAssistanceUtils.debug(TAG, "source info addition"); - BleBroadcastSourceInfoPreference sourceInfoPreference = - new BleBroadcastSourceInfoPreference(mPrefContext, - mCachedDevice, - sourceInfo, - index, - BleBroadcastSourceInfoPreference.SortType.TYPE_DEFAULT); - sourceInfoPreference.setOnGearClickListener(mSourceInfoEntryListener); - if (this instanceof Preference.OnPreferenceClickListener) { - sourceInfoPreference.setOnPreferenceClickListener( - (Preference.OnPreferenceClickListener)this); - } - BroadcastScanAssistanceUtils.debug(TAG, "source info newly added: " + index); - mPreferenceMap.put(index, sourceInfoPreference); - mBleSourceInfoPreferenceCallback.onBroadcastSourceInfoAdded(sourceInfoPreference); - } else { - BleBroadcastSourceInfoPreference pref = (BleBroadcastSourceInfoPreference)mPreferenceMap.get(index); - BleBroadcastSourceInfo currentSi = pref.getBleBroadcastSourceInfo(); - if (currentSi != null && currentSi.equals(sourceInfo)) { - BroadcastScanAssistanceUtils.debug(TAG, "No change in SI" + index); - } else { - BroadcastScanAssistanceUtils.debug(TAG, "source info Updated: " + index); - pref.setBleBroadcastSourceInfo (sourceInfo); - - /*mBleSourceInfoPreferenceCallback.onBroadcastSourceInfoRemoved(mPreferenceMap.get(index)); - mPreferenceMap.remove(index); - - BleBroadcastSourceInfoPreference sourceInfoPreference = - new BleBroadcastSourceInfoPreference(mPrefContext, - mCachedDevice, - sourceInfo, - index, - BleBroadcastSourceInfoPreference.SortType.TYPE_DEFAULT); - sourceInfoPreference.setOnGearClickListener(mSourceInfoEntryListener); - if (this instanceof Preference.OnPreferenceClickListener) { - sourceInfoPreference.setOnPreferenceClickListener( - (Preference.OnPreferenceClickListener)this); - } - BroadcastScanAssistanceUtils.debug(TAG, "source info added again: " + index); - mPreferenceMap.put(index, sourceInfoPreference); - mBleSourceInfoPreferenceCallback.onBroadcastSourceInfoAdded(sourceInfoPreference);*/ - } - } - } - - /** - * Remove the {@link Preference} that represents the {@code cachedDevice} - */ - protected void removePreference(int index, Preference pref) { - if (mPreferenceMap.containsKey(index)) { - mBleSourceInfoPreferenceCallback.onBroadcastSourceInfoRemoved(mPreferenceMap.get(index)); - mPreferenceMap.remove(index); - } - } - - /** - * Get {@link CachedBluetoothDevice} from {@link Preference} and it is used to init - * {@link SubSettingLauncher} to launch {@link BluetoothDeviceDetailsFragment} - */ - protected void launchSourceInfoDetails(Preference preference) { - final BleBroadcastSourceInfo srcInfo = - ((BleBroadcastSourceInfoPreference) preference).getBleBroadcastSourceInfo(); - if (srcInfo == null) { - return; - } - final int index = ((BleBroadcastSourceInfoPreference) preference).getSourceInfoIndex(); - final Bundle args = new Bundle(); - args.putString(BleBroadcastSourceInfoDetailsFragment.KEY_DEVICE_ADDRESS, - mCachedDevice.getAddress()); - args.putParcelable(BleBroadcastSourceInfoDetailsFragment.KEY_SOURCE_INFO, - srcInfo); - args.putInt(BleBroadcastSourceInfoDetailsFragment.KEY_SOURCE_INFO_INDEX, - index); - - new SubSettingLauncher(mFragment.getContext()) - .setDestination(BleBroadcastSourceInfoDetailsFragment.class.getName()) - .setArguments(args) - .setTitleRes(R.string.source_info_details_title) - .setSourceMetricsCategory(mFragment.getMetricsCategory()) - .launch(); - } -} diff --git a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothBroadcastEnableController.java b/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothBroadcastEnableController.java deleted file mode 100644 index 29f565c41fb94a48953ce7293e4822ba80551109..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothBroadcastEnableController.java +++ /dev/null @@ -1,247 +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. - * - ******************************************************************************/ - - -package com.android.settings.bluetooth; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothBroadcast; -import android.content.Context; -import android.util.Log; -import android.os.SystemProperties; -import android.os.Handler; -import android.os.Message; - -import androidx.preference.PreferenceScreen; -import androidx.preference.SwitchPreference; -import com.android.settingslib.RestrictedSwitchPreference; -import com.android.settings.core.TogglePreferenceController; -import com.android.settingslib.bluetooth.BluetoothCallback; -import com.android.settingslib.bluetooth.BluetoothUtils; -import com.android.settingslib.bluetooth.BroadcastProfile; -import com.android.settingslib.bluetooth.LocalBluetoothProfile; -import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; -import com.android.settingslib.core.lifecycle.LifecycleObserver; -import com.android.settingslib.core.lifecycle.events.OnPause; -import com.android.settingslib.core.lifecycle.events.OnResume; -import com.android.settingslib.core.lifecycle.events.OnDestroy; -import com.android.settings.connecteddevice.BluetoothDashboardFragment; -import com.android.settingslib.bluetooth.LocalBluetoothManager; -import androidx.annotation.Keep; - -@Keep -public class BluetoothBroadcastEnableController extends TogglePreferenceController - implements LifecycleObserver, OnResume, OnPause, OnDestroy, BluetoothCallback { - - public static final String TAG = "BluetoothBroadcastEnableController"; - public static final int BROADCAST_AUDIO_MASK = 0x04; - public static final String BLUETOOTH_LE_AUDIO_MASK_PROP = "persist.vendor.service.bt.adv_audio_mask"; - public static final String KEY_BROADCAST_ENABLE = "bluetooth_screen_broadcast_enable"; - private RestrictedSwitchPreference mPreference = null; - private BluetoothAdapter mBluetoothAdapter; - private boolean mState = false; - private boolean reset_pending = false; - private Context mContext; - private BroadcastProfile mBapBroadcastProfile = null; - private boolean isBluetoothLeBroadcastAudioSupported = false; - private boolean mCallbacksRegistered = false; - private LocalBluetoothManager mManager = null; - public BluetoothBroadcastEnableController(Context context, String key) { - super(context, key); - Log.d(TAG, "Constructor() with key"); - Init(context); - } - - private void Init(Context context) { - mContext = context; - int leAudioMask = SystemProperties.getInt(BLUETOOTH_LE_AUDIO_MASK_PROP, 0); - isBluetoothLeBroadcastAudioSupported = ((leAudioMask & BROADCAST_AUDIO_MASK) == BROADCAST_AUDIO_MASK); - if(isBluetoothLeBroadcastAudioSupported){ - mManager = Utils.getLocalBtManager(context); - mBapBroadcastProfile = (BroadcastProfile) mManager.getProfileManager().getBroadcastProfile(); - if (!mCallbacksRegistered) { - Log.d(TAG, "Registering EventManager callbacks"); - mCallbacksRegistered = true; - mManager.getEventManager().registerCallback(this); - } - } - Log.d(TAG, "Init done"); - } - - private void updateState(boolean newState) { - Log.d(TAG, "updateState req " + Boolean.toString(newState)); - if (newState != mState) { - if (mPreference != null) mPreference.setEnabled(false); - Log.d(TAG, "updateState to " + Boolean.toString(newState)); - mBapBroadcastProfile.setBroadcastMode(newState); - } - } - - private void onStateChanged(boolean newState) { - Log.d(TAG, "onStateChanged " + Boolean.toString(newState)); - mState = newState; - if (mPreference != null) mPreference.setChecked(mState); - if (mState == false && reset_pending == true) { - reset_pending = false; - updateState(true); - } - } - - private final Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - Log.d(TAG, "BT state, msg = " + Integer.toString(msg.what)); - switch (msg.what) { - case BluetoothAdapter.STATE_ON: - if (mPreference != null) mPreference.setEnabled(true); - mBapBroadcastProfile = (BroadcastProfile) mManager.getProfileManager().getBroadcastProfile(); - break; - case BluetoothAdapter.STATE_TURNING_ON: - case BluetoothAdapter.STATE_OFF: - case BluetoothAdapter.STATE_TURNING_OFF: - reset_pending = false; - onStateChanged(false); - mBapBroadcastProfile = null; - if (mPreference != null) mPreference.setEnabled(false); - break; - } - } - }; - - @Override - public void onBluetoothStateChanged(int newBtState) { - Log.d(TAG, "onBluetoothStateChanged" + Integer.toString(newBtState)); - - switch (newBtState) { - case BluetoothAdapter.STATE_ON: - mHandler.sendMessageDelayed(mHandler.obtainMessage(newBtState), 200); - break; - case BluetoothAdapter.STATE_TURNING_ON: - case BluetoothAdapter.STATE_OFF: - case BluetoothAdapter.STATE_TURNING_OFF: - mHandler.sendMessage(mHandler.obtainMessage(newBtState)); - break; - } - } - - @Override - public void onBroadcastStateChanged(int newBapState) { - Log.d(TAG, "onBroadcastStateChanged" + Integer.toString(newBapState)); - - switch (newBapState) { - case BluetoothBroadcast.STATE_ENABLED: - if (mPreference != null) mPreference.setEnabled(true); - onStateChanged(true); - break; - case BluetoothBroadcast.STATE_DISABLED: - if (mPreference != null) mPreference.setEnabled(true); - onStateChanged(false); - break; - } - } - - @Override - public void onBroadcastKeyGenerated() { - Log.d(TAG, "onBroadcastKeyGenerated"); - // Encryption key got updated. Reset BAP? - if (mState == true) { - reset_pending = true; - updateState(false); - } - } - - @Override - public String getPreferenceKey() { - Log.d(TAG, "getPreferenceKey"); - return KEY_BROADCAST_ENABLE; - } - - @Override - public void displayPreference(PreferenceScreen screen) { - super.displayPreference(screen); - Log.d(TAG, "displayPreference"); - mPreference = screen.findPreference(getPreferenceKey()); - if(isBluetoothLeBroadcastAudioSupported) { - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - onBluetoothStateChanged(mBluetoothAdapter.getState()); - if ((mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) && - (mBapBroadcastProfile.isProfileReady())) { - int bapState = mBapBroadcastProfile.getBroadcastStatus(); - Log.d(TAG, "get status done"); - if ((bapState == BluetoothBroadcast.STATE_ENABLED) || - (bapState == BluetoothBroadcast.STATE_STREAMING)) - onStateChanged(true); - else - onStateChanged(false); - } - } else { - mPreference.setVisible(false); - } - } - - @Override - public boolean isChecked() { - return mState; - } - - @Override - public boolean setChecked(boolean isChecked) { - updateState(isChecked); - return true; - } - - @Override - public int getAvailabilityStatus() { - Log.d(TAG, "getAvailabilityStatus"); - if(isBluetoothLeBroadcastAudioSupported) { - return AVAILABLE; - } else { - return UNSUPPORTED_ON_DEVICE; - } - } - - @Override - public boolean hasAsyncUpdate() { - Log.d(TAG, "hasAsyncUpdate"); - return true; - } - - @Override - public boolean isPublicSlice() { - Log.d(TAG, "isPublicSlice"); - return true; - } - - @Override - public void onResume() { - Log.d(TAG, "onResume"); - } - - @Override - public void onPause() { - Log.d(TAG, "onPause"); - } - - @Override - public void onDestroy() { - Log.d(TAG, "onDestory"); - mCallbacksRegistered = false; - if (mManager != null) - mManager.getEventManager().unregisterCallback(this); - } -} diff --git a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothBroadcastPinController.java b/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothBroadcastPinController.java deleted file mode 100644 index 500d9414815914075e60c6e59a6fa02c28468a04..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothBroadcastPinController.java +++ /dev/null @@ -1,237 +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. - * - ******************************************************************************/ - - - -package com.android.settings.bluetooth; - -import java.io.UnsupportedEncodingException; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; - -import android.app.settings.SettingsEnums; -import android.bluetooth.BluetoothBroadcast; -import android.content.Context; -import android.content.pm.PackageManager; -import android.util.Log; -import android.view.View; -import android.view.LayoutInflater; -import android.text.TextUtils; -import android.widget.TextView; -import android.bluetooth.BluetoothAdapter; -import android.os.Handler; -import android.os.SystemProperties; - -import androidx.annotation.VisibleForTesting; -import androidx.preference.Preference; -import androidx.preference.PreferenceFragmentCompat; -import androidx.fragment.app.Fragment; -import androidx.preference.PreferenceScreen; - -import com.android.settingslib.bluetooth.BluetoothCallback; -import com.android.settingslib.bluetooth.BluetoothUtils; -import com.android.settingslib.bluetooth.BroadcastProfile; -import com.android.settingslib.bluetooth.LocalBluetoothProfile; -import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; -import com.android.settingslib.RestrictedPreference; -import com.android.settings.core.BasePreferenceController; -import com.android.settings.core.PreferenceControllerMixin; -import com.android.settings.overlay.FeatureFactory; -import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; -import com.android.settingslib.core.lifecycle.events.OnDestroy; -import com.android.settingslib.widget.LayoutPreference; -import com.android.settingslib.bluetooth.LocalBluetoothManager; -import com.android.settings.R; -import com.android.settings.core.instrumentation.InstrumentedDialogFragment; -import androidx.annotation.Keep; - -/** - * Controller that shows Pin for BLE Broadcast Audio - */ -@Keep -public class BluetoothBroadcastPinController extends BasePreferenceController - implements OnDestroy, BluetoothCallback { - public static final String TAG = "BluetoothBroadcastPinController"; - public static final int BROADCAST_AUDIO_MASK = 0x04; - public static final String BLUETOOTH_LE_AUDIO_MASK_PROP = "persist.vendor.service.bt.adv_audio_mask"; - public static final String KEY_BROADCAST_AUDIO_PIN = "bluetooth_screen_broadcast_pin_configure"; - - private BluetoothAdapter mBluetoothAdapter; - private Fragment mFragment = null; - private MetricsFeatureProvider mMetricsFeatureProvider; - @VisibleForTesting - RestrictedPreference mPreference; - private Context mContext; - - private boolean isBluetoothLeBroadcastAudioSupported = false; - private boolean mCallbacksRegistered = false; - private LocalBluetoothManager mManager = null; - private Handler mHandler; - private Runnable mRunnable = new Runnable() { - @Override - public void run() { - onBroadcastKeyGenerated(); - } - }; - - public BluetoothBroadcastPinController(Context context) { - super(context, KEY_BROADCAST_AUDIO_PIN); - int leAudioMask = SystemProperties.getInt(BLUETOOTH_LE_AUDIO_MASK_PROP, 0); - isBluetoothLeBroadcastAudioSupported = ((leAudioMask & BROADCAST_AUDIO_MASK) == BROADCAST_AUDIO_MASK); - Log.d(TAG, "Constructor()"); - mContext = context; - mHandler = new Handler(); - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - if(isBluetoothLeBroadcastAudioSupported) { - mManager = Utils.getLocalBtManager(context); - if (!mCallbacksRegistered) { - Log.d(TAG, "Registering EventManager callbacks"); - mCallbacksRegistered = true; - mManager.getEventManager().registerCallback(this); - } - } - } - - public BluetoothBroadcastPinController(Context context, PreferenceFragmentCompat fragment, String prefKey) { - super(context, KEY_BROADCAST_AUDIO_PIN); - Log.d(TAG, "PinController()" + prefKey); - mFragment = fragment; - mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); - } - - @VisibleForTesting - public void setFragment(Fragment fragment) { - Log.d(TAG, "setFragment"); - mFragment = fragment; - } - - @Override - public int getAvailabilityStatus() { - Log.d(TAG, "getAvailabilityStatus"); - if(isBluetoothLeBroadcastAudioSupported) { - return AVAILABLE; - } else { - return UNSUPPORTED_ON_DEVICE; - } - } - - @Override - public String getPreferenceKey() { - return KEY_BROADCAST_AUDIO_PIN; - } - - @Override - public void displayPreference(PreferenceScreen screen) { - super.displayPreference(screen); - Log.d(TAG, "displayPreference"); - mPreference = screen.findPreference(getPreferenceKey()); - if(isBluetoothLeBroadcastAudioSupported) { - onBroadcastKeyGenerated(); - } else { - mPreference.setVisible(false); - } - } - - @Override - public boolean handlePreferenceTreeClick(Preference preference) { - Log.d(TAG, "PinController: handlePreferenceTreeClick"); - if (KEY_BROADCAST_AUDIO_PIN.equals(preference.getKey())) { - Log.d(TAG, "PinController: handlePreferenceTreeClick true"); - new BluetoothBroadcastPinFragment() - .show(mFragment.getFragmentManager(), "PinFragment"); - return true; - } - - return false; - } - - @Override - public void onBluetoothStateChanged(int newBtState) { - Log.d(TAG, "onBluetoothStateChanged" + Integer.toString(newBtState)); - int delay = 0; - switch (newBtState) { - case BluetoothAdapter.STATE_ON: - delay = 200; - case BluetoothAdapter.STATE_OFF: - mHandler.postDelayed(mRunnable, delay); - break; - } - } - - private String convertBytesToString(byte[] pin) { - if (pin.length != 16) { - Log.e (TAG, "Not 16 bytes ++++++++++++"); - return ""; - } - byte[] temp = new byte[16]; - int i = 0, j = 0; - // Reverse the pin and discard the padding - for (i = 0; i < 16; i++) { - if (pin[15-i] == 0) break; - temp[j++] = pin[15-i]; - } - String str; - if (j == 0) - str = new String(""); // unencrypted - else - str = new String(Arrays.copyOfRange(temp,0,j), StandardCharsets.UTF_8); - Log.d(TAG, "Pin: " + str); - return str; - } - - @Override - public void onBroadcastKeyGenerated() { - Log.d(TAG, "onBroadcastKeyGenerated"); - String summary = "Broadcast code: "; - String keyStr = "Unavailable"; - - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - LocalBluetoothProfileManager profileManager = mManager.getProfileManager(); - BroadcastProfile bapProfile = (BroadcastProfile) profileManager.getBroadcastProfile(); - if ((mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) && - (bapProfile.isProfileReady())) { - byte[] key = bapProfile.getEncryptionKey(); - // Key can only be 16 byte long - if (key.length == 16) { - for(int i = 0; i mRadioButtonIds = new ArrayList<>(); - private List mRadioButtonStrings = new ArrayList<>(); - - private int getDialogTitle() { - return R.string.bluetooth_broadcast_pin_configure_dialog; - } - - private void updatePinConfiguration() { - Log.d(TAG, "updatePinConfiguration with " + Integer.toString(mUserSelectedPinConfiguration)); - if (mUserSelectedPinConfiguration == -1) { - Log.e(TAG, "no pin selected"); - return; - } - // Call lower layer to generate new pin - LocalBluetoothManager mManager = Utils.getLocalBtManager(mContext); - LocalBluetoothProfileManager profileManager = mManager.getProfileManager(); - BroadcastProfile bapProfile = (BroadcastProfile) profileManager.getBroadcastProfile(); - if (mUserSelectedPinConfiguration != 0) - bapProfile.setEncryption(true, mUserSelectedPinConfiguration, false); - else - bapProfile.setEncryption(false, mUserSelectedPinConfiguration, false); - } - - @Override - public void onAttach(Context context) { - Log.d(TAG, "onAttach"); - super.onAttach(context); - mContext = context; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - Log.d(TAG, "onCreate"); - super.onCreate(savedInstanceState); - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - Log.d(TAG, "onActivityCreated"); - super.onActivityCreated(savedInstanceState); - //Dialog mDialog = onCreateDialog(new Bundle()); - //this.show(this.getActivity().getSupportFragmentManager(), "PinFragment"); - } - - /* - public void show() { - Log.e(TAG, "show"); - this.show(this.getActivity().getSupportFragmentManager(), "PinFragment"); - } - */ - - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - //String deviceName = getDeviceName(); - Log.d(TAG, "onCreateDialog - enter"); - if (savedInstanceState != null) { - Log.e(TAG, "savedInstanceState != null"); - } - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) - .setTitle(getDialogTitle()) - .setView(createDialogView()) - .setPositiveButton(R.string.okay, (dialog, which) -> { - //setDeviceName(mDeviceNameView.getText().toString().trim()); - updatePinConfiguration(); - }) - .setNegativeButton(android.R.string.cancel, null); - mAlertDialog = builder.create(); - Log.d(TAG, "onCreateDialog - exit"); - return mAlertDialog; - } - - @Override - public int getMetricsCategory() { - return SettingsEnums.BLUETOOTH_FRAGMENT; - } - - @Override - public void onSaveInstanceState(Bundle outState) { - Log.d(TAG, "onSaveInstanceState"); - } - - private int getRadioButtonGroupId() { - return R.id.bluetooth_broadcast_pin_config_radio_group; - } - - private void setCurrentPin(String pin) { - mCurrentPin = pin; - } - - private String getCurrentPin() { - return mCurrentPin; - } - - @Override - public void onCheckedChanged(RadioGroup group, int checkedId) { - Log.d(TAG, "Index changed to " + checkedId); - // radioButton = (RadioButton) view.findViewById(checkedId); - int index = mRadioButtonIds.indexOf(checkedId); - Log.d(TAG, "index"); - String[] stringArrayValues = getContext().getResources().getStringArray( - R.array.bluetooth_broadcast_pin_config_values); - mUserSelectedPinConfiguration = Integer.parseInt(stringArrayValues[index]); - Log.d(TAG, "Selected Pin Configuration " + Integer.toString(mUserSelectedPinConfiguration)); - } - - private View createDialogView() { - Log.d(TAG, "onCreateDialogView - enter"); - final LayoutInflater layoutInflater = (LayoutInflater)getActivity() - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - View view = layoutInflater.inflate(R.xml.bluetooth_broadcast_pin_config, null); - - final RadioGroup radioGroup = (RadioGroup) view.findViewById(getRadioButtonGroupId()); - if (radioGroup == null) { - Log.e (TAG, "Not able to find RadioGroup"); - return null; - } - radioGroup.clearCheck(); - radioGroup.setOnCheckedChangeListener(this); - - // Fill up the Radio Group - mRadioButtonIds.add(R.id.bluetooth_broadcast_pin_unencrypted); - mRadioButtonIds.add(R.id.bluetooth_broadcast_pin_4); - mRadioButtonIds.add(R.id.bluetooth_broadcast_pin_16); - String[] stringArray = getContext().getResources().getStringArray( - R.array.bluetooth_broadcast_pin_config_titles); - for (int i = 0; i < stringArray.length; i++) { - mRadioButtonStrings.add(stringArray[i]); - } - RadioButton radioButton; - for (int i = 0; i < mRadioButtonStrings.size(); i++) { - radioButton = (RadioButton) view.findViewById(mRadioButtonIds.get(i)); - if (radioButton == null) { - Log.e(TAG, "Unable to show dialog by no radio button:" + mRadioButtonIds.get(i)); - return null; - } - radioButton.setText(mRadioButtonStrings.get(i)); - radioButton.setEnabled(true); - } - - mCurrentPinView = (TextView) view.findViewById(R.id.bluetooth_broadcast_current_pin); - //mCurrentPinView.setText("Current Pin is " + getCurrentPin()); - Log.d(TAG, "onCreateDialogView - exit"); - return view; - } - - @Override - public void onDestroy() { - super.onDestroy(); - Log.d(TAG, "onDestroy"); - mAlertDialog = null; - mOkButton = null; - mCurrentPinView = null; - mRadioButtonIds = new ArrayList<>(); - mRadioButtonStrings = new ArrayList<>(); - mUserSelectedPinConfiguration = -1; - } - - @Override - public void onResume() { - super.onResume(); - Log.d(TAG, "onResume"); - if (mOkButton == null) { - if (mAlertDialog != null) { - mOkButton = mAlertDialog.getButton(DialogInterface.BUTTON_POSITIVE); - mOkButton.setEnabled(true); - } else { - Log.d(TAG, "onResume: mAlertDialog is null"); - } - } - } -} diff --git a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothBroadcastSourceInfoEntries.java b/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothBroadcastSourceInfoEntries.java deleted file mode 100644 index 110d9b7b1cbf5560d3923d6cf36c04ec0d5803c6..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothBroadcastSourceInfoEntries.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - *Copyright (c) 2018, The Linux Foundation. All rights reserved. - * - * Copyright (C) 2017 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.settings.bluetooth; - -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BleBroadcastSourceInfo; -import android.content.Context; -import android.util.Log; - -import androidx.preference.Preference; - -import com.android.settings.bluetooth.BleBroadcastSourceInfoPreferenceCallback; -import com.android.settings.dashboard.DashboardFragment; -import com.android.settingslib.bluetooth.CachedBluetoothDevice; - -/** - * Maintain and update saved bluetooth devices(bonded but not connected) - */ -public class BluetoothBroadcastSourceInfoEntries extends BleBroadcastSourceInfoUpdater - implements Preference.OnPreferenceClickListener { - private static final String TAG = "BluetoothBroadcastSourceInfoEntries"; - - - public BluetoothBroadcastSourceInfoEntries(Context context, DashboardFragment fragment, - BleBroadcastSourceInfoPreferenceCallback bleBroadcastSourceInfoPreferenceCallback, - CachedBluetoothDevice device) { - super(context, fragment, bleBroadcastSourceInfoPreferenceCallback, device); - } - - @Override - public boolean onPreferenceClick(Preference preference) { - final BleBroadcastSourceInfo srcInfo = ((BleBroadcastSourceInfoPreference) preference) - .getBleBroadcastSourceInfo(); - BroadcastScanAssistanceUtils.debug(TAG, "onPreferenceClick: " + srcInfo); - return true; - } -} diff --git a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDetailsAddSourceButtonController.java b/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDetailsAddSourceButtonController.java deleted file mode 100644 index 536bc1bfb82a7eff7f7ef5c53b23ec54ffc31b5f..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothDetailsAddSourceButtonController.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.bluetooth; - -import android.content.Context; - -import androidx.preference.PreferenceFragmentCompat; -import androidx.preference.PreferenceScreen; - -import com.android.settings.R; -import com.android.settingslib.bluetooth.CachedBluetoothDevice; -import com.android.settingslib.core.lifecycle.Lifecycle; -import com.android.settingslib.widget.ActionButtonsPreference; -import com.android.settingslib.bluetooth.BCProfile; -import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; -import com.android.settingslib.bluetooth.LocalBluetoothManager; -import android.util.Log; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.FutureTask; -import com.android.settings.core.SubSettingLauncher; -import android.app.settings.SettingsEnums; -import android.os.Bundle; -import android.bluetooth.BluetoothProfile; -/** - * This class adds two buttons: one to connect/disconnect from a device (depending on the current - * connected state), and one to "Search for LE audio Broadcast sources" around. - */ -public class BluetoothDetailsAddSourceButtonController extends BluetoothDetailsController - implements CachedBluetoothDevice.Callback { - private static final String KEY_ACTION_BUTTONS = "sync_helper_buttons"; - private static final String TAG = "BluetoothDetailsAddSourceButtonController"; - private boolean mIsConnected = false; - - private ActionButtonsPreference mActionButtons; - protected LocalBluetoothProfileManager mProfileManager; - private LocalBluetoothManager mLocalBluetoothManager; - private BCProfile mBCProfile = null; - - - public BluetoothDetailsAddSourceButtonController(Context context, PreferenceFragmentCompat fragment, - CachedBluetoothDevice device, Lifecycle lifecycle) { - super(context, fragment, device, lifecycle); - device.registerCallback(this); - - } - - private void onAddLESourcePressed() { - final Bundle args = new Bundle(); - args.putString(BluetoothSADetail.KEY_DEVICE_ADDRESS, - mCachedDevice.getDevice().getAddress()); - args.putShort(BluetoothSADetail.KEY_GROUP_OP, - (short)0); - - new SubSettingLauncher(mContext) - .setDestination(BluetoothSADetail.class.getName()) - .setArguments(args) - .setTitleRes(R.string.bluetooth_search_broadcasters) - .setSourceMetricsCategory(SettingsEnums.BLUETOOTH_DEVICE_PICKER) - .launch(); - } - - @Override - public void onDeviceAttributesChanged() { - refresh(); - } - - @Override - protected void init(PreferenceScreen screen) { - BroadcastScanAssistanceUtils.debug(TAG, "init"); - mLocalBluetoothManager = Utils.getLocalBtManager(mContext); - mProfileManager = mLocalBluetoothManager.getProfileManager(); - mBCProfile = (BCProfile)mProfileManager.getBCProfile(); - - mActionButtons = ((ActionButtonsPreference) screen.findPreference( - getPreferenceKey())) - .setButton1Text(R.string.add_source_button_text) - .setButton1Icon(R.drawable.ic_add_24dp) - .setButton1OnClickListener((view) -> onAddLESourcePressed()) - .setButton1Enabled(false) - ; - } - - @Override - protected void refresh() { - BroadcastScanAssistanceUtils.debug(TAG, "refresh"); - if (mBCProfile != null) { - mIsConnected = mBCProfile.getConnectionStatus(mCachedDevice.getDevice()) == BluetoothProfile.STATE_CONNECTED; - } - if (mIsConnected) { - mActionButtons - .setButton1Enabled(true); - } else { - BroadcastScanAssistanceUtils.debug(TAG, "Bass is not connected for thsi device>>"); - mActionButtons - .setButton1Enabled(false); - } - } - - @Override - public String getPreferenceKey() { - return KEY_ACTION_BUTTONS; - } - -} diff --git a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothSADetail.java b/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothSADetail.java deleted file mode 100644 index 174332cf2683aa0b45c849e81351920c27a9dba4..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BluetoothSADetail.java +++ /dev/null @@ -1,655 +0,0 @@ -/* - * Copyright (C) 2017 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.settings.bluetooth; - -import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH; - -import android.app.settings.SettingsEnums; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.content.Context; -import android.os.Bundle; -import android.util.Log; -import android.widget.Toast; -import android.text.Html; -import android.widget.EditText; -import android.widget.RadioButton; -import android.view.View; -import android.widget.RadioGroup; -import android.bluetooth.le.ScanResult; -import android.bluetooth.IBluetoothManager; -import java.util.Arrays; -import java.util.Map; -import java.util.List; -import android.bluetooth.le.ScanRecord; -import android.app.Activity; - -import androidx.appcompat.app.AlertDialog; -import android.content.DialogInterface; -import android.text.TextUtils; - -import com.android.settings.R; -import com.android.settingslib.bluetooth.BluetoothDeviceFilter; -import com.android.settingslib.bluetooth.CachedBluetoothDevice; -import com.android.settingslib.bluetooth.VendorCachedBluetoothDevice; -import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; -import com.android.settingslib.bluetooth.BCProfile; - -import android.bluetooth.BleBroadcastAudioScanAssistManager; -import android.bluetooth.BleBroadcastAudioScanAssistCallback; -import android.bluetooth.BleBroadcastSourceInfo; -import android.bluetooth.BleBroadcastSourceChannel; - -import com.android.settingslib.search.Indexable; -import com.android.settingslib.widget.FooterPreference; -import androidx.preference.Preference; -import android.widget.ListView; -import android.text.BidiFormatter; -import android.widget.ArrayAdapter; -import android.widget.AdapterView; -import android.widget.CheckedTextView; - -/** - * BluetoothSADetail is a page to scan bluetooth devices and pair them. - */ -public class BluetoothSADetail extends DeviceListPreferenceFragment implements - Indexable { - private static final String TAG = "BluetoothSADetail"; - private static final boolean DBG = true; - - public static final String KEY_DEVICE_ADDRESS = "device_address"; - public static final String KEY_GROUP_OP = "group_op"; - static final String KEY_AVAIL_LE_AUDIO_SOURCES = "available_audio_sources"; - static final String KEY_FOOTER_PREF = "footer_preference"; - static final String SCAN_DEL_NAME = "Scan Delegator"; - - BluetoothProgressCategory mAvailableDevicesCategory; - FooterPreference mFooterPreference; - - private AlertDialog mScanAssistDetailsDialog; - private boolean mInitialScanStarted; - private CachedBluetoothDevice mCachedDevice; - Preference mScanDelegatorName; - String mSyncState; - BleBroadcastAudioScanAssistManager mScanAssistManager; - protected LocalBluetoothProfileManager mProfileManager; - String mBroadcastCode; - Context mContext; - CachedBluetoothDevice clickedDevice = null; - String mBroadcastPinCode = null; - boolean mScanning = true; - boolean mGroupOperation = false; - AlertDialog mCommonMsgDialog = null; - - private String getBluetoothName(BluetoothDevice dev) { - String aliasName = null; - if (dev == null) { - aliasName = SCAN_DEL_NAME; - } else { - aliasName = dev.getAlias(); - aliasName = TextUtils.isEmpty(aliasName) ? dev.getAddress() : aliasName; - if (aliasName == null) { - aliasName = SCAN_DEL_NAME; - } - } - BroadcastScanAssistanceUtils.debug(TAG, "getBluetoothName returns" + aliasName); - return aliasName; - } - - private int getSourceSelectionErrMessage(int status) { - int errorMessage = R.string.bluetooth_source_selection_error_message; - switch (status) { - case BleBroadcastAudioScanAssistCallback.BASS_STATUS_COLOCATED_SRC_UNAVAILABLE: - case BleBroadcastAudioScanAssistCallback.BASS_STATUS_SOURCE_UNAVAILABLE: - errorMessage = R.string.bluetooth_source_selection_error_src_unavail_message; - break; - case BleBroadcastAudioScanAssistCallback.BASS_STATUS_INVALID_SOURCE_SELECTED: - case BleBroadcastAudioScanAssistCallback.BASS_STATUS_INVALID_SOURCE_ID: - errorMessage = R.string.bluetooth_source_selection_error_message; - break; - case BleBroadcastAudioScanAssistCallback.BASS_STATUS_DUPLICATE_ADDITION : - errorMessage = R.string.bluetooth_source_dup_addition_error_message; - break; - case BleBroadcastAudioScanAssistCallback.BASS_STATUS_NO_EMPTY_SLOT : - errorMessage = R.string.bluetooth_source_no_empty_slot_error_message; - break; - } - return errorMessage; - } - - private int getSourceAdditionErrMessage(int status) { - int errorMessage = R.string.bluetooth_source_addition_error_message; - switch (status) { - case BleBroadcastAudioScanAssistCallback.BASS_STATUS_DUPLICATE_ADDITION : - errorMessage = R.string.bluetooth_source_dup_addition_error_message; - break; - case BleBroadcastAudioScanAssistCallback.BASS_STATUS_NO_EMPTY_SLOT : - errorMessage = R.string.bluetooth_source_no_empty_slot_error_message; - break; - } - return errorMessage; - } - - private int getSourceRemovalErrMessage(int status) { - int errorMessage = R.string.bluetooth_source_removal_error_message; - switch (status) { - case BleBroadcastAudioScanAssistCallback.BASS_STATUS_FATAL : - errorMessage = R.string.bluetooth_source_removal_error_message; - break; - case BleBroadcastAudioScanAssistCallback.BASS_STATUS_INVALID_GROUP_OP : - errorMessage = R.string.bluetooth_source_remove_invalid_group_op; - break; - case BleBroadcastAudioScanAssistCallback.BASS_STATUS_INVALID_SOURCE_ID : - errorMessage = R.string.bluetooth_source_remove_invalid_src_id; - break; - } - return errorMessage; - } - - private int getSourceUpdateErrMessage(int status) { - int errorMessage = R.string.bluetooth_source_update_error_message; - switch (status) { - case BleBroadcastAudioScanAssistCallback.BASS_STATUS_FATAL : - errorMessage = R.string.bluetooth_source_update_error_message; - break; - case BleBroadcastAudioScanAssistCallback.BASS_STATUS_INVALID_GROUP_OP : - errorMessage = R.string.bluetooth_source_update_invalid_group_op; - break; - case BleBroadcastAudioScanAssistCallback.BASS_STATUS_INVALID_SOURCE_ID : - errorMessage = R.string.bluetooth_source_update_invalid_src_id; - break; - } - return errorMessage; - } - - BleBroadcastAudioScanAssistCallback mScanAssistCallback = new BleBroadcastAudioScanAssistCallback() { - DialogInterface.OnClickListener commonMessageListener = new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - BroadcastScanAssistanceUtils.debug(TAG, ">>OK clicked"); - if (mCommonMsgDialog != null) { - mCommonMsgDialog.dismiss(); - } - finish(); - } - }; - public void onBleBroadcastSourceFound(ScanResult res) { - BroadcastScanAssistanceUtils.debug(TAG, "onBleBroadcastSourceFound" + res.getDevice()); - - CachedBluetoothDevice cachedDevice = mLocalManager.getCachedDeviceManager().findDevice(res.getDevice()); - - if (cachedDevice != null) { - BroadcastScanAssistanceUtils.debug(TAG, "seems like CachedDevice entry already present for this device"); - } else { - //Create a Device entry for this, - //If this is randon Address, there would new CachedDevice Entry for this random address Instance - //However this wont have the name - cachedDevice = mLocalManager.getCachedDeviceManager().addDevice(res.getDevice()); - //udate the Name for this device from ADV: HACK - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - if (res.getDevice().getAddress().equals(adapter.getAddress())) { - BroadcastScanAssistanceUtils.debug(TAG, "Self DEVICE:"); - } else { - ScanRecord rec = res.getScanRecord(); - if (rec != null && rec.getDeviceName() != null) { - String s = rec.getDeviceName(); - BroadcastScanAssistanceUtils.debug(TAG,"setting name as " + s); - cachedDevice.setName(s); - } - } - } - - BluetoothDevicePreference pref = mDevicePreferenceMap.get(cachedDevice); - if (pref != null) { - //If the Prefernce alread Created, just update the - //Scan Result - //pref.SetScanResult(res); - BroadcastScanAssistanceUtils.debug(TAG, "Preference is already present" + res.getDevice()); - return; - } - // Prevent updates while the list shows one of the state messages - if (mBluetoothAdapter.getState() != BluetoothAdapter.STATE_ON) return; - //if (mFilter.matches(cachedDevice.getDevice())) { - createDevicePreference(cachedDevice); - //} - // - VendorCachedBluetoothDevice vDev = VendorCachedBluetoothDevice.getVendorCachedBluetoothDevice(cachedDevice, mProfileManager); - vDev.setScanResult(res); - }; - - public void onBleBroadcastSourceSelected(BluetoothDevice rcvr, int status, - List broadcastSourceIndicies) { - BroadcastScanAssistanceUtils.debug(TAG, "onBleBroadcastSourceSelected" + status + "sel indicies:" + broadcastSourceIndicies); - if (status == BleBroadcastAudioScanAssistCallback.BASS_STATUS_SUCCESS) { - launchSyncAndBroadcastIndexOptions(broadcastSourceIndicies); - } else { - String aliasName = getBluetoothName(rcvr); - mCommonMsgDialog = BroadcastScanAssistanceUtils.showScanAssistError(mContext, rcvr.getName(), - getSourceSelectionErrMessage(status), commonMessageListener); - - } - }; - - public void onBleBroadcastAudioSourceAdded(BluetoothDevice rcvr, - byte srcId, - int status) { - - BroadcastScanAssistanceUtils.debug(TAG, "onBleBroadcastAudioSourceAdded: rcvr:" + rcvr + - "status:" + status + "srcId" + srcId); - if (status == BleBroadcastAudioScanAssistCallback.BASS_STATUS_SUCCESS) { - //Show Dialog - if (mGroupOperation) { - String aliasName = getBluetoothName(rcvr); - mCommonMsgDialog = BroadcastScanAssistanceUtils.showScanAssistError(mContext, aliasName, - R.string.bluetooth_source_added_message, commonMessageListener); - } - if(mBroadcastPinCode != null) { - if (status == BleBroadcastAudioScanAssistCallback.BASS_STATUS_SUCCESS - && mScanAssistManager != null) { - mScanAssistManager.setBroadcastCode(srcId,mBroadcastPinCode, mGroupOperation); - } - mBroadcastPinCode = null; - } - finish(); - } else { - String aliasName = getBluetoothName(rcvr); - mCommonMsgDialog = BroadcastScanAssistanceUtils.showScanAssistError(mContext, aliasName, - getSourceAdditionErrMessage(status), commonMessageListener); - } - }; - - public void onBleBroadcastAudioSourceUpdated(BluetoothDevice rcvr, - byte srcId, - int status) { - BroadcastScanAssistanceUtils.debug(TAG, "onBleBroadcastAudioSourceUpdated: rcvr:" + rcvr + - "status:" + status + "srcId" + srcId); - if (status != BleBroadcastAudioScanAssistCallback.BASS_STATUS_SUCCESS) { - String aliasName = getBluetoothName(rcvr); - mCommonMsgDialog = BroadcastScanAssistanceUtils.showScanAssistError(mContext, aliasName, - getSourceUpdateErrMessage(status), commonMessageListener); - } - }; - - public void onBleBroadcastPinUpdated(BluetoothDevice rcvr, - byte srcId, - int status) { - - BroadcastScanAssistanceUtils.debug(TAG, "onBleBroadcastPinUpdated: rcvr:" + rcvr + - "status:" + status + "srcId" + srcId); - if (status != BleBroadcastAudioScanAssistCallback.BASS_STATUS_SUCCESS) { - String aliasName = getBluetoothName(rcvr); - mCommonMsgDialog = BroadcastScanAssistanceUtils.showScanAssistError(mContext, aliasName, - R.string.bluetooth_source_setpin_error_message, commonMessageListener); - } - }; - public void onBleBroadcastAudioSourceRemoved(BluetoothDevice rcvr, - byte srcId, - int status) { - BroadcastScanAssistanceUtils.debug(TAG, "onBleBroadcastAudioSourceRemoved: rcvr:" + rcvr + - "status:" + status + "srcId" + srcId); - if (status != BleBroadcastAudioScanAssistCallback.BASS_STATUS_SUCCESS) { - String aliasName = getBluetoothName(rcvr); - mCommonMsgDialog = BroadcastScanAssistanceUtils.showScanAssistError(mContext, aliasName, - getSourceRemovalErrMessage(status), commonMessageListener); - } - }; - }; - - - public BluetoothSADetail() { - super(DISALLOW_CONFIG_BLUETOOTH); - } - - void createDevicePreference(CachedBluetoothDevice cachedDevice) { - if (mDeviceListGroup == null) { - Log.w(TAG, "Trying to create a device preference before the list group/category " - + "exists!"); - return; - } - - String key = cachedDevice.getDevice().getAddress(); - BluetoothDevicePreference preference = (BluetoothDevicePreference) getCachedPreference(key); - - if (preference == null) { - preference = new BluetoothDevicePreference(getPrefContext(), cachedDevice, - true/*mShowDevicesWithoutNames*/, BluetoothDevicePreference.SortType.TYPE_FIFO); - preference.setKey(key); - //Set hideSecondTarget is true if it's bonded device. - //preference.hideSecondTarget(true); - mDeviceListGroup.addPreference(preference); - } - - initDevicePreference(preference); - Log.w(TAG, "adding" + cachedDevice + "to the Pref map"); - mDevicePreferenceMap.put(cachedDevice, preference); - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - mInitialScanStarted = false; - } - - @Override - public void onDeviceAdded(CachedBluetoothDevice cachedDevice) { - //Do nothing - } - - @Override - public void onStart() { - BroadcastScanAssistanceUtils.debug(TAG, "OnStart Called"); - super.onStart(); - if (mLocalManager == null){ - Log.e(TAG, "Bluetooth is not supported on this device"); - return; - } - updateContent(mBluetoothAdapter.getState()); - mAvailableDevicesCategory.setProgress(mBluetoothAdapter.isDiscovering()); - if (mScanAssistManager == null) { - if (mProfileManager == null) { - mProfileManager = mLocalManager.getProfileManager(); - } - BCProfile bcProfile = (BCProfile)mProfileManager.getBCProfile(); - mScanAssistManager = bcProfile.getBSAManager( - mCachedDevice.getDevice(), mScanAssistCallback); - if (mScanAssistManager == null) { - Log.e(TAG, "On Start: not able to instantiate scanAssistManager"); - //return; - } - } - } - - @Override - public void onAttach(Context context) { - BroadcastScanAssistanceUtils.debug(TAG, "OnAttach Called"); - super.onAttach(context); - mContext = context; - String deviceAddress = getArguments().getString(KEY_DEVICE_ADDRESS); - mGroupOperation = getArguments().getShort(KEY_GROUP_OP) == (short)1; - BluetoothDevice remoteDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice( - deviceAddress); - if (mLocalManager == null) { - Log.e(TAG, "Local mgr is NULL"); - mLocalManager = Utils.getLocalBtManager(getActivity()); - if (mLocalManager == null) { - Log.e(TAG, "Bluetooth is not supported on this device"); - return; - } - } - mCachedDevice = mLocalManager.getCachedDeviceManager().findDevice(remoteDevice); - if (mCachedDevice == null) { - //goBack(); - return; - } else { - mProfileManager = mLocalManager.getProfileManager(); - BCProfile bcProfile = (BCProfile)mProfileManager.getBCProfile(); - mScanAssistManager = bcProfile.getBSAManager( - mCachedDevice.getDevice(), mScanAssistCallback); - if (mScanAssistManager == null) { - Log.e(TAG, "not able to instantiate scanAssistManager"); - //return; - } - } - } - - - @Override - public void onStop() { - super.onStop(); - if (mLocalManager == null){ - Log.e(TAG, "Bluetooth is not supported on this device"); - return; - } - // Make the device only visible to connected devices. - disableScanning(); - //clear the preference map onStop - mDevicePreferenceMap.clear(); - mScanAssistManager = null; - } - - @Override - void initPreferencesFromPreferenceScreen() { - mScanDelegatorName = findPreference("bt_bcast_rcvr_device"); - mScanDelegatorName.setSelectable(false); - if (mCachedDevice == null) { - mScanDelegatorName.setSummary(SCAN_DEL_NAME); - } else { - mScanDelegatorName.setSummary(getBluetoothName(mCachedDevice.getDevice())); - } - mAvailableDevicesCategory = (BluetoothProgressCategory) findPreference(KEY_AVAIL_LE_AUDIO_SOURCES); - mFooterPreference = (FooterPreference) findPreference(KEY_FOOTER_PREF); - mFooterPreference.setSelectable(false); - } - - @Override - public int getMetricsCategory() { - return SettingsEnums.BLUETOOTH_PAIRING; - } - - @Override - void enableScanning() { - // Clear all device states before first scan - if (!mInitialScanStarted) { - if (mAvailableDevicesCategory != null) { - removeAllDevices(); - } - mLocalManager.getCachedDeviceManager().clearNonBondedDevices(); - mInitialScanStarted = true; - } - //Call to Scan for LE Audio Sources - if (mScanAssistManager != null) { - BroadcastScanAssistanceUtils.debug(TAG, "call searchforLeAudioBroadcasters"); - mScanAssistManager.searchforLeAudioBroadcasters(); - } - } - - @Override - void disableScanning() { - if (mScanAssistManager != null && mScanning == true) { - BroadcastScanAssistanceUtils.debug(TAG, "call stopSearchforLeAudioBroadcasters"); - mScanAssistManager.stopSearchforLeAudioBroadcasters(); - mScanning = false; - } - } - - private int getSyncStateFromSelection (String s) { - int ret = -1; - if (s == null) { - BroadcastScanAssistanceUtils.debug(TAG, "getSyncStateFromSelection:Invalid Input"); - } else { - if (mSyncState.equals("Sync Metadata")) { - ret = BleBroadcastAudioScanAssistManager.SYNC_METADATA; - } else { - ret = BleBroadcastAudioScanAssistManager.SYNC_METADATA_AUDIO; - } - } - return ret; - } - - void launchSyncAndBroadcastIndexOptions(List broadcastSourceIndicies) { - Context context = getContext(); - - final View dialogView; - String title, message; - Activity activity = getActivity(); - if (isAdded() && activity != null) { - dialogView = getLayoutInflater().inflate(R.layout.select_source_prompt, null); - String name = null; - if (clickedDevice != null) { - name = clickedDevice.getName(); - } - if (TextUtils.isEmpty(name)) { - name = context.getString(R.string.bluetooth_device); - } - if (mGroupOperation) { - message = context.getString(R.string.bluetooth_grp_source_selection_options_detail, name); - } else { - message = context.getString(R.string.bluetooth_source_selection_options_detail, name); - } - title = context.getString(R.string.bluetooth_source_selection_options_detail_title); - - /* - //BIS Selection choice - ListView bisSelectionList; - bisSelectionList = dialogView.findViewById(R.id.lv); - bisSelectionList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); - ArrayAdapter arrayAdapter = - new ArrayAdapter(context, android.R.layout.simple_list_item_multiple_choice , broadcastSourceIndicies); - - bisSelectionList.setAdapter(arrayAdapter); - - bisSelectionList.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - BroadcastScanAssistanceUtils.debug(TAG, "onItemClick: " +position); - CheckedTextView v = (CheckedTextView) view; - boolean currentCheck = v.isChecked(); - BleBroadcastSourceChannel bisIndex = (BleBroadcastSourceChannel) bisSelectionList.getItemAtPosition(position); - bisIndex.setStatus(currentCheck); - } - }); - */ - DialogInterface.OnClickListener cancelAddSourceListener = new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - BroadcastScanAssistanceUtils.debug(TAG, ">>Cancel clicked"); - finish(); - } - }; - - DialogInterface.OnClickListener addSourceListener = new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - /* - Radio Buttons - final RadioGroup group = dialogView.findViewById(R.id.syncStateOptions); - int selectedId = group.getCheckedRadioButtonId(); - RadioButton radioSelectedButton = (RadioButton) dialogView.findViewById(selectedId); - mSyncState = radioSelectedButton.getText().toString(); - BroadcastScanAssistanceUtils.debug(TAG, "mSyncState: " + mSyncState); - */ - if (clickedDevice == null) { - Log.w(TAG, "Ignore as there is no clicked device"); - } - if (clickedDevice.getAddress().equals(mBluetoothAdapter.getAddress())) { - BroadcastScanAssistanceUtils.debug(TAG, ">>Local Adapter"); - mBroadcastPinCode = null; - } else { - EditText broadcastPIN = dialogView.findViewById(R.id.broadcastPINcode); - mBroadcastPinCode = broadcastPIN.getText().toString(); - BroadcastScanAssistanceUtils.debug(TAG, "broadcastPinCode: " + mBroadcastPinCode); - if (TextUtils.isEmpty(mBroadcastPinCode)) { - BroadcastScanAssistanceUtils.debug(TAG, "Empty broacast PinCode"); - mBroadcastPinCode = null; - } - } - if (mScanAssistManager != null && clickedDevice != null) { - mScanAssistManager.addBroadcastSource(clickedDevice.getDevice(), - /*getSyncStateFromSelection(mSyncState)*/ - BleBroadcastAudioScanAssistManager.SYNC_METADATA_AUDIO, - broadcastSourceIndicies, mGroupOperation); - } - } - }; - EditText broadcastPIN = dialogView.findViewById(R.id.broadcastPINcode); - if (clickedDevice != null && clickedDevice.getAddress().equals(mBluetoothAdapter.getAddress())) { - BroadcastScanAssistanceUtils.debug(TAG, "Local Adapter"); - mBroadcastPinCode = null; - broadcastPIN.setVisibility(View.INVISIBLE); - if (mGroupOperation) { - message = context.getString(R.string.bluetooth_col_grp_source_selection_options_detail, name); - } else { - message = context.getString(R.string.bluetooth_col_source_selection_options_detail, name); - } - } - mScanAssistDetailsDialog = BroadcastScanAssistanceUtils.showScanAssistDetailsDialog(context, - mScanAssistDetailsDialog, addSourceListener, cancelAddSourceListener, title, - Html.fromHtml(message), dialogView); - } - } - - @Override - void onDevicePreferenceClick(BluetoothDevicePreference btPreference) { - disableScanning(); - clickedDevice = btPreference.getBluetoothDevice(); - VendorCachedBluetoothDevice vDevice = VendorCachedBluetoothDevice.getVendorCachedBluetoothDevice(clickedDevice, mProfileManager); - if (mScanAssistManager != null) { - BroadcastScanAssistanceUtils.debug(TAG, "calling selectAudioSource"); - mScanAssistManager.selectBroadcastSource(vDevice.getScanResult(), mGroupOperation); - } - } - void updateContent(int bluetoothState) { - switch (bluetoothState) { - case BluetoothAdapter.STATE_ON: - mDevicePreferenceMap.clear(); - //mBluetoothAdapter.enable(); - - addDeviceCategory(mAvailableDevicesCategory, - R.string.bluetooth_preference_found_media_devices, - BluetoothDeviceFilter.ALL_FILTER, false); - updateFooterPreference(mFooterPreference); - //mAlwaysDiscoverable.start(); - enableScanning(); - break; - - case BluetoothAdapter.STATE_OFF: - finish(); - break; - } - } - - @Override - void updateFooterPreference(Preference myDevicePreference) { - final BidiFormatter bidiFormatter = BidiFormatter.getInstance(); - myDevicePreference.setTitle(getString( - R.string.bluetooth_footer_mac_message, - bidiFormatter.unicodeWrap(mCachedDevice.getAddress()))); - } - - @Override - public void onBluetoothStateChanged(int bluetoothState) { - super.onBluetoothStateChanged(bluetoothState); - updateContent(bluetoothState); - if (bluetoothState == BluetoothAdapter.STATE_ON) { - showBluetoothTurnedOnToast(); - } - } - - - - @Override - public int getHelpResource() { - return R.string.help_url_bluetooth; - } - - @Override - protected String getLogTag() { - return TAG; - } - - @Override - protected int getPreferenceScreenResId() { - return R.xml.bluetooth_search_bcast_sources; - } - - @Override - public String getDeviceListKey() { - return KEY_AVAIL_LE_AUDIO_SOURCES; - } - - void showBluetoothTurnedOnToast() { - Toast.makeText(getContext(), R.string.connected_device_bluetooth_turned_on_toast, - Toast.LENGTH_SHORT).show(); - } -} diff --git a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BroadcastScanAssistanceUtils.java b/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BroadcastScanAssistanceUtils.java deleted file mode 100644 index 9883e70ae899f1c5ab7b836c043ac7aeefce20b7..0000000000000000000000000000000000000000 --- a/le_audio/packages/apps/Settings/src/com/android/settings/bluetooth/BroadcastScanAssistanceUtils.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2011 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.settings.bluetooth; - -import android.app.settings.SettingsEnums; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothProfile; -import android.content.Context; -import android.content.DialogInterface; -import android.provider.Settings; -import android.util.Log; -import android.widget.Toast; -import android.text.InputType; -import android.view.View; - -import androidx.annotation.VisibleForTesting; -import androidx.appcompat.app.AlertDialog; - -import com.android.settings.R; -import com.android.settings.overlay.FeatureFactory; -import com.android.settingslib.bluetooth.BluetoothUtils; -import com.android.settingslib.bluetooth.BluetoothUtils.ErrorListener; -import com.android.settingslib.bluetooth.LocalBluetoothManager; -import com.android.settingslib.bluetooth.LocalBluetoothManager.BluetoothManagerCallback; -import android.bluetooth.BluetoothAdapter; - -/** - * BroadcastScanAssistanceUtils is a helper class that contains constants for various - * Android resource IDs, debug logging flags, and static methods - * for creating BASS dialogs. - */ -public final class BroadcastScanAssistanceUtils { - - private static final String TAG = "BroadcastScanAsssitanceBroadcastScanAssistanceUtils"; - static final boolean BASS_DBG = Log.isLoggable(TAG, Log.VERBOSE); - - private BroadcastScanAssistanceUtils() { - } - - static void debug(String TAG, String msg) { - if (BASS_DBG) { - Log.d(TAG, msg); - } - } - - static boolean isLocalDevice(BluetoothDevice dev) { - boolean ret = false; - if (dev != null) { - BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); - ret = btAdapter.getAddress().equals(dev.getAddress()); - } - Log.d(TAG, "isLocalBroadcastSource returns" +ret); - return ret; - } - - static AlertDialog showScanAssistError(Context context, String name, int messageResId, - DialogInterface.OnClickListener okListener) { - return showScanAssistError(context, name, messageResId, Utils.getLocalBtManager(context), okListener); - } - - private static AlertDialog showScanAssistError(Context context, String name, int messageResId, - LocalBluetoothManager manager, DialogInterface.OnClickListener okListener) { - String message = context.getString(messageResId, name); - Context activity = manager.getForegroundActivity(); - AlertDialog dialog = null; - if (manager.isForegroundActivity()) { - try { - dialog = new AlertDialog.Builder(activity) - .setTitle(R.string.bluetooth_error_title) - .setMessage(message) - .setPositiveButton(android.R.string.ok, okListener) - .show(); - } catch (Exception e) { - Log.e(TAG, "Cannot show error dialog.", e); - return null; - } - return dialog; - } else { - Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); - return dialog; - } - } - // Create (or recycle existing) and show disconnect dialog. - static AlertDialog showScanAssistDetailsDialog(Context context, - AlertDialog dialog, - DialogInterface.OnClickListener addSourceListener, - DialogInterface.OnClickListener cancelAddSourceListener, - CharSequence title, CharSequence message, - View customView - ) { - if (dialog == null) { - dialog = new AlertDialog.Builder(context) - .setPositiveButton(android.R.string.ok, addSourceListener) - .setNegativeButton(android.R.string.cancel, cancelAddSourceListener) - .setView(customView) - .create(); - } else { - if (dialog.isShowing()) { - dialog.dismiss(); - } - // use disconnectListener for the correct profile(s) - //CharSequence okText = context.getText(android.R.string.ok); - //dialog.setButton(DialogInterface.BUTTON_POSITIVE, - // okText, addSourceListener); - } - dialog.setTitle(title); - dialog.setMessage(message); - dialog.show(); - return dialog; - } - - static AlertDialog showAssistanceGroupOptionsDialog(Context context, - AlertDialog dialog, - DialogInterface.OnClickListener groupOpListener, - DialogInterface.OnClickListener singleDevListener, - CharSequence title, CharSequence message) { - if (dialog == null) { - Log.d(TAG, "showAssistanceGroupOptionsDialog creation"); - dialog = new AlertDialog.Builder(context) - .setPositiveButton(R.string.yes, groupOpListener) - .setNegativeButton(R.string.no, singleDevListener) - .create(); - } else { - if (dialog.isShowing()) { - dialog.dismiss(); - } - // use disconnectListener for the correct profile(s) - //CharSequence okText = context.getText(android.R.string.yes); - //dialog.setButton(DialogInterface.BUTTON_POSITIVE, - // okText, groupOpListener); - } - dialog.setTitle(title); - dialog.setMessage(message); - dialog.show(); - return dialog; - } -} diff --git a/le_audio/system/bt/binder/Android.bp b/le_audio/system/bt/binder/Android.bp deleted file mode 100644 index 4744b11c321bcbc2397e945e57a9892e1538ed77..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/binder/Android.bp +++ /dev/null @@ -1,36 +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. - * - ******************************************************************************/ - -// AIDL interface between libbluetooth-binder and framework.jar -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"], -} - -filegroup { - name: "libbluetooth-binder-aidl-adva", - srcs: [ - "android/bluetooth/IBluetoothSyncHelper.aidl", - "android/bluetooth/IBleBroadcastAudioScanAssistCallback.aidl", - "android/bluetooth/IBluetoothBroadcast.aidl", - ], -} diff --git a/le_audio/system/bt/binder/android/bluetooth/BleBroadcastSourceChannel.aidl b/le_audio/system/bt/binder/android/bluetooth/BleBroadcastSourceChannel.aidl deleted file mode 100644 index 4b94f9493c032681bb29eb6de802e95b08473c6c..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/binder/android/bluetooth/BleBroadcastSourceChannel.aidl +++ /dev/null @@ -1,23 +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. - * - ******************************************************************************/ - - -package android.bluetooth; - -parcelable BleBroadcastSourceChannel; - diff --git a/le_audio/system/bt/binder/android/bluetooth/BleBroadcastSourceInfo.aidl b/le_audio/system/bt/binder/android/bluetooth/BleBroadcastSourceInfo.aidl deleted file mode 100644 index 8eb14da6201d92eaf29a4b5a9df775b53a9091f2..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/binder/android/bluetooth/BleBroadcastSourceInfo.aidl +++ /dev/null @@ -1,22 +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. - * - ******************************************************************************/ - -package android.bluetooth; - -parcelable BleBroadcastSourceInfo; - diff --git a/le_audio/system/bt/binder/android/bluetooth/IBleBroadcastAudioScanAssistCallback.aidl b/le_audio/system/bt/binder/android/bluetooth/IBleBroadcastAudioScanAssistCallback.aidl deleted file mode 100644 index 223f8135fa58c97af5e7f6a0f7d4471adf4bf7f9..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/binder/android/bluetooth/IBleBroadcastAudioScanAssistCallback.aidl +++ /dev/null @@ -1,48 +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. - * - ******************************************************************************/ - - -package android.bluetooth; - -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BleBroadcastSourceInfo; -import android.bluetooth.BleBroadcastSourceChannel; -import android.bluetooth.le.ScanResult; - -/** @hide */ -interface IBleBroadcastAudioScanAssistCallback { - void onBleBroadcastSourceFound(in ScanResult scanres); - void onBleBroadcastAudioSourceSelected(in BluetoothDevice device, - in int status, - in List - broadcastSourceChannels); - - void onBleBroadcastAudioSourceAdded(in BluetoothDevice rcvr, - in byte srcId, - in int status); - void onBleBroadcastAudioSourceUpdated(in BluetoothDevice rcvr, - in byte srcId, - in int status); - - void onBleBroadcastPinUpdated(in BluetoothDevice rcvr, - in byte srcId, - in int status); - void onBleBroadcastAudioSourceRemoved(in BluetoothDevice rcvr, - in byte srcId, - in int status); -} diff --git a/le_audio/system/bt/binder/android/bluetooth/IBluetoothBroadcast.aidl b/le_audio/system/bt/binder/android/bluetooth/IBluetoothBroadcast.aidl deleted file mode 100644 index e3054e9aaee76f4e0d03666b626161d56e23775b..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/binder/android/bluetooth/IBluetoothBroadcast.aidl +++ /dev/null @@ -1,35 +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. - * - ******************************************************************************/ - -package android.bluetooth; - -import android.bluetooth.BluetoothDevice; - -/** - * APIs for Bluetooth Broadcast service - * - * @hide - */ -interface IBluetoothBroadcast { - // Public API - boolean SetBroadcast(in boolean enable, in String packageName); - boolean SetEncryption(in boolean enable, in int enc_len, - in boolean use_existing, in String packageName); - byte[] GetEncryptionKey(in String packageName); - int GetBroadcastStatus(in String packageName); -} diff --git a/le_audio/system/bt/binder/android/bluetooth/IBluetoothSyncHelper.aidl b/le_audio/system/bt/binder/android/bluetooth/IBluetoothSyncHelper.aidl deleted file mode 100644 index 495c1ffb017145e59ebe6e54d3821735d8516c48..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/binder/android/bluetooth/IBluetoothSyncHelper.aidl +++ /dev/null @@ -1,75 +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. - * - ******************************************************************************/ - -package android.bluetooth; - -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BleBroadcastSourceInfo; -import android.bluetooth.IBleBroadcastAudioScanAssistCallback; -import android.bluetooth.le.ScanResult; - -/** - * APIs for Bluetooth Bluetooth Scan offloader service - * - * @hide - */ -interface IBluetoothSyncHelper { - // Public API - boolean connect(in BluetoothDevice device); - boolean disconnect(in BluetoothDevice device); - List getConnectedDevices(); - List getDevicesMatchingConnectionStates(in int[] states); - int getConnectionState(in BluetoothDevice device); - boolean setConnectionPolicy(in BluetoothDevice device, int connectionPolicy); - int getConnectionPolicy(in BluetoothDevice device); - boolean startScanOffload (in BluetoothDevice device, - in boolean groupOp); - boolean stopScanOffload (in BluetoothDevice device, - in boolean groupOp); - - void registerAppCallback(in BluetoothDevice device, - in IBleBroadcastAudioScanAssistCallback cb); - void unregisterAppCallback(in BluetoothDevice device, - in IBleBroadcastAudioScanAssistCallback cb); - - boolean searchforLeAudioBroadcasters (in BluetoothDevice device); - boolean stopSearchforLeAudioBroadcasters(in BluetoothDevice device); - - boolean addBroadcastSource(in BluetoothDevice device, - in BleBroadcastSourceInfo srcInfo, - in boolean groupOp - ); - boolean selectBroadcastSource(in BluetoothDevice device, - in ScanResult scanRes, - in boolean groupOp - ); - boolean updateBroadcastSource(in BluetoothDevice device, - in BleBroadcastSourceInfo srcInfo, - in boolean groupOp - ); - boolean setBroadcastCode (in BluetoothDevice device, - in BleBroadcastSourceInfo srcInfo, - in boolean groupOp - ); - boolean removeBroadcastSource (in BluetoothDevice device, - in byte SourceId, - in boolean groupOp - ); - List getAllBroadcastSourceInformation( - in BluetoothDevice device); -} diff --git a/le_audio/system/bt/bta/Android.bp b/le_audio/system/bt/bta/Android.bp deleted file mode 100644 index 5505ad2d78f365335d30ad2962e40f8102c7ca39..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/Android.bp +++ /dev/null @@ -1,97 +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. - * - ******************************************************************************/ - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "system_bt_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["system_bt_license"], -} - -cc_defaults { - name: "fluoride_bta_defaults_qti_adva", - defaults: ["fluoride_defaults"], - local_include_dirs: [ - "include", - ], - include_dirs: [ - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/bta/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/bta/ag", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/btcore/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/hci/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/internal_include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/stack/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/stack/btm", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/udrv/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/vnd/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/utils/include", - "vendor/qcom/opensource/commonsys/bluetooth_ext/system_bt_ext", - "vendor/qcom/opensource/commonsys/bluetooth_ext/vhal/include", - "vendor/qcom/opensource/commonsys/bluetooth_ext/system_bt_ext/bta/include", - "vendor/qcom/opensource/commonsys/bluetooth_ext/system_bt_ext/btif/include", - "vendor/qcom/opensource/commonsys-intf/bluetooth/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/device/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/btif/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/bta/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/bta/sys", - "vendor/qcom/opensource/commonsys/bluetooth_lea/packages/modules/Bluetooth/system", - "vendor/qcom/opensource/commonsys/bluetooth_lea/packages/modules/Bluetooth/system/bta/include", - "vendor/qcom/opensource/commonsys/bluetooth_lea/vhal/include", - "vendor/qcom/opensource/commonsys/bluetooth_lea/packages/modules/Bluetooth/system/bta/bap", - "vendor/qcom/opensource/commonsys/bluetooth_lea/packages/modules/Bluetooth/system/btif/include", - "packages/modules/Bluetooth/system/common/" - ], - shared_libs: [ - "libcutils", - ], - header_libs: ["libbluetooth_headers"], - cflags: [ - "-DBUILDCFG", - "-DADV_AUDIO_FEATURE=1", - ], -} - -// BTA static library for target -// ======================================================== -cc_library_static { - name: "libbt-bta_qti_adva", - defaults: ["fluoride_bta_defaults_qti_adva"], - enabled: false, - srcs: [ - "csip/bta_csip_act.cc", - "csip/bta_csip_api.cc", - "csip/bta_csip_main.cc", - "csip/bta_csip_utils.cc", - "bap/ascs_client.cc", - "bap/pacs_client.cc", - "bap/gattc_ops_queue.cc", - "bap/gatts_ops_queue.cc", - "bap/uclient_main.cc", - "bap/uclient_strm_mgr.cc", - "bap/uclient_strm_tracker.cc", - "bap/connected_iso.cc", - "bap/uclient_alarm.cc", - "vcp/bta_vcp_controller.cc", - "dm/bta_dm_adv_audio.cc", - "mcp/bta_mcp_main.cc", - "cc/bta_cc_main.cc", - ], -} diff --git a/le_audio/system/bt/bta/bap/ascs_client.cc b/le_audio/system/bt/bta/bap/ascs_client.cc deleted file mode 100644 index c9d569418604db4c24005a538f2bbfc52b772587..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/bap/ascs_client.cc +++ /dev/null @@ -1,1730 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/* - * 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 "bta_gatt_api.h" -#include "bta_ascs_client_api.h" -#include "gattc_ops_queue.h" -#include -#include -#include -#include -#include "device/include/controller.h" - -#include -#include "btif/include/btif_bap_config.h" -#include "osi/include/log.h" -#include "btif_util.h" - -namespace bluetooth { -namespace bap { -namespace ascs { - -using base::Closure; -using bluetooth::bap::GattOpsQueue; - -Uuid ASCS_UUID = Uuid::FromString("184E"); -Uuid ASCS_SINK_ASE_UUID = Uuid::FromString("2BC4"); -Uuid ASCS_SRC_ASE_UUID = Uuid::FromString("2BC5"); -Uuid ASCS_ASE_CP_UUID = Uuid::FromString("2BC6"); - -class AscsClientImpl; -AscsClientImpl* instance; - -typedef uint8_t codec_type_t[5]; - -enum class ProfleOP { - CONNECT, - DISCONNECT -}; - -struct ProfileOperation { - uint16_t client_id; - ProfleOP type; -}; - -enum class DevState { - IDLE = 0, - CONNECTING, - CONNECTED, - DISCONNECTING -}; - -void ascs_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data); -void encryption_callback(const RawAddress*, tGATT_TRANSPORT, void*, - tBTM_STATUS); - -std::map resp_codes = { - {0x01, "Un Supported Opcode"}, - {0x02, "Invalid Length"}, - {0x03, "Invalid ASE ID"}, - {0x04, "Invalid ASE SM Transition"}, - {0x05, "Invalid ASE Direction"}, - {0x06, "Un Supported Audio Capabilities"}, - {0x07, "Un Supported Config Param"}, - {0x08, "Rejected Config Param"}, - {0x09, "Invalid Config Param"}, - {0x0A, "Un Supported Metadata"}, - {0x0B, "Rejected Metadata"}, - {0x0C, "Invalid Metadata"}, - {0x0D, "InSufficient Resources"}, - {0x0E, "Unspecified Error"}, -}; - -std::map reason_codes = { - {0x01, "Codec ID"}, - {0x02, "Codec Specific Config"}, - {0x03, "SDU Interval"}, - {0x04, "Framing"}, - {0x05, "PHY"}, - {0x06, "Maximum SDU Size"}, - {0x07, "RTN"}, - {0x08, "MTL"}, - {0x09, "PD"}, - {0x0A, "Invalid ASE CIS Mapping"}, -}; - -std::vector sink_ase_value_list, src_ase_value_list; -AseParams ase; - -struct AscsDevice { - RawAddress address; - /* This is true only during first connection to profile, until we store the - * device */ - bool first_connection; - bool service_changed_rcvd; - - uint16_t conn_id; - std::vector sink_ase_list; - std::vector src_ase_list; - uint16_t ase_cp_handle; - uint16_t ase_cp_ccc_handle; - uint16_t srv_changed_ccc_handle; - bool discovery_completed; - uint8_t num_ases_read; - bool notifications_enabled; - DevState state; - bool is_congested; - std::vector profile_queue; - std::vector connected_client_list; //list client requested for connection - AscsDevice(const RawAddress& address) : address(address) {} -}; - -class AscsDevices { - public: - void Add(AscsDevice device) { - if (FindByAddress(device.address) != nullptr) return; - - devices.push_back(device); - } - - void Remove(const RawAddress& address) { - for (auto it = devices.begin(); it != devices.end();) { - if (it->address != address) { - ++it; - continue; - } - - it = devices.erase(it); - return; - } - } - - AscsDevice* FindByAddress(const RawAddress& address) { - auto iter = std::find_if(devices.begin(), devices.end(), - [&address](const AscsDevice& device) { - return device.address == address; - }); - - return (iter == devices.end()) ? nullptr : &(*iter); - } - - AscsDevice* FindByConnId(uint16_t conn_id) { - auto iter = std::find_if(devices.begin(), devices.end(), - [&conn_id](const AscsDevice& device) { - return device.conn_id == conn_id; - }); - - return (iter == devices.end()) ? nullptr : &(*iter); - } - - size_t size() { return (devices.size()); } - - std::vector devices; -}; - -class AscsClientImpl : public AscsClient { - public: - ~AscsClientImpl() override = default; - - AscsClientImpl() : gatt_client_id(BTA_GATTS_INVALID_IF) {}; - - bool Register(AscsClientCallbacks *callback) { - LOG(WARNING) << __func__ << callback; - // looks for client is already registered - bool is_client_registered = false; - for (auto it : callbacks) { - AscsClientCallbacks *pac_callback = it.second; - if(callback == pac_callback) { - is_client_registered = true; - break; - } - } - - LOG(WARNING) << __func__ ; - - if(is_client_registered) { - LOG(WARNING) << __func__ << " already registered"; - return false; - } - - if(gatt_client_id == BTA_GATTS_INVALID_IF) { - BTA_GATTC_AppRegister( - ascs_gattc_callback, - base::Bind( - [](AscsClientCallbacks *callback, uint8_t client_id, uint8_t status) { - if (status != GATT_SUCCESS) { - LOG(ERROR) << "Can't start ASCS profile - no gatt " - "clients left!"; - return; - } - - if (instance) { - LOG(WARNING) << " ASCS gatt_client_id " - << instance->gatt_client_id; - instance->gatt_client_id = client_id; - instance->callbacks.insert(std::make_pair( - ++instance->ascs_client_id, callback)); - callback->OnAscsInitialized(0, instance->ascs_client_id); - } - }, - callback), true); - } else { - instance->callbacks.insert(std::make_pair( - ++instance->ascs_client_id, callback)); - callback->OnAscsInitialized(0, instance->ascs_client_id); - } - return true; - } - - bool Deregister (uint16_t client_id) { - bool status = false; - auto it = callbacks.find(client_id); - if (it != callbacks.end()) { - callbacks.erase(it); - if(callbacks.empty()) { - // deregister with GATT - LOG(WARNING) << __func__ << " Gatt de-register from ascs"; - BTA_GATTC_AppDeregister(gatt_client_id); - gatt_client_id = BTA_GATTS_INVALID_IF; - } - status = true; - } - return status; - } - - uint8_t GetClientCount () { - return callbacks.size(); - } - - void Connect(uint16_t client_id, const RawAddress& address, - bool is_direct) override { - LOG(WARNING) << __func__ << " " << address; - AscsDevice *dev = ascsDevices.FindByAddress(address); - ProfileOperation op; - op.client_id = client_id; - op.type = ProfleOP::CONNECT; - - if(dev == nullptr) { - AscsDevice pac_dev(address); - ascsDevices.Add(pac_dev); - dev = ascsDevices.FindByAddress(address); - } - if (dev == nullptr) { - LOG(ERROR) << __func__ << "dev is null"; - return; - } - - switch(dev->state) { - case DevState::IDLE: { - BTA_GATTC_Open(gatt_client_id, address, is_direct, - GATT_TRANSPORT_LE, false); - dev->state = DevState::CONNECTING; - dev->profile_queue.push_back(op); - } break; - case DevState::CONNECTING: { - dev->profile_queue.push_back(op); - } break; - case DevState::CONNECTED: { - auto iter = std::find_if(dev->connected_client_list.begin(), - dev->connected_client_list.end(), - [&client_id](uint16_t id) { - return id == client_id; - }); - - if(iter == dev->connected_client_list.end()) - dev->connected_client_list.push_back(client_id); - - auto it = callbacks.find(client_id); - if (it != callbacks.end()) { - AscsClientCallbacks *callback = it->second; - callback->OnConnectionState(address, GattState::CONNECTED); - } - } break; - case DevState::DISCONNECTING: { - dev->profile_queue.push_back(op); - } break; - } - } - - void Disconnect(uint16_t client_id, const RawAddress& address) override { - LOG(WARNING) << __func__ << " " << address; - AscsDevice* dev = ascsDevices.FindByAddress(address); - if (!dev) { - LOG(INFO) << "Device not connected to profile" << address; - return; - } - - ProfileOperation op; - op.client_id = client_id; - op.type = ProfleOP::DISCONNECT; - - switch(dev->state) { - case DevState::CONNECTING: { - auto iter = std::find_if(dev->profile_queue.begin(), - dev->profile_queue.end(), - [&client_id]( ProfileOperation entry) { - return ((entry.type == ProfleOP::CONNECT) && - (entry.client_id == client_id)); - }); - // If it is the last client requested for disconnect - if(iter != dev->profile_queue.end() && - dev->profile_queue.size() == 1) { - if (dev->conn_id) { - // Removes all registrations for connection. - BTA_GATTC_CancelOpen(dev->conn_id, address, false); - GattOpsQueue::Clean(dev->conn_id); - BTA_GATTC_Close(dev->conn_id); - dev->profile_queue.push_back(op); - dev->state = DevState::DISCONNECTING; - } else { - // clear the connection queue and - // move the state to DISCONNECTING to better track - dev->profile_queue.clear(); - dev->state = DevState::DISCONNECTING; - dev->profile_queue.push_back(op); - } - } else { - // remove the connection entry from the list - // as the same client has requested for disconnection - dev->profile_queue.erase(iter); - } - } break; - case DevState::CONNECTED: { - auto iter = std::find_if(dev->connected_client_list.begin(), - dev->connected_client_list.end(), - [&client_id]( uint16_t stored_client_id) { - return stored_client_id == client_id; - }); - // if it is the last client requested for disconnection - if(iter != dev->connected_client_list.end() && - dev->connected_client_list.size() == 1) { - if (dev->conn_id) { - // Removes all registrations for connection. - BTA_GATTC_CancelOpen(dev->conn_id, address, false); - GattOpsQueue::Clean(dev->conn_id); - BTA_GATTC_Close(dev->conn_id); - dev->profile_queue.push_back(op); - dev->state = DevState::DISCONNECTING; - } - } else { - // remove the client from connected_client_list - dev->connected_client_list.erase(iter); - // remove the pending gatt ops( not the ongoing one ) - // initiated from client which requested disconnect - // TODO and send callback as disconnected - } - } break; - case DevState::DISCONNECTING: { - dev->profile_queue.push_back(op); - } break; - default: - break; - } - } - - void StartDiscovery(uint16_t client_id, const RawAddress& address) override { - AscsDevice* dev = ascsDevices.FindByAddress(address); - if (!dev) { - LOG(INFO) << "Device not connected to profile" << address; - return; - } - LOG(WARNING) << __func__ << " " << address; - - switch(dev->state) { - case DevState::CONNECTED: { - auto iter = std::find_if(dev->connected_client_list.begin(), - dev->connected_client_list.end(), - [&client_id]( uint16_t stored_client_id) { - LOG(WARNING) << __func__ << client_id << stored_client_id; - return stored_client_id == client_id; - }); - // check if the client present in the connected client list - if(iter == dev->connected_client_list.end()) { - break; - } - // check if the discovery is already finished - // send back the same results to the other client - if(dev->discovery_completed && dev->notifications_enabled) { - sink_ase_value_list.clear(); - src_ase_value_list.clear(); - auto iter = callbacks.find(client_id); - if (iter != callbacks.end()) { - for (auto it : dev->sink_ase_list) { - memcpy(&ase, (void *) &it.ase_params, sizeof(ase)); - sink_ase_value_list.push_back(ase); - } - for (auto it : dev->src_ase_list) { - memcpy(&ase, (void *) &it.ase_params, sizeof(ase)); - src_ase_value_list.push_back(ase); - } - - AscsClientCallbacks *callback = iter->second; - // send out the callback as service discovery completed - callback->OnSearchComplete(0, dev->address, - sink_ase_value_list, - src_ase_value_list); - } - break; - } - // reset it - dev->num_ases_read = 0x00; - dev->discovery_completed = false; - dev->notifications_enabled = false; - // queue the request to GATT queue module - GattOpsQueue::ServiceSearch(client_id, dev->conn_id, &ASCS_UUID); - } break; - default: - break; - } - } - - void CodecConfig(uint16_t client_id, const RawAddress& address, - std::vector codec_configs) { - AscsDevice* dev = ascsDevices.FindByAddress(address); - std::vector vect_val; - uint8_t opcode = static_cast (AseOpId::CODEC_CONFIG); - uint8_t num_ases = codec_configs.size(); - if (!dev || (dev->state != DevState::CONNECTED)) { - LOG(INFO) << "Device not connected to profile" << address; - return; - } - - LOG(INFO) << __func__ << ": BD Addr : " << address - << ": Num ASEs :" << loghex(num_ases); - - vect_val.insert(vect_val.end(), &opcode, &opcode + 1); - vect_val.insert(vect_val.end(), &num_ases, &num_ases + 1); - - auto it = codec_configs.begin(); - while (it != codec_configs.end()) { - vect_val.insert(vect_val.end(), &it->ase_id, &it->ase_id + 1); - vect_val.insert(vect_val.end(), &it->tgt_latency, &it->tgt_latency + 1); - vect_val.insert(vect_val.end(), &it->tgt_phy, &it->tgt_phy + 1); - vect_val.insert(vect_val.end(), it->codec_id, - ((uint8_t *)it->codec_id) + sizeof(codec_type_t)); - - vect_val.insert(vect_val.end(), &it->codec_params_len, - &it->codec_params_len + 1); - vect_val.insert(vect_val.end(), it->codec_params.begin(), - it->codec_params.end()); - - LOG(INFO) << ": ASE Id = " << loghex(it->ase_id); - LOG(INFO) << ": Target Latency = " << loghex(it->tgt_latency); - LOG(INFO) << ": target Phy = " << loghex(it->tgt_phy); - LOG(INFO) << ": Codec ID = " << loghex(it->codec_id[0]); - it++; - } - - GattOpsQueue::WriteCharacteristic(client_id, dev->conn_id, - dev->ase_cp_handle, vect_val, - GATT_WRITE, nullptr, nullptr); - } - - void QosConfig(uint16_t client_id, const RawAddress& address, - std::vector qos_configs) { - AscsDevice* dev = ascsDevices.FindByAddress(address); - std::vector vect_val; - uint8_t opcode = static_cast (AseOpId::QOS_CONFIG); - uint8_t num_ases = qos_configs.size(); - if (!dev || (dev->state != DevState::CONNECTED)) { - LOG(INFO) << "Device not connected to profile" << address; - return; - } - LOG(INFO) << __func__ << ": BD Addr : " << address - << ": Num ASEs :" << loghex(num_ases); - - vect_val.insert(vect_val.end(), &opcode, &opcode + 1); - vect_val.insert(vect_val.end(), &num_ases, &num_ases + 1); - - auto it = qos_configs.begin(); - while (it != qos_configs.end()) { - vect_val.insert(vect_val.end(), &it->ase_id, &it->ase_id + 1); - vect_val.insert(vect_val.end(), &it->cig_id, &it->cig_id + 1); - vect_val.insert(vect_val.end(), &it->cis_id, &it->cis_id + 1); - - vect_val.insert(vect_val.end(), it->sdu_interval, - (uint8_t *)it->sdu_interval + sizeof(sdu_interval_t)); - - // test change it->framing = 0xFF; - vect_val.insert(vect_val.end(), &it->framing, &it->framing + 1); - vect_val.insert(vect_val.end(), &it->phy, &it->phy + 1); - - vect_val.insert(vect_val.end(), (uint8_t *) &it->max_sdu_size, - (uint8_t *)&it->max_sdu_size + sizeof(uint16_t)); - - vect_val.insert(vect_val.end(), &it->retrans_number, - &it->retrans_number + 1); - - vect_val.insert(vect_val.end(), (uint8_t *) &it->trans_latency, - (uint8_t *)&it->trans_latency + sizeof(uint16_t)); - - vect_val.insert(vect_val.end(), it->present_delay, - (uint8_t *)it->present_delay + sizeof(presentation_delay_t)); - - LOG(INFO) << ": ASE Id = " << loghex(it->ase_id); - LOG(INFO) << ": Cig Id = " << loghex(it->cig_id); - LOG(INFO) << ": Cis Id = " << loghex(it->cis_id); - LOG(INFO) << ": SDU interval =" - << " " << loghex(it->sdu_interval[0]) - << " " << loghex(it->sdu_interval[1]) - << " " << loghex(it->sdu_interval[2]); - LOG(INFO) << ": Framing = " << loghex(it->framing); - LOG(INFO) << ": Phy = " << loghex(it->phy); - LOG(INFO) << ": Max SDU size = " << loghex(it->max_sdu_size); - LOG(INFO) << ": RTN = " << loghex(it->retrans_number); - LOG(INFO) << ": MTL = " << loghex(it->trans_latency); - LOG(INFO) << ": PD =" - << " " << loghex(it->present_delay[0]) - << " " << loghex(it->present_delay[1]) - << " " << loghex(it->present_delay[2]); - it++; - } - - GattOpsQueue::WriteCharacteristic(client_id, dev->conn_id, - dev->ase_cp_handle, vect_val, - GATT_WRITE, nullptr, nullptr); - } - - void Enable(uint16_t client_id, const RawAddress& address, - std::vector enable_ops) { - AscsDevice* dev = ascsDevices.FindByAddress(address); - std::vector vect_val; - uint8_t opcode = static_cast (AseOpId::ENABLE); - uint8_t num_ases = enable_ops.size(); - if (!dev || (dev->state != DevState::CONNECTED)) { - LOG(INFO) << "Device not connected to profile" << address; - return; - } - LOG(INFO) << __func__ << ": BD Addr : " << address - << ": Num ASEs :" << loghex(num_ases); - - vect_val.insert(vect_val.end(), &opcode, &opcode + 1); - vect_val.insert(vect_val.end(), &num_ases, &num_ases + 1); - - auto it = enable_ops.begin(); - while (it != enable_ops.end()) { - LOG(INFO) << ": ASE Id = " << loghex(it->ase_id); - vect_val.insert(vect_val.end(), &it->ase_id, &it->ase_id + 1); - // test change it->meta_data_len = 0xFF; - vect_val.insert(vect_val.end(), &it->meta_data_len, - &it->meta_data_len + 1); - vect_val.insert(vect_val.end(), it->meta_data.begin(), - it->meta_data.end()); - it++; - } - - GattOpsQueue::WriteCharacteristic(client_id, dev->conn_id, - dev->ase_cp_handle, vect_val, - GATT_WRITE, nullptr, nullptr); - } - - void StartReady(uint16_t client_id, const RawAddress& address, - std::vector start_ready_ops) { - AscsDevice* dev = ascsDevices.FindByAddress(address); - std::vector vect_val; - uint8_t opcode = static_cast (AseOpId::START_READY); - uint8_t num_ases = start_ready_ops.size(); - if (!dev || (dev->state != DevState::CONNECTED)) { - LOG(INFO) << "Device not connected to profile" << address; - return; - } - LOG(INFO) << __func__ << ": BD Addr : " << address - << ": Num ASEs :" << loghex(num_ases); - - vect_val.insert(vect_val.end(), &opcode, &opcode + 1); - vect_val.insert(vect_val.end(), &num_ases, &num_ases + 1); - - auto it = start_ready_ops.begin(); - while (it != start_ready_ops.end()) { - LOG(INFO) << ": ASE Id = " << loghex(it->ase_id); - vect_val.insert(vect_val.end(), &it->ase_id, &it->ase_id + 1); - it++; - } - - GattOpsQueue::WriteCharacteristic(client_id, dev->conn_id, - dev->ase_cp_handle, vect_val, - GATT_WRITE, nullptr, nullptr); - } - - void Disable(uint16_t client_id, const RawAddress& address, - std::vector disable_ops) { - AscsDevice* dev = ascsDevices.FindByAddress(address); - std::vector vect_val; - uint8_t opcode = static_cast (AseOpId::DISABLE); - uint8_t num_ases = disable_ops.size(); - if (!dev || (dev->state != DevState::CONNECTED)) { - LOG(INFO) << "Device not connected to profile" << address; - return; - } - LOG(INFO) << __func__ << ": BD Addr : " << address - << ": Num ASEs :" << loghex(num_ases); - - vect_val.insert(vect_val.end(), &opcode, &opcode + 1); - vect_val.insert(vect_val.end(), &num_ases, &num_ases + 1); - - auto it = disable_ops.begin(); - while (it != disable_ops.end()) { - LOG(INFO) << ": ASE Id = " << loghex(it->ase_id); - vect_val.insert(vect_val.end(), &it->ase_id, &it->ase_id + 1); - it++; - } - - GattOpsQueue::WriteCharacteristic(client_id, dev->conn_id, - dev->ase_cp_handle, vect_val, - GATT_WRITE, nullptr, nullptr); - } - - void StopReady(uint16_t client_id, const RawAddress& address, - std::vector stop_ready_ops) { - AscsDevice* dev = ascsDevices.FindByAddress(address); - std::vector vect_val; - uint8_t opcode = static_cast (AseOpId::STOP_READY); - uint8_t num_ases = stop_ready_ops.size(); - if (!dev || (dev->state != DevState::CONNECTED)) { - LOG(INFO) << "Device not connected to profile" << address; - return; - } - LOG(INFO) << __func__ << ": BD Addr : " << address - << ": Num ASEs :" << loghex(num_ases); - - vect_val.insert(vect_val.end(), &opcode, &opcode + 1); - vect_val.insert(vect_val.end(), &num_ases, &num_ases + 1); - - auto it = stop_ready_ops.begin(); - while (it != stop_ready_ops.end()) { - LOG(INFO) << ": ASE Id = " << loghex(it->ase_id); - vect_val.insert(vect_val.end(), &it->ase_id, &it->ase_id + 1); - it++; - } - - GattOpsQueue::WriteCharacteristic(client_id, dev->conn_id, - dev->ase_cp_handle, vect_val, - GATT_WRITE, nullptr, nullptr); - } - - void Release(uint16_t client_id, const RawAddress& address, - std::vector release_ops) { - AscsDevice* dev = ascsDevices.FindByAddress(address); - std::vector vect_val; - uint8_t opcode = static_cast (AseOpId::RELEASE); - uint8_t num_ases = release_ops.size(); - if (!dev || (dev->state != DevState::CONNECTED)) { - LOG(INFO) << "Device not connected to profile" << address; - return; - } - LOG(INFO) << __func__ << ": BD Addr : " << address - << ": Num ASEs :" << loghex(num_ases); - - vect_val.insert(vect_val.end(), &opcode, &opcode + 1); - vect_val.insert(vect_val.end(), &num_ases, &num_ases + 1); - - auto it = release_ops.begin(); - while (it != release_ops.end()) { - LOG(INFO) << ": ASE Id = " << loghex(it->ase_id); - vect_val.insert(vect_val.end(), &it->ase_id, &it->ase_id + 1); - it++; - } - - GattOpsQueue::WriteCharacteristic(client_id, dev->conn_id, - dev->ase_cp_handle, vect_val, - GATT_WRITE, nullptr, nullptr); - } - - void UpdateStream(uint16_t client_id, const RawAddress& address, - std::vector metadata_ops) { - AscsDevice* dev = ascsDevices.FindByAddress(address); - std::vector vect_val; - uint8_t opcode = static_cast (AseOpId::UPDATE_META_DATA); - uint8_t num_ases = metadata_ops.size(); - if (!dev || (dev->state != DevState::CONNECTED)) { - LOG(INFO) << "Device not connected to profile" << address; - return; - } - LOG(INFO) << __func__ << ": BD Addr : " << address - << ": Num ASEs :" << loghex(num_ases); - - vect_val.insert(vect_val.end(), &opcode, &opcode + 1); - vect_val.insert(vect_val.end(), &num_ases, &num_ases + 1); - - auto it = metadata_ops.begin(); - while (it != metadata_ops.end()) { - LOG(INFO) << ": ASE Id = " << loghex(it->ase_id); - vect_val.insert(vect_val.end(), &it->ase_id, &it->ase_id + 1); - vect_val.insert(vect_val.end(), &it->meta_data_len, - &it->meta_data_len + 1); - vect_val.insert(vect_val.end(), it->meta_data.begin(), - it->meta_data.end()); - it++; - } - - GattOpsQueue::WriteCharacteristic(client_id, dev->conn_id, - dev->ase_cp_handle, vect_val, - GATT_WRITE, nullptr, nullptr); - } - - bool GetAseParams(const RawAddress& address, uint8_t ase_id, - AseParams *ase_params) { - bool ase_found = false; - AscsDevice* dev = ascsDevices.FindByAddress(address); - if (!dev) { - LOG(INFO) << "Device not connected to profile" << address; - return false; - } - - // first look for sink ASEs - for (auto it = dev->sink_ase_list.begin(); - it != dev->sink_ase_list.end(); it++) { - if (it->ase_params.ase_id == ase_id) { - *ase_params = it->ase_params; - ase_found = true; - break; - } - } - if(ase_found) return ase_found; - - for (auto it = dev->src_ase_list.begin(); - it != dev->src_ase_list.end(); it++) { - if (it->ase_params.ase_id == ase_id) { - *ase_params = it->ase_params; - ase_found = true; - break; - } - } - return ase_found; - } - - bool GetAseHandle(const RawAddress& address, uint8_t ase_id, - uint16_t *ase_handle) { - bool ase_found = false; - AscsDevice* dev = ascsDevices.FindByAddress(address); - if (!dev) { - LOG(INFO) << "Device not connected to profile" << address; - return false; - } - - // first look for sink ASEs - for (auto it = dev->sink_ase_list.begin(); - it != dev->sink_ase_list.end(); it++) { - if (it->ase_params.ase_id == ase_id) { - *ase_handle = it->ase_handle; - ase_found = true; - break; - } - } - if(ase_found) return ase_found; - - for (auto it = dev->src_ase_list.begin(); - it != dev->src_ase_list.end(); it++) { - if (it->ase_params.ase_id == ase_id) { - *ase_handle = it->ase_handle; - ase_found = true; - break; - } - } - return ase_found; - } - - void GetAseState(uint16_t client_id, const RawAddress& address, - uint8_t ase_id) { - AscsDevice* dev = ascsDevices.FindByAddress(address); - if (!dev) { - LOG(INFO) << "Device not connected to profile" << address; - return; - } - LOG(WARNING) << __func__ << " " << address; - - switch(dev->state) { - case DevState::CONNECTED: { - uint16_t ase_handle; - auto iter = std::find_if(dev->connected_client_list.begin(), - dev->connected_client_list.end(), - [&client_id]( uint16_t stored_client_id) { - return stored_client_id == client_id; - }); - // check if the client present in the connected client list - if(iter == dev->connected_client_list.end()) { - break; - } - - // check if the discovery is already finished - // send back the same results to the other client - if(dev->discovery_completed && dev->notifications_enabled) { - auto iter = callbacks.find(client_id); - AseParams ase_params; - if(iter != callbacks.end() && - GetAseParams(address, ase_id, &ase_params)) { - AscsClientCallbacks *callback = iter->second; - callback->OnAseState(dev->address, ase_params); - } - break; - } - - if(GetAseHandle(address, ase_id, &ase_handle)) { - // queue the request to GATT queue module - GattOpsQueue::ReadCharacteristic(client_id, dev->conn_id, - ase_handle, - AscsClientImpl::OnReadAseStateStatic, nullptr); - } - } break; - default: - LOG(WARNING) << __func__ << "un-handled event"; - break; - } - } - - void OnGattConnected(tGATT_STATUS status, uint16_t conn_id, - tGATT_IF client_if, RawAddress address, - tBTA_TRANSPORT transport, uint16_t mtu) { - - AscsDevice* dev = ascsDevices.FindByAddress(address); - if (!dev) { - /* When device is quickly disabled and enabled in settings, this case - * might happen */ - LOG(ERROR) << "Closing connection to non ascs device, address=" - << address; - BTA_GATTC_Close(conn_id); - return; - } - LOG(INFO) << __func__ << ": BD Addr : " << address - << ": Status : " << loghex(status); - - if(dev->state == DevState::CONNECTING) { - if (status != GATT_SUCCESS) { - LOG(ERROR) << "Failed to connect to ASCS device"; - for (auto it = dev->profile_queue.begin(); - it != dev->profile_queue.end();) { - if(it->type == ProfleOP::CONNECT) { - // get the callback and update the upper layers - auto iter = callbacks.find(it->client_id); - if (iter != callbacks.end()) { - AscsClientCallbacks *callback = iter->second; - callback->OnConnectionState(address, GattState::DISCONNECTED); - } - dev->profile_queue.erase(it); - } else { - it++; - } - } - dev->state = DevState::IDLE; - ascsDevices.Remove(address); - return; - } - } else if(dev->state == DevState::DISCONNECTING) { - // TODO will this happens ? - // it could have called the cancel open to expect the - // open cancelled event - if (status != GATT_SUCCESS) { - LOG(ERROR) << "Failed to connect to ASCS device"; - for (auto it = dev->profile_queue.begin(); - it != dev->profile_queue.end();) { - if(it->type == ProfleOP::DISCONNECT) { - // get the callback and update the upper layers - auto iter = callbacks.find(it->client_id); - if (iter != callbacks.end()) { - AscsClientCallbacks *callback = iter->second; - callback->OnConnectionState(address, GattState::DISCONNECTED); - } - dev->profile_queue.erase(it); - } else { - it++; - } - } - dev->state = DevState::IDLE; - ascsDevices.Remove(address); - return; - } else { - // gatt connected successfully - // if the disconnect entry is found we need to initiate the - // gatt disconnect. may be a race condition just after sending - // cancel open gatt connected event received - for (auto it = dev->profile_queue.begin(); - it != dev->profile_queue.end();) { - if(it->type == ProfleOP::DISCONNECT) { - // get the callback and update the upper layers - auto iter = callbacks.find(it->client_id); - if (iter != callbacks.end()) { - // Removes all registrations for connection. - BTA_GATTC_CancelOpen(dev->conn_id, address, false); - GattOpsQueue::Clean(dev->conn_id); - BTA_GATTC_Close(dev->conn_id); - break; - } - } else { - it++; - } - } - return; - } - } else { - // return unconditinally - return; - } - - // success scenario code - dev->conn_id = conn_id; - - tACL_CONN* p_acl = btm_bda_to_acl(address, BT_TRANSPORT_LE); - if (p_acl != nullptr && - controller_get_interface()->supports_ble_2m_phy() && - HCI_LE_2M_PHY_SUPPORTED(p_acl->peer_le_features)) { - LOG(INFO) << address << " set preferred PHY to 2M"; - BTM_BleSetPhy(address, PHY_LE_2M, PHY_LE_2M, 0); - } - - /* verify bond */ - uint8_t sec_flag = 0; - BTM_GetSecurityFlagsByTransport(address, &sec_flag, BT_TRANSPORT_LE); - - if (sec_flag & BTM_SEC_FLAG_ENCRYPTED) { - /* if link has been encrypted */ - OnEncryptionComplete(address, true); - return; - } - - if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) { - /* if bonded and link not encrypted */ - sec_flag = BTM_BLE_SEC_ENCRYPT; - LOG(WARNING) << "trying to encrypt now"; - BTM_SetEncryption(address, BTA_TRANSPORT_LE, encryption_callback, nullptr, - sec_flag); - return; - } - - /* otherwise let it go through */ - OnEncryptionComplete(address, true); - } - - void OnGattDisconnected(tGATT_STATUS status, uint16_t conn_id, - tGATT_IF client_if, RawAddress remote_bda, - tBTA_GATT_REASON reason) { - AscsDevice* dev = ascsDevices.FindByAddress(remote_bda); - if (!dev) { - LOG(ERROR) << "Skipping unknown device disconnect, conn_id=" - << loghex(conn_id); - return; - } - - LOG(INFO) << __func__ << ": BD Addr : " << remote_bda - << ", Status : " << loghex(status) - << ", state: " << static_cast(dev->state); - - switch(dev->state) { - case DevState::CONNECTING: { - // sudden disconnection - for (auto it = dev->profile_queue.begin(); - it != dev->profile_queue.end();) { - if(it->type == ProfleOP::CONNECT) { - // get the callback and update the upper layers - auto iter = callbacks.find(it->client_id); - if (iter != callbacks.end()) { - AscsClientCallbacks *callback = iter->second; - callback->OnConnectionState(remote_bda, GattState::DISCONNECTED); - } - it = dev->profile_queue.erase(it); - } else { - it++; - } - } - } break; - case DevState::CONNECTED: { - // sudden disconnection - for (auto it = dev->connected_client_list.begin(); - it != dev->connected_client_list.end();) { - // get the callback and update the upper layers - auto iter = callbacks.find(*it); - if (iter != callbacks.end()) { - AscsClientCallbacks *callback = iter->second; - callback->OnConnectionState(remote_bda, GattState::DISCONNECTED); - } - it = dev->connected_client_list.erase(it); - } - } break; - case DevState::DISCONNECTING: { - for (auto it = dev->profile_queue.begin(); - it != dev->profile_queue.end();) { - if(it->type == ProfleOP::DISCONNECT) { - // get the callback and update the upper layers - auto iter = callbacks.find(it->client_id); - if (iter != callbacks.end()) { - AscsClientCallbacks *callback = iter->second; - callback->OnConnectionState(remote_bda, GattState::DISCONNECTED); - } - it = dev->profile_queue.erase(it); - } else { - it++; - } - } - - for (auto it = dev->connected_client_list.begin(); - it != dev->connected_client_list.end();) { - // get the callback and update the upper layers - it = dev->connected_client_list.erase(it); - } - // check if the connection queue is not empty - // if not initiate the Gatt connection - } break; - default: - break; - } - - if (dev->conn_id) { - GattOpsQueue::Clean(dev->conn_id); - BTA_GATTC_Close(dev->conn_id); - dev->conn_id = 0; - } - - dev->state = DevState::IDLE; - ascsDevices.Remove(remote_bda); - } - - void OnConnectionUpdateComplete(uint16_t conn_id, tBTA_GATTC* p_data) { - AscsDevice* dev = ascsDevices.FindByConnId(conn_id); - if (!dev) { - LOG(ERROR) << "Skipping unknown device, conn_id=" << loghex(conn_id); - return; - } - } - - void OnEncryptionComplete(const RawAddress& address, bool success) { - AscsDevice* dev = ascsDevices.FindByAddress(address); - if (!dev) { - LOG(ERROR) << "Skipping unknown device" << address; - return; - } - - if(dev->state != DevState::CONNECTING) { - LOG(ERROR) << "received in wrong state" << address; - return; - } - - LOG(INFO) << __func__ << ": BD Addr : " << address - << ": Status : " << loghex(success); - - // encryption failed - if (!success) { - for (auto it = dev->profile_queue.begin(); - it != dev->profile_queue.end();) { - if(it->type == ProfleOP::CONNECT) { - // get the callback and update the upper layers - auto iter = callbacks.find(it->client_id); - if (iter != callbacks.end()) { - AscsClientCallbacks *callback = iter->second; - callback->OnConnectionState(address, GattState::DISCONNECTED); - } - // change the type to disconnect - it->type = ProfleOP::DISCONNECT; - } else { - it++; - } - } - dev->state = DevState::DISCONNECTING; - // Removes all registrations for connection. - BTA_GATTC_CancelOpen(dev->conn_id, address, false); - BTA_GATTC_Close(dev->conn_id); - } else { - for (auto it = dev->profile_queue.begin(); - it != dev->profile_queue.end();) { - if(it->type == ProfleOP::CONNECT) { - // get the callback and update the upper layers - auto iter = callbacks.find(it->client_id); - if (iter != callbacks.end()) { - dev->connected_client_list.push_back(it->client_id); - AscsClientCallbacks *callback = iter->second; - callback->OnConnectionState(address, GattState::CONNECTED); - } - dev->profile_queue.erase(it); - } else { - it++; - } - } - dev->state = DevState::CONNECTED; - } - } - - void OnServiceChangeEvent(const RawAddress& address) { - AscsDevice* dev = ascsDevices.FindByAddress(address); - if (!dev) { - LOG(ERROR) << "Skipping unknown device" << address; - return; - } - LOG(INFO) << __func__ << ": address=" << address; - dev->first_connection = true; - dev->service_changed_rcvd = true; - GattOpsQueue::Clean(dev->conn_id); - } - - void OnServiceDiscDoneEvent(const RawAddress& address) { - AscsDevice* dev = ascsDevices.FindByAddress(address); - if (!dev) { - LOG(ERROR) << "Skipping unknown device" << address; - return; - } - if (dev->service_changed_rcvd) { - // queue the request to GATT queue module with dummu client id - GattOpsQueue::ServiceSearch(0XFF, dev->conn_id, &ASCS_UUID); - } - } - - void OnServiceSearchComplete(uint16_t conn_id, tGATT_STATUS status) { - AscsDevice* dev = ascsDevices.FindByConnId(conn_id); - if (!dev) { - LOG(ERROR) << "Skipping unknown device, conn_id=" << loghex(conn_id); - return; - } - - LOG(INFO) << __func__ << ": BD Addr : " << dev->address - << ": Status : " << loghex(status); - - uint16_t client_id = GattOpsQueue::ServiceSearchComplete(conn_id, - status); - auto iter = callbacks.find(client_id); - if (status != GATT_SUCCESS) { - /* close connection and report service discovery complete with error */ - LOG(ERROR) << "Service discovery failed"; - if (iter != callbacks.end()) { - AscsClientCallbacks *callback = iter->second; - std::vector ase_value_list; - callback->OnSearchComplete(0xFF, dev->address, ase_value_list, - ase_value_list); - } - return; - } - - const std::vector* services = BTA_GATTC_GetServices(conn_id); - - const gatt::Service* service = nullptr; - if (services) { - for (const gatt::Service& tmp : *services) { - if (tmp.uuid == Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER)) { - LOG(INFO) << "Found UUID_SERVCLASS_GATT_SERVER, handle=" - << loghex(tmp.handle); - const gatt::Service* service_changed_service = &tmp; - find_server_changed_ccc_handle(conn_id, service_changed_service); - } else if (tmp.uuid == ASCS_UUID) { - LOG(INFO) << "Found ASCS service, handle=" << loghex(tmp.handle); - service = &tmp; - } - } - } else { - LOG(ERROR) << "no services found for conn_id: " << conn_id; - return; - } - - if (!service) { - LOG(ERROR) << "No ASCS service found"; - if (iter != callbacks.end()) { - AscsClientCallbacks *callback = iter->second; - std::vector ase_value_list; - callback->OnSearchComplete(0xFF, dev->address, ase_value_list, - ase_value_list); - } - return; - } - - for (const gatt::Characteristic& charac : service->characteristics) { - if (charac.uuid == ASCS_SINK_ASE_UUID || - charac.uuid == ASCS_SRC_ASE_UUID) { - Ase ase_info; - ase_info.ase_handle = charac.value_handle; - GattOpsQueue::ReadCharacteristic( - client_id, conn_id, charac.value_handle, - AscsClientImpl::OnReadOnlyPropertiesReadStatic, nullptr); - - ase_info.ase_ccc_handle = - find_ccc_handle(conn_id, charac.value_handle); - - if(charac.uuid == ASCS_SINK_ASE_UUID) { - dev->sink_ase_list.push_back(ase_info); - } else if(charac.uuid == ASCS_SRC_ASE_UUID) { - dev->src_ase_list.push_back(ase_info); - } - if(ase_info.ase_ccc_handle) { - /* Register and enable the Audio Status Notification */ - tGATT_STATUS register_status; - register_status = BTA_GATTC_RegisterForNotifications( - conn_id, dev->address, ase_info.ase_handle); - if (register_status != GATT_SUCCESS) { - LOG(ERROR) << __func__ - << ": BTA_GATTC_RegisterForNotifications failed, status=" - << loghex(register_status); - } - std::vector value(2); - uint8_t* ptr = value.data(); - UINT16_TO_STREAM(ptr, GATT_CHAR_CLIENT_CONFIG_NOTIFICATION); - GattOpsQueue::WriteDescriptor( - client_id, conn_id, ase_info.ase_ccc_handle, - std::move(value), GATT_WRITE, nullptr, nullptr); - } - } else if (charac.uuid == ASCS_ASE_CP_UUID) { - dev->ase_cp_handle = charac.value_handle; - - dev->ase_cp_ccc_handle = - find_ccc_handle(conn_id, charac.value_handle); - if(dev->ase_cp_ccc_handle) { - /* Register and enable the Audio Status Notification */ - tGATT_STATUS register_status; - register_status = BTA_GATTC_RegisterForNotifications( - conn_id, dev->address, dev->ase_cp_handle); - if (register_status != GATT_SUCCESS) { - LOG(ERROR) << __func__ - << ": BTA_GATTC_RegisterForNotifications failed, status=" - << loghex(register_status); - } - std::vector value(2); - uint8_t* ptr = value.data(); - UINT16_TO_STREAM(ptr, GATT_CHAR_CLIENT_CONFIG_NOTIFICATION); - GattOpsQueue::WriteDescriptor( - client_id, conn_id, dev->ase_cp_ccc_handle, - std::move(value), GATT_WRITE, nullptr, nullptr); - } - } else { - LOG(WARNING) << "Unknown characteristic found:" << charac.uuid; - } - } - - dev->notifications_enabled = true; - - if (dev->service_changed_rcvd) { - dev->service_changed_rcvd = false; - } - } - - const char* GetAseState(uint8_t event) { - switch (event) { - CASE_RETURN_STR(ASE_STATE_IDLE) - CASE_RETURN_STR(ASE_STATE_CODEC_CONFIGURED) - CASE_RETURN_STR(ASE_STATE_QOS_CONFIGURED) - CASE_RETURN_STR(ASE_STATE_ENABLING) - CASE_RETURN_STR(ASE_STATE_STREAMING) - CASE_RETURN_STR(ASE_STATE_DISABLING) - CASE_RETURN_STR(ASE_STATE_RELEASING) - default: - return "Unknown State"; - } - } - - const char* GetAseDirection(uint8_t event) { - switch (event) { - CASE_RETURN_STR(ASE_DIRECTION_SINK) - CASE_RETURN_STR(ASE_DIRECTION_SOURCE) - default: - return "Unknown Direction"; - } - } - - void ParseAseParams(uint8_t *p, AseParams *ase_params, uint8_t ase_dir) { - STREAM_TO_UINT8(ase_params->ase_id, p); - STREAM_TO_UINT8(ase_params->ase_state, p); - LOG(INFO) << __func__ - << ": ASE Id = " << loghex(ase_params->ase_id) - << ": ASE State = " << GetAseState(ase_params->ase_state) - << ": ASE Direction = " << GetAseDirection(ase_dir); - switch(ase_params->ase_state) { - case ASE_STATE_CODEC_CONFIGURED: { - AseCodecConfigParams *codec_config = - &ase_params->codec_config_params; - STREAM_TO_UINT8(codec_config->framing, p); - STREAM_TO_UINT8(codec_config->pref_phy, p); - - STREAM_TO_UINT8(codec_config->pref_rtn, p); - STREAM_TO_UINT16(codec_config->mtl, p); - STREAM_TO_ARRAY(&(codec_config->pd_min), p, - static_cast (sizeof(presentation_delay_t))); - STREAM_TO_ARRAY(&(codec_config->pd_max), p, - static_cast (sizeof(presentation_delay_t))); - STREAM_TO_ARRAY(&(codec_config->pref_pd_min), p, - static_cast (sizeof(presentation_delay_t))); - STREAM_TO_ARRAY(&(codec_config->pref_pd_max), p, - static_cast (sizeof(presentation_delay_t))); - STREAM_TO_ARRAY(&(codec_config->codec_id), - p, static_cast (sizeof(codec_type_t))); - STREAM_TO_UINT8(codec_config->codec_params_len, p); - if(codec_config->codec_params_len) { - codec_config->codec_params.resize(codec_config->codec_params_len); - STREAM_TO_ARRAY(codec_config->codec_params.data(), - p, codec_config->codec_params_len); - } - LOG(INFO) << ": Framing = " << loghex(codec_config->framing); - LOG(INFO) << ": Pref Phy = " << loghex(codec_config->pref_phy); - LOG(INFO) << ": Pref RTN = " << loghex(codec_config->pref_rtn); - LOG(INFO) << ": MTL = " << loghex(codec_config->mtl); - LOG(INFO) << ": PD Min =" - << " " << loghex(codec_config->pd_min[0]) - << " " << loghex(codec_config->pd_min[1]) - << " " << loghex(codec_config->pd_min[2]); - LOG(INFO) << ": PD Max =" - << " " << loghex(codec_config->pd_max[0]) - << " " << loghex(codec_config->pd_max[1]) - << " " << loghex(codec_config->pd_max[2]); - LOG(INFO) << ": Pref PD Min =" - << " " << loghex(codec_config->pref_pd_min[0]) - << " " << loghex(codec_config->pref_pd_min[1]) - << " " << loghex(codec_config->pref_pd_min[2]); - LOG(INFO) << ": Pref PD Max =" - << " " << loghex(codec_config->pref_pd_max[0]) - << " " << loghex(codec_config->pref_pd_max[1]) - << " " << loghex(codec_config->pref_pd_max[2]); - - LOG(INFO) << ": Codec ID = " << loghex(codec_config->codec_id[0]); - } break; - case ASE_STATE_QOS_CONFIGURED: { - AseQosConfigParams *qos_config = &ase_params->qos_config_params; - STREAM_TO_UINT8(qos_config->cig_id, p); - STREAM_TO_UINT8(qos_config->cis_id, p); - STREAM_TO_ARRAY(&(qos_config->sdu_interval), p, - static_cast (sizeof(sdu_interval_t))); - STREAM_TO_UINT8(qos_config->framing, p); - STREAM_TO_UINT8(qos_config->phy, p); - STREAM_TO_UINT16(qos_config->max_sdu_size, p); - STREAM_TO_UINT8(qos_config->rtn, p); - STREAM_TO_UINT16(qos_config->mtl, p); - STREAM_TO_ARRAY(&(qos_config->pd), p, - static_cast (sizeof(presentation_delay_t))); - - LOG(INFO) << ": Cig Id = " << loghex(qos_config->cig_id); - LOG(INFO) << ": Cis Id = " << loghex(qos_config->cis_id); - LOG(INFO) << ": SDU interval =" - << " " << loghex(qos_config->sdu_interval[0]) - << " " << loghex(qos_config->sdu_interval[1]) - << " " << loghex(qos_config->sdu_interval[2]); - LOG(INFO) << ": Framing = " << loghex(qos_config->framing); - LOG(INFO) << ": Phy = " << loghex(qos_config->phy); - LOG(INFO) << ": Max SDU size = " << loghex(qos_config->max_sdu_size); - LOG(INFO) << ": RTN = " << loghex(qos_config->rtn); - LOG(INFO) << ": MTL = " << loghex(qos_config->mtl); - LOG(INFO) << ": PD =" - << " " << loghex(qos_config->pd[0]) - << " " << loghex(qos_config->pd[1]) - << " " << loghex(qos_config->pd[2]); - } break; - case ASE_STATE_ENABLING: - case ASE_STATE_STREAMING: - case ASE_STATE_DISABLING: { - AseGenericParams *gen_params = &ase_params->generic_params; - STREAM_TO_UINT8(gen_params->cig_id, p); - STREAM_TO_UINT8(gen_params->cis_id, p); - STREAM_TO_UINT8(gen_params->meta_data_len, p); - if(gen_params->meta_data_len) { - gen_params->meta_data.resize(gen_params->meta_data_len); - STREAM_TO_ARRAY(gen_params->meta_data.data(), - p, gen_params->meta_data_len); - } - LOG(INFO) << ": Cig Id = " << loghex(gen_params->cig_id); - LOG(INFO) << ": Cis Id = " << loghex(gen_params->cis_id); - } break; - } - } - - void ParseAseNotification(uint16_t conn_id, - uint16_t handle, uint16_t len, uint8_t* value ) { - uint8_t *p = value; - bool ase_found = false; - AscsDevice* dev = ascsDevices.FindByConnId(conn_id); - if (!dev) { - LOG(INFO) << __func__ - << ": Skipping unknown device, conn_id=" << loghex(conn_id); - return; - } - - for (auto it = dev->sink_ase_list.begin(); - it != dev->sink_ase_list.end(); it++) { - if (it->ase_handle == handle) { - LOG(INFO) << __func__ << ": BD Addr : " << dev->address; - ParseAseParams(p, &it->ase_params, ASE_DIRECTION_SINK); - for (auto iter : callbacks) { - AscsClientCallbacks *ascs_callback = iter.second; - ascs_callback->OnAseState(dev->address, it->ase_params); - } - ase_found = true; - break; - } - } - if(!ase_found) { - for (auto it = dev->src_ase_list.begin(); - it != dev->src_ase_list.end(); it++) { - if (it->ase_handle == handle) { - LOG(INFO) << __func__ << ": BD Addr : " << dev->address; - ParseAseParams(p, &it->ase_params,ASE_DIRECTION_SOURCE); - for (auto iter : callbacks) { - AscsClientCallbacks *ascs_callback = iter.second; - ascs_callback->OnAseState(dev->address, it->ase_params); - } - ase_found = true; - break; - } - } - } - } - - void OnNotificationEvent(uint16_t conn_id, uint16_t handle, uint16_t len, - uint8_t* value) { - uint8_t* p = value; - AscsDevice* dev = ascsDevices.FindByConnId(conn_id); - if (!dev) { - LOG(INFO) << __func__ - << ": Skipping unknown device, conn_id=" << loghex(conn_id); - return; - } - - // check if the notification is for ASEs - if( dev->ase_cp_handle == handle) { // control point notification - AseCpNotification cp_notification; - STREAM_TO_UINT8(cp_notification.ase_opcode, p); - STREAM_TO_UINT8(cp_notification.num_ases, p); - uint8_t num_ases = cp_notification.num_ases; - std::vector ase_cp_notify_list; - AseOpStatus status; - bool notify = false; - - while(num_ases--) { - STREAM_TO_UINT8(status.ase_id, p); - STREAM_TO_UINT8(status.resp_code, p); - STREAM_TO_UINT8(status.reason, p); - if(status.resp_code) { - LOG(ERROR) << __func__ - << ": ASE Id = " << loghex(status.ase_id) - << ": Resp code = " << resp_codes[status.resp_code]; - if(status.reason) { - LOG(ERROR) << ": Reason = " << reason_codes[status.reason]; - } - notify = true; - } - - ase_cp_notify_list.push_back(status); - } - if(notify) { - for (auto iter : callbacks) { - AscsClientCallbacks *ascs_callback = iter.second; - LOG(ERROR) << __func__ << " ASE Operation failed"; - ascs_callback->OnAseOpFailed(dev->address, - (AseOpId) cp_notification.ase_opcode, - ase_cp_notify_list); - } - } - } else { - ParseAseNotification(conn_id, handle, len, value); - } - } - - - void OnCongestionEvent(uint16_t conn_id, bool congested) { - AscsDevice* dev = ascsDevices.FindByConnId(conn_id); - if (!dev) { - LOG(INFO) << __func__ - << ": Skipping unknown device, conn_id=" << loghex(conn_id); - return; - } - - LOG(WARNING) << __func__ << ": conn_id:" << loghex(conn_id) - << ", congested: " << congested; - dev->is_congested = congested; - GattOpsQueue::CongestionCallback(conn_id, congested); - } - - void OnReadAseState(uint16_t client_id, - uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, uint16_t len, uint8_t* value, - void* data) { - - AscsDevice* dev = ascsDevices.FindByConnId(conn_id); - if (!dev) { - LOG(ERROR) << __func__ << "unknown conn_id=" << loghex(conn_id); - return; - } - LOG(WARNING) << __func__; - - // check if the notification is for ASEs - ParseAseNotification(conn_id, handle, len, value); - } - - void OnReadOnlyPropertiesRead(uint16_t client_id, - uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, uint16_t len, - uint8_t *value, void* data) { - AscsDevice* dev = ascsDevices.FindByConnId(conn_id); - uint8_t *p = value; - if (!dev) { - LOG(ERROR) << __func__ << "unknown conn_id=" << loghex(conn_id); - return; - } - - for (auto it = dev->sink_ase_list.begin(); - it != dev->sink_ase_list.end(); it++) { - if (it->ase_handle == handle) { - dev->num_ases_read++; - ParseAseParams(p, &it->ase_params, ASE_DIRECTION_SINK); - break; - } - } - - for (auto it = dev->src_ase_list.begin(); - it != dev->src_ase_list.end(); it++) { - if (it->ase_handle == handle) { - dev->num_ases_read++; - ParseAseParams(p, &it->ase_params, ASE_DIRECTION_SOURCE); - break; - } - } - - LOG(INFO) << __func__ << ": num_ases_read : " - << loghex(dev->num_ases_read); - - if(dev->num_ases_read == (dev->sink_ase_list.size() + - dev->src_ase_list.size())) { - sink_ase_value_list.clear(); - src_ase_value_list.clear(); - dev->discovery_completed = true; - // Now update using service discovery callback - auto iter = callbacks.find(client_id); - if (iter != callbacks.end()) { - for (auto it : dev->sink_ase_list) { - memcpy(&ase, (void *) &it.ase_params, sizeof(ase)); - sink_ase_value_list.push_back(ase); - } - for (auto it : dev->src_ase_list) { - memcpy(&ase, (void *) &it.ase_params, sizeof(ase)); - src_ase_value_list.push_back(ase); - } - AscsClientCallbacks *callback = iter->second; - // check if all ascs characteristics are read - // send out the callback as service discovery completed - callback->OnSearchComplete(0, dev->address, - sink_ase_value_list, - src_ase_value_list); - } - } - } - - static void OnReadOnlyPropertiesReadStatic(uint16_t client_id, - uint16_t conn_id, - tGATT_STATUS status, - uint16_t handle, uint16_t len, - uint8_t* value, void* data) { - if (instance) - instance->OnReadOnlyPropertiesRead(client_id, conn_id, status, handle, - len, value, data); - } - - static void OnReadAseStateStatic(uint16_t client_id, - uint16_t conn_id, - tGATT_STATUS status, - uint16_t handle, uint16_t len, - uint8_t* value, void* data) { - if (instance) - instance->OnReadAseState(client_id, conn_id, status, handle, - len, value, data); - } - - private: - uint8_t gatt_client_id = BTA_GATTS_INVALID_IF; - uint16_t ascs_client_id = 0; - AscsDevices ascsDevices; - // client id to callbacks mapping - std::map callbacks; - - void find_server_changed_ccc_handle(uint16_t conn_id, - const gatt::Service* service) { - AscsDevice* ascsDevice = ascsDevices.FindByConnId(conn_id); - if (!ascsDevice) { - LOG(ERROR) << "Skipping unknown device, conn_id=" << loghex(conn_id); - return; - } - for (const gatt::Characteristic& charac : service->characteristics) { - if (charac.uuid == Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD)) { - ascsDevice->srv_changed_ccc_handle = - find_ccc_handle(conn_id, charac.value_handle); - if (!ascsDevice->srv_changed_ccc_handle) { - LOG(ERROR) << __func__ - << ": cannot find service changed CCC descriptor"; - continue; - } - LOG(INFO) << __func__ << " service_changed_ccc=" - << loghex(ascsDevice->srv_changed_ccc_handle); - break; - } - } - } - - // Find the handle for the client characteristics configuration of a given - // characteristics - uint16_t find_ccc_handle(uint16_t conn_id, uint16_t char_handle) { - const gatt::Characteristic* p_char = - BTA_GATTC_GetCharacteristic(conn_id, char_handle); - - if (!p_char) { - LOG(WARNING) << __func__ << ": No such characteristic: " << char_handle; - return 0; - } - - for (const gatt::Descriptor& desc : p_char->descriptors) { - if (desc.uuid == Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG)) - return desc.handle; - } - - return 0; - } -}; - -const char* get_gatt_event_name(uint32_t event) { - switch (event) { - CASE_RETURN_STR(BTA_GATTC_DEREG_EVT) - CASE_RETURN_STR(BTA_GATTC_OPEN_EVT) - CASE_RETURN_STR(BTA_GATTC_CLOSE_EVT) - CASE_RETURN_STR(BTA_GATTC_SEARCH_CMPL_EVT) - CASE_RETURN_STR(BTA_GATTC_NOTIF_EVT) - CASE_RETURN_STR(BTA_GATTC_ENC_CMPL_CB_EVT) - CASE_RETURN_STR(BTA_GATTC_CONN_UPDATE_EVT) - CASE_RETURN_STR(BTA_GATTC_SRVC_CHG_EVT) - CASE_RETURN_STR(BTA_GATTC_SRVC_DISC_DONE_EVT) - CASE_RETURN_STR(BTA_GATTC_CONGEST_EVT) - default: - return "Unknown Event"; - } -} - -void ascs_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) { - if (p_data == nullptr || !instance) return; - - LOG(INFO) << __func__ << ": Event : " << get_gatt_event_name(event); - - switch (event) { - case BTA_GATTC_DEREG_EVT: - break; - - case BTA_GATTC_OPEN_EVT: { - tBTA_GATTC_OPEN& o = p_data->open; - instance->OnGattConnected(o.status, o.conn_id, o.client_if, o.remote_bda, - o.transport, o.mtu); - break; - } - - case BTA_GATTC_CLOSE_EVT: { - tBTA_GATTC_CLOSE& c = p_data->close; - instance->OnGattDisconnected(c.status, c.conn_id, c.client_if, - c.remote_bda, c.reason); - } break; - - case BTA_GATTC_SEARCH_CMPL_EVT: - instance->OnServiceSearchComplete(p_data->search_cmpl.conn_id, - p_data->search_cmpl.status); - break; - - case BTA_GATTC_NOTIF_EVT: - if (!p_data->notify.is_notify || - p_data->notify.len > GATT_MAX_ATTR_LEN) { - LOG(ERROR) << __func__ << ": rejected BTA_GATTC_NOTIF_EVT. is_notify=" - << p_data->notify.is_notify - << ", len=" << p_data->notify.len; - break; - } - instance->OnNotificationEvent(p_data->notify.conn_id, - p_data->notify.handle, p_data->notify.len, - p_data->notify.value); - break; - - case BTA_GATTC_ENC_CMPL_CB_EVT: - instance->OnEncryptionComplete(p_data->enc_cmpl.remote_bda, true); - break; - - case BTA_GATTC_CONN_UPDATE_EVT: - instance->OnConnectionUpdateComplete(p_data->conn_update.conn_id, p_data); - break; - - case BTA_GATTC_SRVC_CHG_EVT: - instance->OnServiceChangeEvent(p_data->remote_bda); - break; - - case BTA_GATTC_SRVC_DISC_DONE_EVT: - instance->OnServiceDiscDoneEvent(p_data->remote_bda); - break; - case BTA_GATTC_CONGEST_EVT: - instance->OnCongestionEvent(p_data->congest.conn_id, - p_data->congest.congested); - break; - default: - break; - } -} - -void encryption_callback(const RawAddress* address, tGATT_TRANSPORT, void*, - tBTM_STATUS status) { - if (instance) { - instance->OnEncryptionComplete(*address, - status == BTM_SUCCESS ? true : false); - } -} - -void AscsClient::Init(AscsClientCallbacks* callbacks) { - if (instance) { - instance->Register(callbacks); - } else { - instance = new AscsClientImpl(); - instance->Register(callbacks); - } -} - -void AscsClient::CleanUp(uint16_t client_id) { - if(instance->GetClientCount()) { - instance->Deregister(client_id); - if(!instance->GetClientCount()) { - delete instance; - instance = nullptr; - } - } -} - -AscsClient* AscsClient::Get() { - CHECK(instance); - return instance; -} - -} // namespace ascs -} // namespace bap -} // namespace bluetooth diff --git a/le_audio/system/bt/bta/bap/connected_iso.cc b/le_audio/system/bt/bta/bap/connected_iso.cc deleted file mode 100644 index e97c50f9766edd0730a3ac38eef4f3d0f9a90c4c..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/bap/connected_iso.cc +++ /dev/null @@ -1,1555 +0,0 @@ -/****************************************************************************** - * - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - - -#include "bta_bap_uclient_api.h" -#include -#include "state_machine.h" -#include "stack/include/btm_ble_api_types.h" -#include "bt_trace.h" -#include "btif_util.h" -#include "osi/include/properties.h" - -namespace bluetooth { -namespace bap { -namespace cis { - -typedef struct { - uint8_t status; - uint16_t cis_handle; - uint8_t reason; -} tBTM_BLE_CIS_DISCONNECTED_EVT_PARAM; - -typedef struct { - uint8_t status; - uint16_t conn_handle; -} tBTM_BLE_CIS_DATA_PATH_EVT_PARAM; - -typedef struct { -uint8_t status; -uint8_t cig_id; -} tBTM_BLE_SET_CIG_REMOVE_PARAM; - -struct CIS; -class CisInterfaceCallbacks; -using bluetooth::bap::cis::CisInterfaceCallbacks; - -struct tIsoSetUpDataPath { - uint16_t conn_handle; - uint8_t data_path_direction; - uint8_t data_path_id; -}; - -struct tIsoRemoveDataPath { - uint16_t conn_handle; - uint8_t data_path_direction; -}; - -enum IsoHciEvent { - CIG_CONFIGURE_REQ = 0, - CIG_CONFIGURED_EVT, - CIS_CREATE_REQ, - CIS_STATUS_EVT, - CIS_ESTABLISHED_EVT, - CIS_DISCONNECT_REQ, - CIS_DISCONNECTED_EVT, - CIG_REMOVE_REQ, - CIG_REMOVED_EVT, - SETUP_DATA_PATH_REQ, - SETUP_DATA_PATH_DONE_EVT, - REMOVE_DATA_PATH_REQ, - REMOVE_DATA_PATH_DONE_EVT, - CIS_CREATE_REQ_DUMMY -}; - -struct DataPathNode { - IsoHciEvent type; - union { - tIsoSetUpDataPath setup_datapath; - tIsoRemoveDataPath rmv_datapath; - }; -}; - -class CisStateMachine : public bluetooth::common::StateMachine { - public: - enum { - kStateIdle, - kStateSettingDataPath, - kStateReady, - kStateEstablishing, - kStateDestroying, - kStateEstablished, - }; - - class StateIdle : public State { - public: - StateIdle(CisStateMachine& sm) - : State(sm, kStateIdle), cis_(sm.GetCis()) {} - void OnEnter() override; - void OnExit() override; - const char* GetState() { return "Idle"; } - bool ProcessEvent(uint32_t event, void* p_data) override; - - private: - CIS &cis_; - }; - - class StateSettingDataPath : public State { - public: - StateSettingDataPath(CisStateMachine& sm) - : State(sm, kStateSettingDataPath), cis_(sm.GetCis()) {} - void OnEnter() override; - void OnExit() override; - const char* GetState() { return "SettingDataPath"; } - bool ProcessEvent(uint32_t event, void* p_data) override; - - private: - CIS &cis_; - }; - - class StateReady : public State { - public: - StateReady(CisStateMachine& sm) - : State(sm, kStateReady), cis_(sm.GetCis()) {} - void OnEnter() override; - void OnExit() override; - const char* GetState() { return "Ready"; } - bool ProcessEvent(uint32_t event, void* p_data) override; - - private: - CIS &cis_; - }; - - class StateDestroying : public State { - public: - StateDestroying(CisStateMachine& sm) - : State(sm, kStateDestroying), cis_(sm.GetCis()) {} - void OnEnter() override; - void OnExit() override; - const char* GetState() { return "Destroying"; } - bool ProcessEvent(uint32_t event, void* p_data) override; - - private: - CIS &cis_; - }; - - class StateEstablishing : public State { - public: - StateEstablishing(CisStateMachine& sm) - : State(sm, kStateEstablishing), cis_(sm.GetCis()) {} - void OnEnter() override; - void OnExit() override; - const char* GetState() { return "Establishing"; } - bool ProcessEvent(uint32_t event, void* p_data) override; - - private: - CIS &cis_; - }; - - class StateEstablished : public State { - public: - StateEstablished(CisStateMachine& sm) - : State(sm, kStateEstablished), cis_(sm.GetCis()) {} - void OnEnter() override; - void OnExit() override; - const char* GetState() { return "Established"; } - bool ProcessEvent(uint32_t event, void* p_data) override; - - private: - CIS &cis_; - }; - - CisStateMachine(CIS &cis) : - cis(cis) { - state_idle_ = new StateIdle(*this); - state_setting_data_path_ = new StateSettingDataPath(*this); - state_ready_ = new StateReady(*this); - state_destroying_ = new StateDestroying(*this); - state_establishing_ = new StateEstablishing(*this); - state_established_ = new StateEstablished(*this); - - AddState(state_idle_); - AddState(state_setting_data_path_); - AddState(state_ready_); - AddState(state_destroying_); - AddState(state_establishing_); - AddState(state_established_); - - SetInitialState(state_idle_); - } - - CIS &GetCis() { return cis; } - - const char* GetEventName(uint32_t event) { - switch (event) { - CASE_RETURN_STR(CIG_CONFIGURE_REQ) - CASE_RETURN_STR(CIG_CONFIGURED_EVT) - CASE_RETURN_STR(CIS_CREATE_REQ) - CASE_RETURN_STR(CIS_STATUS_EVT) - CASE_RETURN_STR(CIS_ESTABLISHED_EVT) - CASE_RETURN_STR(CIS_DISCONNECT_REQ) - CASE_RETURN_STR(CIS_DISCONNECTED_EVT) - CASE_RETURN_STR(CIG_REMOVE_REQ) - CASE_RETURN_STR(CIG_REMOVED_EVT) - CASE_RETURN_STR(SETUP_DATA_PATH_REQ) - CASE_RETURN_STR(SETUP_DATA_PATH_DONE_EVT) - CASE_RETURN_STR(REMOVE_DATA_PATH_REQ) - CASE_RETURN_STR(REMOVE_DATA_PATH_DONE_EVT) - CASE_RETURN_STR(CIS_CREATE_REQ_DUMMY) - default: - return "Unknown Event"; - } - } - - private: - CIS &cis; - StateIdle *state_idle_; - StateSettingDataPath *state_setting_data_path_; - StateReady *state_ready_; - StateDestroying *state_destroying_; - StateEstablishing *state_establishing_; - StateEstablished *state_established_; -}; - -struct CIS { - uint8_t cig_id; - uint8_t cis_id; - uint16_t cis_handle; - bool to_air_setup_done; - bool from_air_setup_done; - uint8_t datapath_status; - uint8_t disc_direction; - uint8_t direction; // input or output or both - CisInterfaceCallbacks *cis_callback; - RawAddress peer_bda; - CISConfig cis_config; - CisStateMachine cis_sm; - CisState cis_state; - std::list datapath_queue; - - CIS(uint8_t cig_id, uint8_t cis_id, uint8_t direction, - CisInterfaceCallbacks* callback): - cig_id(cig_id), cis_id(cis_id), direction(direction), - cis_callback(callback), - cis_sm(*this) { - to_air_setup_done = false; - from_air_setup_done = false; - } -}; - -struct CreateCisNode { - uint8_t cig_id; - std::vector cis_ids; - std::vector cis_handles; - RawAddress peer_bda; -}; - -struct CIG { - CIGConfig cig_config; - CigState cig_state; - std::map clients_list; // address and count - std::map cis_list; // cis id to CIS -}; - -class CisInterfaceImpl; -CisInterfaceImpl *instance; - -static void hci_cig_param_callback(tBTM_BLE_SET_CIG_RET_PARAM *param); -static void hci_cig_param_test_callback(tBTM_BLE_SET_CIG_PARAM_TEST_RET *param); -static void hci_cig_remove_param_callback(uint8_t status, uint8_t cig_id); -static void hci_cis_create_status_callback( uint8_t status); -static void hci_cis_create_callback(tBTM_BLE_CIS_ESTABLISHED_EVT_PARAM *param); -static void hci_cis_setup_datapath_callback( uint8_t status, - uint16_t conn_handle); -static void hci_cis_disconnect_callback(uint8_t status, uint16_t cis_handle, - uint8_t reason); - -void CisStateMachine::StateIdle::OnEnter() { - LOG(INFO) << __func__ << ": CIS State : " << GetState(); -} - -void CisStateMachine::StateIdle::OnExit() { - -} - -bool CisStateMachine::StateIdle::ProcessEvent(uint32_t event, void* p_data) { - LOG(INFO) <<__func__ <<": CIS State = " << GetState() - <<": Event = " << cis_.cis_sm.GetEventName(event); - LOG(INFO) <<__func__ <<": CIS Id = " << loghex(cis_.cis_id); - LOG(INFO) <<__func__ <<": CIS Handle = " << loghex(cis_.cis_handle); - - bool cis_status = true; - switch (event) { - case SETUP_DATA_PATH_REQ: { - tIsoSetUpDataPath *data_path_info = (tIsoSetUpDataPath *) p_data; - tBTM_BLE_SET_ISO_DATA_PATH_PARAM p_params; - p_params.conn_handle = cis_.cis_handle; - p_params.data_path_dir = data_path_info->data_path_direction >> 1; - p_params.data_path_id = data_path_info->data_path_id; - p_params.codec_id[0] = 0x06; - memset(&p_params.codec_id[1], 0x00, sizeof(p_params.codec_id) - 1); - memset(&p_params.cont_delay, 0x00, sizeof(p_params.cont_delay)); - p_params.codec_config_length = 0x00; - p_params.codec_config = nullptr; - p_params.p_cb = &hci_cis_setup_datapath_callback; - if(BTM_BleSetIsoDataPath(&p_params) == HCI_SUCCESS) { - cis_.cis_sm.TransitionTo(CisStateMachine::kStateSettingDataPath); - DataPathNode node = { - .type = SETUP_DATA_PATH_REQ, - .setup_datapath = { - .conn_handle = cis_.cis_handle, - .data_path_direction = - data_path_info->data_path_direction, - .data_path_id = data_path_info->data_path_id - }, - }; - cis_.datapath_queue.push_back(node); - } - } break; - default: - cis_status = false; - break; - } - return cis_status; -} - -void CisStateMachine::StateSettingDataPath::OnEnter() { - LOG(INFO) << __func__ << ": CIS State : " << GetState(); -} - -void CisStateMachine::StateSettingDataPath::OnExit() { - -} - -bool CisStateMachine::StateSettingDataPath::ProcessEvent(uint32_t event, - void* p_data) { - LOG(INFO) <<__func__ <<": CIS State = " << GetState() - <<": Event = " << cis_.cis_sm.GetEventName(event); - LOG(INFO) <<__func__ <<": CIS Id = " << loghex(cis_.cis_id); - LOG(INFO) <<__func__ <<": CIS Handle = " << loghex(cis_.cis_handle); - - bool cis_status = true; - switch (event) { - case SETUP_DATA_PATH_REQ: { - // add them to the queue - tIsoSetUpDataPath *data_path_info = (tIsoSetUpDataPath *) p_data; - - DataPathNode node = { - .type = SETUP_DATA_PATH_REQ, - .setup_datapath = { - .conn_handle = cis_.cis_handle, - .data_path_direction = - data_path_info->data_path_direction, - .data_path_id = data_path_info->data_path_id - } - }; - - cis_.datapath_queue.push_back(node); - } break; - case SETUP_DATA_PATH_DONE_EVT: { - tBTM_BLE_CIS_DATA_PATH_EVT_PARAM *param = - (tBTM_BLE_CIS_DATA_PATH_EVT_PARAM *) p_data; - cis_.datapath_status = param->status; - - if(!cis_.datapath_queue.empty()) { - if(cis_.datapath_status == ISO_HCI_SUCCESS) { - DataPathNode node = cis_.datapath_queue.front(); - if(node.type == SETUP_DATA_PATH_REQ) { - uint8_t direction = node.setup_datapath.data_path_direction; - if(direction == DIR_TO_AIR) { - cis_.to_air_setup_done = true; - } else if( direction == DIR_FROM_AIR) { - cis_.from_air_setup_done = true; - } - } - } - // remove the entry as it is processed - cis_.datapath_queue.pop_front(); - } - - // check if there are any more entries in queue now - // expect the queue entry to be of setup datapath only - if(!cis_.datapath_queue.empty()) { - DataPathNode node = cis_.datapath_queue.front(); - if(node.type == SETUP_DATA_PATH_REQ) { - tBTM_BLE_SET_ISO_DATA_PATH_PARAM p_params; - p_params.conn_handle = node.setup_datapath.conn_handle; - p_params.data_path_dir = node.setup_datapath.data_path_direction >> 1; - p_params.data_path_id = node.setup_datapath.data_path_id; - p_params.codec_id[0] = 0x06; - memset(&p_params.codec_id[1], 0x00, sizeof(p_params.codec_id) - 1); - memset(&p_params.cont_delay, 0x00, sizeof(p_params.cont_delay)); - p_params.codec_config_length = 0x00; - p_params.codec_config = nullptr; - p_params.p_cb = &hci_cis_setup_datapath_callback; - if(BTM_BleSetIsoDataPath(&p_params) != HCI_SUCCESS) { - LOG(ERROR) << "Setup Datapath Failed"; - cis_.datapath_queue.pop_front(); - cis_.cis_sm.TransitionTo(CisStateMachine::kStateReady); - } - } else { - LOG(ERROR) << "Unexpected entry"; - } - } else { - cis_.cis_sm.TransitionTo(CisStateMachine::kStateReady); - } - } break; - default: - cis_status = false; - break; - } - return cis_status; -} - - -void CisStateMachine::StateReady::OnEnter() { - LOG(INFO) << __func__ << ": CIS State : " << GetState(); - // update the ready state incase of transitioned from states except - // setting up datapath as CIG state event is sufficient for transition - // from setting up data path to ready. - if(cis_.cis_sm.PreviousStateId() != CisStateMachine::kStateSettingDataPath) { - cis_.cis_callback->OnCisState(cis_.cig_id, cis_.cis_id, - cis_.direction, - CisState::READY); - } -} - -void CisStateMachine::StateReady::OnExit() { - -} - -bool CisStateMachine::StateReady::ProcessEvent(uint32_t event, void* p_data) { - LOG(INFO) <<__func__ <<": CIS State = " << GetState() - <<": Event = " << cis_.cis_sm.GetEventName(event); - LOG(INFO) <<__func__ <<": CIS Id = " << loghex(cis_.cis_id); - LOG(INFO) <<__func__ <<": CIS Handle = " << loghex(cis_.cis_handle); - - bool cis_status = true; - switch (event) { - case CIS_CREATE_REQ: { - tBTM_BLE_ISO_CREATE_CIS_CMD_PARAM cmd_data; - CreateCisNode *pNode = (CreateCisNode *) p_data; - cmd_data.cis_count = pNode->cis_ids.size(); - cmd_data.p_cb = &hci_cis_create_status_callback; - cmd_data.p_evt_cb = &hci_cis_create_callback; - tACL_CONN* acl = btm_bda_to_acl(pNode->peer_bda, BT_TRANSPORT_LE); - if(!acl) { - BTIF_TRACE_DEBUG("%s create_cis return ", __func__); - return false; - } - for (auto i: pNode->cis_handles) { - - tBTM_BLE_CHANNEL_MAP map = { .cis_conn_handle = i, - .acl_conn_handle = acl->hci_handle }; - cmd_data.link_conn_handles.push_back(map); - } - if(BTM_BleCreateCis(&cmd_data, &hci_cis_disconnect_callback) - == HCI_SUCCESS) - cis_.cis_sm.TransitionTo(CisStateMachine::kStateEstablishing); - } break; - case CIS_CREATE_REQ_DUMMY: { - cis_.cis_sm.TransitionTo(CisStateMachine::kStateEstablishing); - } break; - default: - cis_status = false; - break; - } - return cis_status; -} - - -void CisStateMachine::StateDestroying::OnEnter() { - LOG(INFO) << __func__ << ": CIS State : " << GetState(); - cis_.cis_callback->OnCisState(cis_.cig_id, cis_.cis_id, - cis_.direction, - CisState::DESTROYING); -} - -void CisStateMachine::StateDestroying::OnExit() { - -} - -bool CisStateMachine::StateDestroying::ProcessEvent(uint32_t event, - void* p_data) { - LOG(INFO) <<__func__ <<": CIS State = " << GetState() - <<": Event = " << cis_.cis_sm.GetEventName(event); - LOG(INFO) <<__func__ <<": CIS Id = " << loghex(cis_.cis_id); - LOG(INFO) <<__func__ <<": CIS Handle = " << loghex(cis_.cis_handle); - - bool cis_status = true; - switch (event) { - case CIS_DISCONNECTED_EVT: { - tBTM_BLE_CIS_DISCONNECTED_EVT_PARAM *param = - (tBTM_BLE_CIS_DISCONNECTED_EVT_PARAM *) p_data; - if(param->status != ISO_HCI_SUCCESS) { - LOG(ERROR) <<__func__ << " cis disconnection failed"; - cis_.cis_sm.TransitionTo(cis_.cis_sm.PreviousStateId()); - } else { - cis_.cis_sm.TransitionTo(CisStateMachine::kStateReady); - } - } break; - default: - cis_status = false; - break; - } - return cis_status; -} - - -void CisStateMachine::StateEstablishing::OnEnter() { - LOG(INFO) << __func__ << ": CIS State : " << GetState(); - cis_.cis_callback->OnCisState(cis_.cig_id, cis_.cis_id, - cis_.direction, - CisState::ESTABLISHING); -} - -void CisStateMachine::StateEstablishing::OnExit() { - -} - -bool CisStateMachine::StateEstablishing::ProcessEvent(uint32_t event, - void* p_data) { - LOG(INFO) <<__func__ <<": CIS State = " << GetState() - <<": Event = " << cis_.cis_sm.GetEventName(event); - LOG(INFO) <<__func__ <<": CIS Id = " << loghex(cis_.cis_id); - LOG(INFO) <<__func__ <<": CIS Handle = " << loghex(cis_.cis_handle); - - bool cis_status = true; - switch (event) { - case CIS_STATUS_EVT: { - uint8_t status = *((uint8_t *)(p_data)); - if(status != ISO_HCI_SUCCESS) { - cis_.cis_sm.TransitionTo(CisStateMachine::kStateReady); - } - } break; - case CIS_ESTABLISHED_EVT: { - tBTM_BLE_CIS_ESTABLISHED_EVT_PARAM *param = - (tBTM_BLE_CIS_ESTABLISHED_EVT_PARAM *) p_data; - if(param->status != ISO_HCI_SUCCESS) { - cis_.cis_sm.TransitionTo(CisStateMachine::kStateReady); - } else { - cis_.cis_sm.TransitionTo(CisStateMachine::kStateEstablished); - - } - } break; - default: - cis_status = false; - break; - } - return cis_status; -} - -void CisStateMachine::StateEstablished::OnEnter() { - LOG(INFO) << __func__ << ": CIS State : " << GetState(); - cis_.disc_direction = cis_.direction; - cis_.cis_callback->OnCisState(cis_.cig_id, cis_.cis_id, - cis_.direction, - CisState::ESTABLISHED); -} - -void CisStateMachine::StateEstablished::OnExit() { - -} - -bool CisStateMachine::StateEstablished::ProcessEvent(uint32_t event, - void* p_data) { - LOG(INFO) <<__func__ <<": CIS State = " << GetState() - <<": Event = " << cis_.cis_sm.GetEventName(event); - LOG(INFO) <<__func__ <<": CIS Id = " << loghex(cis_.cis_id); - LOG(INFO) <<__func__ <<": CIS Handle = " << loghex(cis_.cis_handle); - - switch (event) { - case CIS_DISCONNECT_REQ: - if(BTM_BleIsoCisDisconnect(cis_.cis_handle, 0x13 , - &hci_cis_disconnect_callback) == - HCI_SUCCESS) { - cis_.cis_sm.TransitionTo(CisStateMachine::kStateDestroying); - } - break; - case CIS_DISCONNECTED_EVT: { - tBTM_BLE_CIS_DISCONNECTED_EVT_PARAM *param = - (tBTM_BLE_CIS_DISCONNECTED_EVT_PARAM *) p_data; - if(param->status != ISO_HCI_SUCCESS) { - LOG(ERROR) <<__func__ << " cis disconnection failed"; - cis_.cis_sm.TransitionTo(cis_.cis_sm.PreviousStateId()); - } else { - cis_.cis_sm.TransitionTo(CisStateMachine::kStateReady); - } - } break; - default: - break; - } - return true; -} - -class CisInterfaceImpl : public CisInterface { - public: - CisInterfaceImpl(CisInterfaceCallbacks* callback): - callbacks(callback) { } - - ~CisInterfaceImpl() override = default; - - void CleanUp () { - - } - - CigState GetCigState(const uint8_t &cig_id) override { - CIG *cig = GetCig(cig_id); - if (cig != nullptr) { - return cig->cig_state; - } else { - return CigState::IDLE; - } - } - - CisState GetCisState(const uint8_t &cig_id, uint8_t cis_id) override { - return CisState::READY; - } - - uint8_t GetCisCount(const uint8_t &cig_id) override { - return 0; - } - - IsoHciStatus CreateCig(RawAddress client_peer_bda, bool reconfig, - CIGConfig &cig_config, - std::vector &cis_configs) override { - // check if CIG already exists - LOG(INFO) << __func__ << " : CIG Id = " << loghex(cig_config.cig_id); - CIG *cig = GetCig(cig_config.cig_id); - if (cig != nullptr) { - auto it = cig->clients_list.find(client_peer_bda); - if (it == cig->clients_list.end()) { - cig->clients_list.insert(std::make_pair(client_peer_bda, 0x01)); - } else { - if(!reconfig) { - // increment the count - it->second++; - } - } - // check if params are same for group requested - // and for the group alredy exists - if(cig->cig_state == CigState::CREATING) { - return ISO_HCI_IN_PROGRESS; - } else if(IsCigParamsSame(cig_config, cis_configs)) { - if(cig->cig_state == CigState::CREATED) { - return ISO_HCI_SUCCESS; - } - } - } - - // check if the CIS vector length is same as cis count passed - // in CIG confifuration - if(cig_config.cis_count != cis_configs.size()) { - return ISO_HCI_FAILED; - } - - char value[PROPERTY_VALUE_MAX] = {0}; - bool create_cig = false; - property_get("persist.vendor.btstack.get_cig_test_param", value, ""); - uint16_t ft_m_s, ft_s_m, iso_int, clk_accuracy, nse, pdu_m_s, pdu_s_m, bn_m_s, bn_s_m; - int res = sscanf(value, "%hu,%hu,%hu,%hu,%hu,%hu,%hu,%hu,%hu", &ft_m_s, &ft_s_m, &iso_int, - &clk_accuracy, &nse, &pdu_m_s, &pdu_s_m, &bn_m_s, &bn_s_m); - LOG(WARNING) << __func__<< ": FT_M_S: " << loghex(ft_m_s) << ", FT_S_M: " << loghex(ft_s_m) - << ", ISO_Interval: " << loghex(iso_int) << ", slave_clock: " << loghex(clk_accuracy) - << ", NSE: " << loghex(nse) << ", PDU_M_S:" << loghex(pdu_m_s) - << " PDU_S_M:" << loghex(pdu_s_m) << ", BN_M_S: " << loghex(bn_m_s) - << ", BN_S_M: " << loghex(bn_s_m); - if (res == 9) { - tBTM_BLE_SET_CIG_PARAM_TEST p_data_test; - p_data_test.cig_id = cig_config.cig_id; - memcpy(&p_data_test.sdu_int_s_to_m, &cig_config.sdu_interval_s_to_m, - sizeof(p_data_test.sdu_int_s_to_m)); - - memcpy(&p_data_test.sdu_int_m_to_s, &cig_config.sdu_interval_m_to_s, - sizeof(p_data_test.sdu_int_m_to_s)); - - p_data_test.ft_m_to_s = ft_m_s; - p_data_test.ft_s_to_m = ft_s_m; - p_data_test.iso_interval = iso_int; - p_data_test.slave_clock_accuracy = clk_accuracy; - p_data_test.packing = cig_config.packing; - p_data_test.framing = cig_config.framing; - p_data_test.cis_count = cig_config.cis_count; - - for (auto it = cis_configs.begin(); it != cis_configs.end();) { - tBTM_BLE_CIS_TEST_CONFIG cis_config; - cis_config.cis_id = it->cis_id; - cis_config.nse = nse; - cis_config.max_sdu_m_to_s = it->max_sdu_m_to_s; - cis_config.max_sdu_s_to_m = it->max_sdu_s_to_m; - cis_config.max_pdu_m_to_s = it->max_sdu_m_to_s; - cis_config.max_pdu_s_to_m = it->max_sdu_s_to_m; - cis_config.phy_m_to_s = it->phy_m_to_s; - cis_config.phy_s_to_m = it->phy_s_to_m; - cis_config.bn_m_to_s = bn_m_s; - cis_config.bn_s_to_m = 0; - if (cis_config.max_sdu_s_to_m > 0) { - cis_config.bn_s_to_m = bn_s_m; - if (cis_config.max_sdu_m_to_s > 0 && cis_config.nse > 13) { - cis_config.nse = 13; - } - } - p_data_test.cis_config.push_back(cis_config); - it++; - } - p_data_test.p_cb = &hci_cig_param_test_callback; - create_cig = (BTM_BleSetCigParametersTest(&p_data_test) == HCI_SUCCESS); - } else { - tBTM_BLE_ISO_SET_CIG_CMD_PARAM p_data; - p_data.cig_id = cig_config.cig_id; - memcpy(&p_data.sdu_int_s_to_m, &cig_config.sdu_interval_s_to_m, - sizeof(p_data.sdu_int_s_to_m)); - - memcpy(&p_data.sdu_int_m_to_s, &cig_config.sdu_interval_m_to_s, - sizeof(p_data.sdu_int_m_to_s)); - - p_data.slave_clock_accuracy = 0x00; - p_data.packing = cig_config.packing; - p_data.framing = cig_config.framing; - p_data.max_transport_latency_m_to_s = cig_config.max_tport_latency_m_to_s; - p_data.max_transport_latency_s_to_m = cig_config.max_tport_latency_s_to_m; - p_data.cis_count = cig_config.cis_count; - - for (auto it = cis_configs.begin(); it != cis_configs.end();) { - tBTM_BLE_CIS_CONFIG cis_config; - memcpy(&cis_config, &(*it), sizeof(tBTM_BLE_CIS_CONFIG)); - p_data.cis_config.push_back(cis_config); - it++; - } - p_data.p_cb = &hci_cig_param_callback; - create_cig = (BTM_BleSetCigParam(&p_data) == HCI_SUCCESS); - } - if(create_cig) { - // create new CIG and add it to the list - if(cig == nullptr) { - CIG *cig = new (CIG); - cig_list.insert(std::make_pair(cig_config.cig_id, cig)); - cig->cig_config = cig_config; - cig->cig_state = CigState::CREATING; - - for(uint8_t i = 0; i < cig_config.cis_count; i++) { - uint8_t direction = 0; - if(cis_configs[i].max_sdu_m_to_s) direction |= DIR_TO_AIR; - if(cis_configs[i].max_sdu_s_to_m) direction |= DIR_FROM_AIR; - - CIS *cis = new CIS(cig_config.cig_id, cis_configs[i].cis_id, - direction, callbacks); - cis->cis_config = cis_configs[i]; - cig->cis_list.insert(std::make_pair(cis_configs[i].cis_id, cis)); - } - - auto it = cig->clients_list.find(client_peer_bda); - if (it == cig->clients_list.end()) { - cig->clients_list.insert(std::make_pair(client_peer_bda, 0x01)); - } else { - // increment the count - it->second++; - LOG(WARNING) << __func__ << "count " << loghex(it->second); - } - } else { - cig->cig_config = cig_config; - cig->cig_state = CigState::CREATING; - - uint8_t i = 0; - for (auto it = cig->cis_list.begin(); it != cig->cis_list.end();) { - CIS *cis = it->second; - cis->cis_config = cis_configs[i]; - cis->cis_sm.TransitionTo(CisStateMachine::kStateIdle); - it++; i++; - } - - auto it = cig->clients_list.find(client_peer_bda); - if (it == cig->clients_list.end()) { - cig->clients_list.insert(std::make_pair(client_peer_bda, 0x01)); - } - } - return ISO_HCI_IN_PROGRESS; - } else { - return ISO_HCI_FAILED; - } - } - - IsoHciStatus RemoveCig(RawAddress client_peer_bda, uint8_t cig_id) override { - LOG(INFO) <<__func__ << ": CIG Id = " << loghex(cig_id); - // check if the CIG exists - CIG *cig = GetCig(cig_id); - if (cig == nullptr) { - return ISO_HCI_FAILED; - } - - if(cig->cig_state == CigState::IDLE || - cig->cig_state == CigState::CREATING) { - return ISO_HCI_FAILED; - } else if(cig->cig_state == CigState::CREATED) { - - auto it = cig->clients_list.find(client_peer_bda); - if (it == cig->clients_list.end()) { - return ISO_HCI_FAILED; - } else { - // decrement the count - it->second--; - LOG(WARNING) << __func__ << ": Count : " << loghex(it->second); - } - - // check if all clients have voted off then go for CIG removal - uint8_t vote_on_count = 0; - for (auto it = cig->clients_list.begin(); - it != cig->clients_list.end();) { - vote_on_count += it->second; - it++; - } - - if(vote_on_count) { - LOG(WARNING) << __func__ << " : Vote On Count : " - << loghex(vote_on_count); - return ISO_HCI_SUCCESS; - } - - // check if any of the CIS are in established/streaming state - // if so return false as it is not allowed - if(IsCisActive(cig_id, 0xFF)) return ISO_HCI_FAILED; - - if(BTM_BleRemoveCig(cig_id, &hci_cig_remove_param_callback) - == HCI_SUCCESS) { - cig->cig_state = CigState::REMOVING; - return ISO_HCI_IN_PROGRESS; - } else return ISO_HCI_FAILED; - } - return ISO_HCI_FAILED; - } - - IsoHciStatus CreateCis(uint8_t cig_id, std::vector cis_ids, - RawAddress peer_bda) override { - LOG(INFO) <<__func__ << ": CIG Id = " << loghex(cig_id); - LOG(INFO) <<__func__ << ": No. of CISes = " << loghex(cis_ids.size()); - - IsoHciStatus ret; - uint32_t cur_state; - // check if the CIG exists - CIG *cig = GetCig(cig_id); - if (cig == nullptr) { - return ISO_HCI_FAILED; - } - - if(cig->cig_state != CigState::CREATED) { - return ISO_HCI_FAILED; - } - - bool cis_created = false; - CreateCisNode param; - param.cig_id = cig_id; - param.cis_ids = cis_ids; - param.peer_bda = peer_bda; - std::vector cis_handles; - - for (auto i: cis_ids) { - CIS *cis = GetCis(cig_id, i); - if (cis == nullptr) { - return ISO_HCI_FAILED; - } - cis_handles.push_back(cis->cis_handle); - } - param.cis_handles = cis_handles; - - for (auto i: cis_ids) { - LOG(INFO) <<__func__ << ": CIS Id = " << loghex(i); - // check if CIS ID mentioned is present as part of CIG - CIS *cis = GetCis(cig_id, i); - if (cis == nullptr) { - ret = ISO_HCI_FAILED; - break; - } - - cur_state = cis->cis_sm.StateId(); - - // check if CIS is already created or in progress - if(cur_state == CisStateMachine::kStateEstablishing) { - ret = ISO_HCI_IN_PROGRESS; - break; - } else if(cur_state == CisStateMachine::kStateEstablished) { - ret = ISO_HCI_SUCCESS; - break; - } else if(cur_state == CisStateMachine::kStateDestroying) { - ret = ISO_HCI_FAILED; - break; - } - if (cis_created == false) { - // queue it if there is pending create CIS - if (cis_queue.size()) { - // hand it over to the CIS module - // check if the new request is already exists - // as the head entry in the list - CreateCisNode& head = cis_queue.front(); - if(head.cig_id == cig_id && head.cis_ids == cis_ids && - head.peer_bda == peer_bda) { - if(cis->cis_sm.ProcessEvent( - IsoHciEvent::CIS_CREATE_REQ, ¶m)) { - ret = ISO_HCI_IN_PROGRESS; - } else { - ret = ISO_HCI_FAILED; - break; - } - } else { - cis_queue.push_back(param); - } - } else { - cis_queue.push_back(param); - if(cis->cis_sm.ProcessEvent(IsoHciEvent::CIS_CREATE_REQ, - ¶m)) { - ret = ISO_HCI_IN_PROGRESS; - } else { - ret = ISO_HCI_FAILED; - break; - } - } - cis_created = true; - } else { - if(cis->cis_sm.ProcessEvent(IsoHciEvent::CIS_CREATE_REQ_DUMMY, - &peer_bda)) { - ret = ISO_HCI_IN_PROGRESS; - } else { - ret = ISO_HCI_FAILED; - break; - } - } - } - return ret; - } - - IsoHciStatus DisconnectCis(uint8_t cig_id, uint8_t cis_id, - uint8_t direction) override { - LOG(INFO) <<__func__ << ": CIG Id = " << loghex(cig_id) - << ": CIS Id = " << loghex(cis_id); - - uint32_t cur_state; - // check if the CIG exists - CIG *cig = GetCig(cig_id); - if (cig == nullptr) { - return ISO_HCI_FAILED; - } - - if(cig->cig_state != CigState::CREATED) { - return ISO_HCI_FAILED; - } - - // check if CIS ID mentioned is present as part of CIG - CIS *cis = GetCis(cig_id, cis_id); - if (cis == nullptr) { - return ISO_HCI_FAILED; - } - - if(cis->disc_direction & direction) { - // remove the direction bit form disc direciton - cis->disc_direction &= ~direction; - } - - if(cis->disc_direction) return ISO_HCI_SUCCESS; - - // if all directions are voted off go for CIS disconneciton - cur_state = cis->cis_sm.StateId(); - - // check if CIS is not created or in progress - if(cur_state == CisStateMachine::kStateReady) { - return ISO_HCI_SUCCESS; - } else if(cur_state == CisStateMachine::kStateEstablishing) { - return ISO_HCI_FAILED; - } else if(cur_state == CisStateMachine::kStateDestroying) { - return ISO_HCI_IN_PROGRESS; - } - - LOG(INFO) <<__func__ << " Request issued to CIS SM"; - // hand it over to the CIS module - if(cis->cis_sm.ProcessEvent( - IsoHciEvent::CIS_DISCONNECT_REQ, nullptr)) { - return ISO_HCI_IN_PROGRESS; - } else return ISO_HCI_FAILED; - } - - IsoHciStatus SetupDataPath(uint8_t cig_id, uint8_t cis_id, - uint8_t data_path_direction, uint8_t data_path_id) override { - LOG(INFO) <<__func__ << ": CIG Id = " << loghex(cig_id) - << ": CIS Id = " << loghex(cis_id); - - uint32_t cur_state; - // check if the CIG exists - CIG *cig = GetCig(cig_id); - if (cig == nullptr) { - return ISO_HCI_FAILED; - } - - if(cig->cig_state != CigState::CREATED) { - return ISO_HCI_FAILED; - } - - // check if CIS ID mentioned is present as part of CIG - CIS *cis = GetCis(cig_id, cis_id); - if (cis == nullptr) { - return ISO_HCI_FAILED; - } - - cur_state = cis->cis_sm.StateId(); - - // check if CIS is not created or in progress - if(cur_state == CisStateMachine::kStateReady || - cur_state == CisStateMachine::kStateEstablishing || - cur_state == CisStateMachine::kStateDestroying) { - return ISO_HCI_FAILED; - } else if(cur_state == CisStateMachine::kStateEstablished) { - // return success as it is already created - return ISO_HCI_SUCCESS; - } - - // hand it over to the CIS module - tIsoSetUpDataPath data_path_info; - data_path_info.data_path_direction = data_path_direction; - data_path_info.data_path_id = data_path_id; - - if(cis->cis_sm.ProcessEvent( - IsoHciEvent::SETUP_DATA_PATH_REQ, &data_path_info)) { - return ISO_HCI_IN_PROGRESS; - } else return ISO_HCI_FAILED; - } - - IsoHciStatus RemoveDataPath(uint8_t cig_id, uint8_t cis_id, - uint8_t data_path_direction) override { - LOG(INFO) <<__func__ << ": CIG Id = " << loghex(cig_id) - << ": CIS Id = " << loghex(cis_id); - - uint32_t cur_state; - // check if the CIG exists - CIG *cig = GetCig(cig_id); - if (cig == nullptr) { - return ISO_HCI_FAILED; - } - - if(cig->cig_state != CigState::CREATED) { - return ISO_HCI_FAILED; - } - - // check if CIS ID mentioned is present as part of CIG - CIS *cis = GetCis(cig_id, cis_id); - if (cis == nullptr) { - return ISO_HCI_FAILED; - } - - cur_state = cis->cis_sm.StateId(); - - // check if CIS is not created or in progress - if(cur_state == CisStateMachine::kStateReady || - cur_state == CisStateMachine::kStateEstablishing || - cur_state == CisStateMachine::kStateDestroying || - cur_state == CisStateMachine::kStateEstablished) { - return ISO_HCI_FAILED; - } - - // hand it over to the CIS module - if(cis->cis_sm.ProcessEvent( - IsoHciEvent::REMOVE_DATA_PATH_REQ, &data_path_direction)) { - return ISO_HCI_SUCCESS; - } else return ISO_HCI_FAILED; - } - - const char* GetEventName(uint32_t event) { - switch (event) { - CASE_RETURN_STR(CIG_CONFIGURED_EVT) - CASE_RETURN_STR(CIS_STATUS_EVT) - CASE_RETURN_STR(CIS_ESTABLISHED_EVT) - CASE_RETURN_STR(CIS_DISCONNECTED_EVT) - CASE_RETURN_STR(CIG_REMOVED_EVT) - CASE_RETURN_STR(SETUP_DATA_PATH_DONE_EVT) - CASE_RETURN_STR(REMOVE_DATA_PATH_DONE_EVT) - default: - return "Unknown Event"; - } - } - - IsoHciStatus ProcessEvent (uint32_t event, void* p_data) { - LOG(INFO) <<__func__ <<": Event = " << GetEventName(event); - switch (event) { - case CIG_CONFIGURED_EVT: { - tBTM_BLE_SET_CIG_RET_PARAM *param = - (tBTM_BLE_SET_CIG_RET_PARAM *) p_data; - LOG(INFO) <<__func__ <<": CIG Id = " << loghex(param->cig_id) - << ": status = " << loghex(param->status); - - auto it = cig_list.find(param->cig_id); - if (it == cig_list.end()) { - return ISO_HCI_FAILED; - } - - if(!param->status) { - uint8_t i = 0; - CIG *cig = it->second; - tIsoSetUpDataPath data_path_info; - - for (auto it = cig->cis_list.begin(); - it != cig->cis_list.end(); it++) { - CIS *cis = it->second; - cis->cis_handle = *(param->conn_handle + i++); - cis->cis_sm.Start(); - if(cis->direction & DIR_TO_AIR) { - data_path_info.data_path_direction = DIR_TO_AIR; - data_path_info.data_path_id = 0x01; - cis->cis_sm.ProcessEvent(IsoHciEvent::SETUP_DATA_PATH_REQ, - &data_path_info); - } - if(cis->direction & DIR_FROM_AIR) { - data_path_info.data_path_direction = DIR_FROM_AIR; - data_path_info.data_path_id = 0x01; - cis->cis_sm.ProcessEvent(IsoHciEvent::SETUP_DATA_PATH_REQ, - &data_path_info); - } - } - } else { - // delete CIG and CIS - CIG *cig = it->second; - cig->cig_state = CigState::IDLE; - - while (!cig->cis_list.empty()) { - auto it = cig->cis_list.begin(); - CIS * cis = it->second; - cig->cis_list.erase(it); - delete cis; - } - callbacks->OnCigState(param->cig_id, CigState::IDLE); - cig_list.erase(it); - delete cig; - } - - } break; - case CIG_REMOVED_EVT: { - tBTM_BLE_SET_CIG_REMOVE_PARAM *param = - (tBTM_BLE_SET_CIG_REMOVE_PARAM *) p_data; - auto it = cig_list.find(param->cig_id); - if (it == cig_list.end()) { - return ISO_HCI_FAILED; - } else { - // delete CIG and CIS - CIG *cig = it->second; - while (!cig->cis_list.empty()) { - auto it = cig->cis_list.begin(); - CIS * cis = it->second; - cig->cis_list.erase(it); - delete cis; - } - cig->cig_state = CigState::IDLE; - cig_list.erase(it); - callbacks->OnCigState(param->cig_id, CigState::IDLE); - delete cig; - } - } break; - case CIS_STATUS_EVT: { - // clear the first entry from cis queue and send the next - // CIS creation request queue it if there is pending create CIS - CreateCisNode &head = cis_queue.front(); - for (auto i: head.cis_ids) { - CIS *cis = GetCis(head.cig_id, i); - if(cis) { - cis->cis_sm.ProcessEvent(IsoHciEvent::CIS_STATUS_EVT, p_data); - } - } - } break; - case CIS_ESTABLISHED_EVT: { - tBTM_BLE_CIS_ESTABLISHED_EVT_PARAM *param = - (tBTM_BLE_CIS_ESTABLISHED_EVT_PARAM *) p_data; - LOG(INFO) << __func__ << ": CIS handle = " - << loghex(param->connection_handle) - << ": Status = " << loghex(param->status); - CIS *cis = GetCis(param->connection_handle); - if (cis == nullptr) { - return ISO_HCI_FAILED; - } else { - cis->cis_sm.ProcessEvent(IsoHciEvent::CIS_ESTABLISHED_EVT, p_data); - } - bool cis_status = false; - if (cis_queue.size()) { - cis_queue.pop_front(); - } - while(cis_queue.size() && !cis_status) { - CreateCisNode &head = cis_queue.front(); - CIS *cis = GetCis(head.cig_id, head.cis_ids[0]); - if(cis == nullptr || - cis->cis_sm.StateId() == CisStateMachine::kStateEstablished) { - // remove the entry - cis_queue.pop_front(); - } else if(cis) { - IsoHciStatus hci_status = CreateCis(head.cig_id, head.cis_ids, - head.peer_bda); - if(hci_status == ISO_HCI_SUCCESS || - hci_status == ISO_HCI_IN_PROGRESS) { - cis_status = true; - } else { - // remove the entry - cis_queue.pop_front(); - } - } - } - } break; - case CIS_DISCONNECTED_EVT: { - tBTM_BLE_CIS_DISCONNECTED_EVT_PARAM *param = - (tBTM_BLE_CIS_DISCONNECTED_EVT_PARAM *) p_data; - CIS *cis = GetCis(param->cis_handle); - if (cis == nullptr) { - return ISO_HCI_FAILED; - } else { - cis->cis_sm.ProcessEvent(IsoHciEvent::CIS_DISCONNECTED_EVT, p_data); - } - } break; - case SETUP_DATA_PATH_DONE_EVT: { - tBTM_BLE_CIS_DATA_PATH_EVT_PARAM *param = - (tBTM_BLE_CIS_DATA_PATH_EVT_PARAM *) p_data; - - CIS *cis = GetCis(param->conn_handle); - CIG *cig = nullptr; - if (cis == nullptr) { - return ISO_HCI_FAILED; - } else { - cis->cis_sm.ProcessEvent(IsoHciEvent::SETUP_DATA_PATH_DONE_EVT, - p_data); - } - uint8_t cig_id = cis->cig_id; - - auto it = cig_list.find(cig_id); - if (it == cig_list.end()) { - break; - } else { - // delete CIG and CIS - cig = it->second; - } - - uint8_t num_cis_is_ready = 0; - for(auto it = cig->cis_list.begin(); it != cig->cis_list.end(); it++) { - CIS *cis = it->second; - if(cis->cis_sm.StateId() == CisStateMachine::kStateReady) { - num_cis_is_ready++; - } - } - - // check if all setup data paths are completed - if(num_cis_is_ready == cig->cis_list.size()) { - cig->cig_state = CigState::CREATED; - callbacks->OnCigState(cig_id, CigState::CREATED); - } - } break; - case REMOVE_DATA_PATH_DONE_EVT: { - tBTM_BLE_CIS_DATA_PATH_EVT_PARAM *param = - (tBTM_BLE_CIS_DATA_PATH_EVT_PARAM *) p_data; - CIS *cis = GetCis(param->conn_handle); - if (cis == nullptr) { - return ISO_HCI_FAILED; - } else { - cis->cis_sm.ProcessEvent(IsoHciEvent::REMOVE_DATA_PATH_DONE_EVT, - p_data); - } - } break; - default: - break; - } - return ISO_HCI_SUCCESS; - } - - private: - std::map cig_list; // cig id to CIG structure - std::list cis_queue; - CisInterfaceCallbacks *callbacks; - // 0xFF will be passed for cis id in case search is for any of the - // CIS part of that group - bool IsCisActive(uint8_t cig_id, uint8_t cis_id) { - bool is_cis_active = false; - auto it = cig_list.find(cig_id); - if (it == cig_list.end()) { - return is_cis_active; - } else { - CIG *cig = it->second; - if(cis_id != 0XFF) { - auto it = cig->cis_list.find(cis_id); - if (it != cig->cis_list.end()) { - CIS *cis = it->second; - if(cis->cis_sm.StateId() == CisStateMachine::kStateEstablished) { - is_cis_active = true; - } - } - } else { - for (auto it : cig->cis_list) { - CIS *cis = it.second; - if(cis->cis_sm.StateId() == CisStateMachine::kStateEstablished) { - is_cis_active = true; - break; - } - } - } - } - return is_cis_active; - } - - bool IsCigParamsSame(CIGConfig &cig_config, - std::vector &cis_configs) { - CIG *cig = GetCig(cig_config.cig_id); - bool is_params_same = true; - uint8_t i = 0; - - if(cig == nullptr || (cis_configs.size() != cig->cig_config.cis_count)) { - LOG(WARNING) << __func__ << ": Count is different "; - return false; - } - - if(cig->cig_config.cig_id != cig_config.cig_id || - cig->cig_config.cis_count != cig_config.cis_count || - cig->cig_config.packing != cig_config.packing || - cig->cig_config.framing != cig_config.framing || - cig->cig_config.max_tport_latency_m_to_s != - cig_config.max_tport_latency_m_to_s || - cig->cig_config.max_tport_latency_s_to_m != - cig_config.max_tport_latency_s_to_m || - cig->cig_config.sdu_interval_m_to_s[0] != - cig_config.sdu_interval_m_to_s[0] || - cig->cig_config.sdu_interval_m_to_s[1] != - cig_config.sdu_interval_m_to_s[1] || - cig->cig_config.sdu_interval_m_to_s[2] != - cig_config.sdu_interval_m_to_s[2] || - cig->cig_config.sdu_interval_s_to_m[0] != - cig_config.sdu_interval_s_to_m[0] || - cig->cig_config.sdu_interval_s_to_m[1] != - cig_config.sdu_interval_s_to_m[1] || - cig->cig_config.sdu_interval_s_to_m[2] != - cig_config.sdu_interval_s_to_m[2]) { - LOG(WARNING) << __func__ << " cig params are different "; - return false; - } - - for (auto it = cig->cis_list.begin(); it != cig->cis_list.end();) { - CIS *cis = it->second; - if(cis->cis_config.cis_id == cis_configs[i].cis_id && - cis->cis_config.max_sdu_m_to_s == cis_configs[i].max_sdu_m_to_s && - cis->cis_config.max_sdu_s_to_m == cis_configs[i].max_sdu_s_to_m && - cis->cis_config.phy_m_to_s == cis_configs[i].phy_m_to_s && - cis->cis_config.phy_s_to_m == cis_configs[i].phy_s_to_m && - cis->cis_config.rtn_m_to_s == cis_configs[i].rtn_m_to_s && - cis->cis_config.rtn_s_to_m == cis_configs[i].rtn_s_to_m) { - it++; i++; - } else { - is_params_same = false; - break; - } - } - LOG(WARNING) << __func__ << ": is_params_same : " - << loghex(is_params_same); - return is_params_same; - } - - bool IsCisExists(uint8_t cig_id, uint8_t cis_id) { - bool is_cis_exists = false; - auto it = cig_list.find(cig_id); - if (it != cig_list.end()) { - CIG *cig = it->second; - auto it = cig->cis_list.find(cis_id); - if (it != cig->cis_list.end()) { - is_cis_exists = true; - } - } - return is_cis_exists; - } - - CIS *GetCis(uint8_t cig_id, uint8_t cis_id) { - auto it = cig_list.find(cig_id); - if (it != cig_list.end()) { - CIG *cig = it->second; - auto it = cig->cis_list.find(cis_id); - if (it != cig->cis_list.end()) { - return it->second; - } - } - return nullptr; - } - - CIG *GetCig(uint8_t cig_id) { - auto it = cig_list.find(cig_id); - if (it != cig_list.end()) { - return it->second; - } - return nullptr; - } - - CIS *GetCis(uint16_t cis_handle) { - bool cis_found = false; - CIS *cis = nullptr; - for (auto it : cig_list) { - CIG *cig = it.second; - if(cig->cig_state == CigState::CREATED || - cig->cig_state == CigState::CREATING) { - for (auto it : cig->cis_list) { - cis = it.second; - if(cis->cis_handle == cis_handle) { - cis_found = true; - break; - } - } - } - if(cis_found) return cis; - } - return nullptr; - } - - // TODO to remove if there is no need - bool IsCisEstablished(uint8_t cig_id, uint8_t cis_id) { - bool is_cis_established = false; - auto it = cig_list.find(cig_id); - if (it == cig_list.end()) { - return false; - } else { - CIG *cig = it->second; - if(cis_id != 0XFF) { - auto it = cig->cis_list.find(cis_id); - if (it != cig->cis_list.end()) { - CIS *cis = it->second; - if(cis->cis_sm.StateId() == CisStateMachine::kStateEstablished) { - is_cis_established = true; - } - } - } else { - for (auto it : cig->cis_list) { - CIS *cis = it.second; - if(cis->cis_sm.StateId() == CisStateMachine::kStateEstablished) { - is_cis_established = true; - break; - } - } - } - } - return is_cis_established; - } - - // TODO to remove if there is no need - bool IsCisStreaming(uint8_t cig_id, uint8_t cis_id) { - bool is_cis_streaming = false; - auto it = cig_list.find(cig_id); - if (it == cig_list.end()) { - return false; - } else { - CIG *cig = it->second; - if(cis_id != 0XFF) { - auto it = cig->cis_list.find(cis_id); - if (it != cig->cis_list.end()) { - CIS *cis = it->second; - if(cis->cis_sm.StateId() == CisStateMachine::kStateEstablished) { - is_cis_streaming = true; - } - } - } else { - for (auto it : cig->cis_list) { - CIS *cis = it.second; - if(cis->cis_sm.StateId() == CisStateMachine::kStateEstablished) { - is_cis_streaming = true; - break; - } - } - } - } - return is_cis_streaming; - } -}; - -void CisInterface::Initialize( - CisInterfaceCallbacks* callbacks) { - if (instance) { - LOG(ERROR) << "Already initialized!"; - } else { - instance = new CisInterfaceImpl(callbacks); - } -} - -void CisInterface::CleanUp() { - - CisInterfaceImpl* ptr = instance; - instance = nullptr; - ptr->CleanUp(); - delete ptr; -} - -CisInterface* CisInterface::Get() { - CHECK(instance); - return instance; -} - -static void hci_cig_param_callback(tBTM_BLE_SET_CIG_RET_PARAM *param) { - if (instance) { - instance->ProcessEvent(IsoHciEvent::CIG_CONFIGURED_EVT, param); - } -} - -static void hci_cig_param_test_callback(tBTM_BLE_SET_CIG_PARAM_TEST_RET *param) { - if (instance) { - instance->ProcessEvent(IsoHciEvent::CIG_CONFIGURED_EVT, param); - } -} - -static void hci_cig_remove_param_callback(uint8_t status, uint8_t cig_id) { - tBTM_BLE_SET_CIG_REMOVE_PARAM param = { .status = status, - .cig_id = cig_id }; - if (instance) { - instance->ProcessEvent(IsoHciEvent::CIG_REMOVED_EVT, ¶m); - } -} - -static void hci_cis_create_status_callback ( uint8_t status) { - if (instance) { - instance->ProcessEvent(IsoHciEvent::CIS_STATUS_EVT, &status); - } -} - -static void hci_cis_create_callback ( - tBTM_BLE_CIS_ESTABLISHED_EVT_PARAM *param) { - if (instance) { - instance->ProcessEvent(IsoHciEvent::CIS_ESTABLISHED_EVT, param); - } -} - -static void hci_cis_setup_datapath_callback ( uint8_t status, - uint16_t conn_handle) { - tBTM_BLE_CIS_DATA_PATH_EVT_PARAM param = { .status = status, - .conn_handle = conn_handle }; - if (instance) { - instance->ProcessEvent(IsoHciEvent::SETUP_DATA_PATH_DONE_EVT, ¶m); - } -} - -static void hci_cis_disconnect_callback ( uint8_t status, uint16_t cis_handle, - uint8_t reason) { - tBTM_BLE_CIS_DISCONNECTED_EVT_PARAM param = { .status = status, - .cis_handle = cis_handle, - .reason = reason - }; - if (instance) { - instance->ProcessEvent(IsoHciEvent::CIS_DISCONNECTED_EVT, ¶m); - } -} - -#if 0 -static void hci_cis_remove_datapath_callback ( uint8_t status, - uint16_t conn_handle) { - tBTM_BLE_CIS_DATA_PATH_EVT_PARAM param = { .status = status, - .conn_handle = conn_handle }; - if (instance) { - instance->ProcessEvent(IsoHciEvent::REMOVE_DATA_PATH_DONE_EVT, ¶m); - } -} -#endif - -} // namespace ucast -} // namespace bap -} // namespace bluetooth diff --git a/le_audio/system/bt/bta/bap/gattc_ops_queue.cc b/le_audio/system/bt/bta/bap/gattc_ops_queue.cc deleted file mode 100644 index 7c7b187d0f8501a48985b451f7f34cebe2f981e5..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/bap/gattc_ops_queue.cc +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/* - * Copyright 2017 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 "gattc_ops_queue.h" - -#include -#include -#include - -namespace bluetooth { -namespace bap { - -using gatt_operation = GattOpsQueue::gatt_operation; -using bluetooth::Uuid; - -constexpr uint8_t GATT_READ_CHAR = 1; -constexpr uint8_t GATT_READ_DESC = 2; -constexpr uint8_t GATT_WRITE_CHAR = 3; -constexpr uint8_t GATT_WRITE_DESC = 4; -constexpr uint8_t GATT_SERV_SEARCH = 5; - -struct gatt_read_op_data { - BAP_GATT_READ_OP_CB cb; - void* cb_data; -}; - -std::unordered_map> - GattOpsQueue::gatt_op_queue; -std::unordered_set GattOpsQueue::gatt_op_queue_executing; - -std::unordered_map GattOpsQueue::congestion_queue; - -void GattOpsQueue::mark_as_not_executing(uint16_t conn_id) { - gatt_op_queue_executing.erase(conn_id); -} - -void GattOpsQueue::gatt_read_op_finished(uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, uint16_t len, - uint8_t* value, void* data) { - gatt_read_op_data* tmp = (gatt_read_op_data*)data; - BAP_GATT_READ_OP_CB tmp_cb = tmp->cb; - void* tmp_cb_data = tmp->cb_data; - - APPL_TRACE_DEBUG("%s: conn_id=0x%x handle=%d status=%d len=%d", __func__, - conn_id, handle, status, len); - - osi_free(data); - - auto map_ptr = gatt_op_queue.find(conn_id); - if (map_ptr == gatt_op_queue.end() || map_ptr->second.empty()) { - APPL_TRACE_DEBUG("%s: no more operations queued for conn_id %d", __func__, - conn_id); - return; - } - - std::list& gatt_ops = map_ptr->second; - gatt_operation op = gatt_ops.front(); - gatt_ops.pop_front(); - - mark_as_not_executing(conn_id); - gatt_execute_next_op(conn_id); - - if (tmp_cb) { - tmp_cb(op.client_id, conn_id, status, handle, len, value, tmp_cb_data); - return; - } -} - -struct gatt_write_op_data { - BAP_GATT_WRITE_OP_CB cb; - void* cb_data; -}; - -void GattOpsQueue::gatt_write_op_finished(uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, void* data) { - gatt_write_op_data* tmp = (gatt_write_op_data*)data; - BAP_GATT_WRITE_OP_CB tmp_cb = tmp->cb; - void* tmp_cb_data = tmp->cb_data; - - APPL_TRACE_DEBUG("%s: conn_id=0x%x handle=%d status=%d", __func__, conn_id, - handle, status); - - osi_free(data); - - auto map_ptr = gatt_op_queue.find(conn_id); - if (map_ptr == gatt_op_queue.end() || map_ptr->second.empty()) { - APPL_TRACE_DEBUG("%s: no more operations queued for conn_id %d", __func__, - conn_id); - return; - } - - std::list& gatt_ops = map_ptr->second; - gatt_operation op = gatt_ops.front(); - gatt_ops.pop_front(); - - mark_as_not_executing(conn_id); - gatt_execute_next_op(conn_id); - - if (tmp_cb) { - tmp_cb(op.client_id, conn_id, status, handle, tmp_cb_data); - return; - } -} - -void GattOpsQueue::gatt_execute_next_op(uint16_t conn_id) { - APPL_TRACE_DEBUG("%s: conn_id=0x%x", __func__, conn_id); - if (gatt_op_queue.empty()) { - APPL_TRACE_DEBUG("%s: op queue is empty", __func__); - return; - } - - auto ptr = congestion_queue.find(conn_id); - - if (ptr != congestion_queue.end()) { - bool is_congested = ptr->second; - APPL_TRACE_DEBUG("%s: congestion queue exist, conn_id: %d, is_congested: %d", - __func__, conn_id, is_congested); - if(is_congested) { - APPL_TRACE_DEBUG("%s: lower layer is congested", __func__); - return; - } - } - - auto map_ptr = gatt_op_queue.find(conn_id); - - if (map_ptr == gatt_op_queue.end()) { - APPL_TRACE_DEBUG("%s: Queue is null", __func__); - return; - } - - if (map_ptr->second.empty()) { - APPL_TRACE_DEBUG("%s: queue is empty for conn_id: %d", __func__, - conn_id); - return; - } - - if (gatt_op_queue_executing.count(conn_id)) { - APPL_TRACE_DEBUG("%s: can't enqueue next op, already executing", __func__); - return; - } - - gatt_op_queue_executing.insert(conn_id); - - std::list& gatt_ops = map_ptr->second; - - gatt_operation& op = gatt_ops.front(); - - APPL_TRACE_DEBUG("%s: op.type=%d, handle=%d", __func__, op.type, - op.handle); - if (op.type == GATT_READ_CHAR) { - gatt_read_op_data* data = - (gatt_read_op_data*)osi_malloc(sizeof(gatt_read_op_data)); - data->cb = op.read_cb; - data->cb_data = op.read_cb_data; - BTA_GATTC_ReadCharacteristic(conn_id, op.handle, GATT_AUTH_REQ_NONE, - gatt_read_op_finished, data); - - } else if (op.type == GATT_READ_DESC) { - gatt_read_op_data* data = - (gatt_read_op_data*)osi_malloc(sizeof(gatt_read_op_data)); - data->cb = op.read_cb; - data->cb_data = op.read_cb_data; - BTA_GATTC_ReadCharDescr(conn_id, op.handle, GATT_AUTH_REQ_NONE, - gatt_read_op_finished, data); - - } else if (op.type == GATT_WRITE_CHAR) { - gatt_write_op_data* data = - (gatt_write_op_data*)osi_malloc(sizeof(gatt_write_op_data)); - data->cb = op.write_cb; - data->cb_data = op.write_cb_data; - BTA_GATTC_WriteCharValue(conn_id, op.handle, op.write_type, - std::move(op.value), GATT_AUTH_REQ_NONE, - gatt_write_op_finished, data); - - } else if (op.type == GATT_WRITE_DESC) { - gatt_write_op_data* data = - (gatt_write_op_data*)osi_malloc(sizeof(gatt_write_op_data)); - data->cb = op.write_cb; - data->cb_data = op.write_cb_data; - BTA_GATTC_WriteCharDescr(conn_id, op.handle, std::move(op.value), - GATT_AUTH_REQ_NONE, gatt_write_op_finished, data); - } else if (op.type == GATT_SERV_SEARCH) { - BTA_GATTC_ServiceSearchRequest(conn_id, op.p_srvc_uuid); - } -} - -void GattOpsQueue::Clean(uint16_t conn_id) { - APPL_TRACE_DEBUG("%s: conn_id=0x%x", __func__, conn_id); - - gatt_op_queue.erase(conn_id); - gatt_op_queue_executing.erase(conn_id); -} - -void GattOpsQueue::ReadCharacteristic(uint16_t client_id, - uint16_t conn_id, uint16_t handle, - BAP_GATT_READ_OP_CB cb, void* cb_data) { - gatt_op_queue[conn_id].push_back({.type = GATT_READ_CHAR, - .client_id = client_id, - .handle = handle, - .read_cb = cb, - .read_cb_data = cb_data}); - gatt_execute_next_op(conn_id); -} - -void GattOpsQueue::ReadDescriptor(uint16_t client_id, - uint16_t conn_id, uint16_t handle, - BAP_GATT_READ_OP_CB cb, void* cb_data) { - gatt_op_queue[conn_id].push_back({.type = GATT_READ_DESC, - .client_id = client_id, - .handle = handle, - .read_cb = cb, - .read_cb_data = cb_data}); - gatt_execute_next_op(conn_id); -} - -void GattOpsQueue::WriteCharacteristic(uint16_t client_id, - uint16_t conn_id, uint16_t handle, - std::vector value, - tGATT_WRITE_TYPE write_type, - BAP_GATT_WRITE_OP_CB cb, void* cb_data) { - gatt_op_queue[conn_id].push_back({.type = GATT_WRITE_CHAR, - .client_id = client_id, - .handle = handle, - .write_type = write_type, - .write_cb = cb, - .write_cb_data = cb_data, - .value = std::move(value)}); - gatt_execute_next_op(conn_id); -} - -void GattOpsQueue::WriteDescriptor(uint16_t client_id, - uint16_t conn_id, uint16_t handle, - std::vector value, - tGATT_WRITE_TYPE write_type, - BAP_GATT_WRITE_OP_CB cb, void* cb_data) { - gatt_op_queue[conn_id].push_back({.type = GATT_WRITE_DESC, - .client_id = client_id, - .handle = handle, - .write_type = write_type, - .write_cb = cb, - .write_cb_data = cb_data, - .value = std::move(value)}); - gatt_execute_next_op(conn_id); -} - -void GattOpsQueue::ServiceSearch(uint16_t client_id, - uint16_t conn_id, Uuid* srvc_uuid) { - gatt_op_queue[conn_id].push_back({.type = GATT_SERV_SEARCH, - .client_id = client_id, - .p_srvc_uuid = srvc_uuid}); - gatt_execute_next_op(conn_id); -} - -uint16_t GattOpsQueue::ServiceSearchComplete(uint16_t conn_id, - tGATT_STATUS status) { - auto map_ptr = gatt_op_queue.find(conn_id); - if (map_ptr == gatt_op_queue.end() || map_ptr->second.empty()) { - APPL_TRACE_DEBUG("%s: no more operations queued for conn_id %d", __func__, - conn_id); - return 0; - } - - std::list& gatt_ops = map_ptr->second; - - gatt_operation gatt_op = gatt_ops.front(); - gatt_ops.pop_front(); - mark_as_not_executing(conn_id); - gatt_execute_next_op(conn_id); - return gatt_op.client_id; -} - -void GattOpsQueue::CongestionCallback(uint16_t conn_id, bool congested) { - congestion_queue[conn_id] = congested; - if(!congested) { - gatt_execute_next_op(conn_id); - } -} - -} // namespace bap -} // namespace bluetooth diff --git a/le_audio/system/bt/bta/bap/gattc_ops_queue.h b/le_audio/system/bt/bta/bap/gattc_ops_queue.h deleted file mode 100644 index 4dd952536fd2783824413012cdfefeb365956a9f..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/bap/gattc_ops_queue.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/* - * Copyright 2017 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 "bta_gatt_api.h" - -typedef void (*BAP_GATT_READ_OP_CB)(uint16_t client_id,uint16_t conn_id, - tGATT_STATUS status, uint16_t handle, - uint16_t len, uint8_t* value, - void* data); - -typedef void (*BAP_GATT_WRITE_OP_CB)(uint16_t client_id, uint16_t conn_id, - tGATT_STATUS status, - uint16_t handle, void* data); - -/* BTA GATTC implementation does not allow for multiple commands queuing. So one - * client making calls to BTA_GATTC_ReadCharacteristic, BTA_GATTC_ReadCharDescr, - * BTA_GATTC_WriteCharValue, BTA_GATTC_WriteCharDescr must wait for the callacks - * before scheduling next operation. - * - * Methods below can be used as replacement to BTA_GATTC_* in BTA app. They do - * queue the commands if another command is currently being executed. - * - * If you decide to use those methods in your app, make sure to not mix it with - * existing BTA_GATTC_* API. - */ - -namespace bluetooth { -namespace bap { - -class GattOpsQueue { - public: - static void Clean(uint16_t conn_id); - static void ReadCharacteristic(uint16_t client_id, - uint16_t conn_id, uint16_t handle, - BAP_GATT_READ_OP_CB cb, void* cb_data); - static void ReadDescriptor(uint16_t client_id, - uint16_t conn_id, uint16_t handle, - BAP_GATT_READ_OP_CB cb, void* cb_data); - static void WriteCharacteristic(uint16_t client_id, - uint16_t conn_id, uint16_t handle, - std::vector value, - tGATT_WRITE_TYPE write_type, - BAP_GATT_WRITE_OP_CB cb, void* cb_data); - static void WriteDescriptor(uint16_t client_id, - uint16_t conn_id, uint16_t handle, - std::vector value, - tGATT_WRITE_TYPE write_type, BAP_GATT_WRITE_OP_CB cb, - void* cb_data); - static void ServiceSearch(uint16_t client_id, - uint16_t conn_id, Uuid* p_srvc_uuid); - - static uint16_t ServiceSearchComplete(uint16_t conn_id, tGATT_STATUS status); - - static void CongestionCallback(uint16_t conn_id, bool congested); - - - /* Holds pending GATT operations */ - struct gatt_operation { - uint8_t type; - uint16_t client_id; - uint16_t handle; - BAP_GATT_READ_OP_CB read_cb; - void* read_cb_data; - BAP_GATT_WRITE_OP_CB write_cb; - void* write_cb_data; - - /* write-specific fields */ - tGATT_WRITE_TYPE write_type; - std::vector value; - - /* discovery specific */ - Uuid* p_srvc_uuid; - }; - - private: - static bool is_congested; - - static void mark_as_not_executing(uint16_t conn_id); - static void gatt_execute_next_op(uint16_t conn_id); - static void gatt_read_op_finished(uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, uint16_t len, - uint8_t* value, void* data); - static void gatt_write_op_finished(uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, void* data); - - // maps connection id to operations waiting for execution - static std::unordered_map> gatt_op_queue; - - // maps connection id to congestion status of each device - static std::unordered_map congestion_queue; - - // contain connection ids that currently execute operations - static std::unordered_set gatt_op_queue_executing; -}; - -} // namespace bap -} // namespace bluetooth diff --git a/le_audio/system/bt/bta/bap/gatts_ops_queue.cc b/le_audio/system/bt/bta/bap/gatts_ops_queue.cc deleted file mode 100644 index b84fe6593fa5c4d4c38dc0b281eb34813e0d6c84..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/bap/gatts_ops_queue.cc +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/* - * Copyright 2017 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 "gatts_ops_queue.h" - -#include -#include -#include - -namespace bluetooth { -namespace bap { - -using gatts_operation = GattsOpsQueue::gatts_operation; -using bluetooth::Uuid; - -constexpr uint8_t GATT_NOTIFY = 1; - -std::unordered_map> - GattsOpsQueue::gatts_op_queue; -std::unordered_set GattsOpsQueue::gatts_op_queue_executing; -std::unordered_map GattsOpsQueue::congestion_queue; - -void GattsOpsQueue::mark_as_not_executing(uint16_t conn_id) { - gatts_op_queue_executing.erase(conn_id); -} - -void GattsOpsQueue::gatts_execute_next_op(uint16_t conn_id) { - APPL_TRACE_DEBUG("%s: conn_id=0x%x", __func__, conn_id); - - if (gatts_op_queue.empty()) { - APPL_TRACE_DEBUG("%s: op queue is empty", __func__); - return; - } - - auto ptr = congestion_queue.find(conn_id); - - if (ptr != congestion_queue.end()) { - bool is_congested = ptr->second; - APPL_TRACE_DEBUG("%s: congestion queue exist, conn_id: %d, is_congested: %d", - __func__, conn_id, is_congested); - if(is_congested) { - APPL_TRACE_DEBUG("%s: lower layer is congested", __func__); - return; - } - } - - auto map_ptr = gatts_op_queue.find(conn_id); - - if (map_ptr == gatts_op_queue.end()) { - APPL_TRACE_DEBUG("%s: Queue is null", __func__); - return; - } - - if (map_ptr->second.empty()) { - APPL_TRACE_DEBUG("%s: queue is empty for conn_id: %d", __func__, - conn_id); - return; - } - - if (gatts_op_queue_executing.count(conn_id)) { - APPL_TRACE_DEBUG("%s: can't enqueue next op, already executing", __func__); - return; - } - - std::list& gatts_ops = map_ptr->second; - gatts_operation& op = gatts_ops.front(); - APPL_TRACE_DEBUG("%s: op.type=%d, attr_id=%d", - __func__, op.type, op.attr_id); - - if(op.type == GATT_NOTIFY) { - if(GATTS_CheckStatusForApp(conn_id,op.need_confirm) == GATT_SUCCESS) { - BTA_GATTS_HandleValueIndication(conn_id, op.attr_id, op.value, op.need_confirm); - gatts_op_queue_executing.insert(conn_id); - } - } -} - -void GattsOpsQueue::Clean(uint16_t conn_id) { - APPL_TRACE_DEBUG("%s: conn_id=0x%x", __func__, conn_id); - - gatts_op_queue.erase(conn_id); - gatts_op_queue_executing.erase(conn_id); -} - -void GattsOpsQueue::SendNotification(uint16_t conn_id, - uint16_t handle, - std::vector value, - bool need_confirm) { - gatts_op_queue[conn_id].push_back({.type = GATT_NOTIFY, - .attr_id = handle, - .value = value, - .need_confirm = need_confirm}); - gatts_execute_next_op(conn_id); -} - -void GattsOpsQueue::NotificationCallback(uint16_t conn_id){ - auto map_ptr = gatts_op_queue.find(conn_id); - if (map_ptr == gatts_op_queue.end() || map_ptr->second.empty()) { - APPL_TRACE_DEBUG("%s: no more operations queued for conn_id %d", - __func__, conn_id); - return; - } - - std::list& gatts_ops = map_ptr->second; - gatts_operation op = gatts_ops.front(); - gatts_ops.pop_front(); - mark_as_not_executing(conn_id); - gatts_execute_next_op(conn_id); -} - -void GattsOpsQueue::CongestionCallback(uint16_t conn_id, bool congested) { - APPL_TRACE_DEBUG("%s: conn_id: %d, congested: %d", - __func__, conn_id,congested); - - congestion_queue[conn_id] = congested; - if(!congested) { - gatts_execute_next_op(conn_id); - } -} - -} -} // namespace ends diff --git a/le_audio/system/bt/bta/bap/gatts_ops_queue.h b/le_audio/system/bt/bta/bap/gatts_ops_queue.h deleted file mode 100644 index 6c0d5a855c949b07de99845a70a8f85baae0386e..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/bap/gatts_ops_queue.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/* - * Copyright 2017 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 "bta_gatt_api.h" -namespace bluetooth { -namespace bap { - -class GattsOpsQueue { - public: - static void Clean(uint16_t conn_id); - static void SendNotification(uint16_t conn_id, uint16_t handle, std::vector value, bool need_confirm); - static void NotificationCallback(uint16_t conn_id); - static void CongestionCallback(uint16_t conn_id, bool congested); - - /* Holds pending GATT operations */ - struct gatts_operation { - uint8_t type; - uint16_t attr_id; - std::vector value; - bool need_confirm; - }; - - private: - static bool is_congested; - static void mark_as_not_executing(uint16_t conn_id); - static void gatts_execute_next_op(uint16_t conn_id); - - // maps connection id to operations waiting for execution - static std::unordered_map> gatts_op_queue; - - // maps connection id to congestion status of each device - static std::unordered_map congestion_queue; - - // contain connection ids that currently execute operations - static std::unordered_set gatts_op_queue_executing; - -}; // Class GattsOpsQueue ends - -} -} // namespace ends diff --git a/le_audio/system/bt/bta/bap/pacs_client.cc b/le_audio/system/bt/bta/bap/pacs_client.cc deleted file mode 100644 index 47397e0c1799aea7ac2572bfdac245ae4f42372a..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/bap/pacs_client.cc +++ /dev/null @@ -1,1861 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/* - * 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 "bta_gatt_api.h" -#include "bta_pacs_client_api.h" -#include "gattc_ops_queue.h" -#include -#include -#include -#include -#include "device/include/controller.h" -#include "osi/include/properties.h" - -#include -#include "btif/include/btif_bap_config.h" -#include "osi/include/log.h" -#include "btif_util.h" -#include -#include "btif_bap_codec_utils.h" - -namespace bluetooth { -namespace bap { -namespace pacs { - -//using bluetooth::bap::pacs::PacsClientCallbacks; -using base::Closure; -using bluetooth::bap::GattOpsQueue; - -Uuid PACS_UUID = Uuid::FromString("1850"); -Uuid PACS_SINK_PAC_UUID = Uuid::FromString("2BC9"); -Uuid PACS_SINK_LOC_UUID = Uuid::FromString("2BCA"); -Uuid PACS_SRC_PAC_UUID = Uuid::FromString("2BCB"); -Uuid PACS_SRC_LOC_UUID = Uuid::FromString("2BCC"); -Uuid PACS_AVA_AUDIO_UUID = Uuid::FromString("2BCD"); -Uuid PACS_SUP_AUDIO_UUID = Uuid::FromString("2BCE"); - -class PacsClientImpl; -PacsClientImpl* instance; - -typedef uint8_t codec_type_t[5]; - -constexpr uint8_t SINK_PAC = 0x01; -constexpr uint8_t SRC_PAC = 0x02; -constexpr uint8_t SINK_LOC = 0x04; -constexpr uint8_t SRC_LOC = 0x08; -constexpr uint8_t AVAIL_CONTEXTS = 0x10; -constexpr uint8_t SUPP_CONTEXTS = 0x20; - -constexpr uint8_t LTV_TYPE_SUP_FREQS = 0x01; -constexpr uint8_t LTV_TYPE_SUP_FRAME_DUR = 0x02; -constexpr uint8_t LTV_TYPE_CHNL_COUNTS = 0x03; -constexpr uint8_t LTV_TYPE_OCTS_PER_FRAME = 0x04; -constexpr uint8_t LTV_TYPE_MAX_SUP_FRAMES_PER_SDU = 0x05; - -constexpr uint8_t LTV_TYPE_PREF_AUD_CONTEXT = 0x01; -constexpr uint8_t LTV_TYPE_VS_META_DATA = 0xFF;//TODO -constexpr uint16_t QTI_ID = 0x000A; - -constexpr uint8_t LTV_TYPE_VS_META_DATA_LC3Q = 0x10; - -//constexpr uint16_t SAMPLE_RATE_NONE = 0x0; -constexpr uint16_t SAMPLE_RATE_8K = 0x1 << 0; -//constexpr uint16_t SAMPLE_RATE_11K = 0x1 << 1; -constexpr uint16_t SAMPLE_RATE_16K = 0x1 << 2; -//constexpr uint16_t SAMPLE_RATE_22K = 0x1 << 3; -constexpr uint16_t SAMPLE_RATE_24K = 0x1 << 4; -constexpr uint16_t SAMPLE_RATE_32K = 0x1 << 5; -constexpr uint16_t SAMPLE_RATE_441K = 0x1 << 6; -constexpr uint16_t SAMPLE_RATE_48K = 0x1 << 7; -constexpr uint16_t SAMPLE_RATE_882K = 0x1 << 8; -constexpr uint16_t SAMPLE_RATE_96K = 0x1 << 9; -constexpr uint16_t SAMPLE_RATE_176K = 0x1 << 10; -constexpr uint16_t SAMPLE_RATE_192K = 0x1 << 11; -//constexpr uint16_t SAMPLE_RATE_384K = 0x1 << 12; - -constexpr uint8_t CODEC_ID_LC3 = 0x06; -constexpr uint8_t DISCOVER_SUCCESS = 0x00; -constexpr uint8_t DISCOVER_FAIL = 0xFF; - -std::map freq_map = { - {SAMPLE_RATE_8K, CodecSampleRate::CODEC_SAMPLE_RATE_8000 }, - {SAMPLE_RATE_16K, CodecSampleRate::CODEC_SAMPLE_RATE_16000 }, - {SAMPLE_RATE_24K, CodecSampleRate::CODEC_SAMPLE_RATE_24000 }, - {SAMPLE_RATE_32K, CodecSampleRate::CODEC_SAMPLE_RATE_32000 }, - {SAMPLE_RATE_441K, CodecSampleRate::CODEC_SAMPLE_RATE_44100 }, - {SAMPLE_RATE_48K, CodecSampleRate::CODEC_SAMPLE_RATE_48000 }, - {SAMPLE_RATE_882K, CodecSampleRate::CODEC_SAMPLE_RATE_88200 }, - {SAMPLE_RATE_96K, CodecSampleRate::CODEC_SAMPLE_RATE_96000 }, - {SAMPLE_RATE_176K, CodecSampleRate::CODEC_SAMPLE_RATE_176400}, - {SAMPLE_RATE_192K, CodecSampleRate::CODEC_SAMPLE_RATE_192000} -}; - -// ltv type to length -std::map ltv_info = { - {LTV_TYPE_SUP_FREQS, 0x03}, - {LTV_TYPE_SUP_FRAME_DUR, 0x02}, - {LTV_TYPE_CHNL_COUNTS, 0x02}, - {LTV_TYPE_OCTS_PER_FRAME, 0x05}, - {LTV_TYPE_MAX_SUP_FRAMES_PER_SDU, 0x02}, - {LTV_TYPE_PREF_AUD_CONTEXT, 0x03} -}; - -enum class ProfleOP { - CONNECT, - DISCONNECT -}; - -struct ProfileOperation { - uint16_t client_id; - ProfleOP type; -}; - -enum class DevState { - IDLE = 0, - CONNECTING, - CONNECTED, - DISCONNECTING -}; - -struct SinkPacsData { - uint16_t sink_pac_handle; - uint16_t sink_pac_ccc_handle; - std::vector sink_pac_records; - bool read_sink_pac_record; -}; - -struct SrcPacsData { - uint16_t src_pac_handle; - uint16_t src_pac_ccc_handle; - std::vector src_pac_records; - bool read_src_pac_record; -}; - -void pacs_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data); -void encryption_callback(const RawAddress*, tGATT_TRANSPORT, void*, - tBTM_STATUS); - -struct PacsDevice { - RawAddress address; - /* This is true only during first connection to profile, until we store the - * device */ - bool first_connection; - bool service_changed_rcvd; - - /* we are making active attempt to connect to this device, 'direct connect'. - * This is true only during initial phase of first connection. */ - bool connecting_actively; - - uint16_t conn_id; - std::vectorsink_info; - std::vectorsrc_info; - uint16_t sink_loc_handle; - uint16_t sink_loc_ccc_handle; - uint16_t src_loc_handle; - uint16_t src_loc_ccc_handle; - uint16_t avail_contexts_handle; - uint16_t avail_contexts_ccc_handle; - uint16_t supp_contexts_handle; - uint16_t supp_contexts_ccc_handle; - uint16_t srv_changed_ccc_handle; - uint8_t chars_read; - uint8_t chars_to_be_read; - std::vector consolidated_sink_pac_records; - std::vector consolidated_src_pac_records; - uint32_t sink_locations; - uint32_t src_locations; - uint32_t available_contexts; - uint32_t supported_contexts; - bool discovery_completed; - bool notifications_enabled; - DevState state; - bool is_congested; - std::vector profile_queue; - std::vector connected_client_list; //list client requested for connection - PacsDevice(const RawAddress& address) : address(address) {} - PacsDevice() { - first_connection = false; - service_changed_rcvd = false; - conn_id = 0; - sink_loc_handle = 0; - sink_loc_ccc_handle = 0; - src_loc_handle = 0; - src_loc_ccc_handle = 0; - avail_contexts_handle = 0; - avail_contexts_ccc_handle = 0; - supp_contexts_handle = 0; - supp_contexts_ccc_handle = 0; - srv_changed_ccc_handle = 0; - chars_read = 0; - sink_locations = 0; - src_locations = 0; - available_contexts = 0; - supported_contexts = 0; - discovery_completed = false; - notifications_enabled = false; - state = static_cast(0); - is_congested = false; - } -}; - -class PacsDevices { - public: - void Add(PacsDevice device) { - if (FindByAddress(device.address) != nullptr) return; - - devices.push_back(device); - } - - void Remove(const RawAddress& address) { - for (auto it = devices.begin(); it != devices.end();) { - if (it->address != address) { - ++it; - continue; - } - - it = devices.erase(it); - return; - } - } - - PacsDevice* FindByAddress(const RawAddress& address) { - auto iter = std::find_if(devices.begin(), devices.end(), - [&address](const PacsDevice& device) { - return device.address == address; - }); - - return (iter == devices.end()) ? nullptr : &(*iter); - } - - PacsDevice* FindByConnId(uint16_t conn_id) { - auto iter = std::find_if(devices.begin(), devices.end(), - [&conn_id](const PacsDevice& device) { - return device.conn_id == conn_id; - }); - - return (iter == devices.end()) ? nullptr : &(*iter); - } - - size_t size() { return (devices.size()); } - - std::vector devices; -}; - -class PacsClientImpl : public PacsClient { - public: - ~PacsClientImpl() override = default; - - PacsClientImpl() : gatt_client_id(BTA_GATTS_INVALID_IF) {}; - - bool Register(PacsClientCallbacks *callback) { - // looks for client is already registered - bool is_client_registered = false; - for (auto it : callbacks) { - PacsClientCallbacks *pac_callback = it.second; - if (callback == pac_callback) { - is_client_registered = true; - break; - } - } - - LOG(WARNING) << __func__ << " is_client_registered: " - << is_client_registered - << ", gatt_client_id: " << gatt_client_id; - if (is_client_registered) return false; - - if (gatt_client_id == BTA_GATTS_INVALID_IF) { - BTA_GATTC_AppRegister( - pacs_gattc_callback, - base::Bind( - [](PacsClientCallbacks *callback, uint8_t client_id, uint8_t status) { - if (status != GATT_SUCCESS) { - LOG(ERROR) << "Can't start PACS profile - no gatt " - "clients left!"; - return; - } - - if (instance) { - LOG(WARNING) << " PACS gatt_client_id: " - << instance->gatt_client_id; - instance->gatt_client_id = client_id; - instance->callbacks.insert(std::make_pair( - ++instance->pacs_client_id, callback)); - callback->OnInitialized(0, instance->pacs_client_id); - } - }, - callback), true); - } else { - instance->callbacks.insert(std::make_pair( - ++instance->pacs_client_id, callback)); - callback->OnInitialized(0, instance->pacs_client_id); - } - return true; - } - - bool Deregister (uint16_t client_id) { - bool status = false; - auto it = callbacks.find(client_id); - if (it != callbacks.end()) { - callbacks.erase(it); - if(callbacks.empty()) { - // deregister with GATT - LOG(WARNING) << __func__ << " Gatt de-register from pacs"; - BTA_GATTC_AppDeregister(gatt_client_id); - gatt_client_id = BTA_GATTS_INVALID_IF; - } - status = true; - } - return status; - } - - uint8_t GetClientCount () { - return callbacks.size(); - } - - void Connect(uint16_t client_id, const RawAddress& address, - bool is_direct) override { - LOG(WARNING) << __func__ << " address: " << address; - PacsDevice *dev = pacsDevices.FindByAddress(address); - ProfileOperation op; - op.client_id = client_id; - op.type = ProfleOP::CONNECT; - - if (dev == nullptr) { - PacsDevice pac_dev(address); - pacsDevices.Add(pac_dev); - dev = pacsDevices.FindByAddress(address); - } - if (dev == nullptr) { - LOG(ERROR) << __func__ << "dev is null"; - return; - } - - LOG(WARNING) << __func__ << ": state: " << static_cast(dev->state); - - switch(dev->state) { - case DevState::IDLE: { - BTA_GATTC_Open(gatt_client_id, address, is_direct, - GATT_TRANSPORT_LE, false); - dev->state = DevState::CONNECTING; - dev->profile_queue.push_back(op); - } break; - case DevState::CONNECTING: { - dev->profile_queue.push_back(op); - } break; - case DevState::CONNECTED: { - // add it to the client id list if not already done - auto iter = std::find_if(dev->connected_client_list.begin(), - dev->connected_client_list.end(), - [&client_id](uint16_t id) { - return id == client_id; - }); - - if (iter == dev->connected_client_list.end()) - dev->connected_client_list.push_back(client_id); - - // respond immediately as connected - - } break; - case DevState::DISCONNECTING: { - dev->profile_queue.push_back(op); - } break; - } - } - - void Disconnect(uint16_t client_id, const RawAddress& address) override { - PacsDevice* dev = pacsDevices.FindByAddress(address); - if (!dev) { - LOG(INFO) << __func__ <<": Device not connected to profile: " << address; - return; - } - - ProfileOperation op; - op.client_id = client_id; - op.type = ProfleOP::DISCONNECT; - - LOG(WARNING) << __func__ << ": address: " << address - << ", state: " << static_cast(dev->state); - - switch(dev->state) { - case DevState::CONNECTING: { - auto iter = std::find_if(dev->profile_queue.begin(), - dev->profile_queue.end(), - [&client_id]( ProfileOperation entry) { - return ((entry.type == ProfleOP::CONNECT) && - (entry.client_id == client_id)); - }); - // If it is the last client requested for disconnect - if (iter != dev->profile_queue.end() && - dev->profile_queue.size() == 1) { - if (dev->conn_id) { - // Removes all registrations for connection. - BTA_GATTC_CancelOpen(dev->conn_id, address, false); - GattOpsQueue::Clean(dev->conn_id); - BTA_GATTC_Close(dev->conn_id); - } else { - // clear the connection queue and - // move the state to DISCONNECTING to better track - dev->profile_queue.clear(); - } - dev->state = DevState::DISCONNECTING; - dev->profile_queue.push_back(op); - } else { - // remove the connection entry from the list - // as the same client has requested for disconnection - dev->profile_queue.erase(iter); - } - } break; - case DevState::CONNECTED: { - auto iter = std::find_if(dev->connected_client_list.begin(), - dev->connected_client_list.end(), - [&client_id]( uint16_t stored_client_id) { - return stored_client_id == client_id; - }); - // if it is the last client requested for disconnection - if (iter != dev->connected_client_list.end() && - dev->connected_client_list.size() == 1) { - if (dev->conn_id) { - // Removes all registrations for connection. - BTA_GATTC_CancelOpen(dev->conn_id, address, false); - GattOpsQueue::Clean(dev->conn_id); - BTA_GATTC_Close(dev->conn_id); - dev->profile_queue.push_back(op); - dev->state = DevState::DISCONNECTING; - } - } else { - // remove the client from connected_client_list - dev->connected_client_list.erase(iter); - // remove the pending gatt ops( not the ongoing one ) - // initiated from client which requested disconnect - // TODO and send callback as disconnected - } - } break; - case DevState::DISCONNECTING: { - dev->profile_queue.push_back(op); - } break; - default: - break; - } - } - - void StartDiscovery(uint16_t client_id, const RawAddress& address) override { - PacsDevice* dev = pacsDevices.FindByAddress(address); - if (!dev) { - LOG(INFO) << __func__ << ": Device not connected to profile: " << address; - return; - } - LOG(WARNING) << __func__ << " address: " << address - << ", state: " << static_cast(dev->state); - switch(dev->state) { - case DevState::CONNECTED: { - auto iter = std::find_if(dev->connected_client_list.begin(), - dev->connected_client_list.end(), - [&client_id]( uint16_t stored_client_id) { - LOG(WARNING) << __func__ - << ": client_id: " << client_id - << ", stored_client_id:" << stored_client_id; - return stored_client_id == client_id; - }); - // check if the client present in the connected client list - if (iter == dev->connected_client_list.end()) { - break; - } - - LOG(WARNING) << __func__ - << ", discovery_completed: " << dev->discovery_completed - << ", notifications_enabled: " << dev->notifications_enabled; - - // check if the discovery is already finished - // send back the same results to the other client - if (dev->discovery_completed && dev->notifications_enabled) { - auto iter = callbacks.find(client_id); - if (iter != callbacks.end()) { - LOG(WARNING) << __func__ << ": OnSearchComplete"; - PacsClientCallbacks *callback = iter->second; - callback->OnSearchComplete(DISCOVER_SUCCESS, - dev->address, - dev->consolidated_sink_pac_records, - dev->consolidated_src_pac_records, - dev->sink_locations, - dev->src_locations, - dev->available_contexts, - dev->supported_contexts); - } - break; - } - - // reset it - dev->chars_read = 0x00; - dev->chars_to_be_read = 0x00; - dev->sink_info.clear(); - dev->src_info.clear(); - dev->consolidated_sink_pac_records.clear(); - dev->consolidated_src_pac_records.clear(); - //TODO - //btif_bap_remove_record() - - // queue the request to GATT queue module - GattOpsQueue::ServiceSearch(client_id, dev->conn_id, &PACS_UUID); - } break; - - default: - break; - } - } - - void GetAudioAvailability(uint16_t client_id, const RawAddress& address) { - PacsDevice* dev = pacsDevices.FindByAddress(address); - if (!dev) { - LOG(INFO) << __func__ << ": Device not connected to profile: " << address; - return; - } - LOG(WARNING) << __func__ << ": address: " << address - << ", state: " << static_cast(dev->state); - - switch(dev->state) { - case DevState::CONNECTED: { - auto iter = std::find_if(dev->connected_client_list.begin(), - dev->connected_client_list.end(), - [&client_id]( uint16_t stored_client_id) { - return stored_client_id == client_id; - }); - // check if the client present in the connected client list - if (iter == dev->connected_client_list.end()) { - break; - } - - // check if the discovery is already finished - // send back the same results to the other client - if (dev->discovery_completed && dev->notifications_enabled) { - auto iter = callbacks.find(client_id); - if (iter != callbacks.end()) { - PacsClientCallbacks *callback = iter->second; - callback->OnAudioContextAvailable(dev->address, - dev->available_contexts); - } - break; - } - - // queue the request to GATT queue module - GattOpsQueue::ReadCharacteristic( - client_id, dev->conn_id, dev->avail_contexts_handle, - PacsClientImpl::OnReadAvailableAudioStatic, nullptr); - } break; - default: - LOG(WARNING) << __func__ << " default"; - break; - } - } - - void OnGattConnected(tGATT_STATUS status, uint16_t conn_id, - tGATT_IF client_if, RawAddress address, - tBTA_TRANSPORT transport, uint16_t mtu) { - - PacsDevice* dev = pacsDevices.FindByAddress(address); - if (!dev) { - /* When device is quickly disabled and enabled in settings, this case - * might happen */ - LOG(WARNING) << __func__ - <<"Closing connection to non pacs device, address: " - << address; - BTA_GATTC_Close(conn_id); - return; - } - - LOG(WARNING) << __func__ << " address: " << address - << ", state: " << static_cast(dev->state) - << ", status: " << loghex(status); - - if (dev->state == DevState::CONNECTING) { - if (status != GATT_SUCCESS) { - LOG(ERROR) << __func__ << ": Failed to connect to PACS device"; - for (auto it = dev->profile_queue.begin(); - it != dev->profile_queue.end();) { - if(it->type == ProfleOP::CONNECT) { - // get the callback and update the upper layers - auto iter = callbacks.find(it->client_id); - if (iter != callbacks.end()) { - PacsClientCallbacks *callback = iter->second; - callback->OnConnectionState(address, - ConnectionState::DISCONNECTED); - } - dev->profile_queue.erase(it); - } else { - it++; - } - } - dev->state = DevState::IDLE; - pacsDevices.Remove(address); - return; - } - } else if (dev->state == DevState::DISCONNECTING) { - // TODO will this happens ? - // it could have called the cancel open to expect the - // open cancelled event - if (status != GATT_SUCCESS) { - LOG(ERROR) << "Failed to connect to PACS device"; - for (auto it = dev->profile_queue.begin(); - it != dev->profile_queue.end();) { - if(it->type == ProfleOP::DISCONNECT) { - // get the callback and update the upper layers - auto iter = callbacks.find(it->client_id); - if (iter != callbacks.end()) { - PacsClientCallbacks *callback = iter->second; - callback->OnConnectionState(address, - ConnectionState::DISCONNECTED); - } - dev->profile_queue.erase(it); - } else { - it++; - } - } - dev->state = DevState::IDLE; - pacsDevices.Remove(address); - return; - } else { - // gatt connected successfully - // if the disconnect entry is found we need to initiate the - // gatt disconnect. may be a race condition just after sending - // cancel open gatt connected event received - for (auto it = dev->profile_queue.begin(); - it != dev->profile_queue.end();) { - if(it->type == ProfleOP::DISCONNECT) { - // get the callback and update the upper layers - auto iter = callbacks.find(it->client_id); - if (iter != callbacks.end()) { - // Removes all registrations for connection. - BTA_GATTC_CancelOpen(dev->conn_id, address, false); - GattOpsQueue::Clean(dev->conn_id); - BTA_GATTC_Close(dev->conn_id); - break; - } - } else { - it++; - } - } - return; - } - } else { - // return unconditinally - return; - } - - // success scenario code - dev->conn_id = conn_id; - - tACL_CONN* p_acl = btm_bda_to_acl(address, BT_TRANSPORT_LE); - if (p_acl != nullptr && - controller_get_interface()->supports_ble_2m_phy() && - HCI_LE_2M_PHY_SUPPORTED(p_acl->peer_le_features)) { - LOG(INFO) << address << " set preferred PHY to 2M"; - BTM_BleSetPhy(address, PHY_LE_2M, PHY_LE_2M, 0); - } - - /* verify bond */ - uint8_t sec_flag = 0; - BTM_GetSecurityFlagsByTransport(address, &sec_flag, BT_TRANSPORT_LE); - - if (sec_flag & BTM_SEC_FLAG_ENCRYPTED) { - /* if link has been encrypted */ - OnEncryptionComplete(address, true); - return; - } - - if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) { - /* if bonded and link not encrypted */ - sec_flag = BTM_BLE_SEC_ENCRYPT; - LOG(WARNING) << "trying to encrypt now"; - BTM_SetEncryption(address, BTA_TRANSPORT_LE, encryption_callback, - nullptr, sec_flag); - return; - } - - /* otherwise let it go through */ - OnEncryptionComplete(address, true); - } - - void OnGattDisconnected(tGATT_STATUS status, uint16_t conn_id, - tGATT_IF client_if, RawAddress remote_bda, - tBTA_GATT_REASON reason) { - PacsDevice* dev = pacsDevices.FindByConnId(conn_id); - if (!dev) { - LOG(ERROR) << __func__ - << ": Skipping unknown device disconnect, conn_id=" - << loghex(conn_id); - return; - } - - LOG(WARNING) << __func__ << " remote_bda: " << remote_bda - << ", state: " << static_cast(dev->state); - - switch(dev->state) { - case DevState::CONNECTING: { - // sudden disconnection - for (auto it = dev->profile_queue.begin(); - it != dev->profile_queue.end();) { - if (it->type == ProfleOP::CONNECT) { - // get the callback and update the upper layers - auto iter = callbacks.find(it->client_id); - if (iter != callbacks.end()) { - PacsClientCallbacks *callback = iter->second; - callback->OnConnectionState(remote_bda, - ConnectionState::DISCONNECTED); - } - it = dev->profile_queue.erase(it); - } else { - it++; - } - } - } break; - case DevState::CONNECTED: { - // sudden disconnection - for (auto it = dev->connected_client_list.begin(); - it != dev->connected_client_list.end();) { - // get the callback and update the upper layers - auto iter = callbacks.find(*it); - if (iter != callbacks.end()) { - PacsClientCallbacks *callback = iter->second; - callback->OnConnectionState(remote_bda, - ConnectionState::DISCONNECTED); - } - it = dev->connected_client_list.erase(it); - } - } break; - case DevState::DISCONNECTING: { - for (auto it = dev->profile_queue.begin(); - it != dev->profile_queue.end();) { - if (it->type == ProfleOP::DISCONNECT) { - // get the callback and update the upper layers - auto iter = callbacks.find(it->client_id); - if (iter != callbacks.end()) { - PacsClientCallbacks *callback = iter->second; - callback->OnConnectionState(remote_bda, - ConnectionState::DISCONNECTED); - } - it = dev->profile_queue.erase(it); - } else { - it++; - } - } - - for (auto it = dev->connected_client_list.begin(); - it != dev->connected_client_list.end();) { - // get the callback and update the upper layers - it = dev->connected_client_list.erase(it); - } - // check if the connection queue is not empty - // if not initiate the Gatt connection - } break; - default: - break; - } - - if (dev->conn_id) { - GattOpsQueue::Clean(dev->conn_id); - BTA_GATTC_Close(dev->conn_id); - dev->conn_id = 0; - } - - dev->state = DevState::IDLE; - pacsDevices.Remove(remote_bda); - } - - void OnConnectionUpdateComplete(uint16_t conn_id, tBTA_GATTC* p_data) { - PacsDevice* dev = pacsDevices.FindByConnId(conn_id); - if (!dev) { - LOG(ERROR) << __func__ - << ": Skipping unknown device, conn_id=" - << loghex(conn_id); - return; - } - } - - void OnEncryptionComplete(const RawAddress& address, bool success) { - PacsDevice* dev = pacsDevices.FindByAddress(address); - if (!dev) { - LOG(ERROR) << __func__ << ": Skipping unknown device" << address; - return; - } - - if(dev->state != DevState::CONNECTING) { - LOG(ERROR) << __func__ << ": received in wrong state" << address; - return; - } - - LOG(WARNING) << __func__ << ": address=" << address << loghex(success); - // encryption failed - if (!success) { - for (auto it = dev->profile_queue.begin(); - it != dev->profile_queue.end();) { - if (it->type == ProfleOP::CONNECT) { - // get the callback and update the upper layers - auto iter = callbacks.find(it->client_id); - if (iter != callbacks.end()) { - PacsClientCallbacks *callback = iter->second; - callback->OnConnectionState(address, - ConnectionState::DISCONNECTED); - } - // change the type to disconnect - it->type = ProfleOP::DISCONNECT; - } else { - it++; - } - } - dev->state = DevState::DISCONNECTING; - // Removes all registrations for connection. - BTA_GATTC_CancelOpen(dev->conn_id, address, false); - BTA_GATTC_Close(dev->conn_id); - } else { - for (auto it = dev->profile_queue.begin(); - it != dev->profile_queue.end();) { - if (it->type == ProfleOP::CONNECT) { - // get the callback and update the upper layers - auto iter = callbacks.find(it->client_id); - if (iter != callbacks.end()) { - dev->connected_client_list.push_back(it->client_id); - PacsClientCallbacks *callback = iter->second; - LOG(WARNING) << __func__ << " calling OnConnectionState"; - callback->OnConnectionState(address, ConnectionState::CONNECTED); - } - dev->profile_queue.erase(it); - } else { - it++; - } - } - dev->state = DevState::CONNECTED; - } - } - - void OnServiceChangeEvent(const RawAddress& address) { - PacsDevice* dev = pacsDevices.FindByAddress(address); - if (!dev) { - LOG(ERROR) << __func__ << ": Skipping unknown device: " << address; - return; - } - LOG(INFO) << __func__ << ": address: " << address; - dev->first_connection = true; - dev->service_changed_rcvd = true; - GattOpsQueue::Clean(dev->conn_id); - } - - void OnServiceDiscDoneEvent(const RawAddress& address) { - PacsDevice* dev = pacsDevices.FindByAddress(address); - if (!dev) { - LOG(ERROR) << __func__ << ": Skipping unknown device: " << address; - return; - } - - LOG(WARNING) << __func__ << " service_changed_rcvd: " - << dev->service_changed_rcvd; - if (dev->service_changed_rcvd) { - // queue the request to GATT queue module with dummu client id - GattOpsQueue::ServiceSearch(0XFF, dev->conn_id, &PACS_UUID); - } - } - - void RegisterForNotification(uint16_t client_id, uint16_t conn_id, - PacsDevice* dev, uint16_t ccc_handle, - uint16_t handle) { - if(handle && ccc_handle) { - /* Register and enable Notification */ - tGATT_STATUS register_status; - register_status = BTA_GATTC_RegisterForNotifications( - conn_id, dev->address, handle); - if (register_status != GATT_SUCCESS) { - LOG(ERROR) << __func__ - << ": BTA_GATTC_RegisterForNotifications failed, status=" - << loghex(register_status); - } - std::vector value(2); - uint8_t* ptr = value.data(); - UINT16_TO_STREAM(ptr, GATT_CHAR_CLIENT_CONFIG_NOTIFICATION); - GattOpsQueue::WriteDescriptor( - client_id, conn_id, ccc_handle, - std::move(value), GATT_WRITE, nullptr, nullptr); - } - } - - void OnServiceSearchComplete(uint16_t conn_id, tGATT_STATUS status) { - PacsDevice* dev = pacsDevices.FindByConnId(conn_id); - if (!dev) { - LOG(ERROR) << __func__ << ": Skipping unknown device, conn_id = " - << loghex(conn_id); - return; - } - - LOG(WARNING) << __func__ << ": conn_id = " << loghex(conn_id); - - uint16_t client_id = GattOpsQueue::ServiceSearchComplete(conn_id, - status); - LOG(WARNING) << __func__ << ": client_id = " << loghex(client_id); - auto iter = callbacks.find(client_id); - if (status != GATT_SUCCESS) { - /* close connection and report service discovery complete with error */ - LOG(ERROR) << __func__ << ": Service discovery failed"; - if (iter != callbacks.end()) { - PacsClientCallbacks *callback = iter->second; - callback->OnSearchComplete(DISCOVER_FAIL, - dev->address, - dev->consolidated_sink_pac_records, - dev->consolidated_src_pac_records, - dev->sink_locations, - dev->src_locations, - dev->available_contexts, - dev->supported_contexts); - } - return; - } - - const std::vector* services = BTA_GATTC_GetServices(conn_id); - - const gatt::Service* service = nullptr; - if (services) { - for (const gatt::Service& tmp : *services) { - if (tmp.uuid == Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER)) { - LOG(INFO) << __func__ << ": Found UUID_CLASS_GATT_SERVER, handle=" - << loghex(tmp.handle); - const gatt::Service* service_changed_service = &tmp; - find_server_changed_ccc_handle(conn_id, service_changed_service); - } else if (tmp.uuid == PACS_UUID) { - LOG(INFO) << __func__ << ": Found PACS service, handle=" - << loghex(tmp.handle); - service = &tmp; - } - } - } else { - LOG(ERROR) << __func__ - << ": no services found for conn_id: " << loghex(conn_id); - return; - } - - if (!service) { - LOG(ERROR) << __func__ << ": No PACS service found"; - if (iter != callbacks.end()) { - PacsClientCallbacks *callback = iter->second; - callback->OnSearchComplete(DISCOVER_FAIL, - dev->address, - dev->consolidated_sink_pac_records, - dev->consolidated_src_pac_records, - dev->sink_locations, - dev->src_locations, - dev->available_contexts, - dev->supported_contexts); - } - return; - } - - for (const gatt::Characteristic& charac : service->characteristics) { - LOG(INFO) << __func__ << ": uuid: " << charac.uuid; - if (charac.uuid == PACS_SINK_PAC_UUID) { - LOG(INFO) << __func__ << ": sink pac uuid found. "; - - SinkPacsData info; - memset(&info, 0, sizeof(info)); - info.sink_pac_handle = charac.value_handle; - info.sink_pac_ccc_handle = find_ccc_handle(conn_id, charac.value_handle); - dev->sink_info.push_back(info); - dev->chars_to_be_read |= SINK_PAC; - GattOpsQueue::ReadCharacteristic( - client_id, conn_id, charac.value_handle, - PacsClientImpl::OnReadOnlyPropertiesReadStatic, nullptr); - - if (info.sink_pac_ccc_handle) { - RegisterForNotification(client_id, conn_id, dev, - info.sink_pac_ccc_handle, - info.sink_pac_handle); - } - - } else if (charac.uuid == PACS_SINK_LOC_UUID) { - LOG(INFO) << __func__ << ": sink loc uuid found. "; - dev->sink_loc_handle = charac.value_handle; - - GattOpsQueue::ReadCharacteristic( - client_id,conn_id, charac.value_handle, - PacsClientImpl::OnReadOnlyPropertiesReadStatic, nullptr); - - dev->sink_loc_ccc_handle = - find_ccc_handle(conn_id, charac.value_handle); - - dev->chars_to_be_read |= SINK_LOC; - if (dev->sink_loc_ccc_handle) { - RegisterForNotification(client_id, conn_id, dev, - dev->sink_loc_ccc_handle, - dev->sink_loc_handle); - } - - } else if (charac.uuid == PACS_SRC_PAC_UUID) { - LOG(INFO) << __func__ << ": src pac uuid found. "; - - SrcPacsData info; - memset(&info, 0, sizeof(info)); - info.src_pac_handle = charac.value_handle; - info.src_pac_ccc_handle = find_ccc_handle(conn_id, charac.value_handle); - dev->src_info.push_back(info); - dev->chars_to_be_read |= SRC_PAC; - GattOpsQueue::ReadCharacteristic( - client_id, conn_id, charac.value_handle, - PacsClientImpl::OnReadOnlyPropertiesReadStatic, nullptr); - - if (info.src_pac_ccc_handle) { - RegisterForNotification(client_id, conn_id, dev, - info.src_pac_ccc_handle, - info.src_pac_handle); - } - - } else if (charac.uuid == PACS_SRC_LOC_UUID) { - LOG(INFO) << __func__ << ": src loc uuid found. "; - dev->src_loc_handle = charac.value_handle; - - GattOpsQueue::ReadCharacteristic( - client_id, conn_id, charac.value_handle, - PacsClientImpl::OnReadOnlyPropertiesReadStatic, nullptr); - - dev->src_loc_ccc_handle = - find_ccc_handle(conn_id, charac.value_handle); - dev->chars_to_be_read |= SRC_LOC; - if (dev->src_loc_ccc_handle) { - RegisterForNotification(client_id, conn_id, dev, - dev->src_loc_ccc_handle, - dev->src_loc_handle); - } - - } else if (charac.uuid == PACS_AVA_AUDIO_UUID) { - LOG(INFO) << __func__ << ": avaliable audio uuid found. "; - dev->avail_contexts_handle = charac.value_handle; - - GattOpsQueue::ReadCharacteristic( - client_id, conn_id, charac.value_handle, - PacsClientImpl::OnReadOnlyPropertiesReadStatic, nullptr); - - dev->avail_contexts_ccc_handle = - find_ccc_handle(conn_id, charac.value_handle); - dev->chars_to_be_read |= AVAIL_CONTEXTS; - if (dev->avail_contexts_ccc_handle) { - RegisterForNotification(client_id, conn_id, dev, - dev->avail_contexts_ccc_handle, - dev->avail_contexts_handle); - } - - } else if (charac.uuid == PACS_SUP_AUDIO_UUID) { - LOG(INFO) << __func__ << ": supported audio uuid found. "; - dev->supp_contexts_handle = charac.value_handle; - - GattOpsQueue::ReadCharacteristic( - client_id, conn_id, charac.value_handle, - PacsClientImpl::OnReadOnlyPropertiesReadStatic, nullptr); - - dev->supp_contexts_ccc_handle = - find_ccc_handle(conn_id, charac.value_handle); - dev->chars_to_be_read |= SUPP_CONTEXTS; - if (dev->supp_contexts_ccc_handle) { - RegisterForNotification(client_id, conn_id, dev, - dev->supp_contexts_ccc_handle, - dev->supp_contexts_handle); - } - } else { - LOG(WARNING) << "Unknown characteristic found:" << charac.uuid; - } - } - - dev->notifications_enabled = true; - - LOG(INFO) << __func__ - << ": service_changed_rcvd: " << dev->service_changed_rcvd; - if (dev->service_changed_rcvd) { - dev->service_changed_rcvd = false; - } - } - - void OnNotificationEvent(uint16_t conn_id, uint16_t handle, uint16_t len, - uint8_t* value) { - - PacsDevice* dev = pacsDevices.FindByConnId(conn_id); - if (!dev) { - LOG(INFO) << __func__ - << ": Skipping unknown device, conn_id=" << loghex(conn_id); - return; - } - - LOG(WARNING) << __func__ << ": conn_id: " << loghex(conn_id); - - if(dev->avail_contexts_handle == handle) { - uint8_t* p = value; - STREAM_TO_UINT32(dev->available_contexts, p); - } - } - - void OnCongestionEvent(uint16_t conn_id, bool congested) { - PacsDevice* dev = pacsDevices.FindByConnId(conn_id); - if (!dev) { - LOG(INFO) << __func__ - << ": Skipping unknown device, conn_id=" << loghex(conn_id); - return; - } - - LOG(WARNING) << __func__ << ": conn_id=" << loghex(conn_id) - << ", congested: " << congested; - dev->is_congested = congested; - GattOpsQueue::CongestionCallback(conn_id, congested); - } - - void OnReadAvailableAudio(uint16_t client_id, - uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, uint16_t len, uint8_t* value, - void* data) { - PacsDevice* dev = pacsDevices.FindByConnId(conn_id); - if (!dev) { - LOG(ERROR) << __func__ << ": unknown conn_id: " << loghex(conn_id); - return; - } - - LOG(WARNING) << __func__ << ": conn_id: " << loghex(conn_id); - - if(dev->avail_contexts_handle == handle) { - uint8_t* p = value; - STREAM_TO_UINT32(dev->available_contexts, p); - // check if all pacs characteristics are read - // send out the callback as service discovery completed - // get the callback and update the upper layers - auto iter = callbacks.find(client_id); - if (iter != callbacks.end()) { - PacsClientCallbacks *callback = iter->second; - callback->OnAudioContextAvailable(dev->address, - dev->available_contexts); - } - } - } - - bool IsRecordReadable(uint16_t total_len, uint16_t processed_len, - uint16_t req_len) { - LOG(WARNING) << __func__ << ": processed_len: " << loghex(processed_len) - << ", req_len: " << loghex(req_len); - if((total_len > processed_len) && - ((total_len - processed_len) >= req_len)) { - return true; - } else { - return false; - } - } - - bool IsLtvValid(uint8_t ltv_type, uint16_t ltv_len) { - bool valid = true; - for (auto it : ltv_info) { - if(ltv_type == it.first && - ltv_len != it.second) { - valid = false; - break; - } - } - return valid; - } - - void ParsePacRecord (PacsDevice *dev, uint16_t handle, uint16_t total_len, - uint8_t *value, void* data) { - std::vector pac_records; - CodecIndex codec_type; - uint8_t *p = value; - codec_type_t codec_id; - bool stop_reading = false; - uint8_t codec_cap_len; - std::vector codec_caps; - uint8_t meta_data_len; - std::vector meta_data; - uint16_t processed_len = 0; - uint8_t num_pac_recs; - uint16_t context_type; - - SinkPacsData* sinkinfo = FindSinkByHandle(dev, handle); - SrcPacsData* srcinfo = FindSrcByHandle(dev, handle); - - // Number_of_PAC_records is 1 byte - if (!total_len) { - LOG(ERROR) << __func__ - << ": zero len record, total_len: "; - return; - } - - STREAM_TO_UINT8(num_pac_recs, p); - processed_len ++; - - LOG(WARNING) << __func__ << ": num_pac_recs: " << loghex(num_pac_recs) - << ", total_len: " << loghex(total_len); - while (!stop_reading && num_pac_recs) { - // reset context type for before reading record - context_type = ucast::CONTENT_TYPE_UNSPECIFIED; - // read the complete record - // codec_id is of 5 bytes. - if (!IsRecordReadable(total_len, processed_len, sizeof(codec_id))) { - LOG(ERROR) << __func__ << ": Not valid codec id, Bad pacs record."; - break; - } - - STREAM_TO_ARRAY(&codec_id, p, static_cast (sizeof(codec_id))); - - processed_len += static_cast (sizeof(codec_id)); - - if (codec_id[0] == CODEC_ID_LC3) { - LOG(INFO) << __func__ << ": LC3 codec "; - codec_type = CodecIndex::CODEC_INDEX_SOURCE_LC3; - } else { - // TODO to check for vendor codecs - break; - } - - // codec_cap_len is of 1 byte - if (!IsRecordReadable(total_len, processed_len, 1)) { - LOG(ERROR) << __func__ << ": Not valid codec id, Bad pacs record."; - break; - } - - STREAM_TO_UINT8(codec_cap_len, p); - processed_len ++; - - LOG(WARNING) << __func__ - << ": codec_cap_len: " << loghex(codec_cap_len) - << ": processed_len: " << loghex(processed_len); - - if (!codec_cap_len) { - LOG(ERROR) << __func__ - << ": Invalid codec cap len"; - break; - } - - if (!IsRecordReadable(total_len, processed_len, codec_cap_len)) { - LOG(ERROR) << __func__ << ": not enough data, Bad pacs record."; - break; - } - - codec_caps.resize(codec_cap_len); - STREAM_TO_ARRAY(codec_caps.data(), p, codec_cap_len); - uint8_t len = codec_cap_len; - uint8_t *pp = codec_caps.data(); - - // Now look for supported freq LTV entry - while (len) { - LOG(WARNING) << __func__ << ": len: " << loghex(len); - - if (!IsRecordReadable(total_len, processed_len, 1)) { - LOG(ERROR) << __func__ << ": not enough data, Bad pacs record."; - break; - } - uint8_t ltv_len = *pp++; - len--; - processed_len++; - - LOG(WARNING) << __func__ << ": ltv_len: " << loghex(ltv_len); - if (!ltv_len || - !IsRecordReadable(total_len, processed_len, ltv_len)) { - LOG(ERROR) << __func__ << ": Not valid ltv length"; - stop_reading = true; - break; - } - - processed_len += ltv_len; - - // get type and value - uint8_t ltv_type = *pp++; - LOG(WARNING) << __func__ << ": ltv_type: " << loghex(ltv_type); - if(!IsLtvValid(ltv_type, ltv_len)) { - LOG(ERROR) << __func__ << ": No ltv type to length match"; - stop_reading = true; - break; - } - if(ltv_type == LTV_TYPE_SUP_FREQS) { - uint16_t supp_freqs; - STREAM_TO_UINT16(supp_freqs, pp); - LOG(WARNING) << __func__ << ": supp_freqs: " << supp_freqs; - - for (auto it : freq_map) { - if(supp_freqs & it.first) { - CodecConfig codec_config; - codec_config.codec_type = codec_type; - codec_config.sample_rate = it.second; - pac_records.push_back(codec_config); - } - } - } else { - uint8_t rem_len = ltv_len - 1; - LOG(WARNING) << __func__ << ": rem_len: " << loghex(rem_len); - while (rem_len--) { pp++; }; - } - - if (len >= ltv_len) { - len -= ltv_len; - } else { - LOG(ERROR) << __func__ << "wrong len"; - len = 0; - } - } - - LOG(WARNING) << __func__ << ": stop_reading: " << stop_reading; - if (stop_reading) break; - - // set the default chnl count to mono as it is optional - for (auto it = pac_records.begin(); it != pac_records.end(); ++it) { - it->channel_mode = CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - } - - // now check for other LTV values - len = codec_cap_len; - pp = codec_caps.data(); - while (len) { - LOG(WARNING) << __func__ - << ": checking other LTV values,len: " << loghex(len); - uint8_t ltv_len = *pp++; - len--; - LOG(WARNING) << __func__ << ": ltv_len: " << loghex(ltv_len); - - //get type and value - uint8_t ltv_type = *pp++; - LOG(WARNING) << __func__ << ": ltv_type: " << loghex(ltv_type); - if(ltv_type == LTV_TYPE_SUP_FRAME_DUR) { - uint8_t supp_frames; - STREAM_TO_UINT8(supp_frames, pp); - LOG(WARNING) << __func__ - << ": pac rec len: " << loghex(pac_records.size()); - for (auto it = pac_records.begin(); it != pac_records.end(); - ++it) { - UpdateCapaSupFrameDurations(&(*it), supp_frames); - } - } else if (ltv_type == LTV_TYPE_CHNL_COUNTS) { - uint8_t chnl_allocation; - STREAM_TO_UINT8(chnl_allocation, pp); - for (auto it = pac_records.begin(); it != pac_records.end(); ++it) { - it->channel_mode = - static_cast (chnl_allocation); - } - } else if (ltv_type == LTV_TYPE_OCTS_PER_FRAME) { - uint32_t octs_per_frame; - STREAM_TO_UINT32(octs_per_frame, pp); - for (auto it = pac_records.begin(); it != pac_records.end(); ++it) { - UpdateCapaSupOctsPerFrame(&(*it), octs_per_frame); - } - } else if (ltv_type == LTV_TYPE_MAX_SUP_FRAMES_PER_SDU) { - uint32_t max_sup_frames_per_sdu; - STREAM_TO_UINT32(max_sup_frames_per_sdu, pp); - for (auto it = pac_records.begin(); it != pac_records.end(); ++it) { - UpdateCapaMaxSupLc3Frames(&(*it), max_sup_frames_per_sdu); - } - } else { - uint8_t rem_len = ltv_len - 1; - LOG(WARNING) << __func__ << ": rem_len: " << loghex(rem_len); - while (rem_len--) { pp++;}; - } - - if(len >= ltv_len) { - len -= ltv_len; - } else { - LOG(ERROR) << __func__ << ": wrong len"; - len = 0; - } - } - - //Meta data length 1 byte - if (!IsRecordReadable(total_len, processed_len, 1)) { - LOG(ERROR) << __func__ << ": Not valid meta data len, Bad pacs record."; - break; - } - - STREAM_TO_UINT8(meta_data_len, p); - processed_len ++; - LOG(WARNING) << __func__ << ": meta_data_len: " << loghex(meta_data_len) - << ": processed_len: " << loghex(processed_len); - - if (meta_data_len) { - if (!IsRecordReadable(total_len, processed_len, meta_data_len)) { - LOG(ERROR) << __func__ << ": not enough data, Bad pacs record."; - break; - } - - meta_data.resize(meta_data_len); - STREAM_TO_ARRAY(meta_data.data(), p, meta_data_len); - uint8_t len = meta_data_len; - uint8_t *pp = meta_data.data(); - - while (len) { - LOG(WARNING) << __func__ << ": len: " << loghex(len); - uint8_t ltv_len = *pp++; - len--; - processed_len++; - - LOG(WARNING) << __func__ << ": ltv_len: " << loghex(ltv_len); - if (!ltv_len || - !IsRecordReadable(total_len, processed_len, ltv_len)) { - LOG(ERROR) << __func__ << ": Not valid ltv length"; - stop_reading = true; - break; - } - - processed_len += ltv_len; - - // get type and value - uint8_t ltv_type = *pp++; - - LOG(WARNING) << __func__ << ": ltv_type: " << loghex(ltv_type); - - if (!IsLtvValid(ltv_type, ltv_len)) { - LOG(ERROR) << __func__ << ": No ltv type to length match"; - stop_reading = true; - break; - } - - if (ltv_type == LTV_TYPE_PREF_AUD_CONTEXT) { - STREAM_TO_UINT16(context_type, pp); - LOG(WARNING) << __func__ - << ": ltv_context_type: " << loghex(context_type); - - for (auto it = pac_records.begin(); it != pac_records.end(); ++it) { - UpdateCapaPreferredContexts(&(*it), context_type); - } - } else if (ltv_type == LTV_TYPE_VS_META_DATA) { - uint16_t company_id; - STREAM_TO_UINT16(company_id, pp); - - //total vs meta data length(meta length -4) in bytes. - uint8_t total_vendor_ltv_len = meta_data_len - 4; - LOG(WARNING) << __func__ - << ": total_vendor_ltv_len: " << loghex(total_vendor_ltv_len); - - if (company_id == QTI_ID) { - while (total_vendor_ltv_len) { - uint8_t vs_meta_data_len = *pp++; - LOG(WARNING) << __func__ - << ": vs_meta_data_len: " << loghex(vs_meta_data_len); - - // get type and value - uint8_t vs_meta_data_type = *pp++; - LOG(WARNING) << __func__ - << ": vs_meta_data_type: " << loghex(vs_meta_data_type); - - if (vs_meta_data_type == LTV_TYPE_VS_META_DATA_LC3Q) { - uint8_t vs_meta_data_value[vs_meta_data_len - 1]; - STREAM_TO_ARRAY(&vs_meta_data_value, pp, - static_cast (sizeof(vs_meta_data_value))); - - for (auto it = pac_records.begin(); it != pac_records.end(); ++it) { - UpdateCapaVendorMetaDataLc3QPref(&(*it), true); - UpdateCapaVendorMetaDataLc3QVer(&(*it), vs_meta_data_value[0]); - } - } else { - //TODO check for other ltvs - uint8_t rem_len = vs_meta_data_len - 1; - LOG(WARNING) << __func__ << ": rem_len: " << loghex(rem_len); - while (rem_len--) { pp++;}; - } - - /* 5bytes (VS length bypte + Meta datatype + - company ID(2 bytes) + Lc3q length) */ - if(total_vendor_ltv_len >= (vs_meta_data_len + 5)) { - total_vendor_ltv_len -= (vs_meta_data_len + 5); - len = total_vendor_ltv_len; - } else { - LOG(ERROR) << __func__ << ": wrong len."; - total_vendor_ltv_len = 0; - } - } - } else { - //TODO check for other comany IDs - uint8_t rem_len = total_vendor_ltv_len - 1; - LOG(WARNING) << __func__ << ": rem_len: " << loghex(rem_len); - while (rem_len--) { pp++;}; - } - } else { - uint8_t rem_len = ltv_len - 1; - LOG(WARNING) << __func__ << ": rem_len: " << loghex(rem_len); - while (rem_len--) { pp++;}; - } - - if (len >= ltv_len) { - len -= ltv_len; - } else { - LOG(ERROR) << __func__ << ": wrong len"; - len = 0; - } - } - } - - if (sinkinfo != nullptr) { - // Now update all records to conf file - while (!pac_records.empty()) { - CodecConfig record = pac_records.back(); - sinkinfo->sink_pac_records.push_back(record); - pac_records.pop_back(); - btif_bap_add_record(dev->address, REC_TYPE_CAPABILITY, - context_type, CodecDirection::CODEC_DIR_SINK, - &record); - } - } else if (srcinfo != nullptr) { - // Now update all records to conf file - while (!pac_records.empty()) { - CodecConfig record = pac_records.back(); - srcinfo->src_pac_records.push_back(record); - pac_records.pop_back(); - btif_bap_add_record(dev->address, REC_TYPE_CAPABILITY, - context_type, CodecDirection::CODEC_DIR_SRC, - &record); - } - } - num_pac_recs--; - } - - if (sinkinfo != nullptr) { - sinkinfo->read_sink_pac_record = true; - bool all_sink_pacs_read = false; - for (auto it = dev->sink_info.begin(); - it != dev->sink_info.end(); it ++) { - if (it->read_sink_pac_record == true) { - all_sink_pacs_read = true; - continue; - } else { - all_sink_pacs_read = false; - break; - } - } - - LOG(WARNING) << __func__ - << ": all_sink_pacs_read: " << all_sink_pacs_read; - if (all_sink_pacs_read) - dev->chars_read |= SINK_PAC; - - } else if (srcinfo != nullptr) { - srcinfo->read_src_pac_record = true; - bool all_source_pacs_read = false; - for (auto it = dev->src_info.begin(); - it != dev->src_info.end(); it ++) { - if (it->read_src_pac_record == true) { - all_source_pacs_read = true; - continue; - } else { - all_source_pacs_read = false; - break; - } - } - - LOG(WARNING) << __func__ - << ": all_source_pacs_read: " << all_source_pacs_read; - if (all_source_pacs_read) - dev->chars_read |= SRC_PAC; - } - } - - void OnReadOnlyPropertiesRead(uint16_t client_id, uint16_t conn_id, - tGATT_STATUS status, uint16_t handle, - uint16_t len, uint8_t *value, void* data) { - PacsDevice* dev = pacsDevices.FindByConnId(conn_id); - if (!dev) { - LOG(ERROR) << __func__ << "unknown conn_id=" << loghex(conn_id); - return; - } - SinkPacsData* sinkinfo = FindSinkByHandle(dev, handle); - SrcPacsData* srcinfo = FindSrcByHandle(dev, handle); - - if (sinkinfo != nullptr || srcinfo != nullptr) { - ParsePacRecord(dev, handle, len, value, data); - - } else if (dev->sink_loc_handle == handle) { - uint8_t *p = value; - STREAM_TO_UINT32(dev->sink_locations, p); - dev->chars_read |= SINK_LOC; - btif_bap_add_audio_loc(dev->address, CodecDirection::CODEC_DIR_SINK, - dev->sink_locations); - LOG(WARNING) << __func__ << ": sink loc: " << loghex(dev->sink_locations); - - } else if(dev->src_loc_handle == handle) { - uint8_t *p = value; - STREAM_TO_UINT32(dev->src_locations, p); - dev->chars_read |= SRC_LOC; - btif_bap_add_audio_loc(dev->address, CodecDirection::CODEC_DIR_SRC, - dev->src_locations); - LOG(WARNING) << __func__ << ": src loc: " << loghex(dev->src_locations); - - } else if(dev->avail_contexts_handle == handle) { - uint8_t* p = value; - STREAM_TO_UINT32(dev->available_contexts, p); - dev->chars_read |= AVAIL_CONTEXTS; - - } else if(dev->supp_contexts_handle == handle) { - uint8_t* p = value; - STREAM_TO_UINT32(dev->supported_contexts, p); - dev->chars_read |= SUPP_CONTEXTS; - btif_bap_add_supp_contexts(dev->address, dev->supported_contexts); - } - - LOG(WARNING) << __func__ << ": chars_read: " << loghex(dev->chars_read); - - // check if all pacs characteristics are read - // send out the callback as service discovery completed - if (dev->chars_read == dev->chars_to_be_read) { - - UpdateConsolidatedsinkPacRecords(dev); - UpdateConsolidatedsrcPacRecords(dev); - - // get the callback and update the upper layers - auto iter = callbacks.find(client_id); - if (iter != callbacks.end()) { - dev->discovery_completed = true; - PacsClientCallbacks *callback = iter->second; - callback->OnSearchComplete(DISCOVER_SUCCESS, - dev->address, - dev->consolidated_sink_pac_records, - dev->consolidated_src_pac_records, - dev->sink_locations, - dev->src_locations, - dev->available_contexts, - dev->supported_contexts); - } - } - } - - static void OnReadOnlyPropertiesReadStatic(uint16_t client_id, - uint16_t conn_id, - tGATT_STATUS status, - uint16_t handle, uint16_t len, - uint8_t* value, void* data) { - if (instance) - instance->OnReadOnlyPropertiesRead(client_id, conn_id, status, handle, - len, value, data); - } - - static void OnReadAvailableAudioStatic(uint16_t client_id, - uint16_t conn_id, - tGATT_STATUS status, - uint16_t handle, uint16_t len, - uint8_t* value, void* data) { - if (instance) - instance->OnReadAvailableAudio(client_id, conn_id, status, handle, - len, value, data); - } - - - private: - uint8_t gatt_client_id = BTA_GATTS_INVALID_IF; - uint16_t pacs_client_id = 0; - PacsDevices pacsDevices; - // client id to callbacks mapping - std::map callbacks; - - void find_server_changed_ccc_handle(uint16_t conn_id, - const gatt::Service* service) { - PacsDevice* pacsDevice = pacsDevices.FindByConnId(conn_id); - if (!pacsDevice) { - LOG(ERROR) << __func__ - << ": Skipping unknown device, conn_id=" << loghex(conn_id); - return; - } - for (const gatt::Characteristic& charac : service->characteristics) { - if (charac.uuid == Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD)) { - pacsDevice->srv_changed_ccc_handle = - find_ccc_handle(conn_id, charac.value_handle); - if (!pacsDevice->srv_changed_ccc_handle) { - LOG(ERROR) << __func__ - << ": cannot find service changed CCC descriptor"; - continue; - } - LOG(INFO) << __func__ << ": service_changed_ccc=" - << loghex(pacsDevice->srv_changed_ccc_handle); - break; - } - } - } - - // Find the handle for the client characteristics configuration of a given - // characteristics - uint16_t find_ccc_handle(uint16_t conn_id, uint16_t char_handle) { - const gatt::Characteristic* p_char = - BTA_GATTC_GetCharacteristic(conn_id, char_handle); - - if (!p_char) { - LOG(WARNING) << __func__ << ": No such characteristic: " << char_handle; - return 0; - } - - for (const gatt::Descriptor& desc : p_char->descriptors) { - if (desc.uuid == Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG)) - return desc.handle; - } - - return 0; - } - - SinkPacsData *FindSinkByHandle(PacsDevice *dev, uint16_t handle) { - LOG(INFO) << __func__ << ": handle:" << loghex(handle); - auto iter = std::find_if(dev->sink_info.begin(), - dev->sink_info.end(), - [&handle](SinkPacsData data) { - return (data.sink_pac_handle == handle); - }); - - return (iter == dev->sink_info.end()) ? nullptr : &(*iter); - } - - SrcPacsData *FindSrcByHandle(PacsDevice *dev, uint16_t handle) { - LOG(INFO) << __func__ << ": handle:" << loghex(handle); - auto iter = std::find_if(dev->src_info.begin(), - dev->src_info.end(), - [&handle](SrcPacsData data) { - return (data.src_pac_handle == handle); - }); - - return (iter == dev->src_info.end()) ? nullptr : &(*iter); - } - - void UpdateConsolidatedsinkPacRecords(PacsDevice *dev) { - LOG(INFO) << __func__; - for (auto it = dev->sink_info.begin(); - it != dev->sink_info.end(); it ++) { - for (auto i = it->sink_pac_records.begin(); - i != it->sink_pac_records.end(); i ++) { - dev->consolidated_sink_pac_records. - push_back(static_cast(*i)); - } - } - } - - void UpdateConsolidatedsrcPacRecords(PacsDevice *dev) { - LOG(INFO) << __func__; - for (auto it = dev->src_info.begin(); - it != dev->src_info.end(); it ++) { - for (auto i = it->src_pac_records.begin(); - i != it->src_pac_records.end(); i ++) { - dev->consolidated_src_pac_records. - push_back(static_cast(*i)); - } - } - } -}; - -const char* get_gatt_event_name(uint32_t event) { - switch (event) { - CASE_RETURN_STR(BTA_GATTC_DEREG_EVT) - CASE_RETURN_STR(BTA_GATTC_OPEN_EVT) - CASE_RETURN_STR(BTA_GATTC_CLOSE_EVT) - CASE_RETURN_STR(BTA_GATTC_SEARCH_CMPL_EVT) - CASE_RETURN_STR(BTA_GATTC_NOTIF_EVT) - CASE_RETURN_STR(BTA_GATTC_ENC_CMPL_CB_EVT) - CASE_RETURN_STR(BTA_GATTC_CONN_UPDATE_EVT) - CASE_RETURN_STR(BTA_GATTC_SRVC_CHG_EVT) - CASE_RETURN_STR(BTA_GATTC_SRVC_DISC_DONE_EVT) - CASE_RETURN_STR(BTA_GATTC_CONGEST_EVT) - default: - return "Unknown Event"; - } -} - -void pacs_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) { - if (p_data == nullptr || !instance) { - LOG(ERROR) << __func__ << ": p_data is null or no instance, return"; - return; - } - LOG(INFO) << __func__ << ": Event : " << get_gatt_event_name(event); - - switch (event) { - case BTA_GATTC_DEREG_EVT: - break; - - case BTA_GATTC_OPEN_EVT: { - tBTA_GATTC_OPEN& o = p_data->open; - instance->OnGattConnected(o.status, o.conn_id, o.client_if, o.remote_bda, - o.transport, o.mtu); - break; - } - - case BTA_GATTC_CLOSE_EVT: { - tBTA_GATTC_CLOSE& c = p_data->close; - instance->OnGattDisconnected(c.status, c.conn_id, c.client_if, - c.remote_bda, c.reason); - } break; - - case BTA_GATTC_SEARCH_CMPL_EVT: - instance->OnServiceSearchComplete(p_data->search_cmpl.conn_id, - p_data->search_cmpl.status); - break; - - case BTA_GATTC_NOTIF_EVT: - if (!p_data->notify.is_notify || p_data->notify.len > GATT_MAX_ATTR_LEN) { - LOG(ERROR) << __func__ << ": rejected BTA_GATTC_NOTIF_EVT. is_notify=" - << p_data->notify.is_notify - << ", len=" << p_data->notify.len; - break; - } - instance->OnNotificationEvent(p_data->notify.conn_id, - p_data->notify.handle, p_data->notify.len, - p_data->notify.value); - break; - - case BTA_GATTC_ENC_CMPL_CB_EVT: - instance->OnEncryptionComplete(p_data->enc_cmpl.remote_bda, true); - break; - - case BTA_GATTC_CONN_UPDATE_EVT: - instance->OnConnectionUpdateComplete(p_data->conn_update.conn_id, - p_data); - break; - - case BTA_GATTC_SRVC_CHG_EVT: - instance->OnServiceChangeEvent(p_data->remote_bda); - break; - - case BTA_GATTC_SRVC_DISC_DONE_EVT: - instance->OnServiceDiscDoneEvent(p_data->remote_bda); - break; - case BTA_GATTC_CONGEST_EVT: - instance->OnCongestionEvent(p_data->congest.conn_id, - p_data->congest.congested); - break; - default: - break; - } -} - -void encryption_callback(const RawAddress* address, tGATT_TRANSPORT, void*, - tBTM_STATUS status) { - if (instance) { - instance->OnEncryptionComplete(*address, - status == BTM_SUCCESS ? true : false); - } -} - -void PacsClient::Initialize(PacsClientCallbacks* callbacks) { - if (instance) { - instance->Register(callbacks); - } else { - instance = new PacsClientImpl(); - instance->Register(callbacks); - } -} - -void PacsClient::CleanUp(uint16_t client_id) { - if(instance->GetClientCount()) { - instance->Deregister(client_id); - if(!instance->GetClientCount()) { - delete instance; - instance = nullptr; - } - } -} - -PacsClient* PacsClient::Get() { - CHECK(instance); - return instance; -} - -} // namespace pacs -} // namespace bap -} // namespace bluetooth diff --git a/le_audio/system/bt/bta/bap/ucast_client_int.h b/le_audio/system/bt/bta/bap/ucast_client_int.h deleted file mode 100644 index 2d535fa2a887d470065a3301b62c62977b638d3d..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/bap/ucast_client_int.h +++ /dev/null @@ -1,1276 +0,0 @@ -/****************************************************************************** - * - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - - -#pragma once - -#include -#include "state_machine.h" -#include -#include "bta_bap_uclient_api.h" -#include "bta_pacs_client_api.h" -#include "bta_ascs_client_api.h" -#include "bt_trace.h" -#include "uclient_alarm.h" -#include "btif_util.h" - -namespace bluetooth { -namespace bap { -namespace ucast { - -using bluetooth::bap::pacs::ConnectionState; -using bluetooth::bap::pacs::PacsClient; -using bluetooth::bap::ascs::GattState; -using bluetooth::bap::ascs::AscsClient; -using bluetooth::bap::ascs::AseParams; -using bluetooth::bap::ascs::AseCodecConfigParams; -using bluetooth::bap::ascs::AseCodecConfigOp; -using bluetooth::bap::cis::CisInterface; - -using bluetooth::bap::cis::CigState; -using bluetooth::bap::cis::CisState; - -using bluetooth::bap::alarm::BapAlarm; -using bluetooth::bap::alarm::BapAlarmCallbacks; - -class UstreamManager; -class UstreamManagers; -struct UcastAudioStream; -class UcastAudioStreams; -class StreamContexts; -struct StreamContext; -class StreamTracker; - -enum class StreamAttachedState { - IDLE = 0x1 << 0, - IDLE_TO_PHY = 0x1 << 1, - VIRTUAL = 0x1 << 2, - VIR_TO_PHY = 0x1 << 3, - PHYSICAL = 0x1 << 4 -}; - -enum class StreamControlType { - None = 0x00, - Connect = 0X01, - Disconnect = 0x02, - Start = 0x04, - Stop = 0x08, - Reconfig = 0x10, - UpdateStream = 0x20 -}; - -enum class DeviceType { - NONE = 0x00, - EARBUD = 0X01, // group member - HEADSET_STEREO = 0x02, // headset with 1 CIS - HEADSET_SPLIT_STEREO = 0x03 // headset with 2 CIS -}; - -enum class IntConnectState { - IDLE = 0x00, - PACS_CONNECTING = 0x01, - PACS_DISCOVERING = 0X02, - ASCS_CONNECTING = 0x03, - ASCS_DISCOVERING = 0x04, - ASCS_DISCOVERED = 0x05, -}; - -enum class AscsPendingCmd { - NONE = 0x00, - CODEC_CONFIG_ISSUED = 0x01, - QOS_CONFIG_ISSUED = 0x02, - ENABLE_ISSUED = 0x03, - START_READY_ISSUED = 0x04, - DISABLE_ISSUED = 0x05, - STOP_READY_ISSUED = 0x06, - RELEASE_ISSUED = 0x07, - UPDATE_METADATA_ISSUED = 0x08 -}; - -enum class CisPendingCmd { - NONE = 0x00, - CIG_CREATE_ISSUED = 0x08, - CIS_CREATE_ISSUED = 0x09, - CIS_SETUP_DATAPATH_ISSUED = 0x10, - CIS_RMV_DATAPATH_ISSUED = 0x11, - CIS_DESTROY_ISSUED = 0x12, - CIG_REMOVE_ISSUED = 0x13 -}; - -enum class GattPendingCmd { - NONE = 0x00, - GATT_CONN_PENDING = 0x01, - GATT_DISC_PENDING = 0x02 -}; - -typedef enum { - BAP_CONNECT_REQ_EVT = 0X00, - BAP_DISCONNECT_REQ_EVT, - BAP_START_REQ_EVT, - BAP_STOP_REQ_EVT, - BAP_RECONFIG_REQ_EVT, - BAP_STREAM_UPDATE_REQ_EVT, - PACS_CONNECTION_STATE_EVT, - PACS_DISCOVERY_RES_EVT, - PACS_AUDIO_CONTEXT_RES_EVT, - ASCS_CONNECTION_STATE_EVT, - ASCS_DISCOVERY_RES_EVT, - ASCS_ASE_STATE_EVT, - ASCS_ASE_OP_FAILED_EVT, - CIS_GROUP_STATE_EVT, - CIS_STATE_EVT, - BAP_TIME_OUT_EVT, -} BapEvent; - -struct BapConnect { - std::vector bd_addr; - bool is_direct; - std::vector streams; -}; - -struct BapDisconnect { - RawAddress bd_addr; - std::vector streams; -}; - -struct BapStart { - RawAddress bd_addr; - std::vector streams; -}; - -struct BapStop { - RawAddress bd_addr; - std::vector streams; -}; - -struct BapReconfig { - RawAddress bd_addr; - std::vector streams; -}; - -struct BapStreamUpdate { - RawAddress bd_addr; - std::vector update_streams; -}; - -struct PacsConnectionState { - RawAddress bd_addr; - ConnectionState state; -}; - -struct AscsConnectionState { - RawAddress bd_addr; - GattState state; -}; - -struct AscsDiscovery { - int status; - RawAddress bd_addr; - std::vector sink_ases_list; - std::vector src_ases_list; -}; - -struct AscsState { - RawAddress bd_addr; - AseParams ase_params; -}; - -struct AscsOpFailed { - RawAddress bd_addr; - ascs::AseOpId ase_op_id; - std::vector ase_list; -}; - -struct CisGroupState { - uint8_t cig_id; - CigState state; -}; - -struct CisStreamState { - uint8_t cig_id; - uint8_t cis_id; - uint8_t direction; - CisState state; -}; - -struct PacsDiscovery { - int status; - RawAddress bd_addr; - std::vector sink_pac_records; - std::vector src_pac_records; - uint32_t sink_locations; - uint32_t src_locations; - uint32_t available_contexts; - uint32_t supported_contexts; -}; - -struct PacsAvailableContexts { - RawAddress bd_addr; - uint32_t available_contexts; -}; - -struct IntStrmTracker { - IntStrmTracker(StreamType strm_type, uint8_t ase_id, uint8_t cig_id, - uint8_t cis_id, CodecConfig &codec_config, - QosConfig &qos_config) - : strm_type(strm_type), ase_id(ase_id) , cig_id(cig_id) , - cis_id(cis_id), codec_config(codec_config), - qos_config(qos_config) { - attached_state = StreamAttachedState::IDLE; - } - StreamType strm_type; - uint8_t ase_id; - uint8_t cig_id; - uint8_t cis_id; - CodecConfig codec_config; - QosConfig qos_config; - StreamAttachedState attached_state; -}; - -class IntStrmTrackers { - public: - std::vector FindByCigId(uint8_t cig_id) { - std::vector trackers; - for (auto i = int_strm_trackers.begin(); - i != int_strm_trackers.end();i++) { - if((*i)->cig_id == cig_id) { - LOG(WARNING) << __func__ << " tracker found"; - trackers.push_back(*i); - } - } - return trackers; - } - - std::vector FindByCigIdAndDir(uint8_t cig_id, - uint8_t direction) { - std::vector trackers; - for (auto i = int_strm_trackers.begin(); - i != int_strm_trackers.end();i++) { - if((*i)->cig_id == cig_id && - (*i)->strm_type.direction == direction) { - trackers.push_back(*i); - } - } - return trackers; - } - - std::vector FindByCisId(uint8_t cig_id, uint8_t cis_id) { - std::vector trackers; - for (auto i = int_strm_trackers.begin(); - i != int_strm_trackers.end();i++) { - if((*i)->cig_id == cig_id && (*i)->cis_id == cis_id) { - trackers.push_back(*i); - } - } - return trackers; - } - - IntStrmTracker *FindByIndex(uint8_t i) { - IntStrmTracker *tracker = int_strm_trackers.at(i); - return tracker; - } - - IntStrmTracker *FindByAseId(uint8_t ase_id) { - auto iter = std::find_if(int_strm_trackers.begin(), int_strm_trackers.end(), - [&ase_id](IntStrmTracker *tracker) { - return tracker->ase_id == ase_id; - }); - - return (iter == int_strm_trackers.end()) ? nullptr : (*iter); - } - - IntStrmTracker *FindOrAddBytrackerType(StreamType strm_type, - uint8_t ase_id, uint8_t cig_id, uint8_t cis_id, - CodecConfig &codec_config, QosConfig &qos_config) { - - auto iter = std::find_if(int_strm_trackers.begin(), int_strm_trackers.end(), - [&strm_type, &cig_id, &cis_id](IntStrmTracker *tracker) { - return ((tracker->strm_type.type == strm_type.type) && - (tracker->strm_type.direction == - strm_type.direction) && - (tracker->cig_id == cig_id) && - (tracker->cis_id == cis_id)); - }); - - if (iter == int_strm_trackers.end()) { - IntStrmTracker *tracker = new IntStrmTracker(strm_type, - ase_id, cig_id, cis_id, codec_config, qos_config); - int_strm_trackers.push_back(tracker); - return tracker; - } else { - return (*iter); - } - } - - void Remove(StreamType strm_type, uint8_t cig_id, uint8_t cis_id) { - for (auto it = int_strm_trackers.begin(); it != int_strm_trackers.end();) { - if (((*it)->strm_type.type = strm_type.type) && - ((*it)->strm_type.direction = strm_type.direction) && - ((*it)->cig_id = cig_id) && ((*it)->cis_id = cis_id)) { - delete(*it); - it = int_strm_trackers.erase(it); - } else { - it++; - } - } - } - - void RemoveVirtualAttachedTrackers() { - LOG(WARNING) << __func__; - for (auto it = int_strm_trackers.begin(); it != int_strm_trackers.end();) { - if ((*it)->attached_state == StreamAttachedState::VIRTUAL) { - delete(*it); - it = int_strm_trackers.erase(it); - LOG(WARNING) << __func__ - << ": Removed virtual attached tracker"; - } else { - it++; - } - } - } - - size_t size() { return (int_strm_trackers.size()); } - - std::vector *GetTrackerList() { - return &int_strm_trackers; - } - - std::vector GetTrackerListByDir(uint8_t direction) { - std::vector trackers; - for (auto i = int_strm_trackers.begin(); - i != int_strm_trackers.end();i++) { - if((*i)->strm_type.direction == direction) { - trackers.push_back(*i); - } - } - return trackers; - } - - private: - std::vector int_strm_trackers; -}; - -union BapEventData { - BapConnect connect_req; - BapDisconnect disc_req; - BapStart start_req; - BapStop stop_req; - BapReconfig reconfig_req; - PacsConnectionState connection_state_rsp; - PacsDiscovery pacs_discovery_rsp; - PacsAvailableContexts pacs_audio_context_rsp; -}; - -enum class TimeoutVal { //in milli seconds(1sec = 1000ms) - ConnectingTimeout = 10000, - StartingTimeout = 2000, - StoppingTimeout = 2000, - DisconnectingTimeout = 1000, - ReconfiguringTimeout = 2000, - UpdatingTimeout = 1000 -}; - -enum class MaxTimeoutVal { //in milli seconds(1sec = 1000ms) - ConnectingTimeout = 10000, - StartingTimeout = 4000, - StoppingTimeout = 4000, - DisconnectingTimeout = 4000, - ReconfiguringTimeout = 8000, - UpdatingTimeout = 4000 -}; - -enum class TimeoutReason { - STATE_TRANSITION = 1, -}; - -struct BapTimeout { - RawAddress bd_addr; - StreamTracker* tracker; - TimeoutReason reason; - int transition_state; -}; - -class StreamTracker : public bluetooth::common::StateMachine { - public: - enum { - kStateIdle, // - kStateConnecting, // - kStateConnected, // - kStateStarting, // - kStateStreaming, // - kStateStopping, // - kStateDisconnecting, // - kStateReconfiguring, // - kStateUpdating - }; - - class StateIdle : public State { - public: - StateIdle(StreamTracker& sm) - : State(sm, kStateIdle), tracker_(sm), - strm_mgr_(sm.GetStreamManager()) {} - void OnEnter() override; - void OnExit() override; - const char* GetState() { return "Idle"; } - bool ProcessEvent(uint32_t event, void* p_data) override; - - private: - StreamTracker &tracker_; - UstreamManager *strm_mgr_; - }; - - class StateConnecting : public State { - public: - StateConnecting(StreamTracker& sm) - : State(sm, kStateConnecting), tracker_(sm), - strm_mgr_(sm.GetStreamManager()) {} - void OnEnter() override; - void OnExit() override; - const char* GetState() { return "Connecting"; } - bool ProcessEvent(uint32_t event, void* p_data) override; - void DeriveDeviceType(PacsDiscovery *pacs_discovery); - bool AttachStreamsToContext(std::vector *all_trackers, - std::vector *streams, - uint8_t cis_count, - std::vector *ase_ops); - alarm_t* state_transition_timer; - BapTimeout timeout; - - private: - StreamTracker &tracker_; - UstreamManager *strm_mgr_; - PacsDiscovery pacs_discovery_; - AscsDiscovery ascs_discovery_; - IntStrmTrackers int_strm_trackers_; - }; - - class StateConnected : public State { - public: - StateConnected(StreamTracker& sm) - : State(sm, kStateConnected), tracker_(sm), - strm_mgr_(sm.GetStreamManager()){} - void OnEnter() override; - void OnExit() override; - const char* GetState() { return "Connected"; } - bool ProcessEvent(uint32_t event, void* p_data) override; - - private: - StreamTracker &tracker_; - UstreamManager *strm_mgr_; - }; - - class StateStarting : public State { - public: - StateStarting(StreamTracker& sm) - : State(sm, kStateStarting), tracker_(sm), - strm_mgr_(sm.GetStreamManager()){} - void OnEnter() override; - void OnExit() override; - const char* GetState() { return "Starting"; } - bool ProcessEvent(uint32_t event, void* p_data) override; - bool CheckAndUpdateStreamingState(); - alarm_t* state_transition_timer; - PacsAvailableContexts pacs_contexts; - BapTimeout timeout; - - private: - StreamTracker &tracker_; - UstreamManager *strm_mgr_; - IntStrmTrackers int_strm_trackers_; - }; - - class StateStreaming : public State { - public: - StateStreaming(StreamTracker& sm) - : State(sm, kStateStreaming), tracker_(sm), - strm_mgr_(sm.GetStreamManager()){} - void OnEnter() override; - void OnExit() override; - const char* GetState() { return "Streaming"; } - bool ProcessEvent(uint32_t event, void* p_data) override; - - private: - StreamTracker &tracker_; - UstreamManager *strm_mgr_; - }; - - class StateStopping : public State { - public: - StateStopping(StreamTracker& sm) - : State(sm, kStateStopping), tracker_(sm), - strm_mgr_(sm.GetStreamManager()) {} - void OnEnter() override; - void OnExit() override; - const char* GetState() { return "Stopping"; } - bool ProcessEvent(uint32_t event, void* p_data) override; - bool TerminateCisAndCig(UcastAudioStream *stream); - bool CheckAndUpdateStoppedState(); - alarm_t* state_transition_timer; - BapTimeout timeout; - - private: - StreamTracker &tracker_; - UstreamManager *strm_mgr_; - IntStrmTrackers int_strm_trackers_; - }; - - class StateDisconnecting : public State { - public: - StateDisconnecting(StreamTracker& sm) - : State(sm, kStateDisconnecting), tracker_(sm), - strm_mgr_(sm.GetStreamManager()) {} - void OnEnter() override; - void OnExit() override; - const char* GetState() { return "Disconnecting"; } - bool ProcessEvent(uint32_t event, void* p_data) override; - bool TerminateGattConnection(); - void ContinueDisconnection(UcastAudioStream *stream); - bool CheckAndUpdateDisconnectedState(); - alarm_t* state_transition_timer; - BapTimeout timeout; - - private: - StreamTracker &tracker_; - UstreamManager *strm_mgr_; - IntStrmTrackers int_strm_trackers_; - }; - - class StateReconfiguring: public State { - public: - StateReconfiguring(StreamTracker& sm) - : State(sm, kStateReconfiguring), tracker_(sm), - strm_mgr_(sm.GetStreamManager()) {} - void OnEnter() override; - void OnExit() override; - const char* GetState() { return "Reconfiguring"; } - bool ProcessEvent(uint32_t event, void* p_data) override; - alarm_t* state_transition_timer; - BapTimeout timeout; - - private: - StreamTracker &tracker_; - UstreamManager *strm_mgr_; - IntStrmTrackers int_strm_trackers_; - }; - - class StateUpdating: public State { - public: - StateUpdating(StreamTracker& sm) - : State(sm, kStateUpdating), tracker_(sm), - strm_mgr_(sm.GetStreamManager()) {} - void OnEnter() override; - void OnExit() override; - const char* GetState() { return "Updating"; } - bool ProcessEvent(uint32_t event, void* p_data) override; - alarm_t* state_transition_timer; - BapTimeout timeout; - - private: - StreamTracker &tracker_; - UstreamManager *strm_mgr_; - IntStrmTrackers int_strm_trackers_; - }; - - StreamTracker(int init_state_id, UstreamManager *strm_mgr, - std::vector *connect_streams, - std::vector *reconfig_streams, - std::vector *streams, - StreamControlType ops_type): - init_state_id_(init_state_id), - strm_mgr_(strm_mgr) { - - state_idle_ = new StateIdle(*this); - state_connecting_ = new StateConnecting(*this); - state_connected_ = new StateConnected(*this); - state_starting_ = new StateStarting(*this); - state_streaming_ = new StateStreaming(*this); - state_stopping_ = new StateStopping(*this); - state_disconnecting_ = new StateDisconnecting(*this); - state_reconfiguring_ = new StateReconfiguring(*this); - state_updating_ = new StateUpdating(*this); - pacs_disc_succeded_ = false; - - AddState(state_idle_); - AddState(state_connecting_); - AddState(state_connected_); - AddState(state_starting_); - AddState(state_streaming_); - AddState(state_stopping_); - AddState(state_disconnecting_); - AddState(state_reconfiguring_); - AddState(state_updating_); - - switch(init_state_id) { - case kStateIdle: - SetInitialState(state_idle_); - break; - case kStateConnected: - SetInitialState(state_connected_); - break; - case kStateStreaming: - SetInitialState(state_streaming_); - break; - case kStateDisconnecting: - SetInitialState(state_disconnecting_); - break; - default: - SetInitialState(state_idle_); - } - - str_ops_type = ops_type; - - if(ops_type == StreamControlType::Connect) { - conn_streams = *connect_streams; - } else if(ops_type == StreamControlType::Reconfig) { - reconf_streams = *reconfig_streams; - } else if(ops_type != StreamControlType::UpdateStream) { - other_streams = *streams; - } - } - - void PauseRemoteDevInteraction(bool pause); - bool decoupleStream(StreamType *stream_info); - - uint8_t ChooseBestCodec(StreamType stream_type, - std::vector *codec_qos_configs, - PacsDiscovery *pacs_discovery); - - bool ChooseBestQos(QosConfig *src_config, - ascs::AseCodecConfigParams *rem_qos_prefs, - QosConfig *dst_config, - int stream_state, uint8_t stream_direction); - - bool HandlePacsConnectionEvent(void *p_data); - - bool HandlePacsAudioContextEvent(PacsAvailableContexts *pacs_contexts); - - bool HandleCisEventsInStreaming(void* p_data); - - bool HandleStreamUpdate (int cur_state); - - bool CheckAndUpdateStreamingState(IntStrmTrackers *int_strm_trackers); - - bool HandleAscsConnectionEvent(void *p_data); - - void HandleCigStateEvent(uint32_t event, void *p_data, - IntStrmTrackers *int_strm_trackers); - - void HandleAseStateEvent(void *p_data, StreamControlType control_type, - IntStrmTrackers *int_strm_trackers); - - void HandleAseOpFailedEvent(void *p_data); - - bool ValidateAseUpdate(void* p_data, IntStrmTrackers *int_strm_trackers, - int exp_strm_state); - - bool HandleDisconnect(void* p_data, int cur_state); - - bool HandleRemoteDisconnect(uint32_t event, void* p_data, int cur_state); - - bool StreamCanbeDisconnected(StreamContext *cur_context, uint8_t ase_id); - - bool HandleInternalDisconnect(bool release); - - bool HandleStop(void* p_data, int cur_state); - - bool HandleRemoteStop(uint32_t event, void* p_data, int cur_state); - - bool HandleRemoteReconfig(uint32_t event, void* p_data, int cur_state); - - bool PrepareCodecConfigPayload(std::vector *ase_ops, - UcastAudioStream *stream); - - void CheckAndSendQosConfig(IntStrmTrackers *int_strm_trackers); - - void CheckAndSendEnable(IntStrmTrackers *int_strm_trackers); - - bool HandleAbruptStop(uint32_t event, void* p_data); - - alarm_t* SetTimer(const char* alarmname, BapTimeout* timeout, - TimeoutReason reason, uint64_t ms); - - void ClearTimer(alarm_t* timer, const char* alarmname); - - void OnTimeout(void* data); - - StreamControlType GetControlType() { - return str_ops_type; - } - - UstreamManager *GetStreamManager() { - return strm_mgr_; - } - - bool UpdatePacsDiscovery(PacsDiscovery disc_res) { - pacs_disc_succeded_ = true; - pacs_discovery_ = disc_res; - return true; - } - - PacsDiscovery *GetPacsDiscovery() { - if(pacs_disc_succeded_) { - return &pacs_discovery_; - } else { - return nullptr; - } - } - - bool UpdateControlType(StreamControlType ops_type) { - str_ops_type = ops_type; - return true; - } - - bool UpdateStreams(std::vector *streams) { - other_streams = *streams; - return true; - } - - bool UpdateConnStreams( - std::vector *connect_streams) { - conn_streams = *connect_streams; - return true; - } - - bool UpdateReconfStreams( - std::vector *reconfig_streams) { - reconf_streams = *reconfig_streams; - return true; - } - - bool UpdateMetaUpdateStreams( - std::vector *meta_streams) { - meta_update_streams = *meta_streams; - return true; - } - - std::vector *GetStreams() { - return &other_streams; - } - std::vector *GetConnStreams() { - return &conn_streams; - } - std::vector *GetReconfStreams() { - return &reconf_streams; - } - - std::vector *GetMetaUpdateStreams() { - return &meta_update_streams; - } - - const char* GetEventName(uint32_t event) { - switch (event) { - CASE_RETURN_STR(BAP_CONNECT_REQ_EVT) - CASE_RETURN_STR(BAP_DISCONNECT_REQ_EVT) - CASE_RETURN_STR(BAP_START_REQ_EVT) - CASE_RETURN_STR(BAP_STOP_REQ_EVT) - CASE_RETURN_STR(BAP_RECONFIG_REQ_EVT) - CASE_RETURN_STR(BAP_STREAM_UPDATE_REQ_EVT) - CASE_RETURN_STR(PACS_CONNECTION_STATE_EVT) - CASE_RETURN_STR(PACS_DISCOVERY_RES_EVT) - CASE_RETURN_STR(PACS_AUDIO_CONTEXT_RES_EVT) - CASE_RETURN_STR(ASCS_CONNECTION_STATE_EVT) - CASE_RETURN_STR(ASCS_DISCOVERY_RES_EVT) - CASE_RETURN_STR(ASCS_ASE_STATE_EVT) - CASE_RETURN_STR(ASCS_ASE_OP_FAILED_EVT) - CASE_RETURN_STR(CIS_GROUP_STATE_EVT) - CASE_RETURN_STR(CIS_STATE_EVT) - CASE_RETURN_STR(BAP_TIME_OUT_EVT) - default: - return "Unknown Event"; - } - } - - private: - int init_state_id_; - UstreamManager *strm_mgr_; - std::vector conn_streams; - std::vector other_streams; - std::vector reconf_streams; - std::vector meta_update_streams; - StreamControlType str_ops_type; - bool pacs_disc_succeded_; - PacsDiscovery pacs_discovery_; - StateIdle *state_idle_; - StateConnecting *state_connecting_; - StateConnected *state_connected_; - StateStarting *state_starting_; - StateStreaming *state_streaming_; - StateStopping *state_stopping_; - StateDisconnecting *state_disconnecting_; - StateReconfiguring *state_reconfiguring_; - StateUpdating *state_updating_; -}; - -struct StreamOpConnect { - StreamType stream_type; - //std::vector codec_configs; - //std::vector qos_configs; -}; - -struct StreamOpReconfig { - StreamType stream_type; - //std::vector codec_configs; - //std::vector qos_configs; -}; - -union StreamOpData { - StreamOpConnect connect_op; - StreamType stream_type; - StreamOpReconfig reconfig_op; -}; - -struct StreamOpNode { - bool busy; - bool is_client_originated; - StreamControlType ops_type; - StreamOpData ops_data; -}; - -struct StreamIdType { - uint8_t ase_id; - uint8_t ase_direction; - bool virtual_attach; - uint8_t cig_id; - uint8_t cis_id; -}; - -struct StreamContext { - StreamContext(StreamType strm_type) - : stream_type(strm_type) { - stream_state = StreamState::DISCONNECTED; - attached_state = StreamAttachedState::IDLE; - } - StreamType stream_type; - StreamAttachedState attached_state; - std::vector stream_ids; - StreamState stream_state; - IntConnectState connection_state; - CodecConfig codec_config; - QosConfig qos_config; - QosConfig req_qos_config; -}; - -class StreamContexts { - public: - - StreamContext *FindByType(StreamType stream_type); - - StreamContext *FindOrAddByType(StreamType stream_type); - - void Remove(StreamType stream_type); - - bool IsAseAttached(StreamType stream_type); - - std::vector FindByAseAttachedState(uint16_t ase_id, - StreamAttachedState state); - - - StreamContext* FindByAseId(uint16_t ase_id); - - std::vector *GetAllContexts() { - return &strm_contexts; - } - - size_t size() { return (strm_contexts.size()); } - - private: - std::vector strm_contexts; -}; - - -class StreamOpsQueue { - public: - bool Add(StreamOpNode op_node); - - bool AddFirst(StreamOpNode op_node); - - StreamOpNode *GetNextNode(); - - bool Remove(StreamType stream_type); - - StreamOpNode* FindByContext(StreamType stream_type); - - bool ChangeOpType(StreamType stream_type, StreamControlType new_ops_type); - - size_t size() { return (queue.size()); } - - std::vector queue; -}; - -class StreamTrackers { - public: - StreamTracker *FindOrAddByType(int init_state_id, UstreamManager *strm_mgr, - std::vector *connect_streams, - std::vector *reconfig_streams, - std::vector *streams, - StreamControlType ops_type); - - bool Remove(std::vector streams, - StreamControlType ops_type); - - void RemoveByStates(std::vector state_ids); - - std::map > GetTrackersByType( - std::vector *streams); - - StreamTracker *FindByStreamsType(std::vector *streams); - - std::vector GetTrackersByStates( - std::vector *state_ids); - - bool ChangeOpType( StreamType stream_type, - StreamControlType new_ops_type); - - bool IsStreamTrackerValid(StreamTracker* Tracker, - std::vector *state_ids); - - size_t size() { return (stream_trackers.size()); } - - std::vector stream_trackers; -}; - -struct UcastAudioStream { - UcastAudioStream(uint8_t ase_id, uint8_t ase_state, uint8_t ase_direction) - : ase_id(ase_id) , ase_state(ase_state) { - ase_state = ascs::ASE_STATE_INVALID; - cig_state = CigState::INVALID; - cis_state = CisState::INVALID; - direction = ase_direction; - cig_id = 0XFF; - cis_id = 0xFF; - cis_retry_count = 0; - overall_state = StreamTracker::kStateIdle; - ase_pending_cmd = AscsPendingCmd::NONE; - cis_pending_cmd = CisPendingCmd::NONE; - } - bool is_active; - uint8_t ase_id; - uint8_t ase_state; - AseParams ase_params; - AseCodecConfigParams pref_qos_params; - uint8_t cig_id; - CigState cig_state; - uint8_t cis_id; - CisState cis_state; - uint8_t cis_retry_count; - int overall_state; // stream tracker state - StreamControlType control_type; - AscsPendingCmd ase_pending_cmd; - CisPendingCmd cis_pending_cmd; - uint16_t audio_context; - uint8_t direction; - uint32_t audio_location; - CodecConfig codec_config; - QosConfig qos_config; - QosConfig req_qos_config; -}; - -class UcastAudioStreams { - public: - - std::vector FindByCigId(uint8_t cig_id, int state) { - std::vector streams; - for (auto i = audio_streams.begin(); i != audio_streams.end();i++) { - if((*i)->cig_id == cig_id && - (*i)->overall_state == state) { - streams.push_back(*i); - } - } - return streams; - } - - std::vector FindByCisId(uint8_t cig_id, uint8_t cis_id) { - std::vector streams; - for (auto i = audio_streams.begin(); i != audio_streams.end();i++) { - if((*i)->cig_id == cig_id && (*i)->cis_id == cis_id) { - streams.push_back(*i); - } - } - return streams; - } - - UcastAudioStream *FindByStreamType(uint16_t audio_context, - uint8_t direction) { - auto it = audio_streams.begin(); - while (it != audio_streams.end()) { - if((*it)->audio_context == audio_context && - (*it)->direction & direction) { - break; - } - it++; - } - return (it == audio_streams.end()) ? nullptr : (*it); - } - - UcastAudioStream *FindByCisIdAndDir(uint8_t cig_id, uint8_t cis_id, - uint8_t dir) { - auto it = audio_streams.begin(); - while (it != audio_streams.end()) { - if((*it)->cig_id == cig_id && (*it)->cis_id == cis_id && - (*it)->direction & dir) { - break; - } - it++; - } - return (it == audio_streams.end()) ? nullptr : (*it); - } - - UcastAudioStream *FindByAseId(uint8_t ase_id) { - auto it = audio_streams.begin(); - while (it != audio_streams.end()) { - if((*it)->ase_id == ase_id) { - break; - } - it++; - } - return (it == audio_streams.end()) ? nullptr : (*it); - } - - UcastAudioStream *FindOrAddByAseId(uint8_t ase_id, uint8_t ase_state, - uint8_t ase_direction) { - auto iter = std::find_if(audio_streams.begin(), audio_streams.end(), - [&ase_id, &ase_direction](UcastAudioStream *stream) { - return (stream->ase_id == ase_id && - stream->direction == ase_direction); - }); - - if (iter == audio_streams.end()) { - UcastAudioStream *stream = new UcastAudioStream(ase_id, ase_state, - ase_direction); - stream->overall_state = StreamTracker::kStateIdle; - audio_streams.push_back(stream); - auto it = std::find_if(audio_streams.begin(), audio_streams.end(), - [&ase_id, &ase_direction](UcastAudioStream* stream) { - return (stream->ase_id == ase_id && - stream->direction == ase_direction); - }); - return (it == audio_streams.end()) ? nullptr : (*it); - } else { - return (*iter); - } - } - - std::vector GetStreamsByStates( - std::vector state_ids, - uint8_t directions) { - std::vector streams; - for (auto i = audio_streams.begin(); i != audio_streams.end();i++) { - for (auto j = state_ids.begin(); j != state_ids.end();j++) { - if(((*i)->overall_state == *j) && ((*i)->direction & directions)) { - streams.push_back(*i); - } - } - } - return streams; - } - - void Remove(uint8_t ase_id) { - for (auto it = audio_streams.begin(); it != audio_streams.end();) { - if ((*it)->ase_id == ase_id) { - delete(*it); - it = audio_streams.erase(it); - } else { - it++; - } - } - } - - std::vector *GetAllStreams() { - return &audio_streams; - } - - size_t size() { return (audio_streams.size()); } - // UcastAudioStream - private: - std::vector audio_streams; -}; - -struct GattPendingData { - GattPendingData() { - ascs_pending_cmd = GattPendingCmd::NONE; - pacs_pending_cmd = GattPendingCmd::NONE; - } - GattPendingCmd ascs_pending_cmd; - GattPendingCmd pacs_pending_cmd; -}; - -class UstreamManager { - public: - UstreamManager(const RawAddress& address, PacsClient *pacs_client, - uint16_t pacs_client_id, - AscsClient *ascs_client, CisInterface *cis_intf, - UcastClientCallbacks* callbacks, - BapAlarm *bap_alarm) - : address(address) , pacs_client(pacs_client), - pacs_client_id(pacs_client_id), - ascs_client(ascs_client), cis_intf(cis_intf), - ucl_callbacks(callbacks), bap_alarm(bap_alarm) { - pacs_state = ConnectionState::DISCONNECTED; - gatt_pending_data.pacs_pending_cmd = GattPendingCmd::NONE; - gatt_pending_data.ascs_pending_cmd = GattPendingCmd::NONE; - ascs_state = GattState::DISCONNECTED; - dev_type = DeviceType::NONE; - } - - bool PushEventToTracker(uint32_t event, void *p_data, - std::vector *state_ids); - - std::map > SplitContextOnState( - std::vector *streams); - - void ProcessEvent(uint32_t event, void* p_data); - - uint16_t GetConnId(); - - std::list GetCigId(); - - std::list GetCisId(); - - void ReportStreamState (std::vector stream_info); - - RawAddress &GetAddress() { return address; }; - - PacsClient *GetPacsClient() { - return pacs_client; - } - - uint16_t GetPacsClientId() { - return pacs_client_id; - } - - GattPendingData *GetGattPendingData() { - return &gatt_pending_data; - } - - bool UpdatePacsState(ConnectionState state) { - pacs_state = state; - return true; - } - - bool UpdateAscsState(GattState state) { - ascs_state = state; - return true; - } - - ConnectionState GetPacsState() { - return pacs_state; - } - - GattState GetAscsState() { - return ascs_state; - } - - AscsClient *GetAscsClient() { - return ascs_client; - } - - CisInterface *GetCisInterface() { - return cis_intf; - } - - BapAlarm *GetBapAlarm() { - return bap_alarm; - } - - UcastAudioStreams *GetAudioStreams() { - return &audio_streams; - } - - StreamTrackers *GetStreamTrackers() { - return &stream_trackers; - } - - StreamContexts *GetStreamContexts() { - return &stream_contexts; - } - - UcastClientCallbacks *GetUclientCbacks() { - return ucl_callbacks; - } - - void UpdateDevType(DeviceType device_type) { - dev_type = device_type; - } - - DeviceType GetDevType() { - return dev_type; - } - - const char* GetEventName(uint32_t event) { - switch (event) { - CASE_RETURN_STR(BAP_CONNECT_REQ_EVT) - CASE_RETURN_STR(BAP_DISCONNECT_REQ_EVT) - CASE_RETURN_STR(BAP_START_REQ_EVT) - CASE_RETURN_STR(BAP_STOP_REQ_EVT) - CASE_RETURN_STR(BAP_RECONFIG_REQ_EVT) - CASE_RETURN_STR(BAP_STREAM_UPDATE_REQ_EVT) - CASE_RETURN_STR(PACS_CONNECTION_STATE_EVT) - CASE_RETURN_STR(PACS_DISCOVERY_RES_EVT) - CASE_RETURN_STR(PACS_AUDIO_CONTEXT_RES_EVT) - CASE_RETURN_STR(ASCS_CONNECTION_STATE_EVT) - CASE_RETURN_STR(ASCS_DISCOVERY_RES_EVT) - CASE_RETURN_STR(ASCS_ASE_STATE_EVT) - CASE_RETURN_STR(ASCS_ASE_OP_FAILED_EVT) - CASE_RETURN_STR(CIS_GROUP_STATE_EVT) - CASE_RETURN_STR(CIS_STATE_EVT) - CASE_RETURN_STR(BAP_TIME_OUT_EVT) - default: - return "Unknown Event"; - } - } - - private: - RawAddress address; - PacsClient *pacs_client; - uint16_t pacs_client_id; - AscsClient *ascs_client; - ConnectionState pacs_state; - CisInterface *cis_intf; - GattState ascs_state; - StreamOpsQueue ops_queue; - UcastAudioStreams audio_streams; - StreamTrackers stream_trackers; - StreamContexts stream_contexts; - GattPendingData gatt_pending_data; - UcastClientCallbacks* ucl_callbacks; - BapAlarm *bap_alarm; - DeviceType dev_type; -}; - -class UstreamManagers { - public: - UstreamManager* FindByAddress(const RawAddress& address); - - UstreamManager* FindorAddByAddress(const RawAddress& address, - PacsClient *pacs_client, uint16_t pacs_client_id, - AscsClient *ascs_client, CisInterface *cis_intf, - UcastClientCallbacks* callbacks, BapAlarm* bap_alarm); - - - std::vector *GetAllManagers(); - - void Remove(const RawAddress& address); - - size_t size() { return (strm_mgrs.size()); } - - std::vector strm_mgrs; -}; - -} // namespace ucast -} // namespace bap -} // namespace bluetooth diff --git a/le_audio/system/bt/bta/bap/uclient_alarm.cc b/le_audio/system/bt/bta/bap/uclient_alarm.cc deleted file mode 100644 index cca6efac3f4fb2920a4f9b3ed7d99f3f2e59c05c..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/bap/uclient_alarm.cc +++ /dev/null @@ -1,99 +0,0 @@ -/****************************************************************************** - * - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - - -#include "uclient_alarm.h" -#include "bt_trace.h" -#define LOG_TAG "uclient_alarm" - -namespace bluetooth { -namespace bap { -namespace alarm { - -class BapAlarmImpl; -BapAlarmImpl *instance; - -static void alarm_handler(void* data); - -class BapAlarmImpl : public BapAlarm { - public: - BapAlarmImpl(BapAlarmCallbacks* callback): - callbacks(callback) { } - - ~BapAlarmImpl() override = default; - - void CleanUp () { } - - alarm_t* Create(const char* name) { - return alarm_new(name); - } - - void Delete(alarm_t* alarm) { - alarm_free(alarm); - } - - void Start(alarm_t* alarm, period_ms_t interval_ms, - void* data) { - alarm_set_on_mloop(alarm, interval_ms, alarm_handler, data); - } - - void Stop(alarm_t* alarm) { - alarm_cancel(alarm); - } - - bool IsScheduled(const alarm_t* alarm) { - return alarm_is_scheduled(alarm); - } - - void Timeout(void* data) { - if (callbacks) - callbacks->OnTimeout(data); // Call uclient_main - } - - private: - BapAlarmCallbacks *callbacks; -}; - -void BapAlarm::Initialize( - BapAlarmCallbacks* callbacks) { - if (instance) { - LOG(ERROR) << "Already initialized!"; - } else { - instance = new BapAlarmImpl(callbacks); - } -} - -void BapAlarm::CleanUp() { - BapAlarmImpl* ptr = instance; - instance = nullptr; - ptr->CleanUp(); - delete ptr; -} - -BapAlarm* BapAlarm::Get() { - return instance; -} - -static void alarm_handler(void* data) { - if (instance) - instance->Timeout(data); -} - -} //alarm -} //bap -} //bluetooth diff --git a/le_audio/system/bt/bta/bap/uclient_alarm.h b/le_audio/system/bt/bta/bap/uclient_alarm.h deleted file mode 100644 index 3e03d94b52336ba3bbb05e15139f8ac3efdd2f0e..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/bap/uclient_alarm.h +++ /dev/null @@ -1,63 +0,0 @@ -/****************************************************************************** - * - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - - -#pragma once - -#include -#include -#include "osi/include/alarm.h" -#include - -namespace bluetooth { -namespace bap { -namespace alarm { - -class BapAlarmCallbacks { - public: - virtual ~BapAlarmCallbacks() = default; - - /** Callback for timer timeout */ - virtual void OnTimeout(void* data) = 0; -}; - -class BapAlarm { - public: - virtual ~BapAlarm() = default; - - static void Initialize(BapAlarmCallbacks* callbacks); - static void CleanUp(); - static BapAlarm* Get(); - - virtual alarm_t* Create(const char* name) = 0; - - virtual void Delete(alarm_t* alarm) = 0; - - virtual void Start(alarm_t* alarm, period_ms_t interval_ms, - void* data) = 0; - - virtual void Stop(alarm_t* alarm) = 0; - - virtual bool IsScheduled(const alarm_t* alarm) = 0; - - virtual void Timeout(void* data) = 0; -}; - -} //alarm -} //bap -} //bluetooth diff --git a/le_audio/system/bt/bta/bap/uclient_main.cc b/le_audio/system/bt/bta/bap/uclient_main.cc deleted file mode 100644 index 0df1c39f6c77045c7676e2395b1889674ae8a51e..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/bap/uclient_main.cc +++ /dev/null @@ -1,548 +0,0 @@ -/****************************************************************************** - * - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - - -#include "bta_bap_uclient_api.h" -#include "ucast_client_int.h" -#include "bta_pacs_client_api.h" -#include "bta_ascs_client_api.h" -#include -#include -#include -#include -#include "bta_closure_api.h" -#include "bt_trace.h" - -namespace bluetooth { -namespace bap { -namespace ucast { - -using base::Bind; -using base::Unretained; -using base::Closure; -using bluetooth::Uuid; - -using bluetooth::bap::pacs::PacsClient; -using bluetooth::bap::pacs::ConnectionState; -using bluetooth::bap::pacs::CodecConfig; -using bluetooth::bap::pacs::PacsClientCallbacks; - -using bluetooth::bap::ascs::AscsClient; -using bluetooth::bap::ascs::GattState; -using bluetooth::bap::ascs::AscsClientCallbacks; -using bluetooth::bap::ascs::AseOpId; -using bluetooth::bap::ascs::AseOpStatus; -using bluetooth::bap::ascs::AseParams; - -using bluetooth::bap::ucast::UstreamManagers; -using bluetooth::bap::ucast::UstreamManager; - -using bluetooth::bap::ucast::BapEventData; -using bluetooth::bap::ucast::BapEvent; -using bluetooth::bap::ucast::BapConnect; -using bluetooth::bap::ucast::BapDisconnect; -using bluetooth::bap::ucast::BapStart; -using bluetooth::bap::ucast::BapStop; -using bluetooth::bap::ucast::BapReconfig; -using bluetooth::bap::ucast::PacsConnectionState; -using bluetooth::bap::ucast::PacsDiscovery; -using bluetooth::bap::ucast::PacsAvailableContexts; - -using bluetooth::bap::ucast::CisGroupState; -using bluetooth::bap::ucast::CisStreamState; -using bluetooth::bap::cis::CigState; -using bluetooth::bap::cis::CisState; -using bluetooth::bap::cis::CisInterface; - -using bluetooth::bap::alarm::BapAlarm; -using bluetooth::bap::alarm::BapAlarmCallbacks; - -class UcastClientImpl; -UcastClientImpl* instance = nullptr; - -class CisInterfaceCallbacksImpl : public CisInterfaceCallbacks { - public: - ~CisInterfaceCallbacksImpl() = default; - /** Callback for connection state change */ - void OnCigState(uint8_t cig_id, CigState state) { - do_in_bta_thread(FROM_HERE, Bind(&CisInterfaceCallbacks::OnCigState, - Unretained(UcastClient::Get()), cig_id, - state)); - - } - - void OnCisState(uint8_t cig_id, uint8_t cis_id, - uint8_t direction, CisState state) { - do_in_bta_thread(FROM_HERE, Bind(&CisInterfaceCallbacks::OnCisState, - Unretained(UcastClient::Get()), cig_id, - cis_id, direction, state)); - } -}; - -class PacsClientCallbacksImpl : public PacsClientCallbacks { - public: - ~PacsClientCallbacksImpl() = default; - void OnInitialized(int status, int client_id) override { - LOG(WARNING) << __func__ << ": status =" << loghex(status); - do_in_bta_thread(FROM_HERE, Bind(&PacsClientCallbacks::OnInitialized, - Unretained(UcastClient::Get()), status, - client_id)); - } - - void OnConnectionState(const RawAddress& address, - bluetooth::bap::pacs::ConnectionState state) override { - LOG(WARNING) << __func__ << ": address=" << address; - do_in_bta_thread(FROM_HERE, Bind(&PacsClientCallbacks::OnConnectionState, - Unretained(UcastClient::Get()), - address, state)); - } - - void OnAudioContextAvailable(const RawAddress& address, - uint32_t available_contexts) override { - do_in_bta_thread(FROM_HERE, - Bind(&PacsClientCallbacks::OnAudioContextAvailable, - Unretained(UcastClient::Get()), - address, available_contexts)); - } - - void OnSearchComplete(int status, const RawAddress& address, - std::vector sink_pac_records, - std::vector src_pac_records, - uint32_t sink_locations, - uint32_t src_locations, - uint32_t available_contexts, - uint32_t supported_contexts) override { - do_in_bta_thread(FROM_HERE, Bind(&PacsClientCallbacks::OnSearchComplete, - Unretained(UcastClient::Get()), - status, address, - sink_pac_records, - src_pac_records, - sink_locations, - src_locations, - available_contexts, - supported_contexts)); - } -}; - -class AscsClientCallbacksImpl : public AscsClientCallbacks { - public: - ~AscsClientCallbacksImpl() = default; - void OnAscsInitialized(int status, int client_id) override { - do_in_bta_thread(FROM_HERE, Bind(&AscsClientCallbacks::OnAscsInitialized, - Unretained(UcastClient::Get()), status, - client_id)); - } - - void OnConnectionState(const RawAddress& address, - bluetooth::bap::ascs::GattState state) override { - DVLOG(2) << __func__ << " address: " << address; - do_in_bta_thread(FROM_HERE, Bind(&AscsClientCallbacks::OnConnectionState, - Unretained(UcastClient::Get()), - address, state)); - } - - void OnAseOpFailed(const RawAddress& address, - AseOpId ase_op_id, - std::vector status) { - do_in_bta_thread(FROM_HERE, - Bind(&AscsClientCallbacks::OnAseOpFailed, - Unretained(UcastClient::Get()), - address, ase_op_id, status)); - - } - - void OnAseState(const RawAddress& address, - AseParams ase) override { - do_in_bta_thread(FROM_HERE, - Bind(&AscsClientCallbacks::OnAseState, - Unretained(UcastClient::Get()), - address, ase)); - } - - void OnSearchComplete(int status, const RawAddress& address, - std::vector sink_ase_list, - std::vector src_ase_list) override { - do_in_bta_thread(FROM_HERE, Bind(&AscsClientCallbacks::OnSearchComplete, - Unretained(UcastClient::Get()), - status, address, sink_ase_list, - src_ase_list)); - } -}; - -class BapAlarmCallbacksImpl : public BapAlarmCallbacks { - public: - ~BapAlarmCallbacksImpl() = default; - /** Callback for timer timeout */ - void OnTimeout(void* data) { - do_in_bta_thread(FROM_HERE, Bind(&BapAlarmCallbacks::OnTimeout, - Unretained(UcastClient::Get()), data)); - } -}; - -class UcastClientImpl : public UcastClient { - public: - ~UcastClientImpl() override = default; - - // APIs exposed for upper layers - void Connect(std::vector address, bool is_direct, - std::vector streams) override { - if(address.size() == 1) { - UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address[0], - pacs_client, pacs_client_id, - ascs_client, cis_intf, - ucl_callbacks, bap_alarm); - // hand over the request to stream manager - BapConnect data = { .bd_addr = address, .is_direct = is_direct, - .streams = streams}; - mgr->ProcessEvent(BAP_CONNECT_REQ_EVT, &data); - } - } - - void Disconnect(const RawAddress& address, - std::vector streams) override { - UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, - pacs_client, pacs_client_id, - ascs_client, cis_intf, - ucl_callbacks, bap_alarm); - - // hand over the request to stream manager - BapDisconnect data = { .bd_addr = address, - .streams = streams}; - mgr->ProcessEvent(BAP_DISCONNECT_REQ_EVT, &data); - } - - void Start(const RawAddress& address, - std::vector streams) override { - UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, - pacs_client, pacs_client_id, - ascs_client, cis_intf, - ucl_callbacks, bap_alarm); - - // hand over the request to stream manager - BapStart data = { .bd_addr = address, - .streams = streams}; - mgr->ProcessEvent(BAP_START_REQ_EVT, &data); - } - - void Stop(const RawAddress& address, - std::vector streams) override { - UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, - pacs_client, pacs_client_id, - ascs_client, cis_intf, - ucl_callbacks, bap_alarm); - - // hand over the request to stream manager - BapStop data = { .bd_addr = address, - .streams = streams}; - mgr->ProcessEvent(BAP_STOP_REQ_EVT, &data); - - } - - void Reconfigure(const RawAddress& address, - std::vector streams) override { - UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, - pacs_client, pacs_client_id, - ascs_client, cis_intf, - ucl_callbacks, bap_alarm); - - // hand over the request to stream manager - BapReconfig data = { .bd_addr = address, - .streams = streams}; - mgr->ProcessEvent(BAP_RECONFIG_REQ_EVT, &data); - } - - void UpdateStream(const RawAddress& address, - std::vector update_streams) override { - UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, - pacs_client, pacs_client_id, - ascs_client, cis_intf, - ucl_callbacks, bap_alarm); - - // hand over the request to stream manager - BapStreamUpdate data = { .bd_addr = address, - .update_streams = update_streams}; - mgr->ProcessEvent(BAP_STREAM_UPDATE_REQ_EVT, &data); - } - - // To be called from device specific stream manager - bool ReportStreamState(const RawAddress& address) { - //TODO to check - return true; - - } - - // PACS client related callbacks - // to be forwarded to device specific stream manager - void OnInitialized(int status, int client_id) override { - LOG(WARNING) << __func__ << ": actual client_id = " << loghex(client_id); - pacs_client_id = client_id; - } - - void OnConnectionState(const RawAddress& address, - ConnectionState state) override { - LOG(WARNING) << __func__ << ": address=" << address; - UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, - pacs_client, pacs_client_id, - ascs_client, cis_intf, - ucl_callbacks, bap_alarm); - // hand over the request to stream manager - PacsConnectionState data = { .bd_addr = address, - .state = state - }; - mgr->ProcessEvent(PACS_CONNECTION_STATE_EVT, &data); - } - - void OnAudioContextAvailable(const RawAddress& address, - uint32_t available_contexts) override { - LOG(WARNING) << __func__ << ": address=" << address; - UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, - pacs_client, pacs_client_id, - ascs_client, cis_intf, - ucl_callbacks, bap_alarm); - // hand over the request to stream manager - PacsAvailableContexts data = { - .bd_addr = address, - .available_contexts = available_contexts, - }; - mgr->ProcessEvent(PACS_AUDIO_CONTEXT_RES_EVT, &data); - } - - void OnSearchComplete(int status, const RawAddress& address, - std::vector sink_pac_records, - std::vector src_pac_records, - uint32_t sink_locations, - uint32_t src_locations, - uint32_t available_contexts, - uint32_t supported_contexts) override { - LOG(WARNING) << __func__ << ": address=" << address; - UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, - pacs_client, pacs_client_id, - ascs_client, cis_intf, - ucl_callbacks, bap_alarm); - // hand over the request to stream manager - PacsDiscovery data = { - .status = status, - .bd_addr = address, - .sink_pac_records = sink_pac_records, - .src_pac_records = src_pac_records, - .sink_locations = sink_locations, - .src_locations = src_locations, - .available_contexts = available_contexts, - .supported_contexts = supported_contexts - }; - mgr->ProcessEvent(PACS_DISCOVERY_RES_EVT, &data); - } - - // ASCS client related callbacks - // to be forwarded to device specific stream manager - void OnAscsInitialized(int status, int client_id) override { - - } - - void OnConnectionState(const RawAddress& address, - bluetooth::bap::ascs::GattState state) override { - LOG(WARNING) << __func__ << ": address=" << address; - UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, - pacs_client, pacs_client_id, - ascs_client, cis_intf, - ucl_callbacks, bap_alarm); - // hand over the request to stream manager - AscsConnectionState data = { .bd_addr = address, - .state = state - }; - mgr->ProcessEvent(ASCS_CONNECTION_STATE_EVT, &data); - } - - void OnAseOpFailed(const RawAddress& address, - AseOpId ase_op_id, - std::vector status) { - - LOG(WARNING) << __func__ << ": address=" << address; - UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, - pacs_client, pacs_client_id, - ascs_client, cis_intf, - ucl_callbacks, bap_alarm); - // hand over the request to stream manager - AscsOpFailed data = { - .bd_addr = address, - .ase_op_id = ase_op_id, - .ase_list = status - }; - mgr->ProcessEvent(ASCS_ASE_OP_FAILED_EVT, &data); - } - - void OnAseState(const RawAddress& address, - AseParams ase_params) override { - LOG(WARNING) << __func__ << ": address=" << address; - UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, - pacs_client, pacs_client_id, - ascs_client, cis_intf, - ucl_callbacks, bap_alarm); - // hand over the request to stream manager - AscsState data = { - .bd_addr = address, - .ase_params = ase_params - }; - mgr->ProcessEvent(ASCS_ASE_STATE_EVT, &data); - } - - void OnSearchComplete(int status, const RawAddress& address, - std::vector sink_ase_list, - std::vector src_ase_list) override { - UstreamManager *mgr = strm_mgrs.FindorAddByAddress(address, - pacs_client, pacs_client_id, - ascs_client, cis_intf, - ucl_callbacks, bap_alarm); - // hand over the request to stream manager - AscsDiscovery data = { - .status = status, - .bd_addr = address, - .sink_ases_list = sink_ase_list, - .src_ases_list = src_ase_list - }; - mgr->ProcessEvent(ASCS_DISCOVERY_RES_EVT, &data); - } - - // cis callbacks - void OnCigState(uint8_t cig_id, CigState state) override { - std::vector *mgrs_list = strm_mgrs.GetAllManagers(); - // hand over the request to stream manager - CisGroupState data = { - .cig_id = cig_id, - .state = state - }; - - for (auto it = mgrs_list->begin(); it != mgrs_list->end(); it++) { - (*it)->ProcessEvent(CIS_GROUP_STATE_EVT, &data); - } - } - - void OnCisState(uint8_t cig_id, uint8_t cis_id, uint8_t direction, - CisState state) override { - std::vector *mgrs_list = strm_mgrs.GetAllManagers(); - // hand over the request to stream manager - CisStreamState data = { - .cig_id = cig_id, - .cis_id = cis_id, - .direction = direction, - .state = state - }; - - for (auto it = mgrs_list->begin(); it != mgrs_list->end(); it++) { - (*it)->ProcessEvent(CIS_STATE_EVT, &data); - } - } - - void OnTimeout(void* data) override { - LOG(ERROR) << __func__; - BapTimeout* data_ = (BapTimeout *)data; - UstreamManager *mgr = strm_mgrs.FindorAddByAddress(data_->bd_addr, - pacs_client, pacs_client_id, - ascs_client, cis_intf, - ucl_callbacks, bap_alarm); - // hand over the request to stream manager - mgr->ProcessEvent(BAP_TIME_OUT_EVT, data); - } - - bool Init(UcastClientCallbacks *callback) { - // register callbacks with CIS, ASCS client, PACS client - pacs_callbacks = new PacsClientCallbacksImpl; - PacsClient::Initialize(pacs_callbacks); - pacs_client = PacsClient::Get(); - - ascs_callbacks = new AscsClientCallbacksImpl; - AscsClient::Init(ascs_callbacks); - ascs_client = AscsClient::Get(); - - cis_callbacks = new CisInterfaceCallbacksImpl; - CisInterface::Initialize(cis_callbacks); - cis_intf = CisInterface::Get(); - - bap_alarm_cb = new BapAlarmCallbacksImpl; - BapAlarm::Initialize(bap_alarm_cb); - bap_alarm = BapAlarm::Get(); - - pacs_client_id = 0; - if(ucl_callbacks != nullptr) { - // flag an error - return false; - } else { - ucl_callbacks = callback; - return true; - } - } - - bool CleanUp() { - if(ucl_callbacks != nullptr) { - ucl_callbacks = nullptr; - //call clean ups for each clients(ascs, pacs, cis and bap_alarm) - LOG(ERROR) << __func__ - <<": Cleaning up pacs, ascs clients, cis intf and bap_alarm."; - pacs_client->CleanUp(pacs_client_id); - ascs_client->CleanUp(0x01); - cis_intf->CleanUp(); - bap_alarm->CleanUp(); - pacs_client = nullptr; - ascs_client = nullptr; - cis_intf = nullptr; - bap_alarm = nullptr; - // remove all stream managers and other clean ups - return true; - } else { - return false; - } - } - - private: - UcastClientCallbacks* ucl_callbacks; - UstreamManagers strm_mgrs; - PacsClient *pacs_client; - AscsClient *ascs_client; - PacsClientCallbacks *pacs_callbacks; - AscsClientCallbacks *ascs_callbacks; - CisInterface *cis_intf; - CisInterfaceCallbacks *cis_callbacks; - uint16_t pacs_client_id; - BapAlarm* bap_alarm; - BapAlarmCallbacks* bap_alarm_cb; -}; - -void UcastClient::Initialize(UcastClientCallbacks* callbacks) { - if (!instance) { - instance = new UcastClientImpl(); - instance->Init(callbacks); - } else { - LOG(ERROR) << __func__ << " 2nd client registration ignored"; - } -} - -void UcastClient::CleanUp() { - if(instance && instance->CleanUp()) { - delete instance; - instance = nullptr; - } -} - -UcastClient* UcastClient::Get() { - CHECK(instance); - return instance; -} - -} // namespace ucast -} // namespace bap -} // namespace bluetooth diff --git a/le_audio/system/bt/bta/bap/uclient_strm_mgr.cc b/le_audio/system/bt/bta/bap/uclient_strm_mgr.cc deleted file mode 100644 index ea069379ad7825f4862320542682f353189c538d..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/bap/uclient_strm_mgr.cc +++ /dev/null @@ -1,1013 +0,0 @@ -/****************************************************************************** - * - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - - -#include "bta_bap_uclient_api.h" -#include "ucast_client_int.h" -#include "bt_trace.h" - -namespace bluetooth { -namespace bap { -namespace ucast { - -using namespace std; -using bluetooth::bap::ucast::UstreamManagers; -using bluetooth::bap::ucast::UstreamManager; - -std::map state_map = { - {StreamState::DISCONNECTED, StreamTracker::kStateIdle} , - {StreamState::CONNECTING, StreamTracker::kStateConnecting}, - {StreamState::CONNECTED, StreamTracker::kStateConnected}, - {StreamState::STARTING, StreamTracker::kStateStarting}, - {StreamState::STREAMING, StreamTracker::kStateStreaming}, - {StreamState::STOPPING, StreamTracker::kStateStopping}, - {StreamState::DISCONNECTING, StreamTracker::kStateDisconnecting}, - {StreamState::RECONFIGURING, StreamTracker::kStateReconfiguring} -}; - -StreamContext *StreamContexts::FindByType(StreamType stream_type) { - auto iter = std::find_if(strm_contexts.begin(), strm_contexts.end(), - [&stream_type](StreamContext *context) { - return ((context->stream_type.type == stream_type.type) - && (context->stream_type.direction == - stream_type.direction)); - }); - - if (iter == strm_contexts.end()) { - return nullptr; - } else { - return (*iter); - } -} - -std::vector StreamContexts::FindByAseAttachedState( - uint16_t ase_id, StreamAttachedState state) { - std::vector contexts_list; - for(auto i = strm_contexts.begin(); i != strm_contexts.end();i++) { - if(static_cast((*i)->attached_state) & - static_cast(state)) { - for(auto j = (*i)->stream_ids.begin(); j != (*i)->stream_ids.end();j++) { - if(j->ase_id == ase_id) { - contexts_list.push_back(*i); - break; - } - } - } - } - return contexts_list; -} - -StreamContext *StreamContexts::FindOrAddByType(StreamType stream_type) { - auto iter = std::find_if(strm_contexts.begin(), strm_contexts.end(), - [&stream_type](StreamContext *context) { - return ((context->stream_type.type == - stream_type.type) && - (context->stream_type.direction == - stream_type.direction)); - }); - - if (iter == strm_contexts.end()) { - StreamContext *context = new StreamContext(stream_type); - strm_contexts.push_back(context); - return context; - } else { - return (*iter); - } -} - -void StreamContexts::Remove(StreamType stream_type) { - for (auto it = strm_contexts.begin(); it != strm_contexts.end();) { - if (((*it)->stream_type.type = stream_type.type) && - ((*it)->stream_type.direction = stream_type.direction)) { - delete(*it); - it = strm_contexts.erase(it); - } else { - it++; - } - } -} - -bool StreamContexts::IsAseAttached(StreamType stream_type) { - return false; - -} - -StreamContext* StreamContexts::FindByAseId(uint16_t ase_id) { - auto iter = std::find_if(strm_contexts.begin(), strm_contexts.end(), - [&ase_id](StreamContext *context) { - auto it = std::find_if(context->stream_ids.begin(), - context->stream_ids.end(), - [&ase_id](StreamIdType id) { - return (id.ase_id == ase_id); - }); - if (it != context->stream_ids.end()) { - return true; - } else return false; - - }); - - if (iter == strm_contexts.end()) { - return nullptr; - } else { - return (*iter); - } -} - -StreamTracker* StreamTrackers::FindOrAddByType(int init_state_id, - UstreamManager *strm_mgr, - std::vector *connect_streams, - std::vector *reconfig_streams, - std::vector *streams, - StreamControlType ops_type) { - bool found = false; - auto iter = stream_trackers.begin(); - while (iter != stream_trackers.end() && !found) { - if((*iter)->GetControlType() == ops_type) { - if(ops_type == StreamControlType::Connect) { - // compare connection streams - std::vector *conn_strms = (*iter)->GetConnStreams(); - if(conn_strms->size() == connect_streams->size()) { - uint8_t len = connect_streams->size(); - for (uint8_t i = 0; i < len ; i++) { - StreamConnect src = conn_strms->at(i); - StreamConnect dst = connect_streams->at(i); - if((src.stream_type.type == dst.stream_type.type) && - (src.stream_type.direction == dst.stream_type.direction)) { - LOG(WARNING) << __func__ << " StreamConnect found"; - found = true; - break; - } - } - } - } else if(ops_type == StreamControlType::Reconfig) { - // compare connection streams - std::vector *reconf_strms = (*iter)->GetReconfStreams(); - if(reconf_strms->size() == reconfig_streams->size()) { - uint8_t len = reconfig_streams->size(); - for (uint8_t i = 0; i < len ; i++) { - StreamReconfig src = reconf_strms->at(i); - StreamReconfig dst = reconfig_streams->at(i); - if((src.stream_type.type == dst.stream_type.type) && - (src.stream_type.direction == dst.stream_type.direction)) { - LOG(WARNING) << __func__ << " StreamReconfig found"; - found = true; - break; - } - } - } - } else if(ops_type != StreamControlType::None && - ops_type != StreamControlType::UpdateStream) { - // compare connection streams - std::vector *strms = (*iter)->GetStreams(); - if(strms->size() == streams->size()) { - uint8_t len = streams->size(); - for (uint8_t i = 0; i < len ; i++) { - StreamType src = strms->at(i); - StreamType dst = streams->at(i); - if((src.type == dst.type) && - (src.direction == dst.direction)) { - LOG(WARNING) << __func__ << " StreamType found"; - found = true; - break; - } - } - } - } - } - iter++; - } - - if (iter == stream_trackers.end()) { - StreamTracker *tracker = new StreamTracker(init_state_id, strm_mgr, - connect_streams, reconfig_streams, - streams, ops_type); - stream_trackers.push_back(tracker); - return tracker; - } else { - return (*iter); - } -} - -bool StreamTrackers::Remove(std::vector streams, - StreamControlType ops_type) { - return true; -} - -std::vector StreamTrackers::GetTrackersByStates( - std::vector *state_ids) { - vector trackers; - for (auto i = stream_trackers.begin(); - i != stream_trackers.end();i++) { - for (auto j = state_ids->begin(); j != state_ids->end();j++) { - if((*i)->StateId() == *j) { - LOG(WARNING) << __func__ << " tracker found"; - trackers.push_back(*i); - } - } - } - return trackers; -} - -void StreamTrackers::RemoveByStates(std::vector state_ids) { - for (auto i = stream_trackers.begin(); - i != stream_trackers.end();) { - bool found = false; - for (auto j = state_ids.begin(); j != state_ids.end();j++) { - if((*i)->StateId() == *j) { - LOG(WARNING) << __func__ << " tracker found"; - found = true; - break; - } - } - if(found) { - delete(*i); - i = stream_trackers.erase(i); - } else { - i++; - } - } -} - - -std::map > - StreamTrackers::GetTrackersByType( - std::vector *streams) { - std::vector req_types = *streams; - std::vector all_types; - std::map > tracker_and_type_map; - for (auto iter = stream_trackers.begin(); iter != stream_trackers.end(); - iter++) { - all_types.clear(); - if((*iter)->GetControlType() == StreamControlType::Connect) { - // compare connection streams - std::vector *conn_strms = (*iter)->GetConnStreams(); - uint8_t len = conn_strms->size(); - for (uint8_t i = 0; i < len ; i++) { - StreamConnect src = conn_strms->at(i); - all_types.push_back(src.stream_type); - } - } else if((*iter)->GetControlType() == StreamControlType::Reconfig) { - // compare connection streams - std::vector *reconf_strms = (*iter)->GetReconfStreams(); - uint8_t len = reconf_strms->size(); - for (uint8_t i = 0; i < len ; i++) { - StreamReconfig src = reconf_strms->at(i); - all_types.push_back(src.stream_type); - } - } else if((*iter)->GetControlType() == StreamControlType::UpdateStream) { - // compare connection streams - std::vector *update_streams = (*iter)->GetMetaUpdateStreams(); - uint8_t len = update_streams->size(); - for (uint8_t i = 0; i < len ; i++) { - StreamUpdate src = update_streams->at(i); - all_types.push_back(src.stream_type); - } - } else if((*iter)->GetControlType() != StreamControlType::None) { - // compare connection streams - std::vector *strms = (*iter)->GetStreams(); - uint8_t len = strms->size(); - for (uint8_t i = 0; i < len ; i++) { - StreamType src = strms->at(i); - all_types.push_back(src); - } - } - uint8_t count = 0; - std::vector filtered_types; - if(all_types.size() <= req_types.size()) { - filtered_types.clear(); - for (auto it = all_types.begin(); it != all_types.end(); it++) { - for (auto it_2 = req_types.begin(); it_2 != req_types.end();) { - if (((it_2)->type == it->type) && - ((it_2)->direction == it->direction)) { - filtered_types.push_back(*it_2); - tracker_and_type_map[*iter] = filtered_types; - it_2 = req_types.erase(it_2); - count++; - } else { - it_2++; - } - } - } - if(all_types.size() != count) { - LOG(ERROR) << __func__ << " invalid request"; - } - } else { - LOG(ERROR) << __func__ << " invalid request"; - } - } - if(req_types.size()) { - tracker_and_type_map[nullptr] = req_types; - } - return tracker_and_type_map; -} - - -StreamTracker *StreamTrackers::FindByStreamsType( - std::vector *streams) { - bool found = false; - auto iter = stream_trackers.begin(); - while (iter != stream_trackers.end()) { - if((*iter)->GetControlType() == StreamControlType::Connect) { - // compare connection streams - std::vector *conn_strms = (*iter)->GetConnStreams(); - if(conn_strms->size() == streams->size()) { - uint8_t len = streams->size(); - for (uint8_t i = 0; i < len ; i++) { - StreamConnect src = conn_strms->at(i); - StreamType dst = streams->at(i); - if((src.stream_type.type == dst.type) && - (src.stream_type.direction == dst.direction)) { - LOG(WARNING) << __func__ << " StreamConnect found"; - found = true; - break; - } - } - } - } else if((*iter)->GetControlType() == StreamControlType::Reconfig) { - // compare connection streams - std::vector *reconf_strms = (*iter)->GetReconfStreams(); - if(reconf_strms->size() == streams->size()) { - uint8_t len = streams->size(); - for (uint8_t i = 0; i < len ; i++) { - StreamReconfig src = reconf_strms->at(i); - StreamType dst = streams->at(i); - if((src.stream_type.type == dst.type) && - (src.stream_type.direction == dst.direction)) { - LOG(WARNING) << __func__ << " StreamReconfig found"; - found = true; - break; - } - } - } - } else if((*iter)->GetControlType() == StreamControlType::UpdateStream) { - // compare connection streams - std::vector *update_strms = (*iter)->GetMetaUpdateStreams(); - if(update_strms->size() == streams->size()) { - uint8_t len = streams->size(); - for (uint8_t i = 0; i < len ; i++) { - StreamUpdate src = update_strms->at(i); - StreamType dst = streams->at(i); - if((src.stream_type.type == dst.type) && - (src.stream_type.direction == dst.direction)) { - LOG(WARNING) << __func__ << " StreamUpdate found"; - found = true; - break; - } - } - } - } else if((*iter)->GetControlType() != StreamControlType::None) { - // compare connection streams - std::vector *strms = (*iter)->GetStreams(); - if(strms->size() == streams->size()) { - uint8_t len = streams->size(); - for (uint8_t i = 0; i < len ; i++) { - StreamType src = strms->at(i); - StreamType dst = streams->at(i); - if((src.type == dst.type) && - (src.direction == dst.direction)) { - LOG(WARNING) << __func__ << " StreamType found"; - found = true; - break; - } - } - } - } - if(found) break; - iter++; - } - - if (iter == stream_trackers.end()) { - return nullptr; - } else { - return (*iter); - } -} - -bool StreamTrackers::ChangeOpType( StreamType stream_type, - StreamControlType new_ops_type) { - return true; -} - -bool StreamTrackers::IsStreamTrackerValid(StreamTracker* tracker, - std::vector *state_ids) { - vector trackers_ = GetTrackersByStates(state_ids); - LOG(WARNING) << __func__; - if(trackers_.empty()) return false; - - for (auto it = trackers_.begin(); it != trackers_.end(); it++) { - if ((*it) == tracker) { - LOG(WARNING) << __func__ <<": Cached Tracker is valid"; - return true; - } - } - return false; -} - -bool UstreamManager::PushEventToTracker(uint32_t event, void *p_data, - std::vector *state_ids) { - vector trackers = stream_trackers.GetTrackersByStates( - state_ids); - if(trackers.empty()) return false; - - for (auto it = trackers.begin(); it != trackers.end(); it++) { - (*it)->ProcessEvent(event, p_data); - } - return true; -} - - -std::map > UstreamManager::SplitContextOnState( - std::vector *streams) { - StreamContexts *contexts = GetStreamContexts(); - std::vector req_types = *streams; - std::map > state_and_type_map; - - for (auto it = req_types.begin(); it != req_types.end();) { - StreamContext *context = contexts->FindOrAddByType(*it); - if (context) { - int state = state_map[context->stream_state]; - state_and_type_map[state].push_back(*it); - it = req_types.erase(it); - } else { - it++; - } - } - return state_and_type_map; -} - -void UstreamManager::ProcessEvent(uint32_t event, void *p_data) { - LOG(WARNING) << __func__ <<": Event: " << GetEventName(event) - <<", bt_addr: " << GetAddress(); - - std::vector stable_state_ids = { - StreamTracker::kStateConnected, - StreamTracker::kStateStreaming, - StreamTracker::kStateIdle - }; - - std::vector transient_state_ids = { - StreamTracker::kStateConnecting, - StreamTracker::kStateReconfiguring, - StreamTracker::kStateDisconnecting, - StreamTracker::kStateStarting, - StreamTracker::kStateStopping, - StreamTracker::kStateUpdating, - }; - StreamContexts *contexts = GetStreamContexts(); - - switch (event) { - - case BAP_CONNECT_REQ_EVT: { - BapConnect *evt_data = (BapConnect *) p_data; - std::vector conn_streams = evt_data->streams; - LOG(WARNING) << __func__ << ": size: " << conn_streams.size(); - - for (auto it = conn_streams.begin(); it != conn_streams.end();) { - StreamContext *context = contexts->FindOrAddByType(it->stream_type); - if(context && context->stream_state != StreamState::DISCONNECTED) { - LOG(WARNING) << __func__ << ": Stream is not in disconnected state"; - it = conn_streams.erase(it); - } else { - it++; - } - } - - if(!conn_streams.size()) { - LOG(ERROR) << __func__ << ": All streams are not in disconnected state"; - break; - } - - // validate the combinations media Tx or voice TX|RX - StreamTracker *tracker = stream_trackers.FindOrAddByType( - StreamTracker::kStateIdle, - this, &conn_streams, nullptr, nullptr, - StreamControlType::Connect); - - if(tracker) { - tracker->Start(); - tracker->ProcessEvent(event, p_data); - } - } break; - - case BAP_DISCONNECT_REQ_EVT: { - BapDisconnect *evt_data = (BapDisconnect *) p_data; - std::vector disc_streams = evt_data->streams; - BapDisconnect int_evt_data; - - for (auto it = disc_streams.begin(); it != disc_streams.end();) { - StreamContext *context = contexts->FindOrAddByType(*it); - if(!context || context->stream_state == StreamState::DISCONNECTED) { - LOG(WARNING) << __func__ << " Stream is already disconnected"; - it = disc_streams.erase(it); - } else { - it++; - } - } - - if(!disc_streams.size()) { - LOG(ERROR) << __func__ << " All streams are already disconnected"; - break; - } - - LOG(WARNING) << __func__ << " disc streams size " << disc_streams.size(); - - // validate the combinations media Tx or voice TX|RX - std::map > - tracker_and_type_list = - stream_trackers.GetTrackersByType(&disc_streams); - - - // check if all streams disconnection or subset of streams - // create the new tracker - for (auto itr = tracker_and_type_list.begin(); - itr != tracker_and_type_list.end(); itr++) { - if(itr->first == nullptr) { - std::map > - list = SplitContextOnState(&itr->second); - for (auto itr_2 = list.begin(); itr_2 != list.end(); itr_2++) { - StreamTracker *tracker = stream_trackers.FindOrAddByType( - itr_2->first, - this, nullptr, nullptr, &itr_2->second, - StreamControlType::Disconnect); - LOG(ERROR) << __func__ << " new tracker start "; - tracker->Start(); - int_evt_data.streams = itr_2->second; - tracker->ProcessEvent(event, &int_evt_data); - } - } else { - LOG(ERROR) << __func__ << " existing tracker start "; - StreamTracker *tracker = itr->first; - int_evt_data.streams = itr->second; - tracker->ProcessEvent(event, &int_evt_data); - } - } - } break; - - case BAP_START_REQ_EVT: { - BapStart *evt_data = (BapStart *) p_data; - std::vector start_streams = evt_data->streams; - LOG(WARNING) << __func__ << " start streams size " << start_streams.size(); - - for (auto it = start_streams.begin(); it != start_streams.end();) { - StreamContext *context = contexts->FindOrAddByType(*it); - if(!context || context->stream_state != StreamState::CONNECTED) { - LOG(WARNING) << __func__ << " Stream is not in connected state"; - it = start_streams.erase(it); - } else { - it++; - } - } - - if(!start_streams.size()) { - LOG(WARNING) << __func__ << " Not eligible for stream start"; - break; - } - - // validate the combinations media Tx or voice TX|RX - StreamTracker *tracker = stream_trackers.FindByStreamsType( - &start_streams); - // create new tracker - if(tracker == nullptr) { - StreamTracker *tracker = stream_trackers.FindOrAddByType( - StreamTracker::kStateConnected, - this, nullptr, nullptr, &start_streams, - StreamControlType::Start); - tracker->Start(); - tracker->ProcessEvent(event, p_data); - } else { - tracker->ProcessEvent(event, p_data); - } - } break; - - case BAP_STOP_REQ_EVT: { - BapStop *evt_data = (BapStop *) p_data; - std::vector stop_streams = evt_data->streams; - LOG(WARNING) << __func__ << " stop streams size " << stop_streams.size(); - - for (auto it = stop_streams.begin(); it != stop_streams.end();) { - StreamContext *context = contexts->FindOrAddByType(*it); - if(!context || (context->stream_state != StreamState::STREAMING && - context->stream_state != StreamState::STARTING)) { - LOG(WARNING) << __func__ << " Stream is not in streaming state"; - it = stop_streams.erase(it); - } else { - it++; - } - } - - if(!stop_streams.size()) { - LOG(WARNING) << __func__ << " Not eligible for stream stop"; - break; - } - - StreamTracker *tracker = stream_trackers.FindByStreamsType( - &stop_streams); - // create the new tracker - if(tracker == nullptr) { - // validate the combinations media Tx or voice TX|RX - StreamTracker *tracker = stream_trackers.FindOrAddByType( - StreamTracker::kStateStreaming, - this, nullptr, nullptr, &stop_streams, - StreamControlType::Stop); - tracker->Start(); - tracker->ProcessEvent(event, p_data); - } else { - tracker->ProcessEvent(event, p_data); - } - } break; - - case BAP_STREAM_UPDATE_REQ_EVT: { - BapStreamUpdate *evt_data = (BapStreamUpdate *) p_data; - std::vector update_streams = evt_data->update_streams; - std::vector streams; - - for (auto it = update_streams.begin(); it != update_streams.end();) { - StreamContext *context = contexts->FindOrAddByType(it->stream_type); - if(!context || (context->stream_state != StreamState::STREAMING && - context->stream_state != StreamState::STARTING)) { - LOG(WARNING) << __func__ << " Stream is not in proper state"; - it = update_streams.erase(it); - } else { - it++; - } - } - - if(!update_streams.size()) { - LOG(WARNING) << __func__ << " All streams are not in proper state"; - break; - } - - for (auto it = update_streams.begin(); - it != update_streams.end(); it++) { - StreamType type = it->stream_type; - streams.push_back(type); - } - - LOG(WARNING) << __func__ << " update streams size " << streams.size(); - - StreamTracker *tracker = stream_trackers.FindByStreamsType( - &streams); - // create the new tracker - if(tracker == nullptr) { - // validate the combinations media Tx or voice TX|RX - StreamTracker *tracker = stream_trackers.FindOrAddByType( - StreamTracker::kStateStreaming, - this, nullptr, nullptr, nullptr, - StreamControlType::UpdateStream); - tracker->Start(); - tracker->ProcessEvent(event, p_data); - } else { - tracker->ProcessEvent(event, p_data); - } - } break; - - case BAP_RECONFIG_REQ_EVT: { - BapReconfig *evt_data = (BapReconfig *) p_data; - std::vector reconf_streams = evt_data->streams; - std::vector streams; - - for (auto it = reconf_streams.begin(); it != reconf_streams.end();) { - StreamContext *context = contexts->FindOrAddByType(it->stream_type); - if(!context || context->stream_state != StreamState::CONNECTED) { - LOG(WARNING) << __func__ << " Stream is not in Connected state"; - it = reconf_streams.erase(it); - } else { - it++; - } - } - - if(!reconf_streams.size()) { - LOG(WARNING) << __func__ << " All streams are not connected"; - break; - } - - for (auto it = reconf_streams.begin(); - it != reconf_streams.end(); it++) { - StreamType type = it->stream_type; - streams.push_back(type); - } - - LOG(WARNING) << __func__ << " reconf streams size " << streams.size(); - - StreamTracker *tracker = stream_trackers.FindByStreamsType( - &streams); - // create the new tracker - if(tracker == nullptr) { - // validate the combinations media Tx or voice TX|RX - StreamTracker *tracker = stream_trackers.FindOrAddByType( - StreamTracker::kStateConnected, - this, nullptr, &reconf_streams, nullptr, - StreamControlType::Reconfig); - tracker->Start(); - tracker->ProcessEvent(event, p_data); - } else { - tracker->ProcessEvent(event, p_data); - } - } break; - - case PACS_CONNECTION_STATE_EVT: { - PacsConnectionState *pacs_state = (PacsConnectionState *) p_data; - UpdatePacsState(pacs_state->state); - int state = StreamTracker::kStateIdle; - if (pacs_state->state != ConnectionState::DISCONNECTED) { - if(PushEventToTracker(event, p_data, &transient_state_ids)) { - break; - } else { - - std::vector *context_list = contexts->GetAllContexts(); - std::vector streams; - - for (auto it = context_list->begin(); it != context_list->end(); it++) { - if((*it)->stream_state != StreamState::DISCONNECTED) { - streams.push_back((*it)->stream_type); - state = state_map[(*it)->stream_state]; - } - } - - StreamTracker *tracker = stream_trackers.FindByStreamsType( - &streams); - // create the new tracker - if(tracker == nullptr) { - // validate the combinations media Tx or voice TX|RX - StreamTracker *tracker = stream_trackers.FindOrAddByType( - state, - this, nullptr, nullptr, &streams, - StreamControlType::Disconnect); - tracker->Start(); - tracker->ProcessEvent(event, p_data); - } else { - tracker->ProcessEvent(event, p_data); - } - } - } else { - - std::vector *context_list = contexts->GetAllContexts(); - std::vector disc_streams; - - for (auto it = context_list->begin(); it != context_list->end(); it++) { - if((*it)->stream_state != StreamState::DISCONNECTED) { - disc_streams.push_back((*it)->stream_type); - } - } - - LOG(WARNING) << __func__ << ": size: " << disc_streams.size(); - - // validate the combinations media Tx or voice TX|RX - std::map > - tracker_and_type_list = - stream_trackers.GetTrackersByType(&disc_streams); - - // check if all streams disconnection or subset of streams - // create the new tracker - for (auto itr = tracker_and_type_list.begin(); - itr != tracker_and_type_list.end(); itr++) { - if(itr->first == nullptr) { - std::map > - list = SplitContextOnState(&itr->second); - for (auto itr_2 = list.begin(); itr_2 != list.end(); itr_2++) { - StreamTracker *tracker = stream_trackers.FindOrAddByType( - itr_2->first, - this, nullptr, nullptr, &itr_2->second, - StreamControlType::Disconnect); - LOG(ERROR) << __func__ << " new tracker start "; - tracker->Start(); - tracker->ProcessEvent(event, p_data); - } - } else { - LOG(ERROR) << __func__ << " existing tracker start "; - StreamTracker *tracker = itr->first; - tracker->ProcessEvent(event, p_data); - } - } - } - } break; - - case PACS_AUDIO_CONTEXT_RES_EVT: { - // update the same event to upper layers also - PacsAvailableContexts *contexts = (PacsAvailableContexts *) p_data; - ucl_callbacks->OnStreamAvailable( - address, - (contexts->available_contexts >> 16), - (contexts->available_contexts & 0xFFFF)); - std::vector state_ids = { StreamTracker::kStateStarting, - StreamTracker::kStateUpdating}; - PushEventToTracker(event, p_data, &state_ids); - } break; - - case PACS_DISCOVERY_RES_EVT: - case ASCS_DISCOVERY_RES_EVT: { - // validate the combinations media Tx or voice TX|RX - std::vector state_ids = { StreamTracker::kStateConnecting, - StreamTracker::kStateReconfiguring }; - PushEventToTracker(event, p_data, &state_ids); - } break; - - case ASCS_CONNECTION_STATE_EVT: { - AscsConnectionState *ascs_state = (AscsConnectionState *) p_data; - UpdateAscsState(ascs_state->state); - PushEventToTracker(event, p_data, &transient_state_ids); - } break; - - case ASCS_ASE_OP_FAILED_EVT: { - if(PushEventToTracker(event, p_data, &transient_state_ids)) { - break; - } - } break; - - case ASCS_ASE_STATE_EVT: { - if(PushEventToTracker(event, p_data, &transient_state_ids)) { - break; - } - // create strm trackers based on ase ID and push it to - // newly created tracker. - // TODO Handle Releasing , disabling, codec configured states - // initiated from remote device - - AscsState *ascs = ((AscsState *) p_data); - UcastAudioStream *audio_stream = nullptr; - // find out the stream for the given ase id - uint8_t ase_id = ascs->ase_params.ase_id; - std::vector streams; - int state = StreamTracker::kStateIdle; - - UcastAudioStreams *audio_strms = GetAudioStreams(); - audio_stream = audio_strms->FindByAseId(ase_id); - if(audio_stream) { - StreamType type = { - .type = audio_stream->audio_context, - .direction = audio_stream->direction - }; - streams.push_back(type); - state = audio_stream->overall_state; - } - - LOG(WARNING) << __func__ << " size " << streams.size(); - - if (ascs->ase_params.ase_state == ascs::ASE_STATE_RELEASING) { - - StreamTracker *tracker = stream_trackers.FindOrAddByType( - state, - this, nullptr, nullptr, &streams, - StreamControlType::Disconnect); - tracker->Start(); - tracker->ProcessEvent(event, p_data); - } else if (ascs->ase_params.ase_state == ascs::ASE_STATE_DISABLING) { - - StreamTracker *tracker = stream_trackers.FindOrAddByType( - state, - this, nullptr, nullptr, &streams, - StreamControlType::Stop); - tracker->Start(); - tracker->ProcessEvent(event, p_data); - } else if (ascs->ase_params.ase_state == - ascs::ASE_STATE_CODEC_CONFIGURED) { - // TODO reconfig from remote device - } else if (ascs->ase_params.ase_state == - ascs::ASE_STATE_QOS_CONFIGURED) { - // this can happen when CIS is lost and detected on remote side - // first so it will immediately transition to QOS configured. - StreamTracker *tracker = stream_trackers.FindOrAddByType( - state, - this, nullptr, nullptr, &streams, - StreamControlType::Stop); - tracker->Start(); - tracker->ProcessEvent(event, p_data); - } - } break; - - case CIS_GROUP_STATE_EVT: { - // validate the combinations media Tx or voice TX|RX - std::vector state_ids = { StreamTracker::kStateStarting, - StreamTracker::kStateStopping, - StreamTracker::kStateDisconnecting }; - PushEventToTracker(event, p_data, &state_ids); - } break; - - case CIS_STATE_EVT: { - CisStreamState *data = (CisStreamState *) p_data; - - if(PushEventToTracker(event, p_data, &transient_state_ids)) { - break; - } - - // find out the stream for the given ase id - int state = StreamTracker::kStateIdle; - std::vector streams; - - UcastAudioStreams *audio_strms = GetAudioStreams(); - std::vector cis_streams = audio_strms->FindByCisId( - data->cig_id, data->cis_id); - - - if(cis_streams.empty()) break; - - for (auto it = cis_streams.begin(); it != cis_streams.end(); it++) { - StreamType type = { - .type = (*it)->audio_context, - .direction = (*it)->direction - }; - streams.push_back(type); - state = (*it)->overall_state; - } - - LOG(WARNING) << __func__ << " size " << streams.size(); - - // create strm trackers based on CIS ID and push it to - // newly created tracker. - // CIS disconnected - if(data->state == CisState::READY) { - StreamTracker *tracker = stream_trackers.FindOrAddByType( - state, - this, nullptr, nullptr, &streams, - StreamControlType::Stop); - tracker->Start(); - tracker->ProcessEvent(event, p_data); - } - } break; - - case BAP_TIME_OUT_EVT: { - BapTimeout* evt_data = (BapTimeout*) p_data; - - //Get Cached tracker and check if it is valid - if (stream_trackers.IsStreamTrackerValid(evt_data->tracker, - &transient_state_ids)) { - PushEventToTracker(event, p_data, &transient_state_ids); - } else { - LOG(WARNING) << __func__ << ": Tracker is not valid "; - } - } break; - - default: - break; - } - - // look for all stream trackers which are moved to stable states - // like connected, streaming, idle, and destroy those trackers here - stream_trackers.RemoveByStates(stable_state_ids); -} - -// TODO to introduce a queue for serializing the Audio stream establishment -UstreamManager* UstreamManagers::FindByAddress(const RawAddress& address) { - auto iter = std::find_if(strm_mgrs.begin(), strm_mgrs.end(), - [&address](UstreamManager *strm_mgr) { - return strm_mgr->GetAddress() == address; - }); - - return (iter == strm_mgrs.end()) ? nullptr : (*iter); -} - -UstreamManager* UstreamManagers::FindorAddByAddress(const RawAddress& address, - PacsClient *pacs_client, uint16_t pacs_client_id, - AscsClient *ascs_client, CisInterface *cis_intf, - UcastClientCallbacks* ucl_callbacks, - BapAlarm *bap_alarm) { - auto iter = std::find_if(strm_mgrs.begin(), strm_mgrs.end(), - [&address](UstreamManager *strm_mgr) { - return strm_mgr->GetAddress() == address; - }); - - if (iter == strm_mgrs.end()) { - UstreamManager *strm_mgr = new UstreamManager(address, pacs_client, - pacs_client_id, ascs_client, cis_intf, - ucl_callbacks, bap_alarm); - strm_mgrs.push_back(strm_mgr); - return strm_mgr; - } else { - return (*iter); - } -} - -std::vector *UstreamManagers::GetAllManagers() { - return &strm_mgrs; - -} - -void UstreamManagers::Remove(const RawAddress& address) { - for (auto it = strm_mgrs.begin(); it != strm_mgrs.end();) { - if ((*it)->GetAddress() == address) { - delete(*it); - it = strm_mgrs.erase(it); - } else { - it++; - } - } -} - -} // namespace ucast -} // namespace bap -} // namespace bluetooth diff --git a/le_audio/system/bt/bta/bap/uclient_strm_tracker.cc b/le_audio/system/bt/bta/bap/uclient_strm_tracker.cc deleted file mode 100644 index 3272e5633668f1816ea2ec19592f2e5086ef900c..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/bap/uclient_strm_tracker.cc +++ /dev/null @@ -1,4001 +0,0 @@ -/****************************************************************************** - * - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - - -#include "bta_bap_uclient_api.h" -#include "ucast_client_int.h" -#include "bt_trace.h" -#include "btif/include/btif_bap_codec_utils.h" -#include "osi/include/properties.h" -#include "uclient_alarm.h" - -namespace bluetooth { -namespace bap { -namespace ucast { - -using bluetooth::bap::pacs::CodecIndex; -using bluetooth::bap::pacs::CodecBPS; -using bluetooth::bap::pacs::CodecConfig; -using bluetooth::bap::pacs::ConnectionState; -using bluetooth::bap::pacs::CodecSampleRate; -using bluetooth::bap::pacs::CodecChannelMode; -using bluetooth::bap::pacs::PacsClient; -using bluetooth::bap::cis::CisInterface; -using bluetooth::bap::ascs::AseCodecConfigOp; -using bluetooth::bap::ascs::AseQosConfigOp; -using bluetooth::bap::ascs::AseEnableOp; -using bluetooth::bap::ascs::AseStartReadyOp; -using bluetooth::bap::ascs::AseStopReadyOp; -using bluetooth::bap::ascs::AseDisableOp; -using bluetooth::bap::ascs::AseReleaseOp; -using bluetooth::bap::ascs::AseUpdateMetadataOp; - -using cis::IsoHciStatus; -using bluetooth::bap::alarm::BapAlarm; - -using bluetooth::bap::ucast::CONTENT_TYPE_MEDIA; -using bluetooth::bap::ucast::CONTENT_TYPE_CONVERSATIONAL; -using bluetooth::bap::ucast::CONTENT_TYPE_UNSPECIFIED; -using bluetooth::bap::ucast::CONTENT_TYPE_GAME; - -constexpr uint8_t LTV_TYPE_SAMP_FREQ = 0X01; -constexpr uint8_t LTV_TYPE_FRAME_DUR = 0x02; -constexpr uint8_t LTV_TYPE_CHNL_ALLOC = 0x03; -constexpr uint8_t LTV_TYPE_OCTS_PER_FRAME = 0X04; -constexpr uint8_t LTV_TYPE_FRAMES_PER_SDU = 0X05; -constexpr uint8_t LTV_TYPE_STRM_AUDIO_CONTEXTS = 0x02; - -constexpr uint8_t LTV_LEN_SAMP_FREQ = 0X02; -constexpr uint8_t LTV_LEN_FRAME_DUR = 0x02; -constexpr uint8_t LTV_LEN_CHNL_ALLOC = 0x05; -constexpr uint8_t LTV_LEN_OCTS_PER_FRAME = 0X03; -constexpr uint8_t LTV_LEN_FRAMES_PER_SDU = 0X02; -constexpr uint8_t LTV_LEN_STRM_AUDIO_CONTEXTS = 0x03; - -constexpr uint8_t LTV_VAL_SAMP_FREQ_8K = 0X01; -//constexpr uint8_t LTV_VAL_SAMP_FREQ_11K = 0X02; -constexpr uint8_t LTV_VAL_SAMP_FREQ_16K = 0X03; -//constexpr uint8_t LTV_VAL_SAMP_FREQ_22K = 0X04; -constexpr uint8_t LTV_VAL_SAMP_FREQ_24K = 0X05; -constexpr uint8_t LTV_VAL_SAMP_FREQ_32K = 0X06; -constexpr uint8_t LTV_VAL_SAMP_FREQ_441K = 0X07; -constexpr uint8_t LTV_VAL_SAMP_FREQ_48K = 0X08; -constexpr uint8_t LTV_VAL_SAMP_FREQ_882K = 0X09; -constexpr uint8_t LTV_VAL_SAMP_FREQ_96K = 0X0A; -constexpr uint8_t LTV_VAL_SAMP_FREQ_176K = 0X0B; -constexpr uint8_t LTV_VAL_SAMP_FREQ_192K = 0X0C; -//constexpr uint8_t LTV_VAL_SAMP_FREQ_384K = 0X0D; - -constexpr uint8_t LC3_CODEC_ID = 0x06; -constexpr uint8_t ASCS_CLIENT_ID = 0x01; - -constexpr uint8_t TGT_LOW_LATENCY = 0x01; -constexpr uint8_t TGT_BAL_LATENCY = 0x02; -constexpr uint8_t TGT_HIGH_RELIABLE = 0x03; - -std::map freq_to_ltv_map = { - {CodecSampleRate::CODEC_SAMPLE_RATE_8000, LTV_VAL_SAMP_FREQ_8K }, - {CodecSampleRate::CODEC_SAMPLE_RATE_16000, LTV_VAL_SAMP_FREQ_16K }, - {CodecSampleRate::CODEC_SAMPLE_RATE_24000, LTV_VAL_SAMP_FREQ_24K }, - {CodecSampleRate::CODEC_SAMPLE_RATE_32000, LTV_VAL_SAMP_FREQ_32K }, - {CodecSampleRate::CODEC_SAMPLE_RATE_44100, LTV_VAL_SAMP_FREQ_441K }, - {CodecSampleRate::CODEC_SAMPLE_RATE_48000, LTV_VAL_SAMP_FREQ_48K }, - {CodecSampleRate::CODEC_SAMPLE_RATE_88200, LTV_VAL_SAMP_FREQ_882K }, - {CodecSampleRate::CODEC_SAMPLE_RATE_96000, LTV_VAL_SAMP_FREQ_96K }, - {CodecSampleRate::CODEC_SAMPLE_RATE_176400, LTV_VAL_SAMP_FREQ_176K }, - {CodecSampleRate::CODEC_SAMPLE_RATE_192000, LTV_VAL_SAMP_FREQ_192K } -}; - -std::list directions = { - cis::DIR_FROM_AIR, - cis::DIR_TO_AIR -}; - -std::vector locations = { - AUDIO_LOC_LEFT, - AUDIO_LOC_RIGHT -}; - -// common functions used from Stream tracker state Handlers -uint8_t StreamTracker::ChooseBestCodec(StreamType stream_type, - std::vector *codec_qos_configs, - PacsDiscovery *pacs_discovery) { - bool codec_found = false; - uint8_t index = 0; - // check the stream direction, based on direction look for - // matching record from preferred list of upper layer and - // remote device sink or src pac records - std::vector *pac_records = nullptr; - if(stream_type.direction == ASE_DIRECTION_SINK) { - pac_records = &pacs_discovery->sink_pac_records; - } else if(stream_type.direction == ASE_DIRECTION_SRC) { - pac_records = &pacs_discovery->src_pac_records; - } - - if (!pac_records) { - LOG(ERROR) << __func__ << "pac_records is null"; - return 0xFF; - } - DeviceType dev_type = strm_mgr_->GetDevType(); - for (auto i = codec_qos_configs->begin(); i != codec_qos_configs->end() - ; i++, index++) { - if(dev_type == DeviceType::EARBUD || - dev_type == DeviceType::HEADSET_STEREO) { - if((*i).qos_config.ascs_configs.size() != 1) continue; - } else if(dev_type == DeviceType::HEADSET_SPLIT_STEREO) { - if((*i).qos_config.ascs_configs.size() != 2) continue; - } - for (auto j = pac_records->begin(); - j != pac_records->end();j++) { - CodecConfig *src = &((*i).codec_config); - CodecConfig *dst = &(*j); - if (IsCodecConfigEqual(src,dst)) { - LOG(WARNING) << __func__ << ": Checking for matching Codec"; - if (GetLc3QPreference(src) && - GetCapaVendorMetaDataLc3QPref(dst)) { - LOG(INFO) << __func__ << ": Matching Codec LC3Q Found " - << ", for direction: " << loghex(stream_type.direction); - uint8_t lc3qVer = GetCapaVendorMetaDataLc3QVer(dst); - UpdateVendorMetaDataLc3QPref(src, true); - UpdateVendorMetaDataLc3QVer(src, lc3qVer); - } else { - LOG(INFO) << __func__ << ": LC3Q not prefered, going with LC3 " - << "for direction: " << loghex(stream_type.direction); - } - codec_found = true; - break; - } - } - if(codec_found) break; - } - if(codec_found) return index; - else return 0xFF; -} - -// fine tuning the QOS params (RTN, MTL, PD) based on -// remote device preferences -bool StreamTracker::ChooseBestQos(QosConfig *src_config, - ascs::AseCodecConfigParams *rem_qos_prefs, - QosConfig *dst_config, - int stream_state, - uint8_t stream_direction) { - uint8_t final_rtn = 0xFF; - uint16_t final_mtl = 0xFFFF; - uint32_t req_pd = (src_config->ascs_configs[0].presentation_delay[0] | - src_config->ascs_configs[0].presentation_delay[1] << 8 | - src_config->ascs_configs[0].presentation_delay[2] << 16); - - uint32_t rem_pd_min = (rem_qos_prefs->pd_min[0] | - rem_qos_prefs->pd_min[1] << 8 | - rem_qos_prefs->pd_min[2] << 16); - - uint32_t rem_pd_max = (rem_qos_prefs->pd_max[0] | - rem_qos_prefs->pd_max[1] << 8 | - rem_qos_prefs->pd_max[2] << 16); - - uint32_t rem_pref_pd_min = (rem_qos_prefs->pref_pd_min[0] | - rem_qos_prefs->pref_pd_min[1] << 8 | - rem_qos_prefs->pref_pd_min[2] << 16); - - uint32_t rem_pref_pd_max = (rem_qos_prefs->pref_pd_max[0] | - rem_qos_prefs->pref_pd_max[1] << 8 | - rem_qos_prefs->pref_pd_max[2] << 16); - - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - std::vector streams = audio_strms->FindByCigId( - src_config->ascs_configs[0].cig_id, - stream_state); - - // check if the RTN and MTL is with in the limits - if(stream_direction == ASE_DIRECTION_SINK) { - if(src_config->cis_configs[0].rtn_m_to_s > rem_qos_prefs->pref_rtn) { - final_rtn = rem_qos_prefs->pref_rtn; - } - if(src_config->cig_config.max_tport_latency_m_to_s > rem_qos_prefs->mtl) { - final_mtl = rem_qos_prefs->mtl; - } - } else if(stream_direction == ASE_DIRECTION_SRC) { - if(src_config->cis_configs[0].rtn_s_to_m > rem_qos_prefs->pref_rtn) { - final_rtn = rem_qos_prefs->pref_rtn; - } - if(src_config->cig_config.max_tport_latency_s_to_m > rem_qos_prefs->mtl) { - final_mtl = rem_qos_prefs->mtl; - } - } - - LOG(INFO) << __func__ << " req_pd: " << loghex(req_pd) - << " rem_pd_min: " << loghex(rem_pd_min) - << " rem_pd_max: " << loghex(rem_pd_max) - << " rem_pref_pd_min: " << loghex(rem_pref_pd_min) - << " rem_pref_pd_max: " << loghex(rem_pref_pd_max); - - // check if PD is within the limits - if(rem_pref_pd_min && rem_pref_pd_max) { - if(req_pd < rem_pref_pd_min) { - memcpy(&dst_config->ascs_configs[0].presentation_delay, - &rem_qos_prefs->pref_pd_min, - sizeof(dst_config->ascs_configs[0].presentation_delay)); - } else if(req_pd > rem_pref_pd_max) { - memcpy(&dst_config->ascs_configs[0].presentation_delay, - &rem_qos_prefs->pref_pd_max, - sizeof(dst_config->ascs_configs[0].presentation_delay)); - } - } else { - if(req_pd != rem_pd_min) { - memcpy(&dst_config->ascs_configs[0].presentation_delay, - &rem_qos_prefs->pd_min, - sizeof(dst_config->ascs_configs[0].presentation_delay)); - } - } - - // check if anything to be updated for all streams - if(final_rtn == 0xFF && final_mtl == 0XFFFF) { - LOG(WARNING) << __func__ << " No fine tuning for QOS params"; - return true; - } else if(final_rtn != 0xFF) { - LOG(WARNING) << __func__ << " Updated RTN to " << loghex(final_rtn); - } else if(final_mtl != 0XFFFF) { - LOG(WARNING) << __func__ << " Updated MTL to " << loghex(final_mtl); - } - - for (auto i = streams.begin(); i != streams.end();i++) { - UcastAudioStream *stream = (*i); - if(stream_direction == ASE_DIRECTION_SINK) { - if(final_mtl != 0xFFFF) { - stream->qos_config.cig_config.max_tport_latency_m_to_s = final_mtl; - } - if(final_rtn != 0xFF) { - for (auto it = stream->qos_config.cis_configs.begin(); - it != stream->qos_config.cis_configs.end(); it++) { - (*it).rtn_m_to_s = final_rtn; - } - } - } else if(stream_direction == ASE_DIRECTION_SRC) { - if(final_mtl != 0xFFFF) { - stream->qos_config.cig_config.max_tport_latency_s_to_m = final_mtl; - } - if(final_rtn != 0xFF) { - for (auto it = stream->qos_config.cis_configs.begin(); - it != stream->qos_config.cis_configs.end(); it++) { - (*it).rtn_s_to_m = final_rtn; - } - } - } - } - return true; -} - -bool StreamTracker::HandlePacsConnectionEvent(void *p_data) { - PacsConnectionState *pacs_state = (PacsConnectionState *) p_data; - if(pacs_state->state == ConnectionState::CONNECTED) { - LOG(INFO) << __func__ << " PACS server connected"; - } else if(pacs_state->state == ConnectionState::DISCONNECTED) { - HandleInternalDisconnect(false); - } - return true; -} - -bool StreamTracker::HandlePacsAudioContextEvent( - PacsAvailableContexts *pacs_contexts) { - std::vector *update_streams = GetMetaUpdateStreams(); - uint8_t contexts_supported = 0; - - // check if supported audio contexts has required contexts - for(auto it = update_streams->begin(); it != update_streams->end(); it++) { - if(it->update_type == StreamUpdateType::STREAMING_CONTEXT) { - if(it->stream_type.direction == ASE_DIRECTION_SINK) { - if(it->update_value & pacs_contexts->available_contexts) { - contexts_supported++; - } - } else if(it->stream_type.direction == ASE_DIRECTION_SRC) { - if((static_cast(it->update_value) << 16) & - pacs_contexts->available_contexts) { - contexts_supported++; - } - } - } - } - - if(contexts_supported != update_streams->size()) { - LOG(ERROR) << __func__ << ": No Matching available Contexts found"; - return false; - } else { - return true; - } -} - -bool StreamTracker::HandleCisEventsInStreaming(void* p_data) { - CisStreamState *data = (CisStreamState *) p_data; - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - if(data->state == CisState::READY) { - for(auto it = directions.begin(); it != directions.end(); ++it) { - if(data->direction & *it) { - // find out the stream here - UcastAudioStream *stream = audio_strms->FindByCisIdAndDir - (data->cig_id, data->cis_id, *it); - if(stream) { - stream->cis_state = data->state; - stream->cis_pending_cmd = CisPendingCmd::NONE; - } - } - } - TransitionTo(StreamTracker::kStateStopping); - } - return true; -} - -bool StreamTracker::HandleAscsConnectionEvent(void *p_data) { - AscsConnectionState *ascs_state = (AscsConnectionState *) p_data; - if(ascs_state->state == GattState::CONNECTED) { - LOG(INFO) << __func__ << "ASCS server connected"; - } else if(ascs_state->state == GattState::DISCONNECTED) { - // make all streams ASE state ot idle so that further processing - // can happen - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - std::vector *strms_list = audio_strms->GetAllStreams(); - - for (auto it = strms_list->begin(); it != strms_list->end(); it++) { - (*it)->ase_state = ascs::ASE_STATE_IDLE; - (*it)->ase_pending_cmd = AscsPendingCmd::NONE; - (*it)->overall_state = StreamTracker::kStateIdle; - } - HandleInternalDisconnect(false); - } - return true; -} - -bool StreamTracker::ValidateAseUpdate(void* p_data, - IntStrmTrackers *int_strm_trackers, - int exp_strm_state) { - AscsState *ascs = ((AscsState *) p_data); - - uint8_t ase_id = ascs->ase_params.ase_id; - - // check if current stream tracker is interested in this ASE update - if(int_strm_trackers->FindByAseId(ase_id) - == nullptr) { - LOG(INFO) << __func__ << "Not intended for this tracker"; - return false; - } - - // find out the stream for the given ase id - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - - UcastAudioStream *stream = audio_strms->FindByAseId(ase_id); - - LOG(INFO) << __func__ << ": Streams Size = " << audio_strms->size() - << ": ASE Id = " << loghex(ase_id); - - if (stream == nullptr || stream->overall_state != exp_strm_state) { - LOG(WARNING) << __func__ << "No Audio Stream found"; - return false; - } - - stream->ase_state = ascs->ase_params.ase_state; - stream->ase_params = ascs->ase_params; - stream->ase_pending_cmd = AscsPendingCmd::NONE; - return true; -} - -bool StreamTracker::HandleRemoteDisconnect(uint32_t event, - void* p_data, int cur_state) { - UpdateControlType(StreamControlType::Disconnect); - std::vector streams; - - switch(cur_state) { - case StreamTracker::kStateConnecting: { - std::vector *conn_streams = GetConnStreams(); - - for (auto it = conn_streams->begin(); it != conn_streams->end(); it++) { - StreamType type = it->stream_type; - streams.push_back(type); - } - UpdateStreams(&streams); - } break; - case StreamTracker::kStateReconfiguring: { - std::vector *reconf_streams = GetReconfStreams(); - - for (auto it = reconf_streams->begin(); - it != reconf_streams->end(); it++) { - StreamType type = it->stream_type; - streams.push_back(type); - } - UpdateStreams(&streams); - } break; - } - - // update the state to disconnecting - TransitionTo(StreamTracker::kStateDisconnecting); - ProcessEvent(event, p_data); - return true; -} - -bool StreamTracker::StreamCanbeDisconnected(StreamContext *cur_context, - uint8_t ase_id) { - bool can_be_disconnected = false; - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - StreamAttachedState state = (StreamAttachedState) - (static_cast (StreamAttachedState::PHYSICAL) | - static_cast (StreamAttachedState::IDLE_TO_PHY) | - static_cast (StreamAttachedState::VIR_TO_PHY)); - - std::vector attached_contexts = - contexts->FindByAseAttachedState(ase_id, state); - - LOG(INFO) << __func__ <<": attached_contexts: size : " - << attached_contexts.size(); - if(cur_context->attached_state == StreamAttachedState::PHYSICAL || - cur_context->attached_state == StreamAttachedState::IDLE_TO_PHY || - cur_context->attached_state == StreamAttachedState::VIR_TO_PHY ) { - can_be_disconnected = true; - } - return can_be_disconnected; -} - -bool StreamTracker::HandleInternalDisconnect(bool release) { - - UpdateControlType(StreamControlType::Disconnect); - - std::vector streams; - - int cur_state = StateId(); - LOG(WARNING) << __func__ <<": cur_state: " << cur_state - <<", release: " << release; - switch(cur_state) { - case StreamTracker::kStateConnecting: { - std::vector *conn_streams = GetConnStreams(); - - for (auto it = conn_streams->begin(); it != conn_streams->end(); it++) { - StreamType type = it->stream_type; - streams.push_back(type); - } - UpdateStreams(&streams); - } break; - case StreamTracker::kStateReconfiguring: { - std::vector *reconf_streams = GetReconfStreams(); - - for (auto it = reconf_streams->begin(); - it != reconf_streams->end(); it++) { - StreamType type = it->stream_type; - streams.push_back(type); - } - UpdateStreams(&streams); - } break; - } - - if (release) { - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - AscsClient *ascs_client = strm_mgr_->GetAscsClient(); - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - std::vector ase_ops; - std::vector *disc_streams = GetStreams(); - - for (auto it = disc_streams->begin(); it != disc_streams->end(); it++) { - StreamContext *context = contexts->FindOrAddByType(*it); - - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - - UcastAudioStream *stream = audio_strms->FindByAseId(id->ase_id); - bool can_be_disconnected = StreamCanbeDisconnected(context, id->ase_id); - if (can_be_disconnected && - stream && stream->overall_state == cur_state && - stream->ase_state != ascs::ASE_STATE_IDLE && - stream->ase_state != ascs::ASE_STATE_RELEASING && - stream->ase_pending_cmd != AscsPendingCmd::RELEASE_ISSUED) { - LOG(WARNING) << __func__ - <<": ASE State : " << loghex(stream->ase_state); - AseReleaseOp release_op = { - .ase_id = stream->ase_id - }; - ase_ops.push_back(release_op); - stream->ase_pending_cmd = AscsPendingCmd::RELEASE_ISSUED; - // change the overall state to Disconnecting - stream->overall_state = StreamTracker::kStateDisconnecting; - } - } - } - - // send consolidated release command to ASCS client - if(ase_ops.size()) { - LOG(WARNING) << __func__ << ": Going For ASCS Release op"; - ascs_client->Release(ASCS_CLIENT_ID, strm_mgr_->GetAddress(), ase_ops); - } - } - // update the state to disconnecting - TransitionTo(StreamTracker::kStateDisconnecting); - return true; -} - -bool StreamTracker::HandleRemoteStop(uint32_t event, - void* p_data, int cur_state) { - AscsState *ascs = ((AscsState *) p_data); - uint8_t ase_id = ascs->ase_params.ase_id; - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - UcastAudioStream *stream = audio_strms->FindByAseId(ase_id); - - if(!stream) return false; - - if(stream->direction & cis::DIR_TO_AIR) { - LOG(ERROR) << __func__ << ": Invalid State transition to Disabling" - << ": ASE Id = " << loghex(ase_id); - return false; - } - - UpdateControlType(StreamControlType::Stop); - - if(cur_state != StreamTracker::kStateStarting || - cur_state != StreamTracker::kStateStreaming) { - return false; - } - // update the state to stopping - TransitionTo(StreamTracker::kStateStopping); - ProcessEvent(event, p_data); - return true; -} - -bool StreamTracker::HandleAbruptStop(uint32_t event, void* p_data) { - AscsState *ascs = ((AscsState *) p_data); - uint8_t ase_id = ascs->ase_params.ase_id; - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - UcastAudioStream *stream = audio_strms->FindByAseId(ase_id); - - if(!stream) return false; - stream->ase_pending_cmd = AscsPendingCmd::NONE; - - UpdateControlType(StreamControlType::Stop); - - // update the state to stopping - TransitionTo(StreamTracker::kStateStopping); - return true; -} - -bool StreamTracker::HandleRemoteReconfig(uint32_t event, - void* p_data, int cur_state) { - UpdateControlType(StreamControlType::Reconfig); - std::vector streams; - - if(cur_state != StreamTracker::kStateConnected) { - return false; - } - // update the state to Reconfiguring - TransitionTo(StreamTracker::kStateReconfiguring); - ProcessEvent(event, p_data); - return true; -} - -void StreamTracker::HandleAseOpFailedEvent(void *p_data) { - AscsOpFailed *ascs_op = ((AscsOpFailed *) p_data); - std::vector *ase_list = &ascs_op->ase_list; - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - - if(ascs_op->ase_op_id == ascs::AseOpId::CODEC_CONFIG) { - // treat it like internal failure - for (auto i = ase_list->begin(); i != ase_list->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((i)->ase_id); - if(stream) { - stream->ase_pending_cmd = AscsPendingCmd::NONE; - stream->overall_state = StreamTracker::kStateIdle; - } - } - HandleInternalDisconnect(false); - } else { - HandleInternalDisconnect(true); - } -} - -void StreamTracker::HandleAseStateEvent(void *p_data, - StreamControlType control_type, - IntStrmTrackers *int_strm_trackers) { - // check the state and if the state is codec configured for all ASEs - // then proceed with group creation - AscsState *ascs = reinterpret_cast (p_data); - - uint8_t ase_id = ascs->ase_params.ase_id; - - // check if current stream tracker is interested in this ASE update - if(int_strm_trackers->FindByAseId(ase_id) == nullptr) { - LOG(INFO) << __func__ << ": Not intended for this tracker"; - return; - } - - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - - UcastAudioStream *stream = audio_strms->FindByAseId(ase_id); - - if(stream == nullptr) { - return; - } else { - stream->ase_state = ascs->ase_params.ase_state; - stream->ase_params = ascs->ase_params; - stream->ase_pending_cmd = AscsPendingCmd::NONE; - } - - if(ascs->ase_params.ase_state == ascs::ASE_STATE_CODEC_CONFIGURED) { - stream->pref_qos_params = ascs->ase_params.codec_config_params; - // find out the stream for the given ase id - LOG(INFO) << __func__ << ": Total Num Streams = " << audio_strms->size() - << ": ASE Id = " << loghex(ase_id); - - // decide on best QOS params by comparing the upper layer prefs - // and remote dev's preferences - int state = StreamTracker::kStateIdle; - - if(control_type == StreamControlType::Connect) { - state = StreamTracker::kStateConnecting; - } else if(control_type == StreamControlType::Reconfig) { - state = StreamTracker::kStateReconfiguring; - } - - // check for all trackers codec is configured or not - std::vector *all_trackers = - int_strm_trackers->GetTrackerList(); - uint8_t num_codec_configured = 0; - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (!stream) { - LOG(ERROR) << __func__ << "stream is null"; - continue; - } - if(stream->ase_pending_cmd == AscsPendingCmd::NONE && - (stream->ase_state == ascs::ASE_STATE_CODEC_CONFIGURED || - (control_type == StreamControlType::Reconfig && - stream->ase_state == ascs::ASE_STATE_QOS_CONFIGURED))) { - num_codec_configured++; - } - } - - if(int_strm_trackers->size() != num_codec_configured) { - LOG(WARNING) << __func__ << " Codec Not Configured For All Streams"; - return; - } - - // check for all streams together so that final group params - // will be decided - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (stream) { - ChooseBestQos(&stream->req_qos_config, &stream->pref_qos_params, - &stream->qos_config, state, stream->direction); - } - } - CheckAndSendQosConfig(int_strm_trackers); - - } else if(ascs->ase_params.ase_state == ascs::ASE_STATE_QOS_CONFIGURED) { - // TODO update the state as connected using callbacks - // make the state transition to connected - - // check for all trackers QOS is configured or not - // if so update it as streams are connected - std::vector *all_trackers = - int_strm_trackers->GetTrackerList(); - uint8_t num_qos_configured = 0; - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if(stream && stream->ase_state == ascs::ASE_STATE_QOS_CONFIGURED && - stream->ase_pending_cmd == AscsPendingCmd::NONE) { - num_qos_configured++; - } - } - - if(int_strm_trackers->size() != num_qos_configured) { - LOG(WARNING) << __func__ << " QOS Not Configured For All Streams"; - return; - } - - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (!stream) { - LOG(ERROR) << __func__ << "stream is null"; - continue; - } - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - StreamContext *context = contexts->FindOrAddByType( - (*i)->strm_type); - if(context->attached_state == StreamAttachedState::IDLE_TO_PHY || - context->attached_state == StreamAttachedState::VIR_TO_PHY) { - context->attached_state = StreamAttachedState::PHYSICAL; - LOG(INFO) << __func__ << " Attached state made physical"; - } - stream->overall_state = kStateConnected; - } - - // update the state to connected - TransitionTo(StreamTracker::kStateConnected); - - } else if(ascs->ase_params.ase_state == ascs::ASE_STATE_RELEASING) { - HandleRemoteDisconnect(ASCS_ASE_STATE_EVT, p_data, StateId()); - } -} - -bool StreamTracker::HandleStreamUpdate (int cur_state) { - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - AscsClient *ascs_client = strm_mgr_->GetAscsClient(); - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - - std::vector ase_meta_ops; - std::vector *update_streams = GetMetaUpdateStreams(); - - for (auto it = update_streams->begin(); - it != update_streams->end(); it++) { - StreamContext *context = contexts->FindOrAddByType(it->stream_type); - - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - std::vector meta_data; - UcastAudioStream *stream = audio_strms->FindByAseId(id->ase_id); - if(stream && stream->ase_state != ascs::ASE_STATE_ENABLING && - stream->ase_state != ascs::ASE_STATE_STREAMING) { - continue; - } - if(it->update_type == StreamUpdateType::STREAMING_CONTEXT) { - uint8_t len = LTV_LEN_STRM_AUDIO_CONTEXTS; - uint8_t type = LTV_TYPE_STRM_AUDIO_CONTEXTS; - uint16_t value = it->update_value; - if(stream) stream->audio_context = value; - meta_data.insert(meta_data.end(), &len, &len + 1); - meta_data.insert(meta_data.end(), &type, &type + 1); - meta_data.insert(meta_data.end(), ((uint8_t *)&value), - ((uint8_t *)&value) + sizeof(uint16_t)); - } - - AseUpdateMetadataOp meta_op = { - .ase_id = id->ase_id, - .meta_data_len = - static_cast (meta_data.size()), - .meta_data = meta_data // media or voice - }; - ase_meta_ops.push_back(meta_op); - } - } - - // send consolidated update meta command to ASCS client - if(ase_meta_ops.size()) { - LOG(WARNING) << __func__ << ": Going For ASCS Update MetaData op"; - ascs_client->UpdateStream(ASCS_CLIENT_ID, strm_mgr_->GetAddress(), - ase_meta_ops); - } else { - return false; - } - - if(cur_state == StreamTracker::kStateUpdating) { - for (auto it = update_streams->begin(); - it != update_streams->end(); it++) { - StreamContext *context = contexts->FindOrAddByType(it->stream_type); - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - UcastAudioStream *stream = audio_strms->FindByAseId(id->ase_id); - if (stream != nullptr) { - // change the connection state to disable issued - stream->ase_pending_cmd = AscsPendingCmd::UPDATE_METADATA_ISSUED; - // change the overall state to Updating - stream->overall_state = StreamTracker::kStateUpdating; - } - } - } - } - return true; -} - -bool StreamTracker::HandleStop(void* p_data, int cur_state) { - if(p_data != nullptr) { - BapStop *evt_data = (BapStop *) p_data; - UpdateStreams(&evt_data->streams); - } - UpdateControlType(StreamControlType::Stop); - - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - AscsClient *ascs_client = strm_mgr_->GetAscsClient(); - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - - std::vector ase_ops; - std::vector *stop_streams = GetStreams(); - - for (auto it = stop_streams->begin(); - it != stop_streams->end(); it++) { - StreamContext *context = contexts->FindOrAddByType(*it); - - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - AseDisableOp disable_op = { - .ase_id = id->ase_id - }; - ase_ops.push_back(disable_op); - } - } - - // send consolidated disable command to ASCS client - if(ase_ops.size()) { - LOG(WARNING) << __func__ << ": Going For ASCS Disable op"; - ascs_client->Disable(ASCS_CLIENT_ID, strm_mgr_->GetAddress(), ase_ops); - } - - for (auto it = stop_streams->begin(); - it != stop_streams->end(); it++) { - StreamContext *context = contexts->FindOrAddByType(*it); - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - UcastAudioStream *stream = audio_strms->FindByAseId(id->ase_id); - if (stream != nullptr && stream->overall_state == cur_state) { - // change the connection state to disable issued - stream->ase_pending_cmd = AscsPendingCmd::DISABLE_ISSUED; - // change the overall state to stopping - stream->overall_state = StreamTracker::kStateStopping; - } - } - } - TransitionTo(StreamTracker::kStateStopping); - return true; -} - -bool StreamTracker::HandleDisconnect(void* p_data, int cur_state) { - // expect the disconnection for same set of streams connection - // has initiated ex: if connect is issued for media (tx), voice(tx & rx) - // then disconnect is expected for media (tx), voice(tx & rx). - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - - BapDisconnect *evt_data = (BapDisconnect *) p_data; - - UpdateControlType(StreamControlType::Disconnect); - - UpdateStreams(&evt_data->streams); - - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - AscsClient *ascs_client = strm_mgr_->GetAscsClient(); - - std::vector ase_ops; - std::vector *disc_streams = GetStreams(); - - for (auto it = disc_streams->begin(); it != disc_streams->end(); it++) { - StreamContext *context = contexts->FindOrAddByType(*it); - - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - UcastAudioStream *stream = audio_strms->FindByAseId(id->ase_id); - bool can_be_disconnected = StreamCanbeDisconnected(context, id->ase_id); - if(can_be_disconnected && - stream && stream->overall_state != StreamTracker::kStateIdle && - stream->overall_state != StreamTracker::kStateDisconnecting && - stream->ase_pending_cmd != AscsPendingCmd::RELEASE_ISSUED) { - AseReleaseOp release_op = { - .ase_id = id->ase_id - }; - ase_ops.push_back(release_op); - stream->ase_pending_cmd = AscsPendingCmd::RELEASE_ISSUED; - // change the overall state to starting - stream->overall_state = StreamTracker::kStateDisconnecting; - } - } - } - - // send consolidated release command to ASCS client - if(ase_ops.size()) { - LOG(WARNING) << __func__ << ": Going For ASCS Release op"; - ascs_client->Release(ASCS_CLIENT_ID, strm_mgr_->GetAddress(), ase_ops); - } - - TransitionTo(StreamTracker::kStateDisconnecting); - return true; -} - -void StreamTracker::CheckAndSendQosConfig(IntStrmTrackers *int_strm_trackers) { - - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - AscsClient *ascs_client = strm_mgr_->GetAscsClient(); - // check for all trackers CIG is created or not - // if so proceed with QOS config operaiton - std::vector *all_trackers = - int_strm_trackers->GetTrackerList(); - - std::vector ase_ops; - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - QosConfig *qos_config = &stream->qos_config; - if(!stream || stream->ase_pending_cmd != AscsPendingCmd::NONE) { - continue; - } - if(stream->direction & cis::DIR_TO_AIR) { - - AseQosConfigOp qos_config_op = { - .ase_id = (*i)->ase_id, - .cig_id = stream->cig_id, - .cis_id = stream->cis_id, - .sdu_interval = { qos_config->cig_config.sdu_interval_m_to_s[0], - qos_config->cig_config.sdu_interval_m_to_s[1], - qos_config->cig_config.sdu_interval_m_to_s[2] }, - .framing = qos_config->cig_config.framing, - .phy = LE_2M_PHY, - .max_sdu_size = qos_config->cis_configs[(*i)->cis_id].max_sdu_m_to_s, - .retrans_number = qos_config->cis_configs[(*i)->cis_id].rtn_m_to_s, - .trans_latency = qos_config->cig_config.max_tport_latency_m_to_s, - .present_delay = {qos_config->ascs_configs[0].presentation_delay[0], - qos_config->ascs_configs[0].presentation_delay[1], - qos_config->ascs_configs[0].presentation_delay[2]} - }; - ase_ops.push_back(qos_config_op); - - } else if(stream->direction & cis::DIR_FROM_AIR) { - AseQosConfigOp qos_config_op = { - .ase_id = (*i)->ase_id, - .cig_id = stream->cig_id, - .cis_id = stream->cis_id, - .sdu_interval = { qos_config->cig_config.sdu_interval_s_to_m[0], - qos_config->cig_config.sdu_interval_s_to_m[1], - qos_config->cig_config.sdu_interval_s_to_m[2] }, - .framing = qos_config->cig_config.framing, - .phy = LE_2M_PHY, - .max_sdu_size = qos_config->cis_configs[(*i)->cis_id].max_sdu_s_to_m, - .retrans_number = qos_config->cis_configs[(*i)->cis_id].rtn_s_to_m, - .trans_latency = qos_config->cig_config.max_tport_latency_s_to_m, - .present_delay = {qos_config->ascs_configs[0].presentation_delay[0], - qos_config->ascs_configs[0].presentation_delay[1], - qos_config->ascs_configs[0].presentation_delay[2]} - }; - ase_ops.push_back(qos_config_op); - } - } - - if(ase_ops.size()) { - LOG(WARNING) << __func__ << ": Going For ASCS QosConfig op"; - ascs_client->QosConfig(ASCS_CLIENT_ID, strm_mgr_->GetAddress(), ase_ops); - - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if(stream && stream->ase_pending_cmd == AscsPendingCmd::NONE) - stream->ase_pending_cmd = AscsPendingCmd::QOS_CONFIG_ISSUED; - } - } -} - - -void StreamTracker::CheckAndSendEnable(IntStrmTrackers *int_strm_trackers) { - - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - AscsClient *ascs_client = strm_mgr_->GetAscsClient(); - std::vector *start_streams = GetStreams(); - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - std::vector ase_ops; - // check for all trackers CIG is created or not - // if so proceed with QOS config operaiton - std::vector *all_trackers = - int_strm_trackers->GetTrackerList(); - - uint8_t num_cig_created = 0; - - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if(stream && stream->cig_state == CigState::CREATED) { - num_cig_created++; - } - } - - if(int_strm_trackers->size() != num_cig_created) { - LOG(WARNING) << __func__ << " All CIGs are not created"; - return; - } - - for(auto it = start_streams->begin(); it != start_streams->end(); it++) { - StreamContext *context = contexts->FindOrAddByType(*it); - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - std::vector meta_data; - UcastAudioStream *stream = audio_strms->FindByAseId(id->ase_id); - uint8_t len = LTV_LEN_STRM_AUDIO_CONTEXTS; - uint8_t type = LTV_TYPE_STRM_AUDIO_CONTEXTS; - uint16_t value = (*it).audio_context; - if(stream) stream->audio_context = value; - meta_data.insert(meta_data.end(), &len, &len + 1); - meta_data.insert(meta_data.end(), &type, &type + 1); - meta_data.insert(meta_data.end(), ((uint8_t *)&value), - ((uint8_t *)&value) + sizeof(uint16_t)); - - AseEnableOp enable_op = { - .ase_id = id->ase_id, - .meta_data_len = - static_cast (meta_data.size()), - .meta_data = meta_data // media or voice - }; - ase_ops.push_back(enable_op); - } - } - - // send consolidated enable command to ASCS client - if(ase_ops.size()) { - LOG(WARNING) << __func__ << ": Going For ASCS Enable op"; - ascs_client->Enable(ASCS_CLIENT_ID, strm_mgr_->GetAddress(), ase_ops); - - for (auto it = start_streams->begin(); it != start_streams->end(); it++) { - StreamContext *context = contexts->FindOrAddByType(*it); - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - UcastAudioStream *stream = audio_strms->FindByAseId(id->ase_id); - if (stream != nullptr && stream->overall_state == - StreamTracker::kStateConnected) { - // change the connection state to enable issued - stream->ase_pending_cmd = AscsPendingCmd::ENABLE_ISSUED; - // change the overall state to starting - stream->overall_state = StreamTracker::kStateStarting; - } - } - } - } -} - -void StreamTracker::HandleCigStateEvent(uint32_t event, void *p_data, - IntStrmTrackers *int_strm_trackers) { - // check if the associated CIG state is created - // if so go for Enable Operation - CisGroupState *data = ((CisGroupState *) p_data); - - // check if current stream tracker is interested in this CIG update - std::vector int_trackers = - int_strm_trackers->FindByCigId(data->cig_id); - if(int_trackers.empty()) { - LOG(INFO) << __func__ << " Not intended for this tracker"; - return; - } - - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - if(data->state == CigState::CREATED) { - for (auto i = int_trackers.begin(); i != int_trackers.end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if(stream) { - stream->cis_pending_cmd = CisPendingCmd::NONE; - stream->cig_state = data->state; - stream->cis_state = CisState::READY; - } - } - CheckAndSendEnable(int_strm_trackers); - } else if(data->state == CigState::IDLE) { - // CIG state is idle means there is some failure - LOG(ERROR) << __func__ << ": CIG Creation Failed"; - for (auto i = int_trackers.begin(); i != int_trackers.end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if(stream) { - stream->cig_state = CigState::INVALID; - stream->cis_state = CisState::INVALID; - stream->cis_pending_cmd = CisPendingCmd::NONE;; - } - } - HandleInternalDisconnect(false); - return; - } -} - -bool StreamTracker::PrepareCodecConfigPayload( - std::vector *ase_ops, - UcastAudioStream *stream) { - std::vector codec_params; - uint8_t tgt_latency = TGT_HIGH_RELIABLE; - // check for sampling freq - for (auto it : freq_to_ltv_map) { - if(stream->codec_config.sample_rate == it.first) { - uint8_t len = LTV_LEN_SAMP_FREQ; - uint8_t type = LTV_TYPE_SAMP_FREQ; - uint8_t rate = it.second; - codec_params.insert(codec_params.end(), &len, &len + 1); - codec_params.insert(codec_params.end(), &type, &type + 1); - codec_params.insert(codec_params.end(), &rate, &rate + 1); - break; - } - } - - // check for frame duration and fetch 5th byte - uint8_t frame_duration = GetFrameDuration(&stream->codec_config); - uint8_t len = LTV_LEN_FRAME_DUR; - uint8_t type = LTV_TYPE_FRAME_DUR; - codec_params.insert(codec_params.end(), &len, &len + 1); - codec_params.insert(codec_params.end(), &type, &type + 1); - codec_params.insert(codec_params.end(), &frame_duration, - &frame_duration + 1); - - // audio chnl allcation - if(stream->audio_location) { - uint8_t len = LTV_LEN_CHNL_ALLOC; - uint8_t type = LTV_TYPE_CHNL_ALLOC; - uint32_t value = stream->audio_location; - codec_params.insert(codec_params.end(), &len, &len + 1); - codec_params.insert(codec_params.end(), &type, &type + 1); - codec_params.insert(codec_params.end(), ((uint8_t *)&value), - ((uint8_t *)&value) + sizeof(uint32_t)); - } - - // octets per frame - len = LTV_LEN_OCTS_PER_FRAME; - type = LTV_TYPE_OCTS_PER_FRAME; - uint16_t octs_per_frame = GetOctsPerFrame(&stream->codec_config); - codec_params.insert(codec_params.end(), &len, &len + 1); - codec_params.insert(codec_params.end(), &type, &type + 1); - codec_params.insert(codec_params.end(), ((uint8_t *)&octs_per_frame), - ((uint8_t *)&octs_per_frame) + sizeof(uint16_t)); - - // blocks per SDU - len = LTV_LEN_FRAMES_PER_SDU; - type = LTV_TYPE_FRAMES_PER_SDU; - uint8_t blocks_per_sdu = GetLc3BlocksPerSdu(&stream->codec_config); - // initialize it to 1 if it doesn't exists - if(!blocks_per_sdu) { - blocks_per_sdu = 1; - } - codec_params.insert(codec_params.end(), &len, &len + 1); - codec_params.insert(codec_params.end(), &type, &type + 1); - codec_params.insert(codec_params.end(), &blocks_per_sdu, - &blocks_per_sdu + 1); - - if(stream->audio_context == CONTENT_TYPE_MEDIA) { - tgt_latency = TGT_HIGH_RELIABLE; - } else if(stream->audio_context == CONTENT_TYPE_CONVERSATIONAL) { - tgt_latency = TGT_BAL_LATENCY; - } else if(stream->audio_context == CONTENT_TYPE_GAME) { - tgt_latency = TGT_LOW_LATENCY; - } - - AseCodecConfigOp codec_config_op = { - .ase_id = stream->ase_id, - .tgt_latency = tgt_latency, - .tgt_phy = LE_2M_PHY, - .codec_id = {LC3_CODEC_ID, 0, 0, 0, 0}, - .codec_params_len = - static_cast (codec_params.size()), - .codec_params = codec_params - }; - ase_ops->push_back(codec_config_op); - return true; -} - -alarm_t* StreamTracker::SetTimer(const char* alarmname, - BapTimeout* timeout, TimeoutReason reason, uint64_t ms) { - alarm_t* timer = nullptr; - - timeout->bd_addr = strm_mgr_->GetAddress(); - timeout->tracker = this; - timeout->reason = reason; - timeout->transition_state = StateId(); - - BapAlarm* bap_alarm = strm_mgr_->GetBapAlarm(); - if (bap_alarm != nullptr) { - timer = bap_alarm->Create(alarmname); - if (timer == nullptr) { - LOG(ERROR) << __func__ << ": Not able to create alarm"; - return nullptr; - } - LOG(INFO) << __func__ << ": starting " << alarmname; - bap_alarm->Start(timer, ms, timeout); - } - return timer; -} - -void StreamTracker::ClearTimer(alarm_t* timer, const char* alarmname) { - BapAlarm* bap_alarm = strm_mgr_->GetBapAlarm(); - - if (bap_alarm != nullptr && bap_alarm->IsScheduled(timer)) { - LOG(INFO) << __func__ << ": clear " << alarmname; - bap_alarm->Stop(timer); - } -} - -void StreamTracker::OnTimeout(void* data) { - BapTimeout* timeout = (BapTimeout *)data; - if (timeout == nullptr) { - LOG(INFO) << __func__ << ": timeout data null, return "; - return; - } - - bool isReleaseNeeded = false; - int stream_tracker_id = timeout->transition_state; - LOG(INFO) << __func__ << ": stream_tracker_ID: " << stream_tracker_id - << ", timeout reason: " << static_cast(timeout->reason); - - if (timeout->reason == TimeoutReason::STATE_TRANSITION) { - if (stream_tracker_id == StreamTracker::kStateConnecting) { - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - std::vector *conn_streams = GetConnStreams(); - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - - LOG(WARNING) << __func__ << ": audio_strms: " << audio_strms->size() - << ", conn_streams: " << conn_streams->size(); - - for (auto it = conn_streams->begin(); it != conn_streams->end(); it++) { - StreamContext *context = contexts->FindOrAddByType(it->stream_type); - LOG(INFO) << __func__ << ": connection_state: " - << static_cast(context->connection_state); - - if(context->connection_state == IntConnectState::ASCS_DISCOVERED) { - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - UcastAudioStream *stream = audio_strms->FindByAseId(id->ase_id); - if (!stream) { - LOG(ERROR) << __func__ << "stream is null"; - continue; - } - - LOG(INFO) << __func__ << ": ase_state: " << stream->ase_state; - if (stream->ase_state != ascs::ASE_STATE_IDLE && - stream->ase_state != ascs::ASE_STATE_RELEASING) { - LOG(WARNING) << __func__ - << ": ascs state is neither idle nor releasing"; - isReleaseNeeded = true; - break; - } - } - } - } - LOG(INFO) << __func__ << ": isReleaseNeeded: " << isReleaseNeeded; - HandleInternalDisconnect(isReleaseNeeded); - } else if (stream_tracker_id != StreamTracker::kStateDisconnecting) { - //All other transient states - HandleInternalDisconnect(true); - } - } - LOG(INFO) << __func__ << ": Exit"; -} - -void StreamTracker::StateIdle::OnEnter() { - LOG(INFO) << __func__ << ": StreamTracker State: " << GetState(); - - UcastClientCallbacks* callbacks = strm_mgr_->GetUclientCbacks(); - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - std::vector strms; - StreamControlType control_type = tracker_.GetControlType(); - - if(control_type != StreamControlType::Disconnect && - control_type != StreamControlType::Connect) { - return; - } - - if(control_type == StreamControlType::Disconnect) { - std::vector *disc_streams = tracker_.GetStreams(); - LOG(WARNING) << __func__ << ": Disc Streams Size: " - << disc_streams->size(); - for (auto it = disc_streams->begin(); it != disc_streams->end(); it++) { - StreamStateInfo state; - memset(&state, 0, sizeof(state)); - state.stream_type = *it; - state.stream_state = StreamState::DISCONNECTED; - strms.push_back(state); - StreamContext *context = contexts->FindOrAddByType(*it); - context->stream_state = StreamState::DISCONNECTED; - context->attached_state = StreamAttachedState::IDLE; - LOG(INFO) << __func__ << " Attached state made idle"; - context->stream_ids.clear(); - } - } else if(control_type == StreamControlType::Connect) { - std::vector *conn_streams = tracker_.GetConnStreams(); - uint32_t prev_state = tracker_.PreviousStateId(); - for (auto it = conn_streams->begin(); it != conn_streams->end(); it++) { - StreamStateInfo state; - memset(&state, 0, sizeof(state)); - StreamContext *context = contexts->FindOrAddByType(it->stream_type); - context->stream_state = StreamState::DISCONNECTED; - context->attached_state = StreamAttachedState::IDLE; - LOG(INFO) << __func__ << " Attached state made idle"; - context->stream_ids.clear(); - if(prev_state == StreamTracker::kStateConnecting) { - state.stream_type = it->stream_type; - state.stream_state = StreamState::DISCONNECTED; - strms.push_back(state); - } - } - } - callbacks->OnStreamState(strm_mgr_->GetAddress(), strms); -} - -void StreamTracker::StateIdle::OnExit() { - -} - -bool StreamTracker::StateIdle::ProcessEvent(uint32_t event, void* p_data) { - LOG(INFO) <<__func__ <<": BD Addr = " << strm_mgr_->GetAddress() - <<": State = " << GetState() - <<": Event = " << tracker_.GetEventName(event); - - GattPendingData *gatt_pending_data = strm_mgr_->GetGattPendingData(); - - switch (event) { - case BAP_CONNECT_REQ_EVT: { - BapConnect *evt_data = (BapConnect *) p_data; - // check if the PACS client is connected to remote device - PacsClient *pacs_client = strm_mgr_->GetPacsClient(); - uint16_t pacs_client_id = strm_mgr_->GetPacsClientId(); - ConnectionState pacs_state = strm_mgr_->GetPacsState(); - if(pacs_state == ConnectionState::DISCONNECTED || - pacs_state == ConnectionState::DISCONNECTING || - pacs_state == ConnectionState::CONNECTING) { - // move the state to connecting and initiate pacs connection - pacs_client->Connect(pacs_client_id, strm_mgr_->GetAddress(), - evt_data->is_direct); - if(gatt_pending_data->pacs_pending_cmd == GattPendingCmd::NONE) { - gatt_pending_data->pacs_pending_cmd = - GattPendingCmd::GATT_CONN_PENDING; - } - tracker_.TransitionTo(StreamTracker::kStateConnecting); - } else if(pacs_state == ConnectionState::CONNECTED) { - // pacs is already connected so initiate - // pacs service discovry now and move the state to connecting - pacs_client->StartDiscovery(pacs_client_id, strm_mgr_->GetAddress()); - tracker_.TransitionTo(StreamTracker::kStateConnecting); - } - } break; - default: - LOG(WARNING) << __func__ << "Unhandled Event" << loghex(event); - break; - } - return true; -} - -void StreamTracker::StateConnecting::OnEnter() { - LOG(INFO) << __func__ << ": StreamTracker State: " << GetState(); - - UcastClientCallbacks* callbacks = strm_mgr_->GetUclientCbacks(); - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - std::vector strms; - std::vector *conn_streams = tracker_.GetConnStreams(); - - StreamControlType control_type = tracker_.GetControlType(); - - if(control_type != StreamControlType::Connect) return; - - ConnectionState pacs_state = strm_mgr_->GetPacsState(); - - LOG(INFO) << __func__ << ": Conn Streams Size: " << conn_streams->size(); - - for (auto it = conn_streams->begin(); it != conn_streams->end(); it++) { - StreamStateInfo state; - memset(&state, 0, sizeof(state)); - StreamContext *context = contexts->FindOrAddByType(it->stream_type); - context->stream_state = StreamState::CONNECTING; - if(pacs_state == ConnectionState::DISCONNECTED || - pacs_state == ConnectionState::CONNECTING) { - context->connection_state = IntConnectState::PACS_CONNECTING; - } else if(pacs_state == ConnectionState::CONNECTED) { - context->connection_state = IntConnectState::PACS_DISCOVERING; - } - state.stream_type = it->stream_type; - state.stream_state = StreamState::CONNECTING; - strms.push_back(state); - } - callbacks->OnStreamState(strm_mgr_->GetAddress(), strms); - - TimeoutReason reason = TimeoutReason::STATE_TRANSITION; - state_transition_timer = tracker_.SetTimer("StateConnectingTimer", - &timeout, reason, ((conn_streams->size()) * - (static_cast(TimeoutVal::ConnectingTimeout)))); - if (state_transition_timer == nullptr) { - LOG(ERROR) << __func__ << ": StateConnecting: Alarm not allocated."; - return; - } -} - -void StreamTracker::StateConnecting::OnExit() { - tracker_.ClearTimer(state_transition_timer, "StateConnectingTimer"); -} - -void StreamTracker::StateConnecting::DeriveDeviceType( - PacsDiscovery *pacs_discovery) { - // derive the device type based on sink pac records - std::vector *pac_records = &pacs_discovery->sink_pac_records; - uint8_t max_chnl_count = 0; - - // chnl count Audio location Type of device No of ASEs - // 1 Left or Right Earbud 1 ASE per Earbud - // 1 Left and Right Stereo Headset ( 2 CIS) 2 ASEs - // 2 Left and Right Stereo Headset ( 1 CIS) 1 ASE - // 2 Left or Right Earbud 1 ASE per Earbud - - for (auto j = pac_records->begin(); j != pac_records->end();j++) { - CodecConfig *dst = &(*j); - if(static_cast (dst->channel_mode) & - static_cast (CodecChannelMode::CODEC_CHANNEL_MODE_STEREO)) { - max_chnl_count = 2; - } else if(!max_chnl_count && - static_cast (dst->channel_mode) & - static_cast (CodecChannelMode::CODEC_CHANNEL_MODE_MONO)) { - max_chnl_count = 1; - } - } - - if(pacs_discovery->sink_locations & ucast::AUDIO_LOC_LEFT && - pacs_discovery->sink_locations & ucast::AUDIO_LOC_RIGHT) { - if(max_chnl_count == 2) { - strm_mgr_->UpdateDevType(DeviceType::HEADSET_STEREO); - } else if (max_chnl_count == 1) { - strm_mgr_->UpdateDevType(DeviceType::HEADSET_SPLIT_STEREO); - } - } else if(pacs_discovery->sink_locations & ucast::AUDIO_LOC_LEFT || - pacs_discovery->sink_locations & ucast::AUDIO_LOC_RIGHT) { - strm_mgr_->UpdateDevType(DeviceType::EARBUD); - } -} - - -bool StreamTracker::StateConnecting::AttachStreamsToContext( - std::vector *all_trackers, - std::vector *streams, - uint8_t cis_count, - std::vector *ase_ops) { - PacsDiscovery *pacs_discovery_ = tracker_.GetPacsDiscovery(); - if (!pacs_discovery_) { - return false; - } - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - for(uint8_t i = 0; i < all_trackers->size()/cis_count ; i++) { - for(uint8_t j = 0; j < cis_count ; j++) { - IntStrmTracker *tracker = all_trackers->at(i*cis_count + j); - UcastAudioStream *stream = streams->at((i*cis_count + j)% streams->size()); - StreamContext *context = contexts->FindOrAddByType( - tracker->strm_type); - if(stream->overall_state == StreamTracker::kStateIdle) { - stream->audio_context = tracker->strm_type.audio_context; - stream->control_type = StreamControlType::Connect; - stream->ase_pending_cmd = AscsPendingCmd::NONE; - stream->cis_pending_cmd = CisPendingCmd::NONE; - stream->codec_config = tracker->codec_config; - stream->req_qos_config = tracker->qos_config; - stream->qos_config = tracker->qos_config; - stream->cig_id = tracker->cig_id; - stream->cis_id = tracker->cis_id; - - stream->cig_state = CigState::INVALID; - stream->cis_state = CisState::INVALID; - stream->overall_state = StreamTracker::kStateConnecting; - - if (stream->direction == ASE_DIRECTION_SINK) { - if(cis_count > 1) { - stream->audio_location = - pacs_discovery_->sink_locations & locations.at(j); - } else { - if(pacs_discovery_->sink_locations & ucast::AUDIO_LOC_LEFT && - pacs_discovery_->sink_locations & ucast::AUDIO_LOC_RIGHT) { - stream->audio_location = 0; - } else if(pacs_discovery_->sink_locations & ucast::AUDIO_LOC_LEFT || - pacs_discovery_->sink_locations & ucast::AUDIO_LOC_RIGHT) { - stream->audio_location = pacs_discovery_->sink_locations; - } - } - } else if (stream->direction == ASE_DIRECTION_SRC) { - if(cis_count > 1) { - stream->audio_location = - pacs_discovery_->src_locations & locations.at(j); - } else { - if(pacs_discovery_->src_locations & ucast::AUDIO_LOC_LEFT && - pacs_discovery_->src_locations & ucast::AUDIO_LOC_RIGHT) { - stream->audio_location = 0; - } else if(pacs_discovery_->src_locations & ucast::AUDIO_LOC_LEFT || - pacs_discovery_->src_locations & ucast::AUDIO_LOC_RIGHT) { - stream->audio_location = pacs_discovery_->src_locations; - } - } - } - tracker_.PrepareCodecConfigPayload(ase_ops, stream); - tracker->attached_state = context->attached_state = - StreamAttachedState::IDLE_TO_PHY; - LOG(INFO) << __func__ - << ": Physically attached"; - } else { - LOG(INFO) << __func__ - << ": Virtually attached"; - tracker->attached_state = context->attached_state = - StreamAttachedState::VIRTUAL; - } - tracker->ase_id = stream->ase_id; - - StreamIdType id = { - .ase_id = stream->ase_id, - .ase_direction = stream->direction, - .virtual_attach = false, - .cig_id = tracker->cig_id, - .cis_id = tracker->cis_id - }; - context->stream_ids.push_back(id); - } - } - return true; -} - -bool StreamTracker::StateConnecting::ProcessEvent(uint32_t event, void* p_data) { - LOG(INFO) <<__func__ <<": BD Addr = " << strm_mgr_->GetAddress() - <<": State = " << GetState() - <<": Event = " << tracker_.GetEventName(event); - - std::vector *conn_streams = tracker_.GetConnStreams(); - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - GattPendingData *gatt_pending_data = strm_mgr_->GetGattPendingData(); - - uint8_t num_conn_streams = 0; - if(conn_streams) { - num_conn_streams = conn_streams->size(); - } - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - AscsClient *ascs_client = strm_mgr_->GetAscsClient(); - - switch (event) { - case BAP_DISCONNECT_REQ_EVT: { - - // expect the disconnection for same set of streams connection - // has initiated ex: if connect is issued for media (tx), voice(tx & rx) - // then disconnect is expected for media (tx), voice(tx & rx). - - // based on connection state, issue the relevant commands and move - // the state to disconnecting - // issue the release opertion if for any stream ASE operation is - // initiated - - // upate the control type and streams also - BapDisconnect *evt_data = (BapDisconnect *) p_data; - - tracker_.UpdateControlType(StreamControlType::Disconnect); - - tracker_.UpdateStreams(&evt_data->streams); - - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - AscsClient *ascs_client = strm_mgr_->GetAscsClient(); - - std::vector ase_ops; - std::vector *disc_streams = tracker_.GetStreams(); - - LOG(WARNING) << __func__ << ": disc_streams: " << disc_streams->size(); - - for (auto it = disc_streams->begin(); it != disc_streams->end(); it++) { - StreamContext *context = contexts->FindOrAddByType(*it); - if(context->connection_state == IntConnectState::ASCS_DISCOVERED) { - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - UcastAudioStream *stream = audio_strms->FindByAseId(id->ase_id); - if (!stream) { - LOG(ERROR) << __func__ << "stream is null"; - continue; - } - bool can_be_disconnected = - tracker_.StreamCanbeDisconnected(context, id->ase_id); - if(can_be_disconnected && - stream->ase_state == ascs::ASE_STATE_CODEC_CONFIGURED && - stream->ase_pending_cmd != AscsPendingCmd::RELEASE_ISSUED) { - AseReleaseOp release_op = { - .ase_id = stream->ase_id - }; - ase_ops.push_back(release_op); - stream->ase_pending_cmd = AscsPendingCmd::RELEASE_ISSUED; - // change the overall state to starting - stream->overall_state = StreamTracker::kStateDisconnecting; - } - } - } - } - - LOG(INFO) << __func__ << ": ase_ops size: " << ase_ops.size(); - - // send consolidated release command to ASCS client - if(ase_ops.size()) { - LOG(WARNING) << __func__ << ": Going For ASCS Release op"; - ascs_client->Release(ASCS_CLIENT_ID, strm_mgr_->GetAddress(), ase_ops); - } - - tracker_.TransitionTo(StreamTracker::kStateDisconnecting); - - } break; - case PACS_CONNECTION_STATE_EVT: { - PacsConnectionState *pacs_state = (PacsConnectionState *) p_data; - - PacsClient *pacs_client = strm_mgr_->GetPacsClient(); - uint16_t pacs_client_id = strm_mgr_->GetPacsClientId(); - - LOG(WARNING) << __func__ - <<": pacs_state: " << static_cast(pacs_state->state); - if(pacs_state->state == ConnectionState::CONNECTED) { - // now send the PACS discovery - gatt_pending_data->pacs_pending_cmd = GattPendingCmd::NONE; - pacs_client->StartDiscovery(pacs_client_id, strm_mgr_->GetAddress()); - } else if(pacs_state->state == ConnectionState::DISCONNECTED) { - gatt_pending_data->pacs_pending_cmd = GattPendingCmd::NONE; - tracker_.HandleInternalDisconnect(false); - return false; - } - - for (uint8_t i = 0; i < num_conn_streams ; i++) { - StreamConnect conn_stream = conn_streams->at(i); - StreamContext *context = contexts->FindOrAddByType( - conn_stream.stream_type); - if(pacs_state->state == ConnectionState::CONNECTED) { - context->connection_state = IntConnectState::PACS_DISCOVERING; - } - } - } break; - - case PACS_DISCOVERY_RES_EVT: { - PacsDiscovery pacs_discovery_ = *((PacsDiscovery *) p_data); - GattState ascs_state = strm_mgr_->GetAscsState(); - GattPendingData *gatt_pending_data = strm_mgr_->GetGattPendingData(); - bool process_pacs_results = false; - - // check if this tracker already passed the pacs discovery stage - for (uint8_t i = 0; i < num_conn_streams ; i++) { - StreamConnect conn_stream = conn_streams->at(i); - StreamContext *context = contexts->FindOrAddByType( - conn_stream.stream_type); - if(context->connection_state == IntConnectState::PACS_DISCOVERING) { - process_pacs_results = true; - break; - } - } - - if(!process_pacs_results) break; - - bool context_supported = false; - // check the status - if(pacs_discovery_.status) { - tracker_.HandleInternalDisconnect(false); - LOG(ERROR) << __func__ << " PACS discovery failed"; - return false; - } - - tracker_.UpdatePacsDiscovery(pacs_discovery_); - - // Derive the device type based on pacs discovery results - DeriveDeviceType((PacsDiscovery *) p_data); - - // check if supported audio contexts has required contexts - for (auto it = conn_streams->begin(); it != conn_streams->end(); it++) { - StreamType stream = it->stream_type; - if(stream.direction == ASE_DIRECTION_SINK) { - if(stream.audio_context & pacs_discovery_.supported_contexts) { - context_supported = true; - } - } else if(stream.direction == ASE_DIRECTION_SRC) { - if((static_cast(stream.audio_context) << 16) & - pacs_discovery_.supported_contexts) { - context_supported = true; - } - } - } - - if(!context_supported) { - LOG(ERROR) << __func__ << " No Matching Supported Contexts found"; - tracker_.HandleInternalDisconnect(false); - break; - } - - // if not present send the BAP callback as disconnected - // compare the codec configs from upper layer to remote dev - // sink or src PACS records/capabilities. - - // go for ASCS discovery only when codec configs are decided - - for (uint8_t i = 0; i < num_conn_streams ; i++) { - StreamConnect conn_stream = conn_streams->at(i); - // TODO for now will pick directly first set of Codec and QOS configs - - uint8_t index = tracker_.ChooseBestCodec(conn_stream.stream_type, - &conn_stream.codec_qos_config_pair, - &pacs_discovery_); - if(index != 0XFF) { - CodecQosConfig entry = conn_stream.codec_qos_config_pair.at(index); - CodecConfig codec_config = entry.codec_config; - QosConfig qos_config = entry.qos_config; - - StreamContext *context = contexts->FindOrAddByType( - conn_stream.stream_type); - for (auto ascs_config = qos_config.ascs_configs.begin(); - ascs_config != qos_config.ascs_configs.end(); ascs_config++) { - int_strm_trackers_.FindOrAddBytrackerType(conn_stream.stream_type, - 0x00, ascs_config->cig_id, - ascs_config->cis_id, - codec_config, qos_config); - } - context->codec_config = codec_config; - context->req_qos_config = qos_config; - } else { - LOG(ERROR) << __func__ << " No Matching Codec Found For Stream"; - } - } - - // check if any match between upper layer codec and remote dev's - // pacs records - if(!int_strm_trackers_.size()) { - LOG(WARNING) << __func__ << "No Matching codec found for all streams"; - tracker_.HandleInternalDisconnect(false); - return false; - } - - if(ascs_state == GattState::CONNECTED) { - LOG(WARNING) << __func__ << ": Going For ASCS Service Discovery"; - // now send the ASCS discovery - ascs_client->StartDiscovery(ASCS_CLIENT_ID, strm_mgr_->GetAddress()); - } else if(ascs_state == GattState::DISCONNECTED) { - LOG(WARNING) << __func__ << ": Going For ASCS Conneciton"; - ascs_client->Connect(ASCS_CLIENT_ID, strm_mgr_->GetAddress(), false); - if(gatt_pending_data->ascs_pending_cmd == GattPendingCmd::NONE) { - gatt_pending_data->ascs_pending_cmd = - GattPendingCmd::GATT_CONN_PENDING; - } - } - - for (uint8_t i = 0; i < num_conn_streams ; i++) { - StreamConnect conn_stream = conn_streams->at(i); - StreamContext *context = contexts->FindOrAddByType( - conn_stream.stream_type); - if(ascs_state == GattState::CONNECTED) { - context->connection_state = IntConnectState::ASCS_DISCOVERING; - } else if(ascs_state == GattState::DISCONNECTED) { - context->connection_state = IntConnectState::ASCS_CONNECTING; - } - } - } break; - - case ASCS_CONNECTION_STATE_EVT: { - AscsConnectionState *ascs_state = (AscsConnectionState *) p_data; - AscsClient *ascs_client = strm_mgr_->GetAscsClient(); - - if(ascs_state->state == GattState::CONNECTED) { - LOG(INFO) << __func__ << " ASCS server connected"; - // now send the ASCS discovery - gatt_pending_data->ascs_pending_cmd = GattPendingCmd::NONE; - ascs_client->StartDiscovery(ASCS_CLIENT_ID, strm_mgr_->GetAddress()); - } else if(ascs_state->state == GattState::DISCONNECTED) { - LOG(INFO) << __func__ << " ASCS server Disconnected"; - gatt_pending_data->ascs_pending_cmd = GattPendingCmd::NONE; - tracker_.HandleInternalDisconnect(false); - return false; - } - - for (uint8_t i = 0; i < num_conn_streams ; i++) { - StreamConnect conn_stream = conn_streams->at(i); - StreamContext *context = contexts->FindOrAddByType( - conn_stream.stream_type); - if(ascs_state->state == GattState::CONNECTED) { - context->connection_state = IntConnectState::ASCS_DISCOVERING; - } - } - } break; - case ASCS_DISCOVERY_RES_EVT: { - AscsDiscovery ascs_discovery_ = *((AscsDiscovery *) p_data); - std::vector ase_ops; - AscsClient *ascs_client = strm_mgr_->GetAscsClient(); - std::vector sink_ase_list = ascs_discovery_.sink_ases_list; - std::vector src_ase_list = ascs_discovery_.src_ases_list; - // check the status - if(ascs_discovery_.status) { - tracker_.HandleInternalDisconnect(false); - return false; - } - - for (uint8_t i = 0; i < num_conn_streams ; i++) { - StreamConnect conn_stream = conn_streams->at(i); - StreamContext *context = contexts->FindOrAddByType( - conn_stream.stream_type); - context->connection_state = IntConnectState::ASCS_DISCOVERED; - } - - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - // create the UcastAudioStream for each ASEs (ase id) - // check if the entry is present, if not create and add it to list - // find out number of ASEs which are in IDLE state - for (auto & ase : sink_ase_list) { - audio_strms->FindOrAddByAseId(ase.ase_id, - ase.ase_state, ASE_DIRECTION_SINK); - } - - for (auto & ase : src_ase_list) { - audio_strms->FindOrAddByAseId(ase.ase_id, - ase.ase_state, ASE_DIRECTION_SRC); - } - - LOG(INFO) << __func__ << ": total num of audio strms: " - << audio_strms->size(); - - std::vector sink_int_trackers = - int_strm_trackers_.GetTrackerListByDir(ASE_DIRECTION_SINK); - - std::vector src_int_trackers = - int_strm_trackers_.GetTrackerListByDir(ASE_DIRECTION_SRC); - - std::vector state_ids = { StreamTracker::kStateIdle }; - - std::vector idle_sink_streams = - audio_strms->GetStreamsByStates(state_ids, - ASE_DIRECTION_SINK); - std::vector idle_src_streams = - audio_strms->GetStreamsByStates(state_ids, - ASE_DIRECTION_SRC); - LOG(INFO) << __func__ << ": Num of Sink Idle Streams = " - << idle_sink_streams.size() - << ": Num of Src Idle Streams = " - << idle_src_streams.size(); - - LOG(INFO) << __func__ << ": Num of Sink Internal Trackers = " - << sink_int_trackers.size() - << ": Num of Src Internal Trackers = " - << src_int_trackers.size(); - - LOG(INFO) << __func__ << ": Num of Conn Streams " - << loghex(num_conn_streams); - - // check how many stream connections are requested and - // how many streams(ASEs) are available for processing - // check if we have sufficient number of streams(ASEs) for - // the given set of connection requirement - DeviceType dev_type = strm_mgr_->GetDevType(); - uint8_t cis_count = 0; - if(dev_type == DeviceType::EARBUD || - dev_type == DeviceType::HEADSET_STEREO) { - cis_count = 1; - } else if(dev_type == DeviceType::HEADSET_SPLIT_STEREO) { - cis_count = 2; - } - - std::vector valid_state_ids = { - StreamTracker::kStateConnecting, - StreamTracker::kStateConnected, - StreamTracker::kStateStreaming, - StreamTracker::kStateReconfiguring, - StreamTracker::kStateDisconnecting, - StreamTracker::kStateStarting, - StreamTracker::kStateStopping - }; - - if(sink_int_trackers.size()) { - if(idle_sink_streams.size() >= sink_int_trackers.size()) { - AttachStreamsToContext(&sink_int_trackers, &idle_sink_streams, - cis_count, &ase_ops); - } else { - std::vector sink_int_trackers_1, - sink_int_trackers_2; - // split the sink_int_trackers into 2 lists now, one list - // is equal to idle_sink_streams as physical and other - // list as virtually attached - if(idle_sink_streams.size()) { // less num of free ASEs - for (uint8_t i = 0; i < idle_sink_streams.size() ; i++) { - IntStrmTracker *tracker = sink_int_trackers.at(i); - sink_int_trackers_1.push_back(tracker); - } - AttachStreamsToContext(&sink_int_trackers_1, &idle_sink_streams, - cis_count, &ase_ops); - for (uint8_t i = idle_sink_streams.size(); - i < sink_int_trackers.size() ; i++) { - IntStrmTracker *tracker = sink_int_trackers.at(i); - sink_int_trackers_2.push_back(tracker); - } - } - - std::vector all_active_sink_streams = - audio_strms->GetStreamsByStates(valid_state_ids, - ASE_DIRECTION_SINK); - - if(sink_int_trackers_2.size()) { - AttachStreamsToContext(&sink_int_trackers_2, &all_active_sink_streams, - cis_count, &ase_ops); - } else if(sink_int_trackers.size()) { - AttachStreamsToContext(&sink_int_trackers, &all_active_sink_streams, - cis_count, &ase_ops); - } - } - } - - // do the same procedure for src trackers as well - if(src_int_trackers.size()) { - if(idle_src_streams.size() >= src_int_trackers.size()) { - AttachStreamsToContext(&src_int_trackers, &idle_src_streams, - cis_count, &ase_ops); - } else { - std::vector src_int_trackers_1, - src_int_trackers_2; - // split the src_int_trackers into 2 lists now, one list - // is equal to idle_src_streams as physical and other - // list as virtually attached - if(idle_src_streams.size()) { // less num of free ASEs - for (uint8_t i = 0; i < idle_src_streams.size() ; i++) { - IntStrmTracker *tracker = src_int_trackers.at(i); - src_int_trackers_1.push_back(tracker); - } - AttachStreamsToContext(&src_int_trackers_1, &idle_src_streams, - cis_count, &ase_ops); - for (uint8_t i = idle_src_streams.size(); - i < src_int_trackers.size() ; i++) { - IntStrmTracker *tracker = src_int_trackers.at(i); - src_int_trackers_2.push_back(tracker); - } - } - - std::vector all_active_src_streams = - audio_strms->GetStreamsByStates(valid_state_ids, - ASE_DIRECTION_SRC); - - if(src_int_trackers_2.size()) { - AttachStreamsToContext(&src_int_trackers_2, &all_active_src_streams, - cis_count, &ase_ops); - } else if(src_int_trackers.size()) { - AttachStreamsToContext(&src_int_trackers, &all_active_src_streams, - cis_count, &ase_ops); - } - } - } - - // remove all duplicate internal stream trackers - int_strm_trackers_.RemoveVirtualAttachedTrackers(); - - // if the int strm trackers size is 0 then return as - // connected immediately - if(!int_strm_trackers_.size()) { - // update the state to connected - TransitionTo(StreamTracker::kStateConnected); - break; - } - - if(!ase_ops.empty()) { - LOG(WARNING) << __func__ << ": Going For ASCS CodecConfig op"; - ascs_client->CodecConfig(ASCS_CLIENT_ID, strm_mgr_->GetAddress(), - ase_ops); - } else { - tracker_.HandleInternalDisconnect(false); - break; - } - - // refresh the sink and src trackers - sink_int_trackers = - int_strm_trackers_.GetTrackerListByDir(ASE_DIRECTION_SINK); - - src_int_trackers = - int_strm_trackers_.GetTrackerListByDir(ASE_DIRECTION_SRC); - - LOG(INFO) << __func__ << ": Num of new Sink Internal Trackers = " - << sink_int_trackers.size() - << ": Num of new Src Internal Trackers = " - << src_int_trackers.size(); - - LOG(INFO) << __func__ << ": Num of new Sink Idle Streams = " - << idle_sink_streams.size() - << ": Num of new Src Idle Streams = " - << idle_src_streams.size(); - - // update the states to connecting or other internal states - if(sink_int_trackers.size()) { - for (uint8_t i = 0; i < sink_int_trackers.size() ; i++) { - UcastAudioStream *stream = idle_sink_streams.at(i); - stream->ase_pending_cmd = AscsPendingCmd::CODEC_CONFIG_ISSUED; - } - } - if(src_int_trackers.size()) { - for (uint8_t i = 0; i < src_int_trackers.size() ; i++) { - UcastAudioStream *stream = idle_src_streams.at(i); - stream->ase_pending_cmd = AscsPendingCmd::CODEC_CONFIG_ISSUED; - } - } - } break; - - case ASCS_ASE_STATE_EVT: { - tracker_.HandleAseStateEvent(p_data, StreamControlType::Connect, - &int_strm_trackers_); - } break; - - case ASCS_ASE_OP_FAILED_EVT: { - tracker_.HandleAseOpFailedEvent(p_data); - } break; - - case BAP_TIME_OUT_EVT: { - tracker_.OnTimeout(p_data); - } break; - - default: - LOG(WARNING) << __func__ << ": Un-handled event: " - << tracker_.GetEventName(event); - break; - } - return true; -} - - -void StreamTracker::StateConnected::OnEnter() { - LOG(INFO) << __func__ << ": StreamTracker State: " << GetState(); - - UcastClientCallbacks* callbacks = strm_mgr_->GetUclientCbacks(); - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - std::vector strms; - std::vector stream_configs; - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - PacsDiscovery *pacs_discovery_ = tracker_.GetPacsDiscovery(); - StreamControlType control_type = tracker_.GetControlType(); - std::vector conv_streams; - - if(control_type != StreamControlType::Connect && - control_type != StreamControlType::Stop && - control_type != StreamControlType::Reconfig) { - return; - } - - if(control_type == StreamControlType::Connect) { - std::vector *conn_streams = tracker_.GetConnStreams(); - for (auto it = conn_streams->begin(); it != conn_streams->end(); it++) { - StreamType type = it->stream_type; - conv_streams.push_back(type); - } - LOG(WARNING) << __func__ << ": Conn Streams Size " << conn_streams->size(); - } else if(control_type == StreamControlType::Reconfig) { - std::vector *reconf_streams = tracker_.GetReconfStreams(); - for (auto it = reconf_streams->begin(); it != reconf_streams->end();it++) { - StreamType type = it->stream_type; - conv_streams.push_back(type); - } - LOG(WARNING) << __func__ << ": Reconfig Streams size " - << reconf_streams->size(); - } else { - conv_streams = *tracker_.GetStreams(); - } - - if(control_type == StreamControlType::Connect || - control_type == StreamControlType::Reconfig) { - for (auto it = conv_streams.begin(); it != conv_streams.end(); it++) { - StreamContext *context = contexts->FindOrAddByType(*it); - UcastAudioStream *stream = audio_strms->FindByStreamType( - (*it).type, (*it).direction); - // avoid duplicate updates - if(context && pacs_discovery_ && - context->stream_state != StreamState::CONNECTED) { - StreamConfigInfo config; - memset(&config, 0, sizeof(config)); - config.stream_type = *it; - if(stream) { - config.codec_config = stream->codec_config; - config.qos_config = stream->qos_config; - context->qos_config = stream->qos_config; - } else { - config.codec_config = context->codec_config; - config.qos_config = context->req_qos_config; - context->qos_config = context->req_qos_config; - } - - //Keeping bits_per_sample as 24 always for LC3 - if (config.codec_config.codec_type == - CodecIndex::CODEC_INDEX_SOURCE_LC3) { - config.codec_config.bits_per_sample = - CodecBPS::CODEC_BITS_PER_SAMPLE_24; - } - - if(config.stream_type.direction == ASE_DIRECTION_SINK) { - config.audio_location = pacs_discovery_->sink_locations; - config.codecs_selectable = pacs_discovery_->sink_pac_records; - } else if(config.stream_type.direction == ASE_DIRECTION_SRC) { - config.audio_location = pacs_discovery_->src_locations; - config.codecs_selectable = pacs_discovery_->src_pac_records; - } - stream_configs.push_back(config); - } - } - - if(stream_configs.size()) { - callbacks->OnStreamConfig(strm_mgr_->GetAddress(), stream_configs); - } - } - - for (auto it = conv_streams.begin(); it != conv_streams.end(); it++) { - StreamContext *context = contexts->FindOrAddByType(*it); - // avoid duplicate updates - if( context->stream_state != StreamState::CONNECTED) { - StreamStateInfo state; - memset(&state, 0, sizeof(state)); - state.stream_type = *it; - state.stream_state = StreamState::CONNECTED; - context->stream_state = StreamState::CONNECTED; - strms.push_back(state); - } - } - - if(strms.size()) { - callbacks->OnStreamState(strm_mgr_->GetAddress(), strms); - } -} - -void StreamTracker::StateConnected::OnExit() { - -} - -bool StreamTracker::StateConnected::ProcessEvent(uint32_t event, void* p_data) { - LOG(INFO) <<__func__ <<": BD Addr = " << strm_mgr_->GetAddress() - <<": State = " << GetState() - <<": Event = " << tracker_.GetEventName(event); - - switch (event) { - case BAP_DISCONNECT_REQ_EVT: { - tracker_.HandleDisconnect(p_data, StreamTracker::kStateConnected); - } break; - - case BAP_START_REQ_EVT: { - PacsClient *pacs_client = strm_mgr_->GetPacsClient(); - uint16_t pacs_client_id = strm_mgr_->GetPacsClientId(); - - BapStart *evt_data = (BapStart *) p_data; - - tracker_.UpdateControlType(StreamControlType::Start); - - tracker_.UpdateStreams(&evt_data->streams); - - pacs_client->GetAudioAvailability(pacs_client_id, - strm_mgr_->GetAddress()); - - tracker_.TransitionTo(StreamTracker::kStateStarting); - } break; - - case BAP_RECONFIG_REQ_EVT: { - BapReconfig *evt_data = (BapReconfig *) p_data; - - tracker_.UpdateControlType(StreamControlType::Reconfig); - tracker_.UpdateReconfStreams(&evt_data->streams); - - // check if codec reconfiguration or qos reconfiguration - PacsClient *pacs_client = strm_mgr_->GetPacsClient(); - uint16_t pacs_client_id = strm_mgr_->GetPacsClientId(); - - // pacs is already connected so initiate - // pacs service discovry now and move the state to reconfiguring - pacs_client->StartDiscovery(pacs_client_id, strm_mgr_->GetAddress()); - - tracker_.TransitionTo(StreamTracker::kStateReconfiguring); - - } break; - case PACS_CONNECTION_STATE_EVT: { - tracker_.HandlePacsConnectionEvent(p_data); - } break; - case ASCS_CONNECTION_STATE_EVT: { - tracker_.HandleAscsConnectionEvent(p_data); - } break; - case ASCS_ASE_STATE_EVT: { - AscsState *ascs = ((AscsState *) p_data); - if(ascs->ase_params.ase_state == ascs::ASE_STATE_RELEASING) { - tracker_.HandleRemoteDisconnect(ASCS_ASE_STATE_EVT, p_data, StateId()); - } else if(ascs->ase_params.ase_state == - ascs::ASE_STATE_CODEC_CONFIGURED) { - tracker_.HandleRemoteReconfig(ASCS_ASE_STATE_EVT, p_data, StateId()); - } - } break; - default: - LOG(WARNING) << __func__ << ": Un-handled event: " - << tracker_.GetEventName(event); - break; - } - return true; -} - - -void StreamTracker::StateStarting::OnEnter() { - LOG(INFO) << __func__ << ": StreamTracker State: " << GetState(); - - UcastClientCallbacks* callbacks = strm_mgr_->GetUclientCbacks(); - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - std::vector strms; - std::vector *start_streams = tracker_.GetStreams(); - uint8_t num_ases = 0; - - LOG(WARNING) << __func__ << ": Start Streams Size: " - << start_streams->size(); - - StreamControlType control_type = tracker_.GetControlType(); - - if(control_type != StreamControlType::Start) return; - - for (auto it = start_streams->begin(); it != start_streams->end(); it++) { - StreamStateInfo state; - memset(&state, 0, sizeof(state)); - state.stream_type = *it; - state.stream_state = StreamState::STARTING; - strms.push_back(state); - StreamContext *context = contexts->FindOrAddByType(*it); - context->stream_state = StreamState::STARTING; - - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - int_strm_trackers_.FindOrAddBytrackerType(*it, - id->ase_id, id->cig_id, - id->cis_id, - context->codec_config, context->qos_config); - } - num_ases += context->stream_ids.size(); - } - callbacks->OnStreamState(strm_mgr_->GetAddress(), strms); - uint64_t tout = num_ases * - (static_cast(TimeoutVal::StartingTimeout)); - if(!tout) { - tout = static_cast(MaxTimeoutVal::StartingTimeout); - } - TimeoutReason reason = TimeoutReason::STATE_TRANSITION; - state_transition_timer = tracker_.SetTimer("StateStartingTimer", - &timeout, reason, tout); - if (state_transition_timer == nullptr) { - LOG(ERROR) << __func__ << ": StateStarting: Alarm not allocated."; - return; - } -} - -void StreamTracker::StateStarting::OnExit() { - tracker_.ClearTimer(state_transition_timer, "StateStartingTimer"); -} - -bool StreamTracker::CheckAndUpdateStreamingState( - IntStrmTrackers *int_strm_trackers) { - // to check for all internal trackers are moved to - // streaming state then update it upper layers - std::vector *all_trackers = - int_strm_trackers->GetTrackerList(); - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - uint8_t num_strms_in_streaming = 0; - - bool pending_cmds = false; - - // check if any pending commands are present - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if(stream && (stream->cis_pending_cmd != CisPendingCmd::NONE || - stream->ase_pending_cmd != AscsPendingCmd::NONE)) { - LOG(WARNING) << __func__ << ": cis_pending_cmd " - << loghex(static_cast (stream->cis_pending_cmd)); - LOG(WARNING) << __func__ << ": ase_pending_cmd " - << loghex(static_cast (stream->ase_pending_cmd)); - pending_cmds = true; - break; - } - } - - if(pending_cmds) { - LOG(WARNING) << __func__ << ": ASCS/CIS Pending commands left"; - return false; - } - - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (!stream) { - LOG(ERROR) << __func__ << "stream is null"; - continue; - } - if(stream->ase_state == ascs::ASE_STATE_STREAMING && - stream->cis_state == CisState::ESTABLISHED) { - num_strms_in_streaming++; - } - } - - if(int_strm_trackers->size() != num_strms_in_streaming) { - LOG(WARNING) << __func__ << ": Not all streams moved to streaming"; - return false; - } - - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (!stream) { - LOG(ERROR) << __func__ << "stream is null"; - continue; - } - stream->overall_state = StreamTracker::kStateStreaming; - } - - // all streams are moved to streaming state - TransitionTo(StreamTracker::kStateStreaming); - return true; -} - -bool StreamTracker::StateStarting::ProcessEvent(uint32_t event, void* p_data) { - LOG(INFO) <<__func__ <<": BD Addr = " << strm_mgr_->GetAddress() - <<": State = " << GetState() - <<": Event = " << tracker_.GetEventName(event); - - switch (event) { - case BAP_DISCONNECT_REQ_EVT: { - tracker_.HandleDisconnect(p_data, StreamTracker::kStateStarting); - } break; - case BAP_STOP_REQ_EVT: { - tracker_.HandleStop(p_data, StreamTracker::kStateStarting); - } break; - case BAP_STREAM_UPDATE_REQ_EVT: { - BapStreamUpdate *evt_data = (BapStreamUpdate *) p_data; - tracker_.UpdateMetaUpdateStreams(&evt_data->update_streams); - if(tracker_.HandlePacsAudioContextEvent(&pacs_contexts)) { - tracker_.HandleStreamUpdate(StreamTracker::kStateStarting); - } - } break; - case PACS_CONNECTION_STATE_EVT: { - tracker_.HandlePacsConnectionEvent(p_data); - } break; - case PACS_AUDIO_CONTEXT_RES_EVT: { - // check for all stream start requests, stream contexts are - // part of available contexts - pacs_contexts = *((PacsAvailableContexts *) p_data); - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - std::vector *all_trackers = - int_strm_trackers_.GetTrackerList(); - bool ignore_event = false; - - std::vector *start_streams = tracker_.GetStreams(); - uint8_t contexts_supported = 0; - - // check if supported audio contexts has required contexts - for(auto it = start_streams->begin(); it != start_streams->end(); it++) { - if(it->direction == ASE_DIRECTION_SINK) { - if(it->audio_context & pacs_contexts.available_contexts) { - contexts_supported++; - } - } else if(it->direction == ASE_DIRECTION_SRC) { - if((static_cast(it->audio_context) << 16) & - pacs_contexts.available_contexts) { - contexts_supported++; - } - } - } - - if(contexts_supported != start_streams->size()) { - LOG(ERROR) << __func__ << ": No Matching available Contexts found"; - tracker_.TransitionTo(StreamTracker::kStateConnected); - break; - } - - for (auto it = start_streams->begin(); it != start_streams->end(); it++) { - StreamContext *context = contexts->FindOrAddByType(*it); - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - UcastAudioStream *stream = audio_strms->FindByAseId(id->ase_id); - if (stream != nullptr && stream->overall_state == - StreamTracker::kStateStarting) { - ignore_event = true; - break; - } - } - } - - if(ignore_event) break; - - // Now create the groups - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (!stream) { - LOG(ERROR) << __func__ << "stream is null"; - continue; - } - QosConfig *qos_config = &stream->qos_config; - CisInterface *cis_intf = strm_mgr_->GetCisInterface(); - IsoHciStatus status = cis_intf->CreateCig(strm_mgr_->GetAddress(), - false, - qos_config->cig_config, - qos_config->cis_configs); - - LOG(WARNING) << __func__ << ": status: " - << loghex(static_cast(status)); - if( status == IsoHciStatus::ISO_HCI_SUCCESS) { - stream->cig_state = CigState::CREATED; - stream->cis_state = CisState::READY; - } else if (status == IsoHciStatus::ISO_HCI_IN_PROGRESS) { - stream->cis_pending_cmd = CisPendingCmd::CIG_CREATE_ISSUED; - } else { - LOG(ERROR) << __func__ << " CIG Creation Failed"; - } - } - tracker_.CheckAndSendEnable(&int_strm_trackers_); - } break; - - case CIS_GROUP_STATE_EVT: { - tracker_.HandleCigStateEvent(event, p_data, &int_strm_trackers_); - } break; - - case ASCS_CONNECTION_STATE_EVT: { - tracker_.HandleAscsConnectionEvent(p_data); - } break; - case ASCS_ASE_STATE_EVT: { - // to handle remote driven operations - // check the state and if the state is Enabling - // proceed with cis creation - AscsState *ascs = ((AscsState *) p_data); - - if(!tracker_.ValidateAseUpdate(p_data, &int_strm_trackers_, - StreamTracker::kStateStarting)) { - break; - } - - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - - if (ascs->ase_params.ase_state == ascs::ASE_STATE_ENABLING) { - // change the connection state to ENABLING - CisInterface *cis_intf = strm_mgr_->GetCisInterface(); - - // check for Enabling notification is received for all ASEs - std::vector *all_trackers = - int_strm_trackers_.GetTrackerList(); - - uint8_t num_enabling_notify = 0; - - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (!stream) { - LOG(ERROR) << __func__ << "stream is null"; - continue; - } - if(stream->ase_state == ascs::ASE_STATE_ENABLING) { - num_enabling_notify++; - } - } - - if(int_strm_trackers_.size() != num_enabling_notify) { - LOG(WARNING) << __func__ - << "Enabling notification is not received for all strms"; - break; - } - - // As it single group use cases, always single group start request - // will come to BAP layer - IsoHciStatus status; - std::vector cis_ids; - uint8_t cigId; - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (std::find(cis_ids.begin(), cis_ids.end(), - stream->cis_id) == cis_ids.end()) { - cis_ids.push_back(stream->cis_id); - cigId = stream->cig_id; - } - } - if(cis_ids.size()) { - LOG(WARNING) << __func__ << ": Going For CIS Creation "; - status = cis_intf->CreateCis(cigId, - cis_ids, - strm_mgr_->GetAddress()); - } - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (!stream) { - LOG(ERROR) << __func__ << "stream is null"; - continue; - } - stream->cis_retry_count = 0; - if( status == IsoHciStatus::ISO_HCI_SUCCESS) { - stream->cis_state = CisState::ESTABLISHED; - } else if (status == IsoHciStatus::ISO_HCI_IN_PROGRESS) { - // change the connection state to CIS create issued - stream->cis_pending_cmd = CisPendingCmd::CIS_CREATE_ISSUED; - } else { - LOG(WARNING) << __func__ << "CIS create Failed"; - } - } - } else if (ascs->ase_params.ase_state == ascs::ASE_STATE_STREAMING) { - tracker_.CheckAndUpdateStreamingState(&int_strm_trackers_); - - } else if(ascs->ase_params.ase_state == ascs::ASE_STATE_RELEASING) { - tracker_.HandleRemoteDisconnect(ASCS_ASE_STATE_EVT, p_data, StateId()); - - } else if(ascs->ase_params.ase_state == ascs::ASE_STATE_DISABLING) { - tracker_.HandleRemoteStop(ASCS_ASE_STATE_EVT, p_data, StateId()); - } - } break; - - case ASCS_ASE_OP_FAILED_EVT: { - tracker_.HandleAseOpFailedEvent(p_data); - } break; - - case CIS_STATE_EVT: { - CisStreamState *data = (CisStreamState *) p_data; - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - // check if current stream tracker is interested in this CIG update - std::vector int_trackers = - int_strm_trackers_.FindByCisId(data->cig_id, data->cis_id); - if(int_trackers.empty()) { - LOG(INFO) << __func__ << ": Not intended for this tracker"; - break; - } - - if(data->state == CisState::ESTABLISHED) { - // find out the CIS is bidirectional or from air direction - // cis, send Receiver start ready as set up data path - // is already completed during CIG creation - if(data->direction & cis::DIR_FROM_AIR) { - // setup the datapath for RX - // find out the stream here - UcastAudioStream *stream = audio_strms->FindByCisIdAndDir - (data->cig_id, data->cis_id, - cis::DIR_FROM_AIR); - LOG(WARNING) << __func__ << " DIR_FROM_AIR " - << loghex(static_cast (cis::DIR_FROM_AIR)); - - if(stream && int_strm_trackers_.FindByAseId(stream->ase_id)) { - LOG(INFO) << __func__ << ": Stream Direction " - << loghex(static_cast (stream->direction)); - - LOG(INFO) << __func__ << ": Stream ASE Id " - << loghex(static_cast (stream->ase_id)); - - AscsClient *ascs_client = strm_mgr_->GetAscsClient(); - AseStartReadyOp start_ready_op = { - .ase_id = stream->ase_id - }; - std::vector ase_ops; - ase_ops.push_back(start_ready_op); - ascs_client->StartReady(ASCS_CLIENT_ID, - strm_mgr_->GetAddress(), ase_ops); - stream->cis_state = data->state; - stream->cis_pending_cmd = CisPendingCmd::NONE; - stream->ase_pending_cmd = AscsPendingCmd::START_READY_ISSUED; - } - } - - if(data->direction & cis::DIR_TO_AIR) { - UcastAudioStream *stream = audio_strms->FindByCisIdAndDir - (data->cig_id, data->cis_id, - cis::DIR_TO_AIR); - if(stream) { - stream->cis_state = data->state; - stream->cis_pending_cmd = CisPendingCmd::NONE; - } - } - - tracker_.CheckAndUpdateStreamingState(&int_strm_trackers_); - - } else if (data->state == CisState::READY) { // CIS creation failed - CisInterface *cis_intf = strm_mgr_->GetCisInterface(); - UcastAudioStream *stream = audio_strms->FindByCisIdAndDir - (data->cig_id, data->cis_id, - data->direction); - if(stream && stream->cis_retry_count < 2) { - std::vector cisIds = {stream->cis_id}; - LOG(WARNING) << __func__ << ": Going For Retrial of CIS Creation "; - IsoHciStatus status = cis_intf->CreateCis( - stream->cig_id, - cisIds, - strm_mgr_->GetAddress()); - - if( status == IsoHciStatus::ISO_HCI_SUCCESS) { - stream->cis_state = CisState::ESTABLISHED; - tracker_.CheckAndUpdateStreamingState(&int_strm_trackers_); - } else if (status == IsoHciStatus::ISO_HCI_IN_PROGRESS) { - // change the connection state to CIS create issued - stream->cis_retry_count++; - stream->cis_pending_cmd = CisPendingCmd::CIS_CREATE_ISSUED; - } else { - stream->cis_retry_count = 0; - LOG(WARNING) << __func__ << "CIS create Failed"; - } - } else { - if(stream) { - stream->cis_retry_count = 0; - stream->cis_state = data->state; - stream->cis_pending_cmd = CisPendingCmd::NONE; - } - } - } else { // transient states - UcastAudioStream *stream = audio_strms->FindByCisIdAndDir - (data->cig_id, data->cis_id, - data->direction); - if(stream) stream->cis_state = data->state; - } - } break; - - case BAP_TIME_OUT_EVT: { - tracker_.OnTimeout(p_data); - } break; - - default: - LOG(WARNING) << __func__ << ": Un-handled event: " - << tracker_.GetEventName(event); - break; - } - return true; -} - -void StreamTracker::StateUpdating::OnEnter() { - LOG(INFO) << __func__ << ": StreamTracker State: " << GetState(); - - UcastClientCallbacks* callbacks = strm_mgr_->GetUclientCbacks(); - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - std::vector strms; - std::vector *update_streams = tracker_.GetMetaUpdateStreams(); - uint8_t num_ases = 0; - - LOG(WARNING) << __func__ << ": Start Streams Size " - << update_streams->size(); - - StreamControlType control_type = tracker_.GetControlType(); - - if(control_type != StreamControlType::UpdateStream) return; - - for (auto it = update_streams->begin(); it != update_streams->end(); it++) { - StreamStateInfo state; - memset(&state, 0, sizeof(state)); - state.stream_type = it->stream_type; - state.stream_state = StreamState::UPDATING; - strms.push_back(state); - StreamContext *context = contexts->FindOrAddByType(it->stream_type); - context->stream_state = StreamState::UPDATING; - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - int_strm_trackers_.FindOrAddBytrackerType(it->stream_type, - id->ase_id, id->cig_id, - id->cis_id, - context->codec_config, context->qos_config); - } - num_ases += context->stream_ids.size(); - } - callbacks->OnStreamState(strm_mgr_->GetAddress(), strms); - - uint64_t tout = num_ases * - (static_cast(TimeoutVal::UpdatingTimeout)); - if(!tout) { - tout = static_cast(MaxTimeoutVal::UpdatingTimeout); - } - TimeoutReason reason = TimeoutReason::STATE_TRANSITION; - state_transition_timer = tracker_.SetTimer("StateUpdatingTimer", - &timeout, reason, tout); - if (state_transition_timer == nullptr) { - LOG(ERROR) << __func__ << ": StateUpdating: Alarm not allocated."; - return; - } -} - -void StreamTracker::StateUpdating::OnExit() { - tracker_.ClearTimer(state_transition_timer, "StateUpdatingTimer"); -} - -bool StreamTracker::StateUpdating::ProcessEvent(uint32_t event, void* p_data) { - LOG(INFO) <<__func__ <<": BD Addr = " << strm_mgr_->GetAddress() - <<": State = " << GetState() - <<": Event = " << tracker_.GetEventName(event); - - switch (event) { - case BAP_DISCONNECT_REQ_EVT: { - tracker_.HandleDisconnect(p_data, StreamTracker::kStateUpdating); - } break; - case BAP_STOP_REQ_EVT: { - tracker_.HandleStop(p_data, StreamTracker::kStateUpdating); - } break; - case PACS_CONNECTION_STATE_EVT: { - tracker_.HandlePacsConnectionEvent(p_data); - } break; - case ASCS_CONNECTION_STATE_EVT: { - tracker_.HandleAscsConnectionEvent(p_data); - } break; - case PACS_AUDIO_CONTEXT_RES_EVT: { - // check for all stream start requests, stream contexts are - // part of available contexts - PacsAvailableContexts *pacs_contexts = (PacsAvailableContexts *) p_data; - if(!tracker_.HandlePacsAudioContextEvent(pacs_contexts) || - !tracker_.HandleStreamUpdate(StreamTracker::kStateUpdating)) { - tracker_.TransitionTo(StreamTracker::kStateStreaming); - } - } break; - case ASCS_ASE_STATE_EVT: { - AscsState *ascs = ((AscsState *) p_data); - if(!tracker_.ValidateAseUpdate(p_data, &int_strm_trackers_, - StreamTracker::kStateUpdating)) { - break; - } - if(ascs->ase_params.ase_state == ascs::ASE_STATE_STREAMING) { - tracker_.CheckAndUpdateStreamingState(&int_strm_trackers_); - } else if(ascs->ase_params.ase_state == ascs::ASE_STATE_RELEASING) { - tracker_.HandleRemoteDisconnect(ASCS_ASE_STATE_EVT, p_data, StateId()); - } else if(ascs->ase_params.ase_state == ascs::ASE_STATE_DISABLING) { - tracker_.HandleRemoteStop(ASCS_ASE_STATE_EVT, p_data, StateId()); - } else if(ascs->ase_params.ase_state == ascs::ASE_STATE_QOS_CONFIGURED) { - // this can happen when CIS is lost and detected on remote side - // first so it will immediately transition to QOS configured. - tracker_.HandleAbruptStop(ASCS_ASE_STATE_EVT, p_data); - } - } break; - case CIS_STATE_EVT: { - // handle sudden CIS Disconnection - tracker_.HandleCisEventsInStreaming(p_data); - } break; - default: - LOG(WARNING) << __func__ << ": Un-handled event: " - << tracker_.GetEventName(event); - break; - } - return true; -} - -void StreamTracker::StateStreaming::OnEnter() { - LOG(INFO) << __func__ << ": StreamTracker State: " << GetState(); - - UcastClientCallbacks* callbacks = strm_mgr_->GetUclientCbacks(); - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - std::vector strms; - std::vector *start_streams = tracker_.GetStreams(); - std::vector *update_streams = tracker_.GetMetaUpdateStreams(); - LOG(WARNING) << __func__ << ": Start Streams Size " - << start_streams->size(); - - LOG(WARNING) << __func__ << ": Update Streams Size " - << update_streams->size(); - - StreamControlType control_type = tracker_.GetControlType(); - - if(control_type == StreamControlType::Start) { - for (auto it = start_streams->begin(); it != start_streams->end(); it++) { - StreamStateInfo state; - memset(&state, 0, sizeof(state)); - state.stream_type = *it; - state.stream_state = StreamState::STREAMING; - strms.push_back(state); - StreamContext *context = contexts->FindOrAddByType(*it); - context->stream_state = StreamState::STREAMING; - } - } else if(control_type == StreamControlType::UpdateStream) { - for (auto it = update_streams->begin(); it != update_streams->end(); it++) { - StreamStateInfo state; - memset(&state, 0, sizeof(state)); - state.stream_type = it->stream_type; - state.stream_state = StreamState::STREAMING; - strms.push_back(state); - StreamContext *context = contexts->FindOrAddByType(it->stream_type); - context->stream_state = StreamState::STREAMING; - } - } - if(strms.size()) { - callbacks->OnStreamState(strm_mgr_->GetAddress(), strms); - } -} - -void StreamTracker::StateStreaming::OnExit() { - -} - -bool StreamTracker::StateStreaming::ProcessEvent(uint32_t event, void* p_data) { - LOG(INFO) <<__func__ <<": BD Addr = " << strm_mgr_->GetAddress() - <<": State = " << GetState() - <<": Event = " << tracker_.GetEventName(event); - - switch (event) { - case BAP_DISCONNECT_REQ_EVT: { - tracker_.HandleDisconnect(p_data, StreamTracker::kStateStreaming); - } break; - case BAP_STOP_REQ_EVT: { - tracker_.HandleStop(p_data, StreamTracker::kStateStreaming); - } break; - case BAP_STREAM_UPDATE_REQ_EVT: { - PacsClient *pacs_client = strm_mgr_->GetPacsClient(); - uint16_t pacs_client_id = strm_mgr_->GetPacsClientId(); - BapStreamUpdate *evt_data = (BapStreamUpdate *) p_data; - tracker_.UpdateControlType(StreamControlType::UpdateStream); - tracker_.UpdateMetaUpdateStreams(&evt_data->update_streams); - pacs_client->GetAudioAvailability(pacs_client_id, - strm_mgr_->GetAddress()); - tracker_.TransitionTo(StreamTracker::kStateUpdating); - } break; - case PACS_CONNECTION_STATE_EVT: { - tracker_.HandlePacsConnectionEvent(p_data); - } break; - case ASCS_CONNECTION_STATE_EVT: { - tracker_.HandleAscsConnectionEvent(p_data); - } break; - case ASCS_ASE_STATE_EVT: { - AscsState *ascs = ((AscsState *) p_data); - uint8_t ase_id = ascs->ase_params.ase_id; - // find out the stream for the given ase id - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - UcastAudioStream *stream = audio_strms->FindByAseId(ase_id); - if (stream) { - stream->ase_state = ascs->ase_params.ase_state; - stream->ase_params = ascs->ase_params; - stream->ase_pending_cmd = AscsPendingCmd::NONE; - if(ascs->ase_params.ase_state == ascs::ASE_STATE_RELEASING) { - tracker_.HandleRemoteDisconnect(ASCS_ASE_STATE_EVT, p_data, StateId()); - } else if(ascs->ase_params.ase_state == ascs::ASE_STATE_DISABLING) { - tracker_.HandleRemoteStop(ASCS_ASE_STATE_EVT, p_data, StateId()); - } else if(ascs->ase_params.ase_state == ascs::ASE_STATE_QOS_CONFIGURED){ - // this can happen when CIS is lost and detected on remote side - // first so it will immediately transition to QOS configured. - tracker_.HandleAbruptStop(ASCS_ASE_STATE_EVT, p_data); - } - } - } break; - case CIS_STATE_EVT: { - // handle sudden CIS Disconnection - tracker_.HandleCisEventsInStreaming(p_data); - } break; - default: - LOG(WARNING) << __func__ << ": Un-handled event: " - << tracker_.GetEventName(event); - break; - } - return true; -} - -void StreamTracker::StateStopping::OnEnter() { - LOG(INFO) << __func__ << ": StreamTracker State: " << GetState(); - - UcastClientCallbacks* callbacks = strm_mgr_->GetUclientCbacks(); - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - std::vector strms; - std::vector *stop_streams = tracker_.GetStreams(); - uint8_t num_ases = 0; - - LOG(WARNING) << __func__ << ": Stop Streams Size : " - << stop_streams->size(); - StreamControlType control_type = tracker_.GetControlType(); - - if(control_type != StreamControlType::Stop) return; - - for (auto it = stop_streams->begin(); - it != stop_streams->end(); it++) { - StreamStateInfo state; - memset(&state, 0, sizeof(state)); - state.stream_type = *it; - state.stream_state = StreamState::STOPPING; - strms.push_back(state); - StreamContext *context = contexts->FindOrAddByType(*it); - context->stream_state = StreamState::STOPPING; - - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - int_strm_trackers_.FindOrAddBytrackerType(*it, - id->ase_id, id->cig_id, - id->cis_id, - context->codec_config, context->qos_config); - } - num_ases += context->stream_ids.size(); - } - callbacks->OnStreamState(strm_mgr_->GetAddress(), strms); - - uint64_t tout = num_ases * - (static_cast(TimeoutVal::StoppingTimeout)); - if(!tout) { - tout = static_cast(MaxTimeoutVal::StoppingTimeout); - } - - TimeoutReason reason = TimeoutReason::STATE_TRANSITION; - state_transition_timer = tracker_.SetTimer("StateStoppingTimer", - &timeout, reason, tout); - if (state_transition_timer == nullptr) { - LOG(ERROR) << __func__ << ": StateStopping: Alarm not allocated."; - return; - } -} - -void StreamTracker::StateStopping::OnExit() { - tracker_.ClearTimer(state_transition_timer, "StateStoppingTimer"); -} - -bool StreamTracker::StateStopping::TerminateCisAndCig(UcastAudioStream *stream) { - - CisInterface *cis_intf = strm_mgr_->GetCisInterface(); - uint8_t num_strms_in_qos_configured = 0; - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - - std::vector all_trackers = - int_strm_trackers_.FindByCigIdAndDir(stream->cig_id, - stream->direction); - - for(auto i = all_trackers.begin(); i != all_trackers.end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (!stream) { - LOG(ERROR) << __func__ << "stream is null"; - continue; - } - if(stream->ase_state == ascs::ASE_STATE_QOS_CONFIGURED) { - num_strms_in_qos_configured++; - } - } - - if(all_trackers.size() != num_strms_in_qos_configured) { - LOG(WARNING) << __func__ << "Not All Streams Moved to QOS Configured"; - return false; - } - - for (auto i = all_trackers.begin(); i != all_trackers.end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (!stream) { - LOG(ERROR) << __func__ << "stream is null"; - continue; - } - if(stream->cis_pending_cmd == CisPendingCmd::NONE && - stream->cis_state == CisState::ESTABLISHED && - stream->ase_state == ascs::ASE_STATE_QOS_CONFIGURED) { - LOG(WARNING) << __func__ << ": Going For CIS Disconnect "; - IsoHciStatus status = cis_intf->DisconnectCis(stream->cig_id, - stream->cis_id, - stream->direction); - if(status == IsoHciStatus::ISO_HCI_SUCCESS) { - stream->cis_pending_cmd = CisPendingCmd::NONE; - stream->cis_state = CisState::READY; - } else if(status == IsoHciStatus::ISO_HCI_IN_PROGRESS) { - stream->cis_pending_cmd = CisPendingCmd::CIS_DESTROY_ISSUED; - } else { - LOG(WARNING) << __func__ << ": CIS Disconnect Failed"; - } - } - - if(stream->cis_state == CisState::READY) { - if(stream->cig_state == CigState::CREATED && - stream->cis_pending_cmd == CisPendingCmd::NONE) { - LOG(WARNING) << __func__ << ": Going For CIG Removal"; - IsoHciStatus status = cis_intf->RemoveCig(strm_mgr_->GetAddress(), - stream->cig_id); - if( status == IsoHciStatus::ISO_HCI_SUCCESS) { - stream->cig_state = CigState::INVALID; - stream->cis_state = CisState::INVALID; - } else if (status == IsoHciStatus::ISO_HCI_IN_PROGRESS) { - stream->cis_pending_cmd = CisPendingCmd::CIG_REMOVE_ISSUED; - } else { - LOG(WARNING) << __func__ << ": CIG removal Failed"; - } - } - } - } - return true; -} - -bool StreamTracker::StateStopping::CheckAndUpdateStoppedState() { - // to check for all internal trackers are moved to - // cis destroyed state then update the callback - uint8_t num_strms_in_stopping = 0; - bool pending_cmds = false; - - std::vector *all_trackers = - int_strm_trackers_.GetTrackerList(); - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - - // check if any pending commands are present - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if(stream && (stream->cis_pending_cmd != CisPendingCmd::NONE || - stream->ase_pending_cmd != AscsPendingCmd::NONE)) { - pending_cmds = true; - break; - } - } - - if(pending_cmds) return false; - - for(auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if(stream && (stream->cig_state == CigState::IDLE || - stream->cig_state == CigState::INVALID) && - (stream->cis_state == CisState::READY || - stream->cis_state == CisState::INVALID) && - stream->ase_state == ascs::ASE_STATE_QOS_CONFIGURED) { - num_strms_in_stopping++; - } - } - - if(int_strm_trackers_.size() != num_strms_in_stopping) { - LOG(WARNING) << __func__ << "Not All Streams Moved to Stopped State"; - return false; - } - - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (!stream) { - LOG(ERROR) << __func__ << "stream is null"; - continue; - } - stream->overall_state = StreamTracker::kStateConnected; - } - - tracker_.TransitionTo(StreamTracker::kStateConnected); - return true; -} - -bool StreamTracker::StateStopping::ProcessEvent(uint32_t event, void* p_data) { - LOG(INFO) <<__func__ <<": BD Addr = " << strm_mgr_->GetAddress() - <<": State = " << GetState() - <<": Event = " << tracker_.GetEventName(event); - - switch (event) { - case BAP_DISCONNECT_REQ_EVT:{ - tracker_.HandleDisconnect(p_data, StreamTracker::kStateStopping); - } break; - case PACS_CONNECTION_STATE_EVT: { - tracker_.HandlePacsConnectionEvent(p_data); - } break; - case ASCS_CONNECTION_STATE_EVT: { - tracker_.HandleAscsConnectionEvent(p_data); - } break; - case ASCS_ASE_STATE_EVT: { - // to handle remote driven operations - AscsState *ascs = ((AscsState *) p_data); - - if(!tracker_.ValidateAseUpdate(p_data, &int_strm_trackers_, - StreamTracker::kStateStopping)) { - break; - } - - // find out the stream for the given ase id - uint8_t ase_id = ascs->ase_params.ase_id; - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - - UcastAudioStream *stream = audio_strms->FindByAseId(ase_id); - if (!stream) { - LOG(ERROR) << __func__ << "stream is null"; - break; - } - - if(ascs->ase_params.ase_state == ascs::ASE_STATE_DISABLING) { - if(stream->direction & cis::DIR_FROM_AIR) { - LOG(INFO) << __func__ << " Sending Stop Ready "; - AscsClient *ascs_client = strm_mgr_->GetAscsClient(); - AseStopReadyOp stop_ready_op = { - .ase_id = stream->ase_id - }; - std::vector ase_ops; - ase_ops.push_back(stop_ready_op); - ascs_client->StopReady(ASCS_CLIENT_ID, - strm_mgr_->GetAddress(), ase_ops); - stream->ase_pending_cmd = AscsPendingCmd::STOP_READY_ISSUED; - } else { - LOG(ERROR) << __func__ << ": Invalid State transition to Disabling" - << ": ASE Id = " << loghex(ase_id); - } - - } else if(ascs->ase_params.ase_state == ascs::ASE_STATE_QOS_CONFIGURED) { - - stream->ase_pending_cmd = AscsPendingCmd::NONE; - // stopped state then issue CIS disconnect - TerminateCisAndCig(stream); - CheckAndUpdateStoppedState(); - - } else if(ascs->ase_params.ase_state == ascs::ASE_STATE_RELEASING) { - tracker_.HandleRemoteDisconnect(ASCS_ASE_STATE_EVT, p_data, StateId()); - } - } break; - - case ASCS_ASE_OP_FAILED_EVT: { - tracker_.HandleAseOpFailedEvent(p_data); - } break; - - case CIS_STATE_EVT: { - CisStreamState *data = (CisStreamState *) p_data; - CisInterface *cis_intf = strm_mgr_->GetCisInterface(); - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - // check if current stream tracker is interested in this CIG update - std::vector int_trackers = - int_strm_trackers_.FindByCisId(data->cig_id, data->cis_id); - if(int_trackers.empty()) { - LOG(INFO) << __func__ << "Not intended for this tracker"; - break; - } - if(data->state == CisState::ESTABLISHED) { - for(auto it = directions.begin(); it != directions.end(); ++it) { - if(data->direction & *it) { - // find out the stream here - UcastAudioStream *stream = audio_strms->FindByCisIdAndDir - (data->cig_id, data->cis_id, *it); - if(stream) { - stream->cis_state = data->state; - stream->cis_pending_cmd = CisPendingCmd::NONE; - if(int_strm_trackers_.FindByAseId(stream->ase_id)) { - TerminateCisAndCig(stream); - } - } - } - } - CheckAndUpdateStoppedState(); - - } else if(data->state == CisState::READY) { - for(auto it = directions.begin(); it != directions.end(); ++it) { - if(data->direction & *it) { - // find out the stream here - UcastAudioStream *stream = audio_strms->FindByCisIdAndDir - (data->cig_id, data->cis_id, *it); - if(stream) { - stream->cis_state = data->state; - stream->cis_pending_cmd = CisPendingCmd::NONE; - if(stream->cig_state == CigState::CREATED && - stream->cis_pending_cmd == CisPendingCmd::NONE) { - IsoHciStatus status = cis_intf->RemoveCig( - strm_mgr_->GetAddress(), - stream->cig_id); - if( status == IsoHciStatus::ISO_HCI_SUCCESS) { - stream->cig_state = CigState::INVALID; - stream->cis_state = CisState::INVALID; - } else if (status == IsoHciStatus::ISO_HCI_IN_PROGRESS) { - stream->cis_pending_cmd = CisPendingCmd::CIG_REMOVE_ISSUED; - } else { - LOG(WARNING) << __func__ << ": CIG removal Failed"; - } - } - } - } - } - CheckAndUpdateStoppedState(); - } else { // transient states - for(auto it = directions.begin(); it != directions.end(); ++it) { - if(data->direction & *it) { - // find out the stream here - UcastAudioStream *stream = audio_strms->FindByCisIdAndDir - (data->cig_id, data->cis_id, *it); - if(stream) stream->cis_state = data->state; - } - } - } - } break; - - case CIS_GROUP_STATE_EVT: { - CisGroupState *data = ((CisGroupState *) p_data); - // check if current stream tracker is interested in this CIG update - std::vector int_trackers = - int_strm_trackers_.FindByCigId(data->cig_id); - if(int_trackers.empty()) { - LOG(INFO) << __func__ << "Not intended for this tracker"; - break; - } - - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - if(data->state == CigState::CREATED) { - for (auto i = int_trackers.begin(); i != int_trackers.end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (stream) { - // check if this is a CIG created event due to CIG create - // issued during starting state - stream->cis_pending_cmd = CisPendingCmd::NONE; - stream->cig_state = data->state; - stream->cis_state = CisState::READY; - TerminateCisAndCig(stream); - } - } - CheckAndUpdateStoppedState(); - - } else if(data->state == CigState::IDLE) { - for (auto i = int_trackers.begin(); i != int_trackers.end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (stream) { - stream->cig_state = CigState::INVALID; - stream->cis_state = CisState::INVALID; - stream->cis_pending_cmd = CisPendingCmd::NONE; - } - } - CheckAndUpdateStoppedState(); - } - } break; - case BAP_TIME_OUT_EVT: { - tracker_.OnTimeout(p_data); - } break; - - default: - LOG(WARNING) << __func__ << ": Un-handled event: " - << tracker_.GetEventName(event); - break; - } - return true; -} - -bool StreamTracker::StateDisconnecting::TerminateGattConnection() { - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - GattPendingData *gatt_pending_data = strm_mgr_->GetGattPendingData(); - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - std::vector *all_contexts = contexts->GetAllContexts(); - bool any_context_active = false; - bool disc_issued = false; - std::vector ids = { StreamTracker::kStateIdle }; - std::vector idle_streams = - audio_strms->GetStreamsByStates( - ids, ASE_DIRECTION_SINK | ASE_DIRECTION_SRC); - - LOG(WARNING) << __func__ <<": Total Streams size: " << audio_strms->size() - <<": Idle Streams size: " << idle_streams.size(); - - // check if any of the contexts stream state is connected - for (auto it = all_contexts->begin(); it != all_contexts->end(); it++) { - if((*it)->stream_state != StreamState::DISCONNECTING && - (*it)->stream_state != StreamState::DISCONNECTED) { - LOG(INFO) << __func__ <<": Other contexts are active,not to disc Gatt"; - any_context_active = true; - break; - } - } - if(!any_context_active && - (!audio_strms->size() || audio_strms->size() == idle_streams.size())) { - - // check if gatt connection can be tear down for ascs & pacs clients - // all streams are in idle state - AscsClient *ascs_client = strm_mgr_->GetAscsClient(); - PacsClient *pacs_client = strm_mgr_->GetPacsClient(); - uint16_t pacs_client_id = strm_mgr_->GetPacsClientId(); - - ConnectionState pacs_state = strm_mgr_->GetPacsState(); - if((pacs_state == ConnectionState::CONNECTED && - gatt_pending_data->pacs_pending_cmd == GattPendingCmd::NONE) || - (gatt_pending_data->pacs_pending_cmd == - GattPendingCmd::GATT_CONN_PENDING)) { - LOG(WARNING) << __func__ << " Issue PACS server disconnect "; - pacs_client->Disconnect(pacs_client_id, strm_mgr_->GetAddress()); - gatt_pending_data->pacs_pending_cmd = GattPendingCmd::GATT_DISC_PENDING; - disc_issued = true; - } - - GattState ascs_state = strm_mgr_->GetAscsState(); - if((ascs_state == GattState::CONNECTED && - gatt_pending_data->ascs_pending_cmd == GattPendingCmd::NONE) || - (gatt_pending_data->ascs_pending_cmd == - GattPendingCmd::GATT_CONN_PENDING)) { - LOG(WARNING) << __func__ << " Issue ASCS server disconnect "; - ascs_client->Disconnect(ASCS_CLIENT_ID, strm_mgr_->GetAddress()); - gatt_pending_data->ascs_pending_cmd = GattPendingCmd::GATT_DISC_PENDING; - disc_issued = true; - } - } - return disc_issued; -} - -void StreamTracker::StateDisconnecting::OnEnter() { - LOG(INFO) << __func__ << ": StreamTracker State: " << GetState(); - - // check the previous state i.e connecting, starting, stopping - // or reconfiguring - - UcastClientCallbacks* callbacks = strm_mgr_->GetUclientCbacks(); - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - std::vector strms; - uint8_t num_ases = 0; - - std::vector *disc_streams = tracker_.GetStreams(); - LOG(WARNING) << __func__ << ": Disconection Streams Size: " - << disc_streams->size(); - - StreamControlType control_type = tracker_.GetControlType(); - - if(control_type != StreamControlType::Disconnect) { - return; - } - - for (auto it = disc_streams->begin(); it != disc_streams->end(); it++) { - StreamStateInfo state; - memset(&state, 0, sizeof(state)); - state.stream_type = *it; - state.stream_state = StreamState::DISCONNECTING; - strms.push_back(state); - StreamContext *context = contexts->FindOrAddByType(*it); - context->stream_state = StreamState::DISCONNECTING; - if(context->connection_state == IntConnectState::ASCS_DISCOVERED) { - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - bool can_be_disconnected = tracker_. - StreamCanbeDisconnected(context, id->ase_id); - if(can_be_disconnected) { - int_strm_trackers_.FindOrAddBytrackerType(*it, - id->ase_id, id->cig_id, - id->cis_id, - context->codec_config, context->qos_config); - } - } - } - num_ases += context->stream_ids.size(); - } - callbacks->OnStreamState(strm_mgr_->GetAddress(), strms); - - uint64_t tout = num_ases * - (static_cast(TimeoutVal::DisconnectingTimeout)); - if(!tout ||tout > static_cast(MaxTimeoutVal::DisconnectingTimeout)) { - tout = static_cast(MaxTimeoutVal::DisconnectingTimeout); - } - - TimeoutReason reason = TimeoutReason::STATE_TRANSITION; - state_transition_timer = tracker_.SetTimer("StateDisconnectingTimer", - &timeout, reason, tout); - if (state_transition_timer == nullptr) { - LOG(ERROR) << __func__ << ": StateDisconnecting: Alarm not allocated."; - return; - } - - bool gatt_disc_pending = TerminateGattConnection(); - // check if there are no internal stream trackers, then update to - // upper layer as completely disconnected - if(!int_strm_trackers_.size() && !gatt_disc_pending) { - tracker_.TransitionTo(StreamTracker::kStateIdle); - } -} - -void StreamTracker::StateDisconnecting::ContinueDisconnection - (UcastAudioStream *stream) { - - // check ase state, return if state is not releasing or - if(stream->ase_state != ascs::ASE_STATE_IDLE && - stream->ase_state != ascs::ASE_STATE_CODEC_CONFIGURED && - stream->ase_state != ascs::ASE_STATE_RELEASING) { - LOG(WARNING) << __func__ << " Return as ASE is not moved to Right state"; - return; - } - - CisInterface *cis_intf = strm_mgr_->GetCisInterface(); - - // check if there is no pending CIS command then issue relevant - // CIS command based on CIS state - if(stream->cis_pending_cmd != CisPendingCmd::NONE) { - LOG(INFO) << __func__ << ": cis_pending_cmd is not NONE "; - return; - } - - if(stream->cis_state == CisState::ESTABLISHED) { - LOG(WARNING) << __func__ << ": Going For CIS disconnect "; - IsoHciStatus status = cis_intf->DisconnectCis(stream->cig_id, - stream->cis_id, - stream->direction); - if(status == IsoHciStatus::ISO_HCI_SUCCESS) { - stream->cis_pending_cmd = CisPendingCmd::NONE; - stream->cis_state = CisState::READY; - } else if(status == IsoHciStatus::ISO_HCI_IN_PROGRESS) { - stream->cis_pending_cmd = CisPendingCmd::CIS_DESTROY_ISSUED; - } else { - LOG(WARNING) << __func__ << ": CIS Disconnect Failed"; - } - } - - if(stream->cis_state == CisState::READY) { - if(stream->cig_state == CigState::CREATED && - stream->cis_pending_cmd == CisPendingCmd::NONE) { - LOG(WARNING) << __func__ << ": Going For CIG Removal"; - IsoHciStatus status = cis_intf->RemoveCig(strm_mgr_->GetAddress(), - stream->cig_id); - if( status == IsoHciStatus::ISO_HCI_SUCCESS) { - stream->cig_state = CigState::INVALID; - stream->cis_state = CisState::INVALID; - } else if (status == IsoHciStatus::ISO_HCI_IN_PROGRESS) { - stream->cis_pending_cmd = CisPendingCmd::CIG_REMOVE_ISSUED; - } else { - LOG(WARNING) << __func__ << ": CIG removal Failed"; - } - } - } -} - -bool StreamTracker::StateDisconnecting::CheckAndUpdateDisconnectedState() { - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - bool pending_cmds = false; - - std::vector *all_trackers = - int_strm_trackers_.GetTrackerList(); - - // check if any pending commands are present - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if(stream && (stream->cis_pending_cmd != CisPendingCmd::NONE || - stream->ase_pending_cmd != AscsPendingCmd::NONE)) { - pending_cmds = true; - break; - } - } - - if(pending_cmds) { - LOG(WARNING) << __func__ << " Pending ASCS/CIS cmds present "; - return false; - } - - TerminateGattConnection(); - - // check it needs to wait for ASCS & PACS disconnection also - GattPendingData *gatt_pending_data = strm_mgr_->GetGattPendingData(); - if(gatt_pending_data->ascs_pending_cmd != GattPendingCmd::NONE || - gatt_pending_data->pacs_pending_cmd != GattPendingCmd::NONE) { - LOG(WARNING) << __func__ << " Pending Gatt disc present "; - return false; - } - - // check for all trackers moved to idle and - // CIG state is idle if so update it as streams are disconnected - uint8_t num_strms_disconnected = 0; - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (!stream) { - LOG(ERROR) << __func__ << "stream is null"; - continue; - } - if((stream->ase_state == ascs::ASE_STATE_IDLE || - stream->ase_state == ascs::ASE_STATE_CODEC_CONFIGURED) && - (stream->cig_state == CigState::IDLE || - stream->cig_state == CigState::INVALID) && - (stream->cis_state == CisState::READY || - stream->cis_state == CisState::INVALID)) { - num_strms_disconnected++; - } - } - - if(int_strm_trackers_.size() != num_strms_disconnected) { - LOG(WARNING) << __func__ << "Not disconnected for all streams"; - return false; - } else { - LOG(ERROR) << __func__ << "Disconnected for all streams"; - } - - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (stream) { - stream->overall_state = StreamTracker::kStateIdle; - } - } - - // update the state to idle - tracker_.TransitionTo(StreamTracker::kStateIdle); - return true; -} - -void StreamTracker::StateDisconnecting::OnExit() { - tracker_.ClearTimer(state_transition_timer, "StateDisconnectingTimer"); -} - -bool StreamTracker::StateDisconnecting::ProcessEvent(uint32_t event, - void* p_data) { - LOG(INFO) <<__func__ <<": BD Addr = " << strm_mgr_->GetAddress() - <<": State = " << GetState() - <<": Event = " << tracker_.GetEventName(event); - - switch (event) { - case PACS_CONNECTION_STATE_EVT: { - PacsConnectionState *pacs_state = (PacsConnectionState *) p_data; - GattPendingData *gatt_pending_data = strm_mgr_->GetGattPendingData(); - if(pacs_state->state == ConnectionState::DISCONNECTED) { - gatt_pending_data->pacs_pending_cmd = GattPendingCmd::NONE; - } - CheckAndUpdateDisconnectedState(); - } break; - case ASCS_CONNECTION_STATE_EVT: { - AscsConnectionState *ascs_state = (AscsConnectionState *) p_data; - GattPendingData *gatt_pending_data = strm_mgr_->GetGattPendingData(); - if(ascs_state->state == GattState::DISCONNECTED) { - // make all streams ASE state to idle so that further processing - // can happen - gatt_pending_data->ascs_pending_cmd = GattPendingCmd::NONE; - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - std::vector *strms_list = - audio_strms->GetAllStreams(); - - for (auto it = strms_list->begin(); it != strms_list->end(); it++) { - - (*it)->ase_state = ascs::ASE_STATE_IDLE; - (*it)->ase_pending_cmd = AscsPendingCmd::NONE; - (*it)->overall_state = StreamTracker::kStateIdle; - ContinueDisconnection(*it); - } - } - CheckAndUpdateDisconnectedState(); - } break; - case ASCS_ASE_STATE_EVT: { // to handle remote driven operations - - // check for state releasing - // based on prev state do accordingly - AscsState *ascs = ((AscsState *) p_data); - - uint8_t ase_id = ascs->ase_params.ase_id; - - // check if current stream tracker is interested in this ASE update - if(int_strm_trackers_.FindByAseId(ase_id) - == nullptr) { - LOG(INFO) << __func__ << "Not intended for this tracker"; - break; - } - - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - UcastAudioStream *stream = audio_strms->FindByAseId(ase_id); - - if(stream == nullptr) { - break; - } else { - stream->ase_state = ascs->ase_params.ase_state; - stream->ase_params = ascs->ase_params; - } - - if(ascs->ase_params.ase_state == ascs::ASE_STATE_RELEASING) { - // find out the stream for the given ase id - LOG(WARNING) << __func__ << " ASE Id " << loghex(ase_id); - stream->ase_pending_cmd = AscsPendingCmd::NONE; - ContinueDisconnection(stream); - - } else if( ascs->ase_params.ase_state == - ascs::ASE_STATE_CODEC_CONFIGURED) { - // check if this is a codec config notification due to codec config - // issued during connecting state - if((tracker_.PreviousStateId() == StreamTracker::kStateConnecting || - tracker_.PreviousStateId() == StreamTracker::kStateReconfiguring) && - stream->ase_pending_cmd == AscsPendingCmd::CODEC_CONFIG_ISSUED && - stream->ase_state == ascs::ASE_STATE_CODEC_CONFIGURED) { - // mark int conn state as codec configured and issue release command - std::vector ase_ops; - AscsClient *ascs_client = strm_mgr_->GetAscsClient(); - AseReleaseOp release_op = { - .ase_id = stream->ase_id - }; - ase_ops.push_back(release_op); - stream->ase_pending_cmd = AscsPendingCmd::RELEASE_ISSUED; - ascs_client->Release(ASCS_CLIENT_ID, - strm_mgr_->GetAddress(), ase_ops); - break; // break the switch case - } else { - stream->ase_pending_cmd = AscsPendingCmd::NONE; - stream->overall_state = StreamTracker::kStateIdle; - ContinueDisconnection(stream); - CheckAndUpdateDisconnectedState(); - } - } else if(ascs->ase_params.ase_state == ascs::ASE_STATE_IDLE) { - // check for all trackers moved to idle and - // CIG state is idle if so update it as streams are disconnected - stream->ase_pending_cmd = AscsPendingCmd::NONE; - stream->overall_state = StreamTracker::kStateIdle; - ContinueDisconnection(stream); - CheckAndUpdateDisconnectedState(); - } - } break; - - case ASCS_ASE_OP_FAILED_EVT: { - AscsOpFailed *ascs_op = ((AscsOpFailed *) p_data); - std::vector *ase_list = &ascs_op->ase_list; - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - - if(ascs_op->ase_op_id == ascs::AseOpId::RELEASE) { - // treat it like internal failure - for (auto i = ase_list->begin(); i != ase_list->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((i)->ase_id); - if(stream) { - stream->ase_state = ascs::ASE_STATE_IDLE; - stream->ase_pending_cmd = AscsPendingCmd::NONE; - stream->overall_state = StreamTracker::kStateIdle; - ContinueDisconnection(stream); - } - } - CheckAndUpdateDisconnectedState(); - } - } break; - - case CIS_GROUP_STATE_EVT: { - // check if the associated CIG state is created - // if so go for QOS config operation - CisGroupState *data = ((CisGroupState *) p_data); - - // check if current stream tracker is interested in this CIG update - std::vector int_trackers = - int_strm_trackers_.FindByCigId(data->cig_id); - if(int_trackers.empty()) { - LOG(INFO) << __func__ << "Not intended for this tracker"; - break; - } - - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - if(data->state == CigState::CREATED) { - for (auto i = int_trackers.begin(); i != int_trackers.end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (stream) { - stream->cis_pending_cmd = CisPendingCmd::NONE; - stream->cig_state = data->state; - stream->cis_state = CisState::READY; - // check if this is a CIG created event due to CIG create - // issued during starting state - ContinueDisconnection(stream); - } - } - CheckAndUpdateDisconnectedState(); - - } else if(data->state == CigState::IDLE) { - for (auto i = int_trackers.begin(); i != int_trackers.end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (!stream) { - LOG(ERROR) << __func__ << "stream is null"; - continue; - } - stream->cig_state = CigState::INVALID; - stream->cis_state = CisState::INVALID; - stream->cis_pending_cmd = CisPendingCmd::NONE; - } - CheckAndUpdateDisconnectedState(); - } - } break; - case CIS_STATE_EVT: { - CisStreamState *data = (CisStreamState *) p_data; - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - // check if current stream tracker is interested in this CIG update - std::vector int_trackers = - int_strm_trackers_.FindByCisId(data->cig_id, data->cis_id); - if(int_trackers.empty()) { - LOG(INFO) << __func__ << "Not intended for this tracker"; - break; - } - - // go for CIS destroy or CIG removal based on CIS state - if(data->state == CisState::ESTABLISHED) { - for(auto it = directions.begin(); it != directions.end(); ++it) { - if(data->direction & *it) { - UcastAudioStream *stream = audio_strms->FindByCisIdAndDir - (data->cig_id, data->cis_id, *it); - if(stream) { - stream->cis_state = data->state; - stream->cis_pending_cmd = CisPendingCmd::NONE; - ContinueDisconnection(stream); - } - } - } - } else if(data->state == CisState::READY) { - for(auto it = directions.begin(); it != directions.end(); ++it) { - if(data->direction & *it) { - UcastAudioStream *stream = audio_strms->FindByCisIdAndDir - (data->cig_id, data->cis_id, *it); - if(stream) { - stream->cis_state = data->state; - stream->cis_pending_cmd = CisPendingCmd::NONE; - ContinueDisconnection(stream); - } - } - } - CheckAndUpdateDisconnectedState(); - } - } break; - - case BAP_TIME_OUT_EVT: { - BapTimeout* timeout = static_cast (p_data); - if (timeout == nullptr) { - LOG(INFO) << __func__ << ": timeout data null, return "; - break; - } - - int stream_tracker_id = timeout->transition_state; - LOG(INFO) << __func__ << ": stream_tracker_ID: " << stream_tracker_id - << ", timeout reason: " << static_cast(timeout->reason); - - std::vector *int_trackers = - int_strm_trackers_.GetTrackerList(); - if (timeout->reason == TimeoutReason::STATE_TRANSITION) { - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - for (auto i = int_trackers->begin(); i != int_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if(stream) { - stream->ase_state = ascs::ASE_STATE_IDLE; - stream->ase_pending_cmd = AscsPendingCmd::NONE; - stream->overall_state = StreamTracker::kStateIdle; - ContinueDisconnection(stream); - } - } - CheckAndUpdateDisconnectedState(); - } - } break; - default: - LOG(WARNING) << __func__ << ": Un-handled event: " - << tracker_.GetEventName(event); - break; - } - return true; -} - -void StreamTracker::StateReconfiguring::OnEnter() { - LOG(INFO) << __func__ << ": StreamTracker State: " << GetState(); - UcastClientCallbacks* callbacks = strm_mgr_->GetUclientCbacks(); - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - std::vector strms; - std::vector *reconfig_streams = tracker_.GetReconfStreams(); - uint8_t num_ases = 0; - - LOG(WARNING) << __func__ << ": Reconfig Streams Size: " - << reconfig_streams->size(); - - StreamControlType control_type = tracker_.GetControlType(); - - if(control_type != StreamControlType::Reconfig) return; - - for (auto it = reconfig_streams->begin(); - it != reconfig_streams->end(); it++) { - StreamStateInfo state; - memset(&state, 0, sizeof(state)); - state.stream_type = it->stream_type; - state.stream_state = StreamState::RECONFIGURING; - strms.push_back(state); - StreamContext *context = contexts->FindOrAddByType(it->stream_type); - context->connection_state = IntConnectState::PACS_DISCOVERING; - context->stream_state = StreamState::RECONFIGURING; - num_ases += context->stream_ids.size(); - } - callbacks->OnStreamState(strm_mgr_->GetAddress(), strms); - - uint64_t tout = num_ases * - (static_cast(TimeoutVal::ReconfiguringTimeout)); - if(!tout ||tout > static_cast(MaxTimeoutVal::ReconfiguringTimeout)){ - tout = static_cast(MaxTimeoutVal::ReconfiguringTimeout); - } - - TimeoutReason reason = TimeoutReason::STATE_TRANSITION; - state_transition_timer = tracker_.SetTimer("StateReconfiguringTimer", - &timeout, reason, tout); - if (state_transition_timer == nullptr) { - LOG(ERROR) << __func__ << ": state_transition_timer: Alarm not allocated."; - return; - } -} - -void StreamTracker::StateReconfiguring::OnExit() { - tracker_.ClearTimer(state_transition_timer, "StateReconfiguringTimer"); -} - -bool StreamTracker::StateReconfiguring::ProcessEvent(uint32_t event, - void* p_data) { - LOG(INFO) <<__func__ <<": BD Addr = " << strm_mgr_->GetAddress() - <<": State = " << GetState() - <<": Event = " << tracker_.GetEventName(event); - - std::vector *reconf_streams = tracker_.GetReconfStreams(); - StreamContexts *contexts = strm_mgr_->GetStreamContexts(); - uint8_t num_reconf_streams = 0; - if(reconf_streams) { - num_reconf_streams = reconf_streams->size(); - } - UcastAudioStreams *audio_strms = strm_mgr_->GetAudioStreams(); - AscsClient *ascs_client = strm_mgr_->GetAscsClient(); - - switch (event) { - case BAP_DISCONNECT_REQ_EVT: { - tracker_.HandleDisconnect(p_data, StreamTracker::kStateReconfiguring); - } break; - case PACS_DISCOVERY_RES_EVT: { - PacsDiscovery pacs_discovery_ = *((PacsDiscovery *) p_data); - GattState ascs_state = strm_mgr_->GetAscsState(); - uint8_t qos_reconfigs = 0; - - bool process_pacs_results = false; - - // check if this tracker already passed the pacs discovery stage - for (auto it = reconf_streams->begin(); - it != reconf_streams->end(); it++) { - StreamContext *context = contexts->FindOrAddByType(it->stream_type); - if (context->connection_state == IntConnectState::PACS_DISCOVERING) { - context->connection_state = IntConnectState::ASCS_DISCOVERED; - process_pacs_results = true; - } - } - - if(!process_pacs_results) break; - - // check the status - if(pacs_discovery_.status) { - // send the BAP callback as connected as discovery failed - // during reconfiguring - tracker_.TransitionTo(StreamTracker::kStateConnected); - return false; - } - - tracker_.UpdatePacsDiscovery(pacs_discovery_); - - // check if supported audio contexts has required contexts - for (auto it = reconf_streams->begin(); - it != reconf_streams->end();) { - bool context_supported = false; - StreamType stream = it->stream_type; - if(stream.direction == ASE_DIRECTION_SINK) { - if(stream.audio_context & pacs_discovery_.supported_contexts) { - context_supported = true; - } - } else if(stream.direction == ASE_DIRECTION_SRC) { - if((static_cast(stream.audio_context) << 16) & - pacs_discovery_.supported_contexts) { - context_supported = true; - } - } - if(context_supported) { - it++; - } else { - it = reconf_streams->erase(it); - // TODO to update the disconnected callback - } - } - - if(reconf_streams->empty()) { - LOG(ERROR) << __func__ << " No Matching Sup Contexts found"; - LOG(ERROR) << __func__ << " Moving back to Connected state"; - tracker_.TransitionTo(StreamTracker::kStateConnected); - break; - } - - // check physical allocation for all reconfig requests - uint8_t num_phy_attached = 0; - uint8_t num_same_config_applied = 0; - // if not present send the BAP callback as disconnected - // compare the codec configs from upper layer to remote dev - // sink or src PACS records/capabilities. - for (auto it = reconf_streams->begin(); - it != reconf_streams->end(); it++) { - uint8_t index = tracker_.ChooseBestCodec(it->stream_type, - &it->codec_qos_config_pair, - &pacs_discovery_); - if(index != 0XFF) { - CodecQosConfig entry = it->codec_qos_config_pair.at(index); - StreamContext *context = contexts->FindOrAddByType( - it->stream_type); - if(context->attached_state == StreamAttachedState::PHYSICAL) { - num_phy_attached++; - // check if same config is already applied - if(IsCodecConfigEqual(&context->codec_config,&entry.codec_config)) { - num_same_config_applied++; - } - } - } else { - LOG(ERROR) << __func__ << " Matching Codec not found"; - } - } - - if(reconf_streams->size() == num_phy_attached && - num_phy_attached == num_same_config_applied) { - // update the state to connected - LOG(INFO) << __func__ << " Making state to Connected as Nothing to do"; - TransitionTo(StreamTracker::kStateConnected); - break; - } - - if(ascs_state != GattState::CONNECTED) { - break; - } - - for (auto it = reconf_streams->begin(); - it != reconf_streams->end(); it++) { - uint8_t index = tracker_.ChooseBestCodec(it->stream_type, - &it->codec_qos_config_pair, - &pacs_discovery_); - if(index != 0XFF) { - CodecQosConfig entry = it->codec_qos_config_pair.at(index); - StreamContext *context = contexts->FindOrAddByType( - it->stream_type); - CodecConfig codec_config = entry.codec_config; - QosConfig qos_config = entry.qos_config; - - if(context->attached_state == StreamAttachedState::VIRTUAL) { - std::vector phy_attached_contexts; - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - std::vector phy_attached_contexts; - phy_attached_contexts = contexts->FindByAseAttachedState( - id->ase_id, StreamAttachedState::PHYSICAL); - for (auto context_id = phy_attached_contexts.begin(); - context_id != phy_attached_contexts.end(); - context_id++) { - LOG(INFO) << __func__ << ":Attached state made virtual"; - (*context_id)->attached_state = StreamAttachedState::VIRTUAL; - } - } - LOG(INFO) << __func__ << ":Attached state made virtual to phy"; - context->attached_state = StreamAttachedState::VIR_TO_PHY; - context->codec_config = codec_config; - context->req_qos_config = qos_config; - } else if (context->attached_state == StreamAttachedState::PHYSICAL) { - LOG(INFO) << __func__ << ":Attached state is physical"; - // check if same config is already applied - if(IsCodecConfigEqual(&context->codec_config,&entry.codec_config)) { - if(it->reconf_type == StreamReconfigType::CODEC_CONFIG) { - it->reconf_type = StreamReconfigType::QOS_CONFIG; - } - } else { - context->codec_config = codec_config; - } - context->req_qos_config = qos_config; - } - - uint8_t ascs_config_index = 0; - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - int_strm_trackers_.FindOrAddBytrackerType(it->stream_type, - id->ase_id, - qos_config.ascs_configs[ascs_config_index].cig_id, - qos_config.ascs_configs[ascs_config_index].cis_id, - codec_config, - qos_config); - UcastAudioStream *stream = audio_strms->FindByAseId(id->ase_id); - if (!stream) { - LOG(ERROR) << __func__ << "stream is null"; - continue; - } - stream->cig_id = id->cig_id = - qos_config.ascs_configs[ascs_config_index].cig_id; - stream->cis_id = id->cis_id = - qos_config.ascs_configs[ascs_config_index].cis_id; - stream->cig_state = CigState::INVALID; - stream->cis_state = CisState::INVALID; - stream->codec_config = codec_config; - stream->req_qos_config = qos_config; - stream->qos_config = qos_config; - stream->audio_context = it->stream_type.audio_context; - ascs_config_index++; - } - } else { - LOG(ERROR) << __func__ << " Matching Codec not found"; - } - } - for (auto it = reconf_streams->begin(); - it != reconf_streams->end(); it++) { - if (it->reconf_type == StreamReconfigType::QOS_CONFIG) { - qos_reconfigs++; - } - } - - if(qos_reconfigs == num_reconf_streams) { - // now create the group - std::vector *all_trackers = - int_strm_trackers_.GetTrackerList(); - // check for all streams together so that final group params - // will be decided. - for (auto i = all_trackers->begin(); i != all_trackers->end();i++) { - UcastAudioStream *stream = audio_strms->FindByAseId((*i)->ase_id); - if (!stream) { - LOG(ERROR) << __func__ << "stream is null"; - continue; - } - tracker_.ChooseBestQos(&stream->req_qos_config, - &stream->pref_qos_params, - &stream->qos_config, - StreamTracker::kStateReconfiguring, - stream->direction); - } - tracker_.CheckAndSendQosConfig(&int_strm_trackers_); - } else { - // now send the ASCS codec config - std::vector ase_ops; - for (auto it = reconf_streams->begin(); - it != reconf_streams->end(); it++) { - if(it->reconf_type == StreamReconfigType::CODEC_CONFIG) { - StreamContext *context = contexts->FindOrAddByType(it->stream_type); - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - UcastAudioStream *stream = audio_strms->FindByAseId(id->ase_id); - if (stream) { - tracker_.PrepareCodecConfigPayload(&ase_ops, stream); - } - } - } - } - - if(!ase_ops.empty()) { - LOG(WARNING) << __func__ << ": Going For ASCS CodecConfig op"; - ascs_client->CodecConfig(ASCS_CLIENT_ID, - strm_mgr_->GetAddress(), ase_ops); - } - - // update the states to connecting or other internal states - for (auto it = reconf_streams->begin(); - it != reconf_streams->end(); it++) { - if(it->reconf_type == StreamReconfigType::CODEC_CONFIG) { - StreamContext *context = contexts->FindOrAddByType(it->stream_type); - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - UcastAudioStream *stream = audio_strms->FindByAseId(id->ase_id); - if (stream) { - stream->ase_pending_cmd = AscsPendingCmd::CODEC_CONFIG_ISSUED; - stream->overall_state = StreamTracker::kStateReconfiguring; - } - } - } else { - StreamContext *context = contexts->FindOrAddByType(it->stream_type); - for (auto id = context->stream_ids.begin(); - id != context->stream_ids.end(); id++) { - UcastAudioStream *stream = audio_strms->FindByAseId(id->ase_id); - if (stream) { - stream->overall_state = StreamTracker::kStateReconfiguring; - } - } - } - } - } - } break; - - case ASCS_ASE_STATE_EVT: { - tracker_.HandleAseStateEvent(p_data, StreamControlType::Reconfig, - &int_strm_trackers_); - } break; - - case ASCS_ASE_OP_FAILED_EVT: { - tracker_.HandleAseOpFailedEvent(p_data); - } break; - - case PACS_CONNECTION_STATE_EVT: { - tracker_.HandlePacsConnectionEvent(p_data); - } break; - - case ASCS_CONNECTION_STATE_EVT: { - tracker_.HandleAscsConnectionEvent(p_data); - } break; - - case BAP_TIME_OUT_EVT: { - tracker_.OnTimeout(p_data); - } break; - - default: - LOG(WARNING) << __func__ << ": Un-handled event: " - << tracker_.GetEventName(event); - break; - } - return true; -} - -} // namespace ucast -} // namespace bap -} // namespace bluetooth diff --git a/le_audio/system/bt/bta/cc/bta_cc_main.cc b/le_audio/system/bt/bta/cc/bta_cc_main.cc deleted file mode 100644 index 29cc3461fe09e1cbde7edc63deca825504adf141..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/cc/bta_cc_main.cc +++ /dev/null @@ -1,2333 +0,0 @@ -/* - * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. - */ -/* - * Copyright (C) 2003-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 - */ -/****************************************************************************** - * - * This is the main implementation file for the BTA LE audio call Gateway. - * - ******************************************************************************/ - -#include "bta_api.h" -#include "btif_util.h" -#include "bt_target.h" -#include "bta_cc_api.h" -#include "gatts_ops_queue.h" -#include "device/include/controller.h" - -#include "osi/include/properties.h" -#include "osi/include/alarm.h" -#include "osi/include/allocator.h" -#include "osi/include/osi.h" -#include "bta_sys.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#define MAX_URI_SIZE 50 -#define STANDARD_BEARER_UCI "un000" -#define MS_IN_SEC 1000 -#define CCS_DEFAULT_INDEX_VAL 0 -#define DEFAULT_INDICIES_COUNT 1 - -using bluetooth::Uuid; -using bluetooth::bap::GattsOpsQueue; -class CallControllerImpl; -static CallControllerImpl *cc_instance; -static bool gIsTerminatedInitiatedFromClient = false; -static int gTerminateIntiatedIndex = 0; -static bool gIsActiveCC = false; - -//GTBS UUID (4B: TBS, 4C: GTBS) -Uuid CALL_CONTROL_SERVER_UUID = Uuid::FromString("0000184C-0000-1000-8000-00805F9B34FB"); - -Uuid GTBS_CALL_BEARER_NAME_UUID = Uuid::FromString("00002bb3-0000-1000-8000-00805F9B34FB"); -Uuid GTBS_BEARER_UCI = Uuid::FromString("00002bb4-0000-1000-8000-00805F9B34FB"); -Uuid GTBS_BEARER_TECHNOLOGY = Uuid::FromString("00002bb5-0000-1000-8000-00805F9B34FB"); -Uuid GTBS_BEARER_URI_SCHEMES = Uuid::FromString("00002bb6-0000-1000-8000-00805F9B34FB"); -Uuid GTBS_SIGNAL_STRENGTH = Uuid::FromString("00002bb7-0000-1000-8000-00805F9B34FB"); -Uuid GTBS_SIGNAL_STRENGTH_REPORTINTERVAL = Uuid::FromString("00002bb8-0000-1000-8000-00805F9B34FB"); -Uuid GTBS_BEARER_LIST_CURRENT_CALLS = Uuid::FromString("00002bb9-0000-1000-8000-00805F9B34FB"); -Uuid GTBS_CONTENT_CONTROLID = Uuid::FromString("00002bba-0000-1000-8000-00805F9B34FB"); -Uuid GTBS_CALL_STATUS_FLAGS = Uuid::FromString("00002bbb-0000-1000-8000-00805F9B34FB"); -Uuid GTBS_INCOMINGCALL_TARGET_URI = Uuid::FromString("00002bbc-0000-1000-8000-00805F9B34FB"); -Uuid GTBS_CALL_STATE_UUID = Uuid::FromString("00002bbd-0000-1000-8000-00805F9B34FB"); -Uuid GTBS_CALL_CONTROL_POINT_OPS = Uuid::FromString("00002bbe-0000-1000-8000-00805F9B34FB"); -Uuid GTBS_CALL_CONTROL_POINT_OPTIONAL_OPS = Uuid::FromString("00002bbf-0000-1000-8000-00805F9B34FB"); -Uuid GTBS_CALL_TERMINATION_REASON = Uuid::FromString("00002bc0-0000-1000-8000-00805F9B34FB"); -Uuid GTBS_INCOMING_CALL = Uuid::FromString("00002bc1-0000-1000-8000-00805F9B34FB"); -Uuid GTBS_CALL_FRIENDLY_NAME = Uuid::FromString("00002bc2-0000-1000-8000-00805F9B34FB"); - - -Uuid GTBS_DESCRIPTOR_UUID = Uuid::FromString("00002902-0000-1000-8000-00805f9b34fb"); - -//global varibale -CcsControlServiceInfo_t ccsControlServiceInfo; -tCCS_CALL_STATE CallStateInfo; -std::map CallStatelist; -std::map BlccInfolist; -tCCS_CALL_CONTROL_POINT CallControllerOps; -tCCS_CALL_CONTROL_RESPONSE CallControllerResp; -tCCS_BEARER_LIST_CURRENT_CALLS BlccInfo; -tCCS_BEARER_PROVIDER_INFO BearerProviderInfo; -tCCS_CONTENT_CONTROL_ID CcidInfo; -tCCS_STATUS_FLAGS StatusFlags; -tCCS_INCOMING_CALL IncomingCallInfo; -tCCS_INCOMING_CALL_URI IncomingCallTargetUri; -tCCS_TERM_REASON TerminationReason; -tCCS_FRIENDLY_NAME FriendlyName; -tCCS_SUPP_OPTIONAL_OPCODES SupportedOptionalOpcodes; - -void BTCcCback(tBTA_GATTS_EVT event, tBTA_GATTS* param); -void ReverseByteOrder(unsigned char s[], int length); - -typedef base::Callback service)> - OnGtbsServiceAdded; - -static void OnGtbsServiceAddedCb(uint8_t status, int serverIf, - std::vector service); - -const char* bta_cc_event_str(uint32_t event) { - switch (event) { - CASE_RETURN_STR(CCS_NONE_EVENT) - CASE_RETURN_STR(CCS_INIT_EVENT) - CASE_RETURN_STR(CCS_CLEANUP_EVENT) - CASE_RETURN_STR(CCS_CALL_STATE_UPDATE) - CASE_RETURN_STR(CCS_BEARER_NAME_UPDATE) - CASE_RETURN_STR(CCS_BEARER_UCI_UPDATE) - CASE_RETURN_STR(CCS_BEARER_URI_SCHEMES_SUPPORTED) - CASE_RETURN_STR(CCS_UPDATE) - CASE_RETURN_STR(CCS_OPT_OPCODES) - CASE_RETURN_STR(CCS_BEARER_CURRENT_CALL_LIST_UPDATE) - CASE_RETURN_STR(CCS_BEARER_SIGNAL_STRENGTH_UPDATE) - CASE_RETURN_STR(CCS_SIGNAL_STRENGTH_REPORT_INTERVAL) - CASE_RETURN_STR(CCS_STATUS_FLAGS_UPDATE) - CASE_RETURN_STR(CCS_INCOMING_CALL_UPDATE) - CASE_RETURN_STR(CCS_INCOMING_TARGET_URI_UPDATE) - CASE_RETURN_STR(CCS_TERMINATION_REASON_UPDATE) - CASE_RETURN_STR(CCS_BEARER_TECHNOLOGY_UPDATE) - CASE_RETURN_STR(CCS_CCID_UPDATE) - CASE_RETURN_STR(CCS_ACTIVE_DEVICE_UPDATE) - CASE_RETURN_STR(CCS_CALL_CONTROL_RESPONSE) - CASE_RETURN_STR(CCS_NOTIFY_ALL) - CASE_RETURN_STR(CCS_WRITE_RSP) - CASE_RETURN_STR(CCS_READ_RSP) - CASE_RETURN_STR(CCS_DESCRIPTOR_WRITE_RSP) - CASE_RETURN_STR(CCS_DESCRIPTOR_READ_RSP) - CASE_RETURN_STR(CCS_CONNECTION) - CASE_RETURN_STR(CCS_DISCONNECTION) - CASE_RETURN_STR(CCS_CONNECTION_UPDATE) - CASE_RETURN_STR(CCS_CONGESTION_UPDATE) - CASE_RETURN_STR(CCS_PHY_UPDATE) - CASE_RETURN_STR(CCS_MTU_UPDATE) - CASE_RETURN_STR(CCS_SET_ACTIVE_DEVICE) - CASE_RETURN_STR(CCS_CONNECTION_CLOSE_EVENT) - CASE_RETURN_STR(CCS_BOND_STATE_CHANGE_EVENT) - default: - return (char*)"Unknown bta cc event"; - } -} - - -class CallControllerDevices { - private: - CallActiveDevice activeDevice; - //int max_connection; - public: - bool Add(CallControllerDeviceList device) { - if (devices.size() == MAX_CCS_CONNECTION) { - return false; - } - if (FindByAddress(device.peer_bda) != nullptr) return false; - - device.DeviceStateHandlerPointer[CCS_DISCONNECTED] = DeviceStateDisconnectedHandler; - device.DeviceStateHandlerPointer[CCS_CONNECTED] = DeviceStateConnectionHandler; - device.signal_strength_report_interval = 0; - std::string alarmName = device.peer_bda.ToString(); - alarmName.append("-CC_SSReportingTimer"); - - device.signal_strength_reporting_timer = alarm_new_periodic(alarmName.c_str()); - devices.push_back(device); - return true; - } - - void Remove(RawAddress& address) { - for (auto it = devices.begin(); it != devices.end();) { - if (it->peer_bda != address) { - ++it; - continue; - } - if (it == devices.end()) { - LOG(ERROR) << __func__ <<"no matching device"; - return; - } - //Cancel SSReporting timer - if (it->signal_strength_report_interval != 0 && - it->signal_strength_reporting_timer != nullptr) { - alarm_cancel(it->signal_strength_reporting_timer); - alarm_free(it->signal_strength_reporting_timer); - } - - it = devices.erase(it); - - return; - } - } - - void RemoveDevices() { - for (auto it = devices.begin(); it != devices.end();) { - it = devices.erase(it); - } - return; - } - - CallControllerDeviceList* FindByAddress(const RawAddress& address) { - auto iter = std::find_if(devices.begin(), devices.end(), - [&address](const CallControllerDeviceList& device) { - return device.peer_bda == address; - }); - - return (iter == devices.end()) ? nullptr : &(*iter); - } - - CallControllerDeviceList* FindByConnId(uint16_t conn_id) { - auto iter = std::find_if(devices.begin(), devices.end(), - [&conn_id](const CallControllerDeviceList& device) { - return device.conn_id == conn_id; - }); - - return (iter == devices.end()) ? nullptr : &(*iter); - } - - size_t size() { return (devices.size()); } - - std::vector GetRemoteDevices() { - return devices; - } - std::vector FindNotifyDevices(uint16_t handle) { - std::vector notify_devices; - for (size_t it = 0; it != devices.size(); it++){ - if(ccsControlServiceInfo.bearer_provider_name_handle == handle && - devices[it].bearer_provider_name_notify) { - notify_devices.push_back(devices[it]); - } else if(ccsControlServiceInfo.bearer_technology_handle == handle && - devices[it].bearer_technology_changed_notify) { - notify_devices.push_back(devices[it]); - } else if(ccsControlServiceInfo.bearer_signal_strength_handle == handle && - devices[it].bearer_signal_strength_notify) { - notify_devices.push_back(devices[it]); - } else if(ccsControlServiceInfo.bearer_list_currentcalls_handle == handle && - devices[it].bearer_current_calls_list_notify) { - notify_devices.push_back(devices[it]); - } else if(ccsControlServiceInfo.call_status_flags_handle == handle && - devices[it].status_flags_notify) { - notify_devices.push_back(devices[it]); - } else if(ccsControlServiceInfo.incoming_call_target_beareruri_handle == handle && - devices[it].incoming_call_target_URI_notify) { - notify_devices.push_back(devices[it]); - } else if(ccsControlServiceInfo.call_state_handle == handle && - devices[it].call_state_notify) { - notify_devices.push_back(devices[it]); - } else if(ccsControlServiceInfo.call_control_point_handle == handle && - devices[it].call_control_point_notify) { - notify_devices.push_back(devices[it]); - } else if(ccsControlServiceInfo.call_termination_reason_handle == handle && - devices[it].call_termination_reason_notify) { - notify_devices.push_back(devices[it]); - } else if(ccsControlServiceInfo.incoming_call_handle == handle && - devices[it].incoming_call_state_notify) { - notify_devices.push_back(devices[it]); - } else if(ccsControlServiceInfo.call_friendly_name_handle == handle && - devices[it].call_friendly_name_notify) { - notify_devices.push_back(devices[it]); - } - } - return notify_devices; - } - void AddSetActiveDevice(tCCS_SET_ACTIVE_DEVICE *device) { - if (device->set_id == activeDevice.set_id) { - activeDevice.address.push_back(device->address); - } else { - activeDevice.address.clear(); - activeDevice.set_id = device->set_id; - activeDevice.address.push_back(device->address); - } - } - - bool FindActiveDevice(CallControllerDeviceList *remoteDevice) { - bool flag = false; - for (auto& it : activeDevice.address) { - if(remoteDevice->peer_bda == it) { - flag = true; - break; - } - } - return flag; - } - static void SSReportingTimerExpired(void *data) { - LOG(INFO) << __func__ ; - CallControllerDeviceList* dev = (CallControllerDeviceList*)data; - if (dev == nullptr) { - LOG(ERROR) << __func__ << "no valid dev handle"; - return; - } - - //send Notification for Signal Strength - tcc_resp_t *rsp = new tcc_resp_t(); - if (rsp == NULL) { - LOG(ERROR) << __func__ << "Allocation error!"; - return; - } - std::vector _data; - _data.clear(); - rsp->remoteDevice = dev; - rsp->event = CCS_NOTIFY_ALL; - rsp->handle = ccsControlServiceInfo.bearer_signal_strength_handle; - _data.push_back(BearerProviderInfo.signal); - rsp->oper.CallControllerOp.data = std::move(_data); - //force the Notification on timer expiry - rsp->force = true; - - if (dev->bearer_signal_strength_notify) { - LOG(INFO) << "Caling device state handler for SSReporting"; - dev->DeviceStateHandlerPointer[dev->state](CCS_NOTIFY_ALL, rsp); - } else { - LOG(INFO) << "SSReporting Interval set without Desc write for SSR"; - } - } - - static void SetupSSReportingInterval (CallControllerDeviceList* dev) { - LOG(INFO) << __func__ ; - if (alarm_is_scheduled(dev->signal_strength_reporting_timer)) { - alarm_cancel(dev->signal_strength_reporting_timer); - } - if (dev->signal_strength_report_interval != 0) { - alarm_set(dev->signal_strength_reporting_timer, - (period_ms_t)dev->signal_strength_report_interval*MS_IN_SEC, - SSReportingTimerExpired, - (void*)dev); - } - } - - bool UpdateSSReportingInterval(const RawAddress& address, uint8_t ssrInterval) { - bool ret = false; - CallControllerDeviceList *dev = FindByAddress(address); - - if (dev != nullptr) { - dev->signal_strength_report_interval = ssrInterval; - SetupSSReportingInterval(dev); - ret = true; - } - return ret; - } - - std::vector devices; -}; - - -class CallControllerImpl : public CallController { - bluetooth::call_control::CallControllerCallbacks* callbacks; - Uuid app_uuid; - int max_clients; - bool inband_ring_support; - - public: - CallControllerDevices remoteDevices; - virtual ~CallControllerImpl() = default; - - - CallControllerImpl(bluetooth::call_control::CallControllerCallbacks* callback, - Uuid uuid, int max_ccs_clients, bool inband_ringing_enabled) - :callbacks(callback), - app_uuid(uuid), - max_clients(max_ccs_clients), - inband_ring_support(inband_ringing_enabled) { - // HandleCcsEvent(CCS_INIT_EVENT, &app_uuid); - LOG(INFO) << "max_clients " << max_clients; - if (inband_ring_support) { - StatusFlags.supported_flags = (StatusFlags.supported_flags & 0x0000) | INBAND_RINGTONE_FEATURE_BIT; - } else { - StatusFlags.supported_flags = 0x0000; - } - LOG(INFO) << "CallControllerImpl gatts app register"; - BTA_GATTS_AppRegister(app_uuid, BTCcCback, true); - - } - - void Disconnect(const RawAddress& bd_addr) { - LOG(INFO) << __func__; - tCCS_CONNECTION_CLOSE ConnectClosingOp; - ConnectClosingOp.addr = bd_addr; - HandleCcsEvent(CCS_CONNECTION_CLOSE_EVENT, &ConnectClosingOp); - } - - void SetActiveDevice(const RawAddress& address, int setId) { - LOG(INFO) << __func__ ; - tCCS_SET_ACTIVE_DEVICE SetActiveDeviceOp; - SetActiveDeviceOp.set_id = setId; - SetActiveDeviceOp.address = address; - HandleCcsEvent(CCS_ACTIVE_DEVICE_UPDATE, &SetActiveDeviceOp); - } - - void CallState(int len, std::vector call_state_list) { - tCCS_CALL_STATE CallStateOp; - for (int k=0; k::iterator i = BlccInfolist.find(BlccInfo.call_index); - if (i != BlccInfolist.end()) { - LOG(INFO) << __func__ << " update existing Blcc"; - i->second = BlccInfo; - } else { - BlccInfolist.insert({BlccInfo.call_index, BlccInfo}); - } - std::map::iterator j = CallStatelist.find(CallStateOp.index); - if (j != CallStatelist.end()) { - j->second = CallStateOp; - } else { - CallStatelist.insert({CallStateOp.index, CallStateOp}); - } - //clear the term reason - if (CallStateOp.index == TerminationReason.index) { - TerminationReason.index = 0; - TerminationReason.reason = CC_TERM_INVALID_ORIG_URI; - } - } - } - HandleCcsEvent(CCS_CALL_STATE_UPDATE, &CallStatelist); - HandleCcsEvent(CCS_BEARER_CURRENT_CALL_LIST_UPDATE, &BlccInfolist); - } - - void BearerInfoName(uint8_t* name) { - LOG(INFO) << __func__ << name; - tCCS_BEARER_PROVIDER_INFO BearerProviderOp; - BearerProviderOp.length = strlen((char *)name); - memcpy(BearerProviderOp.name, name, BearerProviderOp.length+1); - HandleCcsEvent(CCS_BEARER_NAME_UPDATE, &BearerProviderOp); - } - - void UpdateBearerTechnology(int tech_type) { - LOG(INFO) << __func__ << " tech type: " <::iterator it; - tCCS_INCOMING_CALL IncomingCall; - int len = strlen((char *)Uri); - memcpy(IncomingCall.incoming_uri, Uri, len+1); - IncomingCall.index = index; - for (it = BlccInfolist.begin(); it != BlccInfolist.end(); it++) { - tCCS_BEARER_LIST_CURRENT_CALLS blccObj = it->second; - if (blccObj.call_index == index) { - memcpy(blccObj.call_uri, Uri, strlen((char *)Uri)+1); - break; - } - } - HandleCcsEvent(CCS_INCOMING_CALL_UPDATE, &IncomingCall); - //update Target URI as well with same Info - UpdateIncomingCallTargetUri(index, Uri); - } - - void UpdateIncomingCallTargetUri(int index, uint8_t* target_uri) { - LOG(INFO) << __func__ << " target_uri: " << target_uri; - tCCS_INCOMING_CALL_URI IncomingcallUri; - int len = strlen((char *)target_uri); - memcpy(IncomingcallUri.incoming_target_uri, target_uri, len+1); - IncomingcallUri.index = index; - HandleCcsEvent(CCS_INCOMING_TARGET_URI_UPDATE, &IncomingcallUri); - } - - void ContentControlId(uint32_t ccid) { - LOG(INFO) << __func__; - tCCS_CONTENT_CONTROL_ID ContentControlIdOp; - ContentControlIdOp.ccid = ccid; - HandleCcsEvent(CCS_CCID_UPDATE, &ContentControlIdOp); - } - - int GetDialingCallIndex() { - int retIndex = 0; - std::map::iterator it; - for (it = CallStatelist.begin(); it != CallStatelist.end(); it++) { - tCCS_CALL_STATE obj = it->second; - if (obj.state == CCS_STATE_DIALING || obj.state == CCS_STATE_ALERTING) { - LOG(INFO) << __func__ << " call state match: " << obj.index; - retIndex = obj.index; - break; - } - } - return retIndex; - } - void CallControlResponse(uint8_t op, uint8_t index, uint32_t status, const RawAddress& address) { - LOG(INFO) << __func__; - tCCS_CALL_CONTROL_RESPONSE CallControlResponse; - CallControllerResp.opcode = op; - CallControllerResp.response_status = status; - CallControllerResp.remote_address = address; - CallControllerResp.index = index; - if (status == CCS_STATUS_SUCCESS && op == CALL_ORIGINATE) { - //get proper call Index for call orignate status - CallControllerResp.index = GetDialingCallIndex(); - } - HandleCcsEvent(CCS_CALL_CONTROL_RESPONSE, &CallControlResponse); - } - - void CallControlInitializedCallback(uint8_t state) { - LOG(INFO) << __func__ << " state" << state; - callbacks->CallControlInitializedCallback(state); - if (state == 0) { - //Initialize local char values - memcpy(BearerProviderInfo.uci, STANDARD_BEARER_UCI, strlen(STANDARD_BEARER_UCI)); - } - } - - void ConnectionStateCallback(uint8_t state, const RawAddress& address) { - LOG(INFO) << __func__ << " state: " << state; - callbacks->ConnectionStateCallback(state, address); - } - - void CallControlPointChange(uint8_t op, uint8_t* indices, int count, char* uri, const RawAddress& address) { - LOG(INFO) << __func__ << " op: " < uri_data; - if (uri != NULL) { - LOG(INFO) << __func__ <<" uri=" << uri; - uri_data.insert(uri_data.begin(), uri, uri + strlen(uri)); - } - std::vector call_indicies; - for (int i=0; iCallControlCallback(op, call_indicies, count, uri_data, address); - } -}; - -void CallController::CleanUp() { - HandleCcsEvent(CCS_CLEANUP_EVENT, NULL); - delete cc_instance; - cc_instance = nullptr; - } - -CallController* CallController::Get() { - CHECK(cc_instance); - return cc_instance; -} - -void CallController::Initialize(bluetooth::call_control::CallControllerCallbacks* callbacks, - Uuid uuid, int max_ccs_clients, bool inband_ringing_enabled) { - if (cc_instance) { - LOG(ERROR) << "Already initialized!"; - } else { - cc_instance = new CallControllerImpl(callbacks, uuid, max_ccs_clients, inband_ringing_enabled); - } - char activeCC[PROPERTY_VALUE_MAX] = "false"; - if(osi_property_get("persist.vendor.service.bt.activeCC", activeCC, "false") && - !strcmp(activeCC, "true")) { - gIsActiveCC = true; - } -} - -bool CallController::IsCcServiceRunnig() { return cc_instance; } - -static std::vector CcAddService(int server_if) { - - std::vector ccs_services; - ccs_services.clear(); - //service - btgatt_db_element_t service = {}; - service.uuid = CALL_CONTROL_SERVER_UUID; - service.type = BTGATT_DB_PRIMARY_SERVICE; - ccs_services.push_back(service); - ccsControlServiceInfo.ccs_service_uuid = service.uuid; - - btgatt_db_element_t bearer_provider_name_char = {}; - bearer_provider_name_char.uuid = GTBS_CALL_BEARER_NAME_UUID; - bearer_provider_name_char.type = BTGATT_DB_CHARACTERISTIC; - bearer_provider_name_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY; - bearer_provider_name_char.permissions = GATT_PERM_READ; - ccs_services.push_back(bearer_provider_name_char); - ccsControlServiceInfo.bearer_provider_name_uuid = bearer_provider_name_char.uuid; - - btgatt_db_element_t bearer_provider_name_desc = {}; - bearer_provider_name_desc.uuid = GTBS_DESCRIPTOR_UUID; - bearer_provider_name_desc.type = BTGATT_DB_DESCRIPTOR; - bearer_provider_name_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE; - ccs_services.push_back(bearer_provider_name_desc); - - btgatt_db_element_t bearer_technology_char = {}; - bearer_technology_char.uuid = GTBS_BEARER_TECHNOLOGY; - bearer_technology_char.type = BTGATT_DB_CHARACTERISTIC; - bearer_technology_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY; - bearer_technology_char.permissions = GATT_PERM_READ; - ccs_services.push_back(bearer_technology_char); - ccsControlServiceInfo.bearer_technology_uuid = bearer_technology_char.uuid; - - btgatt_db_element_t bearer_technology_desc = {}; - bearer_technology_desc.uuid = GTBS_DESCRIPTOR_UUID; - bearer_technology_desc.type = BTGATT_DB_DESCRIPTOR; - bearer_technology_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE; - ccs_services.push_back(bearer_technology_desc); - - btgatt_db_element_t gtbs_cc_optional_opcode_char = {}; - gtbs_cc_optional_opcode_char.uuid = GTBS_CALL_CONTROL_POINT_OPTIONAL_OPS; - gtbs_cc_optional_opcode_char.type = BTGATT_DB_CHARACTERISTIC; - gtbs_cc_optional_opcode_char.properties = GATT_CHAR_PROP_BIT_READ; - gtbs_cc_optional_opcode_char.permissions = GATT_PERM_READ; - ccs_services.push_back(gtbs_cc_optional_opcode_char); - ccsControlServiceInfo.call_control_point_opcode_supported_uuid = gtbs_cc_optional_opcode_char.uuid; - - btgatt_db_element_t gtbs_call_state_char = {}; - gtbs_call_state_char.uuid = GTBS_CALL_STATE_UUID; - gtbs_call_state_char.type = BTGATT_DB_CHARACTERISTIC; - gtbs_call_state_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY; - gtbs_call_state_char.permissions = GATT_PERM_READ; - ccs_services.push_back(gtbs_call_state_char); - ccsControlServiceInfo.call_state_uuid = gtbs_call_state_char.uuid; - - btgatt_db_element_t gtbs_call_state_desc = {}; - gtbs_call_state_desc.uuid = GTBS_DESCRIPTOR_UUID; - gtbs_call_state_desc.type = BTGATT_DB_DESCRIPTOR; - gtbs_call_state_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE; - ccs_services.push_back(gtbs_call_state_desc); - - btgatt_db_element_t gtbs_call_control_point_char = {}; - gtbs_call_control_point_char.uuid = GTBS_CALL_CONTROL_POINT_OPS; - gtbs_call_control_point_char.type = BTGATT_DB_CHARACTERISTIC; - gtbs_call_control_point_char.properties = GATT_CHAR_PROP_BIT_WRITE|GATT_CHAR_PROP_BIT_NOTIFY|GATT_CHAR_PROP_BIT_WRITE_NR; - gtbs_call_control_point_char.permissions = GATT_PERM_WRITE; - ccs_services.push_back(gtbs_call_control_point_char); - ccsControlServiceInfo.call_control_point_uuid = gtbs_call_control_point_char.uuid; - - btgatt_db_element_t gtbs_call_control_point_desc = {}; - gtbs_call_control_point_desc.uuid = GTBS_DESCRIPTOR_UUID; - gtbs_call_control_point_desc.type = BTGATT_DB_DESCRIPTOR; - gtbs_call_control_point_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE; - ccs_services.push_back(gtbs_call_control_point_desc); - - btgatt_db_element_t gtbs_bearer_uci_char = {}; - gtbs_bearer_uci_char.uuid = GTBS_BEARER_UCI; - gtbs_bearer_uci_char.type = BTGATT_DB_CHARACTERISTIC; - gtbs_bearer_uci_char.properties = GATT_CHAR_PROP_BIT_READ; - gtbs_bearer_uci_char.permissions = GATT_PERM_READ; - ccs_services.push_back(gtbs_bearer_uci_char); - ccsControlServiceInfo.bearer_uci_uuid= gtbs_bearer_uci_char.uuid; - - btgatt_db_element_t gtbs_bearer_URI_schemes_char = {}; - gtbs_bearer_URI_schemes_char.uuid = GTBS_BEARER_URI_SCHEMES; - gtbs_bearer_URI_schemes_char.type = BTGATT_DB_CHARACTERISTIC; - gtbs_bearer_URI_schemes_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY; - gtbs_bearer_URI_schemes_char.permissions = GATT_PERM_READ; - - ccs_services.push_back(gtbs_bearer_URI_schemes_char); - ccsControlServiceInfo.bearer_uri_schemes_supported_uuid = gtbs_bearer_URI_schemes_char.uuid; - - btgatt_db_element_t gtbs_bearer_URI_schemes_desc = {}; - gtbs_bearer_URI_schemes_desc.uuid = GTBS_DESCRIPTOR_UUID; - gtbs_bearer_URI_schemes_desc.type = BTGATT_DB_DESCRIPTOR; - gtbs_bearer_URI_schemes_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE; - ccs_services.push_back(gtbs_bearer_URI_schemes_desc); - - btgatt_db_element_t gtbs_signal_strength_char = {}; - gtbs_signal_strength_char.uuid = GTBS_SIGNAL_STRENGTH; - gtbs_signal_strength_char.type = BTGATT_DB_CHARACTERISTIC; - gtbs_signal_strength_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY; - gtbs_signal_strength_char.permissions = GATT_PERM_READ; - - ccs_services.push_back(gtbs_signal_strength_char); - ccsControlServiceInfo.bearer_signal_strength_uuid = gtbs_signal_strength_char.uuid; - - btgatt_db_element_t gtbs_signal_strength_desc = {}; - gtbs_signal_strength_desc.uuid = GTBS_DESCRIPTOR_UUID; - gtbs_signal_strength_desc.type = BTGATT_DB_DESCRIPTOR; - gtbs_signal_strength_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE; - ccs_services.push_back(gtbs_signal_strength_desc); - - btgatt_db_element_t gtbs_signal_strength_report_interval_char = {}; - gtbs_signal_strength_report_interval_char.uuid = GTBS_SIGNAL_STRENGTH_REPORTINTERVAL; - gtbs_signal_strength_report_interval_char.type = BTGATT_DB_CHARACTERISTIC; - gtbs_signal_strength_report_interval_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_WRITE|GATT_CHAR_PROP_BIT_WRITE_NR; - gtbs_signal_strength_report_interval_char.permissions = GATT_PERM_READ|GATT_PERM_WRITE; - ccs_services.push_back(gtbs_signal_strength_report_interval_char); - ccsControlServiceInfo.bearer_signal_strength_report_interval_uuid = gtbs_signal_strength_report_interval_char.uuid; - - btgatt_db_element_t gtbs_list_current_calls_char = {}; - gtbs_list_current_calls_char.uuid = GTBS_BEARER_LIST_CURRENT_CALLS; - gtbs_list_current_calls_char.type = BTGATT_DB_CHARACTERISTIC; - gtbs_list_current_calls_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY; - gtbs_list_current_calls_char.permissions = GATT_PERM_READ; - ccs_services.push_back(gtbs_list_current_calls_char); - ccsControlServiceInfo.bearer_list_currentcalls_uuid = gtbs_list_current_calls_char.uuid; - - btgatt_db_element_t gtbs_list_current_calls_desc = {}; - gtbs_list_current_calls_desc.uuid = GTBS_DESCRIPTOR_UUID; - gtbs_list_current_calls_desc.type = BTGATT_DB_DESCRIPTOR; - gtbs_list_current_calls_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE; - ccs_services.push_back(gtbs_list_current_calls_desc); - - btgatt_db_element_t gtbs_call_status_flags_char = {}; - gtbs_call_status_flags_char.uuid = GTBS_CALL_STATUS_FLAGS; - gtbs_call_status_flags_char.type = BTGATT_DB_CHARACTERISTIC; - gtbs_call_status_flags_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY; - gtbs_call_status_flags_char.permissions = GATT_PERM_READ; - ccs_services.push_back(gtbs_call_status_flags_char); - ccsControlServiceInfo.call_status_flags_uuid = gtbs_call_status_flags_char.uuid; - - btgatt_db_element_t gtbs_call_status_flags_desc = {}; - gtbs_call_status_flags_desc.uuid = GTBS_DESCRIPTOR_UUID; - gtbs_call_status_flags_desc.type = BTGATT_DB_DESCRIPTOR; - gtbs_call_status_flags_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE; - ccs_services.push_back(gtbs_call_status_flags_desc); - - btgatt_db_element_t gtbs_incomingcall_target_bearer_URI_char = {}; - gtbs_incomingcall_target_bearer_URI_char.uuid = GTBS_INCOMINGCALL_TARGET_URI; - gtbs_incomingcall_target_bearer_URI_char.type = BTGATT_DB_CHARACTERISTIC; - gtbs_incomingcall_target_bearer_URI_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY; - gtbs_incomingcall_target_bearer_URI_char.permissions = GATT_PERM_READ; - ccs_services.push_back(gtbs_incomingcall_target_bearer_URI_char); - ccsControlServiceInfo.incoming_call_target_beareruri_uuid = gtbs_incomingcall_target_bearer_URI_char.uuid; - - btgatt_db_element_t gtbs_incomingcall_target_bearer_URI_desc = {}; - gtbs_incomingcall_target_bearer_URI_desc.uuid = GTBS_DESCRIPTOR_UUID; - gtbs_incomingcall_target_bearer_URI_desc.type = BTGATT_DB_DESCRIPTOR; - gtbs_incomingcall_target_bearer_URI_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE; - ccs_services.push_back(gtbs_incomingcall_target_bearer_URI_desc); - - btgatt_db_element_t gtbs_incomingcall_char = {}; - gtbs_incomingcall_char.uuid = GTBS_INCOMING_CALL; - gtbs_incomingcall_char.type = BTGATT_DB_CHARACTERISTIC; - gtbs_incomingcall_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY; - gtbs_incomingcall_char.permissions = GATT_PERM_READ; - ccs_services.push_back(gtbs_incomingcall_char); - ccsControlServiceInfo.incoming_call_uuid = gtbs_incomingcall_char.uuid; - - btgatt_db_element_t gtbs_incomingcall_desc = {}; - gtbs_incomingcall_desc.uuid = GTBS_DESCRIPTOR_UUID; - gtbs_incomingcall_desc.type = BTGATT_DB_DESCRIPTOR; - gtbs_incomingcall_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE; - ccs_services.push_back(gtbs_incomingcall_desc); - - btgatt_db_element_t gtbs_call_termination_reason_char = {}; - gtbs_call_termination_reason_char.uuid = GTBS_CALL_TERMINATION_REASON; - gtbs_call_termination_reason_char.type = BTGATT_DB_CHARACTERISTIC; - gtbs_call_termination_reason_char.properties = GATT_CHAR_PROP_BIT_NOTIFY; - ccs_services.push_back(gtbs_call_termination_reason_char); - ccsControlServiceInfo.call_termination_reason_uuid = gtbs_call_termination_reason_char.uuid; - - btgatt_db_element_t gtbs_call_termination_reason_desc = {}; - gtbs_call_termination_reason_desc.uuid = GTBS_DESCRIPTOR_UUID; - gtbs_call_termination_reason_desc.type = BTGATT_DB_DESCRIPTOR; - gtbs_call_termination_reason_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE; - ccs_services.push_back(gtbs_call_termination_reason_desc); - - btgatt_db_element_t gtbs_call_friendly_name_char = {}; - gtbs_call_friendly_name_char.uuid = GTBS_CALL_FRIENDLY_NAME; - gtbs_call_friendly_name_char.type = BTGATT_DB_CHARACTERISTIC; - gtbs_call_friendly_name_char.properties = GATT_CHAR_PROP_BIT_READ|GATT_CHAR_PROP_BIT_NOTIFY; - gtbs_call_friendly_name_char.permissions = GATT_PERM_READ; - ccs_services.push_back(gtbs_call_friendly_name_char); - ccsControlServiceInfo.call_friendly_name_uuid = gtbs_call_friendly_name_char.uuid; - - btgatt_db_element_t gtbs_call_friendly_name_desc = {}; - gtbs_call_friendly_name_desc.uuid = GTBS_DESCRIPTOR_UUID; - gtbs_call_friendly_name_desc.type = BTGATT_DB_DESCRIPTOR; - gtbs_call_friendly_name_desc.permissions = GATT_PERM_READ|GATT_PERM_WRITE; - ccs_services.push_back(gtbs_call_friendly_name_desc); - - btgatt_db_element_t gtbs_ccid_char = {}; - gtbs_ccid_char.uuid = GTBS_CONTENT_CONTROLID; - gtbs_ccid_char.type = BTGATT_DB_CHARACTERISTIC; - gtbs_ccid_char.properties = GATT_CHAR_PROP_BIT_READ; - gtbs_ccid_char.permissions = GATT_PERM_READ; - ccs_services.push_back(gtbs_ccid_char); - ccsControlServiceInfo.gtbs_ccid_uuid = gtbs_ccid_char.uuid; - - return ccs_services; -} - -static void OnGtbsServiceAddedCb(uint8_t status, int serverIf, - std::vector service) { - - if (service[0].uuid == Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER) || - service[0].uuid == Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER)) { - LOG(INFO) << "%s: Attempt to register restricted service"<< __func__; - return; - } - - for(int i=0; i< (int)service.size(); i++) { - - if (service[i].uuid == CALL_CONTROL_SERVER_UUID) { - LOG(INFO) << __func__ << " GTBS service added attr handle: " << service[i].attribute_handle; - } else if(service[i].uuid == GTBS_CALL_BEARER_NAME_UUID) { - ccsControlServiceInfo.bearer_provider_name_handle = service[i++].attribute_handle; - ccsControlServiceInfo.bearer_provider_name_desc = service[i].attribute_handle; - LOG(INFO) << __func__ << " bearer_provider_name_attr: " - << ccsControlServiceInfo.bearer_provider_name_handle - << " bearer_provider_name_desc: " - << ccsControlServiceInfo.bearer_provider_name_desc; - } else if(service[i].uuid == GTBS_BEARER_TECHNOLOGY) { - ccsControlServiceInfo.bearer_technology_handle = service[i++].attribute_handle; - ccsControlServiceInfo.bearer_technology_desc = service[i].attribute_handle; - LOG(INFO) << __func__ << " bearer_technology_handle: " - << ccsControlServiceInfo.bearer_technology_handle - << " bearer_technology_desc: " - << ccsControlServiceInfo.bearer_technology_desc; - } else if(service[i].uuid == GTBS_CALL_CONTROL_POINT_OPTIONAL_OPS) { - ccsControlServiceInfo.call_control_point_opcode_supported_handle = - service[i].attribute_handle; - LOG(INFO) << __func__ << " call_control_point_opcode_supported_handle register: " - << ccsControlServiceInfo.call_control_point_opcode_supported_handle; - } else if (service[i].uuid == GTBS_CALL_STATE_UUID) { - - ccsControlServiceInfo.call_state_handle = service[i++].attribute_handle; - ccsControlServiceInfo.call_state_desc = service[i].attribute_handle; - LOG(INFO) << __func__ << " call_state_handle: " - << ccsControlServiceInfo.call_state_handle - << " call_state_handle desc: " - << ccsControlServiceInfo.call_state_desc; - } else if(service[i].uuid == GTBS_CALL_CONTROL_POINT_OPS) { - ccsControlServiceInfo.call_control_point_handle = service[i++].attribute_handle; - ccsControlServiceInfo.call_control_point_desc = service[i].attribute_handle; - LOG(INFO) << __func__ << " call_control_point_handle: " - << ccsControlServiceInfo.call_control_point_handle - << " call_control_point_desc: " - << ccsControlServiceInfo.call_control_point_desc; - } else if(service[i].uuid == GTBS_BEARER_UCI) { - ccsControlServiceInfo.bearer_uci_handle = service[i].attribute_handle; - LOG(INFO) << __func__ << " bearer_uci_handle: " - << ccsControlServiceInfo.bearer_uci_handle; - - } else if(service[i].uuid == GTBS_BEARER_URI_SCHEMES) { - ccsControlServiceInfo.bearer_uri_schemes_supported_handle = - service[i++].attribute_handle; - ccsControlServiceInfo.bearer_uri_schemes_supported_desc = - service[i].attribute_handle; - LOG(INFO) << __func__ << " bearer_uri_schemes_supported_handle: " - << ccsControlServiceInfo.bearer_uri_schemes_supported_handle - << " bearer_uri_schemes_supported_desc: " - << ccsControlServiceInfo.bearer_uri_schemes_supported_desc; - - } else if(service[i].uuid == GTBS_SIGNAL_STRENGTH) { - ccsControlServiceInfo.bearer_signal_strength_handle = - service[i++].attribute_handle; - ccsControlServiceInfo.bearer_signal_strength_desc = - service[i].attribute_handle; - LOG(INFO) << __func__ << " bearer_signal_strength_handle: " - << ccsControlServiceInfo.bearer_signal_strength_handle - << " bearer_signal_strength_desc: " - << ccsControlServiceInfo.bearer_signal_strength_desc; - - } else if(service[i].uuid == GTBS_SIGNAL_STRENGTH_REPORTINTERVAL) { - ccsControlServiceInfo.bearer_signal_strength_report_interval_handle = - service[i].attribute_handle; - - LOG(INFO) << __func__ << " bearer_signal_strength_report_interval_handle: " - << ccsControlServiceInfo.bearer_signal_strength_report_interval_handle; - - } else if(service[i].uuid == GTBS_BEARER_LIST_CURRENT_CALLS) { - ccsControlServiceInfo.bearer_list_currentcalls_handle = - service[i++].attribute_handle; - ccsControlServiceInfo.bearer_list_currentcalls_desc = - service[i].attribute_handle; - LOG(INFO) << __func__ << " bearer_list_currentcalls_handle: " - << ccsControlServiceInfo.bearer_list_currentcalls_handle - << " bearer_list_currentcalls_desc: " - << ccsControlServiceInfo.bearer_list_currentcalls_desc; - - } else if(service[i].uuid == GTBS_CALL_STATUS_FLAGS) { - ccsControlServiceInfo.call_status_flags_handle = service[i++].attribute_handle; - ccsControlServiceInfo.call_status_flags_desc = service[i].attribute_handle; - LOG(INFO) << __func__ << " call_status_flags_handle: " - << ccsControlServiceInfo.call_status_flags_handle - << " call_status_flags_desc: " - << ccsControlServiceInfo.call_status_flags_desc; - - } else if(service[i].uuid == GTBS_INCOMINGCALL_TARGET_URI) { - ccsControlServiceInfo.incoming_call_target_beareruri_handle = - service[i++].attribute_handle; - ccsControlServiceInfo.incoming_call_target_bearerURI_desc = - service[i].attribute_handle; - LOG(INFO) << __func__ << " incoming_call_target_beareruri_handle: " - << ccsControlServiceInfo.incoming_call_target_beareruri_handle - << " incoming_call_target_bearerURI_desc: " - << ccsControlServiceInfo.incoming_call_target_bearerURI_desc; - } else if(service[i].uuid == GTBS_INCOMING_CALL) { - ccsControlServiceInfo.incoming_call_handle = service[i++].attribute_handle; - ccsControlServiceInfo.incoming_call_desc = service[i].attribute_handle; - LOG(INFO) << __func__ << " incoming_call_handle: " - << ccsControlServiceInfo.incoming_call_handle - << " incoming_call_desc: " - << ccsControlServiceInfo.incoming_call_desc; - } else if(service[i].uuid == GTBS_CONTENT_CONTROLID) { - ccsControlServiceInfo.ccid_handle = service[i].attribute_handle; - LOG(INFO) << __func__ << " ccid_handle: " << ccsControlServiceInfo.ccid_handle; - //Declare the CC Initialization - cc_instance->CallControlInitializedCallback(0); - } else if(service[i].uuid == GTBS_CALL_TERMINATION_REASON) { - ccsControlServiceInfo.call_termination_reason_handle = - service[i++].attribute_handle; - ccsControlServiceInfo.call_termination_reason_desc = - service[i].attribute_handle; - LOG(INFO) << __func__ << " call_termination_reason_handle: " - << ccsControlServiceInfo.call_termination_reason_handle - << " call_termination_reason_desc: " - << ccsControlServiceInfo.call_termination_reason_desc; - } else if(service[i].uuid == GTBS_CALL_FRIENDLY_NAME) { - ccsControlServiceInfo.call_friendly_name_handle = service[i++].attribute_handle; - ccsControlServiceInfo.call_friendly_name_desc = service[i].attribute_handle; - LOG(INFO) << __func__ << " call_friendly_name_handle: " - << ccsControlServiceInfo.call_friendly_name_handle - << " call_friendly_name_desc: " - << ccsControlServiceInfo.call_friendly_name_desc; - } - } -} - -void PrintData(uint8_t data[], uint16_t len) { - for (int i=0; i _data; - _data.clear(); - uint8_t status = BT_STATUS_SUCCESS; - rsp->event = CCS_NONE_EVENT; - bool isCallControllerOpUsed = false; - switch (event) { - - case CCS_INIT_EVENT: - { - Uuid aap_uuid = bluetooth::Uuid::GetRandom(); - BTA_GATTS_AppRegister(aap_uuid, BTCcCback, true); - break; - } - - case CCS_CLEANUP_EVENT: - { - //unregister APP - BTA_GATTS_AppDeregister(ccsControlServiceInfo.server_if); - cc_instance->remoteDevices.RemoveDevices(); - break; - } - case BTA_GATTS_REG_EVT: - { - p_data = (tBTA_GATTS*)param; - if (p_data->reg_oper.status == BT_STATUS_SUCCESS) { - ccsControlServiceInfo.server_if = p_data->reg_oper.server_if; - std::vector service; - service = CcAddService(ccsControlServiceInfo.server_if); - if (service[0].uuid == Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER) || - service[0].uuid == Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER)) { - LOG(INFO) << __func__ << " service app register uuid is not valid"; - break; - } - LOG(INFO) << __func__ << " service app register"; - BTA_GATTS_AddService(ccsControlServiceInfo.server_if, service, base::Bind(&OnGtbsServiceAddedCb)); - } - break; - } - - case BTA_GATTS_DEREG_EVT: - { - break; - } - - case BTA_GATTS_CONF_EVT: { - p_data = (tBTA_GATTS*)param; - uint16_t conn_id = p_data->req_data.conn_id; - uint8_t status = p_data->req_data.status; - LOG(INFO) << __func__ << "conn_id :" << conn_id << "status:" << status; - if (status == BT_STATUS_SUCCESS) { - LOG(INFO) << __func__ << "Notification callback for conn_id :" << conn_id; - GattsOpsQueue::NotificationCallback(conn_id); - } - break; - } - - case BTA_GATTS_CONGEST_EVT: - { - p_data = (tBTA_GATTS*)param; - CallControllerDeviceList *remoteDevice; - remoteDevice = cc_instance->remoteDevices.FindByConnId(p_data->congest.conn_id); - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " connection entry not found conn_id: " - << p_data->congest.conn_id; - break; - } - // rsp->ConngestionOp.status = p_data->req_data.status; - rsp->remoteDevice = remoteDevice; - rsp->oper.CongestionOp.congested = p_data->congest.congested; - rsp->event = CCS_CONGESTION_UPDATE; - break; - } - case BTA_GATTS_MTU_EVT: { - p_data = (tBTA_GATTS*)param; - - CallControllerDeviceList *remoteDevice; - remoteDevice = cc_instance->remoteDevices.FindByConnId(p_data->congest.conn_id); - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " connection entry not found conn_id: " - << p_data->congest.conn_id; - break; - } - rsp->event = CCS_MTU_UPDATE; - rsp->remoteDevice = remoteDevice; - rsp->oper.MtuOp.mtu = p_data->req_data.p_data->mtu; - break; - } - case BTA_GATTS_CONNECT_EVT: { - - p_data = (tBTA_GATTS*)param; - LOG(INFO) << __func__ << " remote devices connected"; - /* - #if (!defined(BTA_SKIP_BLE_START_ENCRYPTION) || BTA_SKIP_BLE_START_ENCRYPTION == FALSE) - btif_gatt_check_encrypted_link(p_data->conn.remote_bda, - p_data->conn.transport); - #endif*/ - CallControllerDeviceList remoteDevice; - memset(&remoteDevice, 0, sizeof(remoteDevice)); - if(cc_instance->remoteDevices.FindByAddress(p_data->conn.remote_bda)) { - LOG(INFO) << __func__ << " remote devices already there is connected list"; - status = BT_STATUS_FAIL; - return; - } - remoteDevice.peer_bda = p_data->conn.remote_bda; - remoteDevice.conn_id = p_data->conn.conn_id; - if(cc_instance->remoteDevices.Add(remoteDevice) == false) { - LOG(INFO) << __func__ << " remote device is not added : max connection reached"; - // need to check disconnection required - break; - } - remoteDevice.state = CCS_DISCONNECTED; - - LOG(INFO) << __func__ << " remote devices connected conn_id: "<< remoteDevice.conn_id << - "bd_addr " << remoteDevice.peer_bda; - - rsp->event = CCS_CONNECTION; - rsp->remoteDevice = cc_instance->remoteDevices.FindByAddress(p_data->conn.remote_bda); - if (rsp->remoteDevice == NULL) { - LOG(INFO)<<__func__ << " remote dev is null"; - break; - } - break; - } - - case BTA_GATTS_DISCONNECT_EVT: { - LOG(INFO) << __func__ << " remote devices disconnected"; - p_data = (tBTA_GATTS*)param; - CallControllerDeviceList *remoteDevice; - remoteDevice = cc_instance->remoteDevices.FindByConnId(p_data->conn_update.conn_id); - if((!remoteDevice) ) { - status = BT_STATUS_FAIL; - break; - } - - rsp->remoteDevice->peer_bda = remoteDevice->peer_bda; - rsp->event = CCS_DISCONNECTION; - rsp->remoteDevice = remoteDevice; - break; - } - - case BTA_GATTS_STOP_EVT: - //Do nothing - break; - - case BTA_GATTS_DELELTE_EVT: - //Do nothing - break; - - case BTA_GATTS_READ_CHARACTERISTIC_EVT: { - p_data = (tBTA_GATTS*)param; - std::vector value; - CallControllerDeviceList *remoteDevice = - cc_instance->remoteDevices.FindByConnId(p_data->req_data.conn_id); - LOG(INFO) << __func__ << " charateristcs read handle " << - p_data->req_data.p_data->read_req.handle <<" trans_id : " << - p_data->req_data.trans_id; - - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " device not found ignore read operation"; - status = BT_STATUS_FAIL; - break; - } - - LOG(INFO) <<" offset: " << p_data->req_data.p_data->read_req.offset << - " long : " << p_data->req_data.p_data->read_req.is_long; - - tGATTS_RSP rsp_struct; - rsp_struct.attr_value.auth_req = 0; - rsp_struct.attr_value.handle = p_data->req_data.p_data->read_req.handle; - rsp_struct.attr_value.offset = p_data->req_data.p_data->read_req.offset; - - if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.call_state_handle) { - std::vector loc_desc_value; - std::map::iterator it; - for (it = CallStatelist.begin(); it != CallStatelist.end(); it++){ - tCCS_CALL_STATE obj = it->second; - loc_desc_value.push_back(obj.index); - loc_desc_value.push_back(obj.state); - loc_desc_value.push_back(obj.flags); - } - size_t count = std::min((size_t)GATT_MAX_ATTR_LEN, loc_desc_value.size()); - rsp_struct.attr_value.len = count; - memcpy(rsp_struct.attr_value.value, loc_desc_value.data(), rsp_struct.attr_value.len); - - - LOG(INFO) << __func__ << " CallStateInfo read"; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.call_control_point_opcode_supported_handle) { - - rsp_struct.attr_value.len = sizeof(SupportedOptionalOpcodes.supp_opcode); - memcpy(rsp_struct.attr_value.value, &SupportedOptionalOpcodes.supp_opcode, rsp_struct.attr_value.len); - LOG(INFO) << __func__ << " callcontrol_point_opcode_supported_handle read"; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.bearer_provider_name_handle) { - LOG(INFO) << __func__ << " BearerProviderInfo name read " << BearerProviderInfo.name; - rsp_struct.attr_value.len = strlen((char *)BearerProviderInfo.name); - LOG(INFO) << __func__ << " BearerProviderInfo name len: " <req_data.p_data->read_req.handle == - ccsControlServiceInfo.bearer_list_currentcalls_handle) { - - std::vector loc_desc_value; - std::map::iterator it; - for (it = BlccInfolist.begin(); it != BlccInfolist.end(); it++){ - tCCS_BEARER_LIST_CURRENT_CALLS obj = it->second; - loc_desc_value.push_back(obj.list_length); - loc_desc_value.push_back(obj.call_index); - loc_desc_value.push_back(obj.call_state); - loc_desc_value.push_back(obj.call_flags); - - loc_desc_value.insert(loc_desc_value.end(), - obj.call_uri, obj.call_uri+(obj.list_length-3)); - } - size_t count = std::min((size_t)GATT_MAX_ATTR_LEN, loc_desc_value.size()); - rsp_struct.attr_value.len = count; - memcpy(rsp_struct.attr_value.value, loc_desc_value.data(), rsp_struct.attr_value.len); - LOG(INFO) << __func__ << " BlccInfo read"; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.bearer_technology_handle) { - rsp_struct.attr_value.len = sizeof(BearerProviderInfo.technology_type); - memcpy(rsp_struct.attr_value.value, &BearerProviderInfo.technology_type, rsp_struct.attr_value.len); - LOG(INFO) << __func__ << " technology_type read"; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.bearer_uci_handle) { - rsp_struct.attr_value.len = strlen((char *)BearerProviderInfo.uci); - memcpy(rsp_struct.attr_value.value, BearerProviderInfo.uci, rsp_struct.attr_value.len); - LOG(INFO) << __func__ << " Bearer UCI read"; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.bearer_signal_strength_handle) { - rsp_struct.attr_value.len = sizeof(BearerProviderInfo.signal); - memcpy(rsp_struct.attr_value.value, &BearerProviderInfo.signal, rsp_struct.attr_value.len); - LOG(INFO) << __func__ << " signal strength read"; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.bearer_signal_strength_report_interval_handle) { - rsp_struct.attr_value.len = sizeof(BearerProviderInfo.signal_report_interval); - memcpy(rsp_struct.attr_value.value, &BearerProviderInfo.signal_report_interval, rsp_struct.attr_value.len); - LOG(INFO) << __func__ << " signal_report_interval read"; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.bearer_uri_schemes_supported_handle) { - rsp_struct.attr_value.len = strlen((const char*)BearerProviderInfo.bearer_schemes_list); - memcpy(rsp_struct.attr_value.value, BearerProviderInfo.bearer_schemes_list, rsp_struct.attr_value.len); - LOG(INFO) << __func__ << " bearer_schemes_list read"; - }else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.incoming_call_handle) { - rsp_struct.attr_value.len = 1 + strlen((char*)IncomingCallInfo.incoming_uri); - memcpy(rsp_struct.attr_value.value, &IncomingCallInfo, rsp_struct.attr_value.len); - LOG(INFO) << __func__ << " Incoming call read"; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.incoming_call_target_beareruri_handle) { - rsp_struct.attr_value.len = 1 + strlen((char*)IncomingCallTargetUri.incoming_target_uri); - memcpy(rsp_struct.attr_value.value, &IncomingCallTargetUri, rsp_struct.attr_value.len); - LOG(INFO) << __func__ << " Incoming Call target URI read"; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.ccid_handle) { - rsp_struct.attr_value.len = sizeof(CcidInfo); - memcpy(rsp_struct.attr_value.value, &CcidInfo, rsp_struct.attr_value.len); - LOG(INFO) << __func__ << " Content Control read"; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.call_status_flags_handle) { - rsp_struct.attr_value.len = sizeof(StatusFlags.supported_flags); - memcpy(rsp_struct.attr_value.value, &StatusFlags.supported_flags, rsp_struct.attr_value.len); - LOG(INFO) << __func__ << " Status flags read"; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.call_friendly_name_handle) { - rsp_struct.attr_value.len = 1 + strlen((char*)FriendlyName.name); - memcpy(rsp_struct.attr_value.value, &FriendlyName, rsp_struct.attr_value.len); - LOG(INFO) << __func__ << " Call friendly name read"; - }else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.call_termination_reason_handle) { - rsp_struct.attr_value.len = sizeof(TerminationReason); - memcpy(rsp_struct.attr_value.value, &TerminationReason, rsp_struct.attr_value.len); - LOG(INFO) << __func__ << " Termination Reason read"; - } - else { - LOG(INFO) << __func__ << " read request for unknow handle " << p_data->req_data.p_data->read_req.handle; - status = BT_STATUS_FAIL; - break; - } - LOG(INFO) << __func__ << " read request handle " << p_data->req_data.p_data->read_req.handle << - "connection id " << p_data->req_data.conn_id; - rsp->oper.ReadOp.char_handle = rsp_struct.attr_value.handle; - rsp->oper.ReadOp.trans_id = p_data->req_data.trans_id; - rsp->oper.ReadOp.status = BT_STATUS_SUCCESS; - rsp->event = CCS_READ_RSP; - rsp->remoteDevice = remoteDevice; - - memcpy((void*)&rsp->rsp_value, &rsp_struct, sizeof(rsp_struct)); - break; - } - - case BTA_GATTS_READ_DESCRIPTOR_EVT: { - LOG(INFO) << __func__ << " read descriptor"; - p_data = (tBTA_GATTS*)param; - LOG(INFO) << __func__ << " charateristcs read desc handle " << - p_data->req_data.p_data->read_req.handle << " offset : " - << p_data->req_data.p_data->read_req.offset; - CallControllerDeviceList *remoteDevice = - cc_instance->remoteDevices.FindByConnId(p_data->req_data.conn_id); - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " device not found ignore write"; - status = BT_STATUS_FAIL; - break; - } - uint16_t data = 0x00; - if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.call_state_desc) { - LOG(INFO) << __func__ << " call_state_desc read"; - data = remoteDevice->call_state_notify; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.call_control_point_desc) { - LOG(INFO) << __func__ << " callcontrol_point_desc read"; - data = remoteDevice->call_control_point_notify; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.bearer_provider_name_desc) { - LOG(INFO) << __func__ << " bearer_provider_name_desc read"; - data = remoteDevice->bearer_provider_name_notify; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.bearer_signal_strength_desc) { - LOG(INFO) << __func__ << " bearer_signal_strength desc read"; - data = remoteDevice->bearer_signal_strength_notify; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.bearer_list_currentcalls_desc) { - LOG(INFO) << __func__ << " bearer_list_currentcall read"; - data = remoteDevice->bearer_current_calls_list_notify; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.bearer_technology_desc) { - LOG(INFO) << __func__ << " bearer_technology_desc read"; - data = remoteDevice->bearer_technology_changed_notify; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.bearer_uci_desc) { - LOG(INFO) << __func__ << " bearer_uci_desc read"; - data = remoteDevice->bearer_uci_notify; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.bearer_uri_schemes_supported_desc) { - LOG(INFO) << __func__ << " bearer_uri_schemes_supported_desc read"; - data = remoteDevice->bearer_uri_schemes_supported_notify; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.call_friendly_name_desc) { - LOG(INFO) << __func__ << " call_friendly_name_desc read"; - data = remoteDevice->call_friendly_name_notify; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.call_control_point_opcode_supported_desc) { - LOG(INFO) << __func__ << " call_control_point_opcode_supported_desc read"; - data = remoteDevice->call_control_point_opcode_supported_notify; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.call_termination_reason_desc) { - LOG(INFO) << __func__ << " call_termination_reason_desc read"; - data = remoteDevice->call_termination_reason_notify; - } else if(p_data->req_data.p_data->read_req.handle == - ccsControlServiceInfo.bearer_signal_strength_report_interval_desc) { - LOG(INFO) << __func__ << " bearer_signal_strength_report_interval_desc read"; - data = remoteDevice->bearer_signal_strength_report_interval_notify; - } else { - LOG(INFO) << __func__ << " read request for unknown handle " << p_data->req_data.p_data->read_req.handle; - status = BT_STATUS_FAIL; - break; - } - rsp->rsp_value.attr_value.auth_req = 0; - rsp->rsp_value.attr_value.handle = p_data->req_data.p_data->read_req.handle; - rsp->rsp_value.attr_value.offset = p_data->req_data.p_data->read_req.offset; - *(uint16_t *)rsp->rsp_value.attr_value.value = (uint16_t)data; - rsp->rsp_value.attr_value.len = sizeof(data); - //cc response - rsp->oper.ReadDescOp.desc_handle = p_data->req_data.p_data->read_req.handle; - rsp->oper.ReadDescOp.trans_id = p_data->req_data.trans_id; - rsp->oper.ReadDescOp.status = BT_STATUS_SUCCESS; - rsp->remoteDevice = remoteDevice; - rsp->event = CCS_DESCRIPTOR_READ_RSP; - break; - } - - case BTA_GATTS_WRITE_CHARACTERISTIC_EVT: { - - p_data = (tBTA_GATTS*)param; - tGATT_WRITE_REQ req = p_data->req_data.p_data->write_req; - LOG(INFO) << __func__ << " write characteristics len: " << req.len; - PrintData(req.value, req.len); - CallControllerDeviceList *remoteDevice = - cc_instance->remoteDevices.FindByConnId(p_data->req_data.conn_id); - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " device not found ignore write"; - status = BT_STATUS_FAIL; - break; - } - if ( status != BT_STATUS_FAIL) { - rsp->oper.WriteOp.char_handle = req.handle; - rsp->oper.WriteOp.trans_id = p_data->req_data.trans_id; - rsp->oper.WriteOp.status = BT_STATUS_SUCCESS; - rsp->remoteDevice = remoteDevice; - rsp->oper.WriteOp.need_rsp = req.need_rsp; - rsp->oper.WriteOp.offset = req.offset; - rsp->oper.WriteOp.len = req.len; - rsp->oper.WriteOp.data = (uint8_t*) malloc(sizeof(uint8_t)*req.len); - memcpy(rsp->oper.WriteOp.data, req.value, req.len); - rsp->event = CCS_WRITE_RSP; - } - break; - } - - case BTA_GATTS_WRITE_DESCRIPTOR_EVT: { - - p_data = (tBTA_GATTS* )param; - std::vector write_desc_value; - write_desc_value.clear(); - uint16_t handle = 0; - uint16_t req_value = 0; - const auto& req = p_data->req_data.p_data->write_req; - CallControllerDeviceList *remoteDevice = - cc_instance->remoteDevices.FindByConnId(p_data->req_data.conn_id); - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " device not found ignore notification"; - break; - } - req_value = *(uint16_t* )req.value; - //need to initialized with proper error code - int status = BT_STATUS_SUCCESS; - LOG(INFO) << __func__ << " write descriptor :" << req.handle << - " is resp: " << req.need_rsp << "is prep: " << req.is_prep << " value " << req_value; - - if(req.handle == - ccsControlServiceInfo.call_state_desc) { - LOG(INFO) << __func__ << " call_state_desc descriptor write"; - remoteDevice->call_state_notify = req_value; - std::map::iterator it; - for (it = CallStatelist.begin(); it != CallStatelist.end(); it++){ - tCCS_CALL_STATE obj = it->second; - write_desc_value.push_back(obj.index); - write_desc_value.push_back(obj.state); - write_desc_value.push_back(obj.flags); - } - handle = ccsControlServiceInfo.call_state_handle; - } else if(req.handle == - ccsControlServiceInfo.bearer_provider_name_desc) { - remoteDevice->bearer_provider_name_notify = req_value; - LOG(INFO) << __func__ << " bearer_provider_name_desc descriptor write"; - write_desc_value.assign(BearerProviderInfo.name, - BearerProviderInfo.name + strlen((char*)BearerProviderInfo.name)); - handle = ccsControlServiceInfo.bearer_provider_name_handle; - } else if(req.handle == - ccsControlServiceInfo.call_control_point_desc) { - LOG(INFO) << __func__ << " callcontrol_point_desc write"; - write_desc_value.push_back(CallControllerResp.opcode); - write_desc_value.push_back(CallControllerResp.index); - write_desc_value.push_back(CallControllerResp.response_status); - - remoteDevice->call_control_point_notify = req_value; - handle = ccsControlServiceInfo.call_control_point_handle; - } else if(req.handle == - ccsControlServiceInfo.bearer_signal_strength_desc) { - LOG(INFO) << __func__ << " bearer_signal_strength desc write"; - write_desc_value.push_back(BearerProviderInfo.signal); - remoteDevice->bearer_signal_strength_notify = req_value; - handle = ccsControlServiceInfo.bearer_signal_strength_handle; - } else if(req.handle == - ccsControlServiceInfo.bearer_uri_schemes_supported_desc) { - remoteDevice->bearer_uri_schemes_supported_notify = req_value; - write_desc_value.assign(BearerProviderInfo.bearer_schemes_list, - BearerProviderInfo.bearer_schemes_list + strlen((char*)BearerProviderInfo.bearer_schemes_list)); - LOG(INFO) << __func__ << " bearer_schemes_list Desc write"; - } else if(req.handle == - ccsControlServiceInfo.bearer_list_currentcalls_desc) { - std::map::iterator it; - LOG(INFO) << __func__ << " bearer_list_currentcall desc write"; - for (it = BlccInfolist.begin(); it != BlccInfolist.end(); it++){ - tCCS_BEARER_LIST_CURRENT_CALLS obj = it->second; - write_desc_value.push_back(obj.list_length); - write_desc_value.push_back(obj.call_index); - write_desc_value.push_back(obj.call_state); - write_desc_value.push_back(obj.call_flags); - write_desc_value.insert(write_desc_value.end(), - obj.call_uri, obj.call_uri+(obj.list_length-3)); - } - remoteDevice->bearer_current_calls_list_notify = req_value; - handle = ccsControlServiceInfo.bearer_list_currentcalls_handle; - - } else if(req.handle == - ccsControlServiceInfo.bearer_technology_desc) { - LOG(INFO) << __func__ << " bearer_technology_desc write"; - remoteDevice->bearer_technology_changed_notify = req_value; - write_desc_value.push_back(BearerProviderInfo.technology_type); - handle = ccsControlServiceInfo.bearer_technology_handle; - } else if(req.handle == - ccsControlServiceInfo.call_friendly_name_desc) { - LOG(INFO) << __func__ << " call_friendly_name_desc read"; - remoteDevice->call_friendly_name_notify = req_value; - int len = 1 + strlen((char*)FriendlyName.name); - write_desc_value.assign((uint8_t*)&FriendlyName, (uint8_t*)&FriendlyName+len); - handle = ccsControlServiceInfo.call_friendly_name_handle; - } else if(req.handle == - ccsControlServiceInfo.call_termination_reason_desc) { - LOG(INFO) << __func__ << " call_termination_reason_desc write"; - remoteDevice->call_termination_reason_notify = req_value; - handle = ccsControlServiceInfo.call_termination_reason_handle; - write_desc_value.push_back(TerminationReason.index); - write_desc_value.push_back(TerminationReason.reason); - - handle = ccsControlServiceInfo.call_termination_reason_handle; - } else if(req.handle == - ccsControlServiceInfo.call_status_flags_desc) { - LOG(INFO) << __func__ << " Status Flags Desc write"; - remoteDevice->status_flags_notify= req_value; - write_desc_value.push_back(StatusFlags.supported_flags); - handle = ccsControlServiceInfo.call_status_flags_handle; - - } else if(req.handle == - ccsControlServiceInfo.incoming_call_target_bearerURI_desc) { - LOG(INFO) << __func__ << " Incoming target bearer desc write"; - int len = 1 + strlen((char*)IncomingCallTargetUri.incoming_target_uri); - write_desc_value.assign((uint8_t*)&IncomingCallTargetUri, (uint8_t*)&IncomingCallTargetUri+len); - remoteDevice->incoming_call_target_URI_notify= req_value; - handle = ccsControlServiceInfo.incoming_call_target_beareruri_handle; - - } else if(req.handle == - ccsControlServiceInfo.incoming_call_desc) { - LOG(INFO) << __func__ << " Incoming Call desc write"; - remoteDevice->incoming_call_state_notify = req_value; - int len = 1 + strlen((char*)IncomingCallInfo.incoming_uri); - write_desc_value.assign((uint8_t*)&IncomingCallInfo, (uint8_t*)&IncomingCallInfo+len); - - handle = ccsControlServiceInfo.incoming_call_handle; - } else { - LOG(INFO) << __func__ << " descriptor write not matched"; - status = 4; //check error code - } - rsp->oper.WriteDescOp.desc_handle = req.handle; - rsp->oper.WriteDescOp.char_handle = handle; - rsp->oper.WriteDescOp.trans_id = p_data->req_data.trans_id; - rsp->oper.WriteDescOp.status = status; - rsp->oper.WriteDescOp.need_rsp = req.need_rsp; - rsp->oper.WriteDescOp.notification = req_value; - rsp->oper.WriteDescOp.value = std::move(write_desc_value); - rsp->event = CCS_DESCRIPTOR_WRITE_RSP; - rsp->remoteDevice = remoteDevice; - break; - } - - case BTA_GATTS_EXEC_WRITE_EVT: { - p_data = (tBTA_GATTS*)param; - break; - } - - case BTA_GATTS_CLOSE_EVT: { - //not required - break; - } - - case BTA_GATTS_PHY_UPDATE_EVT: { - - p_data = (tBTA_GATTS*)param; - CallControllerDeviceList *remoteDevice = - cc_instance->remoteDevices.FindByConnId(p_data->phy_update.conn_id); - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " device not found ignore phy update " - << p_data->phy_update.status; - status = BT_STATUS_FAIL; - break; - } - rsp->event = CCS_PHY_UPDATE; - rsp->oper.PhyOp.rx_phy = p_data->phy_update.rx_phy; - rsp->oper.PhyOp.tx_phy = p_data->phy_update.tx_phy; - rsp->remoteDevice = remoteDevice; - break; - } - - case BTA_GATTS_CONN_UPDATE_EVT: { - p_data = (tBTA_GATTS*)param; - CallControllerDeviceList *remoteDevice = - cc_instance->remoteDevices.FindByConnId(p_data->phy_update.conn_id); - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " connection update device not found"; - break; - } - LOG(INFO) << __func__ << " connection update status " << p_data->phy_update.status; - rsp->event = CCS_CONNECTION_UPDATE; - rsp->oper.ConnectionUpdateOp.remoteDevice = remoteDevice; - rsp->oper.ConnectionUpdateOp.remoteDevice->latency = p_data->conn_update.latency; - rsp->oper.ConnectionUpdateOp.remoteDevice->timeout = p_data->conn_update.timeout; - rsp->oper.ConnectionUpdateOp.remoteDevice->interval = p_data->conn_update.interval; - rsp->oper.ConnectionUpdateOp.status = p_data->conn_update.status; - rsp->remoteDevice = remoteDevice; - break; - } - - case CCS_ACTIVE_DEVICE_UPDATE: - { - tCCS_SET_ACTIVE_DEVICE *data = (tCCS_SET_ACTIVE_DEVICE *)param; - LOG(INFO) << __func__ << " CCS_ACTIVE_DEVICE_UPDATE address " << data->address; - if (cc_instance->remoteDevices.FindByAddress(data->address) != NULL) { - cc_instance->remoteDevices.AddSetActiveDevice(data); - } else { - LOG(ERROR) << __func__ << " CCS_ACTIVE_DEVICE_UPDATE failed as given remote is not registered for notif " << data->address; - } - break; - } - case CCS_CONNECTION_CLOSE_EVENT: - { - break; - } - case CCS_CALL_STATE_UPDATE: - { - std::map::iterator it; - for (it = CallStatelist.begin(); it != CallStatelist.end(); it++){ - tCCS_CALL_STATE obj = it->second; - _data.push_back(obj.index); - _data.push_back(obj.state); - _data.push_back(obj.flags); - } - rsp->event = CCS_NOTIFY_ALL; - rsp->handle = ccsControlServiceInfo.call_state_handle; - isCallControllerOpUsed = true; - break; - } - case CCS_BEARER_NAME_UPDATE: - { - LOG(INFO) << __func__ << " CCS_BEARER_NAME_UPDATE"; - tCCS_BEARER_PROVIDER_INFO *data = (tCCS_BEARER_PROVIDER_INFO*) param; - uint16_t len = strlen((char*)data->name); - ReverseByteOrder(data->name, len); - memcpy(BearerProviderInfo.name, data->name, len); - rsp->event = CCS_NOTIFY_ALL; - rsp->handle = ccsControlServiceInfo.bearer_provider_name_handle; - _data.assign(BearerProviderInfo.name, - BearerProviderInfo.name + len); - isCallControllerOpUsed = true; - break; - } - - case CCS_OPT_OPCODES: - { - LOG(INFO) << __func__ << " CCS_OPT_OPCODES"; - tCCS_SUPP_OPTIONAL_OPCODES *data = (tCCS_SUPP_OPTIONAL_OPCODES*) param; - SupportedOptionalOpcodes.supp_opcode = data->supp_opcode; - - rsp->event = CCS_NOTIFY_ALL; - rsp->handle = ccsControlServiceInfo.call_control_point_opcode_supported_handle; - - _data.push_back(SupportedOptionalOpcodes.supp_opcode); - isCallControllerOpUsed = true; - break; - } - - case CCS_BEARER_CURRENT_CALL_LIST_UPDATE: - { - LOG(INFO) << __func__ << " CCS_BEARER_CURRENT_CALL_LIST_UPDATE"; - std::map::iterator it; - for (it = BlccInfolist.begin(); it != BlccInfolist.end(); it++){ - tCCS_BEARER_LIST_CURRENT_CALLS obj = it->second; - _data.push_back(obj.list_length); - _data.push_back(obj.call_index); - _data.push_back(obj.call_state); - _data.push_back(obj.call_flags); - _data.insert(_data.end(), - obj.call_uri, obj.call_uri+(obj.list_length-3)); - } - - rsp->event = CCS_NOTIFY_ALL; - rsp->handle = ccsControlServiceInfo.bearer_list_currentcalls_handle; - isCallControllerOpUsed = true; - break; - } - - case CCS_BEARER_SIGNAL_STRENGTH_UPDATE: - { - LOG(INFO) << __func__ << " CCS_BEARER_SIGNAL_STRENGTH_UPDATE"; - tCCS_BEARER_PROVIDER_INFO *data = (tCCS_BEARER_PROVIDER_INFO *) param; - BearerProviderInfo.signal = data->signal; - rsp->event = CCS_NOTIFY_ALL; - rsp->handle = ccsControlServiceInfo.bearer_signal_strength_handle; - //control whether notification has to happen based - //on reporting Interval time or not - rsp->force = false; - _data.push_back(BearerProviderInfo.signal); - isCallControllerOpUsed = true; - break; - } - - case CCS_BEARER_TECHNOLOGY_UPDATE: - { - LOG(INFO) << __func__ << " CCS_BEARER_TECHNOLOGY_UPDATE"; - tCCS_BEARER_PROVIDER_INFO *data = (tCCS_BEARER_PROVIDER_INFO *) param; - BearerProviderInfo.technology_type = data->technology_type; - rsp->event = CCS_NOTIFY_ALL; - rsp->handle = ccsControlServiceInfo.bearer_technology_handle; - _data.push_back(BearerProviderInfo.technology_type); - isCallControllerOpUsed = true; - break; - } - - case CCS_BEARER_URI_SCHEMES_SUPPORTED: { - LOG(INFO) << __func__ << " CCS_BEARER_URI_SCHEMES_SUPPORTED"; - tCCS_BEARER_PROVIDER_INFO *data = (tCCS_BEARER_PROVIDER_INFO*) param; - BearerProviderInfo.bearer_list_len = data->bearer_list_len; - LOG(INFO) << __func__ << " CCS_BEARER_URI_SCHEMES_SUPPORTED: len " <bearer_schemes_list, BearerProviderInfo.bearer_list_len); - memcpy(BearerProviderInfo.bearer_schemes_list, data->bearer_schemes_list, BearerProviderInfo.bearer_list_len); - rsp->event = CCS_NOTIFY_ALL; - rsp->handle = ccsControlServiceInfo.bearer_uri_schemes_supported_handle; - isCallControllerOpUsed = true; - _data.assign(BearerProviderInfo.bearer_schemes_list, - BearerProviderInfo.bearer_schemes_list + BearerProviderInfo.bearer_list_len); - isCallControllerOpUsed = true; - break; - } - - case CCS_INCOMING_CALL_UPDATE: - { - LOG(INFO) << __func__ << " CCS_INCOMING_CALL_UPDATE"; - tCCS_INCOMING_CALL* data = (tCCS_INCOMING_CALL *) param; - IncomingCallInfo.index = data->index; - uint16_t len = strlen((char*)data->incoming_uri); - ReverseByteOrder(data->incoming_uri, len); - memcpy(IncomingCallInfo.incoming_uri, data->incoming_uri, len); - - rsp->event = CCS_NOTIFY_ALL; - rsp->handle = ccsControlServiceInfo.incoming_call_handle; - _data.push_back(IncomingCallInfo.index); - _data.insert(_data.end(), IncomingCallInfo.incoming_uri, - IncomingCallInfo.incoming_uri + len); - isCallControllerOpUsed = true; - break; - } - - case CCS_INCOMING_TARGET_URI_UPDATE: - { - LOG(INFO) << __func__ << " CCS_INCOMING_TARGET_URI_UPDATE"; - tCCS_INCOMING_CALL_URI* data = (tCCS_INCOMING_CALL_URI *) param; - IncomingCallTargetUri.index = data->index; - uint16_t len = strlen((char*)data->incoming_target_uri); - LOG(INFO) << __func__ << " CCS_INCOMING_TARGET_URI_UPDATE: urilen " << len; - ReverseByteOrder(data->incoming_target_uri, len); - memcpy(IncomingCallTargetUri.incoming_target_uri, data->incoming_target_uri, len); - - rsp->event = CCS_NOTIFY_ALL; - rsp->handle = ccsControlServiceInfo.incoming_call_target_beareruri_handle; - _data.push_back(IncomingCallTargetUri.index); - _data.insert(_data.end(), IncomingCallTargetUri.incoming_target_uri, - IncomingCallTargetUri.incoming_target_uri + len); - isCallControllerOpUsed = true; - break; - } - - case CCS_TERMINATION_REASON_UPDATE: - { - LOG(INFO) << __func__ << " CCS_TERMINATION_REASON_UPDATE"; - tCCS_TERM_REASON* data = (tCCS_TERM_REASON *) param; - TerminationReason.index = data->index; - TerminationReason.reason = data->reason; - - rsp->event = CCS_NOTIFY_ALL; - rsp->handle = ccsControlServiceInfo.call_termination_reason_handle; - _data.push_back(TerminationReason.index); - _data.push_back(TerminationReason.reason); - - isCallControllerOpUsed = true; - break; - } - - case CCS_STATUS_FLAGS_UPDATE: - { - LOG(INFO) << __func__ << " CCS_STATUS_FLAGS_UPDATE"; - tCCS_STATUS_FLAGS *data = (tCCS_STATUS_FLAGS*) param; - - ReverseByteOrder((unsigned char*)&data->supported_flags, sizeof(data->supported_flags)); - StatusFlags.supported_flags = data->supported_flags; - rsp->event = CCS_NOTIFY_ALL; - rsp->handle = ccsControlServiceInfo.call_status_flags_handle; - _data.push_back(StatusFlags.supported_flags); - isCallControllerOpUsed = true; - break; - } - - case CCS_CCID_UPDATE: - { - LOG(INFO) << __func__ << " CCS_CCID_UPDATE"; - tCCS_CONTENT_CONTROL_ID *data = (tCCS_CONTENT_CONTROL_ID *) param; - ReverseByteOrder((unsigned char*)&data->ccid, sizeof(data->ccid)); - CcidInfo.ccid = (uint32_t)data->ccid; - rsp->event = CCS_NOTIFY_ALL; - rsp->handle = ccsControlServiceInfo.ccid_handle; - _data.push_back(CcidInfo.ccid); - isCallControllerOpUsed = true; - break; - } - - case CCS_CALL_CONTROL_RESPONSE: - { - LOG(INFO) << __func__ << " CCS_CALL_CONTROL_RESPONSE"; - - rsp->event = CCS_NOTIFY_ALL; - rsp->handle = ccsControlServiceInfo.call_control_point_handle; - _data.push_back(CallControllerResp.opcode); - _data.push_back(CallControllerResp.index); - _data.push_back(CallControllerResp.response_status); - isCallControllerOpUsed = true; - break; - } - default: - LOG(INFO) << __func__ << " event not matched !!"; - break; - } - - if(rsp->event != CCS_NONE_EVENT) { - if (isCallControllerOpUsed == true) { - rsp->oper.CallControllerOp.data = std::move(_data); - LOG(INFO) << __func__ << " After Moving size " << rsp->oper.CallControllerOp.data.size(); - } - CCSHandler(rsp->event, rsp); - } - if(rsp) { - LOG(INFO) << __func__ << "free rsp data"; - free(rsp); - } -} - - - -void BTCcCback(tBTA_GATTS_EVT event, tBTA_GATTS* param) { - - HandleCcsEvent((uint32_t)event, param); -} - - - bool DeviceStateConnectionHandler(uint32_t event, void* param) { - LOG(INFO) << __func__ << " device connected handle " << event; - tcc_resp_t *p_data = (tcc_resp_t *) param; - switch (event) { - - case CCS_NOTIFY_ALL: { - LOG(INFO) << __func__ << " device notify all"; - if (p_data->handle == ccsControlServiceInfo.bearer_signal_strength_handle) { - if (p_data->force == false && - p_data->remoteDevice->signal_strength_report_interval != 0) { - LOG(INFO) << __func__ << "Not a timer expired push, dont notify to remote"; - break; - } - } - - GattsOpsQueue::SendNotification(p_data->remoteDevice->conn_id, p_data->handle, - p_data->oper.CallControllerOp.data, false); - break; - } - - case CCS_READ_RSP: - - LOG(INFO) << __func__ << " device CCS_READ_RSP update " << event; - BTA_GATTS_SendRsp(p_data->remoteDevice->conn_id, p_data->oper.ReadOp.trans_id, - BT_STATUS_SUCCESS, &p_data->rsp_value); - break; - - case CCS_DESCRIPTOR_READ_RSP: - - LOG(INFO) << __func__ << " device CCS_DESCRIPTOR_READ_RSP update " << event; - BTA_GATTS_SendRsp(p_data->remoteDevice->conn_id, p_data->oper.ReadDescOp.trans_id, - BT_STATUS_SUCCESS, &p_data->rsp_value); - break; - - case CCS_DESCRIPTOR_WRITE_RSP: - { - LOG(INFO) << __func__ << " device CCS_DESCRIPTOR_WRITE_RSP update rsp: " << p_data->oper.WriteDescOp.need_rsp; - tGATTS_RSP rsp_struct; - rsp_struct.attr_value.handle = p_data->rsp_value.attr_value.handle; - rsp_struct.attr_value.offset = p_data->rsp_value.attr_value.offset; - if (p_data->remoteDevice->congested == false && - p_data->oper.WriteDescOp.need_rsp) { - //send rsp to write - LOG(INFO) << __func__ << " gett send rsp"; - BTA_GATTS_SendRsp(p_data->remoteDevice->conn_id, p_data->oper.WriteDescOp.trans_id, - p_data->oper.WriteDescOp.status, &rsp_struct); - } - if (!p_data->oper.WriteDescOp.status && p_data->oper.WriteDescOp.notification) { - //notify update to register device - GattsOpsQueue::SendNotification(p_data->remoteDevice->conn_id, - p_data->oper.WriteDescOp.char_handle, - p_data->oper.WriteDescOp.value, false); - } else { - LOG(INFO) << __func__ << " notification disable handle : " << p_data->oper.WriteDescOp.char_handle; - } - break; - } - - case CCS_WRITE_RSP: { - LOG(INFO) << __func__ << " device CCS_WRITE_RSP update " << event; - bool need_rsp = p_data->oper.WriteOp.need_rsp; - LOG(INFO) << __func__ << " device CCS_WRITE_RSP update " << event << " need_rsp: " <remoteDevice->conn_id, p_data->oper.WriteOp.trans_id, - BT_STATUS_SUCCESS, &p_data->rsp_value); - } - break; - } - - case CCS_CONNECTION_UPDATE: { - LOG(INFO) << __func__ << " device cconnection update " << event; - break; - } - - case CCS_PHY_UPDATE: { - LOG(INFO) << __func__ << " device CCS_PHY_UPDATE update " << event; - p_data->remoteDevice->rx_phy = p_data->oper.PhyOp.rx_phy; - p_data->remoteDevice->tx_phy = p_data->oper.PhyOp.tx_phy; - break; - } - - case CCS_MTU_UPDATE: { - LOG(INFO) << __func__ << " device CCS_MTU_UPDATE update " << event; - p_data->remoteDevice->mtu = p_data->oper.MtuOp.mtu; - break; - } - - case CCS_CONGESTION_UPDATE: { - LOG(INFO) << __func__ << ": device CCS_CONGESTION_UPDATE update: " << event; - CcpCongestionUpdate(p_data); - break; - } - - case CCS_DISCONNECTION: { - LOG(INFO) << __func__ << " device CCS_DISCONNECTION remove " << event; - cc_instance->remoteDevices.Remove(p_data->remoteDevice->peer_bda); - cc_instance->ConnectionStateCallback(CCS_DISCONNECTED, p_data->remoteDevice->peer_bda); - break; - } - - case CCS_CONNECTION_CLOSE_EVENT: { - LOG(INFO) << __func__ << " device connection closing"; - // Close active connection - if (p_data->remoteDevice->conn_id != 0) - BTA_GATTS_Close(p_data->remoteDevice->conn_id); - else - BTA_GATTS_CancelOpen(ccsControlServiceInfo.server_if, p_data->remoteDevice->peer_bda, true); - // Cancel pending background connections - BTA_GATTS_CancelOpen(ccsControlServiceInfo.server_if, p_data->remoteDevice->peer_bda, false); - break; - } - - case CCS_BOND_STATE_CHANGE_EVENT: - LOG(INFO) << __func__ << " Bond state change"; - cc_instance->remoteDevices.Remove(p_data->remoteDevice->peer_bda); - break; - - default: - LOG(INFO) << __func__ << " event not matched"; - break; - } - - return BT_STATUS_SUCCESS; -} - - -bool DeviceStateDisconnectedHandler(uint32_t event, void* param) { - LOG(INFO) << __func__ << " device disconnected handle " << event; - tcc_resp_t *p_data = (tcc_resp_t *) param; - switch (event) { - case CCS_CONNECTION: - { - LOG(INFO) << __func__ << " connection processing " << event; - p_data->remoteDevice->state = CCS_CONNECTED; - p_data->remoteDevice->call_state_notify = 0x00; - p_data->remoteDevice->bearer_provider_name_notify = 0x00; - p_data->remoteDevice->call_control_point_notify = 0x00; - p_data->remoteDevice->bearer_technology_changed_notify = 0x00; - p_data->remoteDevice->bearer_uci_notify = 0x00; - p_data->remoteDevice->bearer_current_calls_list_notify = 0x00; - p_data->remoteDevice->call_friendly_name_notify = 0x00; - p_data->remoteDevice->call_termination_reason_notify = 0x00; - p_data->remoteDevice->congested = false; - // p_data->remoteDevice->conn_id; - - p_data->remoteDevice->timeout = 0; - p_data->remoteDevice->latency = 0; - p_data->remoteDevice->interval = 0; - p_data->remoteDevice->rx_phy = 0; - p_data->remoteDevice->tx_phy = 0; - cc_instance->ConnectionStateCallback(CCS_CONNECTED, p_data->remoteDevice->peer_bda); - break; - } - - case CCS_CONGESTION_UPDATE: { - LOG(INFO) << __func__ << ": device CCS_CONGESTION_UPDATE update: " << event; - CcpCongestionUpdate(p_data); - break; - } - - case CCS_MTU_UPDATE: - case CCS_PHY_UPDATE: - case CCS_DISCONNECTED: - case CCS_READ_RSP: - case CCS_DESCRIPTOR_READ_RSP: - case CCS_WRITE_RSP: - case CCS_DESCRIPTOR_WRITE_RSP: - case CCS_NOTIFY_ALL: - case CCS_DISCONNECTION: - - default: - //ignore event - LOG(INFO) << __func__ << " Ignore event " << event; - break; - } - return BT_STATUS_SUCCESS; -} - -bool is_digits(const std::string &str) -{ - return str.find_first_not_of("0123456789+") == std::string::npos; -} - -bool IsValidOriginateUri(std::string uri) { - bool ret = false; - std::vector out; - char *token; - char* rest = const_cast(uri.c_str()); - while ((token = strtok_r(rest, ":", &rest))) - { - out.push_back(std::string(token)); - } - if (out.size() == 2) { - if (out[0].compare("tel") == 0 && is_digits(out[1])) { - ret = true; - } - } - LOG(INFO) << __func__ << " ret: " << ret; - return ret; -} - -bool CCSActiveProfile(RawAddress addr) { - bool isCCSActiveProfile = false; - int32_t activeProfile; - activeProfile = osi_property_get_int32("persist.vendor.qcom.bluetooth.default_profiles",0); - if ((activeProfile&0x2000) == 0x2000) { - isCCSActiveProfile = true; - } - LOG(INFO) << __func__ << " activeProfile "<< activeProfile <<" for" << addr; - return isCCSActiveProfile; -} - -bool CCSHandler(uint32_t event, void* param) { - - tcc_resp_t *p_data = (tcc_resp_t *)param; - - CallControllerDeviceList *device = p_data->remoteDevice; - LOG(INFO) << __func__ << " inactive ccs handle event "<< bta_cc_event_str(event); - switch(p_data->event) { - case CCS_NOTIFY_ALL: { - - std::vectornotifyDevices = cc_instance->remoteDevices.FindNotifyDevices(p_data->handle); - std::vector::iterator it; - LOG(INFO) << __func__ << " Notify all handle "<< p_data->handle; - if (notifyDevices.size() <= 0) { - LOG(INFO) << __func__ << " No device register for notification"; - break; - } - for (it = notifyDevices.begin(); it != notifyDevices.end(); it++){ - if (CCSActiveProfile(it->peer_bda)) { - LOG(INFO) << __func__ << " Notify all handle device id " << it->conn_id; - p_data->remoteDevice = cc_instance->remoteDevices.FindByConnId(it->conn_id); - it->DeviceStateHandlerPointer[it->state](p_data->event, p_data); - } - } - break; - } - case CCS_WRITE_RSP: { - - LOG(INFO) << __func__ << " Push Write response first: " << device->state; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data); - //Process the values now - uint8_t* data = p_data->oper.WriteOp.data; - int len = p_data->oper.WriteOp.len; - RawAddress peer_bda = p_data->remoteDevice->peer_bda; - std::map::iterator it; - bool valid_index = false; - uint8_t indices[10]; - char URI[MAX_URI_SIZE]; - int i; - uint32_t handle = p_data->oper.WriteOp.char_handle; - if(handle == ccsControlServiceInfo.call_control_point_handle) { - CallControllerOps.operation = data[0]; - LOG(INFO) << __func__ << " operation: " << std::hex << CallControllerOps.operation; - if (gIsActiveCC == true && !cc_instance->remoteDevices.FindActiveDevice(p_data->remoteDevice) && - (CallControllerOps.operation == CALL_TERMINATE || - CallControllerOps.operation == CALL_LOCAL_HOLD || - CallControllerOps.operation == CALL_LOCAL_RETRIEVE)) { - LOG(ERROR) << __func__ << "TERM|HOLD|RET|JOIN triggered from non-active Device"; - cc_instance->CallControlResponse(CallControllerOps.operation, - CCS_DEFAULT_INDEX_VAL, - CCS_OPCODE_UNSUCCESSFUL, peer_bda); - return true; - } - switch(CallControllerOps.operation) { - case CALL_ACCEPT:{ - if (len != 2) { - LOG(ERROR) << __func__ << " Invalid params"; - valid_index = false; - } else { - indices[0] = data[1]; - valid_index = false; - for (i=0,it = CallStatelist.begin(); it != CallStatelist.end(); it++, i++){ - tCCS_CALL_STATE obj = it->second; - if (obj.index == indices[0] && obj.state == CCS_STATE_INCOMING) { - valid_index = true; - break; - } - } - } - if (valid_index == true) { - cc_instance->CallControlPointChange(CallControllerOps.operation, indices, - DEFAULT_INDICIES_COUNT, NULL, - device->peer_bda); - cc_instance->CallControlResponse(CallControllerOps.operation, - indices[0], - CCS_STATUS_SUCCESS, peer_bda); - } else { - LOG(INFO) << " ACCEPT ignored as there is no valid Index"; - cc_instance->CallControlResponse(CallControllerOps.operation, - CCS_DEFAULT_INDEX_VAL, - CCS_INVALID_INDEX, peer_bda); - } - break; - } - case CALL_TERMINATE: { - if (len != 2) { - LOG(ERROR) << __func__ << " Invalid params"; - valid_index = false; - } else { - indices[0] = data[1]; - valid_index = false; - for (i=0,it = CallStatelist.begin(); it != CallStatelist.end(); it++, i++) { - tCCS_CALL_STATE obj = it->second; - if (obj.index == indices[0]) { - LOG(INFO) << __func__ << " call index match: " << indices[0]; - valid_index = true; - break; - } - } - } - if (valid_index == true) { - cc_instance->CallControlPointChange(CallControllerOps.operation, indices, - DEFAULT_INDICIES_COUNT, NULL, - device->peer_bda); - cc_instance->CallControlResponse(CallControllerOps.operation, - indices[0], - CCS_STATUS_SUCCESS, peer_bda); - gIsTerminatedInitiatedFromClient = true; - gTerminateIntiatedIndex = indices[0]; - } else { - LOG(INFO) << " TERMINATE ignored as there is no valid Index"; - cc_instance->CallControlResponse(CallControllerOps.operation, - CCS_DEFAULT_INDEX_VAL, - CCS_INVALID_INDEX, peer_bda); - } - break; - } - case CALL_LOCAL_HOLD: { - if (len != 2) { - LOG(ERROR) << __func__ << " Invalid params"; - valid_index = false; - } else { - indices[0]= data[1]; - valid_index = false; - for (i=0,it = CallStatelist.begin(); it != CallStatelist.end(); it++, i++) { - tCCS_CALL_STATE obj = it->second; - if (obj.index == indices[0] && - (obj.state == CCS_STATE_INCOMING || obj.state == CCS_STATE_ACTIVE)) { - LOG(INFO) << __func__ << " call index match: " << indices[0]; - valid_index = true; - break; - } - } - } - if (valid_index == true) { - cc_instance->CallControlPointChange(CallControllerOps.operation, indices, - DEFAULT_INDICIES_COUNT, NULL, - device->peer_bda); - - } else { - LOG(INFO) << " CALL_LOCAL_HOLD ignored as there is no valid Index"; - cc_instance->CallControlResponse(CallControllerOps.operation, - CCS_DEFAULT_INDEX_VAL, - CCS_INVALID_INDEX, peer_bda); - } - break; - } - case CALL_LOCAL_RETRIEVE: { - if (len != 2) { - LOG(ERROR) << __func__ << " Invalid params"; - valid_index = false; - } else { - indices[0]= data[1]; - valid_index = false; - for (i=0,it = CallStatelist.begin(); it != CallStatelist.end(); it++, i++) { - tCCS_CALL_STATE obj = it->second; - if (obj.index == indices[0] && (obj.state == CCS_STATE_LOCAL_HELD )) { - LOG(INFO) << __func__ << " call index match: " << indices[0]; - valid_index = true; - break; - } - } - } - if (valid_index == true) { - cc_instance->CallControlPointChange( CallControllerOps.operation, indices, - DEFAULT_INDICIES_COUNT, NULL, - device->peer_bda); - - } else { - LOG(INFO) << " CALL_LOCAL_RETRIEVE ignored as there is no valid Index"; - cc_instance->CallControlResponse(CallControllerOps.operation, - CCS_DEFAULT_INDEX_VAL, - CCS_INVALID_INDEX, peer_bda); - } - break; - } - case CALL_ORIGINATE: { - LOG(INFO) << __func__ << " CALL_ORIGINATE match:"; - memset(URI, '\0', sizeof(char)*MAX_URI_SIZE); - strlcpy(URI, (char*)&data[1], len); - LOG(INFO) << __func__ << " ORIGINATE: " << URI; - if (IsValidOriginateUri(URI)) { - cc_instance->CallControlPointChange(CallControllerOps.operation, /*unused*/0, - /*count*/0, URI, device->peer_bda); - } else { - cc_instance->CallControlResponse(CallControllerOps.operation, - CCS_DEFAULT_INDEX_VAL, - CCS_INVALID_OUTGOING_URI, peer_bda); - } - break; - } - case CALL_JOIN: { - int count = len-1; - uint8_t *start_of_indicies = &(data[1]); - uint8_t indices[MAX_CCS_CONNECTION]; - valid_index = true; - bool atleastOneHeldCall = false; - for (int i=0; i::iterator j = CallStatelist.find(indices[i]); - if (j == CallStatelist.end()) { - valid_index = false; - break; - } else if (j->second.state == CCS_STATE_LOCAL_HELD) { - atleastOneHeldCall = true; - } - } - if (CallStatelist.size() < 2 || atleastOneHeldCall == false) { - LOG(INFO) << __func__ << " Join is not valid: "; - valid_index = false; - } - if (count > 1 && valid_index == true) { - cc_instance->CallControlPointChange(CallControllerOps.operation, - indices, count, - NULL, device->peer_bda); - } else { - LOG(INFO) << __func__ << " no valid indices found for JOIN operation "; - cc_instance->CallControlResponse(CallControllerOps.operation, - CCS_DEFAULT_INDEX_VAL, - CCS_INVALID_INDEX, peer_bda); - } - break; - } - default: - LOG(ERROR) << __func__ << " Unhandled Event: " << CallControllerOps.operation; - cc_instance->CallControlResponse(CallControllerOps.operation, - CCS_DEFAULT_INDEX_VAL, - CCS_OPCODE_NOT_SUPPORTED, peer_bda); - } - } else if (handle == ccsControlServiceInfo.bearer_signal_strength_report_interval_handle) { - if (len != 1) { - LOG(ERROR) << " Invalid input for SSR interval"; - return BT_STATUS_SUCCESS; - } - LOG(INFO) << __func__ << " signal strength repo Interval: " << data[0]; - BearerProviderInfo.signal_report_interval = data[0]; - cc_instance->remoteDevices.UpdateSSReportingInterval(device->peer_bda, BearerProviderInfo.signal_report_interval); - } - break; - } - - case CCS_CONGESTION_UPDATE: { - LOG(INFO) << __func__ << ": device CCS_CONGESTION_UPDATE update: " << event; - CcpCongestionUpdate(p_data); - break; - } - - case CCS_READ_RSP: - case CCS_DESCRIPTOR_READ_RSP: - case CCS_DESCRIPTOR_WRITE_RSP: - case CCS_CONNECTION_UPDATE: - case CCS_PHY_UPDATE: - case CCS_CONNECTION: - LOG(INFO) << __func__ << " calling device state " << device->state; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data); - break; - - default: - LOG(INFO) << __func__ << " event is not in list"; - break; - } - - return BT_STATUS_SUCCESS; - -} - -void CcpCongestionUpdate(tcc_resp_t* p_data) { - p_data->remoteDevice->congested = p_data->oper.CongestionOp.congested; - LOG(INFO) << __func__ << ": conn_id: " << p_data->remoteDevice->conn_id - << ", congested: " << p_data->remoteDevice->congested; - - GattsOpsQueue::CongestionCallback(p_data->remoteDevice->conn_id, - p_data->remoteDevice->congested); -} diff --git a/le_audio/system/bt/bta/csip/bta_csip_act.cc b/le_audio/system/bt/bta/csip/bta_csip_act.cc deleted file mode 100644 index 7bec391eb1b093f7ec40fe1ad853ba08d4fcbb20..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/csip/bta_csip_act.cc +++ /dev/null @@ -1,1685 +0,0 @@ -/****************************************************************************** - -Copyright (c) 2020, The Linux Foundation. All rights reserved. -* -*****************************************************************************/ - -/****************************************************************************** -* - -* Copyright 2009-2013 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 the CSIP Client action functions. - * - ******************************************************************************/ - -#include -#include -#include - -#include -#include -#include -#include - -#include "bta_csip_int.h" -#include "bta_csip_api.h" -#include "bta_gatt_api.h" -#include "bta_gatt_queue.h" -#include "btm_api.h" -#include "btm_ble_api.h" -#include "osi/include/osi.h" -#include "osi/include/properties.h" -#include "bta_dm_api.h" -#include "bta_dm_adv_audio.h" - -/* CSIS Service UUID */ -Uuid CSIS_SERVICE_UUID = Uuid::FromString("1846"); -/* CSIS Characteristic UUID's */ -Uuid CSIS_SERVICE_SIRK_UUID = Uuid::FromString("2B84"); -Uuid CSIS_SERVICE_SIZE_UUID = Uuid::FromString("2B85"); -Uuid CSIS_SERVICE_LOCK_UUID = Uuid::FromString("2B86"); -Uuid CSIS_SERVICE_RANK_UUID = Uuid::FromString("2B87"); - -/******************************************************************************* - * - * Function bta_csip_api_enable - * - * Description This function completes tasks to be done on BT ON - * - * Parameters: p_cback - callbacks from btif layer - * - ******************************************************************************/ -void bta_csip_api_enable(tBTA_CSIP_CBACK *p_cback) { - APPL_TRACE_DEBUG("%s", __func__); - - bta_csip_cb = tBTA_CSIP_CB(); - bta_csip_cb.p_cback = p_cback; - - // register with GATT CLient interface - bta_csip_gattc_register(); - - bta_csip_load_coordinated_sets_from_storage(); -} - -/******************************************************************************* - * - * Function bta_csip_api_disable - * - * Description This function completes tasks to be done on BT OFF - * - * Parameters: None - * - ******************************************************************************/ -void bta_csip_api_disable() { - std::vector &dev_cb = bta_csip_cb.dev_cb; - - /* close all active GATT Connections */ - for (tBTA_CSIP_DEV_CB& p_cb: dev_cb) { - if (p_cb.state == BTA_CSIP_CONN_ST) { - BTA_GATTC_Close(p_cb.conn_id); - } - } - - /* Deregister GATT Interface */ - BTA_GATTC_AppDeregister(bta_csip_cb.gatt_if); -} - -/******************************************************************************* - * - * Function bta_csip_app_register - * - * Description API used to register App/Module for CSIP callbacks. - * operation - * - * Parameters: app_uuid - Application UUID. - * p_cback - Application callbacks. - * cb - callback after registration. - ******************************************************************************/ -void bta_csip_app_register (const Uuid& app_uuid, tBTA_CSIP_CBACK* p_cback, - BtaCsipAppRegisteredCb cb) { - uint8_t i; - tBTA_CSIP_STATUS status = BTA_CSIP_FAILURE; - - for (i = 0; i < BTA_CSIP_MAX_SUPPORTED_APPS; i++) { - if (!bta_csip_cb.app_rcb[i].in_use) { - bta_csip_cb.app_rcb[i].in_use = true; - bta_csip_cb.app_rcb[i].app_id = i; - bta_csip_cb.app_rcb[i].p_cback = p_cback; - status = BTA_CSIP_SUCCESS; - break; - } - } - - if (status == BTA_CSIP_SUCCESS) { - LOG(INFO) << "CSIP App Registered Succesfully. App ID: " << +i; - } else { - LOG(ERROR) << "CSIP App Registration failed. App Limit reached"; - } - - // Give callback to registering App/Module - if (!cb.is_null()) cb.Run(status, i); -} - -/******************************************************************************* - * - * Function bta_csip_app_unregister - * - * Description API used to unregister App/Module for CSIP callbacks. - * - * Parameters: app_id: ID of the application to be unregistered. - * - ******************************************************************************/ -void bta_csip_app_unregister(uint8_t app_id) { - if (app_id >= BTA_CSIP_MAX_SUPPORTED_APPS) { - LOG(ERROR) << __func__ << " Invalid App ID: " << +app_id; - return; - } - - bta_csip_cb.app_rcb[app_id].in_use = false; - bta_csip_cb.app_rcb[app_id].p_cback = NULL; -} - -/******************************************************************************* - * - * Function bta_csip_gattc_callback - * - * Description This is GATT client callback function used in BTA CSIP. - * - * Parameters: event - received from GATT - * p_data - data associated with the event - * - ******************************************************************************/ -static void bta_csip_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) { - tBTA_CSIP_DEV_CB* p_dev_cb; - - APPL_TRACE_DEBUG("bta_csip_gattc_callback event = %d", event); - - if (p_data == NULL) return; - - switch (event) { - case BTA_GATTC_OPEN_EVT: - p_dev_cb = bta_csip_find_dev_cb_by_bda(p_data->open.remote_bda); - if (p_dev_cb) { - bta_csip_sm_execute(p_dev_cb, BTA_CSIP_GATT_OPEN_EVT, - (tBTA_CSIP_REQ_DATA*)&p_data->open); - } - break; - - case BTA_GATTC_CLOSE_EVT: - p_dev_cb = bta_csip_find_dev_cb_by_bda(p_data->close.remote_bda); - if (p_dev_cb) { - APPL_TRACE_DEBUG("BTA_GATTC_CLOSE_EVT state = %d", p_dev_cb->state); - bta_csip_sm_execute(p_dev_cb, BTA_CSIP_GATT_CLOSE_EVT, - (tBTA_CSIP_REQ_DATA*)&p_data->close); - } - break; - - case BTA_GATTC_SEARCH_CMPL_EVT: { - tBTA_GATTC_SEARCH_CMPL* p_srch_data = &p_data->search_cmpl; - tBTA_CSIP_DISC_SET disc_params = {.conn_id = p_srch_data->conn_id, - .status = p_srch_data->status - }; - p_dev_cb = bta_csip_get_dev_cb_by_cid(p_srch_data->conn_id); - if (p_dev_cb) { - disc_params.addr = p_dev_cb->addr; - p_dev_cb->is_disc_external = true; - } - bta_csip_gatt_disc_cmpl_act(&disc_params); - bta_csip_sm_execute(p_dev_cb, BTA_CSIP_OPEN_CMPL_EVT, NULL); - } - break; - - case BTA_GATTC_NOTIF_EVT: { - bta_csip_handle_notification(&p_data->notify); - } - break; - - default: - break; - } -} - -/******************************************************************************* - * - * Function bta_csip_gattc_register - * - * Description API used to register GATT interface for CSIP operations. - * - * Parameters: None - * - ******************************************************************************/ -void bta_csip_gattc_register() { - APPL_TRACE_DEBUG("%s", __func__); - - BTA_GATTC_AppRegister(bta_csip_gattc_callback, - base::Bind([](uint8_t client_id, uint8_t status) { - tBTA_CSIP_STATUS csip_status = BTA_CSIP_FAILURE; - if (status == GATT_SUCCESS) { - bta_csip_cb.gatt_if = client_id; - csip_status = BTA_CSIP_SUCCESS; - } else { - bta_csip_cb.gatt_if = BTA_GATTS_INVALID_IF; - } - - /* BTA_GATTC_AppRegister is done */ - if (bta_csip_cb.p_cback) { - LOG(INFO) << "CSIP GATT IF : " - << +bta_csip_cb.gatt_if; - } - }), true); -} - -/******************************************************************************* - * - * Function bta_csip_process_set_lock_act - * - * Description This function processes lock/unlock request. - * - * Parameters: lock_param: params used in LOCK/UNLOCK request. - * - ******************************************************************************/ -void bta_csip_process_set_lock_act(tBTA_SET_LOCK_PARAMS lock_param) { - LOG(INFO) << __func__ << ": App ID = " << +lock_param.app_id - << ", Set ID = " << +lock_param.set_id - << ", Value = " << +lock_param.lock_value; - - tBTA_CSET_CB* cset_cb = bta_csip_get_cset_cb_by_id (lock_param.set_id); - if (!cset_cb || !bta_csip_is_valid_lock_request(&lock_param)) { - tBTA_LOCK_STATUS_CHANGED res = {.app_id = lock_param.app_id, - .set_id = lock_param.set_id, - .status = INVALID_REQUEST_PARAMS}; - bta_csip_send_lock_req_cmpl_cb(res); - return; - } - - // Add request in the queue if one is already in progress for this set - if (cset_cb->request_in_progress) { - cset_cb->lock_req_queue.push(lock_param); - LOG(INFO) << __func__ << " pending lock requests in queue for Set:" - << +lock_param.set_id - << " Pending Requests = " << +(int)cset_cb->lock_req_queue.size(); - return; - } - - bta_csip_form_lock_request(lock_param, cset_cb); -} - -/******************************************************************************* - * - * Function bta_csip_process_set_lock_act - * - * Description This function forms request (LOCK/UNLOCK and order of the - * set members). - * - * Parameters: lock_param: params used in LOCK/UNLOCK request. - * cset_cb: current set control block. - * - ******************************************************************************/ -void bta_csip_form_lock_request(tBTA_SET_LOCK_PARAMS lock_param, - tBTA_CSET_CB* cset_cb) { - cset_cb->request_in_progress = true; - - std::vector ordered_members; - - if (lock_param.lock_value == LOCK_VALUE) { - ordered_members = bta_csip_arrange_set_members_by_order(cset_cb->set_id, - lock_param.members_addr, true); - } else { - ordered_members = bta_csip_arrange_set_members_by_order(cset_cb->set_id, - lock_param.members_addr, false); - } - - //debug log - for (int i = 0; i < (int)ordered_members.size(); i++) { - APPL_TRACE_DEBUG("%s: Member %d = %s", __func__, (i+1), - ordered_members[i].ToString().c_str()); - } - - // update current request in CB - cset_cb->cur_lock_req = {lock_param.app_id, lock_param.set_id, lock_param.lock_value, - 0, ordered_members}; - - // update current response in CB - cset_cb->cur_lock_res = {}; - cset_cb->cur_lock_res.app_id = lock_param.app_id; - cset_cb->cur_lock_res.set_id = lock_param.set_id; - cset_cb->cur_lock_res.value = UNLOCK_VALUE; - - /* LOCK Request */ - if (cset_cb->cur_lock_req.value == LOCK_VALUE) { - cset_cb->cur_lock_res.status = ALL_LOCKS_ACQUIRED; - /* check if lock request for this set was denied earlier */ - if (bta_csip_validate_req_for_denied_sm(cset_cb)) { - bta_csip_get_next_lock_request(cset_cb); - - /* proceed with request otherwise*/ - } else { - bta_csip_send_lock_req_act(cset_cb); - } - /* UNLOCK Request*/ - } else { - bta_csip_send_unlock_req_act(cset_cb); - } -} - -/******************************************************************************* - * - * Function bta_csip_validate_req_for_denied_sm - * - * Description This function validates request if received for denied set - * member - * - * Parameters: cset_cb: current set control block. - * - ******************************************************************************/ -bool bta_csip_validate_req_for_denied_sm (tBTA_CSET_CB* cset_cb) { - bool is_denied = false; - tBTA_LOCK_REQUEST& lock_req = cset_cb->cur_lock_req; - - for (RawAddress& addr: lock_req.members_addr) { - tBTA_CSIP_DEV_CB* p_cb = bta_csip_find_dev_cb_by_bda(addr); - if (!p_cb) { - APPL_TRACE_ERROR("%s: Device CB not found for %s", __func__, - addr.ToString().c_str()); - continue; - } - - tBTA_CSIS_SRVC_INFO* srvc = bta_csip_get_csis_instance(p_cb, lock_req.set_id); - if (!srvc) { - APPL_TRACE_ERROR("%s: CSIS instance not found for %s", __func__, - addr.ToString().c_str()); - continue; - } - - if (!srvc->denied_applist.empty()) { - is_denied = true; - // add this app_id in the denied_app_list - srvc->denied_applist.push_back(lock_req.app_id); - cset_cb->cur_lock_res.status = LOCK_DENIED; - cset_cb->cur_lock_res.addr.push_back(addr); - } - } - - if (is_denied) { - bta_csip_send_lock_req_cmpl_cb(cset_cb->cur_lock_res); - } - - return is_denied; -} - -/******************************************************************************* - * - * Function bta_csip_lock_release_by_denial_cb - * - * Description This callback function is called when set member is unlocked - * after unlock request is sent post lock denial. - * - * Parameters: GATT operation callback params. - * - ******************************************************************************/ -void bta_csip_lock_release_by_denial_cb(uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, void* data) { - tBTA_CSET_CB* cset_cb = (tBTA_CSET_CB *)data; - tBTA_CSIP_DEV_CB* dev_cb = cset_cb->cur_dev_cb; - tBTA_CSIS_SRVC_INFO* srvc = - bta_csip_get_csis_instance(cset_cb->cur_dev_cb, cset_cb->cur_lock_req.set_id); - - LOG(INFO) << __func__ << " Released lock for device: " << dev_cb->addr - << ", Set ID: " << +cset_cb->set_id; - - if (srvc && status == GATT_SUCCESS) { - srvc->lock = UNLOCK_VALUE; - // remove app id from applist - srvc->lock_applist.erase(std::remove(srvc->lock_applist.begin(), srvc->lock_applist.end(), - cset_cb->cur_lock_req.app_id), srvc->lock_applist.end()); - } - - // release next set member with lower rank - bta_csip_handle_lock_denial(cset_cb); -} - -/******************************************************************************* - * - * Function bta_csip_handle_lock_denial - * - * Description This function is called when lock has been denied by one of - * the set members. - * - * Parameters: cset_cb: current set control block. - * - ******************************************************************************/ -void bta_csip_handle_lock_denial(tBTA_CSET_CB* cset_cb) { - // start lock release procedure for acquired locks - int8_t cur_idx = cset_cb->cur_lock_req.cur_idx - 1; - cset_cb->cur_lock_req.cur_idx--; - - if (cur_idx >= 0) { - RawAddress bd_addr = cset_cb->cur_lock_req.members_addr[cur_idx]; - cset_cb->cur_dev_cb = bta_csip_find_dev_cb_by_bda(bd_addr); - tBTA_CSIS_SRVC_INFO* srvc = - bta_csip_get_csis_instance(cset_cb->cur_dev_cb, cset_cb->cur_lock_req.set_id); - - // check if locked by other app - if (!cset_cb->cur_dev_cb || !srvc || - bta_csip_is_locked_by_other_apps(srvc, cset_cb->cur_lock_req.app_id)) { - LOG(INFO) << "Invalid device or service CB or" - << " other apps have locked this set member(" << bd_addr << "). Skip."; - bta_csip_handle_lock_denial(cset_cb); - return; - } - - // Lock value in vector format (one uint8_t size element with ) - std::vector unlock_value(1, UNLOCK_VALUE); - BtaGattQueue::WriteCharacteristic(cset_cb->cur_dev_cb->conn_id, - srvc->lock_handle, unlock_value, GATT_WRITE, bta_csip_lock_release_by_denial_cb, cset_cb); - - } else { - bta_csip_get_next_lock_request(cset_cb); - } -} - -/******************************************************************************* - * - * Function bta_csip_lock_req_cb - * - * Description This callback function is called when set member is locked - * by remote device after LOCK Request - * - * Parameters: GATT operation callback params. - * - ******************************************************************************/ -void bta_csip_lock_req_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle, - void* data) { - LOG(INFO) << __func__ << " status = " << +status; - tBTA_CSET_CB* cset_cb = (tBTA_CSET_CB *)data; - tBTA_CSIP_DEV_CB* dev_cb = bta_csip_get_dev_cb_by_cid(conn_id); - tBTA_CSIS_SRVC_INFO* srvc = - bta_csip_get_csis_instance(dev_cb, cset_cb->set_id); - - /* Device control block or corresponding CSIS service instance not found */ - if (!dev_cb || !srvc) { - APPL_TRACE_ERROR("%s: Device CB not found for conn_id = %d", __func__, conn_id); - cset_cb->cur_lock_req.cur_idx++; - alarm_cancel(cset_cb->unresp_timer); - bta_csip_send_lock_req_act(cset_cb); - return; - } - - /*check if this response is received from unresponsive set member */ - if (dev_cb->unresponsive) { - LOG(INFO) << __func__ << " unresponsive remote: " << dev_cb->addr; - bta_csip_handle_unresponsive_sm_res(srvc, status); - dev_cb->unresponsive = false; - return; - } - // cancel alarm (used for unresponsive set member) - alarm_cancel(cset_cb->unresp_timer); - - if (status == CSIP_LOCK_DENIED) { - LOG(INFO) << __func__ << " Locked Denied by " << dev_cb->addr; - srvc->lock = UNLOCK_VALUE; - cset_cb->cur_lock_res.value = UNLOCK_VALUE; - cset_cb->cur_lock_res.status = LOCK_DENIED; - - // add member to the response list for which lock is denied and clear others - cset_cb->cur_lock_res.addr.clear(); - cset_cb->cur_lock_res.addr.push_back(dev_cb->addr); - - // add app_id in the denied applist - srvc->denied_applist.push_back(cset_cb->cur_lock_req.app_id); - // Give callback to upper layer that lock is denied - bta_csip_send_lock_req_cmpl_cb(cset_cb->cur_lock_res); - // release all the acquired locks till now - bta_csip_handle_lock_denial(cset_cb); - - /* PTS: Remote responding with invalid value */ - } else if (status == CSIP_INVALID_LOCK_VALUE) { - LOG(ERROR) << __func__ << " remote " << dev_cb->addr - << " responded with INVALID Value"; - /* for PTS to ensure set coordinator is working fine */ - BtaGattQueue::ReadCharacteristic(cset_cb->cur_dev_cb->conn_id, - srvc->lock_handle, NULL, NULL); - - /* Stop locking remaining set members and inform requesting app */ - bta_csip_send_lock_req_cmpl_cb(cset_cb->cur_lock_res); - /* Process next lock request from pending queue */ - bta_csip_get_next_lock_request(cset_cb); - } else { - if (status == GATT_SUCCESS || status == CSIP_LOCK_ALREADY_GRANTED) { - LOG(INFO) << __func__ << " successfully locked " << dev_cb->addr; - cset_cb->cur_lock_res.addr.push_back(dev_cb->addr); - cset_cb->cur_lock_res.value = LOCK_VALUE; - srvc->lock = LOCK_VALUE; - // add app_id against this device entry - srvc->lock_applist.push_back(cset_cb->cur_lock_req.app_id); - } - - //proceed with next set member - cset_cb->cur_lock_req.cur_idx++; - bta_csip_send_lock_req_act(cset_cb); - } -} - -/******************************************************************************* - * - * Function bta_csip_send_lock_req_act - * - * Description This function is is used to send LOCK request to set member. - * It validates if it is required to send lock request based on - * connection state and current lock value. - * - * Parameters: cset_cb: current set control block. - * - ******************************************************************************/ -void bta_csip_send_lock_req_act(tBTA_CSET_CB* cset_cb) { - RawAddress bd_addr; - uint8_t cur_index = cset_cb->cur_lock_req.cur_idx; - - if (cur_index == (uint8_t)cset_cb->cur_lock_req.members_addr.size()) { - LOG(INFO) << __func__ << " lock operation completed for all set members"; - bta_csip_send_lock_req_cmpl_cb(cset_cb->cur_lock_res); - bta_csip_get_next_lock_request(cset_cb); - return; - } - - bd_addr = cset_cb->cur_lock_req.members_addr[cur_index]; - - // get device control block and corresponding csis service details - cset_cb->cur_dev_cb = bta_csip_find_dev_cb_by_bda(bd_addr); - tBTA_CSIS_SRVC_INFO* srvc = - bta_csip_get_csis_instance(cset_cb->cur_dev_cb, cset_cb->cur_lock_req.set_id); - - // Skip device if it is not in connected state - if (!cset_cb->cur_dev_cb || !srvc || - cset_cb->cur_dev_cb->state != BTA_CSIP_CONN_ST) { - LOG(INFO) << __func__ << ": Set Member (" << bd_addr.ToString() - << ") is not connected. Skip this Set member"; - - cset_cb->cur_lock_req.cur_idx++; - cset_cb->cur_lock_res.status = SOME_LOCKS_ACQUIRED_REASON_DISC; - bta_csip_send_lock_req_act(cset_cb); - - // check if already locked (skip sending write request) - } else if (srvc->lock == LOCK_VALUE) { - LOG(INFO) << __func__ << ": Set Member (" << cset_cb->cur_dev_cb->addr - << ") is already locked. Skip this Set member"; - cset_cb->cur_lock_res.value = LOCK_VALUE; - // add element in the list - cset_cb->cur_lock_res.addr.push_back(bd_addr); - // add appid in the list if locked by different app - if (!bta_csip_is_member_locked_by_app(cset_cb->cur_lock_req.app_id, srvc)) { - srvc->lock_applist.push_back(cset_cb->cur_lock_req.app_id); - } - cset_cb->cur_lock_req.cur_idx++; - // process next set member - bta_csip_send_lock_req_act(cset_cb); - - // send the lock request - } else { - // Lock value in vector format (one uint8_t size element with ) - LOG(INFO) << __func__ << " Sending Lock Request to "<< cset_cb->cur_dev_cb->addr - << " Conn Id: " << +cset_cb->cur_dev_cb->conn_id; - std::vector lock_value = {2}; - BtaGattQueue::WriteCharacteristic(cset_cb->cur_dev_cb->conn_id, - srvc->lock_handle, lock_value, GATT_WRITE, bta_csip_lock_req_cb, cset_cb); - - // Start set member request timeout alarm - cset_cb->unresp_timer = alarm_new("csip_unresp_sm_timer"); - alarm_set_on_mloop(cset_cb->unresp_timer, cset_cb->set_member_tout, - bta_csip_set_member_lock_timeout, cset_cb); - } -} - -/******************************************************************************* - * - * Function bta_csip_unlock_req_cb - * - * Description This callback function is called when set member is unlocked - * by remote device after UNLOCK Request - * - * Parameters: GATT operation callback params. - * - ******************************************************************************/ -void bta_csip_unlock_req_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle, - void* data) { - LOG(INFO) << __func__ << " status = " << +status; - tBTA_CSET_CB* cset_cb = (tBTA_CSET_CB *)data; - tBTA_CSIP_DEV_CB* dev_cb = bta_csip_get_dev_cb_by_cid(conn_id); - tBTA_CSIS_SRVC_INFO* srvc = - bta_csip_get_csis_instance(dev_cb, cset_cb->cur_lock_req.set_id); - - /* Device control block or corresponding CSIS service instance not found */ - if (!dev_cb || !srvc) { - APPL_TRACE_ERROR("%s: Device CB not found for conn_id = %d", __func__, conn_id); - cset_cb->cur_lock_req.cur_idx++; - alarm_cancel(cset_cb->unresp_timer); - bta_csip_send_unlock_req_act(cset_cb); - return; - } - - /*check if this response is received from unresponsive set member */ - if (dev_cb->unresponsive) { - LOG(INFO) << __func__ << " unresponsive remote: " << dev_cb->addr; - srvc->lock = UNLOCK_VALUE; - srvc->unrsp_applist.clear(); - dev_cb->unresponsive = false; - return; - } - - // cancel alarm (used for unresponsive set member) - alarm_cancel(cset_cb->unresp_timer); - - /* PTS Test Case: read any characteristic */ - if (status == CSIP_LOCK_RELEASE_NOT_ALLOWED || - status == CSIP_INVALID_LOCK_VALUE) { - /* for PTS to ensure set coordinator is working fine */ - BtaGattQueue::ReadCharacteristic(cset_cb->cur_dev_cb->conn_id, - srvc->lock_handle, NULL, NULL); - - /* Stop unlocking remaining set members and inform requesting app */ - cset_cb->cur_lock_res.status = status; - bta_csip_send_lock_req_cmpl_cb(cset_cb->cur_lock_res); - /* Process next lock request from pending queue */ - bta_csip_get_next_lock_request(cset_cb); - } else { - if (status == GATT_SUCCESS) { - srvc->lock = UNLOCK_VALUE; - // remove app id from applist - srvc->lock_applist.erase(std::remove(srvc->lock_applist.begin(), - srvc->lock_applist.end(), cset_cb->cur_lock_req.app_id), - srvc->lock_applist.end()); - cset_cb->cur_lock_res.addr.push_back(dev_cb->addr); - } - //proceed with next set member - cset_cb->cur_lock_req.cur_idx++; - bta_csip_send_unlock_req_act(cset_cb); - } -} - -/******************************************************************************* - * - * Function bta_csip_send_unlock_req_act - * - * Description This function is is used to send UNLOCK request to set member. - * It validates if it is required to send unlock request based on - * connection state and current lock value. - * - * Parameters: cset_cb: current set control block. - * - ******************************************************************************/ -void bta_csip_send_unlock_req_act(tBTA_CSET_CB* cset_cb) { - RawAddress bd_addr; - uint8_t cur_index = cset_cb->cur_lock_req.cur_idx; - - if (cur_index == (uint8_t)cset_cb->cur_lock_req.members_addr.size()) { - cset_cb->request_in_progress = false; - bta_csip_send_lock_req_cmpl_cb(cset_cb->cur_lock_res); - bta_csip_get_next_lock_request(cset_cb); - LOG(INFO) << __func__ << " Request completed for all set members"; - return; - } - - bd_addr = cset_cb->cur_lock_req.members_addr[cur_index]; - - LOG(INFO) << __func__ << ": Set Member address: " << bd_addr.ToString(); - - // get device control block and corresponding csis service details - cset_cb->cur_dev_cb = bta_csip_find_dev_cb_by_bda(bd_addr); - tBTA_CSIS_SRVC_INFO* srvc = - bta_csip_get_csis_instance(cset_cb->cur_dev_cb, cset_cb->cur_lock_req.set_id); - - /* Device control block or corresponding CSIS service instance not found */ - if (!cset_cb->cur_dev_cb || !srvc) { - APPL_TRACE_ERROR("%s: Device CB not found for %s", __func__, - bd_addr.ToString().c_str()); - cset_cb->cur_lock_req.cur_idx++; - bta_csip_send_unlock_req_act(cset_cb); - return; - } - - /* Set member is not locked by requesting app */ - if (!bta_csip_is_member_locked_by_app(cset_cb->cur_lock_req.app_id, srvc)) { - LOG(INFO) << __func__ << " App "<< +cset_cb->cur_lock_req.app_id - << "has not locked this set member (" << srvc->bd_addr - << "). Skip this set member"; - cset_cb->cur_lock_req.cur_idx++; - bta_csip_send_unlock_req_act(cset_cb); - return; - } - - // Skip device if it is not in connected state - if (cset_cb->cur_dev_cb->state != BTA_CSIP_CONN_ST) { - LOG(INFO) << __func__ << ": Set Member (" << bd_addr.ToString() - << ") is not connected. Skip this Set member"; - - cset_cb->cur_lock_req.cur_idx++; - // remove app id from applist - srvc->lock_applist.erase(std::remove(srvc->lock_applist.begin(), srvc->lock_applist.end(), - cset_cb->cur_lock_req.app_id), srvc->lock_applist.end()); - bta_csip_send_unlock_req_act(cset_cb); - - // check if already unlocked or locked by multiple apps (skip sending write request) - } else if (srvc->lock == UNLOCK_VALUE || - bta_csip_is_locked_by_other_apps(srvc, cset_cb->cur_lock_req.app_id)) { - LOG(INFO) << __func__ << ": Set Member (" << bd_addr.ToString() - << ") is already unlocked or locked by other app. Skip this Set member"; - // remove app id from applist - srvc->lock_applist.erase(std::remove(srvc->lock_applist.begin(), srvc->lock_applist.end(), - cset_cb->cur_lock_req.app_id), srvc->lock_applist.end()); - cset_cb->cur_lock_req.cur_idx++; - cset_cb->cur_lock_res.addr.push_back(cset_cb->cur_dev_cb->addr); - // process next set member - bta_csip_send_unlock_req_act(cset_cb); - - // send the unlock request - } else { - // Unlock value in vector format (one uint8_t size element with unlock value) - std::vector lock_value(1, UNLOCK_VALUE); - BtaGattQueue::WriteCharacteristic(cset_cb->cur_dev_cb->conn_id, - srvc->lock_handle, lock_value, GATT_WRITE, bta_csip_unlock_req_cb, cset_cb); - - // Start set member request timeout alarm - cset_cb->unresp_timer = alarm_new("csip_unresp_sm_timer"); - alarm_set_on_mloop(cset_cb->unresp_timer, cset_cb->set_member_tout, - bta_csip_set_member_lock_timeout, cset_cb); - } -} - -/******************************************************************************* - * - * Function bta_csip_set_member_lock_timeout - * - * Description This API is called when Set Member has not responded within - * required set member lock timeout. - * - * Returns None - * - ******************************************************************************/ -void bta_csip_set_member_lock_timeout(void* p_data) { - tBTA_CSET_CB* cset_cb = (tBTA_CSET_CB *)p_data; - tBTA_CSIP_DEV_CB* dev_cb = cset_cb->cur_dev_cb; - - APPL_TRACE_DEBUG("%s", __func__); - // Device not found or disconnected - if (!dev_cb || dev_cb->state != BTA_CSIP_CONN_ST) { - LOG(ERROR) << __func__ << " device disconnected."; - cset_cb->cur_lock_res.status = SOME_LOCKS_ACQUIRED_REASON_DISC; - cset_cb->cur_lock_req.cur_idx++; - bta_csip_send_lock_req_act(cset_cb); - return; - } - - tBTA_CSIS_SRVC_INFO* srvc = - bta_csip_get_csis_instance(cset_cb->cur_dev_cb, cset_cb->cur_lock_req.set_id); - - if (!srvc) { - APPL_TRACE_ERROR("%s: CSIS instance not found.", __func__); - return; - } - - dev_cb->unresponsive = true; - // add app_id in unresponsive set members app list - srvc->unrsp_applist.push_back(cset_cb->cur_lock_res.app_id); - - if (cset_cb->cur_lock_req.value == LOCK_VALUE) { - cset_cb->cur_lock_res.status = SOME_LOCKS_ACQUIRED_REASON_TIMEOUT; - APPL_TRACE_DEBUG("%s: Process next device in the lock request", __func__); - cset_cb->cur_lock_req.cur_idx++; - bta_csip_send_lock_req_act(cset_cb); - } else if (cset_cb->cur_lock_req.value == UNLOCK_VALUE) { - cset_cb->cur_lock_res.addr.push_back( - cset_cb->cur_lock_req.members_addr[cset_cb->cur_lock_req.cur_idx]); - cset_cb->cur_lock_req.cur_idx++; - bta_csip_send_unlock_req_act(cset_cb); - } -} - -/******************************************************************************* - * - * Function bta_csip_le_encrypt_cback - * - * Description link encryption complete callback. - * - * Returns None - * - ******************************************************************************/ -void bta_csip_le_encrypt_cback(const RawAddress* bd_addr, - UNUSED_ATTR tGATT_TRANSPORT transport, - UNUSED_ATTR void* p_ref_data, tBTM_STATUS result) { - APPL_TRACE_ERROR("%s: status = %d", __func__, result); - tBTA_CSIP_DEV_CB* p_cb = bta_csip_find_dev_cb_by_bda(*bd_addr); - - if (!p_cb) { - APPL_TRACE_ERROR("unexpected encryption callback, ignore"); - return; - } - - /* If encryption fails, disconnect the connection */ - if (result != BTM_SUCCESS) { - bta_csip_close_csip_conn(p_cb); - return; - } - - if (p_cb->state == BTA_CSIP_W4_SEC) { - bta_csip_sm_execute(p_cb, BTA_CSIP_ENC_CMPL_EVT, NULL); - } -} - -/******************************************************************************* - * - * Function bta_csip_open_act - * - * Description API Call to open CSIP Gatt Connection - * - * Returns None - * - ******************************************************************************/ -void bta_csip_api_open_act (tBTA_CSIP_DEV_CB* p_cb, tBTA_CSIP_REQ_DATA* p_data) { - APPL_TRACE_DEBUG("%s: Open GATT connection for CSIP", __func__); - - tBTA_CSIP_API_CONN* p_conn_req = (tBTA_CSIP_API_CONN *)&p_data->conn_param; - - if (!bta_csip_is_app_reg(p_conn_req->app_id)) { - LOG(ERROR) << __func__ << ": Request from Invalid/Unregistered App: " - << +p_conn_req->app_id; - if (p_cb && (uint8_t)p_cb->conn_applist.size() == 0) { - p_cb->state = BTA_CSIP_IDLE_ST; - } - // No need to send callback to invalid/unregistered app - return; - } - - if (btm_sec_is_a_bonded_dev(p_cb->addr) && !bta_csip_is_csis_supported(p_cb)) { - APPL_TRACE_DEBUG("%s: Remote (%s) doesnt contain any coordinated set", __func__, - p_cb->addr.ToString().c_str()); - bta_csip_send_conn_state_changed_cb(p_cb, p_conn_req->app_id, - BTA_CSIP_DISCONNECTED, BTA_CSIP_COORDINATED_SET_NOT_SUPPORTED); - return; - } - - if (!p_cb) { - LOG(ERROR) << __func__ << ": Insufficient resources. Max" - " supported Set members have reached "; - tBTA_CSIP_DEV_CB invalid_cb = { - .addr = p_data->conn_param.bd_addr - }; - bta_csip_send_conn_state_changed_cb(&invalid_cb, p_conn_req->app_id, - BTA_CSIP_DISCONNECTED, BTA_CSIP_CONN_ESTABLISHMENT_FAILED); - return; - } - - // check if connection state is already connected - if (p_cb->state == BTA_CSIP_CONN_ST) { - if (!bta_csip_is_app_from_applist(p_cb, p_conn_req->app_id)) { - bta_csip_add_app_to_applist(p_cb, p_conn_req->app_id); - } - bta_csip_send_conn_state_changed_cb(p_cb, p_conn_req->app_id, - BTA_CSIP_CONNECTED, BTA_CSIP_CONN_ESTABLISHED); - return; - - // other app has already started connection procedure - } else if (!bta_csip_is_app_from_applist(p_cb, p_conn_req->app_id) - && (uint8_t)p_cb->conn_applist.size() > 0 - && p_cb->state != BTA_CSIP_IDLE_ST) { - LOG(INFO) << __func__ << ": Other app is establishing CSIP Connection." - << " Current connection state = " << +p_cb->state; - bta_csip_add_app_to_applist(p_cb, p_conn_req->app_id); - /* Note: Callback will given to all apps once connection procedure is completed */ - return; - } - - p_cb->addr = p_data->conn_param.bd_addr; - bta_csip_add_app_to_applist(p_cb, p_conn_req->app_id); - - BTA_GATTC_Open(bta_csip_cb.gatt_if, p_cb->addr, true, GATT_TRANSPORT_LE, - false); -} - -/******************************************************************************* - * - * Function bta_csip_api_close_act - * - * Description API Call to close CSIP Gatt Connection - * - * Returns None - * - ******************************************************************************/ -void bta_csip_api_close_act (tBTA_CSIP_DEV_CB* p_cb, tBTA_CSIP_REQ_DATA* p_data) { - if (!p_cb) { - LOG(ERROR) << __func__ << " Already Closed"; - return; - } - - tBTA_CSIP_API_CONN* p_req = (tBTA_CSIP_API_CONN *)&p_data->conn_param; - - LOG(INFO) << __func__ << " Disconnect Request from App: " << +p_req->app_id; - - if (!bta_csip_is_app_reg(p_req->app_id)) { - LOG(ERROR) << __func__ << ": Request from Invalid/Unregistered App: " - << +p_req->app_id; - // No need to send callback to invalid/unregistered app - return; - } else if (!bta_csip_is_app_from_applist(p_cb, p_req->app_id)) { - LOG(ERROR) << __func__ << " App (ID:"<< +p_req->app_id <<") has not connected"; - bta_csip_send_conn_state_changed_cb(p_cb, p_req->app_id, - BTA_CSIP_DISCONNECTED, BTA_CSIP_DISCONNECT_WITHOUT_CONNECT); - return; - } - - // Check if its last disconnecting app - if ((uint8_t)p_cb->conn_applist.size() > 1) { - bta_csip_remove_app_from_conn_list(p_cb, p_req->app_id); - bta_csip_send_conn_state_changed_cb(p_cb, p_req->app_id, - BTA_CSIP_DISCONNECTED, BTA_CSIP_APP_DISCONNECTED); - return; - } - - bta_csip_close_csip_conn(p_cb); -} - -/******************************************************************************* - * - * Function bta_csip_gatt_open_act - * - * Description Callback function when GATT Connection is created. - * - * Returns None - * - ******************************************************************************/ -void bta_csip_gatt_open_act (tBTA_CSIP_DEV_CB* p_cb, tBTA_CSIP_REQ_DATA* p_data) { - tBTA_GATTC_OPEN* open_param = &p_data->gatt_open_param; - LOG(INFO) << __func__ << " Remote = " << open_param->remote_bda - << " Status = " << open_param->status - << " conn_id = " << open_param->conn_id; - - if (open_param->status == GATT_SUCCESS) { - p_cb->in_use = true; - p_cb->conn_id = open_param->conn_id; - BtaGattQueue::Clean(p_cb->conn_id); - bta_csip_sm_execute(p_cb, BTA_CSIP_START_ENC_EVT, NULL); - } else { - /* open failure */ - bta_csip_sm_execute(p_cb, BTA_CSIP_OPEN_FAIL_EVT, p_data); - } -} - -/******************************************************************************* - * - * Function bta_csip_gatt_close_act - * - * Description Callback function when GATT Connection is closed. - * - * Returns None - * - ******************************************************************************/ -void bta_csip_gatt_close_act (tBTA_CSIP_DEV_CB* p_cb, tBTA_CSIP_REQ_DATA* p_data) { - tBTA_GATTC_OPEN* open_param = &p_data->gatt_open_param; - - // Give callback to all apps from connection applist - bta_csip_send_conn_state_changed_cb(p_cb, BTA_CSIP_DISCONNECTED, open_param->status); - - // Clear applist - p_cb->conn_applist.clear(); - - for (int i = 0; i < MAX_SUPPORTED_SETS_PER_DEVICE; i++) { - tBTA_CSIS_SRVC_INFO* srvc = &p_cb->csis_srvc[i]; - if (srvc->in_use) { - srvc->lock = UNLOCK_VALUE; - } - } - - p_cb->conn_id = 0; - p_cb->in_use = false; -} - -/******************************************************************************* - * - * Function bta_csip_gatt_open_fail_act - * - * Description Callback function when GATT Connection fails to be created. - * - * Returns None - * - ******************************************************************************/ -void bta_csip_gatt_open_fail_act (tBTA_CSIP_DEV_CB* p_cb, - tBTA_CSIP_REQ_DATA* p_data) { - LOG(ERROR) << __func__ << " Failed to open GATT Connection"; - - tBTA_GATTC_OPEN* open_param = &p_data->gatt_open_param; - - // Give callback to all apps from connection applist waiting for connection - bta_csip_send_conn_state_changed_cb(p_cb, BTA_CSIP_DISCONNECTED, open_param->status); - - // Clear applist - p_cb->conn_applist.clear(); - p_cb->in_use = false; -} - -/******************************************************************************* - * - * Function bta_csip_open_cmpl_act - * - * Description Tasks needed to be done when connection is established. - * - * Returns None - * - ******************************************************************************/ -void bta_csip_open_cmpl_act (tBTA_CSIP_DEV_CB* p_cb, tBTA_CSIP_REQ_DATA* p_data) { - APPL_TRACE_DEBUG("%s", __func__); - - if (!p_cb) { - LOG(ERROR) << __func__ << " Invalid device contrl block"; - return; - } - - // Give callback to all apps from connection applist waiting for connection - bta_csip_send_conn_state_changed_cb(p_cb, BTA_CSIP_CONNECTED, - BTA_CSIP_CONN_ESTABLISHED); - - /* Register for notification of required CSIS characteristic*/ - int i = 0; - for (i = 0; i < MAX_SUPPORTED_SETS_PER_DEVICE; i++) { - tBTA_CSIS_SRVC_INFO* srvc = &p_cb->csis_srvc[i]; - if (srvc->in_use) { - bta_csip_write_cccd(p_cb, srvc->lock_handle, srvc->lock_ccd_handle); - bta_csip_write_cccd(p_cb, srvc->size_handle, srvc->size_ccd_handle); - bta_csip_write_cccd(p_cb, srvc->sirk_handle, srvc->sirk_ccd_handle); - } - } - -} - -/******************************************************************************* - * - * Function bta_csip_start_sec_act - * - * Description Tasks needed to be done to check or establish CSIP required - * security. - * - * Returns None - * - ******************************************************************************/ -void bta_csip_start_sec_act (tBTA_CSIP_DEV_CB* p_cb, tBTA_CSIP_REQ_DATA* p_data) { - APPL_TRACE_DEBUG("%s", __func__); - - uint8_t sec_flag = 0; - - // Get security flags for the device - BTM_GetSecurityFlagsByTransport(p_cb->addr, &sec_flag, BT_TRANSPORT_LE); - - // link is already encrypted, send encryption complete callback to csip - if (sec_flag & BTM_SEC_FLAG_ENCRYPTED) { - LOG(INFO) << __func__ << " Already Encrypted"; - bta_csip_sm_execute(p_cb, BTA_CSIP_ENC_CMPL_EVT, NULL); - } - // device is bonded but link is not encrypted. Start encryption - else if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) { - sec_flag = BTM_BLE_SEC_ENCRYPT; - BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_csip_le_encrypt_cback, - NULL, sec_flag); - } - // unbonded device. Set MITM Encryption - else if (p_cb->sec_mask != BTA_SEC_NONE) { - sec_flag = BTM_BLE_SEC_ENCRYPT_MITM; - BTM_SetEncryption(p_cb->addr, BTA_TRANSPORT_LE, bta_csip_le_encrypt_cback, - NULL, sec_flag); - } - // link is already encrypted - else { - bta_csip_sm_execute(p_cb, BTA_CSIP_ENC_CMPL_EVT, NULL); - } -} - -/******************************************************************************* - * - * Function bta_csip_start_sec_act - * - * Description Tasks needed to be done to check or establish CSIP required - * security. - * - * Returns None - * - ******************************************************************************/ -void bta_csip_sec_cmpl_act (tBTA_CSIP_DEV_CB* p_cb, tBTA_CSIP_REQ_DATA* p_data) { - APPL_TRACE_DEBUG("%s p_cb->csis_srvc[0].in_use = %d, p_cb->csis_srvc[0].sirk_handle = %d", - __func__, p_cb->csis_srvc[0].in_use, p_cb->csis_srvc[0].sirk_handle); - - if (!p_cb->csis_srvc[0].in_use || !p_cb->csis_srvc[0].sirk_handle) { - /* Service discovery is triggered from this path when csip connection is opened - * from 3rd party application */ - LOG(INFO) << __func__ << "Service discovery is pending"; - Uuid pri_srvc = Uuid::From16Bit(UUID_SERVCLASS_CSIS); - BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, &pri_srvc); - } else { - LOG(INFO) << __func__ << "Service discovery is already completed"; - bta_csip_sm_execute(p_cb, BTA_CSIP_OPEN_CMPL_EVT, NULL); - } -} - -/******************************************************************************* - * - * Function bta_csip_close_csip_conn - * - * Description API to close CSIP Connection and remove device from background - * list. - * - * Returns None - * - ******************************************************************************/ -void bta_csip_close_csip_conn (tBTA_CSIP_DEV_CB* p_cb) { - LOG(INFO) << __func__; - if (p_cb->conn_id != GATT_INVALID_CONN_ID) { - // clear pending GATT Requests - BtaGattQueue::Clean(p_cb->conn_id); - p_cb->state = BTA_CSIP_DISCONNECTING_ST; - // Send Close to GATT Layer - if (p_cb->state == BTA_CSIP_CONN_ST || p_cb->conn_id) { - BTA_GATTC_Close(p_cb->conn_id); - } else { - BTA_GATTC_CancelOpen(bta_csip_cb.gatt_if, p_cb->addr, true); - tBTA_GATTC_OPEN open = {.status = GATT_SUCCESS}; - bta_csip_gatt_close_act(p_cb,(tBTA_CSIP_REQ_DATA *)&open); - } - } -} - -/******************************************************************************* - * - * Function bta_csip_handle_notification - * - * Description This function is called when notification is received on one - * of the characteristic registered for notification. - * - * Returns None - * - ******************************************************************************/ -void bta_csip_handle_notification(tBTA_GATTC_NOTIFY* ntf) { - if (!ntf->is_notify) return; - LOG(INFO) << __func__<< " Set Member: " << ntf->bda << ", handle: " << ntf->handle; - - tBTA_CSIP_DEV_CB* p_cb = bta_csip_find_dev_cb_by_bda(ntf->bda); - if (!p_cb) { - LOG(ERROR) << __func__ << " No CSIP GATT Connection for this device"; - return; - } - - const gatt::Characteristic* p_char = - BTA_GATTC_GetCharacteristic(p_cb->conn_id, ntf->handle); - if (p_char == NULL) { - APPL_TRACE_ERROR( - "%s: notification received for Unknown Characteristic, conn_id: " - "0x%04x, handle: 0x%04x", - __func__, p_cb->conn_id, ntf->handle); - return; - } - - if (p_char->uuid == CSIS_SERVICE_LOCK_UUID) { - bta_csip_handle_lock_value_notif(p_cb, ntf->handle, ntf->value[0]); - } else if (p_char->uuid == CSIS_SERVICE_SIRK_UUID) { - //bta_csip_handle_sirk_change(); - } else if (p_char->uuid == CSIS_SERVICE_SIZE_UUID) { - //bta_csip_handle_size_change(); - } -} - -/******************************************************************************* - * - * Function bta_csip_handle_lock_value_notif - * - * Description This function is called when notification is received for - * change in lock value on set member. - * - * Returns None - * - ******************************************************************************/ -void bta_csip_handle_lock_value_notif(tBTA_CSIP_DEV_CB* p_cb, - uint16_t handle, uint8_t value) { - tBTA_CSIS_SRVC_INFO* srvc = bta_csip_find_csis_srvc_by_lock_handle(p_cb, handle); - if (!srvc) { - LOG(ERROR) << __func__ << " CSIS Service instance not found for this handle"; - return; - } - - /* LOCK has been released by Set member (by lock timeout) */ - if (value == UNLOCK_VALUE && srvc->lock == LOCK_VALUE) { - srvc->lock = UNLOCK_VALUE; - /* Give lock status changed notification to all apps holding - * lock for this set member */ - LOG(INFO) << __func__ << " Lock released by timeout"; - for (auto i: srvc->lock_applist) { - tBTA_CSIP_RCB* rcb = bta_csip_get_rcb(i); - if (rcb && rcb->p_cback) { - std::vector sm(1, p_cb->addr); - tBTA_LOCK_STATUS_CHANGED p_data = {i, srvc->set_id, value, - LOCK_RELEASED_TIMEOUT, sm}; - (*rcb->p_cback) (BTA_CSIP_LOCK_STATUS_CHANGED_EVT, (tBTA_CSIP_DATA *)&p_data); - } - } - srvc->lock_applist.clear(); - } - /* LOCK held by other set coordinator is released */ - else if (value == UNLOCK_VALUE && srvc->lock == UNLOCK_VALUE) { - // check if lock was denied for any previous request - for (auto i: srvc->denied_applist) { - tBTA_CSIP_RCB* rcb = bta_csip_get_rcb(i); - if (rcb && rcb->p_cback) { - tBTA_LOCK_AVAILABLE p_data = {i, srvc->set_id, p_cb->addr}; - (*rcb->p_cback) (BTA_CSIP_LOCK_AVAILABLE_EVT, (tBTA_CSIP_DATA *)&p_data); - } - } - srvc->denied_applist.clear(); - } - /* Other Set Coordinator acquired the lock */ - else if (value == LOCK_VALUE && srvc->lock == UNLOCK_VALUE) { - // No action is required to be taken - } -} - -/******************************************************************************* - * - * Function bta_csip_csis_disc_complete_ind - * - * Description This function informas CSIS service discovery has been - * completed to DM layer. - * - * Returns None - * - ******************************************************************************/ -void bta_csip_csis_disc_complete_ind (RawAddress& addr) { - tBTA_CSIP_DEV_CB* p_cb = bta_csip_find_dev_cb_by_bda(addr); - if (p_cb) { - p_cb->total_instance_disc++; - LOG(INFO) << __func__ << " discovered = " << +p_cb->total_instance_disc - << " Total = " << +p_cb->csis_instance_count; - if (p_cb->total_instance_disc == p_cb->csis_instance_count - && !p_cb->is_disc_external) { - bta_dm_csis_disc_complete(addr, true); - bta_dm_lea_disc_complete(addr); - } - } -} - -/******************************************************************************* - * - * Function bta_csip_give_new_set_found_cb - * - * Description Give new coordinate set found callback to upper layer. - * - * Returns None - * - ******************************************************************************/ -void bta_csip_give_new_set_found_cb (tBTA_CSIS_SRVC_INFO *srvc) { - /* Check if this remote csis instance is included in another service */ - const std::vector* services = - BTA_GATTC_GetServices(srvc->conn_id); - - if (services) { - for (const gatt::Service& service : *services) { - if (service.is_primary) { - for (const gatt::IncludedService &included_srvc : service.included_services) { - if (included_srvc.uuid == CSIS_SERVICE_UUID - && service.handle == srvc->service_handle) { - APPL_TRACE_DEBUG("%s: service Uuid of service including CSIS service : %s", - __func__, service.uuid.ToString().c_str()); - srvc->including_srvc_uuid = service.uuid; - } - } - } - } - } - - // Given New Set found callback to upper layer - tBTA_CSIP_NEW_SET_FOUND new_set_params; - new_set_params.set_id = srvc->set_id; - memcpy(new_set_params.sirk, srvc->sirk, SIRK_SIZE); - new_set_params.size = srvc->size; - new_set_params.including_srvc_uuid = srvc->including_srvc_uuid; - new_set_params.addr = srvc->bd_addr; - new_set_params.lock_support = (srvc->lock_handle != 0)? true : false; - - (*bta_csip_cb.p_cback)(BTA_CSIP_NEW_SET_FOUND_EVT, (tBTA_CSIP_DATA *)&new_set_params); -} - -bool bta_csip_decrypt_sirk(tBTA_CSIS_SRVC_INFO *srvc, uint8_t *enc_sirk) { - // Get K from LTK or Link Key based on transport - Octet16 K = {}; - uint8_t gatt_if, transport = BT_TRANSPORT_LE; - RawAddress bdaddr; - GATT_GetConnectionInfor(srvc->conn_id, &gatt_if, bdaddr, &transport); - - char sample_data_prop[6]; - osi_property_get("vendor.bt.pts.sample_csis_data", sample_data_prop, "false"); - - if (!strncmp("true", sample_data_prop, 4)) { // comparing prop with "true" - K = {0x67, 0x6e, 0x1b, 0x9b, 0xd4, 0x48, 0x69, 0x6f, - 0x06, 0x1e, 0xc6, 0x22, 0x3c, 0xe5, 0xce, 0xd9}; - } else if (transport == BT_TRANSPORT_BR_EDR) { - K = BTM_SecGetDeviceLinkKey(srvc->bd_addr); - } else if (transport == BT_TRANSPORT_LE) { - RawAddress pseudo_addr; - pseudo_addr = bta_get_pseudo_addr_with_id_addr(srvc->bd_addr); - Octet16 rev_K = BTM_BleGetLTK(pseudo_addr); - std::reverse_copy(rev_K.begin(), rev_K.end(), K.begin()); - } - - if(is_key_empty(K)) { - APPL_TRACE_DEBUG("%s Invalid Key received", __func__); - srvc->discovery_status = BTA_CSIP_INVALID_KEY; - return false; - } - - /* compute SALT */ - Octet16 salt = bta_csip_get_salt(); - - // Compute T - Octet16 T = bta_csip_compute_T(salt, K); - - // Compute final result k1 - Octet16 k1 = bta_csip_compute_k1(T); - - // Get decrypted SIRK - Octet16 r_k1; - std::reverse_copy(k1.begin(), k1.end(), r_k1.begin()); - bta_csip_get_decrypted_sirk(r_k1, enc_sirk, srvc->sirk); - return true; -} - -/******************************************************************************* - * - * Function bta_sirk_read_cb - * - * Description Callback received when remote device Coordinated Sets SIRK - * is read. - * - * Returns None - * - ******************************************************************************/ -void bta_sirk_read_cb(uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, uint16_t len, - uint8_t* value, void* data) { - APPL_TRACE_DEBUG("%s ", __func__); - - if (status != GATT_SUCCESS) { - APPL_TRACE_ERROR("%s: SIRK Read failed. conn_id = %d status = %04x", - __func__, conn_id, status); - return; - } - - tBTA_CSIS_SRVC_INFO *srvc = (tBTA_CSIS_SRVC_INFO *)data; - - uint8_t type = 0xFF; - LOG(INFO) << __func__ << " SIRK len = " << +len; - - if (len != (SIRK_SIZE + 1)) { - APPL_TRACE_ERROR("%s : Invalid SIRK length", __func__); - srvc->discovery_status = BTA_CSIP_INVALID_SIRK_FORMAT; - bta_csip_csis_disc_complete_ind(srvc->bd_addr); - return; - } - - STREAM_TO_UINT8(type, value); - APPL_TRACE_DEBUG("%s Type Field with SIRK = %d", __func__, type); - if (type != ENCRYPTED_SIRK && type != PLAINTEXT_SIRK) { - APPL_TRACE_ERROR("%s : Invalid SIRK Type", __func__); - srvc->discovery_status = BTA_CSIP_INVALID_KEY_TYPE; - bta_csip_csis_disc_complete_ind(srvc->bd_addr); - return; - } - - if (type == ENCRYPTED_SIRK) { - uint8_t enc_sirk[SIRK_SIZE] = {}; - STREAM_TO_ARRAY(enc_sirk, value, SIRK_SIZE); - if (!bta_csip_decrypt_sirk(srvc, enc_sirk)) { - APPL_TRACE_ERROR("%s : Invalid Empty Key", __func__); - srvc->discovery_status = BTA_CSIP_INVALID_KEY; - bta_csip_csis_disc_complete_ind(srvc->bd_addr); - return; - } - } else { - STREAM_TO_ARRAY(srvc->sirk, value, SIRK_SIZE); - } - // check if this set was found earlier - uint8_t set_id = bta_csip_find_set_id_by_sirk (srvc->sirk); - tBTA_CSET_CB *cset_cb = NULL; - - /* New Coordinated Set */ - if (set_id == INVALID_SET_ID) { - cset_cb = bta_csip_get_cset_cb(); - if (!cset_cb) { - LOG(ERROR) << __func__ << " Insufficient set control blocks available."; - srvc->discovery_status = BTA_CSIP_RSRC_EXHAUSTED; - bta_csip_csis_disc_complete_ind(srvc->bd_addr); - return; - } - memcpy(cset_cb->sirk, srvc->sirk, SIRK_SIZE); - - // Create new coordinated set and update in database - tBTA_CSIP_CSET cset = {}; - cset.set_id = cset_cb->set_id; - cset.set_members.push_back(srvc->bd_addr); - cset.total_discovered++; - cset.lock_support = (srvc->lock_handle != 0 ? true : false); - LOG(INFO) << __func__ << "New Set. Adding device " << srvc->bd_addr.ToString() - << " Set ID: " << +cset.set_id; - bta_csip_cb.csets.push_back(cset); - - // assign set id in respective control blocks - srvc->set_id = cset_cb->set_id; - - /* Existing coordinated Set */ - } else { - LOG(INFO) << __func__ << " Device from existing set (set_id: " << +set_id << " )"; - //bta_csip_csis_disc_complete_ind(srvc->bd_addr); - srvc->set_id = set_id; - if (!bta_csip_update_set_member(set_id, srvc->bd_addr)) { - srvc->discovery_status = BTA_CSIP_ALL_MEMBERS_DISCOVERED; - bta_csip_csis_disc_complete_ind(srvc->bd_addr); - return; - } - - // Give set member found callback - tBTA_SET_MEMBER_FOUND set_member_params = - { .set_id = set_id, - .addr = srvc->bd_addr, - }; - - bta_csip_cb.p_cback (BTA_CSIP_SET_MEMBER_FOUND_EVT, (tBTA_CSIP_DATA *)&set_member_params); - return; - } - - /* If size is optional, give callback to upper layer */ - if (!srvc->size_handle) { - bta_csip_give_new_set_found_cb(srvc); - } - - if (!srvc->size_handle && !srvc->rank_handle) { - bta_csip_preserve_cset(srvc); - } -} - -/******************************************************************************* - * - * Function bta_size_read_cb - * - * Description Callback received when remote device Coordinated Sets SIZE - * characteristic is read. - * - * Returns None - * - ******************************************************************************/ -void bta_size_read_cb(uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, uint16_t len, - uint8_t* value, void* data) { - - if (status != GATT_SUCCESS) { - APPL_TRACE_ERROR("%s: SIZE Read failed. conn_id = %d status = %04x", - __func__, conn_id, status); - return; - } - - tBTA_CSIS_SRVC_INFO *srvc = (tBTA_CSIS_SRVC_INFO *)data; - - if (srvc->discovery_status != BTA_CSIP_DISC_SUCCESS) { - APPL_TRACE_ERROR("%s: Ignore response (Reason: %d)", __func__, srvc->discovery_status); - return; - } - - srvc->size = *value; - APPL_TRACE_DEBUG("%s size = %d", __func__, srvc->size); - - tBTA_CSIP_CSET* cset = bta_csip_get_or_create_cset(srvc->set_id, true); - if (cset) cset->size = srvc->size; - // Give callback only when its a first set member - uint8_t totalDiscovered = bta_csip_get_coordinated_set(srvc->set_id).set_members.size(); - if (totalDiscovered == 1) { - bta_csip_give_new_set_found_cb(srvc); - } - - if (!srvc->rank_handle) { - bta_csip_preserve_cset(srvc); - } -} - -/******************************************************************************* - * - * Function bta_lock_read_cb - * - * Description Callback received when remote device Coordinated Sets LOCK - * characteristic is read. - * - * Returns None - * - ******************************************************************************/ -void bta_lock_read_cb(uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, uint16_t len, - uint8_t* value, void* data) { - if (status != GATT_SUCCESS) { - APPL_TRACE_ERROR("%s: LOCK Read failed. conn_id = %d status = %04x", - __func__, conn_id, status); - return; - } - - APPL_TRACE_DEBUG("%s lock value = %d", __func__, *value); -} - -/******************************************************************************* - * - * Function bta_rank_read_cb - * - * Description Callback received when remote device Coordinated Sets RANK - * characteristic is read. - * - * Returns None - * - ******************************************************************************/ -void bta_rank_read_cb(uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, uint16_t len, - uint8_t* value, void* data) { - if (status != GATT_SUCCESS) { - APPL_TRACE_ERROR("%s: Rank Read failed. conn_id = %d status = %04x", - __func__, conn_id, status); - return; - } - - tBTA_CSIS_SRVC_INFO *srvc = (tBTA_CSIS_SRVC_INFO *)data; - if (srvc->discovery_status != BTA_CSIP_DISC_SUCCESS) { - APPL_TRACE_ERROR("%s: Ignore response (Reason: %d)", __func__, srvc->discovery_status); - return; - } - - srvc->rank = *value; - APPL_TRACE_DEBUG("%s device: %s Rank = %d set_id: %d", __func__, - srvc->bd_addr.ToString().c_str(), srvc->rank, srvc->set_id); - - // get coordinated set control block from set_id - tBTA_CSET_CB *cset_cb = bta_csip_get_cset_cb_by_id(srvc->set_id); - if (cset_cb) { - cset_cb->ordered_members.insert({srvc->rank, srvc->bd_addr}); - } - - bta_csip_preserve_cset(srvc); - bta_csip_csis_disc_complete_ind(srvc->bd_addr); -} - -/******************************************************************************* - * - * Function bta_csip_gatt_disc_cmpl_act - * - * Description This APIS is used to serach presence of csis service on - * remote device and initialize CSIS handles in csis service - * control block. - * - * Returns None - * - ******************************************************************************/ -void bta_csip_gatt_disc_cmpl_act(tBTA_CSIP_DISC_SET *disc_params) { - uint16_t conn_id = disc_params->conn_id; - uint8_t status = disc_params->status; - RawAddress addr = disc_params->addr; - - APPL_TRACE_DEBUG("%s conn_id = %d, status = %d addr: %s", __func__, conn_id, - status, addr.ToString().c_str()); - - if (status) return; - - // Fetch remote device gatt services from database - const std::vector* services = - BTA_GATTC_GetServices(conn_id); - - if (!services) { - LOG(ERROR) << __func__ << " No Services discovered."; - bta_csip_csis_disc_complete_ind(addr); - return; - } - - tBTA_CSIP_DEV_CB* dev_cb = bta_csip_find_dev_cb_by_bda(addr); - - if (!dev_cb) { - dev_cb = bta_csip_create_dev_cb_for_bda(addr); - } - - dev_cb->csis_instance_count = 0; - - // Search for CSIS service in the database - for (const gatt::Service& service : *services) { - if (service.uuid == CSIS_SERVICE_UUID) { - dev_cb->csis_instance_count++; - // Get service control block from service handle (subsequent connection) - tBTA_CSIS_SRVC_INFO *srvc = bta_csip_get_csis_service_by_handle(dev_cb, service.handle); - if (!srvc) { - // create new service cb (if its a first time connection) - srvc = bta_csip_get_csis_service_cb(dev_cb); - if (!srvc) { - APPL_TRACE_ERROR("%s Resources not available for storing CSIS Service.", __func__); - return; - } - } - srvc->bd_addr = addr; - srvc->service_handle = service.handle; - srvc->conn_id = conn_id; - APPL_TRACE_DEBUG("%s: CSIS service found Uuid: %s service_handle = %d", __func__, - service.uuid.ToString().c_str(), srvc->service_handle); - - // Get Characteristic and CCCD handle - for (const gatt::Characteristic& charac : service.characteristics) { - Uuid uuid1 = charac.uuid; - if (uuid1 == CSIS_SERVICE_SIRK_UUID) { - srvc->sirk_handle = charac.value_handle; - srvc->sirk_ccd_handle = bta_csip_get_cccd_handle(conn_id, charac.value_handle); - } else if (uuid1 == CSIS_SERVICE_SIZE_UUID) { - srvc->size_handle = charac.value_handle; - srvc->size_ccd_handle = bta_csip_get_cccd_handle(conn_id, charac.value_handle); - } else if (uuid1 == CSIS_SERVICE_LOCK_UUID) { - srvc->lock_handle = charac.value_handle; - srvc->lock_ccd_handle = bta_csip_get_cccd_handle(conn_id, charac.value_handle); - } else if (uuid1 == CSIS_SERVICE_RANK_UUID) { - srvc->rank_handle = charac.value_handle; - } - } - - /* Skip reading characteristics and Set Discovery procedure if it was done earlier */ - if (srvc->set_id >= 0 && srvc->set_id < BTA_MAX_SUPPORTED_SETS) { - LOG(INFO) << __func__ << " Coordinated set discovery procedure already completed."; - continue; - } - - if (srvc->sirk_handle) { - BtaGattQueue::ReadCharacteristic( - conn_id, srvc->sirk_handle, bta_sirk_read_cb, srvc); - } - - if (srvc->size_handle) { - BtaGattQueue::ReadCharacteristic( - conn_id, srvc->size_handle, bta_size_read_cb, srvc); - } - - if (srvc->lock_handle) { - BtaGattQueue::ReadCharacteristic( - conn_id, srvc->lock_handle, bta_lock_read_cb, srvc); - } - - if (srvc->rank_handle) { - BtaGattQueue::ReadCharacteristic( - conn_id, srvc->rank_handle, bta_rank_read_cb, srvc); - } - } - - } -} diff --git a/le_audio/system/bt/bta/csip/bta_csip_api.cc b/le_audio/system/bt/bta/csip/bta_csip_api.cc deleted file mode 100644 index 73a9054c9667a37c8d347608e4dc424ea57d5340..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/csip/bta_csip_api.cc +++ /dev/null @@ -1,287 +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. - * - ******************************************************************************/ - - -/****************************************************************************** - * - * This file contains the CSIP API in the subsystem of BTA. - * - ******************************************************************************/ - -#define LOG_TAG "bt_bta_csip" - -#include -#include -#include -#include -#include -#include - -#include "bta_csip_api.h" -#include "bta_csip_int.h" -#include "bta_gatt_queue.h" -#include "osi/include/log.h" -#include "osi/include/osi.h" - -/***************************************************************************** - * Constants - ****************************************************************************/ -static const tBTA_SYS_REG bta_csip_reg = {bta_csip_hdl_event, BTA_CsipDisable}; - -/********************************************************************************* - * - * Function BTA_RegisterCsipApp - * - * Description This function is called to register application or module to - * to register with CSIP for using CSIP functionalities. - * - * Parameters p_csip_cb: callback to be received in registering app when - * required CSIP operation is completed. - * reg_cb : callback when app/module is registered with CSIP. - * - * Returns None - * - *********************************************************************************/ -void BTA_RegisterCsipApp(tBTA_CSIP_CBACK* p_csip_cb, - BtaCsipAppRegisteredCb reg_cb) { - do_in_bta_thread(FROM_HERE, base::Bind(&bta_csip_app_register, Uuid::GetRandom(), - p_csip_cb, std::move(reg_cb))); -} - -/********************************************************************************* - * - * Function BTA_UnregisterCsipApp - * - * Description This function is called to unregister application or module. - * - * Parameters app_id: id of the app/module that needs to be unregistered. - * - * Returns None - * - *********************************************************************************/ - -void BTA_UnregisterCsipApp(uint8_t app_id) { - do_in_bta_thread(FROM_HERE, base::Bind(&bta_csip_app_unregister, app_id)); -} - -/********************************************************************************* - * - * Function BTA_CsipSetLockValue - * - * Description This function is called to request or release lock for the - * coordinated set. - * - * Parameters lock_param: parameters to acquire or release lock. - * (tBTA_SET_LOCK_PARAMS). - * - * Returns None - * - *********************************************************************************/ -void BTA_CsipSetLockValue(tBTA_SET_LOCK_PARAMS lock_params) { - tBTA_CSIP_LOCK_PARAMS* p_buf = - (tBTA_CSIP_LOCK_PARAMS*)osi_calloc(sizeof(tBTA_CSIP_LOCK_PARAMS)); - - p_buf->hdr.event = BTA_CSIP_SET_LOCK_VALUE_EVT; - p_buf->lock_req = lock_params; - - bta_sys_sendmsg(p_buf); -} - -/********************************************************************************* - * - * Function BTA_CsipGetCoordinatedSet - * - * Description This function is called to fetch details of the coordinated set. - * - * Parameters set_id: identifier of the coordinated set whose details are - * required to be fetched. - * - * Returns tBTA_CSIP_CSET (containing details of coordinated set). - * - *********************************************************************************/ -tBTA_CSIP_CSET BTA_CsipGetCoordinatedSet(uint8_t set_id) { - APPL_TRACE_DEBUG("%s: set_id = %d", __func__, set_id); - return bta_csip_get_coordinated_set(set_id); -} - -/********************************************************************************* - * - * Function BTA_CsipSetLockValue - * - * Description This function is called to request or release lock for the - * coordinated set. - * - * Parameters None. - * - * Returns vector: (all discovered coordinated set) - * - *********************************************************************************/ -std::vector BTA_CsipGetDiscoveredSets() { - return bta_csip_cb.csets; -} - -/********************************************************************************* - * - * Function BTA_CsipConnect - * - * Description This function is called to establish GATT Connection. - * - * Parameters bd_addr : Address of the remote device. - * - * Returns None. - * - *********************************************************************************/ -void BTA_CsipConnect (uint8_t app_id, const RawAddress& bd_addr) { - tBTA_CSIP_API_CONN* p_buf = - (tBTA_CSIP_API_CONN*)osi_calloc(sizeof(tBTA_CSIP_API_CONN)); - p_buf->hdr.event = BTA_CSIP_API_OPEN_EVT; - p_buf->bd_addr = bd_addr; - p_buf->app_id = app_id; - - bta_sys_sendmsg(p_buf); -} - -/********************************************************************************* - * - * Function BTA_CsipConnect - * - * Description This function is called to establish GATT Connection. - * - * Parameters bd_addr : Address of the remote device. - * - * Returns None. - * - *********************************************************************************/ -void BTA_CsipDisconnect (uint8_t app_id, const RawAddress& bd_addr) { - tBTA_CSIP_API_CONN* p_buf = - (tBTA_CSIP_API_CONN*)osi_calloc(sizeof(tBTA_CSIP_API_CONN)); - p_buf->hdr.event = BTA_CSIP_API_CLOSE_EVT; - p_buf->bd_addr = bd_addr; - p_buf->app_id = app_id; - - bta_sys_sendmsg(p_buf); -} - -/********************************************************************************* - * - * Function BTA_CsipFindCsisInstance - * - * Description This function is called to find presence of CSIS service on - * remote device. - * - * Parameters coon_id : Connection ID of the GATT Connection at DM Layer. - * - * Returns None. - * - *********************************************************************************/ -void BTA_CsipFindCsisInstance(uint16_t conn_id, tGATT_STATUS status, - RawAddress& bd_addr) { - APPL_TRACE_DEBUG("%s ", __func__); - - tBTA_CSIP_DISC_SET* p_buf = - (tBTA_CSIP_DISC_SET*)osi_calloc(sizeof(tBTA_CSIP_DISC_SET)); - p_buf->hdr.event = BTA_CSIP_DISC_CMPL_EVT; - p_buf->conn_id = conn_id; - p_buf->status = status; - p_buf->addr = bd_addr; - - bta_sys_sendmsg(p_buf); -} - -/********************************************************************************* - * - * Function BTA_CsipInit - * - * Description This function is invoked to initialize CSIP in BTA layer. - * - * Parameters None. - * - * Returns None. - * - *********************************************************************************/ -void BTA_CsipEnable(tBTA_CSIP_CBACK *p_cback) { - tBTA_CSIP_ENABLE* p_buf = - (tBTA_CSIP_ENABLE*)osi_calloc(sizeof(tBTA_CSIP_ENABLE)); - - /* register with BTA system manager */ - bta_sys_register(BTA_ID_GROUP, &bta_csip_reg); - - p_buf->hdr.event = BTA_CSIP_API_ENABLE_EVT; - p_buf->p_cback = p_cback; - - bta_sys_sendmsg(p_buf); -} - -/********************************************************************************* - * - * Function BTA_CsipDisable - * - * Description This function is called for deinitialization. - * - * Parameters None. - * - * Returns None. - * - *********************************************************************************/ -void BTA_CsipDisable() { - tBTA_CSIP_ENABLE* p_buf = - (tBTA_CSIP_ENABLE*)osi_calloc(sizeof(tBTA_CSIP_ENABLE)); - - p_buf->hdr.event = BTA_CSIP_API_DISABLE_EVT; - - bta_sys_sendmsg(p_buf); -} - -/********************************************************************************* - * - * Function BTA_CsipRemoveUnpairedSetMember - * - * Description This function is called when a given set member is unpaired. - * - * Parameters addr: BD Address of the set member. - * - * Returns None. - * - *********************************************************************************/ -void BTA_CsipRemoveUnpairedSetMember(RawAddress addr) { - do_in_bta_thread(FROM_HERE, base::Bind(&bta_csip_remove_set_member, addr)); -} - -/********************************************************************************* - * - * Function BTA_CsipGetDeviceSetId - * - * Description This API is used to get set id of the remote device. - * - * Parameters addr: BD Address of the set member. - * uuid: UUID of the service which includes CSIS service. - * - * Returns None. - * - *********************************************************************************/ -uint8_t BTA_CsipGetDeviceSetId(RawAddress addr, bluetooth::Uuid uuid) { - for (tBTA_CSIP_CSET cset: bta_csip_cb.csets) { - for (RawAddress bd_addr: cset.set_members) { - if (bd_addr == addr && (cset.p_srvc_uuid == uuid)) { - return cset.set_id; - } - } - } - - return BTA_MAX_SUPPORTED_SETS; -} diff --git a/le_audio/system/bt/bta/csip/bta_csip_int.h b/le_audio/system/bt/bta/csip/bta_csip_int.h deleted file mode 100644 index 5000bbf6bccacac03cb9ce045bc489e720a852e9..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/csip/bta_csip_int.h +++ /dev/null @@ -1,321 +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. - * - ******************************************************************************/ - - -/****************************************************************************** - * - * This file contains BTA CSIP Client internal definitions - * - ******************************************************************************/ - -#ifndef BTA_CSIP_INT_H -#define BTA_CSIP_INT_H - -#include "bta_csip_api.h" -#include "bta_gatt_api.h" -#include "bta_sys.h" -#include "btm_ble_api_types.h" - -/* Max CSIP supported devices (control blocks) */ -#define BTA_CSIP_MAX_DEVICE 32 - -/* Max CSIP supported coordinated sets */ -#define BTA_MAX_SUPPORTED_SETS 16 - -/* Maximum number of apps that can be registered with CSIP*/ -#define BTA_CSIP_MAX_SUPPORTED_APPS 16 - -/* Max Supported coordinated sets per device*/ -#define MAX_SUPPORTED_SETS_PER_DEVICE 5 - -/* Status of the CSIS Discovery*/ -#define BTA_CSIP_DISC_SUCCESS 0 -#define BTA_CSIP_INVALID_SIRK_FORMAT 1 -#define BTA_CSIP_INVALID_KEY 2 -#define BTA_CSIP_INVALID_KEY_TYPE 3 -#define BTA_CSIP_ALL_MEMBERS_DISCOVERED 4 -#define BTA_CSIP_RSRC_EXHAUSTED 5 - -using bluetooth::Uuid; - -/* state machine events, these events are handled by the state machine */ -enum { - BTA_CSIP_API_OPEN_EVT = BTA_SYS_EVT_START(BTA_ID_GROUP), - BTA_CSIP_API_CLOSE_EVT, - BTA_CSIP_GATT_OPEN_EVT, - BTA_CSIP_GATT_CLOSE_EVT, - BTA_CSIP_OPEN_FAIL_EVT, - BTA_CSIP_OPEN_CMPL_EVT, - BTA_CSIP_START_ENC_EVT, - BTA_CSIP_ENC_CMPL_EVT, - BTA_CSIP_GATT_ENC_CMPL_EVT, - - /* common events: not handled by execute state machine */ - BTA_CSIP_API_ENABLE_EVT, - BTA_CSIP_API_DISABLE_EVT, - BTA_CSIP_DISC_CMPL_EVT, - BTA_CSIP_SET_LOCK_VALUE_EVT, -}; - -/* CSIP device state machine states */ -enum { - BTA_CSIP_IDLE_ST, - BTA_CSIP_W4_CONN_ST, - BTA_CSIP_W4_SEC, - BTA_CSIP_CONN_ST, - BTA_CSIP_DISCONNECTING_ST, -}; - -typedef uint8_t tBTA_CSIP_STATE; - - -/* CSIP Command request parameters in BTA */ - -/* Find Coordinated set parameters*/ -typedef struct { - BT_HDR hdr; - uint16_t conn_id; - tGATT_STATUS status; - RawAddress addr; -} tBTA_CSIP_DISC_SET; - -/* Connection Request parameters */ -typedef struct { - BT_HDR hdr; - RawAddress bd_addr; - uint8_t app_id; -} tBTA_CSIP_API_CONN; - -/* Lock request parameters */ -typedef struct { - BT_HDR hdr; - tBTA_SET_LOCK_PARAMS lock_req; -} tBTA_CSIP_LOCK_PARAMS; - - -typedef struct { - BT_HDR hdr; - tBTA_CSIP_CBACK* p_csip_cb; - tBTA_CSIP_CLT_REG_CB* reg_cb; -} tBTA_CSIP_APP_REG_PARAMS; - -typedef struct { - BT_HDR hdr; - tBTA_CSIP_CBACK *p_cback; -} tBTA_CSIP_ENABLE; - -typedef struct { - BT_HDR hdr; -} tBTA_CSIP_CMD; - -typedef union { - BT_HDR hdr; - tBTA_CSIP_API_CONN conn_param; - tBTA_CSIP_LOCK_PARAMS lock_req; - tBTA_CSIP_APP_REG_PARAMS reg_param; - tBTA_CSIP_ENABLE enable_param; - tBTA_GATTC_OPEN gatt_open_param; - tBTA_GATTC_CLOSE gatt_close_param; - tBTA_CSIP_CMD cmd; -} tBTA_CSIP_REQ_DATA; - -typedef struct { - bool in_use; - uint8_t set_id = BTA_MAX_SUPPORTED_SETS; - uint16_t conn_id; /* GATT conn_id used for service discovery */ - RawAddress bd_addr; - - uint16_t service_handle; /* Handle of this CSIS service */ - uint16_t sirk_handle; /* SIRK characteristic value handle */ - uint16_t size_handle; /* size characteristic value handle */ - uint16_t lock_handle; /* lock characteristic value handle */ - uint16_t rank_handle; /* rank characteristic value handle */ - - uint16_t sirk_ccd_handle; /* SIRK CCCD handle*/ - uint16_t size_ccd_handle; /* size CCCD handle */ - uint16_t lock_ccd_handle; /* lock CCCD handle */ - - uint8_t sirk[SIRK_SIZE]; /* Coordinated set SIRK */ - uint8_t size; /* size of the coordinated set */ - uint8_t lock; /* lock status of the set member */ - uint8_t rank; /* rank of the set member*/ - uint8_t discovery_status = BTA_CSIP_DISC_SUCCESS; /* status of the CSIS discovery*/ - bluetooth::Uuid including_srvc_uuid; /* uuid of the service which includes CSIS*/ - - /* Lock mamangement details*/ - std::vector lock_applist; /* Apps those have locked this set */ - std::vector unrsp_applist; /* Apps to which unresponsive res is sent */ - std::vector denied_applist; /* Apps to which lock was denied */ -} tBTA_CSIS_SRVC_INFO; - -typedef struct { - bool in_use; - RawAddress addr; /* Remote device address */ - uint16_t conn_id; /* GATT Connection ID */ - uint8_t sec_mask = (BTM_SEC_IN_ENCRYPT | BTM_SEC_OUT_ENCRYPT); /* Security Mask for CSIP*/ - bool security_pending; - bool is_disc_external = false; /* if discovery is started by external App*/ - uint8_t state; /* connection state */ - uint8_t csis_instance_count; /* number of CSIS instances on remote device */ - uint8_t total_instance_disc; /* total number of instances discovered */ - - /* CSIS services found on remote device*/ - tBTA_CSIS_SRVC_INFO csis_srvc[MAX_SUPPORTED_SETS_PER_DEVICE]; - - // list of applications which initiated CSIP connect for this device - std::vector conn_applist; /* List of Apps that sent connection request*/ - std::string set_info = ""; - bool unresponsive; /* if remote is unresponsive to GATT request */ -} tBTA_CSIP_DEV_CB; - -typedef struct { - uint8_t app_id; - uint8_t set_id; - uint8_t value; - int8_t cur_idx; - std::vector members_addr; -} tBTA_LOCK_REQUEST; - -typedef struct { - bool in_use; - uint8_t set_id = BTA_MAX_SUPPORTED_SETS; - uint8_t sirk[SIRK_SIZE]; - uint16_t set_member_tout = 500; - bool request_in_progress; - tBTA_CSIP_DEV_CB* cur_dev_cb; - alarm_t* unresp_timer; - tBTA_LOCK_REQUEST cur_lock_req; - tBTA_LOCK_STATUS_CHANGED cur_lock_res; - std::map ordered_members; - std::queue lock_req_queue; -} tBTA_CSET_CB; - -typedef struct { - uint8_t app_id; - bool in_use; - tBTA_CSIP_CBACK* p_cback; -} tBTA_CSIP_RCB; - -typedef struct { - tGATT_IF gatt_if; - tBTA_CSIP_CBACK* p_cback; /* callbacks for btif layer */ - std::vector dev_cb; /* device control block */ - tBTA_CSIP_RCB app_rcb[BTA_CSIP_MAX_SUPPORTED_APPS]; - std::vector csets; - tBTA_CSET_CB csets_cb[BTA_MAX_SUPPORTED_SETS]; -} tBTA_CSIP_CB; - -/***************************************************************************** - * Global data - ****************************************************************************/ - -/* CSIP control block */ -extern tBTA_CSIP_CB bta_csip_cb; - -/***************************************************************************** - * Function prototypes - ****************************************************************************/ -void bta_csip_sm_execute(tBTA_CSIP_DEV_CB* p_cb, uint16_t event, - tBTA_CSIP_REQ_DATA* p_data); - - -//action api's -extern bool bta_csip_hdl_event(BT_HDR* p_msg); -extern void bta_csip_api_enable(tBTA_CSIP_CBACK *p_cback); -extern void bta_csip_api_disable(); -extern void bta_csip_app_register (const Uuid& app_uuid, tBTA_CSIP_CBACK* p_cback, - BtaCsipAppRegisteredCb cb); -extern void bta_csip_gattc_register(); -extern void bta_csip_app_unregister(uint8_t app_id); -extern void bta_csip_gatt_disc_cmpl_act(tBTA_CSIP_DISC_SET *disc_params); -extern void bta_csip_api_open_act (tBTA_CSIP_DEV_CB* p_cb, tBTA_CSIP_REQ_DATA* p_data); -extern void bta_csip_api_close_act (tBTA_CSIP_DEV_CB* p_cb, tBTA_CSIP_REQ_DATA* p_data); -extern void bta_csip_gatt_open_act (tBTA_CSIP_DEV_CB* p_cb, tBTA_CSIP_REQ_DATA* p_data); -extern void bta_csip_gatt_close_act (tBTA_CSIP_DEV_CB* p_cb, tBTA_CSIP_REQ_DATA* p_data); -extern void bta_csip_gatt_open_fail_act (tBTA_CSIP_DEV_CB* p_cb, tBTA_CSIP_REQ_DATA* p_data); -extern void bta_csip_open_cmpl_act (tBTA_CSIP_DEV_CB* p_cb, tBTA_CSIP_REQ_DATA* p_data); -extern void bta_csip_start_sec_act (tBTA_CSIP_DEV_CB* p_cb, tBTA_CSIP_REQ_DATA* p_data); -extern void bta_csip_sec_cmpl_act (tBTA_CSIP_DEV_CB* p_cb, tBTA_CSIP_REQ_DATA* p_data); -extern void bta_csip_close_csip_conn (tBTA_CSIP_DEV_CB* p_cb); -extern void bta_csip_process_set_lock_act(tBTA_SET_LOCK_PARAMS lock_req); -extern void bta_csip_send_lock_req_act(tBTA_CSET_CB* cset_cb); -extern void bta_csip_handle_lock_denial(tBTA_CSET_CB* cset_cb); -extern bool bta_csip_validate_req_for_denied_sm (tBTA_CSET_CB* cset_cb); -extern void bta_csip_form_lock_request(tBTA_SET_LOCK_PARAMS lock_param, - tBTA_CSET_CB* cset_cb); -extern void bta_csip_send_unlock_req_act(tBTA_CSET_CB* cset_cb); -extern void bta_csip_set_member_lock_timeout(void* p_data); -extern void bta_csip_load_coordinated_sets_from_storage(); - -// bta_csip_utils -extern tBTA_CSIP_DEV_CB* bta_csip_find_dev_cb_by_bda(const RawAddress& bda); -extern tBTA_CSIP_DEV_CB* bta_csip_get_dev_cb_by_cid(uint16_t conn_id); -extern tBTA_CSIP_DEV_CB* bta_csip_create_dev_cb_for_bda(const RawAddress& bda); -extern tBTA_CSIS_SRVC_INFO* bta_csip_get_csis_service_cb(tBTA_CSIP_DEV_CB* dev_cb); -extern bool bta_csip_is_csis_supported(tBTA_CSIP_DEV_CB* dev_cb); -extern tBTA_CSIS_SRVC_INFO* bta_csip_get_csis_service_by_handle(tBTA_CSIP_DEV_CB* dev_cb, - uint16_t service_handle); -extern tBTA_CSIS_SRVC_INFO* bta_csip_find_csis_srvc_by_lock_handle(tBTA_CSIP_DEV_CB* dev_cb, - uint16_t lock_handle); -extern tBTA_CSIP_CSET* bta_csip_get_or_create_cset (uint8_t set_id, bool existing); -extern bool bta_csip_validate_set_params(tBTA_SET_LOCK_PARAMS* lock_req); -extern bool bta_csip_is_valid_lock_request(tBTA_SET_LOCK_PARAMS* lock_req); -extern std::vector bta_csip_arrange_set_members_by_order( - uint8_t set_id, std::vector& req_sm, bool ascending); -extern tBTA_CSIP_CSET bta_csip_get_coordinated_set (uint8_t set_id); -extern bool bta_csip_update_set_member (uint8_t set_id, RawAddress addr); -extern tBTA_CSET_CB* bta_csip_get_cset_cb (); -extern tBTA_CSET_CB* bta_csip_get_cset_cb_by_id (uint8_t set_id); -extern uint8_t bta_csip_find_set_id_by_sirk (uint8_t* sirk); -extern tBTA_CSIS_SRVC_INFO* bta_csip_get_csis_instance(tBTA_CSIP_DEV_CB* dev_cb, uint8_t set_id); -extern bool bta_csip_is_locked_by_other_apps(tBTA_CSIS_SRVC_INFO* srvc, uint8_t app_id); -extern std::vector bta_csip_get_set_member_by_order(uint8_t set_id, - bool ascending); -extern bool bta_csip_is_member_locked_by_app (uint8_t app_id, tBTA_CSIS_SRVC_INFO* srvc); -extern void bta_csip_get_next_lock_request(tBTA_CSET_CB* cset_cb); -extern uint16_t bta_csip_get_cccd_handle (uint16_t conn_id, uint16_t char_handle); -extern bool bta_csip_is_app_reg(uint8_t app_id); -extern tBTA_CSIP_RCB* bta_csip_get_rcb (uint8_t app_id); -extern void bta_csip_remove_set_member (RawAddress addr); -extern void bta_csip_handle_notification(tBTA_GATTC_NOTIFY* ntf); -extern void bta_csip_handle_lock_value_notif(tBTA_CSIP_DEV_CB* p_cb, - uint16_t handle, uint8_t value); -extern void bta_csip_add_app_to_applist(tBTA_CSIP_DEV_CB* p_cb, uint8_t app_id); -extern void bta_csip_handle_unresponsive_sm_res(tBTA_CSIS_SRVC_INFO* srvc, - tGATT_STATUS status); -extern void bta_csip_remove_app_from_conn_list(tBTA_CSIP_DEV_CB* p_cb, uint8_t app_id); -extern bool bta_csip_is_app_from_applist(tBTA_CSIP_DEV_CB* p_cb, uint8_t app_id); -extern void bta_csip_send_conn_state_changed_cb(tBTA_CSIP_DEV_CB* p_cb, - uint8_t state, uint8_t status); -extern void bta_csip_send_conn_state_changed_cb (tBTA_CSIP_DEV_CB* p_cb, uint8_t app_id, - uint8_t state, uint8_t status); -extern void bta_csip_send_lock_req_cmpl_cb (tBTA_LOCK_STATUS_CHANGED cset_cb); -extern void bta_csip_write_cccd (tBTA_CSIP_DEV_CB* p_cb, uint16_t char_handle, - uint16_t cccd_handle); -extern void bta_csip_preserve_cset (tBTA_CSIS_SRVC_INFO* srvc); -extern Octet16 bta_csip_get_salt(); -extern Octet16 bta_csip_compute_T(Octet16 salt, Octet16 K); -extern Octet16 bta_csip_compute_k1(Octet16 T); -extern void bta_csip_get_decrypted_sirk(Octet16 k1, uint8_t *enc_sirk, uint8_t *sirk); -extern Octet16 bta_csip_get_aes_cmac_result(const Octet16& key, const Octet16& message); -extern Octet16 bta_csip_get_aes_cmac_result(const Octet16& key, const uint8_t* input, - uint16_t length); -extern void hex_string_to_byte_arr(char *str, uint8_t* byte_arr, uint8_t len); -extern void byte_arr_to_hex_string(uint8_t* byte_arr, char* str, uint8_t len); -extern bool is_key_empty(Octet16& key); -#endif diff --git a/le_audio/system/bt/bta/csip/bta_csip_main.cc b/le_audio/system/bt/bta/csip/bta_csip_main.cc deleted file mode 100644 index 87111f19b0228682c106e3583a31a3ece9215234..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/csip/bta_csip_main.cc +++ /dev/null @@ -1,296 +0,0 @@ -/****************************************************************************** - * - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - - -#include "bt_target.h" -#include "bta_csip_int.h" - -#include - -#include "bt_common.h" - -#define LOG_TAG "bt_bta_csip" - -/***************************************************************************** - * Static methods - ****************************************************************************/ -static const char* bta_csip_evt_code(uint16_t evt_code); -static const char* bta_csip_state_code(tBTA_CSIP_STATE evt_code); - -/***************************************************************************** - * Global data - ****************************************************************************/ -tBTA_CSIP_CB bta_csip_cb; - -enum { - BTA_CSIP_OPEN_ACT, - BTA_CSIP_CLOSE_ACT, - BTA_CSIP_GATT_OPEN_ACT, - BTA_CSIP_GATT_CLOSE_ACT, - BTA_CSIP_GATT_OPEN_FAIL_ACT, - BTA_CSIP_OPEN_CMPL_ACT, - BTA_CSIP_START_SEC_ACT, - BTA_CSIP_SEC_CMPL_ACT, - BTA_CSIP_IGNORE, -}; - -/* type for action functions */ -typedef void (*tBTA_CSIP_ACTION)(tBTA_CSIP_DEV_CB* p_cb, tBTA_CSIP_REQ_DATA* p_data); - -/* action functions */ -const tBTA_CSIP_ACTION bta_csip_action[] = { - bta_csip_api_open_act, - bta_csip_api_close_act, - bta_csip_gatt_open_act, - bta_csip_gatt_close_act, - bta_csip_gatt_open_fail_act, - bta_csip_open_cmpl_act, - bta_csip_start_sec_act, - bta_csip_sec_cmpl_act, -}; - -/* state table information */ -#define BTA_CSIP_ACTION 0 /* position of action */ -#define BTA_CSIP_NEXT_STATE 1 /* position of next state */ -#define BTA_CSIP_NUM_COLS 2 /* number of columns */ - -/* state table in idle state */ -const uint8_t bta_csip_st_idle[][BTA_CSIP_NUM_COLS] = { - /* Event Action Next state */ - /* BTA_CSIP_API_OPEN_EVT */ {BTA_CSIP_OPEN_ACT, BTA_CSIP_W4_CONN_ST}, - /* BTA_CSIP_API_CLOSE_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_IDLE_ST}, - /* BTA_CSIP_GATT_OPEN_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_IDLE_ST}, - /* BTA_CSIP_GATT_CLOSE_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_IDLE_ST}, - /* BTA_CSIP_GATT_OPEN_FAIL_ACT */ {BTA_CSIP_IGNORE, BTA_CSIP_IDLE_ST}, - /* BTA_CSIP_OPEN_CMPL_EVT */ {BTA_CSIP_OPEN_CMPL_ACT, BTA_CSIP_CONN_ST}, - /* BTA_CSIP_START_ENC_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_IDLE_ST}, - /* BTA_CSIP_ENC_CMPL_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_IDLE_ST}, -}; - -/* state table in wait for security state */ -const uint8_t bta_csip_st_w4_conn[][BTA_CSIP_NUM_COLS] = { - /* Event Action Next state */ - /* BTA_CSIP_API_OPEN_EVT */ {BTA_CSIP_OPEN_ACT, BTA_CSIP_W4_CONN_ST}, - /* BTA_CSIP_API_CLOSE_EVT */ {BTA_CSIP_CLOSE_ACT, BTA_CSIP_W4_CONN_ST}, - /* BTA_CSIP_GATT_OPEN_EVT */ {BTA_CSIP_GATT_OPEN_ACT, BTA_CSIP_W4_CONN_ST}, - /* BTA_CSIP_GATT_CLOSE_EVT */ {BTA_CSIP_GATT_CLOSE_ACT, BTA_CSIP_IDLE_ST}, - /* BTA_CSIP_GATT_OPEN_FAIL_ACT */ {BTA_CSIP_GATT_OPEN_FAIL_ACT, BTA_CSIP_IDLE_ST}, - /* BTA_CSIP_OPEN_CMPL_EVT */ {BTA_CSIP_OPEN_CMPL_ACT, BTA_CSIP_CONN_ST}, - /* BTA_CSIP_START_ENC_EVT */ {BTA_CSIP_START_SEC_ACT, BTA_CSIP_W4_SEC}, - /* BTA_CSIP_ENC_CMPL_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_W4_CONN_ST}, -}; - -/* state table in wait for connection state */ -const uint8_t bta_csip_st_w4_sec[][BTA_CSIP_NUM_COLS] = { - /* Event Action Next state */ - /* BTA_CSIP_API_OPEN_EVT */ {BTA_CSIP_OPEN_ACT, BTA_CSIP_W4_SEC}, - /* BTA_CSIP_API_CLOSE_EVT */ {BTA_CSIP_CLOSE_ACT, BTA_CSIP_W4_SEC}, - /* BTA_CSIP_GATT_OPEN_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_W4_SEC}, - /* BTA_CSIP_GATT_CLOSE_EVT */ {BTA_CSIP_GATT_CLOSE_ACT, BTA_CSIP_IDLE_ST}, - /* BTA_CSIP_GATT_OPEN_FAIL_ACT */ {BTA_CSIP_GATT_OPEN_FAIL_ACT, BTA_CSIP_IDLE_ST}, - /* BTA_CSIP_OPEN_CMPL_EVT */ {BTA_CSIP_OPEN_CMPL_ACT, BTA_CSIP_CONN_ST}, - /* BTA_CSIP_START_ENC_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_W4_SEC}, - /* BTA_CSIP_ENC_CMPL_EVT */ {BTA_CSIP_SEC_CMPL_ACT, BTA_CSIP_W4_CONN_ST}, -}; - -/* state table in connection state */ -const uint8_t bta_csip_st_connected[][BTA_CSIP_NUM_COLS] = { - /* Event Action Next state */ - /* BTA_CSIP_API_OPEN_EVT */ {BTA_CSIP_OPEN_ACT, BTA_CSIP_CONN_ST}, - /* BTA_CSIP_API_CLOSE_EVT */ {BTA_CSIP_CLOSE_ACT, BTA_CSIP_CONN_ST}, - /* BTA_CSIP_GATT_OPEN_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_CONN_ST}, - /* BTA_CSIP_GATT_CLOSE_EVT */ {BTA_CSIP_GATT_CLOSE_ACT, BTA_CSIP_IDLE_ST}, - /* BTA_CSIP_GATT_OPEN_FAIL_ACT */ {BTA_CSIP_GATT_OPEN_FAIL_ACT, BTA_CSIP_IDLE_ST}, - /* BTA_CSIP_OPEN_CMPL_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_CONN_ST}, - /* BTA_CSIP_START_ENC_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_CONN_ST}, - /* BTA_CSIP_ENC_CMPL_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_CONN_ST}, -}; - -/* state table in disconnecting state */ -const uint8_t bta_csip_st_disconnecting[][BTA_CSIP_NUM_COLS] = { - /* Event Action Next state */ - /* BTA_CSIP_API_OPEN_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_DISCONNECTING_ST}, - /* BTA_CSIP_API_CLOSE_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_DISCONNECTING_ST}, - /* BTA_CSIP_GATT_OPEN_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_DISCONNECTING_ST}, - /* BTA_CSIP_GATT_CLOSE_EVT */ {BTA_CSIP_GATT_CLOSE_ACT, BTA_CSIP_IDLE_ST}, - /* BTA_CSIP_GATT_OPEN_FAIL_ACT */ {BTA_CSIP_IGNORE, BTA_CSIP_DISCONNECTING_ST}, - /* BTA_CSIP_OPEN_CMPL_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_DISCONNECTING_ST}, - /* BTA_CSIP_START_ENC_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_DISCONNECTING_ST}, - /* BTA_CSIP_ENC_CMPL_EVT */ {BTA_CSIP_IGNORE, BTA_CSIP_DISCONNECTING_ST}, -}; - -/* type for state table */ -typedef const uint8_t (*tBTA_CSIP_ST_TBL)[BTA_CSIP_NUM_COLS]; - -/* state table */ -tBTA_CSIP_ST_TBL bta_csip_st_tbl[] = {bta_csip_st_idle, bta_csip_st_w4_conn, - bta_csip_st_w4_sec, bta_csip_st_connected, - bta_csip_st_disconnecting}; - -/******************************************************************************* - * - * Function bta_csip_sm_execute - * - * Description API to execute state operation. - * - * Returns void - * - ******************************************************************************/ -void bta_csip_sm_execute(tBTA_CSIP_DEV_CB* p_cb, uint16_t event, - tBTA_CSIP_REQ_DATA* p_data) { - tBTA_CSIP_ST_TBL state_table; - uint8_t action; - - if (!p_cb) { - APPL_TRACE_ERROR("%s: Device not found. Return.", __func__); - return; - } - - state_table = bta_csip_st_tbl[p_cb->state]; - - event &= 0xff; - - p_cb->state = state_table[event][BTA_CSIP_NEXT_STATE]; - APPL_TRACE_DEBUG("%s: Next State = %d(%s) event = %04x(%s)", __func__, - p_cb->state, bta_csip_state_code(p_cb->state), event, - bta_csip_evt_code(event)); - - action = state_table[event][BTA_CSIP_ACTION]; - APPL_TRACE_DEBUG("%s: action = %d", __func__, action); - if (action != BTA_CSIP_IGNORE) { - (*bta_csip_action[action])(p_cb, p_data); - } - -} - -/******************************************************************************* - * - * Function bta_csip_hdl_event - * - * Description CSIP client main event handling function. - * - * Returns void - * - ******************************************************************************/ -bool bta_csip_hdl_event(BT_HDR* p_msg) { - tBTA_CSIP_DEV_CB* dev_cb = NULL; - - APPL_TRACE_DEBUG("%s: Event: %04x", __func__, p_msg->event); - - switch (p_msg->event) { - case BTA_CSIP_API_ENABLE_EVT: - bta_csip_api_enable(((tBTA_CSIP_ENABLE *)p_msg)->p_cback); - break; - - case BTA_CSIP_API_DISABLE_EVT: - bta_csip_api_disable(); - break; - - case BTA_CSIP_DISC_CMPL_EVT: - bta_csip_gatt_disc_cmpl_act((tBTA_CSIP_DISC_SET *)p_msg); - break; - - case BTA_CSIP_SET_LOCK_VALUE_EVT: - bta_csip_process_set_lock_act(((tBTA_CSIP_LOCK_PARAMS*)p_msg)->lock_req); - break; - - default: - if (p_msg->event == BTA_CSIP_API_OPEN_EVT) { - RawAddress bd_addr = ((tBTA_CSIP_API_CONN *)p_msg)->bd_addr; - dev_cb = bta_csip_find_dev_cb_by_bda(bd_addr); - if (!dev_cb) { - dev_cb = bta_csip_create_dev_cb_for_bda(bd_addr); - APPL_TRACE_DEBUG("%s: Created Device CB for device: %s", - __func__, bd_addr.ToString().c_str()); - } - } else if (p_msg->event == BTA_CSIP_API_CLOSE_EVT) { - dev_cb = bta_csip_find_dev_cb_by_bda(((tBTA_CSIP_API_CONN *)p_msg)->bd_addr); - } - - bta_csip_sm_execute(dev_cb, p_msg->event, (tBTA_CSIP_REQ_DATA*)p_msg); - } - - return (true); - -} - -/******************************************************************************* - * - * Function bta_csip_evt_code - * - * Description returns event name in string format - * - * Returns string representation of event code - * - ******************************************************************************/ -static const char* bta_csip_evt_code(uint16_t evt_code) { - evt_code = (BTA_ID_GROUP << 8) | evt_code; - switch (evt_code) { - case BTA_CSIP_API_OPEN_EVT: - return "BTA_CSIP_API_OPEN_EVT"; - case BTA_CSIP_API_CLOSE_EVT: - return "BTA_CSIP_API_CLOSE_EVT"; - case BTA_CSIP_GATT_OPEN_EVT: - return "BTA_CSIP_GATT_OPEN_EVT"; - case BTA_CSIP_GATT_CLOSE_EVT: - return "BTA_CSIP_GATT_CLOSE_EVT"; - case BTA_CSIP_OPEN_FAIL_EVT: - return "BTA_CSIP_OPEN_FAIL_EVT"; - case BTA_CSIP_OPEN_CMPL_EVT: - return "BTA_CSIP_OPEN_CMPL_EVT"; - case BTA_CSIP_START_ENC_EVT: - return "BTA_CSIP_START_ENC_EVT"; - case BTA_CSIP_ENC_CMPL_EVT: - return "BTA_CSIP_ENC_CMPL_EVT"; - case BTA_CSIP_API_ENABLE_EVT: - return "BTA_CSIP_API_ENABLE_EVT"; - case BTA_CSIP_API_DISABLE_EVT: - return "BTA_CSIP_API_DISABLE_EVT"; - case BTA_CSIP_SET_LOCK_VALUE_EVT: - return "BTA_CSIP_SET_LOCK_VALUE_EVT"; - default: - return "Unknown CSIP event code"; - } -} - -/******************************************************************************* - * - * Function bta_csip_state_code - * - * Description returns state name in string format - * - * Returns string representation of connection state - * - ******************************************************************************/ -static const char* bta_csip_state_code(tBTA_CSIP_STATE state) { - switch (state) { - case BTA_CSIP_IDLE_ST: - return "BTA_CSIP_IDLE_ST"; - case BTA_CSIP_W4_CONN_ST: - return "BTA_CSIP_W4_CONN_ST"; - case BTA_CSIP_W4_SEC: - return "BTA_CSIP_W4_SEC"; - case BTA_CSIP_CONN_ST: - return "BTA_CSIP_CONN_ST"; - case BTA_CSIP_DISCONNECTING_ST: - return "BTA_CSIP_DISCONNECTING_ST"; - default: - return "Incorrect State"; - } -} - diff --git a/le_audio/system/bt/bta/csip/bta_csip_utils.cc b/le_audio/system/bt/bta/csip/bta_csip_utils.cc deleted file mode 100644 index b900c3abbf589ac28e25c228fe46d4aa11f264cb..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/csip/bta_csip_utils.cc +++ /dev/null @@ -1,1318 +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. - * - ******************************************************************************/ - - -/****************************************************************************** - * - * This file contains the CSIP Client supporting functions - * - ******************************************************************************/ - -#include -#include -#include - -#include - -#include "bta_csip_api.h" -#include "bta_csip_int.h" -#include "bta_gatt_queue.h" - -#include "osi/include/config.h" -#include "btif/include/btif_config.h" -#include "stack/crypto_toolbox/crypto_toolbox.h" - -/* CSIS Characteristic descriptors handles */ -#define CSIP_CCCD_UUID_VAL 0x2902 -Uuid CSIP_CCCD_UUID = Uuid::From16Bit(CSIP_CCCD_UUID_VAL); - -/******************************************************************************* - * - * Function bta_csip_validate_set_params - * - * Description Validates if set id and its members are valid - * - * Returns bool. true - if details are valid otherwise false. - * - ******************************************************************************/ -bool bta_csip_validate_set_params(tBTA_SET_LOCK_PARAMS* lock_req) { - std::vector *csets = &bta_csip_cb.csets; - tBTA_CSIP_CSET cset; - bool is_valid_set = false; - - std::vector::iterator itr; - for (itr = csets->begin(); itr != csets->end(); ++itr) { - if (lock_req->set_id == itr->set_id) { - cset = *itr; - is_valid_set = true; - break; - } - } - - if (!is_valid_set) { - LOG(ERROR) << __func__ << ": Invalid Set ID = " << +lock_req->set_id; - //TODO: Give Invalid parameters callback - return (false); - } - - std::vector req_members = lock_req->members_addr; - // TODO: if requested set members size = 0, return true - if ((int)lock_req->members_addr.size() == 0) { - LOG(INFO) << __func__<< " Lock of All Set Memebers is requested"; - return (true); - } - - std::vector set_members = cset.set_members; - int members_matched = 0; - for (int i = 0; i < (int)req_members.size(); i++) { - for (int j = 0; j < (int)set_members.size(); j++) { - if (req_members[i] == set_members[j]) { - members_matched++; - break; - } - } - } - LOG(INFO) << "set members matched count = " << +members_matched; //debug - if (members_matched != (int)req_members.size()) { - LOG(ERROR) << __func__ << " Incorrect Set members provided"; - return (false); - } - - return (true); -} - -/******************************************************************************* - * - * Function bta_csip_is_valid_lock_request - * - * Description Validates lock request parameters received - * - * Returns bool. true - if details are valid otherwise false. - * - ******************************************************************************/ -bool bta_csip_is_valid_lock_request(tBTA_SET_LOCK_PARAMS* lock_req) { - // validate if correct lock value is provided - if (lock_req->lock_value != UNLOCK_VALUE && lock_req->lock_value != LOCK_VALUE) { - LOG(ERROR) << __func__ << ": Invalid Lock Value."; - return (false); - } - - // validate set id - if (!bta_csip_validate_set_params(lock_req)) { - LOG(INFO) << __func__ << " Invalid params"; - return (false); - } - - return (true); -} - -/******************************************************************************* - * - * Function bta_csip_get_cset_cb - * - * Description Finds coordinated set control block by set_id - * - * Returns tBTA_CSET_CB. NULL - if set is not found. - * - ******************************************************************************/ -tBTA_CSET_CB* bta_csip_get_cset_cb_by_id (uint8_t set_id) { - int i; - tBTA_CSET_CB* cset_cb = &bta_csip_cb.csets_cb[0]; - - for (i = 0; i < BTA_MAX_SUPPORTED_SETS; i++, cset_cb++) { - if ((cset_cb->in_use) && (cset_cb->set_id == set_id)) { - return (cset_cb); - } - } - - /* no match found */ - return (NULL); -} - -/******************************************************************************* - * - * Function bta_csip_get_cset_cb - * - * Description Creates new coordinated set control block with next available - * set id. - * - * Returns tBTA_CSET_CB. NULL - if no resources are available for set. - * - ******************************************************************************/ -tBTA_CSET_CB* bta_csip_get_cset_cb () { - int i; - tBTA_CSET_CB* cset_cb = &bta_csip_cb.csets_cb[0]; - - for (i = 0; i < BTA_MAX_SUPPORTED_SETS; i++, cset_cb++) { - if (!cset_cb->in_use) { - cset_cb->set_id = i; - cset_cb->in_use = true; - return (cset_cb); - } - } - - LOG(ERROR) << __func__ << " No resource available for Coordinated set"; - return (NULL); -} - -/******************************************************************************** - * - * Function bta_csip_is_app_reg - * - * Description Utility function to check if app_id is valid and registered. - * - * Returns true - if reistered. - * false - if invalid app id or its not registered. - * - *******************************************************************************/ -bool bta_csip_is_app_reg(uint8_t app_id) { - if (app_id >= BTA_CSIP_MAX_SUPPORTED_APPS) { - return (false); - } - - if (bta_csip_cb.app_rcb[app_id].in_use) { - return (true); - } - - return (false); -} - -/******************************************************************************** - * - * Function bta_csip_get_rcb - * - * Description Utility function to check if app_id is valid and registered. - * - * Returns registration control block. NULL if not in use. - * - *******************************************************************************/ -tBTA_CSIP_RCB* bta_csip_get_rcb (uint8_t app_id) { - if (app_id >= BTA_CSIP_MAX_SUPPORTED_APPS) { - return (NULL); - } - - if (bta_csip_cb.app_rcb[app_id].in_use) { - return (&bta_csip_cb.app_rcb[app_id]); - } - - return (NULL); -} - -/******************************************************************************* - * - * Function bta_csip_get_coordinated_set - * - * Description Creates new coordinated set control block - * - * Returns tBTA_CSIP_CSET for valid set_id. - * Empty set with INVALID_SET_ID if not found. - * - ******************************************************************************/ -tBTA_CSIP_CSET bta_csip_get_coordinated_set (uint8_t set_id) { - for (tBTA_CSIP_CSET cset: bta_csip_cb.csets) { - if (cset.set_id == set_id) { - return cset; - } - } - - LOG(ERROR) << __func__ << "Coordinated set not found for set_id: " << +set_id; - tBTA_CSIP_CSET cset = {.set_id = INVALID_SET_ID, - .size = 0 - }; - return cset; - } - -/****************************************************************************** - * - * Function bta_csip_update_set_member - * - * Description Updates set member in the given set. - * - * Returns bool (true, if added successfully. Otherwise, false.) - * - ******************************************************************************/ -bool bta_csip_update_set_member (uint8_t set_id, RawAddress addr) { - for (tBTA_CSIP_CSET& cset: bta_csip_cb.csets) { - if (cset.set_id == set_id) { - if (cset.set_members.size() == cset.size) { - LOG(ERROR) << __func__ << " All Set members already discovered."; - return false; - } - cset.set_members.push_back(addr); - return true; - } - } - - LOG(ERROR) << __func__ << "Coordinated set not found for set_id: " << +set_id; - return false; -} - -/******************************************************************************* - * - * Function bta_csip_remove_set_member - * - * Description Removes set member from given coordinated set after unpairing. - * If its the last set member in set, coordinated set is deleted. - * - * Returns void - * - ******************************************************************************/ -void bta_csip_remove_set_member (RawAddress addr) { - LOG(INFO) << __func__ << " Device = " << addr.ToString(); - bool is_device_found = false; - - btif_config_remove(addr.ToString().c_str(), "DGroup"); - tBTA_CSIP_DEV_CB* p_cb = bta_csip_find_dev_cb_by_bda(addr); - if (!p_cb) { - APPL_TRACE_DEBUG("%s: Set Member not found", __func__); - return; - } - - tBTA_CSIS_SRVC_INFO* srvc = &p_cb->csis_srvc[0]; - for (int i = 0; i < MAX_SUPPORTED_SETS_PER_DEVICE && !is_device_found; i++, srvc++) { - if (!srvc->in_use) continue; - for (tBTA_CSIP_CSET& cset: bta_csip_cb.csets) { - if (cset.set_id == srvc->set_id) { - //std::remove(cset.set_members.begin(), cset.set_members.end(), addr); - cset.set_members.erase( - std::remove_if(cset.set_members.begin(), cset.set_members.end(), - [&](RawAddress const & bdaddr) { - return bdaddr == addr; - }), - cset.set_members.end()); - is_device_found = true; - LOG(INFO) << __func__ << " Size = " << +(int)cset.set_members.size(); - if (cset.set_members.empty()) { - tBTA_CSET_CB* cset_cb = bta_csip_get_cset_cb_by_id(cset.set_id); - if (cset_cb) { - LOG(INFO) << __func__ << " Invalidating set. Last member unpaired."; - cset_cb->in_use = false; - cset_cb->set_id = INVALID_SET_ID; - cset.set_members.clear(); - bta_csip_cb.csets.erase( - std::remove_if(bta_csip_cb.csets.begin(), - bta_csip_cb.csets.end(), [&](tBTA_CSIP_CSET& cs) { - return cs.set_id == srvc->set_id; - }), - bta_csip_cb.csets.end()); - } - } - break; - } - } - } - - bta_csip_cb.dev_cb.erase( - std::remove_if(bta_csip_cb.dev_cb.begin(), bta_csip_cb.dev_cb.end(), - [&](tBTA_CSIP_DEV_CB const &dev_cb) { - return dev_cb.addr == addr; - }), - bta_csip_cb.dev_cb.end()); -} - -/******************************************************************************* - * - * Function bta_csip_get_or_create_cset - * - * Description API used to create Coordinated Set Control block. - * - * Returns void - * - ******************************************************************************/ -tBTA_CSIP_CSET* bta_csip_get_or_create_cset (uint8_t set_id, bool existing) { - /*std::find_if(bta_csip_cb.csets.begin(), bta_csip_cb.csets.end(), - [&set_id](const tBTA_CSIP_CSET& set) { - return set.set_id == set_id; - });*/ - - for (tBTA_CSIP_CSET& cset: bta_csip_cb.csets) { - if (cset.set_id == set_id) { - return &cset; - } - } - - if (existing) return NULL; - - /* Create a new set with invalid set_id*/ - tBTA_CSIP_CSET cset = {.set_id = INVALID_SET_ID, - .size = 0 - }; - bta_csip_cb.csets.push_back(cset); - return &bta_csip_cb.csets.back(); -} - -/******************************************************************************* - * - * Function bta_csip_find_set_id_by_sirk - * - * Description Finds Coordinated set control block by sirk - * - * Returns set_id if SIRK is found - * otherwise, INVALID_SET_ID - * - ******************************************************************************/ -uint8_t bta_csip_find_set_id_by_sirk (uint8_t* sirk) { - int i = 0; - tBTA_CSET_CB* csets = &bta_csip_cb.csets_cb[0]; - - for (i = 0; i < BTA_MAX_SUPPORTED_SETS; i++, csets++) { - if (csets->in_use) { - // compare SIRK's - if (!memcmp(sirk, csets->sirk, SIRK_SIZE)) { - return csets->set_id; - } - } - } - - return INVALID_SET_ID; -} - - -/******************************************************************************* - * - * Function bta_csip_get_cset_cb - * - * Description Finds coordinated set control block by set_id - * - * Returns tBTA_CSET_CB. NULL - if set is not found. - * - ******************************************************************************/ -tBTA_CSIS_SRVC_INFO* bta_csip_get_csis_instance(tBTA_CSIP_DEV_CB* dev_cb, - uint8_t set_id) { - int i = 0; - - if (!dev_cb) return NULL; - - tBTA_CSIS_SRVC_INFO* srvc = &dev_cb->csis_srvc[0]; - - for (i = 0; i < MAX_SUPPORTED_SETS_PER_DEVICE; i++, srvc++) { - srvc = &dev_cb->csis_srvc[i]; - if ((srvc->in_use) && (srvc->set_id == set_id)) { - return (srvc); - } - } - - /* no match found */ - return (NULL); -} - -/******************************************************************************* - * - * Function bta_csip_get_csis_service_cb - * - * Description Creates new coordinated set control block for a given device - * - * Returns tBTA_CSET_CB. NULL if no resources available. - * - ******************************************************************************/ -tBTA_CSIS_SRVC_INFO* bta_csip_get_csis_service_cb(tBTA_CSIP_DEV_CB* dev_cb) { - int i = 0; - tBTA_CSIS_SRVC_INFO* srvc = &dev_cb->csis_srvc[0]; - - for (i = 0; i < MAX_SUPPORTED_SETS_PER_DEVICE; i++, srvc++) { - if (!srvc->in_use) { - srvc->in_use = true; - return srvc; - } - } - - /* no match found */ - return (NULL); -} - -/******************************************************************************* - * - * Function bta_csip_is_csis_supported - * - * Description checks if remote device supports coordinated set - * - * Returns true if supported, otherwise false. - * - ******************************************************************************/ -bool bta_csip_is_csis_supported(tBTA_CSIP_DEV_CB* dev_cb) { - int i = 0; - tBTA_CSIS_SRVC_INFO* srvc = &dev_cb->csis_srvc[0]; - - for (i = 0; i < MAX_SUPPORTED_SETS_PER_DEVICE; i++, srvc++) { - if (srvc->in_use) { - return true; - } - } - - /* no csis instance found */ - return (false); -} - -/******************************************************************************* - * - * Function bta_csip_get_csis_service_by_handle - * - * Description Gives CSIS Service Control block by service handle. - * - * Returns CSIS Service control block. Null if not found. - * - ******************************************************************************/ -tBTA_CSIS_SRVC_INFO* bta_csip_get_csis_service_by_handle( - tBTA_CSIP_DEV_CB* dev_cb, uint16_t service_handle) { - int i = 0; - tBTA_CSIS_SRVC_INFO* srvc = &dev_cb->csis_srvc[0]; - - for (i = 0; i < MAX_SUPPORTED_SETS_PER_DEVICE; i++, srvc++) { - if (srvc->in_use && srvc->service_handle == service_handle) { - return srvc; - } - } - - /* no match found */ - return (NULL); -} - -/******************************************************************************* - * - * Function bta_csip_find_csis_srvc_by_lock_handle - * - * Description Gives CSIS Service Control block by lock handle. - * - * Returns CSIS Service control block. Null if not found. - * - ******************************************************************************/ -tBTA_CSIS_SRVC_INFO* bta_csip_find_csis_srvc_by_lock_handle( - tBTA_CSIP_DEV_CB* dev_cb, uint16_t lock_handle) { - int i = 0; - tBTA_CSIS_SRVC_INFO* srvc = &dev_cb->csis_srvc[0]; - - for (i = 0; i < MAX_SUPPORTED_SETS_PER_DEVICE; i++, srvc++) { - if (srvc->in_use && srvc->lock_handle == lock_handle) { - return srvc; - } - } - - /* no match found */ - return (NULL); - -} - -/******************************************************************************* - * - * Function bta_csip_is_locked_by_other_apps - * - * Description Checks if set is locked by app other than mentioned one. - * - * Returns true, if locked by other app otherwise false. - * - ******************************************************************************/ -bool bta_csip_is_locked_by_other_apps(tBTA_CSIS_SRVC_INFO* srvc, uint8_t app_id) { - std::vector &lock_applist = srvc->lock_applist; - - for (auto& it : lock_applist) { - if (it != app_id) { - return (true); - } - } - - return (false); -} - -/******************************************************************************* - * - * Function bta_csip_form_set_lock_order - * - * Description Forms order of set members as per rank. - * - * Returns Ordered Set members. - * - ******************************************************************************/ -std::vector bta_csip_form_set_lock_order(tBTA_CSET_CB* cset_cb) { - std::vector ordered_members; - std::vector req_members = cset_cb->cur_lock_req.members_addr; - std::map lock_order_map; - - for (int i = 0; i < (int)req_members.size(); i++) { - // get device control block and corresponding csis service details - tBTA_CSIP_DEV_CB* dev_cb = bta_csip_find_dev_cb_by_bda(req_members[i]); - // null checks required - tBTA_CSIS_SRVC_INFO* srvc = - bta_csip_get_csis_instance(dev_cb, cset_cb->cur_lock_req.set_id); - if (srvc) { - lock_order_map.insert({srvc->rank, req_members[i]}); - } - } - - for (auto itr: lock_order_map) { - ordered_members.push_back(itr.second); - } - - return ordered_members; -} - -/******************************************************************************* - * - * Function bta_csip_arrange_set_members_by_order - * - * Description Forms order of set members for LOCK/UNLOCK request. - * - * Returns Ordered set members in vector. - * - ******************************************************************************/ -std::vector bta_csip_arrange_set_members_by_order( - uint8_t set_id, std::vector& req_sm, bool ascending) { - LOG(INFO) << __func__; - - std::vector ordered_req_sm; - std::vector set_members = - bta_csip_get_set_member_by_order(set_id, ascending); - - // Check if all set members are requested - if ((uint8_t)req_sm.size() == 0) { - LOG(INFO) << __func__ << " original size = " << +set_members.size(); - return set_members; - } - - /* LOCK Request Order*/ - for (int i = 0; i < (int)set_members.size(); i++) { - for (int j = 0; j < (int)req_sm.size(); j++) { - if (set_members[i] == req_sm[j]) { - ordered_req_sm.push_back(set_members[i]); - if (ordered_req_sm.size() == req_sm.size()) { - return ordered_req_sm; - } - } - } - } - - return {}; -} - -/******************************************************************************* - * - * Function bta_csip_arrange_set_members_by_order - * - * Description Forms order of set members for LOCK/UNLOCK request. - * - * Returns Ordered set members in vector. - * - ******************************************************************************/ -std::vector bta_csip_get_set_member_by_order(uint8_t set_id, - bool ascending) { - std::vector ordered_members; - - tBTA_CSET_CB* cset_cb = &bta_csip_cb.csets_cb[set_id]; - if (!cset_cb->in_use) { - LOG(ERROR) << __func__ << " Invalid Set for for Set ID: " << +set_id; - return {}; - } - - if (ascending) { - for (auto itr: cset_cb->ordered_members) { - ordered_members.push_back(itr.second); - } - } else { - for (auto i = cset_cb->ordered_members.rbegin(); - i != cset_cb->ordered_members.rend(); ++i) { - ordered_members.push_back(i->second); - } - } - - return ordered_members; -} - - -/******************************************************************************* - * - * Function bta_csip_is_member_locked_by_app - * - * Description checks if application (app_id) has locked given set. - * - * Returns void. - ******************************************************************************/ -bool bta_csip_is_member_locked_by_app (uint8_t app_id, tBTA_CSIS_SRVC_INFO* srvc) { - std::vector& lock_applist = srvc->lock_applist; - - auto it = std::find(lock_applist.begin(), lock_applist.end(), app_id); - if (it != lock_applist.end()) { - LOG(INFO) << __func__ << " App Id found in app list"; - return true; - } - - LOG(INFO) << __func__ << " App Id not found in app list"; - return false; -} - -/******************************************************************************* - * - * Function bta_csip_handle_unresponsive_sm_res - * - * Description sends lock response to earlier requesting app. - * - * Returns void. - ******************************************************************************/ -void bta_csip_handle_unresponsive_sm_res(tBTA_CSIS_SRVC_INFO* srvc, - tGATT_STATUS status) { - LOG(INFO) << __func__ << " Response from unresponsive remote " << srvc->bd_addr.ToString() - << " status: " << +status; - std::vector& unres_applist = srvc->unrsp_applist; - - if (status == GATT_SUCCESS) { - srvc->lock = LOCK_VALUE; - for (auto& it : unres_applist) { - LOG(INFO) << __func__ << " Sending GATT_SUCCESS callback to app: " << +it; - std::vector sm = {srvc->bd_addr}; - tBTA_LOCK_STATUS_CHANGED res = {.app_id = it, .set_id = srvc->set_id, - .value = 0x02, .addr = sm}; - bta_csip_send_lock_req_cmpl_cb(res); - // Add app id to the lock applist - srvc->lock_applist.push_back(it); - } - } - - unres_applist.clear(); -} - -/******************************************************************************* - * - * Function bta_csip_get_next_lock_request - * - * Description Schedules next pending lock request for the given set. - * - * Returns void. - ******************************************************************************/ -void bta_csip_get_next_lock_request(tBTA_CSET_CB* cset_cb) { - tBTA_SET_LOCK_PARAMS lock_req_params; - std::queue& lock_req_queue = cset_cb->lock_req_queue; - - if (lock_req_queue.empty()) { - LOG(INFO) << " No pending Lock Request for Set: " << +cset_cb->set_id; - cset_cb->request_in_progress = false; - return; - } - - lock_req_params = lock_req_queue.front(); - lock_req_queue.pop(); - - bta_csip_form_lock_request(lock_req_params, cset_cb); -} - -/******************************************************************************* - * - * Function bta_csip_find_dev_cb_by_bda - * - * Description Utility function find a device control block by BD address. - * - * Returns tBTA_CSIP_DEV_CB - device control block for a given remote. - * nullptr, if device control block is not present. - ******************************************************************************/ -tBTA_CSIP_DEV_CB* bta_csip_find_dev_cb_by_bda(const RawAddress& bda) { - /*auto iter = std::find_if(bta_csip_cb.dev_cb.begin(), bta_csip_cb.dev_cb.end(), - [&bda](const tBTA_CSIP_DEV_CB& device) { - return device.addr == bda; - }); - - return (iter == bta_csip_cb.dev_cb.end()) ? nullptr : &(*iter);*/ - for (tBTA_CSIP_DEV_CB& p_cb: bta_csip_cb.dev_cb) { - if (p_cb.addr == bda) { - return &p_cb; - } - } - - return NULL; -} - -/******************************************************************************* - * - * Function bta_csip_get_dev_cb_by_cid - * - * Description Utility function find a device control block by gatt conn id. - * - * Returns tBTA_CSIP_DEV_CB (device control block for a given remote.) - ******************************************************************************/ -tBTA_CSIP_DEV_CB* bta_csip_get_dev_cb_by_cid(uint16_t conn_id) { - auto iter = std::find_if(bta_csip_cb.dev_cb.begin(), bta_csip_cb.dev_cb.end(), - [&conn_id](const tBTA_CSIP_DEV_CB& device) { - return device.conn_id == conn_id; - }); - - return (iter == bta_csip_cb.dev_cb.end()) ? nullptr : &(*iter); -} - -/******************************************************************************* - * - * Function bta_csip_create_dev_cb_for_bda - * - * Description Utility function find a device control block by BD address. - * - * Returns tBTA_CSIP_DEV_CB (device control block for a given remote. - ******************************************************************************/ -tBTA_CSIP_DEV_CB* bta_csip_create_dev_cb_for_bda(const RawAddress& bda) { - tBTA_CSIP_DEV_CB p_dev_cb = {}; - p_dev_cb.addr = bda; - p_dev_cb.in_use = true; - - bta_csip_cb.dev_cb.push_back(p_dev_cb); - - return &bta_csip_cb.dev_cb.back(); -} - -/************************************************************************************ - * - * Function bta_csip_get_cccd_handle - * - * Description Utility function to fetch cccd handle of a given characteristic. - * - * Returns handle of cccd. 0 if not found. - ************************************************************************************/ -uint16_t bta_csip_get_cccd_handle(uint16_t conn_id, uint16_t char_handle) { - const gatt::Characteristic* p_char = - BTA_GATTC_GetCharacteristic(conn_id, char_handle); - if (!p_char) { - LOG(WARNING) << __func__ << ": Characteristic not found: " << char_handle; - return 0; - } - - for (const gatt::Descriptor& desc : p_char->descriptors) { - if (desc.uuid == CSIP_CCCD_UUID) { - LOG(INFO) << __func__ << " desc handle = " << +desc.handle; - return desc.handle; - } - } - - return 0; -} - -/************************************************************************************ - * - * Function bta_csip_add_app_to_applist - * - * Description Utility function adds app to connection applist of a - * given device control block. - * - * Returns void - ************************************************************************************/ -void bta_csip_add_app_to_applist(tBTA_CSIP_DEV_CB* p_cb, uint8_t app_id) { - if (p_cb && !bta_csip_is_app_from_applist(p_cb, app_id)) { - LOG(INFO) << __func__ << ": adding app(" << +app_id - << ") to connection applist of " << p_cb->addr; - p_cb->conn_applist.push_back(app_id); - } -} - -/************************************************************************************ - * - * Function bta_csip_is_app_from_applist - * - * Description Utility function checks if app is from connection applist of a - * given device control block. - * - * Returns true if app has already sent connect request for CSIP. - ************************************************************************************/ -bool bta_csip_is_app_from_applist(tBTA_CSIP_DEV_CB* p_cb, uint8_t app_id) { - for (auto i: p_cb->conn_applist) { - if (i == app_id) { - return (true); - } - } - - return (false); -} - -/************************************************************************************ - * - * Function bta_csip_remove_app_from_conn_list - * - * Description Utility function to remove application from connection applist of - * given device control block - * - * Returns void - ************************************************************************************/ -void bta_csip_remove_app_from_conn_list(tBTA_CSIP_DEV_CB* p_cb, uint8_t app_id) { - p_cb->conn_applist.erase( - std::remove(p_cb->conn_applist.begin(), p_cb->conn_applist.end(), app_id), - p_cb->conn_applist.end()); -} - -/************************************************************************************ - * - * Function bta_csip_send_conn_state_changed_cb - * - * Description Utility function to send connection state changed to all - * registered application in connection app list. - * - * Returns void - ************************************************************************************/ -void bta_csip_send_conn_state_changed_cb(tBTA_CSIP_DEV_CB* p_cb, - uint8_t state, uint8_t status) { - if (!p_cb) { - LOG(ERROR) << __func__ << ": Device CB for " << p_cb->addr << " not found"; - return; - } - - // send connection state change to all apps in conn_applist - for (auto i: p_cb->conn_applist) { - tBTA_CSIP_CONN_STATE_CHANGED conn_cb_params = { - .app_id = i, - .addr = p_cb->addr, - .state = state, - .status =status - }; - if (bta_csip_cb.app_rcb[i].p_cback) { - (*bta_csip_cb.app_rcb[i].p_cback) - (BTA_CSIP_CONN_STATE_CHG_EVT, (tBTA_CSIP_DATA *)&conn_cb_params); - } - } -} - -/************************************************************************************ - * - * Function bta_csip_send_conn_state_changed_cb - * - * Description Utility function to send connection state changed to requesting - * registered application from connection applist. - * - * Returns void - ************************************************************************************/ -void bta_csip_send_conn_state_changed_cb (tBTA_CSIP_DEV_CB* p_cb, uint8_t app_id, - uint8_t state, uint8_t status) { - - tBTA_CSIP_CONN_STATE_CHANGED conn_cb_params = { - .app_id = app_id, - .addr = p_cb->addr, - .state = state, - .status =status - }; - - // send connection state change to the requested App - if (bta_csip_cb.app_rcb[app_id].p_cback) { - (*bta_csip_cb.app_rcb[app_id].p_cback) - (BTA_CSIP_CONN_STATE_CHG_EVT, (tBTA_CSIP_DATA *)&conn_cb_params); - } - -} - -/************************************************************************************ - * - * Function bta_csip_process_completed_lock_req - * - * Description Utility function to send lock state changed to requesting - * registered application. - * - * Returns void - ************************************************************************************/ -void bta_csip_send_lock_req_cmpl_cb (tBTA_LOCK_STATUS_CHANGED response) { - if (response.app_id >= BTA_CSIP_MAX_SUPPORTED_APPS || - !bta_csip_cb.app_rcb[response.app_id].in_use) { - LOG(ERROR) << __func__ << "Invalid or unregistered application: " << +response.app_id; - return; - } - - if (bta_csip_cb.app_rcb[response.app_id].p_cback) { - (*bta_csip_cb.app_rcb[response.app_id].p_cback) - (BTA_CSIP_LOCK_STATUS_CHANGED_EVT, (tBTA_CSIP_DATA *)&response); - } -} - -/************************************************************************************ - * - * Function bta_csip_write_cccd - * - * Description API used to write required characteristic descriptor. - * - * Returns void - ************************************************************************************/ -void bta_csip_write_cccd (tBTA_CSIP_DEV_CB* p_cb, uint16_t char_handle, - uint16_t cccd_handle) { - LOG(INFO) << __func__; - // Register for LOCK - if (BTA_GATTC_RegisterForNotifications( - bta_csip_cb.gatt_if, p_cb->addr, char_handle)) { - LOG(ERROR) << __func__ - << " Notification Registration failed for char handle: " << +char_handle; - return; - } - - LOG(INFO) << __func__ << " notification registration successful. handle: " << +char_handle; - std::vector value(2); - uint8_t* ptr = value.data(); - UINT16_TO_STREAM(ptr, GATT_CHAR_CLIENT_CONFIG_NOTIFICATION); - BtaGattQueue::WriteDescriptor(p_cb->conn_id, cccd_handle, value, - GATT_WRITE, nullptr, nullptr); -} - -/************************************************************************************ - * - * Function bta_csip_load_coordinated_sets_from_storage - * - * Description API used to load coordinated sets from storage on BT ON. - * - * Returns void - ************************************************************************************/ -void bta_csip_load_coordinated_sets_from_storage () { - LOG(INFO) << __func__; - - static const char* CONFIG_FILE_PATH = "/data/misc/bluedroid/bt_config.conf"; - config_t* config = config_new(CONFIG_FILE_PATH); - if (!config) { - LOG(INFO) << __func__ << " file "<< CONFIG_FILE_PATH << " not found"; - return; - } - - const config_section_node_t* snode = config_section_begin(config); - while (snode != config_section_end(config)) { - - const char* name = config_section_name(snode); - if (!RawAddress::IsValidAddress(name)) { - snode = config_section_next(snode); - continue; - } - - const char* key = "DGroup"; - const char* coordinated_sets = config_get_string(config, name, key, ""); - if (!strcmp(coordinated_sets, "")) { - LOG(INFO) << __func__ << " doesnt support cooedinated set."; - snode = config_section_next(snode); - continue; - } - - RawAddress bdaddr; - RawAddress::FromString(name, bdaddr); - tBTA_CSIP_DEV_CB* dev_cb = bta_csip_find_dev_cb_by_bda(bdaddr); - if (!dev_cb) { - dev_cb = bta_csip_create_dev_cb_for_bda(bdaddr); - } - - char *next = NULL; - char *csets = strdup(coordinated_sets); - /* Set Level parsing*/ - char *set_details = strtok_r(csets, " ", &next); - - do { - tBTA_CSIP_CSET *cset = NULL; - uint8_t set_id = INVALID_SET_ID, size = 0, rank = 0; - uint16_t srvc_handle = 0; - bluetooth::Uuid uuid; - uint8_t sirk[SIRK_SIZE] = {}; - bool lock_support = false; - - char *part; - char *posn; - /* separating properties of set*/ - part = strtok_r(set_details, "~", &posn); - - while (part != NULL) - { - char *ptr = NULL; - /* Decode property type and its value*/ - char *prop_details = strtok_r(part, ":", &ptr); - - if (prop_details != NULL) { - char* prop_val = strtok_r(NULL, ":", &ptr); - if (prop_val) { - if (!strcmp(prop_details, "SET_ID")) { - set_id = (uint8_t)atoi(prop_val); - cset = bta_csip_get_or_create_cset(set_id, true); - if (!cset) LOG(INFO) << __func__ << " got cset empty"; - else LOG(INFO) << "valid " << +cset->set_id; - } else if (!strcmp(prop_details, "SIZE")) { - size = (uint8_t)atoi(prop_val); - } else if (!strcmp(prop_details, "SIRK")) { - hex_string_to_byte_arr(prop_val, sirk, SIRK_SIZE * 2); - } else if (!strcmp(prop_details, "INCLUDING_SRVC")) { - uuid = Uuid::FromString(prop_val); - } else if (!strcmp(prop_details, "LOCK_SUPPORT")) { - if (!strcmp(prop_val, "true")) lock_support = true; - } else if (!strcmp(prop_details, "RANK")) { - rank = (uint8_t)atoi(prop_val); - } else if (!strcmp(prop_details, "SRVC_HANDLE")) { - srvc_handle = (uint16_t)atoi(prop_val); - } - } - } - - part = strtok_r(NULL, "~", &posn); - } - - if (set_id < BTA_MAX_SUPPORTED_SETS) { - if (!cset) { - // Create new coordinated set insatnce and device to it - cset = bta_csip_get_or_create_cset(set_id, false); - cset->set_id = set_id; - cset->size = size; - cset->p_srvc_uuid = uuid; - cset->total_discovered = 1; - cset->set_members.push_back(bdaddr); - - // create coordinated set control block - tBTA_CSET_CB* cset_cb = &bta_csip_cb.csets_cb[set_id]; - cset_cb->set_id = set_id; - cset_cb->in_use = true; - memcpy(cset_cb->sirk, sirk, SIRK_SIZE); - if (rank != 0) { - cset_cb->ordered_members.insert({rank, bdaddr}); - } - - } else { - //LOG(INFO) << "Existing set = " << +cset->set_id; - cset->total_discovered++; - cset->set_members.push_back(bdaddr); - - tBTA_CSET_CB* cset_cb = &bta_csip_cb.csets_cb[set_id]; - if (rank != 0) { - cset_cb->ordered_members.insert({rank, bdaddr}); - } - } - - // assign service properties - set_id and bd_addr - tBTA_CSIS_SRVC_INFO *srvc = bta_csip_get_csis_service_cb(dev_cb); - if (srvc) { - srvc->set_id = set_id; - srvc->bd_addr = bdaddr; - srvc->size = size; - srvc->rank = rank; - srvc->service_handle = srvc_handle; - memcpy(srvc->sirk, sirk, SIRK_SIZE); - } - } - } while ((set_details = strtok_r(NULL, " ", &next)) != NULL); - - snode = config_section_next(snode); - } - - /*LOG(INFO) << "------------------DEBUG----------------------------"; - LOG(INFO) << "printing all loaded coordinated sets"; - for (int i = 0; i < (int)bta_csip_cb.csets.size(); i++) { - tBTA_CSIP_CSET set = bta_csip_cb.csets[i]; - LOG(INFO) << " Set ID = " << +set.set_id - << " Size = " << +set.size - << " total discovered = " << +set.total_discovered; - for (int j = 0; j < (int)set.set_members.size(); j++) { - LOG(INFO) << " Member (" << +(j+1) <<") = " << set.set_members[j].ToString(); - } - }*/ -} - -/************************************************************************************ - * - * Function bta_csip_preserve_cset - * - * Description function used to preserve coordinated set details to storage. - * - * Returns void - ************************************************************************************/ -void bta_csip_preserve_cset (tBTA_CSIS_SRVC_INFO* srvc) { - tBTA_CSIP_DEV_CB* p_cb = bta_csip_find_dev_cb_by_bda(srvc->bd_addr); - - if (!p_cb) { - LOG(ERROR) << " Device cb record not found for " << srvc->bd_addr; - return; - } - - std::string& set_info = p_cb->set_info; - if (set_info.size() > 0) { - set_info += " "; - } - - set_info += "SET_ID:" + std::to_string(srvc->set_id); - - if (srvc->size_handle) { - set_info += "~SIZE:" + std::to_string(srvc->size); - } - - char sirk[SIRK_SIZE * 2 + 1] = {0}; - byte_arr_to_hex_string(srvc->sirk, sirk, SIRK_SIZE); - set_info += "~SIRK:" + std::string(sirk); - - if (!srvc->including_srvc_uuid.IsEmpty()) { - set_info += "~INCLUDING_SRVC:" + srvc->including_srvc_uuid.ToString(); - } - - if (srvc->lock_handle) { - set_info += "~LOCK_SUPPORT:" + std::string((srvc->lock_handle ? "true" : "false")); - } - - if (srvc->rank_handle) { - set_info += "~RANK:" + std::to_string(srvc->rank); - } - - set_info += "~SRVC_HANDLE:" + std::to_string(srvc->service_handle); - - LOG(INFO) << __func__ << " " << set_info; - - btif_config_set_str(p_cb->addr.ToString().c_str(), - "DGroup", set_info.c_str()); -} - -/************************************************************************************ - * - * Function bta_csip_get_salt - * - * Description function s1: Used to compute SALT. - * - * Returns Octet16 (cipher - SALT) - ************************************************************************************/ -Octet16 bta_csip_get_salt() { - Octet16 salt = {}; - Octet16 zero = {}; - uint8_t SIRKenc[] = {0x53, 0x49, 0x52, 0x4B, 0x65, 0x6E, 0x63}; - - salt = bta_csip_get_aes_cmac_result(zero, SIRKenc, 7); - - return salt; -} - -/************************************************************************************ - * - * Function bta_csip_compute_T - * - * Description First step of k1 function. Used to compute T from SALT and K. - * - * Returns Octet16 (cipher - T) - ************************************************************************************/ -Octet16 bta_csip_compute_T(Octet16 salt, Octet16 K) { - Octet16 T = {}; - - T = bta_csip_get_aes_cmac_result(salt, K); - - return T; -} - -/************************************************************************************ - * - * Function bta_csip_get_aes_cmac_result - * - * Description Second step of k1 function. Used to compute k1 from T and "csis". - * - * Returns Octet16 (cipher - k1) - ************************************************************************************/ -Octet16 bta_csip_compute_k1(Octet16 T) { - Octet16 k1 = {}; - uint8_t csis[] = {0x63,0x73,0x69,0x73}; - - k1 = bta_csip_get_aes_cmac_result(T, csis, 4); - - return k1; -} - -/************************************************************************************ - * - * Function bta_csip_get_aes_cmac_result - * - * Description sdf function. Used to compute SIRK from encrypted SIRK and k1. - * - * Returns Octet16 (SIRK) - ************************************************************************************/ -void bta_csip_get_decrypted_sirk(Octet16 k1, uint8_t *enc_sirk, uint8_t *sirk) { - for (int i = 0; i < 16; i++) { - sirk[i] = k1[i] ^ enc_sirk[i]; - } -} - -/************************************************************************************ - * - * Function bta_csip_get_aes_cmac_result - * - * Description Used to get aes-cmac result (for 16 byte input and output - * in LSB->MSB order) - * - * Returns Octet16 (cipher) - ************************************************************************************/ -Octet16 bta_csip_get_aes_cmac_result(const Octet16& key, const Octet16& message) { - Octet16 r_key, r_message, r_result; - - // reverse inputs as required by crypto_toolbox::aes_cmac - std::reverse_copy(key.begin(), key.end(), r_key.begin()); - std::reverse_copy(message.begin(), message.end(), r_message.begin()); - - Octet16 result = crypto_toolbox::aes_cmac(r_key, r_message.data(), r_message.size()); - - // reverse the result to get LSB->MSB order - std::reverse_copy(result.begin(), result.end(), r_result.begin()); - - return r_result; -} - -/************************************************************************************ - * - * Function bta_csip_get_aes_cmac_result - * - * Description Used to get aes-cmac result (for variable input and output - * in LSB->MSB order) - * - * Returns Octet16 (cipher) - ************************************************************************************/ -Octet16 bta_csip_get_aes_cmac_result(const Octet16& key, const uint8_t* input, - uint16_t length) { - Octet16 r_key, r_result; - - // reverse inputs as required by crypto_toolbox::aes_cmac - std::reverse_copy(key.begin(), key.end(), r_key.begin()); - uint8_t *input_buf = (uint8_t *)osi_malloc(length); - for (int i = 0; i < length; i++) { - input_buf[i] = input[length - 1 - i]; - } - - Octet16 result = crypto_toolbox::aes_cmac(r_key, input_buf, length); - - // reverse the result to get LSB->MSB order - std::reverse_copy(result.begin(), result.end(), r_result.begin()); - - return r_result; -} - -/************************************************************************************ - * - * Function byte_arr_to_hex_string - * - * Description function used to get hex representation in string format for byte[]. - * - * Returns void - ************************************************************************************/ -void byte_arr_to_hex_string(uint8_t* byte_arr, char* str, uint8_t len) { - int i; - LOG(INFO) << __func__ << " Convert byte array to hex format string"; - - for (i = 0; i < len; i++) - { - snprintf(str + (i * 2), (len * 2 + 1), "%02X", byte_arr[i]); - } -} - -/************************************************************************************ - * - * Function hex_string_to_byte_arr - * - * Description function used to get byte array from hex format string. - * - * Returns void - ************************************************************************************/ -void hex_string_to_byte_arr(char *str, uint8_t* byte_arr, uint8_t len) { - for (int length = 0; *str; str += 2, length++) - sscanf(str, "%02hhx", &byte_arr[length]); -} - -/************************************************************************************ - * - * Function is_key_empty - * - * Description function used to check if key is 0 intialized. - * - * Returns true, if all elements are 0. Otherwise, false. - ************************************************************************************/ -bool is_key_empty(Octet16& key) { - for (unsigned int i = 0; i < key.size(); i++) { - if (key[i] != 0) return false; - } - return true; -} diff --git a/le_audio/system/bt/bta/dm/bta_dm_adv_audio.cc b/le_audio/system/bt/bta/dm/bta_dm_adv_audio.cc deleted file mode 100644 index 4b41f02bd3099183f3bbbda79f69c2cd145b4c1a..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/dm/bta_dm_adv_audio.cc +++ /dev/null @@ -1,1185 +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. - * - ******************************************************************************/ - - -#define LOG_TAG "bt_bta_dm_adv_audio" - -#include -#include -#include -#include - -#include "bt_common.h" -#include "bt_target.h" -#include "bt_types.h" -#include "bta_api.h" -#include "bta_dm_api.h" -#include "bta_dm_co.h" -#include "bta/dm/bta_dm_int.h" -#include "bta_csip_api.h" -#include "bta_sys.h" -#include "btif/include/btif_storage.h" -#include "btm_api.h" -#include "btu.h" -#include "gap_api.h" /* For GAP_BleReadPeerPrefConnParams */ -#include "l2c_api.h" -#include "osi/include/log.h" -#include "osi/include/osi.h" -#include "sdp_api.h" -#include "bta_sdp_api.h" -#include "stack/gatt/connection_manager.h" -#include "stack/include/gatt_api.h" -#include "utl.h" -#include "device/include/interop_config.h" -#include "device/include/profile_config.h" -#include "device/include/interop.h" -#include "stack/sdp/sdpint.h" -#include -#include "btif/include/btif_config.h" -#include "device/include/device_iot_config.h" -#include -#include -#include "bta_gatt_queue.h" -#include "bta_dm_adv_audio.h" -#include "btif/include/btif_dm_adv_audio.h" - -#if (GAP_INCLUDED == TRUE) -#include "gap_api.h" -#endif - -using bluetooth::Uuid; - -#define ADV_AUDIO_VOICE_ROLE_BIT 2 -#define ADV_AUDIO_MEDIA_ROLE_BIT 8 -#define CONN_LESS_MEDIA_SINK_ROLE_BIT 32 -#define CONN_LESS_ASSIST_ROLE_BIT 64 -#define CONN_LESS_DELEGATE_ROLE_BIT 128 -#define PACS_CT_SUPPORT_VALUE 2 -#define PACS_UMR_SUPPORT_VALUE 4 -#define PACS_CONVERSATIONAL_ROLE_VALUE 2 -#define PACS_MEDIA_ROLE_VALUE 4 - -#define BTA_DM_ADV_AUDIO_GATT_CLOSE_DELAY_TOUT 5000 - -Uuid UUID_SERVCLASS_WMCP = Uuid::FromString - ("2587db3c-ce70-4fc9-935f-777ab4188fd7"); - -std::vector uuid_srv_disc_search; -tBTA_LE_AUDIO_DEV_CB bta_le_audio_dev_cb; -tBTA_LEA_PAIRING_DB bta_lea_pairing_cb; -extern void bta_dm_proc_open_evt(tBTA_GATTC_OPEN* p_data); -bool is_adv_audio_unicast_supported(RawAddress rem_bda, int conn_id); - - -/*************************************************************************** - * - * Function bta_get_lea_ctrl_cb - * - * Description Gets the control block of LE audio device - * - * Parameters: tBTA_LE_AUDIO_DEV_INFO* - * - ****************************************************************************/ - -tBTA_LE_AUDIO_DEV_INFO* bta_get_lea_ctrl_cb(RawAddress peer_addr) { - tBTA_LE_AUDIO_DEV_INFO *p_lea_cb = NULL; - p_lea_cb = &bta_le_audio_dev_cb.bta_lea_dev_info[0]; - - for (int i = 0; i < MAX_LEA_DEVICES ; i++) { - if (p_lea_cb[i].in_use && - (p_lea_cb[i].peer_address == peer_addr)) { - APPL_TRACE_DEBUG(" %s Control block Found for addr %s", - __func__, peer_addr.ToString().c_str()); - return &p_lea_cb[i]; - } - } - APPL_TRACE_DEBUG(" %s Control block Not Found for addr %s", - __func__, peer_addr.ToString().c_str()); - return NULL; -} - -/* Callback received when remote device Coordinated Sets SIRK is read */ -void bta_gap_gatt_read_cb(uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, uint16_t len, - uint8_t* value, void* data) { - - tBTA_LE_AUDIO_DEV_INFO *p_lea_cb = - bta_get_lea_ctrl_cb(bta_le_audio_dev_cb.gatt_op_addr); - uint32_t role = 0; - uint8_t *p_val = value; - - STREAM_TO_ARRAY(&role, p_val, len); - - if (p_lea_cb) { - APPL_TRACE_DEBUG("%s Addr %s ", __func__, - p_lea_cb->peer_address.ToString().c_str()); - if (status == GATT_SUCCESS) { - if (p_lea_cb->t_role_handle == handle) { - LOG(INFO) << __func__ << " Role derived by T_ADV_AUDIO " - << +role; - if (role != 0) { - if (role & ADV_AUDIO_VOICE_ROLE_BIT) - p_lea_cb->uuids.push_back(Uuid::From16Bit - (UUID_SERVCLASS_T_ADV_AUDIO_VOICE)); - if (role & ADV_AUDIO_MEDIA_ROLE_BIT) - p_lea_cb->uuids.push_back(Uuid::From16Bit - (UUID_SERVCLASS_T_ADV_AUDIO_MEDIA_SINK)); - if (role & CONN_LESS_MEDIA_SINK_ROLE_BIT) - p_lea_cb->uuids.push_back(Uuid::From16Bit - (UUID_SERVCLASS_T_ADV_AUDIO_CONN_LESS_MEDIA_SINK)); - if (role & CONN_LESS_ASSIST_ROLE_BIT) - p_lea_cb->uuids.push_back(Uuid::From16Bit - (UUID_SERVCLASS_T_ADV_AUDIO_ASSIST)); - if (role & CONN_LESS_DELEGATE_ROLE_BIT) - p_lea_cb->uuids.push_back(Uuid::From16Bit - (UUID_SERVCLASS_T_ADV_AUDIO_DELEGATE)); - } - p_lea_cb->disc_progress--; - } else if(handle == p_lea_cb->pacs_char_handle) { - LOG(INFO) << __func__ << " derived by PACS " << +role; - if (role == 0) { - LOG(INFO) << __func__ << " Invalid Information "; - } else { - if (is_adv_audio_unicast_supported(bta_le_audio_dev_cb.gatt_op_addr, conn_id)) { - LOG(INFO) << __func__ << " ASCS Supported by the remote "; - if ((role & PACS_CONVERSATIONAL_ROLE_VALUE) == PACS_CT_SUPPORT_VALUE) - p_lea_cb->uuids.push_back(Uuid::From16Bit(UUID_SERVCLASS_PACS_CT_SUPPORT)); - if ((role & PACS_MEDIA_ROLE_VALUE) == PACS_UMR_SUPPORT_VALUE) - p_lea_cb->uuids.push_back(Uuid::From16Bit(UUID_SERVCLASS_PACS_UMR_SUPPORT)); - } - //TODO LEA_DBG Call API which will be provided by BAP - } - p_lea_cb->disc_progress--; - } else { - LOG(INFO) << __func__ << " Invalid Handle for LE AUDIO"; - } - } else { - p_lea_cb->disc_progress--; - LOG(INFO) << __func__ << " GATT READ FAILED" ; - } - - if (p_lea_cb->disc_progress <= 0) { - bta_dm_lea_disc_complete(p_lea_cb->peer_address); - } - } else { - LOG(INFO) << __func__ << " INVALID CONTROL BLOCK" ; - } - -} - - -/******************************************************************************* - * - * Function bta_get_adv_audio_role - * - * Description This API gets role for LE Audio Device after all services - * discovered - * - * Parameters: none - * - ******************************************************************************/ -void bta_get_adv_audio_role(RawAddress peer_address, uint16_t conn_id, - tGATT_STATUS status) { - tBTA_LE_AUDIO_DEV_INFO *p_lea_cb = bta_get_lea_ctrl_cb(peer_address); - - bta_le_audio_dev_cb.gatt_op_addr = peer_address; - - if (p_lea_cb == NULL) { - APPL_TRACE_ERROR(" %s Control block didnt find for peer address %s", __func__, - peer_address.ToString().c_str()); - return; - } - - // Fetch remote device gatt services from database - const std::vector* services = BTA_GATTC_GetServices(conn_id); - - if (services) { - APPL_TRACE_DEBUG(" bta_get_adv_audio_role SIZE %d addr %s conn_id %d", - (*services).size(),bta_le_audio_dev_cb.gatt_op_addr.ToString().c_str(), - conn_id); - - // Search for CSIS service in the database - for (const gatt::Service& service : *services) { - APPL_TRACE_DEBUG("%s: SERVICES IN REMOTE DEVICE %s ", __func__, - service.uuid.ToString().c_str()) - if (is_le_audio_service(service.uuid)) { - size_t len = service.uuid.GetShortestRepresentationSize(); - uint16_t uuid_val = 0; - if (len == Uuid::kNumBytes16) { - uuid_val = service.uuid.As16Bit(); - } else if(len == Uuid::kNumBytes128) { - if (service.uuid == UUID_SERVCLASS_WMCP) { - APPL_TRACE_DEBUG("%s: WMCP Service UUId found", __func__); - std::vector::iterator itr; - itr = std::find(p_lea_cb->uuids.begin(), p_lea_cb->uuids.end(), - UUID_SERVCLASS_WMCP); - if (itr == p_lea_cb->uuids.end()) { - p_lea_cb->uuids.push_back(UUID_SERVCLASS_WMCP); - } - } - } - - switch (uuid_val) { - case UUID_SERVCLASS_CSIS: - { - APPL_TRACE_DEBUG("%s:CSIS service found Uuid: %s ", __func__, - service.uuid.ToString().c_str()); - - p_lea_cb->is_csip_support = true; - bta_dm_csis_disc_complete(bta_dm_search_cb.peer_bdaddr, false); - // Get Characteristic and CCCD handle - for (const gatt::Characteristic& charac : service.characteristics) { - Uuid lock_uuid = charac.uuid; - if (lock_uuid.As16Bit() == UUID_SERVCLASS_CSIS_LOCK) { - APPL_TRACE_DEBUG("%s: CSIS rank found Uuid: %s ", __func__, - lock_uuid.ToString().c_str()); - if (p_lea_cb != NULL) { - Uuid csip_lock_uuid = Uuid::FromString("6AD8"); - std::vector::iterator itr; - itr = std::find(p_lea_cb->uuids.begin(), p_lea_cb->uuids.end(), - csip_lock_uuid); - if (itr == p_lea_cb->uuids.end()) { - p_lea_cb->uuids.push_back(csip_lock_uuid); - } - } else { - APPL_TRACE_DEBUG(" %s No Control Block", __func__); - } - } - } - } - break; - case UUID_SERVCLASS_T_ADV_AUDIO: - { - if (!p_lea_cb->is_has_found) { - APPL_TRACE_DEBUG("%s: T_ADV_AUDIO service found Uuid: %s ", __func__, - service.uuid.ToString().c_str()); - std::vector::iterator itr; - itr = std::find(p_lea_cb->uuids.begin(), p_lea_cb->uuids.end(), - service.uuid); - if (itr == p_lea_cb->uuids.end()) { - p_lea_cb->uuids.push_back(service.uuid); - } - // Get Characteristic and CCCD handle - for (const gatt::Characteristic& charac : service.characteristics) { - Uuid role_uuid = charac.uuid; - if (role_uuid.As16Bit() == UUID_SERVCLASS_T_ADV_AUDIO_ROLE_CHAR) { - APPL_TRACE_DEBUG("%s:T_ADV_AUDIO ROLE CHAR found Uuid: %s ", __func__, - role_uuid.ToString().c_str()); - if (p_lea_cb != NULL) { - p_lea_cb->is_t_audio_srvc_found = true; - p_lea_cb->disc_progress++; - p_lea_cb->t_role_handle = charac.value_handle; - } else { - APPL_TRACE_DEBUG(" %s No Control Block", __func__); - } - } - } - if (p_lea_cb->t_role_handle) { - APPL_TRACE_DEBUG("%s t_role_handle %d", __func__, - p_lea_cb->t_role_handle); - BtaGattQueue::ReadCharacteristic(conn_id, p_lea_cb->t_role_handle, - bta_gap_gatt_read_cb, NULL); - } - } - } - break; - case UUID_SERVCLASS_HAS: - if (!p_lea_cb->is_t_audio_srvc_found) { - p_lea_cb->is_has_found = true; - APPL_TRACE_DEBUG("%s: HAS service found Uuid: %s ", __func__, - service.uuid.ToString().c_str()); - std::vector::iterator itr; - itr = std::find(p_lea_cb->uuids.begin(), p_lea_cb->uuids.end(), - service.uuid); - if (itr == p_lea_cb->uuids.end()) { - p_lea_cb->uuids.push_back(service.uuid); - } - } - FALLTHROUGH_INTENDED; /* FALLTHROUGH */ - case UUID_SERVCLASS_PACS: - { - if ((!p_lea_cb->pacs_char_handle) && - ((!p_lea_cb->is_t_audio_srvc_found))) { - APPL_TRACE_DEBUG("%s:PACS service found Uuid: %s ", __func__, - service.uuid.ToString().c_str()); - - std::vector::iterator itr; - itr = std::find(p_lea_cb->uuids.begin(), p_lea_cb->uuids.end(), - service.uuid); - if (itr == p_lea_cb->uuids.end()) { - p_lea_cb->uuids.push_back(service.uuid); - } - // Get Characteristic and CCCD handle - for (const gatt::Characteristic& charac : service.characteristics) { - Uuid role_uuid = charac.uuid; - if (role_uuid.As16Bit() == UUID_SERVCLASS_SOURCE_CONTEXT) { - APPL_TRACE_DEBUG("%s: PACS Source context CHAR found Uuid: %s ", - __func__, role_uuid.ToString().c_str()); - if (p_lea_cb != NULL) { - p_lea_cb->disc_progress++; - p_lea_cb->pacs_char_handle = charac.value_handle; - } else { - APPL_TRACE_DEBUG(" %s No Control Block", __func__); - } - } - } - if (p_lea_cb->pacs_char_handle) { - BtaGattQueue::ReadCharacteristic(conn_id, p_lea_cb->pacs_char_handle, - bta_gap_gatt_read_cb, NULL); - } - } - } - break; - default: - APPL_TRACE_DEBUG(" Not a LE AUDIO SERVICE-- IGNORE %s ", - service.uuid.ToString().c_str()); - } - } - } - } - - if (p_lea_cb->disc_progress == 0) { - bta_dm_lea_disc_complete(peer_address); - } -} - -/***************************************************************************** - * - * Function bta_dm_csis_disc_complete - * - * Description This API updates csis discovery complete status - * - * Parameters: none - *****************************************************************************/ -void bta_dm_csis_disc_complete(RawAddress p_bd_addr, bool status) { - tBTA_LE_AUDIO_DEV_INFO *p_lea_cb = bta_get_lea_ctrl_cb(p_bd_addr); - APPL_TRACE_DEBUG("%s %s %d", __func__, p_bd_addr.ToString().c_str(), - status); - - if (p_lea_cb) { - p_lea_cb->csip_disc_progress = status; - } else { - RawAddress pseudo_addr = bta_get_pseudo_addr_with_id_addr(p_bd_addr); - if (pseudo_addr != RawAddress::kEmpty) { - p_lea_cb = bta_get_lea_ctrl_cb(pseudo_addr); - if (p_lea_cb) { - p_lea_cb->csip_disc_progress = status; - APPL_TRACE_DEBUG(" %s Pseudo addr disc_progress resetted", __func__); - } else { - APPL_TRACE_DEBUG(" %s No Control Block for pseudo addr", __func__); - } - } else { - APPL_TRACE_DEBUG(" %s No Control Block", __func__); - } - } -} - -/***************************************************************************** - * - * Function bta_dm_lea_disc_complete - * - * Description This API sends the event to upper layer that LE audio - * gatt operations are complete. - * - * Parameters: none - * - ****************************************************************************/ -void bta_dm_lea_disc_complete(RawAddress p_bd_addr) { - tBTA_DM_SEARCH result; - tBTA_LE_AUDIO_DEV_INFO *p_lea_cb = bta_get_lea_ctrl_cb(p_bd_addr); - APPL_TRACE_DEBUG("%s %s", __func__, p_bd_addr.ToString().c_str()); - - if (p_lea_cb == NULL) { - RawAddress pseudo_addr = bta_get_pseudo_addr_with_id_addr(p_bd_addr); - p_lea_cb = bta_get_lea_ctrl_cb(pseudo_addr); - p_bd_addr = pseudo_addr; - } - - if (p_lea_cb) { - APPL_TRACE_DEBUG("csip_disc_progress %d", p_lea_cb->csip_disc_progress); - if ((p_lea_cb->disc_progress == 0) && - (p_lea_cb->csip_disc_progress)) { //Add CSIS check also - result.adv_audio_disc_cmpl.num_uuids = 0; - for (uint16_t i = 0; i < p_lea_cb->uuids.size(); i++) { - result.adv_audio_disc_cmpl.adv_audio_uuids[i] = p_lea_cb->uuids[i]; - result.adv_audio_disc_cmpl.num_uuids++; - } - - result.adv_audio_disc_cmpl.bd_addr = p_bd_addr; - APPL_TRACE_DEBUG("Sending Call back with no of uuids's" - "p_lea_cb->uuids.size() %d", p_lea_cb->uuids.size()); - bta_dm_search_cb.p_search_cback(BTA_DM_LE_AUDIO_SEARCH_CMPL_EVT, &result); - } else { - APPL_TRACE_DEBUG("%s Discovery in progress", __func__); - } - } else { - APPL_TRACE_DEBUG(" %s No Control Block", __func__); - } -} - - -/***************************************************************************** - * - * Function bta_add_adv_audio_uuid - * - * Description This is GATT client callback function used in DM. - * - * Parameters: - * - ******************************************************************************/ -void bta_add_adv_audio_uuid(RawAddress peer_address, - tBTA_GATT_ID srvc_uuid) { - auto itr = find(uuid_srv_disc_search.begin(), - uuid_srv_disc_search.end(), srvc_uuid.uuid); - - if(itr != uuid_srv_disc_search.end()) { - tBTA_LE_AUDIO_DEV_INFO *p_lea_cb = bta_get_lea_ctrl_cb(peer_address); - if (p_lea_cb != NULL) { - APPL_TRACE_DEBUG(" %s Control Block Found", __func__); - - std::vector::iterator itr; - itr = std::find(p_lea_cb->uuids.begin(), p_lea_cb->uuids.end(), srvc_uuid.uuid); - if (itr == p_lea_cb->uuids.end()) { - p_lea_cb->uuids.push_back(srvc_uuid.uuid); - } - } else { - APPL_TRACE_DEBUG(" %s No Control Block", __func__); - } - } -} - - - - -/******************************************************************************* - * - * Function bta_set_lea_ctrl_cb - * - * Description This is GATT client callback function used in DM. - * - * Parameters: - * - ******************************************************************************/ - -tBTA_LE_AUDIO_DEV_INFO* bta_set_lea_ctrl_cb(RawAddress peer_addr) { - tBTA_LE_AUDIO_DEV_INFO *p_lea_cb = NULL; - - p_lea_cb = bta_get_lea_ctrl_cb(peer_addr); - - if (p_lea_cb == NULL) { - APPL_TRACE_DEBUG("%s Control block create ", __func__); - - for (int i = 0; i < MAX_LEA_DEVICES ; i++) { - if (!bta_le_audio_dev_cb.bta_lea_dev_info[i].in_use) { - bta_le_audio_dev_cb.bta_lea_dev_info[i].peer_address = peer_addr; - bta_le_audio_dev_cb.bta_lea_dev_info[i].in_use = true; - bta_le_audio_dev_cb.bta_lea_dev_info[i].csip_disc_progress = true; - bta_le_audio_dev_cb.bta_lea_dev_info[i].is_csip_support = false; - bta_le_audio_dev_cb.bta_lea_dev_info[i].gatt_disc_progress = true; - bta_le_audio_dev_cb.num_lea_devices++; - return (&(bta_le_audio_dev_cb.bta_lea_dev_info[i])); - } - } - } else { - return p_lea_cb; - } - return NULL; -} - -/******************************************************************************* - * - * Function bta_dm_reset_adv_audio_dev_info - * - * Description This is GATT client callback function used in DM. - * - * Parameters: - * - ******************************************************************************/ -void bta_dm_reset_adv_audio_dev_info(RawAddress p_addr) { - tBTA_LE_AUDIO_DEV_INFO *p_lea_cb = bta_get_lea_ctrl_cb(p_addr); - - if (p_lea_cb != NULL) { - p_lea_cb->peer_address = RawAddress::kEmpty; - p_lea_cb->disc_progress = 0; - p_lea_cb->conn_id = 0; - p_lea_cb->transport = 0; - p_lea_cb->in_use = false; - p_lea_cb->t_role_handle = 0; - p_lea_cb->is_has_found = false; - p_lea_cb->is_t_audio_srvc_found = false; - p_lea_cb->pacs_char_handle = 0; - p_lea_cb->using_bredr_bonding = 0; - p_lea_cb->gatt_disc_progress = false; - p_lea_cb->uuids.clear(); - bta_le_audio_dev_cb.gatt_op_addr = RawAddress::kEmpty; - bta_le_audio_dev_cb.pending_peer_addr = RawAddress::kEmpty; - bta_le_audio_dev_cb.num_lea_devices--; - bta_le_audio_dev_cb.bond_progress = false; - APPL_TRACE_DEBUG("bta_dm_reset_adv_audio_dev_info %s transport %d ", - p_lea_cb->peer_address.ToString().c_str(), p_lea_cb->transport); - } -} - -/******************************************************************************* - * - * Function bta_dm_set_adv_audio_dev_info - * - * Description This is GATT client callback function used in DM. - * - * Parameters: - * - ******************************************************************************/ -void bta_dm_set_adv_audio_dev_info(tBTA_GATTC_OPEN* p_data) { - tBTA_LE_AUDIO_DEV_INFO *p_lea_cb = bta_set_lea_ctrl_cb(p_data->remote_bda); - - if (p_lea_cb != NULL) { - p_lea_cb->peer_address = p_data->remote_bda; - p_lea_cb->disc_progress = 0; - p_lea_cb->conn_id = p_data->conn_id; - p_lea_cb->transport = p_data->transport;//BTM_UseLeLink(p_data->remote_bda); - APPL_TRACE_DEBUG("bta_dm_set_adv_audio_dev_info %s transport %d ", - p_lea_cb->peer_address.ToString().c_str(), p_lea_cb->transport); - } -} - -/******************************************************************************* - * - * Function is_adv_audio_unicast_supported - * - * Description This function checks whether unicast support is there or not on - * remote side - * - * Parameters: - * - ******************************************************************************/ - -bool is_adv_audio_unicast_supported(RawAddress rem_bda, int conn_id) { - const std::vector* services = BTA_GATTC_GetServices(conn_id); - - if (services) { - for (const gatt::Service& service : *services) { - uint16_t uuid_val = service.uuid.As16Bit(); - if (uuid_val == UUID_SERVCLASS_ASCS) - return true; - } - } - - return false; -} - -/******************************************************************************* - * - * Function is_adv_audio_group_supported - * - * Description This function checks whether csip support is there or not on - * remote side - * - * Parameters: - * - ******************************************************************************/ - -bool is_adv_audio_group_supported(RawAddress rem_bda, int conn_id) { - const std::vector* services = BTA_GATTC_GetServices(conn_id); - - if (services) { - for (const gatt::Service& service : *services) { - if (is_le_audio_service(service.uuid)) { - uint16_t uuid_val = service.uuid.As16Bit(); - if (uuid_val == UUID_SERVCLASS_CSIS) - return true; - } - } - } - - return false; -} - -/******************************************************************************* - * - * Function bta_dm_lea_gattc_callback - * - * Description This is GATT client callback function used in DM. - * - * Parameters: - * - ******************************************************************************/ - -void bta_dm_lea_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) { - APPL_TRACE_DEBUG("bta_dm_lea_gattc_callback event = %d", event); - - switch (event) { - case BTA_GATTC_OPEN_EVT: - if (p_data->status != GATT_SUCCESS) { - btif_dm_release_action_uuid(bta_le_audio_dev_cb.pending_peer_addr); - } else { - if (is_remote_support_adv_audio(bta_le_audio_dev_cb.pending_peer_addr)) { - bta_dm_set_adv_audio_dev_info(&p_data->open); - } - bta_dm_proc_open_evt(&p_data->open); - } - break; - - case BTA_GATTC_SEARCH_RES_EVT: - if (is_remote_support_adv_audio(bta_le_audio_dev_cb.pending_peer_addr)) { - bta_add_adv_audio_uuid(bta_le_audio_dev_cb.pending_peer_addr, - p_data->srvc_res.service_uuid); - } - break; - - case BTA_GATTC_SEARCH_CMPL_EVT: - if (is_remote_support_adv_audio(bta_le_audio_dev_cb.pending_peer_addr)) { - bta_get_adv_audio_role(bta_le_audio_dev_cb.pending_peer_addr, - p_data->search_cmpl.conn_id, - p_data->search_cmpl.status); - if (is_adv_audio_group_supported(bta_le_audio_dev_cb.pending_peer_addr, - p_data->search_cmpl.conn_id)) { - RawAddress p_id_addr = - bta_get_rem_dev_id_addr(bta_le_audio_dev_cb.pending_peer_addr); - if (p_id_addr != RawAddress::kEmpty) { - BTA_CsipFindCsisInstance(p_data->search_cmpl.conn_id, - p_data->search_cmpl.status, - p_id_addr); - } else { - BTA_CsipFindCsisInstance(p_data->search_cmpl.conn_id, - p_data->search_cmpl.status, - bta_le_audio_dev_cb.pending_peer_addr); - } - } - } - break; - - case BTA_GATTC_CLOSE_EVT: - APPL_TRACE_DEBUG("BTA_GATTC_CLOSE_EVT reason = %d, data conn_id %d," - "search conn_id %d", p_data->close.reason, p_data->close.conn_id, - bta_dm_search_cb.conn_id); - - if (is_remote_support_adv_audio(bta_le_audio_dev_cb.pending_peer_addr)) { - bta_dm_reset_adv_audio_dev_info(bta_le_audio_dev_cb.pending_peer_addr); - } - break; - - default: - break; - } -} - -/****************************************************************************** - * - * Function bta_dm_adv_audio_gatt_conn - * - * Description This API opens the gatt conn after finding sdp record - * during BREDR Discovery - * - * Parameters: none - * - ******************************************************************************/ -void bta_dm_adv_audio_gatt_conn(RawAddress p_bd_addr) { - APPL_TRACE_DEBUG("bta_dm_adv_audio_gatt_conn "); - - bta_le_audio_dev_cb.pending_peer_addr = p_bd_addr; - - tBTA_LE_AUDIO_DEV_INFO *tmp_lea_cb = bta_get_lea_ctrl_cb(p_bd_addr); - if (tmp_lea_cb && tmp_lea_cb->in_use) { - APPL_TRACE_DEBUG("bta_dm_adv_audio_gatt_conn Already exists %d", - tmp_lea_cb->conn_id); - return; - } - - BTA_GATTC_AppRegister(bta_dm_lea_gattc_callback, - base::Bind([](uint8_t client_id, uint8_t status) { - if (status == GATT_SUCCESS) { - tBTA_LE_AUDIO_DEV_INFO *p_lea_cb = - bta_set_lea_ctrl_cb(bta_le_audio_dev_cb.pending_peer_addr); - if (p_lea_cb) { - APPL_TRACE_DEBUG("bta_dm_adv_audio_gatt_conn Client Id: %d", - client_id); - p_lea_cb->gatt_if = client_id; - p_lea_cb->using_bredr_bonding = true; - BTA_GATTC_Open(client_id, bta_le_audio_dev_cb.pending_peer_addr, - true, GATT_TRANSPORT_LE, false); - } - } - }), false); - -} - -/****************************************************************************** - * - * Function bta_dm_adv_audio_close - * - * Description This API closes the gatt conn with was opened by dm layer - * for service discovery (or) opened after finding sdp record - * during BREDR Discovery - * - * Parameters: none - * - ******************************************************************************/ -void bta_dm_adv_audio_close(RawAddress p_bd_addr) { - tBTA_LE_AUDIO_DEV_INFO *p_lea_cb = bta_get_lea_ctrl_cb(p_bd_addr); - APPL_TRACE_DEBUG("%s", __func__); - - if (p_lea_cb) { - APPL_TRACE_DEBUG("%s %d", __func__, p_lea_cb->gatt_if); - if (p_lea_cb->using_bredr_bonding) { - APPL_TRACE_DEBUG("%s closing LE conn est due to bredr bonding %d", __func__, - p_lea_cb->gatt_if); - BTA_GATTC_AppDeregister(p_lea_cb->gatt_if); - } else { - bta_sys_start_timer(bta_dm_search_cb.gatt_close_timer, - BTA_DM_ADV_AUDIO_GATT_CLOSE_DELAY_TOUT, - BTA_DM_DISC_CLOSE_TOUT_EVT, 0); - } - } -} - -/******************************************************************************* - * - * Function bta_get_lea_ctrl_cb - * - * Description This API returns pairing control block of LE AUDIO DEVICE - * - * Parameters: tBTA_DEV_PAIRING_CB - * - ******************************************************************************/ -tBTA_DEV_PAIRING_CB* bta_get_lea_pair_cb(RawAddress peer_addr) { - tBTA_DEV_PAIRING_CB *p_lea_pair_cb = NULL; - p_lea_pair_cb = &bta_lea_pairing_cb.bta_dev_pair_db[0]; - APPL_TRACE_DEBUG("%s %s ", __func__, peer_addr.ToString().c_str()); - - for (int i = 0; i < MAX_LEA_DEVICES; i++) { - if ((p_lea_pair_cb[i].in_use) && - (p_lea_pair_cb[i].p_addr == peer_addr)) { - APPL_TRACE_DEBUG("%s Found %s index i %d ", __func__, - p_lea_pair_cb[i].p_addr.ToString().c_str(), i); - return &p_lea_pair_cb[i]; - } - } - return NULL; -} - - - -/******************************************************************************* - * - * Function bta_set_lea_ctrl_cb - * - * Description This is GATT client callback function used in DM. - * - * Parameters: - * - ******************************************************************************/ - -tBTA_DEV_PAIRING_CB* bta_set_lea_pair_cb(RawAddress peer_addr) { - tBTA_DEV_PAIRING_CB *p_lea_pair_cb = NULL; - APPL_TRACE_DEBUG("bta_set_lea_ctrl_cb %s", peer_addr.ToString().c_str()); - - p_lea_pair_cb = bta_get_lea_pair_cb(peer_addr); - - if (p_lea_pair_cb == NULL) { - APPL_TRACE_DEBUG("bta_set_lea_ctrl_cb Control block create "); - - for (int i = 0; i < MAX_LEA_DEVICES ; i++) { - if (!bta_lea_pairing_cb.bta_dev_pair_db[i].in_use) { - bta_lea_pairing_cb.bta_dev_pair_db[i].p_addr = peer_addr; - bta_lea_pairing_cb.bta_dev_pair_db[i].in_use = true; - bta_lea_pairing_cb.is_pairing_progress = true; - bta_lea_pairing_cb.num_devices++; - return (&(bta_lea_pairing_cb.bta_dev_pair_db[i])); - } - } - } else { - return p_lea_pair_cb; - } - return NULL; -} - -/******************************************************************************* - * - * Function bta_dm_reset_adv_audio_dev_info - * - * Description This API resets all the pairing information related to le - * audio remote device. - * Parameters: none - * - ******************************************************************************/ -void bta_dm_reset_lea_pairing_info(RawAddress p_addr) { - - APPL_TRACE_DEBUG("%s Addr %s", __func__, p_addr.ToString().c_str()); - - auto itr = bta_lea_pairing_cb.dev_addr_map.find(p_addr); - if (itr != bta_lea_pairing_cb.dev_addr_map.end()) { - bta_lea_pairing_cb.dev_addr_map.erase(p_addr); - } - - itr = bta_lea_pairing_cb.dev_rand_addr_map.find(p_addr); - if (itr != bta_lea_pairing_cb.dev_rand_addr_map.end()) { - bta_lea_pairing_cb.dev_rand_addr_map.erase(p_addr); - } - - tBTA_DEV_PAIRING_CB *p_lea_pair_cb = NULL; - p_lea_pair_cb = bta_get_lea_pair_cb(p_addr); - if (p_lea_pair_cb) { - APPL_TRACE_DEBUG("%s RESETTING VALUES", __func__); - p_lea_pair_cb->in_use = false; - p_lea_pair_cb->is_dumo_device = false; - p_lea_pair_cb->is_le_pairing = false; - p_lea_pair_cb->dev_type = 0; - if (p_lea_pair_cb->p_id_addr != RawAddress::kEmpty) { - itr = bta_lea_pairing_cb.dev_addr_map.find(p_lea_pair_cb->p_id_addr); - APPL_TRACE_DEBUG("%s RESETTING Addr %s", __func__, - p_lea_pair_cb->p_id_addr.ToString().c_str()); - if (itr != bta_lea_pairing_cb.dev_addr_map.end()) { - APPL_TRACE_DEBUG("%s Clearing INSIDE LEA ADDR DB MAP", - __func__); - bta_lea_pairing_cb.dev_addr_map.erase(p_lea_pair_cb->p_id_addr); - } - p_lea_pair_cb->p_id_addr = RawAddress::kEmpty; - p_lea_pair_cb->transport = 0; - p_lea_pair_cb->p_addr = RawAddress::kEmpty; - } - bta_lea_pairing_cb.is_pairing_progress = false; - bta_lea_pairing_cb.num_devices--; - bta_lea_pairing_cb.is_sdp_discover = true; - } else { - APPL_TRACE_DEBUG("%s INVALID CONTROL BLOCK", __func__); - } -} - -/***************************************************************************** - * - * Function bta_dm_ble_adv_audio_idaddr_map - * - * Description storing the identity address information in the device - * control block. It will used for DUMO devices - * - * Returns none - * - *****************************************************************************/ -void bta_dm_ble_adv_audio_idaddr_map(RawAddress p_bd_addr, - RawAddress p_id_addr) { - APPL_TRACE_DEBUG("%s p_bd_addr %s id_addr %s ", __func__, - p_bd_addr.ToString().c_str(), p_id_addr.ToString().c_str()); - if (is_remote_support_adv_audio(p_bd_addr)) { - bta_lea_pairing_cb.dev_addr_map[p_id_addr] = p_bd_addr; - bta_lea_pairing_cb.dev_rand_addr_map[p_bd_addr] = p_id_addr; - - tBTA_DEV_PAIRING_CB *p_lea_pair_cb = NULL; - p_lea_pair_cb = bta_get_lea_pair_cb(p_bd_addr); - if (p_lea_pair_cb) { - if (p_id_addr != p_bd_addr) { - APPL_TRACE_DEBUG("%s is_dumo_device %s", __func__, - p_id_addr.ToString().c_str()); - p_lea_pair_cb->p_id_addr = p_id_addr; - p_lea_pair_cb->is_dumo_device = true; - } - } - } -} - -bool bta_remote_dev_identity_addr_match(RawAddress p_addr) { - APPL_TRACE_DEBUG("%s ", __func__); - - auto itr = bta_lea_pairing_cb.dev_addr_map.find(p_addr); - - if (itr != bta_lea_pairing_cb.dev_addr_map.end()) { - APPL_TRACE_DEBUG("%s Identity BD_ADDR %s", __func__, - p_addr.ToString().c_str()); - return true; - } - return false; -} - -bool bta_is_bredr_primary_transport(RawAddress p_bd_addr) { - - tBTA_DEV_PAIRING_CB *p_lea_pair_cb = NULL; - - p_lea_pair_cb = bta_get_lea_pair_cb(p_bd_addr); - APPL_TRACE_DEBUG("%s ", __func__); - if (p_lea_pair_cb) { - APPL_TRACE_DEBUG("%s Transport %d ", __func__, p_lea_pair_cb->transport); - if (p_lea_pair_cb->transport == BT_TRANSPORT_BR_EDR) { - return true; - } - } - - return false; -} - -bool bta_remote_device_is_dumo(RawAddress p_bd_addr) { - - auto itr = bta_lea_pairing_cb.dev_addr_map.find(p_bd_addr); - APPL_TRACE_DEBUG("%s Addr %s", __func__, p_bd_addr.ToString().c_str()); - - if (itr != bta_lea_pairing_cb.dev_addr_map.end()) { - APPL_TRACE_DEBUG("%s DUMO DEVICE Identity BD_ADDR %s", __func__, - p_bd_addr.ToString().c_str()); - return true; - } - - auto itr2 = bta_lea_pairing_cb.dev_rand_addr_map.find(p_bd_addr); - if (itr2 != bta_lea_pairing_cb.dev_rand_addr_map.end()) { - APPL_TRACE_DEBUG("%s Dumo addressed %s %s ", __func__, - itr2->first.ToString().c_str(), itr2->second.ToString().c_str()); - return true; - } - return false; -} - -RawAddress bta_get_rem_dev_id_addr(RawAddress p_bd_addr) { - tBTA_DEV_PAIRING_CB *p_lea_pair_cb = NULL; - APPL_TRACE_DEBUG("%s ", __func__); - - p_lea_pair_cb = bta_get_lea_pair_cb(p_bd_addr); - if (p_lea_pair_cb) { - APPL_TRACE_DEBUG("%s %s", __func__, - p_lea_pair_cb->p_id_addr.ToString().c_str()); - return p_lea_pair_cb->p_id_addr; - } - return RawAddress::kEmpty; -} - -/***************************************************************************** - * - * Function bta_adv_audio_update_bond_db - * - * Description Updates pairing control block of the device and the bonding - * is initiated using LE transport or not. - * - * Returns void - * - *****************************************************************************/ -void bta_adv_audio_update_bond_db(RawAddress p_bd_addr, uint8_t transport) { - tBTA_DEV_PAIRING_CB *p_dev_pair_cb = bta_set_lea_pair_cb(p_bd_addr); - - APPL_TRACE_DEBUG("%s", __func__); - if (p_dev_pair_cb) { - APPL_TRACE_DEBUG("%s Addr %s Transport %d", __func__, - p_bd_addr.ToString().c_str(), transport); - p_dev_pair_cb->p_addr = p_bd_addr; - p_dev_pair_cb->transport = transport; - if (transport == BT_TRANSPORT_LE) { - if (is_remote_support_adv_audio(p_dev_pair_cb->p_addr)) - p_dev_pair_cb->is_le_pairing = true; - else - p_dev_pair_cb->is_le_pairing = false; - } else - p_dev_pair_cb->is_le_pairing = false; - } -} - -/***************************************************************************** - * - * Function is_le_audio_service - * - * Description It checks whether the given service is related to the LE - * Audio service or not. - * - * Returns true for LE Audio service which are registered. - false by default - * - *****************************************************************************/ -bool is_le_audio_service(Uuid uuid) { - - uint16_t uuid_val = 0; - bool status = false; - - size_t len = uuid.GetShortestRepresentationSize(); - if (len == Uuid::kNumBytes16) { - uuid_val = uuid.As16Bit(); - APPL_TRACE_DEBUG("is_le_audio_service : 0x%X 0x%X ", uuid.As16Bit(), uuid_val); - //TODO check the service contains any LE AUDIO service or not - switch (uuid_val) { - case UUID_SERVCLASS_CSIS: - FALLTHROUGH_INTENDED; /* FALLTHROUGH */ - case UUID_SERVCLASS_BASS: - FALLTHROUGH_INTENDED; /* FALLTHROUGH */ - case UUID_SERVCLASS_T_ADV_AUDIO: - FALLTHROUGH_INTENDED; /* FALLTHROUGH */ - case UUID_SERVCLASS_ASCS: - FALLTHROUGH_INTENDED; /* FALLTHROUGH */ - case UUID_SERVCLASS_BAAS: - FALLTHROUGH_INTENDED; /* FALLTHROUGH */ - case UUID_SERVCLASS_PACS: - { - auto itr = find(uuid_srv_disc_search.begin(), - uuid_srv_disc_search.end(), uuid); - if (itr != uuid_srv_disc_search.end()) - status = true; - } - break; - default: - APPL_TRACE_DEBUG("%s : Not a LEA service ", __func__); - } - } else if(len == Uuid::kNumBytes128) { - if (uuid == UUID_SERVCLASS_WMCP) { - APPL_TRACE_DEBUG("%s: WMCP Service UUId found", __func__); - auto itr = find(uuid_srv_disc_search.begin(), - uuid_srv_disc_search.end(), uuid); - if (itr != uuid_srv_disc_search.end()) - status = true; - } - } - - return status; -} - -/***************************************************************************** - * - * Function bta_is_adv_audio_valid_bdaddr - * - * Description This API is used for DUMO device. If the device contains - * two address (random and public), it checks for valid - * address. - * - * Returns 0 - for random address in dumo device - * 1 - for public address in dumo device - * - ****************************************************************************/ -int bta_is_adv_audio_valid_bdaddr(RawAddress p_bd_addr) { - tBTA_DEV_PAIRING_CB *p_lea_pair_cb = NULL; - p_lea_pair_cb = bta_get_lea_pair_cb(p_bd_addr); - - if (p_lea_pair_cb) { - APPL_TRACE_DEBUG("%s p_lea_pair_cb %s", __func__, - p_lea_pair_cb->p_addr.ToString().c_str()); - auto itr = bta_lea_pairing_cb.dev_addr_map.find(p_bd_addr); - if (itr == bta_lea_pairing_cb.dev_addr_map.end() && - (p_lea_pair_cb->is_dumo_device)) { - APPL_TRACE_DEBUG("%s Ignore BD_ADDR because of ID %s", __func__, - p_lea_pair_cb->p_id_addr.ToString().c_str()); - return 0; - } - } - return 1; -} - -/***************************************************************************** - * - * Function devclass2uint - * - * Description This API is to derive the class of device based of dev_class - * - * Returns uint32_t - class of device - * - ****************************************************************************/ -static uint32_t devclass2uint(DEV_CLASS dev_class) { - uint32_t cod = 0; - - if (dev_class != NULL) { - /* if COD is 0, irrespective of the device type set it to Unclassified - * device */ - cod = (dev_class[2]) | (dev_class[1] << 8) | (dev_class[0] << 16); - } - return cod; -} - -/***************************************************************************** - * - * Function bta_is_remote_support_lea - * - * Description This API is to check the remote device contains LEA service - * or not. It checks in Inquiry database initially. - * If the address is Public identity address then it will - * check in the pairing database of that remote device. - * - * Returns true - if remote device inquiry db contains LEA service - * - ****************************************************************************/ -bool bta_is_remote_support_lea(RawAddress p_addr) { - tBTM_INQ_INFO* p_inq_info; - - p_inq_info = BTM_InqDbRead(p_addr); - if (p_inq_info != NULL) { - uint32_t cod = devclass2uint(p_inq_info->results.dev_class); - BTIF_TRACE_DEBUG("%s cod is 0x%06x", __func__, cod); - if ((cod & MAJOR_LE_AUDIO_VENDOR_COD) - == MAJOR_LE_AUDIO_VENDOR_COD) { - return true; - } - } - - /* check the address is public identity address and its related to random - * address which supports to LEA then that Public ID address should return - * true. - */ - auto itr = bta_lea_pairing_cb.dev_addr_map.find(p_addr); - if (itr != bta_lea_pairing_cb.dev_addr_map.end()) { - BTIF_TRACE_DEBUG("%s Idenity address mapping", __func__); - return true; - } - - return false; -} - -void bta_find_adv_audio_group_instance(uint16_t conn_id, tGATT_STATUS status, - RawAddress p_addr) { - RawAddress p_id_addr = - bta_get_rem_dev_id_addr(p_addr); - if (p_id_addr != RawAddress::kEmpty) { - BTA_CsipFindCsisInstance(conn_id, status, p_id_addr); - } else { - BTA_CsipFindCsisInstance(conn_id, status, p_addr); - } -} - -/******************************************************************************* - * - * Function is_gatt_srvc_disc_pending - * - * Description This function checks whether gatt_srvc_disc is processing - * or not - * - * Parameters: - * - ******************************************************************************/ -bool is_gatt_srvc_disc_pending(RawAddress rem_bda) { - tBTA_LE_AUDIO_DEV_INFO *p_lea_cb = bta_get_lea_ctrl_cb(rem_bda); - - APPL_TRACE_DEBUG("%s ", __func__); - if (p_lea_cb == NULL) { - return false; - } else { - APPL_TRACE_DEBUG("%s gatt_disc_progress %d ", __func__, - p_lea_cb->gatt_disc_progress); - return p_lea_cb->gatt_disc_progress; - } -} - -/****************************************************************************** - * - * Function bta_get_pseudo_addr_with_id_addr - * - * Description This function returns the mapping id_addr(if present) to - * pseudo addr - * - * Parameters: - * - *****************************************************************************/ -RawAddress bta_get_pseudo_addr_with_id_addr(RawAddress p_addr) { - auto itr = bta_lea_pairing_cb.dev_addr_map.find(p_addr); - - APPL_TRACE_DEBUG("%s p_addr %s ", __func__, p_addr.ToString().c_str()); - if (itr != bta_lea_pairing_cb.dev_addr_map.end()) { - APPL_TRACE_DEBUG("%s addr is mapped to %s ", __func__, - itr->second.ToString().c_str()); - if (itr->second != RawAddress::kEmpty) { - return itr->second; - } - } - return p_addr; -} diff --git a/le_audio/system/bt/bta/include/bta_ascs_client_api.h b/le_audio/system/bt/bta/include/bta_ascs_client_api.h deleted file mode 100644 index 5bcf48e5cb36e707e75f8d933daa28eb2c6496e8..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/include/bta_ascs_client_api.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/* - * 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 - -namespace bluetooth { -namespace bap { -namespace ascs { - -class AscsClient { - public: - virtual ~AscsClient() = default; - - static void Init(bluetooth::bap::ascs::AscsClientCallbacks* callbacks); - - static void CleanUp(uint16_t client_id); - - static AscsClient* Get(); - - virtual void Connect(uint16_t client_id, const RawAddress& address, - bool is_direct) = 0; - - virtual void Disconnect(uint16_t client_id, const RawAddress& address) = 0; - - virtual void StartDiscovery(uint16_t client_id, - const RawAddress& address) = 0; - - virtual void GetAseState(uint16_t client_id, const RawAddress& address, - uint8_t ase_id) = 0; - - virtual void CodecConfig(uint16_t client_id, const RawAddress& address, - std::vector codec_configs); - - virtual void QosConfig(uint16_t client_id, const RawAddress& address, - std::vector qos_configs); - - virtual void Enable(uint16_t client_id, const RawAddress& address, - std::vector enable_ops); - - virtual void Disable(uint16_t client_id, const RawAddress& address, - std::vector disable_ops); - - virtual void StartReady(uint16_t client_id, const RawAddress& address, - std::vector start_ready_ops); - - virtual void StopReady(uint16_t client_id, const RawAddress& address, - std::vector stop_ready_ops); - - virtual void Release(uint16_t client_id, const RawAddress& address, - std::vector release_ops); - - virtual void UpdateStream(uint16_t client_id, const RawAddress& address, - std::vector metadata_ops); -}; - -} // namespace ascs -} // namespace bap -} // namespace bluetooth diff --git a/le_audio/system/bt/bta/include/bta_bap_uclient_api.h b/le_audio/system/bt/bta/include/bta_bap_uclient_api.h deleted file mode 100644 index 33bd53bf141ccd52e399a7870bcc53b61e170348..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/include/bta_bap_uclient_api.h +++ /dev/null @@ -1,67 +0,0 @@ -/****************************************************************************** - * - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - - -#pragma once - -#include -#include "connected_iso_api.h" -#include -#include "bta_ascs_client_api.h" -#include "bta/bap/uclient_alarm.h" - -namespace bluetooth { -namespace bap { -namespace ucast { - -using bluetooth::bap::pacs::PacsClientCallbacks; -using bluetooth::bap::ascs::AscsClientCallbacks; -using bluetooth::bap::cis::CisInterfaceCallbacks; -using bluetooth::bap::ucast::StreamConnect; -using bluetooth::bap::ucast::StreamType; -using bluetooth::bap::alarm::BapAlarmCallbacks; - -class UcastClient : public PacsClientCallbacks, - public AscsClientCallbacks, - public CisInterfaceCallbacks, - public BapAlarmCallbacks { - public: - virtual ~UcastClient() = default; - - static void Initialize(UcastClientCallbacks* callbacks); - static void CleanUp(); - static UcastClient* Get(); - - // APIs exposed to upper layer - virtual void Connect(std::vector address, bool is_direct, - std::vector streams) = 0; - virtual void Disconnect(const RawAddress& address, - std::vector streams) = 0; - virtual void Start(const RawAddress& address, - std::vector streams) = 0; - virtual void Stop(const RawAddress& address, - std::vector streams) = 0; - virtual void Reconfigure(const RawAddress& address, - std::vector streams) = 0; - virtual void UpdateStream(const RawAddress& address, - std::vector update_streams) = 0; -}; - -} // namespace ucast -} // namespace bap -} // namespace bluetooth diff --git a/le_audio/system/bt/bta/include/bta_cc_api.h b/le_audio/system/bt/bta/include/bta_cc_api.h deleted file mode 100644 index f7dbd6929c411f0b4609663113928203d432e4b5..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/include/bta_cc_api.h +++ /dev/null @@ -1,472 +0,0 @@ -/* - *Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. - */ - -/* - * Copyright (C) 2003-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. - */ -#pragma once - -#include -#include -#include -#include -#include "bta_gatt_api.h" -#include -#include - -using bluetooth::Uuid; -using bluetooth::call_control::CallControllerCallbacks; -#define MAX_RESPONSE_DATA_LEN 255 -#define MAX_CCS_CONNECTION 5 -#define MAX_BEARER_NAME 255 -#define MAX_UCI_NAME 255 -#define MAX_URI_LENGTH 255 -#define MAX_BEARER_LIST_LEN 255 -#define MAX_FRIENDLY_NAME_LEN 255 -//Atmost there could be only two Indicies (for JOIN) -//Keeping this as Internal max as SPec don't define any upper limit on this -#define MAX_NUM_INDICIES 10 - -#define INBAND_RINGTONE_FEATURE_BIT 0x01 -#define SILENT_MODE_FEATURE_BIT 0x02 - -typedef enum { - CCS_NONE_EVENT = 120, - CCS_INIT_EVENT, - CCS_CLEANUP_EVENT, - CCS_CALL_STATE_UPDATE, - CCS_BEARER_NAME_UPDATE, - CCS_BEARER_UCI_UPDATE, - CCS_BEARER_URI_SCHEMES_SUPPORTED, - CCS_UPDATE, - CCS_OPT_OPCODES, - CCS_BEARER_CURRENT_CALL_LIST_UPDATE, - CCS_BEARER_SIGNAL_STRENGTH_UPDATE, - CCS_SIGNAL_STRENGTH_REPORT_INTERVAL, - CCS_STATUS_FLAGS_UPDATE, - CCS_INCOMING_CALL_UPDATE, - CCS_INCOMING_TARGET_URI_UPDATE, - CCS_TERMINATION_REASON_UPDATE, - CCS_BEARER_TECHNOLOGY_UPDATE, - CCS_CCID_UPDATE, - CCS_ACTIVE_DEVICE_UPDATE, - CCS_CALL_CONTROL_RESPONSE, - //events to handle in CCS state machine - CCS_NOTIFY_ALL, - CCS_WRITE_RSP, - CCS_READ_RSP, - CCS_DESCRIPTOR_WRITE_RSP, - CCS_DESCRIPTOR_READ_RSP, - CCS_CONNECTION, - CCS_DISCONNECTION, - CCS_CONNECTION_UPDATE, - CCS_CONGESTION_UPDATE, - CCS_PHY_UPDATE, - CCS_MTU_UPDATE, - CCS_SET_ACTIVE_DEVICE, - CCS_CONNECTION_CLOSE_EVENT, - CCS_BOND_STATE_CHANGE_EVENT, -}cc_event_t; - -typedef enum { - CCS_STATUS_SUCCESS = 0x00, - CCS_OPCODE_NOT_SUPPORTED, - CCS_OPCODE_UNSUCCESSFUL, - CCS_INVALID_INDEX, - CCS_STATE_MISMATCH, - CCS_LACK_OF_RESOURCES, - CCS_INVALID_OUTGOING_URI, - CCS_CALL_STATE_INACTIVE, -}cc_error_t; - -typedef enum { - CCS_DISCONNECTED = 0x00, - CCS_CONNECTED, - CCS_MAX_DEVICE_STATE -} call_connect_state_t; - -typedef enum { - CALL_ACCEPT = 0x00, - CALL_TERMINATE, - CALL_LOCAL_HOLD, - CALL_LOCAL_RETRIEVE, - CALL_ORIGINATE, - CALL_JOIN, - } cc_opcode_t; - - typedef enum { - CC_TERM_INVALID_ORIG_URI = 0x00, - CC_TERM_FAILED, - CC_TERM_END_FROM_REMOTE, - CC_TERM_END_FROM_SERVER, - CC_TERM_LINE_BUSY, - CC_TERM_NW_CONGESTION, - CC_TERM_END_FROM_CLIENT, - CC_TERM_NO_SERVICE, - CC_TERM_NO_ANSWER, - } cc_term_reason_t; - - typedef enum { - CCS_STATE_INCOMING = 0x00, - CCS_STATE_DIALING, - CCS_STATE_ALERTING, - CCS_STATE_ACTIVE, - CCS_STATE_LOCAL_HELD, - CCS_STATE_REMOTELY_HELD, - CCS_STATE_LOCAL_REMOTE_HELD, - CCS_STATE_DISCONNECTED, - } cc_state_t; - - //connection state machine - bool DeviceStateConnectionHandler(uint32_t event, void* param); - bool DeviceStateDisConnectingHandler(uint32_t event, void* param); - bool DeviceStateDisconnectedHandler(uint32_t event, void* param); - -typedef struct { - int server_if; - Uuid ccs_service_uuid; - Uuid bearer_provider_name_uuid; - Uuid call_control_point_uuid; - Uuid call_control_point_opcode_supported_uuid; - Uuid bearer_uci_uuid; - Uuid bearer_technology_uuid; - Uuid bearer_uri_schemes_supported_uuid; - Uuid bearer_signal_strength_uuid; - Uuid bearer_signal_strength_report_interval_uuid; - Uuid bearer_list_currentcalls_uuid; - Uuid incoming_call_target_beareruri_uuid; - Uuid call_status_flags_uuid; - Uuid call_state_uuid; - Uuid gtbs_ccid_uuid; - Uuid call_termination_reason_uuid; - Uuid incoming_call_uuid; - Uuid call_friendly_name_uuid; - //handle for characteristics - uint16_t call_state_handle; - uint16_t bearer_provider_name_handle; - uint16_t call_control_point_opcode_supported_handle; - uint16_t call_control_point_handle; - uint16_t bearer_uci_handle; - uint16_t bearer_technology_handle; - uint16_t bearer_uri_schemes_supported_handle; - uint16_t bearer_signal_strength_handle; - uint16_t bearer_signal_strength_report_interval_handle; - uint16_t bearer_list_currentcalls_handle; - uint16_t incoming_call_target_beareruri_handle; - uint16_t call_status_flags_handle; - uint16_t call_termination_reason_handle; - uint16_t incoming_call_handle; - uint16_t call_friendly_name_handle; - uint16_t ccid_handle; - uint16_t call_state_desc; - uint16_t bearer_provider_name_desc; - uint16_t call_control_point_opcode_supported_desc; - uint16_t call_control_point_desc; - uint16_t bearer_uci_desc; - uint16_t bearer_technology_desc; - uint16_t bearer_uri_schemes_supported_desc; - uint16_t bearer_signal_strength_desc; - uint16_t bearer_signal_strength_report_interval_desc; - uint16_t bearer_list_currentcalls_desc; - uint16_t incoming_call_target_bearerURI_desc; - uint16_t call_status_flags_desc; - uint16_t call_termination_reason_desc; - uint16_t incoming_call_desc; - uint16_t call_friendly_name_desc; - uint16_t ccid_desc; -}CcsControlServiceInfo_t; - -typedef struct { - call_connect_state_t state; - uint16_t call_state_notify; - uint16_t bearer_provider_name_notify; - uint16_t call_control_point_notify; - uint16_t call_control_point_opcode_supported_notify; - uint16_t bearer_technology_changed_notify; - uint16_t bearer_uci_notify; - uint16_t bearer_uri_schemes_supported_notify; - uint16_t bearer_current_calls_list_notify; - uint16_t bearer_signal_strength_notify; - uint16_t bearer_signal_strength_report_interval_notify; - uint16_t incoming_call_state_notify; - uint16_t incoming_call_target_URI_notify; - uint16_t status_flags_notify; - uint16_t call_termination_reason_notify; - uint16_t call_friendly_name_notify; - uint8_t signal_strength_report_interval; - alarm_t* signal_strength_reporting_timer; - bool congested; - int conn_id; - int trans_id; - int timeout; - int latency; - int interval; - int rx_phy; - int tx_phy; - int mtu; - - RawAddress peer_bda; - bool (*DeviceStateHandlerPointer[2])(uint32_t event, void* param); -}CallControllerDeviceList; - -typedef struct { - std::vector address; - int set_id; -}CallActiveDevice; - -typedef struct { - uint8_t index; - uint8_t state; - uint8_t flags; -}tCCS_CALL_STATE; - -typedef struct { - uint8_t index; - uint8_t incoming_target_uri[MAX_URI_LENGTH]; -}tCCS_INCOMING_CALL_URI; - -typedef struct { - uint8_t index; - uint8_t incoming_uri[MAX_URI_LENGTH]; -}tCCS_INCOMING_CALL; - -typedef struct { - uint8_t operation; - uint8_t index[MAX_NUM_INDICIES]; - uint8_t supported_flags; - char* uri; - uint32_t ccid; -}tCCS_CALL_CONTROL_POINT; - -typedef struct { - uint8_t opcode; - uint8_t index; - uint8_t response_status; - RawAddress remote_address; -}tCCS_CALL_CONTROL_RESPONSE; - -typedef struct { - uint16_t supported_flags; -}tCCS_STATUS_FLAGS; - -typedef struct { - uint16_t supp_opcode; -}tCCS_SUPP_OPTIONAL_OPCODES; - - -typedef struct { - uint8_t index; - uint8_t reason; -}tCCS_TERM_REASON; - -typedef struct { - uint8_t index; - uint8_t name[MAX_FRIENDLY_NAME_LEN]; -}tCCS_FRIENDLY_NAME; - -typedef struct { - uint32_t ccid; -}tCCS_CONTENT_CONTROL_ID; - -typedef struct { - RawAddress addr; -}tCCS_CONNECTION_CLOSE; - -typedef struct { - uint8_t list_length; - uint8_t call_index; - uint8_t call_state; - uint8_t call_flags; - uint8_t call_uri[MAX_URI_LENGTH]; - }tCCS_BEARER_LIST_CURRENT_CALLS; - -typedef struct { - uint8_t name[MAX_BEARER_NAME]; - uint8_t uci[MAX_UCI_NAME]; - uint8_t length; - uint8_t technology_type; - uint8_t signal; - uint8_t signal_report_interval; - int bearer_list_len; - uint8_t bearer_schemes_list[MAX_BEARER_LIST_LEN]; -}tCCS_BEARER_PROVIDER_INFO; - -typedef struct { - bool status; -}tCCS_BEARER_URI_SCHEMES; - -//Union ops -struct tCCS_CHAR_DESC_WRITE { - tCCS_CHAR_DESC_WRITE() {}; - ~tCCS_CHAR_DESC_WRITE() {}; - std::vector value; - uint8_t status; - uint16_t notification; - uint32_t trans_id; - uint32_t desc_handle; - uint32_t char_handle; - bool need_rsp; - bool prep_rsp; - //is to send notification -}; - -struct tCCS_CHAR_DESC_READ { - tCCS_CHAR_DESC_READ() {}; - ~tCCS_CHAR_DESC_READ() {}; - uint8_t status; - uint32_t trans_id; - uint32_t desc_handle; - uint32_t char_handle; -}; - -struct tCCS_CHAR_GATT_READ { - tCCS_CHAR_GATT_READ() {}; - ~tCCS_CHAR_GATT_READ() {}; - uint8_t status; - uint32_t trans_id; - uint32_t char_handle; -}; - -struct tCCS_CHAR_WRITE { - tCCS_CHAR_WRITE() {}; - ~tCCS_CHAR_WRITE() {}; - uint8_t status; - bool need_rsp; - bool prep_rsp; - uint16_t offset; - uint16_t trans_id; - uint32_t char_handle; - int len; - std::vector value; - uint8_t *data; -}; - -struct tCCS_CONNECTION { - uint8_t status; - CallControllerDeviceList remoteDevice; -}; - -struct tCCS_CONN_UPDATE { - tCCS_CONN_UPDATE() {}; - ~tCCS_CONN_UPDATE() {}; - uint8_t status; - CallControllerDeviceList *remoteDevice; -}; - -struct tCCS_DISCONNECTION { - tCCS_DISCONNECTION() {}; - ~tCCS_DISCONNECTION() {}; - uint8_t status; - CallControllerDeviceList *remoteDevice; -}; - -struct tCCS_CONGESTION { - tCCS_CONGESTION() {}; - ~tCCS_CONGESTION() {}; - bool congested; - CallControllerDeviceList *remoteDevice; -}; - -struct tCCS_PHY{ - tCCS_PHY(); - ~tCCS_PHY(); - uint8_t status; - uint8_t tx_phy; - uint8_t rx_phy; - CallControllerDeviceList *remoteDevice; -}; - -struct tCCS_MTU { - tCCS_MTU() {}; - ~tCCS_MTU() {}; - uint8_t status; - uint16_t mtu; - CallControllerDeviceList *remoteDevice; -}; - -struct tCCS_SET_ACTIVE_DEVICE { - tCCS_SET_ACTIVE_DEVICE() {}; - ~tCCS_SET_ACTIVE_DEVICE() {}; - RawAddress address; - uint16_t set_id; -}; - -struct tCALL_CONTROL_UPDATE { - tCALL_CONTROL_UPDATE() {}; - ~tCALL_CONTROL_UPDATE() {}; - std::vector data; -}; - -union CALL_CONTROL_OPERATION{ - CALL_CONTROL_OPERATION() : CallControllerOp() { - }; - ~CALL_CONTROL_OPERATION() {}; - tCALL_CONTROL_UPDATE CallControllerOp; - tCCS_SET_ACTIVE_DEVICE SetActiveDeviceOp; - tCCS_CHAR_DESC_WRITE WriteDescOp; - tCCS_CHAR_DESC_READ ReadDescOp; - tCCS_CHAR_WRITE WriteOp; - tCCS_CHAR_GATT_READ ReadOp; - tCCS_CONNECTION ConnectionOp; - tCCS_CONN_UPDATE ConnectionUpdateOp; - tCCS_DISCONNECTION DisconnectionOp; - tCCS_CONGESTION CongestionOp; - tCCS_MTU MtuOp; - tCCS_PHY PhyOp; -}; - -typedef union CALL_CONTROL_OPERATION tCCS_OPERATION; - -struct tcc_resp_t { - tcc_resp_t() {}; - ~tcc_resp_t() {}; - uint32_t event = 0; - uint16_t handle = 0; - uint16_t status = 0; - bool force = false; - CallControllerDeviceList *remoteDevice = nullptr; - tGATTS_RSP rsp_value; - tCCS_OPERATION oper; - }; - -class CallController { - - public: - virtual ~CallController() = default; - static void Initialize(bluetooth::call_control::CallControllerCallbacks* callbacks, - Uuid app_id, int max_ccs_clients, bool inband_ringing_enabled); - static void CleanUp(); - static CallController* Get(); - static bool IsCcServiceRunnig(); - - virtual void CallState(int len, std::vector value) = 0; - virtual void BearerInfoName(uint8_t* bearer_name) = 0; - virtual void UpdateBearerTechnology(int tech_type) = 0; - virtual void UpdateSupportedBearerList(uint8_t* list) = 0; - virtual void UpdateIncomingCallTargetUri(int index, uint8_t* target_uri) = 0; - virtual void UpdateIncomingCall(int index, uint8_t* Uri) = 0; - virtual void UpdateBearerSignalStrength(int signal) = 0; - virtual void UpdateStatusFlags(uint8_t status_flag) = 0; - virtual void CallControlOptionalOpSupported(int feature) = 0; - virtual void CallControlResponse(uint8_t op, uint8_t index, uint32_t status, const RawAddress& address)= 0; - virtual void SetActiveDevice(const RawAddress& address, int setId) = 0; - virtual void ContentControlId(uint32_t ccid) = 0; - virtual void Disconnect(const RawAddress& bd_add) = 0; -}; - -void HandleCcsEvent(uint32_t event, void* param); -bool CCSHandler(uint32_t event, void* param); -void CcpCongestionUpdate(tcc_resp_t * p_data); diff --git a/le_audio/system/bt/bta/include/bta_csip_api.h b/le_audio/system/bt/bta/include/bta_csip_api.h deleted file mode 100644 index 4efb422b4943c9983961b50f1258c26a83479d7b..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/include/bta_csip_api.h +++ /dev/null @@ -1,396 +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. - * - ******************************************************************************/ - - -/****************************************************************************** - * - * This is the public interface file to provide CSIP API's. - * - ******************************************************************************/ - -#ifndef BTA_CSIP_API_H -#define BTA_CSIP_API_H - -//#include "bta_api.h" -#include -#include - -#include "bta_gatt_api.h" //temp - -#include - -#define SIRK_SIZE 16 // SIRK Size -#define UNLOCK_VALUE 0x01 // UNLOCK Value -#define LOCK_VALUE 0x02 // LOCK Value -#define ENCRYPTED_SIRK 0x00 // Encrypted SIRK Type -#define PLAINTEXT_SIRK 0x01 // Plain Text SIRK -#define INVALID_SET_ID 0x10 // Invalid set id - -/* status for applications for LOCK Status changed callback*/ -enum { - LOCK_RELEASED, // (LOCK Released successfully) - LOCK_RELEASED_TIMEOUT, // (LOCK Released by timeout) - ALL_LOCKS_ACQUIRED, // (LOCK Acquired for all requested set members) - SOME_LOCKS_ACQUIRED_REASON_TIMEOUT, // (Request timeout for some set members) - SOME_LOCKS_ACQUIRED_REASON_DISC, // (Some of the set members were disconnected) - LOCK_DENIED, // (Denied by one of the set members) - INVALID_REQUEST_PARAMS, // (Upper layer provided invalid parameters) - LOCK_RELEASE_NOT_ALLOWED, // (Response from remote (PTS)) - INVALID_VALUE, // (Response from remote (PTS)) -}; - -/* LOCK Request Error Codes from set members */ -#define CSIP_LOCK_DENIED 0x80 -#define CSIP_LOCK_RELEASE_NOT_ALLOWED 0x81 -#define CSIP_INVALID_LOCK_VALUE 0x82 -#define CSIP_LOCK_ALREADY_GRANTED 0x84 - -/* Events when CSIP operations are completed */ -#define BTA_CSIP_NEW_SET_FOUND_EVT 1 -#define BTA_CSIP_SET_MEMBER_FOUND_EVT 2 -#define BTA_CSIP_CONN_STATE_CHG_EVT 3 -#define BTA_CSIP_LOCK_STATUS_CHANGED_EVT 4 -#define BTA_CSIP_LOCK_AVAILABLE_EVT 5 -#define BTA_CSIP_SET_SIZE_CHANGED 6 -#define BTA_CSIP_SET_SIRK_CHANGED 7 - -/* CSIP operation completed event*/ -typedef uint8_t tBTA_CSIP_EVT; - -enum { - BTA_CSIP_SUCCESS, - BTA_CSIP_FAILURE, -}; - -/* CSIP Operation Status*/ -typedef uint8_t tBTA_CSIP_STATUS; - -/* CSIP GATT Connection States (to be notified to upper layer)*/ -/* Mapping to BluetoothProfile Connection States*/ -enum { - BTA_CSIP_DISCONNECTED, - BTA_CSIP_CONNECTED = 0x02, -}; - - /* CSIP device GATT Connection state */ -typedef uint8_t tBTA_CSIP_CONN_STATE; - -enum { - BTA_CSIP_CONN_ESTABLISHED = 0x40, // reason values to be decided - BTA_CSIP_CONN_ESTABLISHMENT_FAILED, - BTA_CSIP_APP_ALREADY_CONNECTED, - BTA_CSIP_APP_ALREADY_DISCONNECTED, - BTA_CSIP_APP_DISCONNECTED, - BTA_CSIP_DISCONNECT_WITHOUT_CONNECT, - BTA_CSIP_COORDINATED_SET_NOT_SUPPORTED, -}; - -/* CSIP device GATT Connection state */ -typedef uint8_t tBTA_CSIP_CONN_STATUS; - -/* Params in callback to requesting app when lock status has been changed */ -typedef struct { - uint8_t app_id; - uint8_t set_id; - uint8_t value = UNLOCK_VALUE; - uint8_t status; - std::vector addr; -} tBTA_LOCK_STATUS_CHANGED; - -/* Params in callback to registered app when coordinated set member is discovered */ -typedef struct { - uint8_t set_id; - bluetooth::Uuid uuid; - RawAddress addr; -} tBTA_SET_MEMBER_FOUND; - -/* Params in callback to registered app when discovery for coordinated set is completed */ -/*TODO: not required, to be removed */ -typedef struct { - uint8_t set_id; - bluetooth::Uuid uuid; - std::vector addr; -} tBTA_SET_DISC_CMPL; - -/* params in callback to app when lock is available on earlier denied member*/ -typedef struct { - uint8_t app_id; - uint8_t set_id; - RawAddress addr; -} tBTA_LOCK_AVAILABLE; - -/* params in callback to app space when new set is found*/ -typedef struct { - uint8_t set_id; - uint8_t sirk[SIRK_SIZE]; - uint8_t size; - bool lock_support; - RawAddress addr; - bluetooth::Uuid including_srvc_uuid; -} tBTA_CSIP_NEW_SET_FOUND; - -/* params in callback to app when set size is changed */ -typedef struct { - uint8_t set_id; - uint8_t size; - RawAddress addr; -} tBTA_CSIP_SET_SIZE_CHANGED; - -/* params in callback to app when set sirk is changed */ -typedef struct { - uint8_t set_id; - uint8_t* sirk; - RawAddress addr; -} tBTA_CSIP_SET_SIRK_CHANGED; - -/* params in callback to app when connection state has been changed */ -typedef struct { - uint8_t app_id; - RawAddress addr; - tBTA_CSIP_CONN_STATE state; - tBTA_CSIP_CONN_STATUS status; -} tBTA_CSIP_CONN_STATE_CHANGED; - -/* callbacks params on completion of CSIP operations */ -typedef union { - tBTA_LOCK_STATUS_CHANGED lock_status_param; - tBTA_CSIP_CONN_STATE_CHANGED conn_params; - tBTA_SET_MEMBER_FOUND set_member_param; - tBTA_SET_DISC_CMPL set_disc_cmpl_param; - tBTA_LOCK_AVAILABLE lock_available_param; - tBTA_CSIP_NEW_SET_FOUND new_set_params; - tBTA_CSIP_CONN_STATE_CHANGED conn_chg_params; - tBTA_CSIP_SET_SIZE_CHANGED size_chg_params; - tBTA_CSIP_SET_SIRK_CHANGED sirk_chg_params; -} tBTA_CSIP_DATA; - -/* CSIP callbacks to be given to upper layers*/ - -/* Callback given when one of the operation mentioned in */ -typedef void (tBTA_CSIP_CBACK) (tBTA_CSIP_EVT event, tBTA_CSIP_DATA* p_data); - -/* Callback when application is registered with CSIP */ -typedef void (tBTA_CSIP_CLT_REG_CB) (tBTA_CSIP_STATUS status, uint8_t app_id); - -/* parameters used for api BTA_CsipSetLockValue() */ -typedef struct { - uint8_t app_id; - uint8_t set_id; - uint8_t lock_value; - std::vector members_addr; -} tBTA_SET_LOCK_PARAMS; - -/* Coordinated set details */ -typedef struct { - uint8_t set_id; - uint8_t size; - uint8_t total_discovered; - bool lock_support; - std::vector set_members; - bluetooth::Uuid p_srvc_uuid; -} tBTA_CSIP_CSET; - -using BtaCsipAppRegisteredCb = - base::Callback; - -/********************************************************************************* - * - * Function BTA_RegisterCsipApp - * - * Description This function is called to register application or module to - * to register with CSIP for using CSIP functionalities. - * - * Parameters p_csip_cb: callback to be received in registering app when - * required CSIP operation is completed. - * reg_cb : callback when app/module is registered with CSIP. - * - * Returns None - * - *********************************************************************************/ -extern void BTA_RegisterCsipApp(tBTA_CSIP_CBACK* p_csip_cb, - BtaCsipAppRegisteredCb reg_cb); - -/********************************************************************************* - * - * Function BTA_UnregisterCsipApp - * - * Description This function is called to register application or module to - * to register with CSIP for using CSIP functionalities. - * - * Parameters app_id: Identifier of the app that needs to be unregistered. - * - * Returns None - * - *********************************************************************************/ -extern void BTA_UnregisterCsipApp(uint8_t app_id); - -/********************************************************************************* - * - * Function BTA_CsipSetLockValue - * - * Description This function is called to request or release lock for the - * coordinated set. - * - * Parameters lock_param: parameters to acquire or release lock. - * (tBTA_SET_LOCK_PARAMS). - * - * Returns None - * - *********************************************************************************/ -extern void BTA_CsipSetLockValue(tBTA_SET_LOCK_PARAMS lock_param); - -/********************************************************************************* - * - * Function BTA_CsipGetCoordinatedSet - * - * Description This function is called to fetch details of the coordinated set. - * - * Parameters set_id: identifier of the coordinated set whose details are - * required to be fetched. - * - * Returns tBTA_CSIP_CSET (containing details of coordinated set). - * - *********************************************************************************/ -extern tBTA_CSIP_CSET BTA_CsipGetCoordinatedSet(uint8_t set_id); - -/********************************************************************************* - * - * Function BTA_CsipSetLockValue - * - * Description This function is called to request or release lock for the - * coordinated set. - * - * Parameters None. - * - * Returns vector: (all discovered coordinated set) - * - *********************************************************************************/ -extern std::vector BTA_CsipGetDiscoveredSets(); - -/********************************************************************************* - * - * Function BTA_CsipConnect - * - * Description This function is called to establish GATT Connection. - * - * Parameters bd_addr : Address of the remote device. - * - * Returns None. - * - * Note This shouldnt be used by registered module. CSIP Profile - * internally manages GATT Connection. - * - *********************************************************************************/ -extern void BTA_CsipConnect (uint8_t app_id, const RawAddress& bd_addr); - -/********************************************************************************* - * - * Function BTA_CsipConnect - * - * Description This function is called to establish GATT Connection. - * - * Parameters bd_addr : Address of the remote device. - * - * Returns None. - * - * Note This shouldnt be used by registered module. CSIP Profile - * internally manages GATT Connection. - * - *********************************************************************************/ -extern void BTA_CsipDisconnect (uint8_t app_id, const RawAddress& bd_addr); - - -/********************************************************************************* - * - * Function BTA_CsipEnable - * - * Description This function is invoked to initialize CSIP in BTA layer. - * - * Parameters p_cback: callbacks registered with btif_csip module. - * - * Returns None. - * - * Note This API shouldn't be used by other BT modules. - * - *********************************************************************************/ -extern void BTA_CsipEnable(tBTA_CSIP_CBACK *p_cback); - -/********************************************************************************* - * - * Function BTA_CsipEnable - * - * Description This function is invoked to deinitialize CSIP in BTA layer. - * - * Parameters None. - * - * Returns None. - * - * Note This API shouldn't be used by other BT modules. - * - *********************************************************************************/ -extern void BTA_CsipDisable(); - -/********************************************************************************* - * - * Function BTA_CsipFindCsisInstance - * - * Description This function is invoked to find presence of CSIS service on - * remote device and start coordinated set discovery. - * - * Parameters conn_id: GATT Connection ID used for getting remote services - * status : Status of the discovery procedure - * - * Returns None. - * - * Note This API shouldn't be used by other BT modules. - * - *********************************************************************************/ -extern void BTA_CsipFindCsisInstance(uint16_t conn_id, tGATT_STATUS status, - RawAddress& bd_addr); - -/********************************************************************************* - * - * Function BTA_CsipRemoveUnpairedSetMember - * - * Description This function is called when a given set member is unpaired. - * - * Parameters addr: BD Address of the set member. - * - * Returns None. - * - * Note This API shouldn't be used by other BT modules. - * - *********************************************************************************/ -void BTA_CsipRemoveUnpairedSetMember(RawAddress addr); - -/********************************************************************************* - * - * Function BTA_CsipGetDeviceSetId - * - * Description This API is used to get set id of the remote device. - * - * Parameters addr: BD Address of the set member. - * uuid: UUID of the service which includes CSIS service. - * - * Returns None. - * - *********************************************************************************/ -uint8_t BTA_CsipGetDeviceSetId(RawAddress addr, bluetooth::Uuid uuid); - - -#endif /* BTA_CSIP_API_H */ diff --git a/le_audio/system/bt/bta/include/bta_dm_adv_audio.h b/le_audio/system/bt/bta/include/bta_dm_adv_audio.h deleted file mode 100644 index d7fe588ae5465657860b56112ad01cc401d2e049..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/include/bta_dm_adv_audio.h +++ /dev/null @@ -1,152 +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. - * - ******************************************************************************/ - -#ifndef BTA_DM_ADV_AUDIO_H -#define BTA_DM_ADV_AUDIO_H - -#include "stack/include/bt_types.h" -#include "bta/dm/bta_dm_int.h" -#include -#include -#include "bt_target.h" -#include "bta_sys.h" - -#include "bta_gatt_api.h" - -#define UUID_SERVCLASS_CSIS 0x1846 /* Coordinated Set Identification Service */ -#define UUID_SERVCLASS_PACS 0x1850 /* LE AUDIO PACS */ -#define UUID_SERVCLASS_ASCS 0x184E /* LE AUDIO ASCS */ -#define UUID_SERVCLASS_BASS 0x184F /* LE AUDIO BASS */ -#define UUID_SERVCLASS_BAAS 0x1851 /* LE AUDIO BAAS */ -#define UUID_SERVCLASS_BRASS 0x1852 /* LE AUDIO BRASS */ -#define UUID_SERVCLASS_T_ADV_AUDIO 0x1FA0 /* LE AUDIO T_ADV_AUDIO */ -#define UUID_SERVCLASS_CSIS_LOCK 0x2B86 /* LE AUDIO CSIS LOCK */ -#define UUID_SERVCLASS_T_ADV_AUDIO_ROLE_CHAR 0xFE00 /*LE AUDIO CSIS LOCK */ -#define UUID_SERVCLASS_T_ADV_AUDIO_MEDIA_SINK 0x6AD0 -#define UUID_SERVCLASS_T_ADV_AUDIO_VOICE 0x6AD5 -#define UUID_SERVCLASS_T_ADV_AUDIO_CONN_LESS_MEDIA_SINK 0xFFA6 -#define UUID_SERVCLASS_T_ADV_AUDIO_ASSIST 0xFFA7 -#define UUID_SERVCLASS_T_ADV_AUDIO_DELEGATE 0xFFA8 -#define UUID_SERVCLASS_HAS 0x6AD2 -#define UUID_SERVCLASS_SOURCE_CONTEXT 0x2BCE -#define UUID_SERVCLASS_PACS_CT_SUPPORT 0x6AD4 -#define UUID_SERVCLASS_PACS_UMR_SUPPORT 0x6AD1 - -#define BTA_DM_LE_AUDIO_SEARCH_CMPL_EVT 7 - -#define BTA_DM_GROUP_DATA_TYPE 0x2E - -typedef struct { - RawAddress peer_address; - bool in_use =false; - bool is_t_audio_srvc_found = false; - bool is_has_found = false; - std::vector uuids; - int transport; //BTM_UseLeLink(remote_bda); - int conn_id = 0; - int8_t disc_progress = 0; - uint8_t gatt_if; - bool using_bredr_bonding = false; - uint16_t t_role_handle = 0; - uint16_t pacs_char_handle = 0; - bool csip_disc_progress = true; - bool is_csip_support = false; - bool gatt_disc_progress = false; -} tBTA_LE_AUDIO_DEV_INFO; - -typedef struct { - RawAddress p_addr; - RawAddress p_id_addr; - bool is_le_pairing = false; - bool in_use = false; - bool is_dumo_device = false; - uint8_t dev_type; - uint8_t transport; - bool sdp_disc_status = true; -} tBTA_DEV_PAIRING_CB; - -#define MAX_LEA_DEVICES 3 -typedef struct { - tBTA_DEV_PAIRING_CB bta_dev_pair_db[MAX_LEA_DEVICES]; - uint8_t num_devices; - bool is_pairing_progress = false; - std::map dev_addr_map; - std::map dev_rand_addr_map; - RawAddress pending_address; - bool is_sdp_discover = true; -} tBTA_LEA_PAIRING_DB; - - -typedef struct { - tBTA_LE_AUDIO_DEV_INFO bta_lea_dev_info[MAX_LEA_DEVICES]; - RawAddress pending_peer_addr; - RawAddress gatt_op_addr = RawAddress::kEmpty; - int num_lea_devices = 0; - bool bond_progress = false; -} tBTA_LE_AUDIO_DEV_CB; - -extern tBTA_LE_AUDIO_DEV_CB bta_le_audio_dev_cb; -extern bool is_remote_support_adv_audio(const RawAddress remote_bdaddr); -extern void bta_adv_audio_update_bond_db(RawAddress p_bd_addr, uint8_t transport); -extern bool is_le_audio_service(bluetooth::Uuid uuid); -extern int bta_is_adv_audio_valid_bdaddr(RawAddress p_bd_addr); -extern bool bta_is_le_audio_supported(RawAddress p_bd_addr); -extern bool bta_remote_device_is_dumo(RawAddress p_bd_addr); -extern RawAddress bta_get_rem_dev_id_addr(RawAddress p_bd_addr); -extern tBTA_DEV_PAIRING_CB* bta_get_lea_pair_cb(RawAddress peer_addr); -extern bool bta_lea_addr_match(RawAddress p_bd_addr); -extern void bta_dm_reset_lea_pairing_info(RawAddress p_addr); -extern bool bta_is_bredr_primary_transport(RawAddress p_bd_addr); -extern bool bta_is_remote_support_lea(RawAddress p_addr); -extern bool bta_remote_dev_identity_addr_match(RawAddress p_addr); -extern void bta_dm_lea_disc_complete(RawAddress p_bd_addr); -extern void bta_dm_csis_disc_complete(RawAddress p_bd_addr, bool status); -extern tBTA_LE_AUDIO_DEV_INFO* bta_get_lea_ctrl_cb(RawAddress peer_addr); -extern void bta_gap_gatt_read_cb(uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, uint16_t len, - uint8_t* value, void* data); -extern void bta_get_adv_audio_role(RawAddress peer_address, uint16_t conn_id, - tGATT_STATUS status); -extern void bta_dm_csis_disc_complete(RawAddress p_bd_addr, bool status); -extern void bta_dm_lea_disc_complete(RawAddress p_bd_addr); -extern void bta_add_adv_audio_uuid(RawAddress peer_address, - tBTA_GATT_ID srvc_uuid); -extern tBTA_LE_AUDIO_DEV_INFO* bta_set_lea_ctrl_cb(RawAddress peer_addr); -extern void bta_dm_reset_adv_audio_dev_info(RawAddress p_addr); -extern void bta_dm_set_adv_audio_dev_info(tBTA_GATTC_OPEN* p_data); -extern bool is_adv_audio_group_supported(RawAddress rem_bda, int conn_id); -extern void bta_dm_lea_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data); -extern void bta_dm_adv_audio_gatt_conn(RawAddress p_bd_addr); -extern void bta_dm_adv_audio_close(RawAddress p_bd_addr); -extern tBTA_DEV_PAIRING_CB* bta_get_lea_pair_cb(RawAddress peer_addr); -extern tBTA_DEV_PAIRING_CB* bta_set_lea_pair_cb(RawAddress peer_addr); -extern void bta_dm_reset_lea_pairing_info(RawAddress p_addr); -extern void bta_dm_ble_adv_audio_idaddr_map(RawAddress p_bd_addr, - RawAddress p_id_addr); -extern bool bta_remote_dev_identity_addr_match(RawAddress p_addr); -extern bool bta_lea_is_le_pairing(RawAddress p_bd_addr); -extern bool bta_remote_device_is_dumo(RawAddress p_bd_addr); -extern RawAddress bta_get_rem_dev_id_addr(RawAddress p_bd_addr); -extern void bta_adv_audio_update_bond_db(RawAddress p_bd_addr, uint8_t transport); -extern int bta_is_adv_audio_valid_bdaddr(RawAddress p_bd_addr); -extern void bta_find_adv_audio_group_instance(uint16_t conn_id, tGATT_STATUS status, - RawAddress p_addr); -extern bool bta_is_remote_support_lea(RawAddress p_addr); -extern bool is_gatt_srvc_disc_pending(RawAddress rem_bda); -extern RawAddress bta_get_pseudo_addr_with_id_addr(RawAddress p_addr); -#endif /* BTA_DM_ADV_AUDIO_H*/ diff --git a/le_audio/system/bt/bta/include/bta_mcp_api.h b/le_audio/system/bt/bta/include/bta_mcp_api.h deleted file mode 100644 index de6dfc77d29524b9a552b63b0eee3ddd26282275..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/include/bta_mcp_api.h +++ /dev/null @@ -1,489 +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. - * - ******************************************************************************/ - - -#ifndef BTA_MCP_API_H -#define BTA_MCP_API_H - -#include -#include -#include -#include -#include -#include "bta_gatt_api.h" - -using bluetooth::Uuid; -using bluetooth::mcp_server::McpServerCallbacks; - - -#define MAX_PLAYER_NAME_SIZE GATT_MAX_ATTR_LEN -#define MAX_TRACK_TITLE_SIZE GATT_MAX_ATTR_LEN -#define MAX_RESPONSE_DATA_LEN GATT_MAX_ATTR_LEN -#define MAX_MCP_CONNECTION 5 - -#define TRACK_POSITION_UNAVAILABLE 0xFFFFFFFF -#define TRACK_DURATION_UNAVAILABLE 0xFFFFFFFF - -/* Media Control Point Opcodes Supported characteristics bit values */ -#define MCP_MEDIA_CONTROL_SUP_PLAY 1<<0 -#define MCP_MEDIA_CONTROL_SUP_PAUSE 1<<1 -#define MCP_MEDIA_CONTROL_SUP_FAST_REWIND 1<<2 -#define MCP_MEDIA_CONTROL_SUP_FAST_FORWARD 1<<3 -#define MCP_MEDIA_CONTROL_SUP_STOP 1<<4 -#define MCP_MEDIA_CONTROL_SUP_MOVE_RELATIVE 1<<5 -#define MCP_MEDIA_CONTROL_SUP_PREVIOUS_SEGMENT 1<<6 -#define MCP_MEDIA_CONTROL_SUP_NEXT_SEGMENT 1<<7 -#define MCP_MEDIA_CONTROL_SUP_FIRST_SEGMENT 1<<8 -#define MCP_MEDIA_CONTROL_SUP_LAST_SEGMENT 1<<9 -#define MCP_MEDIA_CONTROL_SUP_GOTO_SEGMENT 1<<10 -#define MCP_MEDIA_CONTROL_SUP_PREVIOUS_TRACK 1<<11 -#define MCP_MEDIA_CONTROL_SUP_NEXT_TRACK 1<<12 -#define MCP_MEDIA_CONTROL_SUP_FIRST_TRACK 1<<13 -#define MCP_MEDIA_CONTROL_SUP_LAST_TRACK 1<<14 -#define MCP_MEDIA_CONTROL_SUP_GOTO_TRACK 1<<15 -#define MCP_MEDIA_CONTROL_SUP_PREVIOUS_GROUP 1<<16 -#define MCP_MEDIA_CONTROL_SUP_NEXT_GROUP 1<<17 -#define MCP_MEDIA_CONTROL_SUP_FIRST_GROUP 1<<18 -#define MCP_MEDIA_CONTROL_SUP_LAST_GROUP 1<<19 -#define MCP_MEDIA_CONTROL_SUP_GOTO_GROUP 1<<20 - -//media control point opcodes -#define MCP_MEDIA_CONTROL_OPCODE_PLAY 0x01 -#define MCP_MEDIA_CONTROL_OPCODE_PAUSE 0x02 -#define MCP_MEDIA_CONTROL_OPCODE_FAST_REWIND 0x03 -#define MCP_MEDIA_CONTROL_OPCODE_FAST_FORWARD 0x04 -#define MCP_MEDIA_CONTROL_OPCODE_STOP 0x05 -#define MCP_MEDIA_CONTROL_OPCODE_PREV_TRACK 0x30 -#define MCP_MEDIA_CONTROL_OPCODE_NEXT_TRACK 0x31 -#define MCP_MEDIA_CONTROL_OPCODE_MOVE_RELATIVE 0x10 - -/* Playing Order Supported characteristic bit values */ -#define MCP_PLAYING_OREDR_SINGLE_ONCE 1<<0 -#define MCP_PLAYING_OREDR_SINGLE_REPEAT 1<<1 -#define MCP_PLAYING_OREDR_IN_ORDER_ONCE 1<<2 -#define MCP_PLAYING_OREDR_IN_ORDER_REPEAT 1<<3 -#define MCP_PLAYING_OREDR_OLDEST_ONCE 1<<4 -#define MCP_PLAYING_OREDR_OLDEST_REPEAT 1<<5 -#define MCP_PLAYING_OREDR_NEWEST_ONCE 1<<6 -#define MCP_PLAYING_OREDR_NEWEST_REPEAT 1<<7 -#define MCP_PLAYING_OREDR_SHUFFLE_ONCE 1<<8 -#define MCP_PLAYING_OREDR_SHUFFLE_REPEAT 1<<9 - -#define MCP_DEFAULT_MEDIA_CTRL_SUPP_FEAT MCP_MEDIA_CONTROL_SUP_PLAY| \ - MCP_MEDIA_CONTROL_SUP_PAUSE| \ - MCP_MEDIA_CONTROL_SUP_FAST_REWIND| \ - MCP_MEDIA_CONTROL_SUP_FAST_FORWARD| \ - MCP_MEDIA_CONTROL_SUP_STOP| \ - MCP_MEDIA_CONTROL_SUP_PREVIOUS_TRACK| \ - MCP_MEDIA_CONTROL_SUP_NEXT_TRACK - -typedef enum { - // TO-DO: Naming in such a way to distinguish BTIF and lower layer events - MCP_NONE_EVENT = 70, - MCP_INIT_EVENT, - MCP_CLEANUP_EVENT, - MCP_MEDIA_STATE_UPDATE, - MCP_MEDIA_PLAYER_NAME_UPDATE, - MCP_MEDIA_SUPPORTED_OPCODE_UPDATE, - MCP_MEDIA_CONTROL_POINT_UPDATE, - MCP_PLAYING_ORDER_SUPPORTED_UPDATE, - MCP_PLAYING_ORDER_UPDATE, - MCP_TRACK_CHANGED_UPDATE, - MCP_TRACK_POSITION_UPDATE, - MCP_TRACK_DURATION_UPDATE, - MCP_TRACK_TITLE_UPDATE, - MCP_CCID_UPDATE, - MCP_ACTIVE_DEVICE_UPDATE, - MCP_ACTIVE_PROFILE, - - //local event to handle in mcp state machine, - MCP_PLAYING_ORDER_SUPPORTED_READ, - MCP_PLAYING_ORDER_READ, - MCP_MEDIA_STATE_READ, - MCP_MEDIA_CONTROL_POINT_OPCODE_SUPPORTED_READ, - MCP_MEDIA_PLAYER_NAME_READ, - MCP_TRACK_TITLE_READ, - MCP_TRACK_POSITION_READ, - MCP_TRACK_DURATION_READ, - MCP_CCID_READ, - MCP_SEEKING_SPEED_READ, - MCP_MEDIA_STATE_READ_DESCRIPTOR, - MCP_MEDIA_CONTROL_POINT_READ_DESCRIPTOR, - MCP_MEDIA_CONTROL_POINT_OPCODE_SUPPORTED_DESCRIPTOR_READ, - MCP_MEDIA_PLAYER_NAME_DESCRIPTOR_READ, - MCP_TRACK_CHANGED_DESCRIPTOR_READ, - MCP_TRACK_TITLE_DESCRIPTOR_READ, - MCP_TRACK_POSITION_DESCRIPTOR_READ, - MCP_TRACK_DURATION_DESCRIPTOR_READ, - MCP_PLAYING_ORDER_DESCRIPTOR_READ, - MCP_MEDIA_STATE_DESCRIPTOR_WRITE, - MCP_MEDIA_PLAYER_NAME_DESCRIPTOR_WRITE, - MCP_MEDIA_CONTROL_POINT_DESCRIPTOR_WRITE, - MCP_MEDIA_CONTROL_POINT_SUPPORTED_DESCRIPTOR_WRITE, - MCP_TRACK_CHANGED_DESCRIPTOR_WRITE, - MCP_TRACK_TITLE_DESCRIPTOR_WRITE, - MCP_TRACK_POSITION_DESCRIPTOR_WRITE, - MCP_TRACK_DURATION_DESCRIPTOR_WRITE, - MCP_PLAYING_ORDER_DESCRIPTOR_WRITE, - MCP_MEDIA_CONTROL_POINT_WRITE, - MCP_PLAYING_ORDER_WRITE, - MCP_TRACK_POSITION_WRITE, -//device state event - MCP_NOTIFY_ALL, - MCP_WRITE_RSP, - MCP_READ_RSP, - MCP_DESCRIPTOR_WRITE_RSP, - MCP_DESCRIPTOR_READ_RSP, - MCP_CONNECTION, - MCP_DISCONNECTION, - MCP_CONNECTION_UPDATE, - MCP_CONGESTION_UPDATE, - MCP_PHY_UPDATE, - MCP_MTU_UPDATE, - MCP_SET_ACTIVE_DEVICE, - MCP_CONNECTION_CLOSE_EVENT, - MCP_BOND_STATE_CHANGE_EVENT, -//media write op code event - MCP_MEDIA_CONTROL_PLAY_READ_REQ, - MCP_MEDIA_CONTROL_PAUSE_REQ, - MCP_MEDIA_CONTROL_FAST_FORWARD_REQ, - MCP_MEDIA_CONTROL_FAST_REWIND_REQ, - MCP_MEDIA_CONTROL_MOVE_RELATIVE_REQ, - MCP_MEDIA_CONTROL_STOP_REQ, - MCP_MEDIA_CONTROL_NEXT_TRACK_REQ, - MCP_MEDIA_CONTROL_PREVIOUS_TRACK_REQ, - MCP_PLAYING_OREDR_SHUFFLE_REPEAT_REQ, - -}mcp_event_t; - -//state handler declaration -typedef bool (*mcp_handler)(uint32_t event, void* param, uint8_t state); -typedef enum { - //media conrol point success or error code - MCP_STATUS_SUCCESS = 1, - MCP_OPCODE_NOT_SUPPORTED, - MCP_MEDIA_PLAYER_INACTIVE, - MCP_COMMAND_CANNOT_COMPLETED, - - BT_STATUS_DEVICE_NOT_CONNECTED, - BT_STATUS_HANLDE_NOT_MATCHED, -}mcp_error_t; - -typedef enum { - MCP_DISCONNECTED = 0x00, - MCP_CONNECTED, - MCP_MAX_DEVICE_STATE -} remote_device_state_t; - -typedef enum { - MCP_STATE_INACTIVE = 0x00, - MCP_STATE_PLAYING, - MCP_STATE_PAUSE, - MCP_STATE_SEEKING, - MCP_MAX_MEDIA_STATE -} mcp_state_t; - -typedef struct { - uint8_t media_state; - uint16_t media_ctrl_point; - uint32_t media_supported_feature; - uint8_t player_name[MAX_PLAYER_NAME_SIZE]; - uint16_t player_name_len; - uint8_t track_changed; - int32_t duration; - int32_t position; - uint16_t playing_order_supported; - uint8_t playing_order_value; - uint8_t title[MAX_TRACK_TITLE_SIZE]; - uint16_t track_title_len; - uint8_t ccid; - uint8_t seeking_speed; - mcp_handler MediaStateHandlerPointer[MCP_MAX_MEDIA_STATE]; -} MediaPlayerInfo_t; - -typedef struct { - int server_if; - Uuid mcs_service_uuid; - Uuid media_state_uuid; - Uuid media_player_name_uuid; - Uuid media_control_point_uuid; - Uuid media_control_point_opcode_supported_uuid; - Uuid track_changed_uuid; - Uuid track_title_uuid; - Uuid track_duration_uuid; - Uuid track_position_uuid; - Uuid playing_order_supported_uuid; - Uuid playing_order_uuid; - Uuid ccid_uuid; - Uuid seeking_speed_uuid; - //handle for characteristics - uint16_t media_state_handle; - uint16_t media_player_name_handle; - uint16_t media_control_point_opcode_supported_handle; - uint16_t media_control_point_handle; - uint16_t track_changed_handle; - uint16_t track_title_handle; - uint16_t track_duration_handle; - uint16_t track_position_handle; - uint16_t playing_order_supported_handle; - uint16_t playing_order_handle; - uint16_t ccid_handle; - uint16_t seeking_speed_handle; - uint16_t media_state_desc; - uint16_t media_player_name_desc; - uint16_t media_control_point_opcode_supported_desc; - uint16_t media_control_point_desc; - uint16_t track_changed_desc; - uint16_t track_title_desc; - uint16_t track_duration_desc; - uint16_t track_position_desc; - uint16_t playing_order_supported_desc; - uint16_t playing_order_desc; - uint16_t ccid_desc; - uint16_t seeking_speed_desc; -} mcsServerServiceInfo_t; - -typedef struct { - remote_device_state_t state; - uint8_t active_profile; - uint16_t media_state_notify; - uint16_t media_player_name_notify; - uint16_t media_control_point_notify; - uint16_t media_control_point_opcode_supported_notify; - uint16_t track_changed_notify; - uint16_t track_duration_notify; - uint16_t track_title_notify; - uint16_t track_position_notify; - uint16_t playing_order_notify; - uint16_t seeking_speed_notify; - bool congested; - int conn_id; - int trans_id; - int timeout; - int latency; - int interval; - int rx_phy; - int tx_phy; - int mtu; - RawAddress peer_bda; - mcp_handler DeviceStateHandlerPointer[MCP_MAX_DEVICE_STATE]; -}RemoteDevice; - -typedef struct { - std::vector address; - int set_id; -}ActiveDevice; - -typedef struct { - uint8_t status; - uint16_t notification; - uint32_t trans_id; - uint32_t desc_handle; - uint32_t char_handle; - bool need_rsp; - bool prep_rsp; - //is to send notification - uint8_t *data; - uint16_t len; -}tMCP_DESC_WRITE; - -typedef struct { - uint8_t status; - uint32_t trans_id; - uint32_t desc_handle; - uint32_t char_handle; -}tMCP_DESC_READ; - -typedef struct { - bool is_long; - uint8_t status; - uint32_t trans_id; - uint32_t char_handle; -}tMCP_READ; - -typedef struct { - uint8_t status; - bool need_rsp; - bool prep_rsp; - uint16_t offset; - uint32_t trans_id; - uint16_t char_handle; - //is to send notification - uint8_t data[GATT_MAX_ATTR_LEN]; -}tMCP_WRITE; - -typedef struct { - uint8_t status; - RemoteDevice remoteDevice; -}tMCP_CONNECTION; - -typedef struct { - uint8_t status; - int timeout; - int latency; - int interval; -}tMCP_CONN_UPDATE; - -typedef struct { - uint8_t status; - RemoteDevice *remoteDevice; -}tMCP_DISCONNECTION; - -typedef struct { - bool congested; - RemoteDevice *remoteDevice; -} tMCP_CONGESTION; - -typedef struct { - uint8_t status; - uint8_t tx_phy; - uint8_t rx_phy; - RemoteDevice *remoteDevice; -} tMCP_PHY; - -typedef struct { - uint8_t status; - uint16_t mtu; - RemoteDevice *remoteDevice; -} tMCP_MTU; - -typedef struct { - uint8_t state; -}tMCP_MEDIA_STATE; - -typedef struct { - uint32_t req_opcode; - uint8_t result; -}tMCP_MEDIA_CONTROL_POINT; - -typedef struct { - uint32_t supported; -}tMCP_MEDIA_OPCODE_SUPPORT; - -typedef struct { - uint8_t *name; - uint16_t len; -}tMCP_MEDIA_PLAYER_NAME; - -typedef struct { - bool status; -}tMCP_TRACK_CHANGED; - -typedef struct { - int32_t position; -}tMCP_TRACK_POSTION; - -typedef struct { - uint32_t duration; -}tMCP_TRACK_DURATION; - -typedef struct { - uint8_t *title; - uint16_t len; -}tMCP_TRACK_TITLE; - -typedef struct { - uint8_t ccid; -}tMCP_CONTENT_CONTROL_ID; - -typedef struct { - uint8_t seek_speed; -}tMCP_SEEKING_SPEED_CONTROL_ID; - -typedef struct { - RawAddress addr; -}tMCP_CONNECTION_CLOSE; - -typedef struct { - RawAddress addr; - int state; -}tMCP_BOND_STATE_CHANGE; - -typedef struct { - uint32_t order_supported; -}tMCP_PLAYING_ORDER_SUPPORT; - -typedef struct { - uint8_t order; -}tMCP_PLAYING_ORDER; - -typedef struct { - RawAddress address; - uint16_t set_id; - uint8_t profile; -}tMCP_SET_ACTIVE_DEVICE; - -typedef struct { - uint8_t *data; - uint16_t len; -}tMCP_MEDIA_UPDATE; - -union tMCP_MEDIA_OPERATION{ - tMCP_MEDIA_UPDATE MediaUpdateOp; - tMCP_SET_ACTIVE_DEVICE SetActiveDeviceOp; - tMCP_DESC_WRITE WriteDescOp; - tMCP_DESC_READ ReadDescOp; - tMCP_WRITE WriteOp; - tMCP_READ ReadOp; - tMCP_CONNECTION ConnectionOp; - tMCP_CONN_UPDATE ConnectionUpdateOp; - tMCP_DISCONNECTION DisconnectionOp; - tMCP_CONGESTION CongestionOp; - tMCP_MTU MtuOp; - tMCP_PHY PhyOp; -}; - -typedef union tMCP_MEDIA_OPERATION tMCP_MEDIA_OPERATION; - -struct mcp_resp_t { - uint32_t event; - uint16_t handle; - uint16_t status; - RemoteDevice *remoteDevice; - tGATTS_RSP rsp_value; - tMCP_MEDIA_OPERATION oper; -}; - -typedef struct mcp_resp_t mcp_resp_t; - -class McpServer { - public: - virtual ~McpServer() = default; - static void Initialize(bluetooth::mcp_server::McpServerCallbacks* callbacks, Uuid ap_id); - static void CleanUp(); - static McpServer* Get(); - static bool isMcpServiceRunnig(); - virtual void MediaState(uint8_t state) = 0; - virtual void MediaPlayerName(uint8_t* player_name) = 0; - virtual void MediaControlPointOpcodeSupported(uint32_t feature) = 0; - virtual void MediaControlPoint(uint8_t value) = 0; - virtual void TrackChanged(bool status) = 0; - virtual void TrackDuration(int32_t duration) = 0; - virtual void TrackTitle(uint8_t* title) = 0; - virtual void TrackPosition(int32_t position) = 0; - virtual void PlayingOrderSupported(uint16_t order) = 0; - virtual void PlayingOrder(uint8_t value) = 0; - virtual void SetActiveDevice(const RawAddress& address, int setId, int profile) = 0; - virtual void ContentControlId(uint8_t ccid) = 0; - virtual void DisconnectMcp(const RawAddress& address) = 0; - virtual void BondStateChange(const RawAddress& address, int state) = 0; -}; - -void McpCongestionUpdate(mcp_resp_t *p_data); - -#endif // BTA_MCP_API_H diff --git a/le_audio/system/bt/bta/include/bta_pacs_client_api.h b/le_audio/system/bt/bta/include/bta_pacs_client_api.h deleted file mode 100644 index 1a364d8dc5c5e2f0c1e2eb767906ddabc0fd3b12..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/include/bta_pacs_client_api.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/* - * 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 - -namespace bluetooth { -namespace bap { -namespace pacs { - -class PacsClient { - public: - virtual ~PacsClient() = default; - - static void Initialize(bluetooth::bap::pacs::PacsClientCallbacks* callbacks); - static void CleanUp(uint16_t client_id); - static PacsClient* Get(); - virtual void Connect(uint16_t client_id, const RawAddress& address, - bool is_direct) = 0; - virtual void Disconnect(uint16_t client_id, - const RawAddress& address) = 0; - virtual void StartDiscovery(uint16_t client_id, - const RawAddress& address) = 0; - virtual void GetAudioAvailability(uint16_t client_id, - const RawAddress& address) = 0; -}; - -} // namespace pacs -} // namespace bap -} // namespace bluetooth diff --git a/le_audio/system/bt/bta/include/bta_vcp_controller_api.h b/le_audio/system/bt/bta/include/bta_vcp_controller_api.h deleted file mode 100644 index 8518262a91c4b9e19a5323ecbbc68df480eaccdb..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/include/bta_vcp_controller_api.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - *Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/****************************************************************************** - * - * 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 - -enum { - BTA_VCP_DISCONNECTED = 0x0, - BTA_VCP_CONNECTING, - BTA_VCP_CONNECTED, - BTA_VCP_DISCONNECTING, -}; - -enum { - VCS_VOLUME_STATE_READ_CMPL_EVT = 0x0, - VCS_VOLUME_FLAGS_READ_CMPL_EVT, - VCS_VOLUME_STATE_CCC_WRITE_CMPL_EVT, - VCS_VOLUME_FLAGS_CCC_WRITE_CMPL_EVT, -}; - -enum { - VCS_CONTROL_POINT_OP_REL_VOLUME_DOWN = 0x0, - VCS_CONTROL_POINT_OP_REL_VOLUME_UP, - VCS_CONTROL_POINT_OP_UNMUTE_REL_VOLUME_DOWN, - VCS_CONTROL_POINT_OP_UNMUTE_REL_VOLUME_UP, - VCS_CONTROL_POINT_OP_SET_ABS_VOL, - VCS_CONTROL_POINT_OP_UNMUTE, - VCS_CONTROL_POINT_OP_MUTE, -}; - -enum { - VCS_UNMUTE_STATE = 0x0, - VCS_MUTE_STATE, -}; - -typedef struct { - uint8_t op_id; - uint8_t change_counter; - uint8_t volume_setting; -} SetAbsVolumeOp; - -typedef struct { - uint8_t op_id; - uint8_t change_counter; -} MuteOp; - -typedef struct { - uint8_t op_id; - uint8_t change_counter; -} UnmuteOp; - -struct VolumeState { - uint8_t volume_setting; - uint8_t mute; - uint8_t change_counter; - - VolumeState() - : volume_setting(0), - mute(0), - change_counter(0) {} -}; - -struct VolumeControlService { - uint16_t volume_state_handle; - uint16_t volume_control_point_handle; - uint16_t volume_flags_handle; - uint16_t volume_state_ccc_handle; - uint16_t volume_flags_ccc_handle; - - VolumeState volume_state; - uint8_t volume_flags; - uint8_t pending_volume_setting; - uint8_t pending_mute_setting; - uint8_t retry_cmd; - - VolumeControlService() - : volume_state_handle(0), - volume_control_point_handle(0), - volume_flags_handle(0), - volume_state_ccc_handle(0), - volume_flags_ccc_handle(0), - volume_state(), - volume_flags(0), - pending_volume_setting(0), - pending_mute_setting(0), - retry_cmd(0) {} -}; - -struct RendererDevice { - RawAddress address; - uint16_t conn_id; - uint8_t state; - bool bg_conn; - bool service_changed_rcvd; - VolumeControlService vcs; - - RendererDevice(const RawAddress& address) - : address(address), - conn_id(0), - state(BTA_VCP_DISCONNECTED), - bg_conn(false), - service_changed_rcvd(false), - vcs() {} - - RendererDevice() : RendererDevice(RawAddress::kEmpty) {} -}; - -class VcpController { - public: - virtual ~VcpController() = default; - - static void Initialize(bluetooth::vcp_controller::VcpControllerCallbacks* callbacks); - static void CleanUp(); - static VcpController* Get(); - static bool IsVcpControllerRunning(); - static int GetDeviceCount(); - - virtual void Connect(const RawAddress& address, bool isDirect) = 0; - virtual void Disconnect(const RawAddress& address) = 0; - virtual void SetAbsVolume(const RawAddress& address, uint8_t volume) = 0; - virtual void Mute(const RawAddress& address) = 0; - virtual void Unmute(const RawAddress& address) = 0; -}; - diff --git a/le_audio/system/bt/bta/include/connected_iso_api.h b/le_audio/system/bt/bta/include/connected_iso_api.h deleted file mode 100644 index 74e16ccfc40748d61965997bc6c2288988f2b813..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/include/connected_iso_api.h +++ /dev/null @@ -1,111 +0,0 @@ -/****************************************************************************** - * - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - - -#pragma once - -#include -#include - -#include "stack/include/bt_types.h" -#include - -namespace bluetooth { -namespace bap { -namespace cis { - -using bluetooth::bap::ucast::CISConfig; -using bluetooth::bap::ucast::CIGConfig; - -constexpr uint8_t DIR_TO_AIR = 0x1 << 0; -constexpr uint8_t DIR_FROM_AIR = 0x1 << 1; - -typedef uint8_t sdu_interval_t[3]; - -enum class CisState { - INVALID = 0, - READY, - DESTROYING, - ESTABLISHING, - ESTABLISHED -}; - -enum class CigState { - INVALID = 0, - IDLE, - CREATING, - CREATED, - REMOVING -}; - -enum IsoHciStatus { - ISO_HCI_SUCCESS = 0, - ISO_HCI_FAILED, - ISO_HCI_IN_PROGRESS -}; - -class CisInterfaceCallbacks { - public: - virtual ~CisInterfaceCallbacks() = default; - - /** Callback for connection state change */ - virtual void OnCigState(uint8_t cig_id, CigState state) = 0; - - virtual void OnCisState(uint8_t cig_id, uint8_t cis_id, - uint8_t direction, CisState state) = 0; -}; - -class CisInterface { - public: - virtual ~CisInterface() = default; - - static void Initialize(CisInterfaceCallbacks* callbacks); - static void CleanUp(); - static CisInterface* Get(); - - virtual CigState GetCigState(const uint8_t &cig_id); - - virtual CisState GetCisState(const uint8_t &cig_id, uint8_t cis_id); - - virtual uint8_t GetCisCount(const uint8_t &cig_id) = 0; - - virtual IsoHciStatus CreateCig(RawAddress client_peer_bda, - bool reconfig, - CIGConfig &cig_config, - std::vector &cis_configs) = 0; - - virtual IsoHciStatus RemoveCig(RawAddress peer_bda, - uint8_t cig_id) = 0; - - virtual IsoHciStatus CreateCis(uint8_t cig_id, std::vector cis_ids, - RawAddress peer_bda) = 0; - - virtual IsoHciStatus DisconnectCis(uint8_t cig_id, uint8_t cis_id, - uint8_t direction) = 0; - - virtual IsoHciStatus SetupDataPath(uint8_t cig_id, uint8_t cis_id, - uint8_t direction, - uint8_t path_id) = 0; - - virtual IsoHciStatus RemoveDataPath(uint8_t cig_id, uint8_t cis_id, - uint8_t direction) = 0; -}; - -} // namespace ucast -} // namespace bap -} // namespace bluetooth diff --git a/le_audio/system/bt/bta/mcp/bta_mcp_main.cc b/le_audio/system/bt/bta/mcp/bta_mcp_main.cc deleted file mode 100644 index a7e1d9487b6dd1f2f257660508f5565124de4db5..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/mcp/bta_mcp_main.cc +++ /dev/null @@ -1,3088 +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. - * - ******************************************************************************/ - - - - -/****************************************************************************** - * - * This file contains the MCP server main functions and state machine. - * - ******************************************************************************/ - -#include "bta_api.h" -#include "bt_target.h" -#include "bta_mcp_api.h" -#include "gatts_ops_queue.h" -#include "device/include/controller.h" -#include "osi/include/properties.h" -#include "bta_sys.h" -#include "btif_util.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -using bluetooth::Uuid; -using bluetooth::bap::GattsOpsQueue; - -class McpServerImpl; -static McpServerImpl *instance; - -//global variables -mcsServerServiceInfo_t mcsServerServiceInfo; -MediaPlayerInfo_t mediaPlayerInfo; - -void HandleMcsEvent(uint32_t event, void* param); - -typedef base::Callback service)> - OnMcpServiceAdded; - -static void OnMcpServiceAddedCb(uint8_t status, int serverIf, - std::vector service); - -/* Media state handlers */ -static bool MediaStateInactiveHandler(uint32_t event, void* param, uint8_t state); -static bool MediaStatePauseHandler(uint32_t event, void* param, uint8_t state); -static bool MediaStatePlayingHandler(uint32_t event, void* param, uint8_t state); -static bool MediaStateSeekingHandler(uint32_t event, void* param, uint8_t state); - -/* Connection state machine handlers */ -static bool DeviceStateConnectionHandler(uint32_t event, void* param, uint8_t state); -static bool DeviceStateDisconnectedHandler(uint32_t event, void* param, uint8_t state); - -Uuid MCS_UUID = Uuid::FromString("1848"); -Uuid GMCS_UUID = Uuid::FromString("1849"); - -Uuid DESCRIPTOR_UUID = Uuid::FromString("2902"); - -Uuid GMCS_MEDIA_STATE_UUID = Uuid::FromString("2BA3"); -Uuid GMCS_MEDIA_CONTROL_POINT_OPCODE_SUPPORTED = Uuid::FromString("2BA5"); -Uuid GMCS_MEDIA_PLAYER_NAME_UUID = Uuid::FromString("2B93"); -Uuid GMCS_MEDIA_CONTROL_POINT = Uuid::FromString("2BA4"); -Uuid GMCS_TRACK_CHANGED = Uuid::FromString("2B96"); -Uuid GMCS_TRACK_TITLE = Uuid::FromString("2B97"); -Uuid GMCS_TRACK_DURATION = Uuid::FromString("2B98"); -Uuid GMCS_TRACK_POSITION = Uuid::FromString("2B99"); -Uuid GMCS_PLAYING_ORDER_SUPPORTED = Uuid::FromString("2BA2"); -Uuid GMCS_PLAYING_ORDER = Uuid::FromString("2BA1"); -Uuid GMCS_CONTENT_CONTROLID = Uuid::FromString("2BBA"); -Uuid GMCS_SEEKING_SPEED_UUID = Uuid::FromString("2B9B"); - - - bool is_pts_running() { - char value[PROPERTY_VALUE_MAX] = {'\0'}; - bool pts_test_enabled = false; - osi_property_get("persist.vendor.service.bt.mcs.pts", value, "false"); - pts_test_enabled = (strcmp(value, "true") == 0); - LOG(INFO) << "pts test enabled " << pts_test_enabled; - return pts_test_enabled; - } - - int playing_order_opcode(int data) { - int event = 0; - if (data & MCP_PLAYING_OREDR_SHUFFLE_REPEAT) { - event = MCP_PLAYING_OREDR_SHUFFLE_REPEAT_REQ; - } else - LOG(INFO) << "opcode not matched or not supported"; - return event; - } - - bool is_opcode_supported(int data) { - LOG(INFO) << __func__ << "data " << data << "media_supported_feature " << mediaPlayerInfo.media_supported_feature; - switch (data) { - case MCP_MEDIA_CONTROL_OPCODE_PLAY: - return (mediaPlayerInfo.media_supported_feature & MCP_MEDIA_CONTROL_SUP_PLAY); - case MCP_MEDIA_CONTROL_OPCODE_PAUSE: - return (mediaPlayerInfo.media_supported_feature & MCP_MEDIA_CONTROL_SUP_PAUSE); - case MCP_MEDIA_CONTROL_OPCODE_FAST_REWIND: - return (mediaPlayerInfo.media_supported_feature & MCP_MEDIA_CONTROL_SUP_FAST_REWIND); - case MCP_MEDIA_CONTROL_OPCODE_FAST_FORWARD: - return (mediaPlayerInfo.media_supported_feature & MCP_MEDIA_CONTROL_SUP_FAST_FORWARD); - case MCP_MEDIA_CONTROL_OPCODE_STOP: - return (mediaPlayerInfo.media_supported_feature & MCP_MEDIA_CONTROL_SUP_STOP); - case MCP_MEDIA_CONTROL_OPCODE_PREV_TRACK: - return (mediaPlayerInfo.media_supported_feature & MCP_MEDIA_CONTROL_SUP_PREVIOUS_TRACK); - case MCP_MEDIA_CONTROL_OPCODE_NEXT_TRACK: - return (mediaPlayerInfo.media_supported_feature & MCP_MEDIA_CONTROL_SUP_NEXT_TRACK); - - // Fallthrough for all unknown key mappings - default: - LOG(INFO) << __func__ << "opcode is not supported"; - return false; - } - } - -const char* get_mcp_event_name(uint32_t event) { - switch (event) { - CASE_RETURN_STR(MCP_INIT_EVENT) - CASE_RETURN_STR(MCP_CLEANUP_EVENT) - CASE_RETURN_STR(MCP_MEDIA_STATE_UPDATE) - CASE_RETURN_STR(MCP_MEDIA_PLAYER_NAME_UPDATE) - CASE_RETURN_STR(MCP_MEDIA_SUPPORTED_OPCODE_UPDATE) - CASE_RETURN_STR(MCP_MEDIA_CONTROL_POINT_UPDATE) - CASE_RETURN_STR(MCP_PLAYING_ORDER_SUPPORTED_UPDATE) - CASE_RETURN_STR(MCP_PLAYING_ORDER_UPDATE) - CASE_RETURN_STR(MCP_TRACK_CHANGED_UPDATE) - CASE_RETURN_STR(MCP_TRACK_POSITION_UPDATE) - CASE_RETURN_STR(MCP_TRACK_DURATION_UPDATE) - CASE_RETURN_STR(MCP_TRACK_TITLE_UPDATE) - CASE_RETURN_STR(MCP_CCID_UPDATE) - CASE_RETURN_STR(MCP_ACTIVE_DEVICE_UPDATE) - CASE_RETURN_STR(MCP_ACTIVE_PROFILE) - - //local event to handle in mcp state machine, - CASE_RETURN_STR(MCP_PLAYING_ORDER_SUPPORTED_READ) - CASE_RETURN_STR(MCP_PLAYING_ORDER_READ) - CASE_RETURN_STR(MCP_MEDIA_STATE_READ) - CASE_RETURN_STR(MCP_MEDIA_CONTROL_POINT_OPCODE_SUPPORTED_READ) - CASE_RETURN_STR(MCP_MEDIA_PLAYER_NAME_READ) - CASE_RETURN_STR(MCP_TRACK_TITLE_READ) - CASE_RETURN_STR(MCP_TRACK_POSITION_READ) - CASE_RETURN_STR(MCP_TRACK_DURATION_READ) - CASE_RETURN_STR(MCP_CCID_READ) - CASE_RETURN_STR(MCP_SEEKING_SPEED_READ) - CASE_RETURN_STR(MCP_MEDIA_STATE_READ_DESCRIPTOR) - CASE_RETURN_STR(MCP_MEDIA_CONTROL_POINT_READ_DESCRIPTOR) - CASE_RETURN_STR(MCP_MEDIA_CONTROL_POINT_OPCODE_SUPPORTED_DESCRIPTOR_READ) - CASE_RETURN_STR(MCP_MEDIA_PLAYER_NAME_DESCRIPTOR_READ) - CASE_RETURN_STR(MCP_TRACK_CHANGED_DESCRIPTOR_READ) - CASE_RETURN_STR(MCP_TRACK_TITLE_DESCRIPTOR_READ) - CASE_RETURN_STR(MCP_TRACK_POSITION_DESCRIPTOR_READ) - CASE_RETURN_STR(MCP_TRACK_DURATION_DESCRIPTOR_READ) - CASE_RETURN_STR(MCP_PLAYING_ORDER_DESCRIPTOR_READ) - CASE_RETURN_STR(MCP_MEDIA_STATE_DESCRIPTOR_WRITE) - CASE_RETURN_STR(MCP_MEDIA_PLAYER_NAME_DESCRIPTOR_WRITE) - CASE_RETURN_STR(MCP_MEDIA_CONTROL_POINT_DESCRIPTOR_WRITE) - CASE_RETURN_STR(MCP_MEDIA_CONTROL_POINT_SUPPORTED_DESCRIPTOR_WRITE) - CASE_RETURN_STR(MCP_TRACK_CHANGED_DESCRIPTOR_WRITE) - CASE_RETURN_STR(MCP_TRACK_TITLE_DESCRIPTOR_WRITE) - CASE_RETURN_STR(MCP_TRACK_POSITION_DESCRIPTOR_WRITE) - CASE_RETURN_STR(MCP_TRACK_DURATION_DESCRIPTOR_WRITE) - CASE_RETURN_STR(MCP_PLAYING_ORDER_DESCRIPTOR_WRITE) - CASE_RETURN_STR(MCP_MEDIA_CONTROL_POINT_WRITE) - CASE_RETURN_STR(MCP_PLAYING_ORDER_WRITE) - CASE_RETURN_STR(MCP_TRACK_POSITION_WRITE) - - CASE_RETURN_STR(MCP_NOTIFY_ALL) - CASE_RETURN_STR(MCP_WRITE_RSP) - CASE_RETURN_STR(MCP_READ_RSP) - CASE_RETURN_STR(MCP_DESCRIPTOR_WRITE_RSP) - CASE_RETURN_STR(MCP_DESCRIPTOR_READ_RSP) - CASE_RETURN_STR(MCP_CONNECTION) - CASE_RETURN_STR(MCP_DISCONNECTION) - CASE_RETURN_STR(MCP_CONNECTION_UPDATE) - CASE_RETURN_STR(MCP_CONGESTION_UPDATE) - CASE_RETURN_STR(MCP_PHY_UPDATE) - CASE_RETURN_STR(MCP_MTU_UPDATE) - CASE_RETURN_STR(MCP_SET_ACTIVE_DEVICE) - CASE_RETURN_STR(MCP_CONNECTION_CLOSE_EVENT) - CASE_RETURN_STR(MCP_BOND_STATE_CHANGE_EVENT) - //media write op code event - CASE_RETURN_STR(MCP_MEDIA_CONTROL_PLAY_READ_REQ) - CASE_RETURN_STR(MCP_MEDIA_CONTROL_PAUSE_REQ) - CASE_RETURN_STR(MCP_MEDIA_CONTROL_FAST_FORWARD_REQ) - CASE_RETURN_STR(MCP_MEDIA_CONTROL_FAST_REWIND_REQ) - CASE_RETURN_STR(MCP_MEDIA_CONTROL_MOVE_RELATIVE_REQ) - CASE_RETURN_STR(MCP_MEDIA_CONTROL_STOP_REQ) - CASE_RETURN_STR(MCP_MEDIA_CONTROL_NEXT_TRACK_REQ) - CASE_RETURN_STR(MCP_MEDIA_CONTROL_PREVIOUS_TRACK_REQ) - CASE_RETURN_STR(MCP_PLAYING_OREDR_SHUFFLE_REPEAT_REQ) - default: - return "Unknown Event"; - } -} - -const char* get_mcp_media_state_name(uint8_t media_state) { - switch (media_state) { - CASE_RETURN_STR(MCP_STATE_INACTIVE) - CASE_RETURN_STR(MCP_STATE_PLAYING) - CASE_RETURN_STR(MCP_STATE_PAUSE) - CASE_RETURN_STR(MCP_STATE_SEEKING) - default: - return "Unknown Media State"; - } -} - -class RemoteDevices { - private: - ActiveDevice activeDevice; - //int max_connection; - public: - bool Add(RemoteDevice device) { - if (devices.size() == MAX_MCP_CONNECTION) { - return false; - } - if (FindByAddress(device.peer_bda) != nullptr) return false; - device.DeviceStateHandlerPointer[MCP_DISCONNECTED] = DeviceStateDisconnectedHandler; - device.DeviceStateHandlerPointer[MCP_CONNECTED] = DeviceStateConnectionHandler; - devices.push_back(device); - return true; - } - - void Remove(RawAddress& address) { - for (auto it = devices.begin(); it != devices.end();) { - if (it->peer_bda != address) { - ++it; - continue; - } - - it = devices.erase(it); - return; - } - } - - RemoteDevice* FindByAddress(const RawAddress& address) { - auto iter = std::find_if(devices.begin(), devices.end(), - [&address](const RemoteDevice& device) { - return device.peer_bda == address; - }); - - return (iter == devices.end()) ? nullptr : &(*iter); - } - - RemoteDevice* FindByConnId(uint16_t conn_id) { - auto iter = std::find_if(devices.begin(), devices.end(), - [&conn_id](const RemoteDevice& device) { - return device.conn_id == conn_id; - }); - - return (iter == devices.end()) ? nullptr : &(*iter); - } - - size_t size() { return (devices.size()); } - - std::vector GetRemoteDevices() { - return devices; - } - std::vector FindNotifyDevices(uint16_t handle) { - std::vector notify_devices; - for (size_t it = 0; it != devices.size(); it++){ - if(mcsServerServiceInfo.media_state_handle == handle && - devices[it].media_state_notify) { - notify_devices.push_back(devices[it]); - } else if(mcsServerServiceInfo.media_player_name_handle == handle && - devices[it].media_player_name_notify) { - notify_devices.push_back(devices[it]); - } else if (mcsServerServiceInfo.media_control_point_opcode_supported_handle == handle && - devices[it].media_control_point_opcode_supported_notify) { - notify_devices.push_back(devices[it]); - } else if(mcsServerServiceInfo.media_control_point_handle == handle && - devices[it].media_control_point_notify) { - notify_devices.push_back(devices[it]); - } else if(mcsServerServiceInfo.track_changed_handle == handle && - devices[it].track_changed_notify) { - notify_devices.push_back(devices[it]); - } else if(mcsServerServiceInfo.track_title_handle == handle && - devices[it].track_title_notify) { - notify_devices.push_back(devices[it]); - } else if(mcsServerServiceInfo.track_duration_handle == handle && - devices[it].track_duration_notify) { - notify_devices.push_back(devices[it]); - } else if(mcsServerServiceInfo.track_position_handle == handle && - devices[it].track_position_notify) { - notify_devices.push_back(devices[it]); - } else if(mcsServerServiceInfo.playing_order_handle == handle && - devices[it].playing_order_notify) { - notify_devices.push_back(devices[it]); - } - } - return notify_devices; - } - void AddSetActiveDevice(tMCP_SET_ACTIVE_DEVICE *device) { - if (device->set_id == activeDevice.set_id) { - activeDevice.address.push_back(device->address); - } else { - activeDevice.address.clear(); - activeDevice.set_id = device->set_id; - activeDevice.address.push_back(device->address); - } - } - - bool FindActiveDevice(RemoteDevice *remoteDevice) { - bool flag = false; - for (auto& it : activeDevice.address) { - if(remoteDevice->peer_bda == it) { - flag = true; - break; - } - } - return flag; - } - - std::vector devices; -}; - - -class McpServerImpl : public McpServer { - bluetooth::mcp_server::McpServerCallbacks* callbacks; - Uuid app_uuid; - - public: - RemoteDevices remoteDevices; - virtual ~McpServerImpl() = default; - - - McpServerImpl(bluetooth::mcp_server::McpServerCallbacks* callback, Uuid uuid) - :callbacks(callback), - app_uuid(uuid){ - LOG(INFO) << "McpServerImpl gatts app register"; - HandleMcsEvent(MCP_INIT_EVENT, &app_uuid); - - } - - void SetActiveDevice(const RawAddress& address, int setId, int profile) { - LOG(INFO) << __func__ ; - tMCP_SET_ACTIVE_DEVICE SetActiveDeviceOp; - SetActiveDeviceOp.set_id = setId; - SetActiveDeviceOp.address = address; - SetActiveDeviceOp.profile = profile; - HandleMcsEvent(MCP_ACTIVE_DEVICE_UPDATE, &SetActiveDeviceOp); - } - - void MediaState(uint8_t state) { - LOG(INFO) << __func__ << " state: " << unsigned(state); - tMCP_MEDIA_STATE MediaStateOp; - MediaStateOp.state = state; - HandleMcsEvent(MCP_MEDIA_STATE_UPDATE, &MediaStateOp); - } - - void MediaPlayerName(uint8_t* player_name) { - LOG(INFO) << __func__; - tMCP_MEDIA_PLAYER_NAME MediaPlayerNameOp; - MediaPlayerNameOp.name = player_name; - MediaPlayerNameOp.len = strlen((char *)player_name); - if(MediaPlayerNameOp.len != 0) - HandleMcsEvent(MCP_MEDIA_PLAYER_NAME_UPDATE, &MediaPlayerNameOp); - } - - void MediaControlPointOpcodeSupported(uint32_t feature) { - LOG(INFO) << __func__; - tMCP_MEDIA_OPCODE_SUPPORT MediaControlPointOpcodeSupportedOp; - MediaControlPointOpcodeSupportedOp.supported = feature; - HandleMcsEvent(MCP_MEDIA_SUPPORTED_OPCODE_UPDATE, &MediaControlPointOpcodeSupportedOp); - } - - void MediaControlPoint(uint8_t value) { - LOG(INFO) << __func__; - tMCP_MEDIA_CONTROL_POINT MediaControlPoint; - MediaControlPoint.req_opcode = value; - MediaControlPoint.result = MCP_STATUS_SUCCESS; // success - HandleMcsEvent(MCP_MEDIA_CONTROL_POINT_UPDATE, &MediaControlPoint); - } - - void TrackChanged(bool status) { - LOG(INFO) << __func__; - tMCP_TRACK_CHANGED TrackChangedOp; - TrackChangedOp.status = status; - HandleMcsEvent(MCP_TRACK_CHANGED_UPDATE, &TrackChangedOp); - } - - void TrackTitle(uint8_t* track_name) { - LOG(INFO) << __func__; - tMCP_TRACK_TITLE TrackTitleOp; - TrackTitleOp.title = track_name; - TrackTitleOp.len = strlen((char *)track_name); - if (TrackTitleOp.len != 0) - HandleMcsEvent(MCP_TRACK_TITLE_UPDATE, &TrackTitleOp); - } - - void TrackDuration(int32_t duration) { - LOG(INFO) << __func__; - tMCP_TRACK_DURATION TrackDurationOp; - TrackDurationOp.duration = duration; - HandleMcsEvent(MCP_TRACK_DURATION_UPDATE, &TrackDurationOp); - } - - void TrackPosition(int32_t position) { - LOG(INFO) << __func__; - tMCP_TRACK_POSTION TrackPositionOp; - TrackPositionOp.position = position; - HandleMcsEvent(MCP_TRACK_POSITION_UPDATE, &TrackPositionOp); - } - - void PlayingOrderSupported(uint16_t order) { - LOG(INFO) << __func__; - tMCP_PLAYING_ORDER_SUPPORT PlayingOrderSupportedOp; - PlayingOrderSupportedOp.order_supported = order; - HandleMcsEvent(MCP_PLAYING_ORDER_SUPPORTED_UPDATE, &PlayingOrderSupportedOp); - } - - void PlayingOrder(uint8_t value) { - LOG(INFO) << __func__; - tMCP_PLAYING_ORDER PlayingOrderOp; - PlayingOrderOp.order = value; - HandleMcsEvent(MCP_PLAYING_ORDER_UPDATE, &PlayingOrderOp); - } - - void ContentControlId(uint8_t ccid) { - LOG(INFO) << __func__; - tMCP_CONTENT_CONTROL_ID ContentControlIdOp; - ContentControlIdOp.ccid = ccid; - HandleMcsEvent(MCP_CCID_UPDATE, &ContentControlIdOp); - } - - void DisconnectMcp(const RawAddress& bd_addr) { - LOG(INFO) << __func__; - tMCP_CONNECTION_CLOSE ConnectClosingOp; - ConnectClosingOp.addr = bd_addr; - HandleMcsEvent(MCP_CONNECTION_CLOSE_EVENT, &ConnectClosingOp); - } - - void BondStateChange(const RawAddress& bd_addr, int state) { - LOG(INFO) << __func__; - tMCP_BOND_STATE_CHANGE BondStateChangeOP; - BondStateChangeOP.addr = bd_addr; - BondStateChangeOP.state = state; - HandleMcsEvent(MCP_BOND_STATE_CHANGE_EVENT, &BondStateChangeOP); - } - - void OnConnectionStateChange(uint8_t state, const RawAddress& address) { - LOG(INFO) << __func__ << " bta"; - callbacks->OnConnectionStateChange(state, address); - } - - void MediaControlPointChangeReq(uint8_t state, const RawAddress& address) { - callbacks->MediaControlPointChangeReq(state, address); - LOG(INFO) << __func__; - } - - void TrackPositionChangeReq(int32_t position) { - callbacks->TrackPositionChangeReq(position); - LOG(INFO) << __func__; - } - - void PlayingOrderChangeReq(uint16_t playingOrder) { - callbacks->PlayingOrderChangeReq(playingOrder); - LOG(INFO) << __func__; - } - -}; - - -void McpServer::CleanUp() { - HandleMcsEvent(MCP_CLEANUP_EVENT, NULL); - delete instance; - instance = nullptr; -} - -McpServer* McpServer::Get() { - CHECK(instance); - return instance; -} - -void McpServer::Initialize(bluetooth::mcp_server::McpServerCallbacks* callbacks, Uuid uuid) { - if (instance) { - LOG(ERROR) << "Already initialized!"; - } else { - instance = new McpServerImpl(callbacks, uuid); - } -} - -bool McpServer::isMcpServiceRunnig() { return instance; } - -static std::vector McpAddService(int server_if) { - - std::vector mcs_services; - mcs_services.clear(); - //service - btgatt_db_element_t service = {.uuid = GMCS_UUID, .type = BTGATT_DB_PRIMARY_SERVICE, 0}; - mcs_services.push_back(service); - mcsServerServiceInfo.mcs_service_uuid = service.uuid; - - //media state service - btgatt_db_element_t mcs_media_state_char = {.uuid = GMCS_MEDIA_STATE_UUID, - .type = BTGATT_DB_CHARACTERISTIC, - .properties = GATT_CHAR_PROP_BIT_READ| - GATT_CHAR_PROP_BIT_NOTIFY, - .permissions = GATT_PERM_READ}; - mcs_services.push_back(mcs_media_state_char); - mcsServerServiceInfo.media_state_uuid = mcs_media_state_char.uuid; - - //1st desc - btgatt_db_element_t desc1 = {.uuid = DESCRIPTOR_UUID, - .type = BTGATT_DB_DESCRIPTOR, - .permissions = GATT_PERM_READ|GATT_PERM_WRITE}; - mcs_services.push_back(desc1); - - //media supported feature - btgatt_db_element_t mcs_media_opcode_supported_char = {.uuid = GMCS_MEDIA_CONTROL_POINT_OPCODE_SUPPORTED, - .type = BTGATT_DB_CHARACTERISTIC, - .properties = GATT_CHAR_PROP_BIT_READ| - GATT_CHAR_PROP_BIT_NOTIFY, - .permissions = GATT_PERM_READ}; - - mcs_services.push_back(mcs_media_opcode_supported_char); - mcsServerServiceInfo.media_control_point_opcode_supported_uuid = - mcs_media_opcode_supported_char.uuid; - - //2nd desc - btgatt_db_element_t desc2 = {.uuid = DESCRIPTOR_UUID, - .type = BTGATT_DB_DESCRIPTOR, - .permissions = GATT_PERM_READ|GATT_PERM_WRITE}; - mcs_services.push_back(desc2); - - ////media player name - btgatt_db_element_t mcs_media_player_name_char = {.uuid = GMCS_MEDIA_PLAYER_NAME_UUID, - .type = BTGATT_DB_CHARACTERISTIC, - .properties = GATT_CHAR_PROP_BIT_READ| - GATT_CHAR_PROP_BIT_NOTIFY, - .permissions = GATT_PERM_READ}; - mcs_services.push_back(mcs_media_player_name_char); - mcsServerServiceInfo.media_player_name_uuid = mcs_media_player_name_char.uuid; - - //3rd desc - btgatt_db_element_t desc3 = {.uuid = DESCRIPTOR_UUID, - .type = BTGATT_DB_DESCRIPTOR, - .permissions = GATT_PERM_READ|GATT_PERM_WRITE}; - mcs_services.push_back(desc3); - - //media control point - btgatt_db_element_t mcs_media_control_point_char = {.uuid = GMCS_MEDIA_CONTROL_POINT, - .type = BTGATT_DB_CHARACTERISTIC, - .properties = GATT_CHAR_PROP_BIT_WRITE_NR| - GATT_CHAR_PROP_BIT_WRITE| - GATT_CHAR_PROP_BIT_NOTIFY, - .permissions = GATT_PERM_WRITE}; - - mcs_services.push_back(mcs_media_control_point_char); - - mcsServerServiceInfo.media_player_name_uuid = mcs_media_control_point_char.uuid; - - //4th desc - btgatt_db_element_t desc4 = {.uuid = DESCRIPTOR_UUID, - .type = BTGATT_DB_DESCRIPTOR, - .permissions = GATT_PERM_READ|GATT_PERM_WRITE}; - mcs_services.push_back(desc4); - - btgatt_db_element_t track_changed_char = {.uuid = GMCS_TRACK_CHANGED, - .type = BTGATT_DB_CHARACTERISTIC, - .properties = GATT_CHAR_PROP_BIT_NOTIFY, - .permissions = GATT_PERM_READ}; - - mcs_services.push_back(track_changed_char); - mcsServerServiceInfo.track_changed_uuid = track_changed_char.uuid; - - //5th desc - btgatt_db_element_t desc5 = {.uuid = DESCRIPTOR_UUID, - .type = BTGATT_DB_DESCRIPTOR, - .permissions = GATT_PERM_READ|GATT_PERM_WRITE}; - mcs_services.push_back(desc5); - - btgatt_db_element_t track_title_char = {.uuid = GMCS_TRACK_TITLE, - .type = BTGATT_DB_CHARACTERISTIC, - .properties = GATT_CHAR_PROP_BIT_NOTIFY| - GATT_CHAR_PROP_BIT_READ, - .permissions = GATT_PERM_READ}; - - mcs_services.push_back(track_title_char); - mcsServerServiceInfo.track_title_uuid = track_title_char.uuid; - - //6th desc - btgatt_db_element_t desc6 = {.uuid = DESCRIPTOR_UUID, - .type = BTGATT_DB_DESCRIPTOR, - .permissions = GATT_PERM_READ|GATT_PERM_WRITE}; - mcs_services.push_back(desc6); - - - btgatt_db_element_t track_duration_char = {.uuid = GMCS_TRACK_DURATION, - .type = BTGATT_DB_CHARACTERISTIC, - .properties = GATT_CHAR_PROP_BIT_NOTIFY| - GATT_CHAR_PROP_BIT_READ, - .permissions = GATT_PERM_READ}; - - mcs_services.push_back(track_duration_char); - mcsServerServiceInfo.track_duration_uuid = track_duration_char.uuid; - - //7th desc - btgatt_db_element_t desc7 = {.uuid = DESCRIPTOR_UUID, - .type = BTGATT_DB_DESCRIPTOR, - .permissions = GATT_PERM_READ|GATT_PERM_WRITE}; - mcs_services.push_back(desc7); - - btgatt_db_element_t track_position_char = {.uuid = GMCS_TRACK_POSITION, - .type = BTGATT_DB_CHARACTERISTIC, - .properties = GATT_CHAR_PROP_BIT_READ| - GATT_CHAR_PROP_BIT_WRITE_NR| - GATT_CHAR_PROP_BIT_WRITE| - GATT_CHAR_PROP_BIT_NOTIFY, - .permissions = GATT_PERM_READ|GATT_PERM_WRITE}; - - mcs_services.push_back(track_position_char); - mcsServerServiceInfo.track_position_uuid = track_position_char.uuid; - - //8th desc - btgatt_db_element_t desc8 = {.uuid = DESCRIPTOR_UUID, - .type = BTGATT_DB_DESCRIPTOR, - .permissions = GATT_PERM_READ|GATT_PERM_WRITE}; - mcs_services.push_back(desc8); - - btgatt_db_element_t playing_order_supported_char = {.uuid = GMCS_PLAYING_ORDER_SUPPORTED, - .type = BTGATT_DB_CHARACTERISTIC, - .properties = GATT_CHAR_PROP_BIT_READ, - .permissions = GATT_PERM_READ}; - - mcs_services.push_back(playing_order_supported_char); - mcsServerServiceInfo.playing_order_supported_uuid = playing_order_supported_char.uuid; - - btgatt_db_element_t playing_order_char = {.uuid = GMCS_PLAYING_ORDER, - .type = BTGATT_DB_CHARACTERISTIC, - .properties = GATT_CHAR_PROP_BIT_READ| - GATT_CHAR_PROP_BIT_WRITE_NR| - GATT_CHAR_PROP_BIT_WRITE| - GATT_CHAR_PROP_BIT_NOTIFY, - .permissions = GATT_PERM_READ|GATT_PERM_WRITE}; - - mcs_services.push_back(playing_order_char); - mcsServerServiceInfo.playing_order_uuid = playing_order_char.uuid; - - //10th desc - btgatt_db_element_t desc10 = {.uuid = DESCRIPTOR_UUID, - .type = BTGATT_DB_DESCRIPTOR, - .permissions = GATT_PERM_READ|GATT_PERM_WRITE}; - mcs_services.push_back(desc10); - - btgatt_db_element_t ccid_char = {.uuid = GMCS_CONTENT_CONTROLID, - .type = BTGATT_DB_CHARACTERISTIC, - .properties = GATT_CHAR_PROP_BIT_READ, - .permissions = GATT_PERM_READ}; - - mcs_services.push_back(ccid_char); - mcsServerServiceInfo.ccid_uuid = ccid_char.uuid; - - btgatt_db_element_t seek_speed_char = {.uuid = GMCS_SEEKING_SPEED_UUID, - .type = BTGATT_DB_CHARACTERISTIC, - .properties = GATT_CHAR_PROP_BIT_READ, - .permissions = GATT_PERM_READ}; - mcs_services.push_back(seek_speed_char); - mcsServerServiceInfo.seeking_speed_uuid = seek_speed_char.uuid; - - return mcs_services; -} - - -static void OnMcpServiceAddedCb(uint8_t status, int serverIf, - std::vector service) { - - if (service[0].uuid == Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER) || - service[0].uuid == Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER)) { - LOG(INFO) << "%s: Attempt to register restricted service"<< __func__; - return; - } - for(int i = 0; i < (int)service.size(); i++) { - - if (service[i].uuid == GMCS_UUID) { - LOG(INFO) << __func__ << " mcs service added attr handle " << service[i].attribute_handle; - } else if (service[i].uuid == GMCS_MEDIA_STATE_UUID) { - mcsServerServiceInfo.media_state_handle = service[i++].attribute_handle; - mcsServerServiceInfo.media_state_desc = service[i].attribute_handle; - LOG(INFO) << __func__ << " media_state_handle" << - mcsServerServiceInfo.media_state_handle; - LOG(INFO) << __func__ << " media_state_handle desc" << - mcsServerServiceInfo.media_state_desc; - } else if(service[i].uuid == GMCS_MEDIA_CONTROL_POINT_OPCODE_SUPPORTED) { - mcsServerServiceInfo.media_control_point_opcode_supported_handle = - service[i++].attribute_handle; - LOG(INFO) << __func__ << " media_control_point_opcode_supported_handle register" << - mcsServerServiceInfo.media_control_point_opcode_supported_handle; - mcsServerServiceInfo.media_control_point_opcode_supported_desc = - service[i].attribute_handle; - LOG(INFO) << __func__ << " media_control_point_opcode_supported_handle desc register" << - mcsServerServiceInfo.media_control_point_opcode_supported_desc; - } else if(service[i].uuid == GMCS_MEDIA_PLAYER_NAME_UUID) { - mcsServerServiceInfo.media_player_name_handle = - service[i++].attribute_handle; - LOG(INFO) << __func__ << " media_player_name_handle GMCS_MEDIA_PLAYER_NAME_UUID register" - << mcsServerServiceInfo.media_player_name_handle; - mcsServerServiceInfo.media_player_name_desc = - service[i].attribute_handle; - LOG(INFO) << __func__ << " media_player_name_handle GMCS_MEDIA_PLAYER_NAME_UUID desc" - << mcsServerServiceInfo.media_player_name_desc; - } else if(service[i].uuid == GMCS_MEDIA_CONTROL_POINT) { - mcsServerServiceInfo.media_control_point_handle = - service[i++].attribute_handle; - LOG(INFO) << __func__ << " media_control_point_handle GMCS_MEDIA_CONTROL_POINT register" - << mcsServerServiceInfo.media_control_point_handle; - mcsServerServiceInfo.media_control_point_desc = - service[i].attribute_handle; - LOG(INFO) << __func__ << " media_control_point_handle GMCS_MEDIA_CONTROL_POINT desc" - << mcsServerServiceInfo.media_control_point_desc; - } else if(service[i].uuid == GMCS_TRACK_CHANGED) { - mcsServerServiceInfo.track_changed_handle = - service[i++].attribute_handle; - LOG(INFO) << __func__ << "track_changed_handle GMCS_TRACK_CHANGED register" - << mcsServerServiceInfo.track_changed_handle; - mcsServerServiceInfo.track_changed_desc = - service[i].attribute_handle; - LOG(INFO) << __func__ << "track_changed_handle GMCS_TRACK_CHANGED desc" - << mcsServerServiceInfo.track_changed_desc; - } else if(service[i].uuid == GMCS_TRACK_TITLE) { - mcsServerServiceInfo.track_title_handle = - service[i++].attribute_handle; - LOG(INFO) << __func__ << "track_title_handle GMCS_TRACK_TITLE register" - << mcsServerServiceInfo.track_title_handle; - mcsServerServiceInfo.track_title_desc = - service[i].attribute_handle; - LOG(INFO) << __func__ << "track_title_handle GMCS_TRACK_TITLE desc" - << mcsServerServiceInfo.track_title_desc; - } else if(service[i].uuid == GMCS_TRACK_DURATION) { - mcsServerServiceInfo.track_duration_handle = - service[i++].attribute_handle; - - LOG(INFO) << __func__ << "track_duration_handle GMCS_TRACK_DURATION register" - << mcsServerServiceInfo.track_duration_handle; - mcsServerServiceInfo.track_duration_desc = - service[i].attribute_handle; - - LOG(INFO) << __func__ << "track_duration_handle GMCS_TRACK_DURATION desc" - << mcsServerServiceInfo.track_duration_desc; - - } else if(service[i].uuid == GMCS_TRACK_POSITION) { - mcsServerServiceInfo.track_position_handle = - service[i++].attribute_handle; - LOG(INFO) << __func__ << "track_position_handle GMCS_TRACK_POSITION register" - << mcsServerServiceInfo.track_position_handle; - mcsServerServiceInfo.track_position_desc = - service[i].attribute_handle; - LOG(INFO) << __func__ << "track_position_handle GMCS_TRACK_POSITION desc" - << mcsServerServiceInfo.track_position_handle; - - } else if(service[i].uuid == GMCS_PLAYING_ORDER_SUPPORTED) { - mcsServerServiceInfo.playing_order_supported_handle = - service[i].attribute_handle; - LOG(INFO) << __func__ << "playing_order_supported_handle GMCS_PLAYING_ORDER_SUPPORTED register" - << mcsServerServiceInfo.playing_order_supported_handle; - } else if(service[i].uuid == GMCS_PLAYING_ORDER) { - mcsServerServiceInfo.playing_order_handle = - service[i++].attribute_handle; - LOG(INFO) << __func__ << "playing_order_handle GMCS_PLAYING_ORDER register" - << mcsServerServiceInfo.playing_order_handle; - mcsServerServiceInfo.playing_order_desc = - service[i].attribute_handle; - LOG(INFO) << __func__ << "playing_order_handle GMCS_PLAYING_ORDER desc" - << mcsServerServiceInfo.playing_order_desc; - } else if(service[i].uuid == GMCS_CONTENT_CONTROLID) { - mcsServerServiceInfo.ccid_handle = - service[i].attribute_handle; - LOG(INFO) << __func__ << "ccid_handle GMCS_CONTENT_CONTROLID register" << - mcsServerServiceInfo.ccid_handle; - } else if(service[i].uuid == GMCS_SEEKING_SPEED_UUID) { - mcsServerServiceInfo.seeking_speed_handle = - service[i].attribute_handle; - LOG(INFO) << __func__ << "ccid_handle GMCS_SEEKING_SPEED_ID register" << - mcsServerServiceInfo.seeking_speed_handle; - } - } //for -} - - -void BTMcpCback(tBTA_GATTS_EVT event, tBTA_GATTS* param) { - HandleMcsEvent((uint32_t)event, param); -} - -//mcs handle event -void HandleMcsEvent(uint32_t event, void* param) { - LOG(INFO) << __func__ << " mcs handle event " << get_mcp_event_name(event); - tBTA_GATTS* p_data = NULL; - uint32_t proc_event; - mcp_resp_t *rsp = (mcp_resp_t *)osi_malloc(sizeof(mcp_resp_t)); - if (rsp == NULL) { - LOG(INFO) << __func__ << " mcs handle return rsp not allocated "; - return; - } - uint8_t status = BT_STATUS_SUCCESS; - proc_event = MCP_NONE_EVENT; - rsp->event = MCP_NONE_EVENT; - switch (event) { - - case MCP_INIT_EVENT: - { - // Uuid app_uuid = (Uuid)*param; - Uuid aap_uuid = Uuid::FromString("1849"); - mediaPlayerInfo.media_state = MCP_STATE_INACTIVE; - mediaPlayerInfo.MediaStateHandlerPointer[MCP_STATE_INACTIVE] = - MediaStateInactiveHandler; - mediaPlayerInfo.MediaStateHandlerPointer[MCP_STATE_PAUSE] = - MediaStatePauseHandler; - mediaPlayerInfo.MediaStateHandlerPointer[MCP_STATE_PLAYING] = - MediaStatePlayingHandler; - mediaPlayerInfo.MediaStateHandlerPointer[MCP_STATE_SEEKING] = - MediaStateSeekingHandler; - - mediaPlayerInfo.media_supported_feature = MCP_DEFAULT_MEDIA_CTRL_SUPP_FEAT; - mediaPlayerInfo.ccid = 0; - mediaPlayerInfo.seeking_speed = 0; - mediaPlayerInfo.duration = TRACK_POSITION_UNAVAILABLE; - mediaPlayerInfo.position = TRACK_DURATION_UNAVAILABLE; - mediaPlayerInfo.track_changed = false; - mediaPlayerInfo.playing_order_value = 1; - mediaPlayerInfo.playing_order_supported = 1; - mediaPlayerInfo.player_name_len = 0; - mediaPlayerInfo.track_title_len = 0; - mediaPlayerInfo.media_ctrl_point = 0; - //adding app with random uuid - BTA_GATTS_AppRegister(aap_uuid, BTMcpCback, true); - break; - } - - case MCP_CLEANUP_EVENT: - { - //initiate disconnection to all connected device - //unregister APP - BTA_GATTS_AppDeregister(mcsServerServiceInfo.server_if); - break; - } - case BTA_GATTS_REG_EVT: - { - p_data = (tBTA_GATTS*)param; - if (p_data->reg_oper.status == BT_STATUS_SUCCESS) { - mcsServerServiceInfo.server_if = p_data->reg_oper.server_if; - std::vector service; - service = McpAddService(mcsServerServiceInfo.server_if); - if (service[0].uuid == Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER) || - service[0].uuid == Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER)) { - LOG(INFO) << __func__ << " service app register uuid is not valid"; - break; - } - LOG(INFO) << __func__ << " service app register"; - BTA_GATTS_AddService(mcsServerServiceInfo.server_if, service, base::Bind(&OnMcpServiceAddedCb)); - } - break; - } - - case BTA_GATTS_DEREG_EVT: - { - break; - } - - case BTA_GATTS_CONF_EVT: { - p_data = (tBTA_GATTS*)param; - uint16_t conn_id = p_data->req_data.conn_id; - uint8_t status = p_data->req_data.status; - LOG(INFO) << __func__ << "conn_id :" << conn_id << "status:" << status; - if (status == BT_STATUS_SUCCESS) { - LOG(INFO) << __func__ << "Notification callback for conn_id :" << conn_id; - GattsOpsQueue::NotificationCallback(conn_id); - } - break; - } - - case BTA_GATTS_CONGEST_EVT: - { - p_data = (tBTA_GATTS*)param; - RemoteDevice *remoteDevice; - remoteDevice = instance->remoteDevices.FindByConnId(p_data->congest.conn_id); - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " connection entry not found conn_id :" - << p_data->congest.conn_id; - break; - } - // rsp->ConngestionOp.status = p_data->req_data.status; - rsp->remoteDevice = remoteDevice; - rsp->oper.CongestionOp.congested = p_data->congest.congested; - proc_event = MCP_CONGESTION_UPDATE; - rsp->event = MCP_CONGESTION_UPDATE; - break; - } - case BTA_GATTS_MTU_EVT: { - p_data = (tBTA_GATTS*)param; - RemoteDevice *remoteDevice; - remoteDevice = instance->remoteDevices.FindByConnId(p_data->req_data.p_data->mtu); - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " connection entry not found conn_id :" - << p_data->congest.conn_id; - break; - } - LOG(INFO) << __func__ << " conn_id :"<< p_data->req_data.p_data->mtu; - LOG(INFO) <<"mtu " <req_data.p_data->mtu; - proc_event = MCP_MTU_UPDATE; - rsp->event = MCP_MTU_UPDATE; - rsp->remoteDevice = remoteDevice; - rsp->oper.MtuOp.mtu = p_data->req_data.p_data->mtu; - break; - } - case BTA_GATTS_CONNECT_EVT: { - p_data = (tBTA_GATTS*)param; - LOG(INFO) << __func__ << " remote devices connected"; - // need to discuss how to get encryption support - /* - #if (!defined(BTA_SKIP_BLE_START_ENCRYPTION) || BTA_SKIP_BLE_START_ENCRYPTION == FALSE) - btif_gatt_check_encrypted_link(p_data->conn.remote_bda, - p_data->conn.transport); - #endif*/ - RemoteDevice remoteDevice; - memset(&remoteDevice, 0, sizeof(remoteDevice)); - if(instance->remoteDevices.FindByAddress(p_data->conn.remote_bda)) { - LOG(INFO) << __func__ << " remote devices already there is connected list"; - status = BT_STATUS_FAIL; - return; - } - remoteDevice.peer_bda = p_data->conn.remote_bda; - remoteDevice.conn_id = p_data->conn.conn_id; - if(instance->remoteDevices.Add(remoteDevice) == false) { - LOG(INFO) << __func__ << " remote device is not added : max connection reached"; - // need to check disconnection required - break; - } - remoteDevice.state = MCP_DISCONNECTED; - - LOG(INFO) << __func__ << " remote devices connected conn_id: "<< remoteDevice.conn_id << - "bd_addr " << remoteDevice.peer_bda; - rsp->remoteDevice = instance->remoteDevices.FindByAddress(p_data->conn.remote_bda); - if ( rsp->remoteDevice == NULL) { - LOG(INFO) << __func__ ; - break; - } - proc_event = MCP_CONNECTION; - rsp->event = MCP_CONNECTION; - break; - } - - case BTA_GATTS_CLOSE_EVT: - case BTA_GATTS_DISCONNECT_EVT: { - p_data = (tBTA_GATTS*)param; - LOG(INFO) << __func__ << " remote devices disconnected conn_id " << p_data->conn.conn_id; - RemoteDevice *remoteDevice; - remoteDevice = instance->remoteDevices.FindByConnId(p_data->conn.conn_id); - if((!remoteDevice) ) { - status = BT_STATUS_FAIL; - break; - } - - rsp->remoteDevice = remoteDevice; - proc_event = MCP_DISCONNECTION; - rsp->event = MCP_DISCONNECTION; - LOG(INFO) << __func__ << " disconnected conn_id " << p_data->conn.conn_id; - break; - } - - case BTA_GATTS_STOP_EVT: - // not required - break; - - case BTA_GATTS_DELELTE_EVT: - // not required - break; - - case BTA_GATTS_READ_CHARACTERISTIC_EVT: { - p_data = (tBTA_GATTS*)param; - std::vector value; - RemoteDevice *remoteDevice = - instance->remoteDevices.FindByConnId(p_data->req_data.conn_id); - LOG(INFO) << __func__ << " charateristcs read handle " << - p_data->req_data.p_data->read_req.handle <<" trans_id : " << - p_data->req_data.trans_id; - - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " device not found ignore read operation"; - status = BT_STATUS_FAIL; - break; - } - - LOG(INFO) <<" offset: " << p_data->req_data.p_data->read_req.offset << - " long : " << p_data->req_data.p_data->read_req.is_long; - - rsp->rsp_value.attr_value.auth_req = 0; - rsp->rsp_value.attr_value.handle = p_data->req_data.p_data->read_req.handle; - rsp->rsp_value.attr_value.offset = p_data->req_data.p_data->read_req.offset; - - if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.media_state_handle) { - proc_event = MCP_MEDIA_STATE_READ; - LOG(INFO) << __func__ << " media_state_handle read"; - } else if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.media_control_point_opcode_supported_handle) { - proc_event = MCP_MEDIA_CONTROL_POINT_OPCODE_SUPPORTED_READ; - LOG(INFO) << __func__ << " media_control_point_opcode_supported_handle read"; - } else if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.media_player_name_handle) { - proc_event = MCP_MEDIA_PLAYER_NAME_READ; - LOG(INFO) << __func__ << " media_player_name_handle read"; - } else if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.track_title_handle) { - proc_event = MCP_TRACK_TITLE_READ; - LOG(INFO) << __func__ << " track_title_handle read"; - } else if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.track_position_handle) { - proc_event = MCP_TRACK_POSITION_READ; - LOG(INFO) << __func__ << " track_position_handle read"; - } else if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.track_duration_handle) { - proc_event = MCP_TRACK_DURATION_READ; - LOG(INFO) << __func__ << " track_duration_handle read"; - } else if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.ccid_handle) { - LOG(INFO) << __func__ << " ccid_handle read"; - proc_event = MCP_CCID_READ; - } else if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.seeking_speed_handle) { - LOG(INFO) << __func__ << " seeking_speed_handle read"; - proc_event = MCP_SEEKING_SPEED_READ; - } else if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.playing_order_supported_handle) { - LOG(INFO) << __func__ << " playing_order_supported_handle read"; - proc_event = MCP_PLAYING_ORDER_SUPPORTED_READ; - } else if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.playing_order_handle) { - LOG(INFO) << __func__ << " playing_order_handle read"; - proc_event = MCP_PLAYING_ORDER_READ; - } else { - LOG(INFO) << __func__ << " read request for unknown handle" << p_data->req_data.p_data->read_req.handle; - status = BT_STATUS_FAIL; - break; - } - LOG(INFO) << __func__ << " read request handle" << p_data->req_data.p_data->read_req.handle << - "connection id" << p_data->req_data.conn_id; - rsp->event = MCP_READ_RSP; - rsp->oper.ReadOp.trans_id = p_data->req_data.trans_id; - rsp->oper.ReadOp.is_long = p_data->req_data.p_data->read_req.is_long; - rsp->oper.ReadOp.status = BT_STATUS_SUCCESS; - rsp->remoteDevice = remoteDevice; - break; - } - - case BTA_GATTS_READ_DESCRIPTOR_EVT: { - LOG(INFO) << __func__ << " read descriptor"; - p_data = (tBTA_GATTS*)param; - LOG(INFO) << __func__ << " charateristcs read desc handle " << - p_data->req_data.p_data->read_req.handle << " offset : " - << p_data->req_data.p_data->read_req.offset; - RemoteDevice *remoteDevice = - instance->remoteDevices.FindByConnId(p_data->req_data.conn_id); - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " device not found ignore write"; - status = BT_STATUS_FAIL; - break; - } - - if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.media_state_desc) { - LOG(INFO) << __func__ << " media_state_desc read"; - proc_event = MCP_MEDIA_STATE_READ_DESCRIPTOR; - } else if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.media_control_point_desc) { - LOG(INFO) << __func__ << " media_control_point_desc read"; - proc_event = MCP_MEDIA_CONTROL_POINT_READ_DESCRIPTOR; - } else if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.media_control_point_opcode_supported_desc) { - LOG(INFO) << __func__ << " media_control_point_opcode_supported_desc read"; - proc_event = MCP_MEDIA_CONTROL_POINT_OPCODE_SUPPORTED_DESCRIPTOR_READ; - } else if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.media_player_name_desc) { - LOG(INFO) << __func__ << " media_player_name_desc read"; - proc_event = MCP_MEDIA_PLAYER_NAME_DESCRIPTOR_READ; - } else if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.track_changed_desc) { - LOG(INFO) << __func__ << " track_changed_desc read"; - proc_event = MCP_TRACK_CHANGED_DESCRIPTOR_READ; - } else if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.track_title_desc) { - LOG(INFO) << __func__ << " track_title_desc read"; - proc_event = MCP_TRACK_TITLE_DESCRIPTOR_READ; - } else if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.track_position_desc) { - LOG(INFO) << __func__ << " track_position_desc read"; - proc_event = MCP_TRACK_POSITION_DESCRIPTOR_READ; - } else if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.track_duration_desc) { - LOG(INFO) << __func__ << " track_duration_desc read"; - proc_event = MCP_TRACK_DURATION_DESCRIPTOR_READ; - } else if(p_data->req_data.p_data->read_req.handle == - mcsServerServiceInfo.playing_order_desc) { - LOG(INFO) << __func__ << " playing_order_desc read"; - proc_event = MCP_PLAYING_ORDER_DESCRIPTOR_READ; - } else { - LOG(INFO) << __func__ << " read request for unknown handle" << p_data->req_data.p_data->read_req.handle; - status = BT_STATUS_FAIL; - break; - } - rsp->event = MCP_DESCRIPTOR_READ_RSP; - rsp->rsp_value.attr_value.auth_req = 0; - rsp->rsp_value.attr_value.handle = p_data->req_data.p_data->read_req.handle; - rsp->rsp_value.attr_value.offset = p_data->req_data.p_data->read_req.offset; - //mcp response - rsp->oper.ReadDescOp.desc_handle = p_data->req_data.p_data->read_req.handle; - rsp->oper.ReadDescOp.trans_id = p_data->req_data.trans_id; - rsp->oper.ReadDescOp.status = BT_STATUS_SUCCESS; - rsp->remoteDevice = remoteDevice; - break; - } - - case BTA_GATTS_WRITE_CHARACTERISTIC_EVT: { - p_data = (tBTA_GATTS*)param; - const auto& req = p_data->req_data.p_data->write_req; - LOG(INFO) << __func__ << " write characteristics len : " << req.len << " value "<< req.value[0]; - RemoteDevice *remoteDevice = - instance->remoteDevices.FindByConnId(p_data->req_data.conn_id); - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " device not found ignore write"; - status = BT_STATUS_DEVICE_NOT_CONNECTED; - break; - } - - rsp->event = MCP_WRITE_RSP; - rsp->oper.WriteOp.status = BT_STATUS_SUCCESS; - if (req.handle == mcsServerServiceInfo.playing_order_handle) { - proc_event = MCP_PLAYING_ORDER_WRITE; - } else if (req.handle == mcsServerServiceInfo.media_control_point_handle) { - proc_event = MCP_MEDIA_CONTROL_POINT_WRITE; - } else if (req.handle == mcsServerServiceInfo.track_position_handle) { - proc_event = MCP_TRACK_POSITION_WRITE; - } else { - //characteristics handle not matched. - // - rsp->oper.WriteOp.status = BT_STATUS_HANLDE_NOT_MATCHED; - } - rsp->oper.WriteOp.char_handle = req.handle; - rsp->oper.WriteOp.trans_id = p_data->req_data.trans_id; - rsp->remoteDevice = remoteDevice; - rsp->oper.WriteOp.need_rsp = req.need_rsp; - rsp->oper.WriteOp.offset = req.offset; // need to check requirement - memcpy(rsp->oper.WriteOp.data, req.value, req.len); - LOG(INFO) << __func__ << " Local Tx ID " << rsp->oper.WriteOp.trans_id << " Gatt Tx ID: " << p_data->req_data.trans_id; - break; - } - - case BTA_GATTS_WRITE_DESCRIPTOR_EVT: { - p_data = (tBTA_GATTS* )param; - uint16_t req_value = 0; - const auto& req = p_data->req_data.p_data->write_req; - RemoteDevice *remoteDevice = - instance->remoteDevices.FindByConnId(p_data->req_data.conn_id); - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " device not found ignore notification"; - break; - } - req_value = *(uint16_t* )req.value; - //need to initialized with proper error code - int status = BT_STATUS_SUCCESS; - LOG(INFO) << __func__ << " write descriptor :" << req.handle << - "is resp: " << req.need_rsp << "is prep: " << req.is_prep << " value " << req_value; - - if(req.handle == - mcsServerServiceInfo.media_state_desc) { - LOG(INFO) << __func__ << " media_state_desc descriptor write"; - remoteDevice->media_state_notify = req_value; - proc_event = MCP_MEDIA_STATE_DESCRIPTOR_WRITE; - } else if(req.handle == - mcsServerServiceInfo.media_player_name_desc) { - remoteDevice->media_player_name_notify = req_value; - LOG(INFO) << __func__ << " media_player_name_desc descriptor write"; - proc_event = MCP_MEDIA_PLAYER_NAME_DESCRIPTOR_WRITE; - } else if(req.handle == - mcsServerServiceInfo.media_control_point_desc) { - remoteDevice->media_control_point_notify = req_value; - LOG(INFO) << __func__ << " media_player_control_point_desc descriptor write"; - proc_event = MCP_MEDIA_CONTROL_POINT_DESCRIPTOR_WRITE; - } else if(req.handle == - mcsServerServiceInfo.media_control_point_opcode_supported_desc) { - remoteDevice->media_control_point_opcode_supported_notify = req_value; - LOG(INFO) << __func__ << " media_control_point_opcode_supported_desc descriptor write"; - proc_event = MCP_MEDIA_CONTROL_POINT_SUPPORTED_DESCRIPTOR_WRITE; - } else if(req.handle == - mcsServerServiceInfo.track_changed_desc) { - remoteDevice->track_changed_notify = req_value; - LOG(INFO) << __func__ << " track_changed_desc descriptor write"; - proc_event = MCP_TRACK_CHANGED_DESCRIPTOR_WRITE; - } else if(req.handle == - mcsServerServiceInfo.track_title_desc) { - remoteDevice->track_title_notify = req_value; - LOG(INFO) << __func__ << " track_title_desc descriptor write"; - proc_event = MCP_TRACK_TITLE_DESCRIPTOR_WRITE; - } else if(req.handle == - mcsServerServiceInfo.track_position_desc) { - remoteDevice->track_position_notify = req_value; - LOG(INFO) << __func__ << " track_position_desc descriptor write"; - proc_event = MCP_TRACK_POSITION_DESCRIPTOR_WRITE; - } else if(req.handle == - mcsServerServiceInfo.track_duration_desc) { - remoteDevice->track_duration_notify = req_value; - LOG(INFO) << __func__ << " track_duration_desc descriptor write"; - proc_event = MCP_TRACK_DURATION_DESCRIPTOR_WRITE; - } else if(req.handle == - mcsServerServiceInfo.playing_order_desc) { - remoteDevice->playing_order_notify = req_value; - LOG(INFO) << __func__ << " playing_order_desc descriptor write"; - proc_event = MCP_PLAYING_ORDER_DESCRIPTOR_WRITE; - } else { - LOG(INFO) << __func__ << " descriptor write not matched "; - status = 4; //need to check error code - } - rsp->event = MCP_DESCRIPTOR_WRITE_RSP; - rsp->oper.WriteDescOp.desc_handle = req.handle; - rsp->oper.WriteDescOp.trans_id = p_data->req_data.trans_id; - rsp->oper.WriteDescOp.status = status; - rsp->oper.WriteDescOp.need_rsp = req.need_rsp; - rsp->oper.WriteDescOp.notification = req_value; - rsp->remoteDevice = remoteDevice; - break; - } - - case BTA_GATTS_EXEC_WRITE_EVT: { - p_data = (tBTA_GATTS*)param; - // need to check requirement - break; - } - - case BTA_GATTS_PHY_UPDATE_EVT: { - p_data = (tBTA_GATTS*)param; - RemoteDevice *remoteDevice = - instance->remoteDevices.FindByConnId(p_data->phy_update.conn_id); - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " device not found ignore phy update" - << p_data->phy_update.status; - status = BT_STATUS_FAIL; - break; - } - proc_event = MCP_PHY_UPDATE; - rsp->event = MCP_PHY_UPDATE; - rsp->oper.PhyOp.rx_phy = p_data->phy_update.rx_phy; - rsp->oper.PhyOp.tx_phy = p_data->phy_update.tx_phy; - rsp->remoteDevice = remoteDevice; - break; - } - - case BTA_GATTS_CONN_UPDATE_EVT: { - p_data = (tBTA_GATTS*)param; - RemoteDevice *remoteDevice = - instance->remoteDevices.FindByConnId(p_data->phy_update.conn_id); - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " connection update device not found"; - break; - } - LOG(INFO) << __func__ << " connection update status" << p_data->phy_update.status; - proc_event = MCP_CONNECTION_UPDATE; - rsp->event = MCP_CONNECTION_UPDATE; - rsp->oper.ConnectionUpdateOp.latency = p_data->conn_update.latency; - rsp->oper.ConnectionUpdateOp.timeout = p_data->conn_update.timeout; - rsp->oper.ConnectionUpdateOp.interval = p_data->conn_update.interval; - rsp->oper.ConnectionUpdateOp.status = p_data->conn_update.status; - rsp->remoteDevice = remoteDevice; - break; - } - - case MCP_ACTIVE_DEVICE_UPDATE: - { - tMCP_SET_ACTIVE_DEVICE *data = (tMCP_SET_ACTIVE_DEVICE *)param; - LOG(INFO) << __func__ << " address " << data->address; - RemoteDevice *remoteDevice = instance->remoteDevices.FindByAddress(data->address); - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " active device update device address not found"; - break; - } - instance->remoteDevices.AddSetActiveDevice(data); - rsp->remoteDevice = remoteDevice; - rsp->oper.SetActiveDeviceOp.profile = data->profile; - proc_event = MCP_ACTIVE_DEVICE_UPDATE; - rsp->event = MCP_ACTIVE_DEVICE_UPDATE; - - - break; - } - - case MCP_MEDIA_STATE_UPDATE: - { - tMCP_MEDIA_STATE *data = (tMCP_MEDIA_STATE *) param; - if (mediaPlayerInfo.media_state != data->state) - mediaPlayerInfo.media_state = data->state; - LOG(INFO) << __func__ << " state: " << unsigned(mediaPlayerInfo.media_state); - proc_event = MCP_NOTIFY_ALL; - rsp->event = MCP_NOTIFY_ALL; - rsp->handle = mcsServerServiceInfo.media_state_handle; - rsp->oper.MediaUpdateOp.data = &mediaPlayerInfo.media_state; - rsp->oper.MediaUpdateOp.len = sizeof(mediaPlayerInfo.media_state); - break; - } - - case MCP_MEDIA_PLAYER_NAME_UPDATE: - { - tMCP_MEDIA_PLAYER_NAME *data = (tMCP_MEDIA_PLAYER_NAME *) param; - if (memcmp(mediaPlayerInfo.player_name, data->name, data->len)) { - memcpy(mediaPlayerInfo.player_name, data, data->len); - mediaPlayerInfo.player_name_len = data->len; - } - proc_event = MCP_NOTIFY_ALL; - rsp->event = MCP_NOTIFY_ALL; - rsp->handle = mcsServerServiceInfo.media_player_name_handle; - rsp->oper.MediaUpdateOp.data = (uint8_t *)mediaPlayerInfo.player_name; - rsp->oper.MediaUpdateOp.len = mediaPlayerInfo.player_name_len; - break; - } - - case MCP_MEDIA_SUPPORTED_OPCODE_UPDATE: - { - tMCP_MEDIA_OPCODE_SUPPORT *data = (tMCP_MEDIA_OPCODE_SUPPORT *)param; - mediaPlayerInfo.media_supported_feature = data->supported; - proc_event = MCP_NOTIFY_ALL; - rsp->event = MCP_NOTIFY_ALL; - rsp->handle = mcsServerServiceInfo.media_control_point_opcode_supported_handle; - rsp->oper.MediaUpdateOp.data = (uint8_t *)&mediaPlayerInfo.media_supported_feature; - rsp->oper.MediaUpdateOp.len = sizeof(mediaPlayerInfo.media_supported_feature); - break; - } - - case MCP_MEDIA_CONTROL_POINT_UPDATE: - { - tMCP_MEDIA_CONTROL_POINT *data = (tMCP_MEDIA_CONTROL_POINT *)param; - mediaPlayerInfo.media_ctrl_point = data->req_opcode | (data->result << 8); - proc_event = MCP_NOTIFY_ALL; - rsp->event = MCP_NOTIFY_ALL; - rsp->handle = mcsServerServiceInfo.media_control_point_handle; - rsp->oper.MediaUpdateOp.data = (uint8_t *)&mediaPlayerInfo.media_ctrl_point; - rsp->oper.MediaUpdateOp.len = sizeof(mediaPlayerInfo.media_ctrl_point); - break; - } - case MCP_PLAYING_ORDER_SUPPORTED_UPDATE: - { - tMCP_PLAYING_ORDER_SUPPORT *data = (tMCP_PLAYING_ORDER_SUPPORT *) param; - mediaPlayerInfo.playing_order_supported = data->order_supported; - proc_event = MCP_NOTIFY_ALL; - rsp->event = MCP_NOTIFY_ALL; - rsp->handle = - mcsServerServiceInfo.media_control_point_opcode_supported_handle; - rsp->oper.MediaUpdateOp.data = (uint8_t *)&mediaPlayerInfo.playing_order_supported; - rsp->oper.MediaUpdateOp.len = sizeof(mediaPlayerInfo.playing_order_supported); - break; - } - - case MCP_PLAYING_ORDER_UPDATE: - { - tMCP_PLAYING_ORDER *data = (tMCP_PLAYING_ORDER *) param; - mediaPlayerInfo.playing_order_value = data->order; - proc_event = MCP_NOTIFY_ALL; - rsp->event = MCP_NOTIFY_ALL; - rsp->handle = mcsServerServiceInfo.playing_order_handle; - rsp->oper.MediaUpdateOp.data = (uint8_t *)&mediaPlayerInfo.playing_order_value; - rsp->oper.MediaUpdateOp.len = sizeof(mediaPlayerInfo.playing_order_value); - break; - } - - case MCP_TRACK_CHANGED_UPDATE: - { - tMCP_TRACK_CHANGED *data = (tMCP_TRACK_CHANGED *) param; - mediaPlayerInfo.track_changed = data->status; - proc_event = MCP_NOTIFY_ALL; - rsp->event = MCP_NOTIFY_ALL; - rsp->handle = mcsServerServiceInfo.track_changed_handle; - rsp->oper.MediaUpdateOp.data = (uint8_t *)&mediaPlayerInfo.track_changed; - rsp->oper.MediaUpdateOp.len = sizeof(mediaPlayerInfo.track_changed); - break; - } - - case MCP_TRACK_POSITION_UPDATE: - { - tMCP_TRACK_POSTION *data = (tMCP_TRACK_POSTION*) param; - if(data->position != mediaPlayerInfo.position) { - mediaPlayerInfo.position = data->position; - } - proc_event = MCP_NOTIFY_ALL; - rsp->event = MCP_NOTIFY_ALL; - rsp->handle = mcsServerServiceInfo.track_position_handle; - rsp->oper.MediaUpdateOp.data = (uint8_t *)&mediaPlayerInfo.position; - rsp->oper.MediaUpdateOp.len = sizeof(mediaPlayerInfo.position); - break; - } - - case MCP_TRACK_DURATION_UPDATE: - { - tMCP_TRACK_DURATION* data = (tMCP_TRACK_DURATION *) param; - mediaPlayerInfo.duration = data->duration; - proc_event = MCP_NOTIFY_ALL; - rsp->event = MCP_NOTIFY_ALL; - rsp->rsp_value.handle = mcsServerServiceInfo.track_duration_handle; - rsp->handle = mcsServerServiceInfo.track_duration_handle; - rsp->oper.MediaUpdateOp.data = (uint8_t *)&mediaPlayerInfo.duration; - rsp->oper.MediaUpdateOp.len = sizeof(mediaPlayerInfo.duration); - break; - } - - case MCP_TRACK_TITLE_UPDATE: - { - tMCP_TRACK_TITLE *data = (tMCP_TRACK_TITLE*) param; - proc_event = MCP_NOTIFY_ALL; - rsp->event = MCP_NOTIFY_ALL; - rsp->handle = mcsServerServiceInfo.track_title_handle; - if (memcmp(mediaPlayerInfo.title, data->title, data->len)) { - memcpy(mediaPlayerInfo.title, data->title, data->len); - mediaPlayerInfo.track_title_len = data->len; - } - rsp->oper.MediaUpdateOp.data = (uint8_t *)mediaPlayerInfo.title; - rsp->oper.MediaUpdateOp.len = sizeof(mediaPlayerInfo.track_title_len); - break; - } - case MCP_CCID_UPDATE: - { - tMCP_CONTENT_CONTROL_ID *data = (tMCP_CONTENT_CONTROL_ID *) param; - mediaPlayerInfo.ccid = (uint8_t)data->ccid; - proc_event = MCP_NOTIFY_ALL; - rsp->event = MCP_NOTIFY_ALL; - rsp->handle = mcsServerServiceInfo.ccid_handle; - rsp->oper.MediaUpdateOp.data = (uint8_t *)&mediaPlayerInfo.ccid; - rsp->oper.MediaUpdateOp.len = sizeof(mediaPlayerInfo.ccid); - break; - } - - case MCP_CONNECTION_CLOSE_EVENT: - { - tMCP_CONNECTION_CLOSE* p_data = (tMCP_CONNECTION_CLOSE *)param; - RemoteDevice* remoteDevice = instance->remoteDevices.FindByAddress(p_data->addr); - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " address is not in list"; - break; - } - proc_event = MCP_CONNECTION_CLOSE_EVENT; - rsp->remoteDevice = remoteDevice; - break; - } - - case MCP_BOND_STATE_CHANGE_EVENT: - { - tMCP_BOND_STATE_CHANGE* p_data = (tMCP_BOND_STATE_CHANGE *)param; - RemoteDevice* remoteDevice = instance->remoteDevices.FindByAddress(p_data->addr); - if(remoteDevice == NULL) { - LOG(INFO) << __func__ << " address is not in list"; - break; - } - instance->remoteDevices.Remove(p_data->addr); - break; - } - default: - LOG(INFO) << __func__ << " event not matched !!"; - break; - } - - if(rsp->event != MCP_NONE_EVENT) { - LOG(INFO) << __func__ << " event to media handler " << get_mcp_event_name(rsp->event); - mediaPlayerInfo.MediaStateHandlerPointer[mediaPlayerInfo.media_state](proc_event, rsp, mediaPlayerInfo.media_state); - } - if(rsp) { - LOG(INFO) << __func__ << "free rsp data"; - osi_free(rsp); - } -} - - -bool MediaStateInactiveHandler(uint32_t event, void* param, uint8_t state) { - LOG(INFO) << __func__ << " handle event " << get_mcp_event_name(event) - << " in state " << get_mcp_media_state_name(state); - - mcp_resp_t *p_data = (mcp_resp_t *)param; - - RemoteDevice *device = p_data->remoteDevice; - LOG(INFO) << __func__ << " inactive mcs handle event "<< get_mcp_event_name(p_data->event); - switch(event) { - case MCP_NOTIFY_ALL: { - LOG(INFO) << __func__ << " Notify all handle "<< p_data->handle; - std::vectornotifyDevices = instance->remoteDevices.FindNotifyDevices(p_data->handle); - std::vector::iterator it; - if (notifyDevices.size() <= 0) { - LOG(INFO) << __func__ << " No device register for notification"; - break; - } - for (it = notifyDevices.begin(); it != notifyDevices.end(); it++){ - LOG(INFO) << __func__ << " Notify all handle device id " << it->conn_id; - p_data->remoteDevice = instance->remoteDevices.FindByConnId(it->conn_id); - it->DeviceStateHandlerPointer[it->state](p_data->event, p_data, it->state); - } - break; - } - - case MCP_TRACK_POSITION_WRITE: - case MCP_PLAYING_ORDER_WRITE: { - LOG(INFO) << __func__ << "Ignore other request as player is not active"; - //need to ignore write rsp because no player is active - p_data->rsp_value.attr_value.len = 0; - uint8_t data = (uint8_t)(*p_data->oper.WriteOp.data); - std::vector value; - value.push_back(data); - value.push_back(0x03); // To-Do check ??? - LOG(INFO) << __func__ << "hndl " << p_data->oper.WriteOp.char_handle; - GattsOpsQueue::SendNotification(device->conn_id, p_data->oper.WriteOp.char_handle, value, false); - break; - } - - case MCP_MEDIA_CONTROL_POINT_WRITE: { - LOG(INFO) << __func__ << "Ignore other request as player is not active ctrl pt write"; - //need to ignore write rsp because no player is active - p_data->rsp_value.attr_value.len = 0; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - uint8_t data = (uint8_t)(*p_data->oper.WriteOp.data); - uint8_t status = MCP_MEDIA_PLAYER_INACTIVE; - std::vector value; - bool opcode_support = is_opcode_supported(data); - if (!opcode_support) { - status = MCP_OPCODE_NOT_SUPPORTED; - LOG(INFO) << __func__ << "Sending OPCode Unsupported indication"; - } else { - LOG(INFO) << __func__ << "Sending INACTIVE indication"; - } - value.push_back(data); - value.push_back(status); - LOG(INFO) << __func__ << "handle " << p_data->oper.WriteOp.char_handle; - GattsOpsQueue::SendNotification(device->conn_id, p_data->oper.WriteOp.char_handle, value, false); - break; - } - case MCP_MEDIA_STATE_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.media_state); - *(uint8_t *)p_data->rsp_value.attr_value.value = (uint8_t)mediaPlayerInfo.media_state; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.media_state); - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_PLAYER_NAME_READ: { - uint16_t len = mediaPlayerInfo.player_name_len; - if (device->mtu != -1 && len >= device->mtu - 3) //to check player len should not greater than mtu - len = device->mtu - 3; - p_data->rsp_value.attr_value.len = len; - memcpy(p_data->rsp_value.attr_value.value, mediaPlayerInfo.player_name, - p_data->rsp_value.attr_value.len); - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_OPCODE_SUPPORTED_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.media_supported_feature); - *(uint32_t*)p_data->rsp_value.attr_value.value = - MCP_DEFAULT_MEDIA_CTRL_SUPP_FEAT; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_TITLE_READ: { - uint16_t len = mediaPlayerInfo.track_title_len; - if (device->mtu != -1 && len >= device->mtu - 3) //to check title len should not greater than mtu - len = device->mtu - 3; - p_data->rsp_value.attr_value.len = len; - memcpy(p_data->rsp_value.attr_value.value, mediaPlayerInfo.title, - p_data->rsp_value.attr_value.len); - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_POSITION_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.position); - *(int *)p_data->rsp_value.attr_value.value = (int)mediaPlayerInfo.position; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_DURATION_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.duration); - *(int *)p_data->rsp_value.attr_value.value = (int)mediaPlayerInfo.duration; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_PLAYING_ORDER_SUPPORTED_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.playing_order_supported); - *(uint16_t *)p_data->rsp_value.attr_value.value = - (uint16_t)mediaPlayerInfo.playing_order_supported; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_PLAYING_ORDER_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.playing_order_value); - *(uint16_t *)p_data->rsp_value.attr_value.value = (uint16_t)mediaPlayerInfo.playing_order_value; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_CCID_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.ccid); - *(uint32_t *)p_data->rsp_value.attr_value.value = (uint8_t)mediaPlayerInfo.ccid; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_SEEKING_SPEED_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.seeking_speed); - *(uint8_t *)p_data->rsp_value.attr_value.value = (uint8_t)mediaPlayerInfo.seeking_speed; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_STATE_READ_DESCRIPTOR:{ - *(uint16_t *)p_data->rsp_value.attr_value.value = (uint16_t)device->media_state_notify; - p_data->rsp_value.attr_value.len = sizeof(device->media_state_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_READ_DESCRIPTOR: { - *(uint16_t *)p_data->rsp_value.attr_value.value = (uint16_t)device->media_control_point_notify; - p_data->rsp_value.attr_value.len = sizeof(device->media_control_point_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_OPCODE_SUPPORTED_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = - (uint16_t)device->media_control_point_opcode_supported_notify; - p_data->rsp_value.attr_value.len = sizeof(device->media_control_point_opcode_supported_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_PLAYER_NAME_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = (uint16_t)device->media_player_name_notify; - p_data->rsp_value.attr_value.len = sizeof(device->media_player_name_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_CHANGED_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = (uint16_t)device->track_changed_notify; - p_data->rsp_value.attr_value.len = sizeof(device->track_changed_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_TITLE_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = (uint16_t)device->track_title_notify; - p_data->rsp_value.attr_value.len = sizeof(device->track_title_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_POSITION_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = (uint16_t)device->track_position_notify; - p_data->rsp_value.attr_value.len = sizeof(device->track_position_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_DURATION_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = (uint16_t)device->track_duration_notify;; - p_data->rsp_value.attr_value.len = sizeof(device->track_duration_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_PLAYING_ORDER_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = (uint16_t)device->playing_order_notify; - p_data->rsp_value.attr_value.len = sizeof(device->playing_order_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_MEDIA_STATE_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.media_state; - p_data->oper.WriteDescOp.len = sizeof (mediaPlayerInfo.media_state); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.media_state_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_PLAYER_NAME_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.player_name; - p_data->oper.WriteDescOp.len = mediaPlayerInfo.player_name_len; - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.media_player_name_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.media_ctrl_point; - p_data->oper.WriteDescOp.len = sizeof (mediaPlayerInfo.media_ctrl_point); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.media_control_point_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_SUPPORTED_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.media_supported_feature; - p_data->oper.WriteDescOp.len = sizeof (mediaPlayerInfo.media_supported_feature); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.media_control_point_opcode_supported_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_CHANGED_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.track_changed; - p_data->oper.WriteDescOp.len = sizeof (mediaPlayerInfo.track_changed); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.track_changed_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_TITLE_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.title; - p_data->oper.WriteDescOp.len = mediaPlayerInfo.track_title_len; - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.track_title_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_TRACK_POSITION_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.position; - p_data->oper.WriteDescOp.len = sizeof(mediaPlayerInfo.position); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.track_position_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_TRACK_DURATION_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.duration; - p_data->oper.WriteDescOp.len = sizeof(mediaPlayerInfo.duration); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.track_duration_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_PLAYING_ORDER_DESCRIPTOR_WRITE : { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.playing_order_value; - p_data->oper.WriteDescOp.len = sizeof(mediaPlayerInfo.playing_order_value); - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_CONGESTION_UPDATE: { - McpCongestionUpdate(p_data); - break; - } - - case MCP_CONNECTION_UPDATE: - case MCP_ACTIVE_DEVICE_UPDATE: - case MCP_PHY_UPDATE: - case MCP_CONNECTION: - case MCP_CONNECTION_CLOSE_EVENT: - case MCP_DISCONNECTION: - case MCP_BOND_STATE_CHANGE_EVENT: - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - - default: - LOG(INFO) << __func__ << " event is not in list"; - break; - } - - return BT_STATUS_SUCCESS; -} - - - -bool MediaStatePlayingHandler(uint32_t event, void* param, uint8_t state) { - LOG(INFO) << __func__ << " handle event " << get_mcp_event_name(event) - << " in state " << get_mcp_media_state_name(state); - mcp_resp_t *p_data = (mcp_resp_t *)param; - RemoteDevice *device = p_data->remoteDevice; - switch(event) { - case MCP_NOTIFY_ALL: { - LOG(INFO) << __func__ << " Notify all handle "<< p_data->handle; - std::vectornotifyDevices = instance->remoteDevices.FindNotifyDevices(p_data->handle); - std::vector::iterator it; - if (notifyDevices.size() <= 0) { - LOG(INFO) << __func__ << " No device register for notification"; - } - for (it = notifyDevices.begin(); it != notifyDevices.end(); it++){ - LOG(INFO) << __func__ << " Notify all handle device id " << it->conn_id; - p_data->remoteDevice = instance->remoteDevices.FindByConnId(it->conn_id); - it->DeviceStateHandlerPointer[it->state](p_data->event, p_data, it->state); - } - break; - } - case MCP_PLAYING_ORDER_WRITE: { - uint8_t data = (uint8_t)(*p_data->oper.WriteOp.data); - if (mediaPlayerInfo.playing_order_supported & data) { - instance->PlayingOrderChangeReq(data & mediaPlayerInfo.playing_order_value); - } else { - LOG(INFO) << __func__ << " ignore playing_order_handle write feature is not supported"; - break; - } - p_data->rsp_value.attr_value.len = 0; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_WRITE: { - uint8_t data = (uint8_t)(*p_data->oper.WriteOp.data); - uint8_t opcode_support = is_opcode_supported(data); - LOG(INFO) << __func__ << " data " << data << " Tx ID: " << p_data->oper.WriteOp.trans_id; - if (!opcode_support) { - uint8_t status = MCP_OPCODE_NOT_SUPPORTED; - std::vector value; - value.push_back(data); - value.push_back(status); - LOG(INFO) << __func__ << "hndl " << p_data->oper.WriteOp.char_handle; - LOG(INFO) << __func__ << "opcode not supported " << data; - GattsOpsQueue::SendNotification(device->conn_id, p_data->oper.WriteOp.char_handle, value, false); - } - if (data != MCP_MEDIA_CONTROL_OPCODE_PLAY) { - instance->MediaControlPointChangeReq((uint32_t)data, device->peer_bda); - LOG(INFO) << __func__ << "media_control_point_handle write "; - } else { - LOG(INFO) << __func__ << " ignore media_control_point_handle write feature is not supported/already playing"; - } - p_data->rsp_value.attr_value.len = 0; - device = p_data->remoteDevice; - LOG(INFO) << __func__ << " p_data->event "<< p_data->event; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_POSITION_WRITE: { - uint32_t track_duration = mediaPlayerInfo.duration; - uint32_t track_position = mediaPlayerInfo.position; - uint32_t data; - uint8_t *w_data = p_data->oper.WriteOp.data; - STREAM_TO_UINT32(data, w_data); - uint32_t position = track_duration; - if ((track_position == (uint32_t)data) || (data < 0) || - (track_duration == 0xFFFF) || (track_duration > 0 && track_duration < data)) { - LOG(INFO) << __func__ << " ignore track_position_handle write"; - } else { - position = data; - instance->TrackPositionChangeReq(data); - LOG(INFO) << __func__ << " track_position_handle write"; - } - std::vector value; - value.push_back(position & 0xff); - value.push_back((position >> 8) & 0xff); - value.push_back((position >> 16) & 0xff); - value.push_back((position >> 24) & 0xff); - GattsOpsQueue::SendNotification(device->conn_id, p_data->oper.WriteOp.char_handle, value, false); - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_STATE_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.media_state); - *(uint8_t *)p_data->rsp_value.attr_value.value = *(uint8_t *)&mediaPlayerInfo.media_state; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_PLAYER_NAME_READ: { - uint16_t len = mediaPlayerInfo.player_name_len; - if (device->mtu != -1 && len >= device->mtu - 3) //to check player len should not greater than mtu - len = device->mtu - 3; - p_data->rsp_value.attr_value.len = len; - memcpy(p_data->rsp_value.attr_value.value, mediaPlayerInfo.player_name, - p_data->rsp_value.attr_value.len); - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_OPCODE_SUPPORTED_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.media_supported_feature); - *(uint32_t*)p_data->rsp_value.attr_value.value = - *(uint32_t *)&mediaPlayerInfo.media_supported_feature; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_TITLE_READ: { - uint16_t len = mediaPlayerInfo.track_title_len; - if (device->mtu != -1 && len >= device->mtu - 3) //to check title len should not greater than mtu - len = device->mtu - 3; - p_data->rsp_value.attr_value.len = len; - memcpy(p_data->rsp_value.attr_value.value, mediaPlayerInfo.title, - p_data->rsp_value.attr_value.len); - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_POSITION_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.position); - *(int *)p_data->rsp_value.attr_value.value = *(int *)&mediaPlayerInfo.position; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_DURATION_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.duration); - *(int *)p_data->rsp_value.attr_value.value = *(int *)&mediaPlayerInfo.duration; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_PLAYING_ORDER_SUPPORTED_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.playing_order_supported); - *(uint16_t *)p_data->rsp_value.attr_value.value = - *(uint16_t *)&mediaPlayerInfo.playing_order_supported; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_PLAYING_ORDER_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.playing_order_value); - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&mediaPlayerInfo.playing_order_value; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_CCID_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.ccid); - *(uint32_t *)p_data->rsp_value.attr_value.value = *(uint8_t *)&mediaPlayerInfo.ccid; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_SEEKING_SPEED_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.seeking_speed); - *(uint8_t *)p_data->rsp_value.attr_value.value = (uint8_t)mediaPlayerInfo.seeking_speed; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_MEDIA_STATE_READ_DESCRIPTOR:{ - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->media_state_notify; - p_data->rsp_value.attr_value.len = sizeof(device->media_state_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_MEDIA_CONTROL_POINT_READ_DESCRIPTOR: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->media_control_point_notify; - p_data->rsp_value.attr_value.len = sizeof(device->media_control_point_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_MEDIA_CONTROL_POINT_OPCODE_SUPPORTED_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = - *(uint16_t *)&device->media_control_point_opcode_supported_notify; - p_data->rsp_value.attr_value.len = sizeof(device->media_control_point_opcode_supported_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_MEDIA_PLAYER_NAME_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->media_player_name_notify; - p_data->rsp_value.attr_value.len = sizeof(device->media_player_name_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_TRACK_CHANGED_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->track_changed_notify; - p_data->rsp_value.attr_value.len = sizeof(device->track_changed_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_TRACK_TITLE_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->track_title_notify; - p_data->rsp_value.attr_value.len = sizeof(device->track_title_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_TRACK_POSITION_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->track_position_notify; - p_data->rsp_value.attr_value.len = sizeof(device->track_position_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_TRACK_DURATION_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->track_duration_notify;; - p_data->rsp_value.attr_value.len = sizeof(device->track_duration_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_PLAYING_ORDER_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->playing_order_notify; - p_data->rsp_value.attr_value.len = sizeof(device->playing_order_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - LOG(INFO) << __func__ << " calling device state" << device->state; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_MEDIA_STATE_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.media_state; - p_data->oper.WriteDescOp.len = sizeof (mediaPlayerInfo.media_state); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.media_state_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_PLAYER_NAME_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.player_name; - p_data->oper.WriteDescOp.len = mediaPlayerInfo.player_name_len; - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.media_player_name_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.media_ctrl_point; - p_data->oper.WriteDescOp.len = sizeof (mediaPlayerInfo.media_ctrl_point); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.media_control_point_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_SUPPORTED_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.media_supported_feature; - p_data->oper.WriteDescOp.len = sizeof (mediaPlayerInfo.media_supported_feature); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.media_control_point_opcode_supported_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_CHANGED_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.track_changed; - p_data->oper.WriteDescOp.len = sizeof (mediaPlayerInfo.track_changed); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.track_changed_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_TITLE_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.title; - p_data->oper.WriteDescOp.len = mediaPlayerInfo.track_title_len; - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.track_title_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_TRACK_POSITION_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.position; - p_data->oper.WriteDescOp.len = sizeof(mediaPlayerInfo.position); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.track_position_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_TRACK_DURATION_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.duration; - p_data->oper.WriteDescOp.len = sizeof(mediaPlayerInfo.duration); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.track_duration_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_PLAYING_ORDER_DESCRIPTOR_WRITE : { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.playing_order_value; - p_data->oper.WriteDescOp.len = sizeof(mediaPlayerInfo.playing_order_value); - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_CONGESTION_UPDATE: { - McpCongestionUpdate(p_data); - break; - } - - case MCP_CONNECTION_UPDATE: - case MCP_ACTIVE_DEVICE_UPDATE: - case MCP_PHY_UPDATE: - case MCP_CONNECTION: - case MCP_DISCONNECTION: - case MCP_CONNECTION_CLOSE_EVENT: - case MCP_BOND_STATE_CHANGE_EVENT: - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - - default: - break; - } - - return BT_STATUS_SUCCESS; -} - -bool MediaStateSeekingHandler(uint32_t event, void* param, uint8_t state) { - LOG(INFO) << __func__ << " handle event " << get_mcp_event_name(event) - << " in state " << get_mcp_media_state_name(state); - mcp_resp_t *p_data = (mcp_resp_t *)param; - RemoteDevice *device = p_data->remoteDevice; - switch(event) { - case MCP_NOTIFY_ALL: { - LOG(INFO) << __func__ << " Notify all handle "<< p_data->handle; - std::vectornotifyDevices = - instance->remoteDevices.FindNotifyDevices(p_data->handle); - if (notifyDevices.size() <= 0) { - LOG(INFO) << __func__ << " No device register for notification"; - break; - } - std::vector::iterator it; - for (it = notifyDevices.begin(); it != notifyDevices.end(); it++){ - p_data->remoteDevice = instance->remoteDevices.FindByConnId(it->conn_id); - it->DeviceStateHandlerPointer[it->state](p_data->event, p_data, it->state); - LOG(INFO) << __func__ << " Notify all handle device id " << it->conn_id; - } - - break; - } - - case MCP_PLAYING_ORDER_WRITE: { - uint8_t data = (uint8_t)(*p_data->oper.WriteOp.data); - if (mediaPlayerInfo.playing_order_supported & data) { - instance->PlayingOrderChangeReq(data & mediaPlayerInfo.playing_order_value); - } else { - LOG(INFO) << __func__ << " ignore playing_order_handle write feature is not supported"; - break; - } - p_data->rsp_value.attr_value.len = 0; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_WRITE: { - uint8_t data = (uint8_t)(*p_data->oper.WriteOp.data); - uint8_t opcode_support = is_opcode_supported(data); - if (!opcode_support) { - uint8_t status = MCP_OPCODE_NOT_SUPPORTED; - std::vector value; - value.push_back(data); - value.push_back(status); - LOG(INFO) << __func__ << "hndl " << p_data->oper.WriteOp.char_handle; - LOG(INFO) << __func__ << "opcode not supported " << data; - GattsOpsQueue::SendNotification(device->conn_id, p_data->oper.WriteOp.char_handle, value, false); - } - - if (((data == MCP_MEDIA_CONTROL_OPCODE_PAUSE) || - (data == MCP_MEDIA_CONTROL_OPCODE_PLAY)) && - (instance->remoteDevices.FindActiveDevice(p_data->remoteDevice)) == false) { - LOG(INFO) << __func__ << " media control point write received from inactive device"; - break; - } - if ((data != MCP_MEDIA_CONTROL_OPCODE_FAST_FORWARD) && (data != MCP_MEDIA_CONTROL_OPCODE_FAST_REWIND) - && (data != MCP_MEDIA_CONTROL_OPCODE_MOVE_RELATIVE)) { - instance->MediaControlPointChangeReq(data, device->peer_bda); - LOG(INFO) << __func__ << "media_control_point_handle write "; - } - p_data->rsp_value.attr_value.len = 0; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_POSITION_WRITE: { - uint32_t track_duration = mediaPlayerInfo.duration; - uint32_t track_position = mediaPlayerInfo.position; - uint32_t data; - uint8_t *w_data = p_data->oper.WriteOp.data; - uint32_t position = track_duration; - STREAM_TO_UINT32(data, w_data); - if ((track_position == (uint32_t)data) || (data < 0) || - (track_duration == 0xFFFF) || (track_duration > 0 && track_duration < data)) { - LOG(INFO) << __func__ << " ignore track_position_handle write"; - } else { - position = data; - instance->TrackPositionChangeReq(data); - LOG(INFO) << __func__ << " track_position_handle write"; - } - std::vector value; - value.push_back(position & 0xff); - value.push_back((position >> 8) & 0xff); - value.push_back((position >> 16) & 0xff); - value.push_back((position >> 24) & 0xff); - GattsOpsQueue::SendNotification(device->conn_id, p_data->oper.WriteOp.char_handle, value, false); - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_STATE_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.media_state); - *(uint8_t *)p_data->rsp_value.attr_value.value = *(uint8_t *)&mediaPlayerInfo.media_state; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_PLAYER_NAME_READ: { - uint16_t len = mediaPlayerInfo.player_name_len; - if (device->mtu != -1 && len >= device->mtu - 3) //to check player len should not greater than mtu - len = device->mtu - 3; - p_data->rsp_value.attr_value.len = len; - memcpy(p_data->rsp_value.attr_value.value, mediaPlayerInfo.player_name, - p_data->rsp_value.attr_value.len); - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_OPCODE_SUPPORTED_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.media_supported_feature); - *(uint32_t*)p_data->rsp_value.attr_value.value = - *(uint32_t *)&mediaPlayerInfo.media_supported_feature; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_TITLE_READ: { - uint16_t len = mediaPlayerInfo.track_title_len; - if (device->mtu != -1 && len >= device->mtu - 3) //to check title len should not greater than mtu - len = device->mtu - 3; - p_data->rsp_value.attr_value.len = len; - memcpy(p_data->rsp_value.attr_value.value, mediaPlayerInfo.title, - p_data->rsp_value.attr_value.len); - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_POSITION_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.position); - *(int *)p_data->rsp_value.attr_value.value = *(int *)&mediaPlayerInfo.position; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_DURATION_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.duration); - *(int *)p_data->rsp_value.attr_value.value = *(int *)&mediaPlayerInfo.duration; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_PLAYING_ORDER_SUPPORTED_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.playing_order_supported); - *(uint16_t *)p_data->rsp_value.attr_value.value = - *(uint16_t *)&mediaPlayerInfo.playing_order_supported; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_PLAYING_ORDER_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.playing_order_value); - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&mediaPlayerInfo.playing_order_value; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_CCID_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.ccid); - *(uint32_t *)p_data->rsp_value.attr_value.value = *(uint8_t *)&mediaPlayerInfo.ccid; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_SEEKING_SPEED_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.seeking_speed); - *(uint8_t *)p_data->rsp_value.attr_value.value = (uint8_t)mediaPlayerInfo.seeking_speed; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_STATE_READ_DESCRIPTOR:{ - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->media_state_notify; - p_data->rsp_value.attr_value.len = sizeof(device->media_state_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_READ_DESCRIPTOR: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->media_control_point_notify; - p_data->rsp_value.attr_value.len = sizeof(device->media_control_point_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_OPCODE_SUPPORTED_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = - *(uint16_t *)&device->media_control_point_opcode_supported_notify; - p_data->rsp_value.attr_value.len = sizeof(device->media_control_point_opcode_supported_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_PLAYER_NAME_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->media_player_name_notify; - p_data->rsp_value.attr_value.len = sizeof(device->media_player_name_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_CHANGED_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->track_changed_notify; - p_data->rsp_value.attr_value.len = sizeof(device->track_changed_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_TITLE_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->track_title_notify; - p_data->rsp_value.attr_value.len = sizeof(device->track_title_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_POSITION_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->track_position_notify; - p_data->rsp_value.attr_value.len = sizeof(device->track_position_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_DURATION_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->track_duration_notify;; - p_data->rsp_value.attr_value.len = sizeof(device->track_duration_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_PLAYING_ORDER_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->playing_order_notify; - p_data->rsp_value.attr_value.len = sizeof(device->playing_order_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_MEDIA_STATE_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.media_state; - p_data->oper.WriteDescOp.len = sizeof (mediaPlayerInfo.media_state); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.media_state_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_PLAYER_NAME_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.player_name; - p_data->oper.WriteDescOp.len = mediaPlayerInfo.player_name_len; - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.media_player_name_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.media_ctrl_point; - p_data->oper.WriteDescOp.len = sizeof (mediaPlayerInfo.media_ctrl_point); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.media_control_point_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_SUPPORTED_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.media_supported_feature; - p_data->oper.WriteDescOp.len = sizeof (mediaPlayerInfo.media_supported_feature); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.media_control_point_opcode_supported_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_CHANGED_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.track_changed; - p_data->oper.WriteDescOp.len = sizeof (mediaPlayerInfo.track_changed); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.track_changed_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_TITLE_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.title; - p_data->oper.WriteDescOp.len = mediaPlayerInfo.track_title_len; - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.track_title_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_TRACK_POSITION_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.position; - p_data->oper.WriteDescOp.len = sizeof(mediaPlayerInfo.position); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.track_position_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_TRACK_DURATION_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.duration; - p_data->oper.WriteDescOp.len = sizeof(mediaPlayerInfo.duration); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.track_duration_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_PLAYING_ORDER_DESCRIPTOR_WRITE : { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.playing_order_value; - p_data->oper.WriteDescOp.len = sizeof(mediaPlayerInfo.playing_order_value); - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_CONGESTION_UPDATE: { - LOG(INFO) << __func__ << ": device MCP_CONGESTION_UPDATE update: " << event; - McpCongestionUpdate(p_data); - break; - } - - case MCP_CONNECTION_UPDATE: - case MCP_ACTIVE_DEVICE_UPDATE: - case MCP_PHY_UPDATE: - case MCP_CONNECTION: - case MCP_DISCONNECTION: - case MCP_CONNECTION_CLOSE_EVENT: - case MCP_BOND_STATE_CHANGE_EVENT: - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - - default: - break; - } - return BT_STATUS_SUCCESS; -} - - -bool MediaStatePauseHandler(uint32_t event, void* param, uint8_t state) { - LOG(INFO) << __func__ << " handle event " << get_mcp_event_name(event) - << " in state " << get_mcp_media_state_name(state); - - mcp_resp_t *p_data = (mcp_resp_t *)param; - RemoteDevice *device = p_data->remoteDevice; - switch(event) { - case MCP_NOTIFY_ALL: { - LOG(INFO) << __func__ << " Notify all handle "<< p_data->handle; - std::vectornotifyDevices = instance->remoteDevices.FindNotifyDevices(p_data->handle); - std::vector::iterator it; - if (notifyDevices.size() <= 0) { - LOG(INFO) << __func__ << " No device register for notification"; - } - for (it = notifyDevices.begin(); it != notifyDevices.end(); it++){ - p_data->remoteDevice = instance->remoteDevices.FindByConnId(it->conn_id); - it->DeviceStateHandlerPointer[it->state](p_data->event, p_data, it->state); - LOG(INFO) << __func__ << " Notify all handle device id " << it->conn_id; - - } - break; - } - - case MCP_PLAYING_ORDER_WRITE: { - uint8_t data = (uint8_t)(*p_data->oper.WriteOp.data); - if (mediaPlayerInfo.playing_order_supported & data) { - instance->PlayingOrderChangeReq(data & mediaPlayerInfo.playing_order_value); - } else { - LOG(INFO) << __func__ << " ignore playing_order_handle write feature is not supported"; - break; - } - p_data->rsp_value.attr_value.len = 0; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_WRITE: { - uint8_t data = (uint8_t)(*p_data->oper.WriteOp.data); - uint8_t opcode_support = is_opcode_supported(data); - if (!opcode_support) { - uint8_t status = MCP_OPCODE_NOT_SUPPORTED; - std::vector value; - value.push_back(data); - value.push_back(status); - LOG(INFO) << __func__ << "hndl " << p_data->oper.WriteOp.char_handle; - LOG(INFO) << __func__ << "opcode not supported " << data; - GattsOpsQueue::SendNotification(device->conn_id, p_data->oper.WriteOp.char_handle, value, false); - } - - if ((data != MCP_MEDIA_CONTROL_OPCODE_PLAY) && - (instance->remoteDevices.FindActiveDevice(p_data->remoteDevice) == false) - && is_pts_running() == false) { - LOG(INFO) << __func__ << " media control point write received from inactive device"; - break; - } - if (data != MCP_MEDIA_CONTROL_OPCODE_PAUSE) { - // MCP_MEDIA_CONTROL_STOP need to check for stop - instance->MediaControlPointChangeReq(data, device->peer_bda); - LOG(INFO) << __func__ << "media_control_point_handle write "; - } else { - LOG(INFO) << __func__ << " ignore media_control_point_handle write feature is not supported / already paused"; - } - p_data->rsp_value.attr_value.len = 0; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_POSITION_WRITE: { - uint32_t track_duration = mediaPlayerInfo.duration; - uint32_t track_position = mediaPlayerInfo.position; - uint32_t data; - uint8_t *w_data = p_data->oper.WriteOp.data; - STREAM_TO_UINT32(data, w_data); - uint32_t position = track_duration; - if ((track_position == (uint32_t)data) || (data < 0) || - (track_duration == 0xFFFF) || (track_duration > 0 && track_duration < data)) { - LOG(INFO) << __func__ << " ignore track_position_handle write"; - } else { - position = data; - instance->TrackPositionChangeReq(data); - LOG(INFO) << __func__ << " track_position_handle write"; - } - std::vector value; - value.push_back(position & 0xff); - value.push_back((position >> 8) & 0xff); - value.push_back((position >> 16) & 0xff); - value.push_back((position >> 24) & 0xff); - GattsOpsQueue::SendNotification(device->conn_id, p_data->oper.WriteOp.char_handle, value, false); - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_STATE_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.media_state); - *(uint8_t *)p_data->rsp_value.attr_value.value = *(uint8_t *)&mediaPlayerInfo.media_state; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_PLAYER_NAME_READ: { - uint16_t len = mediaPlayerInfo.player_name_len; - LOG(INFO) << __func__ << " before player name len: " << len; - LOG(INFO) << __func__ << " before player name mtu: " << device->mtu; - if (device->mtu != -1 && len >= device->mtu - 3) //to check player len should not greater than mtu - len = device->mtu - 3; - p_data->rsp_value.attr_value.len = len; - LOG(INFO) << __func__ << " player name len: " << len; - memcpy(p_data->rsp_value.attr_value.value, mediaPlayerInfo.player_name, - p_data->rsp_value.attr_value.len); - p_data->event = MCP_READ_RSP; - LOG(INFO) << __func__ << " calling player name read"; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_OPCODE_SUPPORTED_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.media_supported_feature); - *(uint32_t*)p_data->rsp_value.attr_value.value = - *(uint32_t *)&mediaPlayerInfo.media_supported_feature; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_TITLE_READ: { - uint16_t len = mediaPlayerInfo.track_title_len; - if (device->mtu != -1 && len >= device->mtu - 3) //to check title len should not greater than mtu - len = device->mtu - 3; - p_data->rsp_value.attr_value.len = len; - memcpy(p_data->rsp_value.attr_value.value, mediaPlayerInfo.title, - p_data->rsp_value.attr_value.len); - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_POSITION_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.position); - *(int *)p_data->rsp_value.attr_value.value = *(int *)&mediaPlayerInfo.position; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_DURATION_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.duration); - *(int *)p_data->rsp_value.attr_value.value = *(int *)&mediaPlayerInfo.duration; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_PLAYING_ORDER_SUPPORTED_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.playing_order_supported); - *(uint16_t *)p_data->rsp_value.attr_value.value = - *(uint16_t*)&mediaPlayerInfo.playing_order_supported; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_PLAYING_ORDER_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.playing_order_value); - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&mediaPlayerInfo.playing_order_value; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_CCID_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.ccid); - *(uint32_t *)p_data->rsp_value.attr_value.value = *(uint8_t *)&mediaPlayerInfo.ccid; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_SEEKING_SPEED_READ: { - p_data->rsp_value.attr_value.len = sizeof(mediaPlayerInfo.seeking_speed); - *(uint8_t *)p_data->rsp_value.attr_value.value = (uint8_t)mediaPlayerInfo.seeking_speed; - p_data->event = MCP_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_STATE_READ_DESCRIPTOR:{ - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->media_state_notify; - p_data->rsp_value.attr_value.len = sizeof(device->media_state_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_READ_DESCRIPTOR: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->media_control_point_notify; - p_data->rsp_value.attr_value.len = sizeof(device->media_control_point_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_OPCODE_SUPPORTED_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = - *(uint16_t *)&device->media_control_point_opcode_supported_notify; - p_data->rsp_value.attr_value.len = sizeof(device->media_control_point_opcode_supported_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_PLAYER_NAME_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->media_player_name_notify; - p_data->rsp_value.attr_value.len = sizeof(device->media_player_name_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_CHANGED_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->track_changed_notify; - p_data->rsp_value.attr_value.len = sizeof(device->track_changed_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_TITLE_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->track_title_notify; - p_data->rsp_value.attr_value.len = sizeof(device->track_title_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_POSITION_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->track_position_notify; - p_data->rsp_value.attr_value.len = sizeof(device->track_position_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_DURATION_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->track_duration_notify;; - p_data->rsp_value.attr_value.len = sizeof(device->track_duration_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_PLAYING_ORDER_DESCRIPTOR_READ: { - *(uint16_t *)p_data->rsp_value.attr_value.value = *(uint16_t *)&device->playing_order_notify; - p_data->rsp_value.attr_value.len = sizeof(device->playing_order_notify); - p_data->event = MCP_DESCRIPTOR_READ_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_MEDIA_STATE_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.media_state; - p_data->oper.WriteDescOp.len = sizeof (mediaPlayerInfo.media_state); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.media_state_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_PLAYER_NAME_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.player_name; - p_data->oper.WriteDescOp.len = mediaPlayerInfo.player_name_len; - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.media_player_name_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.media_ctrl_point; - p_data->oper.WriteDescOp.len = sizeof (mediaPlayerInfo.media_ctrl_point); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.media_control_point_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_MEDIA_CONTROL_POINT_SUPPORTED_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.media_supported_feature; - p_data->oper.WriteDescOp.len = sizeof (mediaPlayerInfo.media_supported_feature); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.media_control_point_opcode_supported_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_CHANGED_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.track_changed; - p_data->oper.WriteDescOp.len = sizeof (mediaPlayerInfo.track_changed); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.track_changed_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - case MCP_TRACK_TITLE_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.title; - p_data->oper.WriteDescOp.len = mediaPlayerInfo.track_title_len; - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.track_title_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_TRACK_POSITION_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.position; - p_data->oper.WriteDescOp.len = sizeof(mediaPlayerInfo.position); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.track_position_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_TRACK_DURATION_DESCRIPTOR_WRITE: { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.duration; - p_data->oper.WriteDescOp.len = sizeof(mediaPlayerInfo.duration); - p_data->oper.WriteDescOp.char_handle = mcsServerServiceInfo.track_duration_handle; - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_PLAYING_ORDER_DESCRIPTOR_WRITE : { - p_data->oper.WriteDescOp.data = (uint8_t *)&mediaPlayerInfo.playing_order_value; - p_data->oper.WriteDescOp.len = sizeof(mediaPlayerInfo.playing_order_value); - p_data->event = MCP_DESCRIPTOR_WRITE_RSP; - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - } - - case MCP_CONGESTION_UPDATE: { - McpCongestionUpdate(p_data); - break; - } - - case MCP_CONNECTION_UPDATE: - case MCP_ACTIVE_DEVICE_UPDATE: - case MCP_PHY_UPDATE: - case MCP_CONNECTION: - case MCP_DISCONNECTION: - case MCP_CONNECTION_CLOSE_EVENT: - case MCP_BOND_STATE_CHANGE_EVENT: - device = p_data->remoteDevice; - device->DeviceStateHandlerPointer[device->state](p_data->event, p_data, device->state); - break; - - default: - break; - } - return BT_STATUS_SUCCESS; -} - -bool DeviceStateConnectionHandler(uint32_t event, void* param, uint8_t state) { - LOG(INFO) << __func__ << " device connected handle " << get_mcp_event_name(event); - mcp_resp_t *p_data = (mcp_resp_t *) param; - switch (event) { - case MCP_NOTIFY_ALL: { - LOG(INFO) << __func__ << " device notify all "; - if (is_pts_running() || p_data->remoteDevice->active_profile == 0x10) {// need to check profile value - std::vector value; - tMCP_MEDIA_UPDATE *notfiyUpdate = &p_data->oper.MediaUpdateOp; - value.assign(notfiyUpdate->data, notfiyUpdate->data + notfiyUpdate->len); - GattsOpsQueue::SendNotification(p_data->remoteDevice->conn_id, - p_data->handle, value, false); - } - break; - } - - case MCP_READ_RSP: - BTA_GATTS_SendRsp(p_data->remoteDevice->conn_id, p_data->oper.ReadOp.trans_id, - BT_STATUS_SUCCESS, &p_data->rsp_value); - - break; - - case MCP_DESCRIPTOR_READ_RSP: - BTA_GATTS_SendRsp(p_data->remoteDevice->conn_id, p_data->oper.ReadDescOp.trans_id, - BT_STATUS_SUCCESS, &p_data->rsp_value); - - break; - - case MCP_DESCRIPTOR_WRITE_RSP: { - LOG(INFO) << __func__ << " device MCP_DESCRIPTOR_WRITE_RSP update rsp :" << p_data->oper.WriteDescOp.need_rsp; - tGATTS_RSP rsp_struct; - rsp_struct.attr_value.handle = p_data->rsp_value.attr_value.handle; - rsp_struct.attr_value.offset = p_data->rsp_value.attr_value.offset; - if (p_data->remoteDevice->congested == false && - p_data->oper.WriteDescOp.need_rsp) { - //send rsp to write - LOG(INFO) << __func__ << " gatt send rsp status" << p_data->oper.WriteDescOp.status; - BTA_GATTS_SendRsp(p_data->remoteDevice->conn_id, p_data->oper.WriteDescOp.trans_id, - p_data->oper.WriteDescOp.status, &rsp_struct); - } - break; - } - - case MCP_WRITE_RSP: { - LOG(INFO) << __func__ << " device MCP_WRITE_RSP update Tx ID: " << p_data->oper.WriteOp.trans_id; - bool need_rsp = p_data->oper.WriteOp.need_rsp; - if (need_rsp) { - BTA_GATTS_SendRsp(p_data->remoteDevice->conn_id, p_data->oper.WriteOp.trans_id, - BT_STATUS_SUCCESS, &p_data->rsp_value); - } - break; - } - - case MCP_CONNECTION_UPDATE: { - p_data->remoteDevice->latency = p_data->oper.ConnectionUpdateOp.latency; - p_data->remoteDevice->timeout = p_data->oper.ConnectionUpdateOp.timeout; - p_data->remoteDevice->interval = p_data->oper.ConnectionUpdateOp.interval; - p_data->remoteDevice->active_profile = 0x10; - break; - } - - case MCP_ACTIVE_DEVICE_UPDATE: { - p_data->remoteDevice->active_profile = p_data->oper.SetActiveDeviceOp.profile; - break; - } - case MCP_PHY_UPDATE: { - p_data->remoteDevice->rx_phy = p_data->oper.PhyOp.rx_phy; - p_data->remoteDevice->tx_phy = p_data->oper.PhyOp.tx_phy; - break; - } - - case MCP_MTU_UPDATE: { - p_data->remoteDevice->mtu = p_data->oper.MtuOp.mtu; - break; - } - - case MCP_CONGESTION_UPDATE: { - McpCongestionUpdate(p_data); - break; - } - - case MCP_DISCONNECTION: { - LOG(INFO) << __func__ << " device event MCP_DISCONNECTION remove "; - instance->remoteDevices.Remove(p_data->remoteDevice->peer_bda); - instance->OnConnectionStateChange(MCP_DISCONNECTED, p_data->remoteDevice->peer_bda); - break; - } - - case MCP_CONNECTION_CLOSE_EVENT: { - LOG(INFO) << __func__ << " device connection closing"; - // Close active connection - if (p_data->remoteDevice->conn_id != 0) - BTA_GATTS_Close(p_data->remoteDevice->conn_id); - else - BTA_GATTS_CancelOpen(mcsServerServiceInfo.server_if, p_data->remoteDevice->peer_bda, true); - - // Cancel pending background connections - BTA_GATTS_CancelOpen(mcsServerServiceInfo.server_if, p_data->remoteDevice->peer_bda, false); - break; - } - - case MCP_BOND_STATE_CHANGE_EVENT: - LOG(INFO) << __func__ << "Bond state change : "; - instance->remoteDevices.Remove(p_data->remoteDevice->peer_bda); - break; - - default: - LOG(INFO) << __func__ << " event not matched"; - break; - } - - return BT_STATUS_SUCCESS; -} - - -bool DeviceStateDisconnectedHandler(uint32_t event, void* param, uint8_t state) { - LOG(INFO) << __func__ << " device disconnected handle " << get_mcp_event_name(event); - mcp_resp_t *p_data = (mcp_resp_t *) param; - switch (event) { - case MCP_CONNECTION: { - p_data->remoteDevice->state = MCP_CONNECTED; - p_data->remoteDevice->media_state_notify = 0x00; - p_data->remoteDevice->media_player_name_notify = 0x00; - p_data->remoteDevice->media_control_point_notify = 0x00; - p_data->remoteDevice->track_changed_notify = 0x00; - p_data->remoteDevice->track_duration_notify = 0x00; - p_data->remoteDevice->track_title_notify = 0x00; - p_data->remoteDevice->track_position_notify = 0x00; - p_data->remoteDevice->playing_order_notify = 0x00; - p_data->remoteDevice->congested = false; - - p_data->remoteDevice->timeout = 0; - p_data->remoteDevice->latency = 0; - p_data->remoteDevice->interval = 0; - p_data->remoteDevice->rx_phy = 0; - p_data->remoteDevice->tx_phy = 0; - p_data->remoteDevice->mtu = -1; - instance->OnConnectionStateChange(MCP_CONNECTED, p_data->remoteDevice->peer_bda); - break; - } - - case MCP_CONGESTION_UPDATE: { - McpCongestionUpdate(p_data); - break; - } - - case MCP_MTU_UPDATE: - case MCP_PHY_UPDATE: - case MCP_READ_RSP: - case MCP_DESCRIPTOR_READ_RSP: - case MCP_WRITE_RSP: - case MCP_DESCRIPTOR_WRITE_RSP: - case MCP_NOTIFY_ALL: - case MCP_DISCONNECTION: - case MCP_CONNECTION_CLOSE_EVENT: - case MCP_BOND_STATE_CHANGE_EVENT: - default: - //ignore event - LOG(INFO) << __func__ << " Ignore event " << get_mcp_event_name(event); - break; - } - return BT_STATUS_SUCCESS; -} - -void McpCongestionUpdate(mcp_resp_t *p_data) { - p_data->remoteDevice->congested = p_data->oper.CongestionOp.congested; - LOG(INFO) << __func__ << ": conn_id: " << p_data->remoteDevice->conn_id - << ", congested: " << p_data->remoteDevice->congested; - - GattsOpsQueue::CongestionCallback(p_data->remoteDevice->conn_id, - p_data->remoteDevice->congested); -} diff --git a/le_audio/system/bt/bta/vcp/bta_vcp_controller.cc b/le_audio/system/bt/bta/vcp/bta_vcp_controller.cc deleted file mode 100644 index b4f48118c16865d29d88e8943e93fe99256f9f67..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/bta/vcp/bta_vcp_controller.cc +++ /dev/null @@ -1,1107 +0,0 @@ -/* - *Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/****************************************************************************** - * - * 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 "bt_target.h" -#include "bta_vcp_controller_api.h" -#include "bta_gatt_api.h" -#include "device/include/controller.h" -#include "gap_api.h" -#include "gatt_api.h" -#include "gattc_ops_queue.h" -#include "osi/include/properties.h" - -#include -#include -#include -#include -#include -#include - -using base::Closure; -using bluetooth::Uuid; -using bluetooth::bap::GattOpsQueue; -using bluetooth::vcp_controller::ConnectionState; - -// Assigned Numbers for VCS -Uuid VCS_UUID = Uuid::FromString("1844"); -Uuid VCS_VOLUME_STATE_UUID = Uuid::FromString("2B7D"); -Uuid VCS_VOLUME_CONTROL_POINT_UUID = Uuid::FromString("2B7E"); -Uuid VCS_VOLUME_FLAGS_UUID = Uuid::FromString("2B7F"); - -#define VCS_RETRY_SET_ABS_VOL 0x01 -#define VCS_RETRY_SET_MUTE_STATE 0x02 - -// VCS Application Error Code -#define VCS_INVALID_CHANGE_COUNTER 0x80 -#define VCS_OPCODE_NOT_SUPPORTED 0x81 - -void vcp_controller_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data); -void vcp_controller_encryption_callback(const RawAddress*, tGATT_TRANSPORT, void*, tBTM_STATUS); -const char* vcp_controller_gatt_callback_evt_str(uint8_t event); -const char* vcp_controller_handle_vcs_evt_str(uint8_t event); - -class VcpControllerImpl; -static VcpControllerImpl* instance; - -class RendererDevices { - private: - - public: - void Add(RendererDevice device) { - if (FindByAddress(device.address) != nullptr) return; - devices.push_back(device); - } - - void Remove(const RawAddress& address) { - for (auto it = devices.begin(); it != devices.end();) { - if (it->address != address) { - ++it; - continue; - } - - it = devices.erase(it); - return; - } - } - - RendererDevice* FindByAddress(const RawAddress& address) { - auto iter = std::find_if(devices.begin(), devices.end(), - [&address](const RendererDevice& device) { - return device.address == address; - }); - - return (iter == devices.end()) ? nullptr : &(*iter); - } - - RendererDevice* FindByConnId(uint16_t conn_id) { - auto iter = std::find_if(devices.begin(), devices.end(), - [&conn_id](const RendererDevice& device) { - return device.conn_id == conn_id; - }); - - return (iter == devices.end()) ? nullptr : &(*iter); - } - - size_t size() { return (devices.size()); } - - std::vector devices; -}; - -class VcpControllerImpl : public VcpController { - private: - uint8_t gatt_if; - bluetooth::vcp_controller::VcpControllerCallbacks* callbacks; - RendererDevices rendererDevices; - - public: - virtual ~VcpControllerImpl() = default; - - VcpControllerImpl(bluetooth::vcp_controller::VcpControllerCallbacks* callbacks) - : gatt_if(0), - callbacks(callbacks) { - LOG(INFO) << "VcpControllerImpl gattc app register"; - - BTA_GATTC_AppRegister( - vcp_controller_gattc_callback, - base::Bind( - [](uint8_t client_id, uint8_t status) { - if (status != GATT_SUCCESS) { - LOG(ERROR) << "Can't start Vcp profile - no gatt " - "clients left!"; - return; - } - instance->gatt_if = client_id; - }), true); - } - - void Connect(const RawAddress& address, bool isDirect) override { - LOG(INFO) << __func__ << " " << address << ", isDirect = " << logbool(isDirect); - RendererDevice* rendererDevice = rendererDevices.FindByAddress(address); - - if (rendererDevice) { - LOG(INFO) << "Device already in connected/connecting state" << address; - return; - } - - rendererDevices.Add(RendererDevice(address)); - rendererDevice = rendererDevices.FindByAddress(address); - if (!rendererDevice) { - LOG(INFO) << "Device address could not be foundL"; - return; - } - rendererDevice->state = BTA_VCP_CONNECTING; - callbacks->OnConnectionState(ConnectionState::CONNECTING, rendererDevice->address); - - if (!isDirect) { - rendererDevice->bg_conn = true; - } - - BTA_GATTC_Open(gatt_if, address, isDirect, GATT_TRANSPORT_LE, false); - } - - void Disconnect(const RawAddress& address) override { - RendererDevice* rendererDevice = rendererDevices.FindByAddress(address); - - if (!rendererDevice) { - LOG(INFO) << "Device not connected to profile" << address; - return; - } - - LOG(INFO) << __func__ << " " << address; - rendererDevice->state = BTA_VCP_DISCONNECTING; - callbacks->OnConnectionState(ConnectionState::DISCONNECTING, rendererDevice->address); - VcpGattClose(rendererDevice); - } - - void SetAbsVolume(const RawAddress& address, uint8_t volume) { - RendererDevice* rendererDevice = rendererDevices.FindByAddress(address); - - if (!rendererDevice) { - LOG(INFO) << "Device not connected to profile" << address; - return; - } - - if (rendererDevice->conn_id == 0) { - LOG(INFO) << __func__ << ": GATT is not connected, skip set absolute volume"; - return; - } - - if (rendererDevice->state != BTA_VCP_CONNECTED) { - LOG(INFO) - << __func__ << ": VCP is not connected, skip set absolute volume, state = " - << loghex(rendererDevice->state); - return; - } - // Send the data packet - LOG(INFO) << __func__ << ": Set abs volume. device=" << rendererDevice->address - << ", volume=" << loghex(volume); - - rendererDevice->vcs.pending_volume_setting = volume; - - uint8_t p_buf[256]; - SetAbsVolumeOp set_abs_vol_op; - set_abs_vol_op.op_id = VCS_CONTROL_POINT_OP_SET_ABS_VOL; - set_abs_vol_op.change_counter = rendererDevice->vcs.volume_state.change_counter; - set_abs_vol_op.volume_setting = volume; - - memcpy(p_buf, &set_abs_vol_op , sizeof(set_abs_vol_op)); - std::vector vect_val(p_buf, p_buf + sizeof(set_abs_vol_op)); - - GattOpsQueue::WriteCharacteristic(gatt_if, - rendererDevice->conn_id, rendererDevice->vcs.volume_control_point_handle, vect_val, - GATT_WRITE, VcpControllerImpl::OnSetAbsVolumeStatic, nullptr); - } - - void Mute(const RawAddress& address) { - RendererDevice* rendererDevice = rendererDevices.FindByAddress(address); - - if (!rendererDevice) { - LOG(INFO) << "Device not connected to profile" << address; - return; - } - - if (rendererDevice->conn_id == 0) { - LOG(INFO) << __func__ << ": GATT is not connected, skip mute"; - return; - } - - if (rendererDevice->state != BTA_VCP_CONNECTED) { - LOG(INFO) - << __func__ << ": VCP is not connected, skip mute, state = " - << loghex(rendererDevice->state); - return; - } - // Send the data packet - LOG(INFO) << __func__ << ": Mute device=" << rendererDevice->address; - - rendererDevice->vcs.pending_mute_setting = VCS_MUTE_STATE; - - uint8_t p_buf[256]; - MuteOp mute_op; - mute_op.op_id = VCS_CONTROL_POINT_OP_MUTE; - mute_op.change_counter = rendererDevice->vcs.volume_state.change_counter; - - memcpy(p_buf, &mute_op , sizeof(mute_op)); - std::vector vect_val(p_buf, p_buf + sizeof(mute_op)); - - GattOpsQueue::WriteCharacteristic(gatt_if, - rendererDevice->conn_id, rendererDevice->vcs.volume_control_point_handle, vect_val, - GATT_WRITE, VcpControllerImpl::OnMuteStatic, nullptr); - } - - void Unmute(const RawAddress& address) { - RendererDevice* rendererDevice = rendererDevices.FindByAddress(address); - - if (!rendererDevice) { - LOG(WARNING) << "Device not connected to profile" << address; - return; - } - - if (rendererDevice->conn_id == 0) { - LOG(INFO) << __func__ << ": GATT is not connected, skip unmute."; - return; - } - - if (rendererDevice->state != BTA_VCP_CONNECTED) { - LOG(INFO) - << __func__ << ": VCP is not connected, skip unmute, state = " - << loghex(rendererDevice->state); - return; - } - // Send the data packet - LOG(INFO) << __func__ << ": unmute device=" << rendererDevice->address; - - rendererDevice->vcs.pending_mute_setting = VCS_UNMUTE_STATE; - - uint8_t p_buf[256]; - UnmuteOp unmute_op; - unmute_op.op_id = VCS_CONTROL_POINT_OP_UNMUTE; - unmute_op.change_counter = rendererDevice->vcs.volume_state.change_counter; - - memcpy(p_buf, &unmute_op , sizeof(unmute_op)); - std::vector vect_val(p_buf, p_buf + sizeof(unmute_op)); - - GattOpsQueue::WriteCharacteristic(gatt_if, - rendererDevice->conn_id, rendererDevice->vcs.volume_control_point_handle, vect_val, - GATT_WRITE, VcpControllerImpl::OnUnmuteStatic, nullptr); - } - - void VcpGattClose(RendererDevice* rendererDevice) { - LOG(INFO) << __func__ << " " << rendererDevice->address; - - // Removes all registrations for connection. - BTA_GATTC_CancelOpen(gatt_if, rendererDevice->address, false); - rendererDevice->bg_conn = false; - - if (rendererDevice->conn_id) { - GattOpsQueue::Clean(rendererDevice->conn_id); - BTA_GATTC_Close(rendererDevice->conn_id); - } else { - // cancel pending direct connect - BTA_GATTC_CancelOpen(gatt_if, rendererDevice->address, true); - PostDisconnected(rendererDevice); - } - } - - void OnGattConnected(tGATT_STATUS status, uint16_t conn_id, - tGATT_IF client_if, RawAddress address, - tBTA_TRANSPORT transport, uint16_t mtu) { - RendererDevice* rendererDevice = rendererDevices.FindByAddress(address); - LOG(INFO) << __func__ << ": address=" << address << ", conn_id=" << conn_id; - - if (!rendererDevice) { - LOG(WARNING) << "Closing connection to non volume renderer device, address=" - << address; - BTA_GATTC_Close(conn_id); - return; - } - - if (status != GATT_SUCCESS) { - if (rendererDevice->bg_conn) { - // whitelist connection failed, that's ok. - LOG(INFO) << "bg conn failed, return immediately"; - return; - } - - LOG(INFO) << "Failed to connect to volume renderer device"; - rendererDevices.Remove(address); - callbacks->OnConnectionState(ConnectionState::DISCONNECTED, address); - return; - } - - if (rendererDevice->bg_conn) { - LOG(INFO) << __func__ << ": backgound connection from: address=" << address; - } - - rendererDevice->bg_conn = false; - rendererDevice->conn_id = conn_id; - - /* verify bond */ - uint8_t sec_flag = 0; - BTM_GetSecurityFlagsByTransport(address, &sec_flag, BT_TRANSPORT_LE); - - LOG(INFO) << __func__ << ": sec_flag =" << loghex(sec_flag); - if (sec_flag & BTM_SEC_FLAG_ENCRYPTED) { - /* if link has been encrypted */ - OnEncryptionComplete(address, true); - return; - } - - if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN) { - /* if bonded and link not encrypted */ - sec_flag = BTM_BLE_SEC_ENCRYPT; - BTM_SetEncryption(address, BTA_TRANSPORT_LE, vcp_controller_encryption_callback, nullptr, - sec_flag); - return; - } - - /* otherwise let it go through */ - OnEncryptionComplete(address, true); - } - - void OnGattDisconnected(tGATT_STATUS status, uint16_t conn_id, - tGATT_IF client_if, RawAddress remote_bda, - tBTA_GATT_REASON reason) { - RendererDevice* rendererDevice = rendererDevices.FindByConnId(conn_id); - - if (!rendererDevice) { - LOG(WARNING) << "Skipping unknown device disconnect, conn_id=" - << loghex(conn_id); - return; - } - LOG(INFO) << __func__ << ": conn_id=" << loghex(conn_id) - << ", reason=" << loghex(reason) << ", remote_bda=" << remote_bda; - - PostDisconnected(rendererDevice); - } - - void PostDisconnected(RendererDevice* rendererDevice) { - LOG(INFO) << __func__ << " " << rendererDevice->address; - rendererDevice->state = BTA_VCP_DISCONNECTED; - - if(rendererDevice->vcs.volume_state_handle != 0xFFFF) { - BTIF_TRACE_WARNING("%s: Deregister notifications", __func__); - BTA_GATTC_DeregisterForNotifications(gatt_if, - rendererDevice->address, - rendererDevice->vcs.volume_state_handle); - } - if(rendererDevice->vcs.volume_flags_handle != 0xFFFF) { - BTIF_TRACE_WARNING("%s: Deregister notifications", __func__); - BTA_GATTC_DeregisterForNotifications(gatt_if, - rendererDevice->address, - rendererDevice->vcs.volume_flags_handle); - } - - if (rendererDevice->conn_id) { - GattOpsQueue::Clean(rendererDevice->conn_id); - rendererDevice->conn_id = 0; - } - - callbacks->OnConnectionState(ConnectionState::DISCONNECTED, rendererDevice->address); - rendererDevices.Remove(rendererDevice->address); - } - - void OnEncryptionComplete(const RawAddress& address, bool success) { - RendererDevice* rendererDevice = rendererDevices.FindByAddress(address); - LOG(INFO) << __func__ << " " << address; - - if (!rendererDevice) { - LOG(WARNING) << "Skipping unknown device" << address; - return; - } - - if (!success) { - LOG(ERROR) << "encryption failed"; - BTA_GATTC_Close(rendererDevice->conn_id); - return; - } - - BTA_GATTC_ServiceSearchRequest(rendererDevice->conn_id, &VCS_UUID); - } - - void OnServiceSearchComplete(uint16_t conn_id, tGATT_STATUS status) { - RendererDevice* rendererDevice = rendererDevices.FindByConnId(conn_id); - LOG(INFO) << __func__; - - if (!rendererDevice) { - LOG(WARNING) << "Skipping unknown device, conn_id=" << loghex(conn_id); - return; - } - - if (status != GATT_SUCCESS) { - /* close connection and report service discovery complete with error */ - LOG(ERROR) << "Service discovery failed"; - VcpGattClose(rendererDevice); - return; - } - - const std::vector* services = BTA_GATTC_GetServices(conn_id); - - const gatt::Service* service = nullptr; - if (services) { - for (const gatt::Service& tmp : *services) { - if (tmp.uuid == Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER)) { - /* - LOG(INFO) << "Found UUID_SERVCLASS_GATT_SERVER, handle=" - << loghex(tmp.handle); - const gatt::Service* service_changed_service = &tmp; - FindServerChangedCCCHandle(conn_id, service_changed_service); - */ - } else if (tmp.uuid == VCS_UUID) { - LOG(INFO) << "Found Volume Control service, handle=" << loghex(tmp.handle); - service = &tmp; - } - } - } else { - LOG(ERROR) << "no services found for conn_id: " << conn_id; - return; - } - - if (!service) { - LOG(ERROR) << "No VCS found"; - VcpGattClose(rendererDevice); - return; - } - - for (const gatt::Characteristic& charac : service->characteristics) { - if (charac.uuid == VCS_VOLUME_STATE_UUID) { - rendererDevice->vcs.volume_state_handle = charac.value_handle; - - rendererDevice->vcs.volume_state_ccc_handle = - FindCccHandle(conn_id, charac.value_handle); - if (!rendererDevice->vcs.volume_state_ccc_handle) { - LOG(ERROR) << __func__ << ": cannot find volume state CCC descriptor"; - continue; - } - - LOG(INFO) << __func__ - << ": vcs volume_state_handle=" << loghex(charac.value_handle) - << ", ccc=" << loghex(rendererDevice->vcs.volume_state_ccc_handle); - } else if (charac.uuid == VCS_VOLUME_FLAGS_UUID) { - rendererDevice->vcs.volume_flags_handle = charac.value_handle; - - rendererDevice->vcs.volume_flags_ccc_handle = - FindCccHandle(conn_id, charac.value_handle); - if (!rendererDevice->vcs.volume_flags_ccc_handle) { - LOG(ERROR) << __func__ << ": cannot find volume flags CCC descriptor"; - continue; - } - - LOG(INFO) << __func__ - << ": vcs volume_flags_handle=" << loghex(charac.value_handle) - << ", ccc=" << loghex(rendererDevice->vcs.volume_flags_ccc_handle); - } else if (charac.uuid == VCS_VOLUME_CONTROL_POINT_UUID) { - // store volume control point! - rendererDevice->vcs.volume_control_point_handle = charac.value_handle; - } else { - LOG(WARNING) << "Unknown characteristic found:" << charac.uuid; - } - } - - LOG(WARNING) << "reading vcs volume_state_handle"; - GattOpsQueue::ReadCharacteristic(gatt_if, - conn_id, rendererDevice->vcs.volume_state_handle, - VcpControllerImpl::OnVolumeStateReadStatic, nullptr); - - } - - void OnServiceChangeEvent(const RawAddress& address) { - RendererDevice* rendererDevice = rendererDevices.FindByAddress(address); - if (!rendererDevice) { - VLOG(2) << "Skipping unknown device" << address; - return; - } - LOG(INFO) << __func__ << ": address=" << address; - rendererDevice->service_changed_rcvd = true; - GattOpsQueue::Clean(rendererDevice->conn_id); - } - - void OnServiceDiscDoneEvent(const RawAddress& address) { - RendererDevice* rendererDevice = rendererDevices.FindByAddress(address); - if (!rendererDevice) { - VLOG(2) << "Skipping unknown device" << address; - return; - } - if (rendererDevice->service_changed_rcvd) { - BTA_GATTC_ServiceSearchRequest(rendererDevice->conn_id, &VCS_UUID); - } - } - - void OnVolumeStateRead(uint16_t client_id, uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, uint16_t len, uint8_t* value, void* data) { - RendererDevice* rendererDevice = rendererDevices.FindByConnId(conn_id); - - if (!rendererDevice) { - LOG(WARNING) << "Skipping unknown read event, conn_id=" << loghex(conn_id); - return; - } - - LOG(INFO) << __func__ << " " << rendererDevice->address << ", status: " << loghex(status) - << ", renderer device state: " << loghex(rendererDevice->state); - - if (status != GATT_SUCCESS) { - LOG(ERROR) << "Error reading Volume State for device" << rendererDevice->address; - } else { - uint8_t* p = value; - uint8_t volume_setting; - STREAM_TO_UINT8(volume_setting, p); - rendererDevice->vcs.volume_state.volume_setting = volume_setting; - - uint8_t mute; - STREAM_TO_UINT8(mute, p); - rendererDevice->vcs.volume_state.mute = mute; - - uint8_t change_counter; - STREAM_TO_UINT8(change_counter, p); - rendererDevice->vcs.volume_state.change_counter = change_counter; - } - - HandleVCSEvent(rendererDevice, VCS_VOLUME_STATE_READ_CMPL_EVT, status); - } - - void OnVolumeFlagsRead(uint16_t client_id, uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, uint16_t len, uint8_t* value, void* data) { - RendererDevice* rendererDevice = rendererDevices.FindByConnId(conn_id); - - if (!rendererDevice) { - LOG(WARNING) << "Skipping unknown read event, conn_id=" << loghex(conn_id); - return; - } - - LOG(INFO) << __func__ << " " << rendererDevice->address << ", status: " << loghex(status); - - if (status != GATT_SUCCESS) { - LOG(ERROR) << "Error reading Volume Flags for device" << rendererDevice->address; - } else { - uint8_t* p = value; - uint8_t volume_flags; - STREAM_TO_UINT8(volume_flags, p); - rendererDevice->vcs.volume_flags = volume_flags; - } - - HandleVCSEvent(rendererDevice, VCS_VOLUME_FLAGS_READ_CMPL_EVT, status); - } - - void OnVolumeStateCCCWrite(uint16_t client_id, uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, void* data) { - RendererDevice* rendererDevice = rendererDevices.FindByConnId(conn_id); - - if (!rendererDevice) { - LOG(WARNING) << "Skipping unknown read event, conn_id=" << loghex(conn_id); - return; - } - - LOG(INFO) << __func__ << " " << rendererDevice->address << ", status: " << loghex(status); - - HandleVCSEvent(rendererDevice, VCS_VOLUME_STATE_CCC_WRITE_CMPL_EVT, status); - } - - void OnVolumeFlagsCCCWrite(uint16_t client_id, uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, void* data) { - RendererDevice* rendererDevice = rendererDevices.FindByConnId(conn_id); - - if (!rendererDevice) { - LOG(WARNING) << "Skipping unknown read event, conn_id=" << loghex(conn_id); - return; - } - - LOG(INFO) << __func__ << " " << rendererDevice->address << ", status: " << loghex(status); - - HandleVCSEvent(rendererDevice, VCS_VOLUME_FLAGS_CCC_WRITE_CMPL_EVT, status); - } - - void OnSetAbsVolume(uint16_t client_id, uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, void* data) { - RendererDevice* rendererDevice = rendererDevices.FindByConnId(conn_id); - - if (!rendererDevice) { - LOG(WARNING) << "Skipping unknown read event, conn_id=" << loghex(conn_id); - return; - } - - LOG(INFO) << __func__ << " " << rendererDevice->address << ", status: " << loghex(status); - - if (status != GATT_SUCCESS) { - // Check for VCS Invalid Change Counter error, it may - // conflict with GATT_NO_RESOURCES error. - if (status == VCS_INVALID_CHANGE_COUNTER || - status == VCS_OPCODE_NOT_SUPPORTED) { - LOG(ERROR) << __func__ << ": Error code: " << status - << " device: " << rendererDevice->address - << " Read Volume State to update change counter"; - - rendererDevice->vcs.retry_cmd |= VCS_RETRY_SET_ABS_VOL; - GattOpsQueue::ReadCharacteristic(gatt_if, - conn_id, rendererDevice->vcs.volume_state_handle, - VcpControllerImpl::OnVolumeStateReadStatic, nullptr); - } else { - LOG(ERROR) << __func__ << ": Other errors, not retry"; - } - } else { - rendererDevice->vcs.retry_cmd &= ~VCS_RETRY_SET_ABS_VOL; - LOG(INFO) << "Set abs volume success " << rendererDevice->address; - } - } - - void OnMute(uint16_t client_id, uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, void* data) { - RendererDevice* rendererDevice = rendererDevices.FindByConnId(conn_id); - - if (!rendererDevice) { - LOG(WARNING) << "Skipping unknown read event, conn_id=" << loghex(conn_id); - return; - } - - LOG(INFO) << __func__ << " " << rendererDevice->address << ", status: " << loghex(status); - - if (status != GATT_SUCCESS) { - LOG(ERROR) << "Volume State Write failed" << rendererDevice->address - << "Read Volume State"; - - rendererDevice->vcs.retry_cmd |= VCS_RETRY_SET_MUTE_STATE; - GattOpsQueue::ReadCharacteristic(gatt_if, - conn_id, rendererDevice->vcs.volume_state_handle, - VcpControllerImpl::OnVolumeStateReadStatic, nullptr); - } else { - LOG(INFO) << "Mute success" << rendererDevice->address; - } - - } - - void OnUnmute(uint16_t client_id, uint16_t conn_id, tGATT_STATUS status, - uint16_t handle, void* data) { - RendererDevice* rendererDevice = rendererDevices.FindByConnId(conn_id); - - if (!rendererDevice) { - LOG(WARNING) << "Skipping unknown read event, conn_id=" << loghex(conn_id); - return; - } - - LOG(INFO) << __func__ << " " << rendererDevice->address << ", status: " << loghex(status); - - if (status != GATT_SUCCESS) { - LOG(ERROR) << "Volume State Write failed" << rendererDevice->address - << "Read Volume State"; - - rendererDevice->vcs.retry_cmd |= VCS_RETRY_SET_MUTE_STATE; - GattOpsQueue::ReadCharacteristic(gatt_if, - conn_id, rendererDevice->vcs.volume_state_handle, - VcpControllerImpl::OnVolumeStateReadStatic, nullptr); - } else { - LOG(INFO) << "Unmute success" << rendererDevice->address; - } - } - - void RetryVolumeControlOp(RendererDevice* rendererDevice) { - LOG(INFO) << __func__ << " " << rendererDevice->address; - - if (rendererDevice->vcs.retry_cmd & VCS_RETRY_SET_ABS_VOL) { - rendererDevice->vcs.retry_cmd &= ~VCS_RETRY_SET_ABS_VOL; - SetAbsVolume(rendererDevice->address, rendererDevice->vcs.pending_volume_setting); - } - - if (rendererDevice->vcs.retry_cmd & VCS_RETRY_SET_MUTE_STATE) { - rendererDevice->vcs.retry_cmd &= ~VCS_RETRY_SET_MUTE_STATE; - if (rendererDevice->vcs.pending_mute_setting == VCS_MUTE_STATE) { - Mute(rendererDevice->address); - } else { - Unmute(rendererDevice->address); - } - } - } - - static void OnVolumeStateReadStatic(uint16_t client_id, uint16_t conn_id, - tGATT_STATUS status, - uint16_t handle, uint16_t len, - uint8_t* value, void* data) { - if (instance) - instance->OnVolumeStateRead(client_id, conn_id, status, handle, len, value, - data); - } - - static void OnVolumeFlagsReadStatic(uint16_t client_id, uint16_t conn_id, - tGATT_STATUS status, - uint16_t handle, uint16_t len, - uint8_t* value, void* data) { - if (instance) - instance->OnVolumeFlagsRead(client_id, conn_id, status, handle, len, value, - data); - } - - static void OnVolumeStateCCCWriteStatic(uint16_t client_id, uint16_t conn_id, - tGATT_STATUS status, uint16_t handle, void* data) { - if (instance) - instance->OnVolumeStateCCCWrite(client_id, conn_id, status, handle, data); - } - - static void OnVolumeFlagsCCCWriteStatic(uint16_t client_id, uint16_t conn_id, - tGATT_STATUS status, uint16_t handle, void* data) { - if (instance) - instance->OnVolumeFlagsCCCWrite(client_id, conn_id, status, handle, data); - } - - static void OnSetAbsVolumeStatic(uint16_t client_id, uint16_t conn_id, - tGATT_STATUS status, uint16_t handle, void* data) { - if (instance) - instance->OnSetAbsVolume(client_id, conn_id, status, handle, data); - } - - static void OnMuteStatic(uint16_t client_id, uint16_t conn_id, - tGATT_STATUS status, uint16_t handle, void* data) { - if (instance) - instance->OnMute(client_id, conn_id, status, handle, data); - } - - static void OnUnmuteStatic(uint16_t client_id, uint16_t conn_id, - tGATT_STATUS status, uint16_t handle, void* data) { - if (instance) - instance->OnUnmute(client_id, conn_id, status, handle, data); - } - - - void OnNotificationEvent(uint16_t conn_id, uint16_t handle, uint16_t len, - uint8_t* value) { - RendererDevice* device = rendererDevices.FindByConnId(conn_id); - - if (!device) { - LOG(INFO) << __func__ - << ": Skipping unknown device, conn_id=" << loghex(conn_id); - return; - } - - if (handle == device->vcs.volume_state_handle) { - if ( len != sizeof(device->vcs.volume_state)) { - LOG(ERROR) << __func__ << ": Data Length mismatch, len=" << len - << ", expecting " << sizeof(device->vcs.volume_state); - return; - } - - LOG(INFO) << __func__ << " " << device->address << " volume state notification"; - memcpy(&device->vcs.volume_state, value, len); - callbacks->OnVolumeStateChange(device->vcs.volume_state.volume_setting, - device->vcs.volume_state.mute, device->address); - } else if (handle == device->vcs.volume_flags_handle) { - if ( len != sizeof(device->vcs.volume_flags)) { - LOG(ERROR) << __func__ << ": Data Length mismatch, len=" << len - << ", expecting " << sizeof(device->vcs.volume_flags); - return; - } - - LOG(INFO) << __func__ << " " << device->address << " volume flags notification"; - memcpy(&device->vcs.volume_flags, value, len); - callbacks->OnVolumeFlagsChange(device->vcs.volume_flags, device->address); - } else { - LOG(INFO) << __func__ << ": Mismatched handle, " - << loghex(device->vcs.volume_state_handle) - << " or " << loghex(device->vcs.volume_flags_handle) - << "!=" << loghex(handle); - return; - } - } - - void OnCongestionEvent(uint16_t conn_id, bool congested) { - RendererDevice* device = rendererDevices.FindByConnId(conn_id); - if (!device) { - LOG(INFO) << __func__ - << ": Skipping unknown device, conn_id=" << loghex(conn_id); - return; - } - - LOG(WARNING) << __func__ << ": conn_id:" << loghex(conn_id) - << ", congested: " << congested; - GattOpsQueue::CongestionCallback(conn_id, congested); - } - - void HandleVCSEvent(RendererDevice* rendererDevice, uint32_t event, tGATT_STATUS status) { - LOG(INFO) << __func__ << " event = " << vcp_controller_handle_vcs_evt_str(event); - - if (status != GATT_SUCCESS) { - if (rendererDevice->state == BTA_VCP_CONNECTING) { - LOG(ERROR) << __func__ << ": Error status while VCP connecting, Close GATT for device: " - << rendererDevice->address; - VcpGattClose(rendererDevice); - return; - } else if (rendererDevice->state == BTA_VCP_CONNECTED) { - LOG(ERROR) << __func__ << ": Error status while VCP is connected for device: " - << rendererDevice->address; - if (rendererDevice->vcs.retry_cmd != 0) { - rendererDevice->vcs.retry_cmd = 0; - } - return; - } else { - LOG(ERROR) << __func__ << ": Error status in disconnected or disconnecting " - << "Igore handle VCS Event for device: " << rendererDevice->address; - return; - } - } - - switch (event) { - case VCS_VOLUME_STATE_READ_CMPL_EVT: { - if (rendererDevice->state == BTA_VCP_CONNECTING) { - LOG(WARNING) << "Setup VCP connection, reading vcs volume_flags_handle"; - GattOpsQueue::ReadCharacteristic(gatt_if, - rendererDevice->conn_id, rendererDevice->vcs.volume_flags_handle, - VcpControllerImpl::OnVolumeFlagsReadStatic, nullptr); - break; - } else if (rendererDevice->state == BTA_VCP_CONNECTED) { - if (rendererDevice->vcs.retry_cmd != 0) { - RetryVolumeControlOp(rendererDevice); - } - } - break; - } - - case VCS_VOLUME_FLAGS_READ_CMPL_EVT: { - if (rendererDevice->state == BTA_VCP_CONNECTING) { - /* Register and enable the Volume State Notification */ - tGATT_STATUS register_status; - register_status = BTA_GATTC_RegisterForNotifications( - gatt_if, rendererDevice->address, rendererDevice->vcs.volume_state_handle); - if (register_status != GATT_SUCCESS) { - LOG(ERROR) << __func__ - << ": BTA_GATTC_RegisterForNotifications failed, status=" - << loghex(register_status); - VcpGattClose(rendererDevice); - return; - } - - std::vector value(2); - uint8_t* ptr = value.data(); - UINT16_TO_STREAM(ptr, GATT_CHAR_CLIENT_CONFIG_NOTIFICATION); - GattOpsQueue::WriteDescriptor(gatt_if, - rendererDevice->conn_id, rendererDevice->vcs.volume_state_ccc_handle, - std::move(value), GATT_WRITE, VcpControllerImpl::OnVolumeStateCCCWriteStatic, - nullptr); - } - break; - } - - case VCS_VOLUME_STATE_CCC_WRITE_CMPL_EVT: { - if (rendererDevice->state == BTA_VCP_CONNECTING) { - /* Register and enable the Volume State Notification */ - tGATT_STATUS register_status; - register_status = BTA_GATTC_RegisterForNotifications( - gatt_if, rendererDevice->address, rendererDevice->vcs.volume_flags_handle); - if (register_status != GATT_SUCCESS) { - LOG(ERROR) << __func__ - << ": BTA_GATTC_RegisterForNotifications failed, status=" - << loghex(register_status); - VcpGattClose(rendererDevice); - return; - } - - std::vector value(2); - uint8_t* ptr = value.data(); - UINT16_TO_STREAM(ptr, GATT_CHAR_CLIENT_CONFIG_NOTIFICATION); - GattOpsQueue::WriteDescriptor(gatt_if, - rendererDevice->conn_id, rendererDevice->vcs.volume_flags_ccc_handle, - std::move(value), GATT_WRITE, VcpControllerImpl::OnVolumeFlagsCCCWriteStatic, - nullptr); - } - break; - } - - case VCS_VOLUME_FLAGS_CCC_WRITE_CMPL_EVT: { - if (rendererDevice->state == BTA_VCP_CONNECTING) { - LOG(INFO) << __func__ << ": VCP Connection Setup complete"; - rendererDevice->state = BTA_VCP_CONNECTED; - callbacks->OnConnectionState(ConnectionState::CONNECTED, rendererDevice->address); - callbacks->OnVolumeFlagsChange(rendererDevice->vcs.volume_flags, - rendererDevice->address); - callbacks->OnVolumeStateChange(rendererDevice->vcs.volume_state.volume_setting, - rendererDevice->vcs.volume_state.mute, rendererDevice->address); - break; - } - break; - } - - default: - LOG(INFO) << __func__ << ": unexpected VCS event"; - break; - } - } - - // Find the handle for the client characteristics configuration of a given - // characteristics - uint16_t FindCccHandle(uint16_t conn_id, uint16_t char_handle) { - const gatt::Characteristic* p_char = - BTA_GATTC_GetCharacteristic(conn_id, char_handle); - LOG(INFO) << __func__ << " " << ", conn_id: " << conn_id << ", char_handle: " << char_handle; - - if (!p_char) { - LOG(WARNING) << __func__ << ": No such characteristic: " << char_handle; - return 0; - } - - for (const gatt::Descriptor& desc : p_char->descriptors) { - if (desc.uuid == Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG)) - return desc.handle; - } - return 0; - } - - void CleanUp() { - LOG(INFO) << __func__; - BTA_GATTC_AppDeregister(gatt_if); - for (RendererDevice& device : rendererDevices.devices) { - PostDisconnected(&device); - } - - rendererDevices.devices.clear(); - } -}; - -void vcp_controller_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) { - LOG(INFO) << __func__ << " event = " << vcp_controller_gatt_callback_evt_str(event); - - if (p_data == nullptr) return; - - switch (event) { - case BTA_GATTC_DEREG_EVT: - break; - - case BTA_GATTC_OPEN_EVT: { - if (!instance) return; - tBTA_GATTC_OPEN& o = p_data->open; - instance->OnGattConnected(o.status, o.conn_id, o.client_if, o.remote_bda, - o.transport, o.mtu); - break; - } - - case BTA_GATTC_CLOSE_EVT: { - if (!instance) return; - tBTA_GATTC_CLOSE& c = p_data->close; - instance->OnGattDisconnected(c.status, c.conn_id, c.client_if, - c.remote_bda, c.reason); - } break; - - case BTA_GATTC_SEARCH_CMPL_EVT: - if (!instance) return; - instance->OnServiceSearchComplete(p_data->search_cmpl.conn_id, - p_data->search_cmpl.status); - break; - - case BTA_GATTC_NOTIF_EVT: - if (!instance) return; - if (!p_data->notify.is_notify || p_data->notify.len > GATT_MAX_ATTR_LEN) { - LOG(ERROR) << __func__ << ": rejected BTA_GATTC_NOTIF_EVT. is_notify=" - << p_data->notify.is_notify - << ", len=" << p_data->notify.len; - break; - } - instance->OnNotificationEvent(p_data->notify.conn_id, - p_data->notify.handle, p_data->notify.len, - p_data->notify.value); - break; - - case BTA_GATTC_ENC_CMPL_CB_EVT: - if (!instance) return; - instance->OnEncryptionComplete(p_data->enc_cmpl.remote_bda, true); - break; - - case BTA_GATTC_SRVC_CHG_EVT: - if (!instance) return; - instance->OnServiceChangeEvent(p_data->remote_bda); - break; - - case BTA_GATTC_SRVC_DISC_DONE_EVT: - if (!instance) return; - instance->OnServiceDiscDoneEvent(p_data->remote_bda); - break; - - case BTA_GATTC_CONGEST_EVT: - if (!instance) return; - instance->OnCongestionEvent(p_data->congest.conn_id, - p_data->congest.congested); - break; - - case BTA_GATTC_SEARCH_RES_EVT: - case BTA_GATTC_CANCEL_OPEN_EVT: - case BTA_GATTC_CONN_UPDATE_EVT: - - default: - break; - } -} - -void vcp_controller_encryption_callback(const RawAddress* address, - UNUSED_ATTR tGATT_TRANSPORT transport, - UNUSED_ATTR void* data, tBTM_STATUS status) { - if (instance) { - instance->OnEncryptionComplete(*address, - status == BTM_SUCCESS ? true : false); - } -} - -void VcpController::Initialize( - bluetooth::vcp_controller::VcpControllerCallbacks* callbacks) { - LOG(INFO) << __func__ ; - - if (instance) { - LOG(ERROR) << "Already initialized!"; - } - - instance = new VcpControllerImpl(callbacks); -} - -bool VcpController::IsVcpControllerRunning() { return instance; } - -VcpController* VcpController::Get() { - CHECK(instance); - return instance; -}; - -int VcpController::GetDeviceCount() { - if (!instance) { - LOG(INFO) << __func__ << ": Not initialized yet"; - return 0; - } - - return (instance->GetDeviceCount()); -} - -void VcpController::CleanUp() { - VcpControllerImpl* ptr = instance; - instance = nullptr; - - ptr->CleanUp(); - - delete ptr; -}; - -/******************************************************************************* - * Debugging functions - ******************************************************************************/ -#define CASE_RETURN_STR(const) \ - case const: \ - return #const; - -const char* vcp_controller_gatt_callback_evt_str(uint8_t event) { - switch (event) { - CASE_RETURN_STR(BTA_GATTC_DEREG_EVT) - CASE_RETURN_STR(BTA_GATTC_OPEN_EVT) - CASE_RETURN_STR(BTA_GATTC_CLOSE_EVT) - CASE_RETURN_STR(BTA_GATTC_SEARCH_CMPL_EVT) - CASE_RETURN_STR(BTA_GATTC_NOTIF_EVT) - CASE_RETURN_STR(BTA_GATTC_ENC_CMPL_CB_EVT) - CASE_RETURN_STR(BTA_GATTC_SEARCH_RES_EVT) - CASE_RETURN_STR(BTA_GATTC_CANCEL_OPEN_EVT) - CASE_RETURN_STR(BTA_GATTC_SRVC_CHG_EVT) - CASE_RETURN_STR(BTA_GATTC_CONN_UPDATE_EVT) - CASE_RETURN_STR(BTA_GATTC_SRVC_DISC_DONE_EVT) - CASE_RETURN_STR(BTA_GATTC_CONGEST_EVT) - default: - return (char*)"Unknown GATT Callback Event"; - } -} - -const char* vcp_controller_handle_vcs_evt_str(uint8_t event) { - switch (event) { - CASE_RETURN_STR(VCS_VOLUME_STATE_READ_CMPL_EVT) - CASE_RETURN_STR(VCS_VOLUME_FLAGS_READ_CMPL_EVT) - CASE_RETURN_STR(VCS_VOLUME_STATE_CCC_WRITE_CMPL_EVT) - CASE_RETURN_STR(VCS_VOLUME_FLAGS_CCC_WRITE_CMPL_EVT) - default: - return (char*)"Unknown handling VCS Event"; - } -} - diff --git a/le_audio/system/bt/btif/Android.bp b/le_audio/system/bt/btif/Android.bp deleted file mode 100644 index f989ec4c3784d76b4bc80911015d084dd27aaa19..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/Android.bp +++ /dev/null @@ -1,107 +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. - * - ******************************************************************************/ - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "system_bt_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["system_bt_license"], -} - -cc_defaults { - name: "fluoride_btif_defaults_qti_adva", - defaults: ["fluoride_defaults"], - include_dirs: [ - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/bta/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/bta/ag", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/btcore/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/hci/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/internal_include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/stack/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/stack/btm", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/udrv/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/vnd/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/utils/include", - "vendor/qcom/opensource/commonsys/bluetooth_ext/system_bt_ext", - "vendor/qcom/opensource/commonsys/bluetooth_ext/vhal/include", - "vendor/qcom/opensource/commonsys/bluetooth_ext/system_bt_ext/bta/include", - "vendor/qcom/opensource/commonsys/bluetooth_ext/system_bt_ext/btif/include", - "vendor/qcom/opensource/commonsys-intf/bluetooth/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/device/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/btif/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/bta/include", - "vendor/qcom/opensource/commonsys/packages/modules/Bluetooth/system/bta/sys", - "packages/modules/Bluetooth/system/common", - "vendor/qcom/opensource/commonsys/bluetooth_lea/packages/modules/Bluetooth/system/btif/include", - "vendor/qcom/opensource/commonsys/bluetooth_lea/packages/modules/Bluetooth/system/bta/include", - "vendor/qcom/opensource/commonsys/bluetooth_lea/packages/modules/Bluetooth/system", - "vendor/qcom/opensource/commonsys/bluetooth_lea/vhal/include", - "external/libxml2/include", - ], - shared_libs: [ - "libcutils", - "vendor.qti.hardware.bluetooth_audio@2.0", - "vendor.qti.hardware.bluetooth_audio@2.1", - "libcrypto", - "libxml2", - ], - header_libs: ["libbluetooth_headers"], - cflags: [ - "-DBUILDCFG", - "-DADV_AUDIO_FEATURE=1", - ], - required: ["leaudio_configs.xml"], -} - -// BTA static library for target -// ======================================================== -cc_library_static { - name: "libbt-btif_qti_adva", - defaults: ["fluoride_btif_defaults_qti_adva"], - enabled: false, - srcs: [ - "src/bluetooth_adv_audio.cc", - "src/btif_bap_broadcast.cc", - "src/btif_csip.cc", - "src/btif_acm.cc", - "src/btif_pacs_client.cc", - "src/btif_ascs_client.cc", - "src/btif_bap_config.cc", - "src/btif_bap_uclient.cc", - "src/btif_bap_codec_utils.cc", - "src/btif_vmcp.cc", - "src/btif_apm.cc", - "src/btif_vcp_controller.cc", - "src/btif_dm_adv_audio.cc", - "src/btif_acm_source.cc", - "src/btif_mcp.cc", - "src/btif_cc.cc" - ], -} - -// Bluetooth le audio configs xml -// ======================================================== -prebuilt_etc { - name: "leaudio_configs.xml", - src: "leaudio_configs.xml", - sub_dir: "bluetooth", - system_ext_specific: true, -} diff --git a/le_audio/system/bt/btif/include/bluetooth_adv_audio.h b/le_audio/system/bt/btif/include/bluetooth_adv_audio.h deleted file mode 100644 index 5fcc4100d0db7d1e719673878c76877bfe5ae5b4..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/include/bluetooth_adv_audio.h +++ /dev/null @@ -1,33 +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. - * - ******************************************************************************/ - - * - * Filename: bluetooth_adv_audio.h - * - * Description: Main API header file for LEA interfacing - * - ******************************************************************************/ - -#pragma once - -/******************************************************************************* - * TInterface APIs - ******************************************************************************/ - -const void* get_adv_audio_profile_interface(const char* profile_id); -void init_adv_audio_interfaces(); diff --git a/le_audio/system/bt/btif/include/btif_acm.h b/le_audio/system/bt/btif/include/btif_acm.h deleted file mode 100644 index c11dcb7ad6ec6cb8f0ea1862e28c7080d7d3bc23..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/include/btif_acm.h +++ /dev/null @@ -1,250 +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. - * - ******************************************************************************/ - - -#ifndef BTIF_ACM_H -#define BTIF_ACM_H - -#include - -//#include "bta_acm_api.h" -#include "btif_common.h" -#include "bta_bap_uclient_api.h" -#include "bta_pacs_client_api.h" -#include "bta_ascs_client_api.h" - -typedef uint8_t tBTA_ACM_HNDL; -typedef uint8_t tBTIF_ACM_STATUS; - -#define BTA_ACM_MAX_EVT 26 -#define BTA_ACM_NUM_STRS 6 -#define BTA_ACM_NUM_CIGS 239 -//starting setid from 16 onwards as 16 is inavlid -#define BTA_ACM_MIN_NUM_SETID 17 -#define BTA_ACM_MAX_NUM_SETID 255 -#define CONTEXT_TYPE_UNKNOWN 0 -#define CONTEXT_TYPE_MUSIC 1 -#define CONTEXT_TYPE_VOICE 2 -#define CONTEXT_TYPE_MUSIC_VOICE 3 - -#define BTA_ACM_DISCONNECT_EVT 0 -#define BTA_ACM_CONNECT_EVT 1 -#define BTA_ACM_START_EVT 2 -#define BTA_ACM_STOP_EVT 3 -#define BTA_ACM_RECONFIG_EVT 4 -#define BTA_ACM_CONFIG_EVT 5 -#define BTA_ACM_CONN_UPDATE_TIMEOUT_EVT 6 - -#define BTA_ACM_INITIATOR_SERVICE_ID 0xFF -#define ACM_UUID 0xFFFF -#define ACM_TSEP_SNK 1 - -#define SRC 0 -#define SNK 1 - -constexpr uint8_t STREAM_STATE_DISCONNECTED = 0x00; -constexpr uint8_t STREAM_STATE_CONNECTING = 0x01; -constexpr uint8_t STREAM_STATE_CONNECTED = 0x02; -constexpr uint8_t STREAM_STATE_STARTING = 0x03; -constexpr uint8_t STREAM_STATE_STREAMING = 0x04; -constexpr uint8_t STREAM_STATE_STOPPING = 0x05; -constexpr uint8_t STREAM_STATE_DISCONNECTING = 0x06; -constexpr uint8_t STREAM_STATE_RECONFIGURING = 0x07; - -using bluetooth::bap::ucast::StreamStateInfo; -using bluetooth::bap::ucast::StreamConfigInfo; - -using bluetooth::bap::ucast::StreamConnect; -using bluetooth::bap::ucast::StreamType; -using bluetooth::bap::ucast::StreamReconfig; -using bluetooth::bap::ucast::StreamDiscReason; -using bluetooth::bap::ucast::StreamState; -using bluetooth::bap::ucast::QosConfig; - -using bluetooth::bap::pacs::CodecConfig; - -typedef struct { - RawAddress bd_addr; - int contextType; - int profileType; -}tBTIF_ACM_CONN_DISC; - -typedef struct { - RawAddress bd_addr; -}tBTA_ACM_CONN_UPDATE_TIMEOUT_INFO; - -typedef struct { - RawAddress bd_addr; - StreamType stream_type; - CodecConfig codec_config; - uint32_t audio_location; - QosConfig qos_config; - std::vector codecs_selectable; -}tBTA_ACM_CONFIG_INFO; - -typedef struct { - RawAddress bd_addr; - StreamType stream_type; - StreamState stream_state; - StreamDiscReason reason; -}tBTA_ACM_STATE_INFO; - -typedef struct { - RawAddress bd_addr; - bool is_direct; - StreamStateInfo streams_info; -}tBTIF_ACM_CONNECT; - -typedef struct { - RawAddress bd_addr; - StreamStateInfo streams_info; -}tBTIF_ACM_DISCONNECT; - -typedef struct { - RawAddress bd_addr; - StreamStateInfo streams_info; -}tBTIF_ACM_START; - -typedef struct { - RawAddress bd_addr; - StreamStateInfo streams_info; -}tBTIF_ACM_STOP; - -typedef struct { - RawAddress bd_addr; - StreamReconfig streams_info; -}tBTIF_ACM_RECONFIG; - -typedef union { - tBTIF_ACM_CONN_DISC acm_conn_disc; - tBTA_ACM_STATE_INFO state_info; - tBTA_ACM_CONFIG_INFO config_info; - tBTIF_ACM_CONNECT acm_connect; - tBTIF_ACM_DISCONNECT acm_disconnect; - tBTIF_ACM_START acm_start; - tBTIF_ACM_STOP acm_stop; - tBTIF_ACM_RECONFIG acm_reconfig; -}tBTIF_ACM; - -typedef enum { - /* Reuse BTA_ACM_XXX_EVT - No need to redefine them here */ - BTIF_ACM_CONNECT_REQ_EVT = BTA_ACM_MAX_EVT, - BTIF_ACM_DISCONNECT_REQ_EVT, - BTIF_ACM_START_STREAM_REQ_EVT, - BTIF_ACM_STOP_STREAM_REQ_EVT, - BTIF_ACM_SUSPEND_STREAM_REQ_EVT, - BTIF_ACM_RECONFIG_REQ_EVT, -} btif_acm_sm_event_t; - -typedef enum { - BTA_CSIP_NEW_SET_FOUND_EVT = 1, - BTA_CSIP_SET_MEMBER_FOUND_EVT, - BTA_CSIP_CONN_STATE_CHG_EVT, - BTA_CSIP_LOCK_STATUS_CHANGED_EVT, - BTA_CSIP_LOCK_AVAILABLE_EVT, - BTA_CSIP_SET_SIZE_CHANGED, - BTA_CSIP_SET_SIRK_CHANGED, -} btif_csip_sm_event_t; - -/** - * When the local device is ACM source, get the address of the active peer. - */ -RawAddress btif_acm_source_active_peer(void); - -/** - * When the local device is ACM sink, get the address of the active peer. - */ -RawAddress btif_acm_sink_active_peer(void); - -/** - * Start streaming. - */ -void btif_acm_stream_start(void); - -/** - * Stop streaming. - * - * @param peer_address the peer address or RawAddress::kEmpty to stop all peers - */ -void btif_acm_stream_stop(void); - -/** - * Suspend streaming. - */ -void btif_acm_stream_suspend(void); - -/** - * Start offload streaming. - */ -void btif_acm_stream_start_offload(void); - -bool btif_acm_check_if_requested_devices_stopped(void); - -/** - * Get the Stream Endpoint Type of the Active peer. - * - * @return the stream endpoint type: either AVDT_TSEP_SRC or AVDT_TSEP_SNK - */ -uint8_t btif_acm_get_peer_sep(void); - -/** - - * Report ACM Source Codec State for a peer. - * - * @param peer_address the address of the peer to report - * @param codec_config the codec config to report - * @param codecs_local_capabilities the codecs local capabilities to report - * @param codecs_selectable_capabilities the codecs selectable capabilities - * to report - */ -void btif_acm_report_source_codec_state( - const RawAddress& peer_address, - const CodecConfig& codec_config, - const std::vector& codecs_local_capabilities, - const std::vector& - codecs_selectable_capabilities, int contextType); - -/** - * Initialize / shut down the ACM Initiator service. - * - * @param enable true to enable the ACM Source service, false to disable it - * @return BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise - */ -bt_status_t btif_acm_initiator_execute_service(bool enable); - -/** - * Dump debug-related information for the BTIF ACM module. - * - * @param fd the file descriptor to use for writing the ASCII formatted - * information - */ -void btif_debug_acm_dump(int fd); - -bool btif_acm_is_active(); -uint16_t btif_acm_get_sample_rate(); -uint8_t btif_acm_get_ch_mode(); -uint32_t btif_acm_get_bitrate(); -uint32_t btif_acm_get_octets(uint32_t bit_rate); -uint16_t btif_acm_get_framelength(); -uint8_t btif_acm_get_ch_count(); -uint16_t btif_acm_get_current_active_profile(); -bool btif_acm_is_codec_type_lc3q(); -uint8_t btif_acm_lc3q_ver(); -bool btif_acm_is_call_active(void); - -#endif /* BTIF_ACM_H */ diff --git a/le_audio/system/bt/btif/include/btif_acm_source.h b/le_audio/system/bt/btif/include/btif_acm_source.h deleted file mode 100644 index 8203a6578afefde992d9711aba6b846fc7b842f7..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/include/btif_acm_source.h +++ /dev/null @@ -1,35 +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. - * - ******************************************************************************/ - - -#if AHIM_ENABLED -void btif_register_cb(); -void btif_acm_process_request(tA2DP_CTRL_CMD cmd); -void btif_acm_handle_event(uint16_t event, char* p_param); -bool btif_acm_source_start_session(const RawAddress& peer_address); -bool btif_acm_source_end_session(const RawAddress& peer_address); -bool btif_acm_source_restart_session(const RawAddress& old_peer_address, - const RawAddress& new_peer_address); -void btif_acm_source_command_ack(tA2DP_CTRL_CMD cmd, tA2DP_CTRL_ACK status); -void btif_acm_source_on_stopped(tA2DP_CTRL_ACK status); -void btif_acm_source_on_suspended(tA2DP_CTRL_ACK status); -bool btif_acm_on_started(tA2DP_CTRL_ACK status); -bt_status_t btif_acm_source_setup_codec(); -bool btif_acm_update_sink_latency_change(uint16_t sink_latency); - -#endif diff --git a/le_audio/system/bt/btif/include/btif_bap_broadcast.h b/le_audio/system/bt/btif/include/btif_bap_broadcast.h deleted file mode 100644 index f2bf96dc46a1047efbe91bfe560b22199b3fa116..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/include/btif_bap_broadcast.h +++ /dev/null @@ -1,92 +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. - * - ******************************************************************************/ - - * - * Filename: btif_bap_broadcast.h - * - * Description: Main API header file for all BTIF BAP Broadcast functions - * accessed from internal stack. - * - ******************************************************************************/ - -#ifndef BTIF_BAP_BROADCAST_H -#define BTIF_BAP_BROADCAST_H - -#include "bta_av_api.h" -#include "btif_common.h" -#include "btif_sm.h" - - -/******************************************************************************* - * Type definitions for callback functions - ******************************************************************************/ - -typedef enum { - /* Reuse BTA_AV_XXX_EVT - No need to redefine them here */ - BTIF_BAP_BROADCAST_ENABLE_EVT, - BTIF_BAP_BROADCAST_DISABLE_EVT, - BTIF_BAP_BROADCAST_START_STREAM_REQ_EVT, - BTIF_BAP_BROADCAST_STOP_STREAM_REQ_EVT, - BTIF_BAP_BROADCAST_SUSPEND_STREAM_REQ_EVT, - BTIF_BAP_BROADCAST_SOURCE_CONFIG_REQ_EVT, - BTIF_BAP_BROADCAST_CLEANUP_REQ_EVT, - BTIF_BAP_BROADCAST_SET_ACTIVE_REQ_EVT, - BTIF_BAP_BROADCAST_REMOVE_ACTIVE_REQ_EVT, - BTIF_BAP_BROADCAST_SETUP_ISO_DATAPATH_EVT, - BTIF_BAP_BROADCAST_REMOVE_ISO_DATAPATH_EVT, - BTIF_BAP_BROADCAST_GENERATE_ENC_KEY_EVT, - BTIF_BAP_BROADCAST_BISES_SETUP_EVT, - BTIF_BAP_BROADCAST_BISES_REMOVE_EVT, - BTIF_BAP_BROADCAST_BIG_SETUP_EVT, - BTIF_BAP_BROADCAST_BIG_REMOVED_EVT, - BTIF_BAP_BROADCAST_SETUP_NEXT_BIS_EVENT, - BTIF_BAP_BROADCAST_PROCESS_HIDL_REQ_EVT, -} btif_bap_broadcast_sm_event_t; - -enum { - BTBAP_CODEC_CHANNEL_MODE_JOINT_STEREO = 0x01 << 2, - BTBAP_CODEC_CHANNEL_MODE_DUAL_MONO = 0x1 << 3 -}; -/******************************************************************************* - * BTIF AV API - ******************************************************************************/ -bool btif_bap_broadcast_is_active(); - -uint16_t btif_bap_broadcast_get_sample_rate(); -uint8_t btif_bap_broadcast_get_ch_mode(); -uint16_t btif_bap_broadcast_get_framelength(); -uint32_t btif_bap_broadcast_get_mtu(uint32_t bitrate); -uint32_t btif_bap_broadcast_get_bitrate(); -uint8_t btif_bap_broadcast_get_ch_count(); -bool btif_bap_broadcast_is_simulcast_enabled(); -/******************************************************************************* - * - * Function btif_dispatch_sm_event - * - * Description Send event to AV statemachine - * - * Returns None - * - ******************************************************************************/ - -/* used to pass events to AV statemachine from other tasks */ -void btif_bap_ba_dispatch_sm_event(btif_bap_broadcast_sm_event_t event, void *p_data, int len); - - -#endif /* BTIF_BAP_BROADCAST_H */ - diff --git a/le_audio/system/bt/btif/include/btif_bap_codec_utils.h b/le_audio/system/bt/btif/include/btif_bap_codec_utils.h deleted file mode 100644 index e557268dc359e2952a268a66cd40cd98084c4ae8..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/include/btif_bap_codec_utils.h +++ /dev/null @@ -1,90 +0,0 @@ -/****************************************************************************** - * - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - -#pragma once - -#include -#include - -#include -#include "bt_types.h" - -using bluetooth::bap::pacs::CodecConfig; - -bool UpdateCapaSupFrameDurations(CodecConfig *config , uint8_t sup_frame); - -bool UpdateCapaMaxSupLc3Frames(CodecConfig *config, - uint8_t max_sup_lc3_frames); - - -bool UpdateCapaPreferredContexts(CodecConfig *config, uint16_t contexts); - - -bool UpdateCapaSupOctsPerFrame(CodecConfig *config, - uint32_t octs_per_frame); - -bool UpdateCapaVendorMetaDataLc3QPref(CodecConfig *config, bool lc3q_pref); - -bool UpdateCapaVendorMetaDataLc3QVer(CodecConfig *config, uint8_t lc3q_ver); - -uint8_t GetCapaSupFrameDurations(CodecConfig *config); - -uint8_t GetCapaMaxSupLc3Frames(CodecConfig *config); - -uint16_t GetCapaPreferredContexts(CodecConfig *config); - -uint32_t GetCapaSupOctsPerFrame(CodecConfig *config); - -bool GetCapaVendorMetaDataLc3QPref(CodecConfig *config); - -uint8_t GetCapaVendorMetaDataLc3QVer(CodecConfig *config); - -// configurations -bool UpdateFrameDuration(CodecConfig *config , uint8_t frame_dur); - -bool UpdateLc3BlocksPerSdu(CodecConfig *config, - uint8_t lc3_blocks_per_sdu) ; - -bool UpdateOctsPerFrame(CodecConfig *config , uint16_t octs_per_frame); - -bool UpdateLc3QPreference(CodecConfig *config , bool lc3q_pref); - -bool UpdateVendorMetaDataLc3QPref(CodecConfig *config, bool lc3q_pref); - -bool UpdateVendorMetaDataLc3QVer(CodecConfig *config, uint8_t lc3q_ver); - -bool UpdatePreferredAudioContext(CodecConfig *config , - uint16_t pref_audio_context); - -uint8_t GetFrameDuration(CodecConfig *config); - -uint8_t GetLc3BlocksPerSdu(CodecConfig *config); - -uint16_t GetOctsPerFrame(CodecConfig *config); - -uint8_t GetLc3QPreference(CodecConfig *config); - -uint8_t GetVendorMetaDataLc3QPref(CodecConfig *config); - -uint8_t GetVendorMetaDataLc3QVer(CodecConfig *config); - -uint16_t GetPreferredAudioContext(CodecConfig *config); - -bool IsCodecConfigEqual(CodecConfig *src_config, CodecConfig *dst_config); - - diff --git a/le_audio/system/bt/btif/include/btif_bap_config.h b/le_audio/system/bt/btif/include/btif_bap_config.h deleted file mode 100644 index a83b8e9bb5cf54de177249e100aeacce0e1a020c..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/include/btif_bap_config.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/****************************************************************************** - * - * Copyright (C) 2014 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - -#pragma once - -#include -#include - -#include -#include "bt_types.h" - -using bluetooth::bap::pacs::CodecConfig; -using bluetooth::bap::pacs::CodecDirection; -using bluetooth::bap::pacs::CodecIndex; - -typedef enum { - REC_TYPE_CAPABILITY = 0x01, - REC_TYPE_CONFIGURATION -} btif_bap_record_type_t; - -const char BTIF_BAP_CONFIG_MODULE[] = "btif_bap_config_module"; - -typedef struct btif_bap_config_section_iter_t btif_bap_config_section_iter_t; - -bool btif_bap_add_record(const RawAddress& bd_addr, - btif_bap_record_type_t rec_type, - uint16_t context_type, - CodecDirection direction, - CodecConfig *record); - -bool btif_bap_remove_record(const RawAddress& bd_addr, - btif_bap_record_type_t rec_type, - uint16_t context_type, - CodecDirection direction, - CodecConfig *record); - -bool btif_bap_remove_record_by_context(const RawAddress& bd_addr, - btif_bap_record_type_t rec_type, - uint16_t context_type, - CodecDirection direction); - -bool btif_bap_remove_all_records(const RawAddress& bd_addr); - -bool btif_bap_get_records(const RawAddress& bd_addr, - btif_bap_record_type_t rec_type, - uint16_t context_type, - CodecDirection direction, - std::vector *pac_records); - -bool btif_bap_add_audio_loc(const RawAddress& bd_addr, - CodecDirection direction, uint32_t audio_loc); - -bool btif_bap_rem_audio_loc(const RawAddress& bd_addr, - CodecDirection direction); - -bool btif_bap_add_supp_contexts(const RawAddress& bd_addr, - uint32_t supp_contexts); - -bool btif_bap_get_supp_contexts(const RawAddress& bd_addr, - uint32_t *supp_contexts); - -bool btif_bap_rem_supp_contexts(const RawAddress& bd_addr); - -bool btif_bap_config_clear(void); diff --git a/le_audio/system/bt/btif/include/btif_dm_adv_audio.h b/le_audio/system/bt/btif/include/btif_dm_adv_audio.h deleted file mode 100644 index d28863311e2aa5f27a57111bd6d4e87b7daf64c4..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/include/btif_dm_adv_audio.h +++ /dev/null @@ -1,33 +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. - * - ******************************************************************************/ - -#ifndef BTIF_DM_ADV_AUDIO_H -#define BTIF_DM_ADV_AUDIO_H - -extern std::unordered_map adv_audio_device_db; -extern tBTA_TRANSPORT btif_dm_get_adv_audio_transport(const RawAddress& bd_addr); -extern void btif_dm_lea_search_services_evt(uint16_t event, char* p_param); -extern void btif_register_uuid_srvc_disc(bluetooth::Uuid uuid); -extern bool check_adv_audio_cod(uint32_t cod); -extern bool is_remote_support_adv_audio(const RawAddress p_addr); -extern void bte_dm_adv_audio_search_services_evt(tBTA_DM_SEARCH_EVT event, - tBTA_DM_SEARCH* p_data); -extern void btif_dm_release_action_uuid(RawAddress bd_addr); - -#endif - diff --git a/le_audio/system/bt/btif/include/btif_vmcp.h b/le_audio/system/bt/btif/include/btif_vmcp.h deleted file mode 100644 index 7eb72bf5c8a6494f2b0878e4cb6efc82700de3ea..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/include/btif_vmcp.h +++ /dev/null @@ -1,147 +0,0 @@ -/****************************************************************************** - * - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - - -#include -#include "raw_address.h" -#include "hardware/bt_pacs_client.h" - -using bluetooth::bap::pacs::CodecSampleRate; -using bluetooth::bap::pacs::CodecIndex; -using bluetooth::bap::pacs::CodecFrameDuration; -using bluetooth::bap::pacs::CodecConfig; - -#define BAP 0x01 -#define GCP 0x02 -#define WMCP 0x04 -#define VMCP 0x08 -#define BAP_CALL 0x10 -#define GCP_TX_RX 0x20 - -#define EB_CONFIG 1 -#define STEREO_HS_CONFIG_1 2 -#define STEREO_HS_CONFIG_2 3 - -#define VOICE_CONTEXT 1 -#define MEDIA_CONTEXT 2 -#define MEDIA_LL_CONTEXT 3 -#define MEDIA_HR_CONTEXT 4 - -#define SAMPLE_RATE_8000 8000 -#define SAMPLE_RATE_16000 16000 -#define SAMPLE_RATE_24000 24000 -#define SAMPLE_RATE_32000 32000 -#define SAMPLE_RATE_44100 44100 -#define SAMPLE_RATE_48000 48000 - - -#define FRM_DURATION_7_5_MS 7.5 -#define FRM_DURATION_10_MS 10 - -#define OCT_PER_CODEC_FRM_26 26 -#define OCT_PER_CODEC_FRM_30 30 -#define OCT_PER_CODEC_FRM_60 60 -#define OCT_PER_CODEC_FRM_75 75 -#define OCT_PER_CODEC_FRM_80 80 -#define OCT_PER_CODEC_FRM_90 90 -#define OCT_PER_CODEC_FRM_98 98 -#define OCT_PER_CODEC_FRM_100 100 -#define OCT_PER_CODEC_FRM_117 117 -#define OCT_PER_CODEC_FRM_120 120 -#define OCT_PER_CODEC_FRM_130 130 -#define OCT_PER_CODEC_FRM_150 150 -#define OCT_PER_CODEC_FRM_155 155 - -#define UNFRAMED 0 -#define FRAMED 1 - -#define RETRANS_NO_2 2 -#define RETRANS_NO_5 5 -#define RETRANS_NO_7 7 -#define RETRANS_NO_11 11 -#define RETRANS_NO_13 13 -#define RETRANS_NO_23 23 -#define RETRANS_NO_29 29 -#define RETRANS_NO_35 35 -#define RETRANS_NO_41 41 -#define RETRANS_NO_47 47 -#define RETRANS_NO_53 53 - -#define MAX_TRANS_LAT_MS_8 8 -#define MAX_TRANS_LAT_MS_10 10 -#define MAX_TRANS_LAT_MS_15 15 -#define MAX_TRANS_LAT_MS_20 20 -#define MAX_TRANS_LAT_MS_24 24 -#define MAX_TRANS_LAT_MS_25 25 -#define MAX_TRANS_LAT_MS_31 31 -#define MAX_TRANS_LAT_MS_33 33 -#define MAX_TRANS_LAT_MS_45 45 -#define MAX_TRANS_LAT_MS_54 54 -#define MAX_TRANS_LAT_MS_60 60 -#define MAX_TRANS_LAT_MS_71 71 -#define MAX_TRANS_LAT_MS_95 95 - -#define PRES_DELAY_20_MS 20 -#define PRES_DELAY_25_MS 25 -#define PRES_DELAY_40_MS 40 - -#define LEAUDIO_CONFIG_PATH "/system_ext/etc/bluetooth/leaudio_configs.xml" -using namespace std; - -// for storing codec config as it is read from xml -struct codec_config -{ - uint32_t freq_in_hz; - float frame_dur_msecs; - uint8_t oct_per_codec_frm; - uint8_t mandatory; -}; - -// for storing QoS settings as it is read from xml -struct qos_config -{ - uint32_t freq_in_hz; - uint32_t sdu_int_micro_secs; - uint8_t framing; - uint8_t max_sdu_size; - uint8_t retrans_num; - uint8_t max_trans_lat; - uint32_t presentation_delay; - uint8_t mandatory; -}; - - -// QoS configuration in the structure needed by ACM -struct QoSConfig -{ - CodecSampleRate sample_rate; - uint32_t sdu_int_micro_secs; - uint8_t framing; - uint8_t max_sdu_size; - uint8_t retrans_num; - uint8_t max_trans_lat; - uint32_t presentation_delay; - uint8_t mandatory; -}; -void btif_vmcp_init(); - -vector get_all_codec_configs(uint8_t profile, uint8_t context); -vector get_preferred_codec_configs(uint8_t profile, uint8_t context); - -vector get_all_qos_params(uint8_t profile, uint8_t context); -vector get_qos_params_for_codec(uint8_t profile, uint8_t context, CodecSampleRate freq, uint8_t frame_dur, uint8_t octets); diff --git a/le_audio/system/bt/btif/leaudio_configs.xml b/le_audio/system/bt/btif/leaudio_configs.xml deleted file mode 100644 index 0971d6fbbcbbbee86f0f9f3dc469cb9a61eb09ef..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/leaudio_configs.xml +++ /dev/null @@ -1,727 +0,0 @@ - - - - - - - - 8000 - 7500 - 26 - 0 - - - 8000 - 10000 - 30 - 0 - - - 32000 - 7500 - 60 - 0 - - - 32000 - 10000 - 80 - 1 - - - - - - 48000 - 7500 - 75 - 0 - - - 48000 - 10000 - 100 - 1 - - - 48000 - 7500 - 90 - 0 - - - 48000 - 10000 - 120 - 0 - - - 48000 - 7500 - 117 - 0 - - - 48000 - 10000 - 155 - 1 - - - - - - 8000 - 7500 - 0 - 26 - 2 - 8 - 20000 - 0 - - - 8000 - 10000 - 0 - 30 - 2 - 10 - 20000 - 0 - - - 32000 - 7500 - 0 - 60 - 2 - 8 - 20000 - 1 - - - 32000 - 10000 - 0 - 80 - 2 - 10 - 20000 - 1 - - - - - 48000 - 7500 - 0 - 75 - 5 - 15 - 20000 - 0 - - - 48000 - 10000 - 0 - 100 - 5 - 20 - 20000 - 1 - - - 48000 - 7500 - 0 - 90 - 5 - 15 - 20000 - 0 - - - 48000 - 10000 - 0 - 120 - 5 - 20 - 20000 - 0 - - - 48000 - 7500 - 0 - 117 - 5 - 15 - 20000 - 0 - - - 48000 - 10000 - 0 - 155 - 5 - 20 - 20000 - 0 - - - - - 48000 - 7500 - 0 - 75 - 23 - 45 - 20000 - 0 - - - 48000 - 10000 - 0 - 100 - 23 - 60 - 20000 - 1 - - - 48000 - 7500 - 0 - 90 - 23 - 45 - 20000 - 0 - - - 48000 - 10000 - 0 - 120 - 23 - 60 - 20000 - 0 - - - 48000 - 7500 - 0 - 117 - 23 - 45 - 20000 - 0 - - - 48000 - 10000 - 0 - 155 - 23 - 60 - 20000 - 0 - - - - - - - - 32000 - 10000 - 80 - 0 - - - - - 48000 - 10000 - 100 - 0 - - - - - 32000 - 10000 - 0 - 80 - 2 - 10 - 40000 - 0 - - - - - 8000 - 7500 - 0 - 26 - 2 - 8 - 40000 - 0 - - - 8000 - 10000 - 0 - 30 - 2 - 10 - 40000 - 0 - - - 16000 - 7500 - 0 - 30 - 2 - 8 - 40000 - 0 - - - 16000 - 10000 - 0 - 40 - 2 - 10 - 40000 - 0 - - - 24000 - 7500 - 0 - 45 - 2 - 8 - 40000 - 0 - - - 24000 - 10000 - 0 - 60 - 2 - 10 - 40000 - 0 - - - 48000 - 7500 - 0 - 75 - 5 - 15 - 40000 - 0 - - - 48000 - 10000 - 0 - 100 - 15 - 70 - 40000 - 0 - - - 48000 - 7500 - 0 - 90 - 5 - 15 - 40000 - 0 - - - 48000 - 10000 - 0 - 120 - 5 - 20 - 40000 - 0 - - - 32000 - 7500 - 0 - 60 - 2 - 8 - 40000 - 0 - - - 32000 - 10000 - 0 - 80 - 2 - 10 - 40000 - 0 - - - 48000 - 7500 - 0 - 117 - 5 - 15 - 40000 - 0 - - - 48000 - 10000 - 0 - 155 - 13 - 100 - 40000 - 0 - - - - - 8000 - 7500 - 0 - 26 - 41 - 45 - 40000 - 0 - - - 8000 - 10000 - 0 - 30 - 53 - 60 - 40000 - 0 - - - 16000 - 7500 - 0 - 30 - 41 - 45 - 40000 - 0 - - - 16000 - 10000 - 0 - 40 - 47 - 60 - 40000 - 1 - - - 24000 - 7500 - 0 - 45 - 35 - 45 - 40000 - 0 - - - 24000 - 10000 - 0 - 60 - 41 - 60 - 40000 - 0 - - - 32000 - 7500 - 0 - 60 - 29 - 45 - 40000 - 0 - - - 32000 - 10000 - 0 - 80 - 35 - 60 - 40000 - 0 - - - 48000 - 7500 - 0 - 75 - 23 - 45 - 40000 - 0 - - - 48000 - 10000 - 0 - 100 - 23 - 60 - 40000 - 0 - - - 48000 - 7500 - 0 - 90 - 23 - 45 - 40000 - 0 - - - 48000 - 10000 - 0 - 120 - 23 - 60 - 40000 - 0 - - - 48000 - 7500 - 0 - 117 - 23 - 45 - 40000 - 0 - - - 48000 - 10000 - 0 - 155 - 13 - 100 - 40000 - 0 - - - - - - - - 16000 - 7500 - 60 - 1 - - - 16000 - 7500 - 60 - 0 - - - 16000 - 7500 - 30 - 1 - - - - - - 48000 - 7500 - 75 - 0 - - - - - - 16000 - 15000 - 0 - 60 - 2 - 8 - 25000 - 1 - - - 16000 - 15000 - 0 - 60 - 7 - 25 - 25000 - 0 - - - 16000 - 7500 - 0 - 30 - 11 - 33 - 25000 - 1 - - - - - - 48000 - 7500 - 0 - 75 - 5 - 12 - 25000 - 0 - - - - - - - - 48000 - 10000 - 100 - 0 - - - - - 16000 - 10000 - 0 - 40 - 13 - 95 - 40000 - 0 - - - 16000 - 7500 - 0 - 30 - 13 - 75 - 40000 - 0 - - - 32000 - 10000 - 0 - 80 - 13 - 95 - 40000 - 0 - - - 32000 - 7500 - 0 - 60 - 13 - 75 - 40000 - 0 - - - 48000 - 10000 - 0 - 100 - 11 - 40 - 25000 - 0 - - - 48000 - 7500 - 0 - 75 - 13 - 75 - 40000 - 0 - - - - - - diff --git a/le_audio/system/bt/btif/src/bluetooth_adv_audio.cc b/le_audio/system/bt/btif/src/bluetooth_adv_audio.cc deleted file mode 100644 index ad1b1accff39f8fc5875ce4e8bbea0e9add4cc9f..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/src/bluetooth_adv_audio.cc +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/****************************************************************************** - * - * Copyright (C) 2009-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. - * - ******************************************************************************/ - -/******************************************************************************* - * - * Filename: bluetooth_adv_audio.cc - * - * Description: Bluetooth LEA HAL implementation - * - ******************************************************************************/ - -#define LOG_TAG "bt_btif_adv_audio" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "osi/include/log.h" -#include "btif_bap_config.h" -#include "bta_csip_api.h" -#include "stack_interface.h" -#include "btcore/include/module.h" -#include "btcore/include/osi_module.h" -#include - -/******************************************************************************* - * Externs - ******************************************************************************/ - -/* list all extended interfaces here */ -using bluetooth::bap::pacs::PacsClientInterface; -using bluetooth::bap::ascs::AscsClientInterface; -using bluetooth::bap::ucast::UcastClientInterface; -using bluetooth::vcp_controller::VcpControllerInterface; -using bluetooth::mcp_server::McpServerInterface; -using bluetooth::call_control::CallControllerInterface; -extern PacsClientInterface *btif_pacs_client_get_interface(); -extern AscsClientInterface *btif_ascs_client_get_interface(); -extern UcastClientInterface *btif_bap_uclient_get_interface(); -extern bt_apm_interface_t *btif_apm_get_interface(); -extern btacm_initiator_interface_t* btif_acm_initiator_get_interface(); -extern btbap_broadcast_interface_t * btif_bap_broadcast_get_interface(); -/* Coordinated set identification profile - client */ -extern btcsip_interface_t* btif_csip_get_interface(); -/*Vcp Controller*/ -extern VcpControllerInterface* btif_vcp_get_controller_interface(); -/*Mcp server*/ -extern McpServerInterface* btif_mcp_server_get_interface(); -extern CallControllerInterface* btif_cc_server_get_interface(); - -/******************************************************************************* - * Functions - ******************************************************************************/ - -static bool is_profile(const char* p1, const char* p2) { - CHECK(p1); - CHECK(p2); - return strlen(p1) == strlen(p2) && strncmp(p1, p2, strlen(p2)) == 0; -} - -/***************************************************************************** - * - * BLUETOOTH LEA HAL INTERFACE FUNCTIONS - * - ****************************************************************************/ - -StackCallbacks *stack_callbacks; - -const void* get_adv_audio_profile_interface(const char* profile_id) { - LOG_INFO(LOG_TAG, "%s: id = %s", __func__, profile_id); - - if (is_profile(profile_id, BT_PROFILE_PACS_CLIENT_ID)) { - return btif_pacs_client_get_interface(); - } - - if (is_profile(profile_id, BT_APM_MODULE_ID)) { - return btif_apm_get_interface(); - } - - if (is_profile(profile_id, BT_PROFILE_ACM_ID)) { - return btif_acm_initiator_get_interface(); - } - - if (is_profile(profile_id, BT_PROFILE_BAP_BROADCAST_ID)) - return btif_bap_broadcast_get_interface(); - - if (is_profile(profile_id, BT_PROFILE_CSIP_CLIENT_ID)) { - return btif_csip_get_interface(); - } - - if (is_profile(profile_id, BT_PROFILE_VOLUME_CONTROL_ID)) { - return btif_vcp_get_controller_interface(); - } - - if (is_profile(profile_id, BT_PROFILE_MCP_ID)) { - return btif_mcp_server_get_interface(); - } - - if (is_profile(profile_id, BT_PROFILE_CC_ID)) { - return btif_cc_server_get_interface(); - } - - if (is_profile(profile_id, BT_PROFILE_ASCS_CLIENT_ID)) { - return btif_ascs_client_get_interface(); - } - - if (is_profile(profile_id, BT_PROFILE_BAP_UCLIENT_ID)) { - return bluetooth::bap::ucast::btif_bap_uclient_get_interface(); - } - return NULL; -} - -class StackCallbacksImpl : public StackCallbacks { - public: - ~StackCallbacksImpl() = default; - void OnDevUnPaired(const RawAddress& address) override { - BTA_CsipRemoveUnpairedSetMember(address); - btif_bap_remove_all_records(address); - } - - void OnConfigCleared(void) override { - btif_bap_config_clear(); - } - - void OnStackState(StackState state) { - switch(state) { - case StackState::INITIALIZING: - module_init(get_module(BTIF_BAP_CONFIG_MODULE)); - break; - case StackState::TURNING_ON: - module_start_up(get_module(BTIF_BAP_CONFIG_MODULE)); - break; - case StackState::TURNING_OFF: - module_shut_down(get_module(BTIF_BAP_CONFIG_MODULE)); - break; - case StackState::CLEAND_UP: - module_clean_up(get_module(BTIF_BAP_CONFIG_MODULE)); - break; - default: - break; - } - } -}; - -void init_adv_audio_interfaces() { - stack_callbacks = new StackCallbacksImpl; - StackInterface::Initialize(stack_callbacks); -} diff --git a/le_audio/system/bt/btif/src/btif_acm.cc b/le_audio/system/bt/btif/src/btif_acm.cc deleted file mode 100644 index 85ab0425748a544bf3455c118de8de86d8807df6..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/src/btif_acm.cc +++ /dev/null @@ -1,6671 +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. - * - ******************************************************************************/ - - -#define LOG_TAG "btif_acm" -#include "btif_acm.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "bta_closure_api.h" -#include "btif_storage.h" -#include -#include -#include "audio_hal_interface/a2dp_encoding.h" -#include "bt_common.h" -#include "bt_utils.h" -#include "bta/include/bta_api.h" -#include "btif/include/btif_a2dp_source.h" -#include "btif_common.h" -#include -#include "audio_a2dp_hw/include/audio_a2dp_hw.h" -#include "btif_av_co.h" -#include "btif_util.h" -#include "btu.h" -#include "common/state_machine.h" -#include "osi/include/allocator.h" -#include "osi/include/osi.h" -#include "osi/include/properties.h" -#include "btif/include/btif_bap_config.h" -#include "bta_bap_uclient_api.h" -#include "btif_bap_codec_utils.h" -#include "bta/include/bta_csip_api.h" -#include -#include "osi/include/thread.h" -#include -#include "bta_api.h" -#include -#include -#include "btif/include/btif_vmcp.h" -#include "btif/include/btif_acm_source.h" -#include "l2c_api.h" -#include "bt_types.h" -#include - -/***************************************************************************** - * Constants & Macros - *****************************************************************************/ -#define LE_AUDIO_MASK 0x00000300 -#define LE_AUDIO_NOT_AVAILABLE 0x00000100 -#define LE_AUDIO_AVAILABLE_NOT_LICENSED 0x00000200 //LC3 -#define LE_AUDIO_AVAILABLE_LICENSED 0x00000300 //LC3Q -#define LE_AUDIO_CS_3_1ST_BYTE_INDEX 0x00 -#define LE_AUDIO_CS_3_2ND_BYTE_INDEX 0x01 -#define LE_AUDIO_CS_3_3RD_BYTE_INDEX 0x02 -#define LE_AUDIO_CS_3_4TH_BYTE_INDEX 0x03 -#define LE_AUDIO_CS_3_5TH_BYTE_INDEX 0x04 -#define LE_AUDIO_CS_3_7TH_BYTE_INDEX 0x06 -#define LE_AUDIO_CS_3_8TH_BYTE_INDEX 0x07 - -static RawAddress active_bda = {}; -static constexpr int kDefaultMaxConnectedAudioDevices = 5; -CodecConfig current_active_config; -static CodecConfig current_media_config; -static CodecConfig current_voice_config; -static CodecConfig current_recording_config; -uint16_t current_active_profile_type = 0; -uint16_t current_active_context_type; - -using bluetooth::bap::ucast::UcastClientInterface; -using bluetooth::bap::ucast::UcastClientCallbacks; -using bluetooth::bap::ucast::UcastClient; -using bluetooth::bap::ucast::StreamState; -using bluetooth::bap::ucast::StreamConnect; -using bluetooth::bap::ucast::StreamType; - -using bluetooth::bap::pacs::CodecIndex; -using bluetooth::bap::pacs::CodecPriority; -using bluetooth::bap::pacs::CodecSampleRate; -using bluetooth::bap::pacs::CodecBPS; -using bluetooth::bap::pacs::CodecChannelMode; -using bluetooth::bap::pacs::CodecFrameDuration; -using bluetooth::bap::ucast::CodecQosConfig; -using bluetooth::bap::ucast::StreamStateInfo; -using bluetooth::bap::ucast::StreamConfigInfo; -using bluetooth::bap::ucast::StreamReconfig; -using bluetooth::bap::ucast::CISConfig; -using bluetooth::bap::pacs::CodecDirection; -using bluetooth::bap::ucast::CONTENT_TYPE_MEDIA; -using bluetooth::bap::ucast::CONTENT_TYPE_CONVERSATIONAL; -using bluetooth::bap::ucast::CONTENT_TYPE_LIVE; -using bluetooth::bap::ucast::CONTENT_TYPE_UNSPECIFIED; -using bluetooth::bap::ucast::CONTENT_TYPE_INSTRUCTIONAL; -using bluetooth::bap::ucast::CONTENT_TYPE_NOTIFICATIONS; -using bluetooth::bap::ucast::CONTENT_TYPE_ALERT; -using bluetooth::bap::ucast::CONTENT_TYPE_MAN_MACHINE; -using bluetooth::bap::ucast::CONTENT_TYPE_EMERGENCY; -using bluetooth::bap::ucast::CONTENT_TYPE_RINGTONE; -using bluetooth::bap::ucast::CONTENT_TYPE_SOUND_EFFECTS; -using bluetooth::bap::ucast::CONTENT_TYPE_GAME; - -using bluetooth::bap::ucast::ASE_DIRECTION_SRC; -using bluetooth::bap::ucast::ASE_DIRECTION_SINK; -using bluetooth::bap::ucast::ASCSConfig; -using bluetooth::bap::ucast::LE_2M_PHY; -using bluetooth::bap::ucast::LE_QHS_PHY; - -using base::Bind; -using base::Unretained; -using base::IgnoreResult; -using bluetooth::Uuid; -extern void do_in_bta_thread(const base::Location& from_here, - const base::Closure& task); - -bool reconfig_acm_initiator(const RawAddress& peer_address, int profileType); - -static void btif_acm_initiator_dispatch_sm_event(const RawAddress& peer_address, - btif_acm_sm_event_t event); -void btif_acm_update_lc3q_params(int64_t* cs3, tBTIF_ACM* p_acm_data); - -uint16_t btif_acm_bap_to_acm_context(uint16_t bap_context); - -std::mutex acm_session_wait_mutex_; -std::condition_variable acm_session_wait_cv; -bool acm_session_wait; - - -/***************************************************************************** - * Local type definitions - *****************************************************************************/ - -class BtifCsipEvent { - public: - BtifCsipEvent(uint32_t event, const void* p_data, size_t data_length); - BtifCsipEvent(const BtifCsipEvent& other); - BtifCsipEvent() = delete; - ~BtifCsipEvent(); - BtifCsipEvent& operator=(const BtifCsipEvent& other); - - uint32_t Event() const { return event_; } - void* Data() const { return data_; } - size_t DataLength() const { return data_length_; } - std::string ToString() const; - static std::string EventName(uint32_t event); - - private: - void DeepCopy(uint32_t event, const void* p_data, size_t data_length); - void DeepFree(); - - uint32_t event_; - void* data_; - size_t data_length_; -}; - -class BtifAcmEvent { - public: - BtifAcmEvent(uint32_t event, const void* p_data, size_t data_length); - BtifAcmEvent(const BtifAcmEvent& other); - BtifAcmEvent() = delete; - ~BtifAcmEvent(); - BtifAcmEvent& operator=(const BtifAcmEvent& other); - - uint32_t Event() const { return event_; } - void* Data() const { return data_; } - size_t DataLength() const { return data_length_; } - std::string ToString() const; - static std::string EventName(uint32_t event); - - private: - void DeepCopy(uint32_t event, const void* p_data, size_t data_length); - void DeepFree(); - - uint32_t event_; - void* data_; - size_t data_length_; -}; - -class BtifAcmPeer; - -class BtifAcmStateMachine : public bluetooth::common::StateMachine { - public: - enum { - kStateIdle, // ACM state disconnected - kStateOpening, // ACM state connecting - kStateOpened, // ACM state connected - kStateStarted, // ACM state streaming - kStateReconfiguring, // ACM state reconfiguring - kStateClosing, // ACM state disconnecting - }; - - class StateIdle : public State { - public: - StateIdle(BtifAcmStateMachine& sm) - : State(sm, kStateIdle), peer_(sm.Peer()) {} - void OnEnter() override; - void OnExit() override; - bool ProcessEvent(uint32_t event, void* p_data) override; - - private: - BtifAcmPeer& peer_; - }; - - class StateOpening : public State { - public: - StateOpening(BtifAcmStateMachine& sm) - : State(sm, kStateOpening), peer_(sm.Peer()) {} - void OnEnter() override; - void OnExit() override; - bool ProcessEvent(uint32_t event, void* p_data) override; - - private: - BtifAcmPeer& peer_; - }; - - class StateOpened : public State { - public: - StateOpened(BtifAcmStateMachine& sm) - : State(sm, kStateOpened), peer_(sm.Peer()) {} - void OnEnter() override; - void OnExit() override; - bool ProcessEvent(uint32_t event, void* p_data) override; - - private: - BtifAcmPeer& peer_; - }; - - class StateStarted : public State { - public: - StateStarted(BtifAcmStateMachine& sm) - : State(sm, kStateStarted), peer_(sm.Peer()) {} - void OnEnter() override; - void OnExit() override; - bool ProcessEvent(uint32_t event, void* p_data) override; - - private: - BtifAcmPeer& peer_; - }; - - class StateReconfiguring : public State { - public: - StateReconfiguring(BtifAcmStateMachine& sm) - : State(sm, kStateReconfiguring), peer_(sm.Peer()) {} - void OnEnter() override; - void OnExit() override; - bool ProcessEvent(uint32_t event, void* p_data) override; - - private: - BtifAcmPeer& peer_; - }; - - class StateClosing : public State { - public: - StateClosing(BtifAcmStateMachine& sm) - : State(sm, kStateClosing), peer_(sm.Peer()) {} - void OnEnter() override; - void OnExit() override; - bool ProcessEvent(uint32_t event, void* p_data) override; - - private: - BtifAcmPeer& peer_; - }; - - BtifAcmStateMachine(BtifAcmPeer& btif_acm_peer) : peer_(btif_acm_peer) { - state_idle_ = new StateIdle(*this); - state_opening_ = new StateOpening(*this); - state_opened_ = new StateOpened(*this); - state_started_ = new StateStarted(*this); - state_reconfiguring_ = new StateReconfiguring(*this); - state_closing_ = new StateClosing(*this); - - AddState(state_idle_); - AddState(state_opening_); - AddState(state_opened_); - AddState(state_started_); - AddState(state_reconfiguring_); - AddState(state_closing_); - SetInitialState(state_idle_); - } - - BtifAcmPeer& Peer() { return peer_; } - - private: - BtifAcmPeer& peer_; - StateIdle* state_idle_; - StateOpening* state_opening_; - StateOpened* state_opened_; - StateStarted* state_started_; - StateReconfiguring* state_reconfiguring_; - StateClosing* state_closing_; -}; - -class BtifAcmPeer { - public: - enum { - kFlagPendingLocalSuspend = 0x01, - kFlagPendingReconfigure = 0x02, - kFlagPendingStart = 0x04, - kFlagPendingStop = 0x08, - kFLagPendingStartAfterReconfig = 0x10, - }; - - enum { - kFlagAggresiveMode = 0x01, - kFlagRelaxedMode = 0x02, - }; - - static constexpr uint64_t kTimeoutLockReleaseMs = 5 * 1000; - - BtifAcmPeer(const RawAddress& peer_address, uint8_t peer_sep, - uint8_t set_id, uint8_t cig_id, uint8_t cis_id); - ~BtifAcmPeer(); - - bt_status_t Init(); - void Cleanup(); - - /** - * Check whether the peer can be deleted. - * - * @return true if the pair can be deleted, otherwise false - */ - bool CanBeDeleted() const; - - bool IsPeerActiveForMusic() const { - return (SetId() == MusicActiveSetId()); - } - bool IsPeerActiveForVoice() const { - return (SetId() == VoiceActiveSetId()); - } - - bool IsAcceptor() const { return (peer_sep_ == ACM_TSEP_SNK); } - - const RawAddress& MusicActivePeerAddress() const; - const RawAddress& VoiceActivePeerAddress() const; - uint8_t MusicActiveSetId() const; - uint8_t VoiceActiveSetId() const; - - const RawAddress& PeerAddress() const { return peer_address_; } - - void SetContextType(uint16_t contextType) { context_type_ = context_type_ | contextType; } - uint16_t GetContextType() { return context_type_; } - void ResetContextType(uint16_t contextType) { context_type_ &= ~contextType; } - - - void SetProfileType(uint16_t profileType) { profile_type_ = profile_type_ | profileType; } - uint16_t GetProfileType() {return profile_type_;} - void ResetProfileType(uint16_t profileType) { profile_type_ &= ~profileType; } - - - void SetRcfgProfileType(uint16_t profileType) { rcfg_profile_type_ = profileType; } - uint16_t GetRcfgProfileType() {return rcfg_profile_type_;} - - void SetPrefContextType(uint16_t preferredContext) {preferred_context_ = preferredContext;}; - uint16_t GetPrefContextType() {return preferred_context_;} - - void SetStreamContextType(uint16_t contextType) { stream_context_type_ = contextType; } - uint16_t GetStreamContextType() { return stream_context_type_; } - - void SetPeerVoiceRxState(StreamState state) {voice_rx_state = state;} - StreamState GetPeerVoiceRxState() {return voice_rx_state;} - - void SetPeerVoiceTxState(StreamState state) {voice_tx_state = state;} - StreamState GetPeerVoiceTxState() {return voice_tx_state;} - - void SetPeerMusicTxState(StreamState state) {music_tx_state = state;} - StreamState GetPeerMusicTxState() {return music_tx_state;} - - void SetPeerMusicRxState(StreamState state) {music_rx_state = state;} - StreamState GetPeerMusicRxState() {return music_rx_state;} - - void SetPeerLatency(uint16_t peerLatency) { peer_latency_ = peerLatency; } - uint16_t GetPeerLatency() {return peer_latency_;} - - void SetIsStereoHsType(bool stereoHsType) { is_stereohs_type_= stereoHsType; } - bool IsStereoHsType() {return is_stereohs_type_;} - - void set_peer_media_codec_config(CodecConfig &codec_config) { - peer_media_codec_config = codec_config; - } - CodecConfig get_peer_media_codec_config() {return peer_media_codec_config;} - - void set_peer_media_qos_config(QosConfig &qos_config) {peer_media_qos_config = qos_config;} - QosConfig get_peer_media_qos_config() {return peer_media_qos_config;} - - void set_peer_media_codec_qos_config(CodecQosConfig &codec_qos_config) { - peer_media_codec_qos_config = codec_qos_config;} - CodecQosConfig get_peer_media_codec_qos_config() {return peer_media_codec_qos_config;} - - void set_peer_voice_rx_codec_config(CodecConfig &codec_config) { - peer_voice_rx_codec_config = codec_config; - } - CodecConfig get_peer_voice_rx_codec_config() {return peer_voice_rx_codec_config;} - - void set_peer_voice_rx_qos_config(QosConfig &qos_config) {peer_voice_rx_qos_config = qos_config;} - QosConfig get_peer_voice_rx_qos_config() {return peer_voice_rx_qos_config;} - - void set_peer_voice_rx_codec_qos_config(CodecQosConfig &codec_qos_config) { - peer_voice_rx_codec_qos_config = codec_qos_config;} - CodecQosConfig get_peer_voice_rx_codec_qos_config() {return peer_voice_rx_codec_qos_config;} - - void set_peer_voice_tx_codec_config(CodecConfig &codec_config) { - peer_voice_tx_codec_config = codec_config; - } - CodecConfig get_peer_voice_tx_codec_config() {return peer_voice_tx_codec_config;} - - void set_peer_voice_tx_qos_config(QosConfig &qos_config) {peer_voice_tx_qos_config = qos_config;} - QosConfig get_peer_voice_tx_qos_config() {return peer_voice_tx_qos_config;} - - void set_peer_voice_tx_codec_qos_config(CodecQosConfig &codec_qos_config) { - peer_voice_tx_codec_qos_config = codec_qos_config;} - CodecQosConfig get_peer_voice_tx_codec_qos_config() {return peer_voice_tx_codec_qos_config;} - - uint8_t SetId() const { return set_id_; } - uint8_t CigId() const { return cig_id_; } - uint8_t CisId() const { return cis_id_; } - - BtifAcmStateMachine& StateMachine() { return state_machine_; } - const BtifAcmStateMachine& StateMachine() const { return state_machine_; } - - bool IsConnected() const; - bool IsStreaming() const; - - bool CheckConnUpdateMode(uint8_t mode) const { - return (conn_mode_ == mode); - } - - void SetConnUpdateMode(uint8_t mode) { - if(conn_mode_ == mode) return; - if(mode == kFlagAggresiveMode) { - BTIF_TRACE_DEBUG("%s: push aggressive intervals", __func__); - L2CA_UpdateBleConnParams(peer_address_, 16, 32, 0, 1000); - } else if(mode == kFlagRelaxedMode) { - BTIF_TRACE_DEBUG("%s: push relaxed intervals", __func__); - L2CA_UpdateBleConnParams(peer_address_, 40, 56, 0, 1000); - } - conn_mode_ = mode; - } - - void ClearConnUpdateMode() { conn_mode_ = 0; } - - bool CheckFlags(uint8_t flags_mask) const { - return ((flags_ & flags_mask) != 0); - } - - /** - * Set only the flags as specified by the flags mask. - * - * @param flags_mask the flags to set - */ - void SetFlags(uint8_t flags_mask) { flags_ |= flags_mask; } - - /** - * Clear only the flags as specified by the flags mask. - * - * @param flags_mask the flags to clear - */ - void ClearFlags(uint8_t flags_mask) { flags_ &= ~flags_mask; } - - /** - * Clear all the flags. - */ - void ClearAllFlags() { flags_ = 0; } - - /** - * Get string for the flags set. - */ - std::string FlagsToString() const; - - private: - const RawAddress peer_address_; - const uint8_t peer_sep_;// SEP type of peer device - uint8_t set_id_, cig_id_, cis_id_; - BtifAcmStateMachine state_machine_; - uint8_t flags_; - uint8_t conn_mode_; - bool is_stereohs_type_ = false; - StreamState voice_rx_state, voice_tx_state, music_tx_state, music_rx_state; - uint16_t peer_latency_; - uint16_t context_type_ = 0; - uint16_t profile_type_ = 0; - uint16_t rcfg_profile_type_ = 0; - uint16_t preferred_context_ = 0; - uint16_t stream_context_type_ = 0; - CodecConfig peer_media_codec_config, peer_voice_rx_codec_config, peer_voice_tx_codec_config; - QosConfig peer_media_qos_config, peer_voice_rx_qos_config, peer_voice_tx_qos_config; - CodecQosConfig peer_media_codec_qos_config, peer_voice_rx_codec_qos_config, peer_voice_tx_codec_qos_config; -}; - -static void btif_acm_check_and_cancel_lock_release_timer(uint8_t setId); -bool btif_acm_request_csip_unlock(uint8_t setId); -void btif_acm_process_request(tA2DP_CTRL_CMD cmd); - -void btif_acm_source_on_stopped(); -void btif_acm_source_on_suspended(); -void btif_acm_on_idle(void); -bool btif_acm_check_if_requested_devices_stopped(); - -void btif_acm_source_cleanup(void); - -bt_status_t btif_acm_source_setup_codec(); -uint16_t btif_acm_get_active_device_latency(); - -class BtifAcmInitiator { - public: - static constexpr uint8_t kCigIdMin = 0; - static constexpr uint8_t kCigIdMax = BTA_ACM_NUM_CIGS; - static constexpr uint8_t kPeerMinSetId = BTA_ACM_MIN_NUM_SETID; - static constexpr uint8_t kPeerMaxSetId = BTA_ACM_MAX_NUM_SETID; - - enum { - kFlagStatusUnknown = 0x0, - kFlagStatusUnlocked = 0x1, - kFlagStatusPendingLock = 0x2, - kFlagStatusSubsetLocked = 0x4, - kFlagStatusLocked = 0x8, - kFlagStatusPendingUnlock = 0x10, - }; - - // acm group procedure timer - static constexpr uint64_t kTimeoutAcmGroupProcedureMs = 10 * 1000; - static constexpr uint64_t kTimeoutConnIntervalMs = 5 * 1000; - - BtifAcmInitiator() - : callbacks_(nullptr), - enabled_(false), - max_connected_peers_(kDefaultMaxConnectedAudioDevices), - music_active_setid_(INVALID_SET_ID), - voice_active_setid_(INVALID_SET_ID), - csip_app_id_(0), - is_csip_reg_(false), - lock_flags_(0), - music_set_lock_release_timer_(nullptr), - voice_set_lock_release_timer_(nullptr), - acm_group_procedure_timer_(nullptr), - acm_conn_interval_timer_(nullptr){} - ~BtifAcmInitiator(); - - bt_status_t Init( - btacm_initiator_callbacks_t* callbacks, int max_connected_audio_devices, - const std::vector& codec_priorities); - void Cleanup(); - bool IsSetIdle(uint8_t setId) const; - - btacm_initiator_callbacks_t* Callbacks() { return callbacks_; } - bool Enabled() const { return enabled_; } - - BtifAcmPeer* FindPeer(const RawAddress& peer_address); - uint8_t FindPeerSetId(const RawAddress& peer_address); - uint8_t FindPeerBySetId(uint8_t set_id); - uint8_t FindPeerCigId(uint8_t set_id); - uint8_t FindPeerByCigId(uint8_t cig_id); - uint8_t FindPeerByCisId(uint8_t cig_id, uint8_t cis_id); - BtifAcmPeer* FindOrCreatePeer(const RawAddress& peer_address); - BtifAcmPeer* FindMusicActivePeer(); - - /** - * Check whether a connection to a peer is allowed. - * The check considers the maximum number of connected peers. - * - * @param peer_address the peer address to connect to - * @return true if connection is allowed, otherwise false - */ - bool AllowedToConnect(const RawAddress& peer_address) const; - bool IsAcmIdle() const; - - bool IsOtherSetPeersIdle(const RawAddress& peer_address, uint8_t setId) const; - - alarm_t* MusicSetLockReleaseTimer() { return music_set_lock_release_timer_; } - alarm_t* VoiceSetLockReleaseTimer() { return voice_set_lock_release_timer_; } - alarm_t* AcmGroupProcedureTimer() { return acm_group_procedure_timer_; } - alarm_t* AcmConnIntervalTimer() { return acm_conn_interval_timer_; } - - /** - * Delete a peer. - * - * @param peer_address of the peer to be deleted - * @return true on success, false on failure - */ - bool DeletePeer(const RawAddress& peer_address); - - /** - * Delete all peers that are in Idle state and can be deleted. - */ - void DeleteIdlePeers(); - - /** - * Get the Music active peer. - * - * @return the music active peer - */ - const RawAddress& MusicActivePeer() const { return music_active_peer_; } - - /** - * Get the Voice active peer. - * - * @return the voice active peer - */ - const RawAddress& VoiceActivePeer() const { return voice_active_peer_; } - - uint8_t MusicActiveCSetId() const { return music_active_setid_; } - uint8_t VoiceActiveCSetId() const { return voice_active_setid_; } - - void SetCsipAppId(uint8_t csip_app_id) { csip_app_id_ = csip_app_id; } - uint8_t GetCsipAppId() const { return csip_app_id_; } - - void SetCsipRegistration(bool is_csip_reg) { is_csip_reg_ = is_csip_reg; } - bool IsCsipRegistered() const { return is_csip_reg_;} - - void SetMusicActiveGroupStarted(bool flag) { is_music_active_set_started_ = flag; } - bool IsMusicActiveGroupStarted () { return is_music_active_set_started_; } - - bool IsConnUpdateEnabled() const { - return (is_conn_update_enabled_ == true); - } - - void SetOrUpdateGroupLockStatus(uint8_t set_id, int lock_status) { - std::map::iterator p = set_lock_status_.find(set_id); - if (p == set_lock_status_.end()) { - set_lock_status_.insert(std::make_pair(set_id, lock_status)); - } else { - set_lock_status_.erase(set_id); - set_lock_status_.insert(std::make_pair(set_id, lock_status)); - } - } - - int GetGroupLockStatus(uint8_t set_id) { - auto it = set_lock_status_.find(set_id); - if (it != set_lock_status_.end()) return it->second; - return kFlagStatusUnknown; - } - - bool CheckLockFlags(uint8_t bitlockflags_mask) const { - return ((lock_flags_ & bitlockflags_mask) != 0); - } - - /** - * Set only the flags as specified by the bitlockflags_mask. - * - * @param bitlockflags_mask the lock flags to set - */ - void SetLockFlags(uint8_t bitlockflags_mask) { lock_flags_ |= bitlockflags_mask;} - - /** - * Clear only the flags as specified by the bitlockflags_mask. - * - * @param bitlockflags_mask the lock flags to clear - */ - void ClearLockFlags(uint8_t bitlockflags_mask) { lock_flags_ &= ~bitlockflags_mask;} - - /** - * Clear all lock flags. - */ - void ClearAllLockFlags() { lock_flags_ = 0;} - - /** - * Get a string for lock flags. - */ - std::string LockFlagsToString() const; - - bool SetAcmActivePeer(const RawAddress& peer_address, uint16_t contextType, uint16_t profileType, - std::promise peer_ready_promise) { - LOG(INFO) << __PRETTY_FUNCTION__ << ": peer: " << peer_address - << " music_active_peer_: " << music_active_peer_ << " voice_active_peer_: " << voice_active_peer_; - uint16_t sink_latency; - active_bda = peer_address;// for stereo LEA active_bda = peer_address - BtifAcmPeer* peer = FindPeer(peer_address); - BTIF_TRACE_DEBUG("%s address byte BDA:%02x", __func__,active_bda.address[5]); - if (contextType == CONTEXT_TYPE_MUSIC) { - if (music_active_peer_ == active_bda) { - //Same active device, profileType may have changed. - if ((peer != nullptr) && (current_active_profile_type != 0) && (current_active_profile_type != profileType)) { - BTIF_TRACE_DEBUG("%s current_active_profile_type %d, profileType %d peer->GetProfileType() %d", - __func__, current_active_profile_type, profileType, peer->GetProfileType()); - if ((peer->GetProfileType() & profileType) == 0) { - std::unique_lock guard(acm_session_wait_mutex_); - acm_session_wait = false; - if (reconfig_acm_initiator(peer_address, profileType)) { - acm_session_wait_cv.wait_for(guard, std::chrono::milliseconds(3000), []{return acm_session_wait;}); - BTIF_TRACE_EVENT("%s: done with signal",__func__); - } - } else { - current_active_profile_type = profileType; - if (current_active_profile_type != WMCP) - current_active_config = current_media_config; - else - current_active_config = current_recording_config; - if (!btif_acm_source_restart_session(music_active_peer_, active_bda)) { - // cannot set promise but need to be handled within restart_session - return false; - } - if (current_active_profile_type == WMCP) { - sink_latency = btif_acm_get_active_device_latency(); - BTIF_TRACE_EVENT("%s: sink_latency = %dms", __func__, sink_latency); - if ((sink_latency > 0) && !btif_acm_update_sink_latency_change(sink_latency * 10)) { - BTIF_TRACE_ERROR("%s: unable to update latency", __func__); - } - } - } - peer_ready_promise.set_value(); - return true; - } else { - peer_ready_promise.set_value(); - return true; - } - } - - if (active_bda.IsEmpty()) { - BTIF_TRACE_EVENT("%s: set address is empty, shutdown the Acm initiator", - __func__); - btif_acm_check_and_cancel_lock_release_timer(music_active_setid_); - if ((GetGroupLockStatus(music_active_setid_) == BtifAcmInitiator::kFlagStatusLocked) || - (GetGroupLockStatus(music_active_setid_) == BtifAcmInitiator::kFlagStatusSubsetLocked)) { - if (!btif_acm_request_csip_unlock(music_active_setid_)) { - BTIF_TRACE_ERROR("%s: error unlocking", __func__); - } - } - btif_acm_source_end_session(music_active_peer_); - music_active_peer_ = active_bda; - current_active_profile_type = 0; - memset(¤t_active_config, 0, sizeof(current_active_config)); - peer_ready_promise.set_value(); - return true; - } - - btif_acm_check_and_cancel_lock_release_timer(music_active_setid_); - if ((GetGroupLockStatus(music_active_setid_) == BtifAcmInitiator::kFlagStatusLocked) || - (GetGroupLockStatus(music_active_setid_) == BtifAcmInitiator::kFlagStatusSubsetLocked)) { - if (!btif_acm_request_csip_unlock(music_active_setid_)) { - BTIF_TRACE_ERROR("%s: error unlocking", __func__); - } - } - - /*check if previous active device is streaming, then STOP it first*/ - if (!music_active_peer_.IsEmpty()) { - int setid = music_active_setid_; - if (setid < INVALID_SET_ID) { - tBTA_CSIP_CSET cset_info; - memset(&cset_info, 0, sizeof(tBTA_CSIP_CSET)); - cset_info = BTA_CsipGetCoordinatedSet(setid); - if (cset_info.size != 0) { - std::vector::iterator itr; - BTIF_TRACE_DEBUG("%s: size of set members %d", __func__, (cset_info.set_members).size()); - if ((cset_info.set_members).size() > 0) { - for (itr =(cset_info.set_members).begin(); itr != (cset_info.set_members).end(); itr++) { - BtifAcmPeer* grp_peer = FindPeer(*itr); - if (grp_peer != nullptr && grp_peer->IsStreaming()) { - BTIF_TRACE_DEBUG("%s: peer is streaming %s ", __func__, grp_peer->PeerAddress().ToString().c_str()); - btif_acm_initiator_dispatch_sm_event(*itr, BTIF_ACM_STOP_STREAM_REQ_EVT); - } - } - } - } - } else { - BTIF_TRACE_DEBUG("%s: music_active_peer_ is twm device ", __func__); - BtifAcmPeer* twm_peer = FindPeer(music_active_peer_); - if (twm_peer != nullptr && twm_peer->IsStreaming()) { - BTIF_TRACE_DEBUG("%s: music_active_peer_ %s is streaming, send stop ", __func__, twm_peer->PeerAddress().ToString().c_str()); - btif_acm_initiator_dispatch_sm_event(music_active_peer_, BTIF_ACM_STOP_STREAM_REQ_EVT); - } - } - } - - if ((peer != nullptr) && ((peer->GetProfileType() & profileType) == 0)) { - BTIF_TRACE_DEBUG("%s peer.GetProfileType() %d, profileType %d", __func__, peer->GetProfileType(), profileType); - std::unique_lock guard(acm_session_wait_mutex_); - acm_session_wait = false; - if (reconfig_acm_initiator(peer_address, profileType)) { - acm_session_wait_cv.wait_for(guard, std::chrono::milliseconds(3000), []{return acm_session_wait;}); - BTIF_TRACE_EVENT("%s: done with signal",__func__); - } - } else { - current_active_profile_type = profileType; - if (current_active_profile_type != WMCP) - current_active_config = current_media_config; - else - current_active_config = current_recording_config; - if (!btif_acm_source_restart_session(music_active_peer_, active_bda)) { - // cannot set promise but need to be handled within restart_session - return false; - } - } - music_active_peer_ = active_bda; - if (active_bda.address[0] == 0x9E && active_bda.address[1] == 0x8B && active_bda.address[2] == 0x00) { - BTIF_TRACE_DEBUG("%s: get set ID from group BD address ", __func__); - music_active_setid_ = active_bda.address[5]; - } else { - BTIF_TRACE_DEBUG("%s: get set ID from peer data ", __func__); - if (peer != nullptr) - music_active_setid_ = peer->SetId(); - } - - if (current_active_profile_type == WMCP) { - sink_latency = btif_acm_get_active_device_latency(); - BTIF_TRACE_EVENT("%s: sink_latency = %dms", __func__, sink_latency); - if ((sink_latency > 0) && !btif_acm_update_sink_latency_change(sink_latency * 10)) { - BTIF_TRACE_ERROR("%s: unable to update latency", __func__); - } - } - peer_ready_promise.set_value(); - return true; - } else if (contextType == CONTEXT_TYPE_VOICE) { - if (voice_active_peer_ == active_bda) { - peer_ready_promise.set_value(); - return true; - } - if (active_bda.IsEmpty()) { - BTIF_TRACE_EVENT("%s: peer address is empty, shutdown the acm initiator", - __func__); - voice_active_peer_ = active_bda; - peer_ready_promise.set_value(); - return true; - } - - /*check if previous active device is streaming, then STOP it first*/ - if (!voice_active_peer_.IsEmpty()) { - int setid = voice_active_setid_; - if (setid < INVALID_SET_ID) { - tBTA_CSIP_CSET cset_info; - memset(&cset_info, 0, sizeof(tBTA_CSIP_CSET)); - cset_info = BTA_CsipGetCoordinatedSet(setid); - if (cset_info.size != 0) { - std::vector::iterator itr; - BTIF_TRACE_DEBUG("%s: size of set members %d", __func__, (cset_info.set_members).size()); - if ((cset_info.set_members).size() > 0) { - for (itr =(cset_info.set_members).begin(); itr != (cset_info.set_members).end(); itr++) { - BtifAcmPeer* grp_peer = FindPeer(*itr); - if (grp_peer != nullptr && grp_peer->IsStreaming()) { - BTIF_TRACE_DEBUG("%s: voice peer is streaming %s ", __func__, grp_peer->PeerAddress().ToString().c_str()); - btif_acm_initiator_dispatch_sm_event(*itr, BTIF_ACM_STOP_STREAM_REQ_EVT); - } - } - } - } - } else { - BTIF_TRACE_DEBUG("%s: voice_active_peer_ is twm device ", __func__); - BtifAcmPeer* twm_peer = FindPeer(voice_active_peer_); - if (twm_peer != nullptr && twm_peer->IsStreaming()) { - BTIF_TRACE_DEBUG("%s: voice_active_peer_ %s is streaming, send stop ", __func__, twm_peer->PeerAddress().ToString().c_str()); - btif_acm_initiator_dispatch_sm_event(voice_active_peer_, BTIF_ACM_STOP_STREAM_REQ_EVT); - } - } - } - - voice_active_peer_ = active_bda; - if (active_bda.address[0] == 0x9E && active_bda.address[1] == 0x8B && active_bda.address[2] == 0x00) { - BTIF_TRACE_DEBUG("%s: get set ID from group BD address ", __func__); - voice_active_setid_ = active_bda.address[5]; - } else { - BTIF_TRACE_DEBUG("%s: get set ID from peer data ", __func__); - if (peer != nullptr) - voice_active_setid_ = peer->SetId(); - } - peer_ready_promise.set_value(); - return true; - } else { - peer_ready_promise.set_value(); - return true; - } - } - - void btif_acm_initiator_encoder_user_config_update_req( - const RawAddress& peer_addr, - const std::vector& codec_user_preferences, - std::promise peer_ready_promise); - - - void UpdateCodecConfig( - const RawAddress& peer_address, - const std::vector& codec_preferences, - int contextType, - int profileType, - std::promise peer_ready_promise) { - // Restart the session if the codec for the active peer is updated - if (!peer_address.IsEmpty() && music_active_peer_ == peer_address) { - btif_acm_source_end_session(music_active_peer_); - } - - btif_acm_initiator_encoder_user_config_update_req( - peer_address, codec_preferences, std::move(peer_ready_promise)); - } - - const std::map& Peers() const { return peers_; } - // const std::map& SetPeers() const { return set_peers_; } - - std::vector locked_devices; - private: - void CleanupAllPeers(); - - btacm_initiator_callbacks_t* callbacks_; - bool enabled_; - int max_connected_peers_; - - RawAddress music_active_peer_; - RawAddress voice_active_peer_; - uint8_t music_active_setid_; - uint8_t voice_active_setid_; - uint8_t music_active_set_locked_dev_count_; - uint8_t voice_active_set_locked_dev_count_; - bool is_music_active_set_started_; - bool is_voice_active_set_started_; - bool is_conn_update_enabled_; - - uint8_t csip_app_id_; - bool is_csip_reg_; - uint8_t lock_flags_; - - alarm_t* music_set_lock_release_timer_; - alarm_t* voice_set_lock_release_timer_; - alarm_t* acm_group_procedure_timer_; - alarm_t* acm_conn_interval_timer_; - - - std::map peers_; - std::map addr_setid_pair; - std::map set_cig_pair;//setid and cig id pair - std::map > cig_cis_pair;//cig id and cis id pair - std::map set_lock_status_; -}; - - -/***************************************************************************** - * Static variables - *****************************************************************************/ -static BtifAcmInitiator btif_acm_initiator; -std::vector unicast_codecs_capabilities; -static CodecConfig acm_local_capability = - {CodecIndex::CODEC_INDEX_SOURCE_LC3, - CodecPriority::CODEC_PRIORITY_DEFAULT, - CodecSampleRate::CODEC_SAMPLE_RATE_48000, - CodecBPS::CODEC_BITS_PER_SAMPLE_24, - CodecChannelMode::CODEC_CHANNEL_MODE_STEREO, 0, 0, 0, 0}; -static CodecConfig default_config; -static bool mandatory_codec_selected = false; -static bt_status_t disconnect_acm_initiator(const RawAddress& peer_address, - uint16_t contextType); - -static bt_status_t start_stream_acm_initiator(const RawAddress& peer_address, - uint16_t contextType); -static bt_status_t stop_stream_acm_initiator(const RawAddress& peer_address, - uint16_t contextType); - -static void btif_acm_handle_csip_status_locked(std::vector addr, uint8_t setId); - -static void btif_acm_handle_evt(uint16_t event, char* p_param); -static void btif_report_connection_state(const RawAddress& peer_address, - btacm_connection_state_t state, uint16_t contextType); -static void btif_report_audio_state(const RawAddress& peer_address, - btacm_audio_state_t state, uint16_t contextType); - -static void btif_acm_check_and_start_lock_release_timer(uint8_t setId); - -static void btif_acm_initiator_lock_release_timer_timeout(void* data); - -static void btif_acm_check_and_start_group_procedure_timer(uint8_t setId); -static void btif_acm_check_and_start_conn_Interval_timer(BtifAcmPeer* peer); -static void btif_acm_initiator_conn_Interval_timer_timeout(void *data); -static void btif_acm_check_and_cancel_conn_Interval_timer(); - - -static void btif_acm_check_and_cancel_group_procedure_timer(uint8_t setId); -static void btif_acm_initiator_group_procedure_timer_timeout(void *data); -static void SelectCodecQosConfig(const RawAddress& bd_addr, int profile_type, - int context_type, int direction, int config_type); -bool compare_codec_config_(CodecConfig &first, CodecConfig &second); -void print_codec_parameters(CodecConfig config); -void print_qos_parameters(QosConfig qos_config); -void select_best_codec_config(const RawAddress& bd_addr, uint16_t context_type, - uint8_t profile_type, CodecConfig *codec_config, int dir, int config_type); -static UcastClientInterface* sUcastClientInterface = nullptr; - -/***************************************************************************** - * Local helper functions - *****************************************************************************/ - -const char* dump_acm_sm_event_name(btif_acm_sm_event_t event) { - switch ((int)event) { - CASE_RETURN_STR(BTA_ACM_DISCONNECT_EVT) - CASE_RETURN_STR(BTA_ACM_CONNECT_EVT) - CASE_RETURN_STR(BTA_ACM_START_EVT) - CASE_RETURN_STR(BTA_ACM_STOP_EVT) - CASE_RETURN_STR(BTA_ACM_RECONFIG_EVT) - CASE_RETURN_STR(BTA_ACM_CONFIG_EVT) - CASE_RETURN_STR(BTIF_ACM_CONNECT_REQ_EVT) - CASE_RETURN_STR(BTIF_ACM_DISCONNECT_REQ_EVT) - CASE_RETURN_STR(BTIF_ACM_START_STREAM_REQ_EVT) - CASE_RETURN_STR(BTIF_ACM_STOP_STREAM_REQ_EVT) - CASE_RETURN_STR(BTIF_ACM_SUSPEND_STREAM_REQ_EVT) - CASE_RETURN_STR(BTIF_ACM_RECONFIG_REQ_EVT) - CASE_RETURN_STR(BTA_ACM_CONN_UPDATE_TIMEOUT_EVT) - default: - return "UNKNOWN_EVENT"; - } -} - -const char* dump_csip_event_name(btif_csip_sm_event_t event) { - switch ((int)event) { - CASE_RETURN_STR(BTA_CSIP_NEW_SET_FOUND_EVT) - CASE_RETURN_STR(BTA_CSIP_SET_MEMBER_FOUND_EVT) - CASE_RETURN_STR(BTA_CSIP_CONN_STATE_CHG_EVT) - CASE_RETURN_STR(BTA_CSIP_LOCK_STATUS_CHANGED_EVT) - CASE_RETURN_STR(BTA_CSIP_LOCK_AVAILABLE_EVT) - CASE_RETURN_STR(BTA_CSIP_SET_SIZE_CHANGED) - CASE_RETURN_STR(BTA_CSIP_SET_SIRK_CHANGED) - default: - return "UNKNOWN_EVENT"; - } -} - -void btif_acm_signal_session_ready() { - std::unique_lock guard(acm_session_wait_mutex_); - if(!acm_session_wait) { - acm_session_wait = true; - acm_session_wait_cv.notify_all(); - } else { - BTIF_TRACE_WARNING("%s: already signalled ",__func__); - } -} - -void fetch_media_tx_codec_qos_config(const RawAddress& bd_addr, int profile_type, StreamConnect *conn_media) { - BTIF_TRACE_DEBUG("%s: Peer %s , profile_type: %d", __func__, bd_addr.ToString().c_str(), profile_type); - CodecQosConfig conf; - BtifAcmPeer* peer = btif_acm_initiator.FindPeer(bd_addr); - if (peer == nullptr) { - BTIF_TRACE_WARNING("%s: peer is NULL", __func__); - return; - } - if (peer->IsStereoHsType()) { - //Stereo HS config 1 - SelectCodecQosConfig(peer->PeerAddress(), profile_type, MEDIA_CONTEXT, SNK, STEREO_HS_CONFIG_1); - conf = peer->get_peer_media_codec_qos_config(); - print_codec_parameters(conf.codec_config); - print_qos_parameters(conf.qos_config); - conn_media->codec_qos_config_pair.push_back(conf); - } else { - //EB config - SelectCodecQosConfig(peer->PeerAddress(), profile_type, MEDIA_CONTEXT, SNK, EB_CONFIG); - conf = peer->get_peer_media_codec_qos_config(); - print_codec_parameters(conf.codec_config); - print_qos_parameters(conf.qos_config); - conn_media->codec_qos_config_pair.push_back(conf); - } - conn_media->stream_type.type = CONTENT_TYPE_MEDIA; - conn_media->stream_type.audio_context = CONTENT_TYPE_MEDIA; - conn_media->stream_type.direction = ASE_DIRECTION_SINK; -} - -void fetch_media_rx_codec_qos_config(const RawAddress& bd_addr, int profile_type, StreamConnect *conn_media) { - BTIF_TRACE_DEBUG("%s: Peer %s , profile_type: %d", __func__, bd_addr.ToString().c_str(), profile_type); - CodecQosConfig conf; - BtifAcmPeer* peer = btif_acm_initiator.FindPeer(bd_addr); - if (peer == nullptr) { - BTIF_TRACE_WARNING("%s: peer is NULL", __func__); - return; - } - if (peer->IsStereoHsType()) { - //Stereo HS config 1 - SelectCodecQosConfig(peer->PeerAddress(), WMCP, MEDIA_CONTEXT, SRC, STEREO_HS_CONFIG_1); - conf = peer->get_peer_media_codec_qos_config(); - print_codec_parameters(conf.codec_config); - print_qos_parameters(conf.qos_config); - conn_media->codec_qos_config_pair.push_back(conf); - } else { - //EB config - SelectCodecQosConfig(peer->PeerAddress(), WMCP, MEDIA_CONTEXT, SRC, EB_CONFIG); - conf = peer->get_peer_media_codec_qos_config(); - print_codec_parameters(conf.codec_config); - print_qos_parameters(conf.qos_config); - conn_media->codec_qos_config_pair.push_back(conf); - } - conn_media->stream_type.type = CONTENT_TYPE_MEDIA; - conn_media->stream_type.audio_context = CONTENT_TYPE_LIVE; //Live audio context - conn_media->stream_type.direction = ASE_DIRECTION_SRC; -} - -void fetch_voice_rx_codec_qos_config(const RawAddress& bd_addr, int profile_type, StreamConnect *conn_voice) { - BTIF_TRACE_DEBUG("%s: Peer %s , profile_type: %d", __func__, bd_addr.ToString().c_str(), profile_type); - CodecQosConfig conf; - BtifAcmPeer* peer = btif_acm_initiator.FindPeer(bd_addr); - if (peer == nullptr) { - BTIF_TRACE_WARNING("%s: peer is NULL", __func__); - return; - } - if (peer->IsStereoHsType()) { - //Stereo HS config 1 - SelectCodecQosConfig(peer->PeerAddress(), BAP, VOICE_CONTEXT, SRC, STEREO_HS_CONFIG_1); - conf = peer->get_peer_voice_rx_codec_qos_config(); - print_codec_parameters(conf.codec_config); - print_qos_parameters(conf.qos_config); - conn_voice->codec_qos_config_pair.push_back(conf); - } else { - // EB config - SelectCodecQosConfig(peer->PeerAddress(), BAP, VOICE_CONTEXT, SRC, EB_CONFIG); - conf = peer->get_peer_voice_rx_codec_qos_config(); - print_codec_parameters(conf.codec_config); - print_qos_parameters(conf.qos_config); - conn_voice->codec_qos_config_pair.push_back(conf); - } - conn_voice->stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - conn_voice->stream_type.audio_context = CONTENT_TYPE_CONVERSATIONAL; - conn_voice->stream_type.direction = ASE_DIRECTION_SRC; -} - -void fetch_voice_tx_codec_qos_config(const RawAddress& bd_addr, int profile_type, StreamConnect *conn_voice) { - BTIF_TRACE_DEBUG("%s: Peer %s , profile_type: %d", __func__, bd_addr.ToString().c_str(), profile_type); - CodecQosConfig conf; - BtifAcmPeer* peer = btif_acm_initiator.FindPeer(bd_addr); - if (peer == nullptr) { - BTIF_TRACE_WARNING("%s: peer is NULL", __func__); - return; - } - if (peer->IsStereoHsType()) { - //Stereo HS config 1 - SelectCodecQosConfig(peer->PeerAddress(), BAP, VOICE_CONTEXT, SNK, STEREO_HS_CONFIG_1); - conf = peer->get_peer_voice_tx_codec_qos_config(); - print_codec_parameters(conf.codec_config); - print_qos_parameters(conf.qos_config); - conn_voice->codec_qos_config_pair.push_back(conf); - } else { - // EB config - SelectCodecQosConfig(peer->PeerAddress(), BAP, VOICE_CONTEXT, SNK, EB_CONFIG); - conf = peer->get_peer_voice_tx_codec_qos_config(); - print_codec_parameters(conf.codec_config); - print_qos_parameters(conf.qos_config); - conn_voice->codec_qos_config_pair.push_back(conf); - } - conn_voice->stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - conn_voice->stream_type.audio_context = CONTENT_TYPE_CONVERSATIONAL; - conn_voice->stream_type.direction = ASE_DIRECTION_SINK; -} - -BtifAcmEvent::BtifAcmEvent(uint32_t event, const void* p_data, size_t data_length) - : event_(event), data_(nullptr), data_length_(0) { - DeepCopy(event, p_data, data_length); -} - -BtifAcmEvent::BtifAcmEvent(const BtifAcmEvent& other) - : event_(0), data_(nullptr), data_length_(0) { - *this = other; -} - -BtifAcmEvent& BtifAcmEvent::operator=(const BtifAcmEvent& other) { - DeepFree(); - DeepCopy(other.Event(), other.Data(), other.DataLength()); - return *this; -} - -BtifAcmEvent::~BtifAcmEvent() { DeepFree(); } - -std::string BtifAcmEvent::ToString() const { - return BtifAcmEvent::EventName(event_); -} - -std::string BtifAcmEvent::EventName(uint32_t event) { - std::string name = dump_acm_sm_event_name((btif_acm_sm_event_t)event); - std::stringstream ss_value; - ss_value << "(0x" << std::hex << event << ")"; - return name + ss_value.str(); -} - -void BtifAcmEvent::DeepCopy(uint32_t event, const void* p_data, - size_t data_length) { - event_ = event; - data_length_ = data_length; - if (data_length == 0) { - data_ = nullptr; - } else { - data_ = osi_malloc(data_length_); - memcpy(data_, p_data, data_length); - } -} - -void BtifAcmEvent::DeepFree() { - osi_free_and_reset((void**)&data_); - data_length_ = 0; -} - -BtifCsipEvent::BtifCsipEvent(uint32_t event, const void* p_data, size_t data_length) - : event_(event), data_(nullptr), data_length_(0) { - DeepCopy(event, p_data, data_length); -} - -BtifCsipEvent::BtifCsipEvent(const BtifCsipEvent& other) - : event_(0), data_(nullptr), data_length_(0) { - *this = other; -} - -BtifCsipEvent& BtifCsipEvent::operator=(const BtifCsipEvent& other) { - DeepFree(); - DeepCopy(other.Event(), other.Data(), other.DataLength()); - return *this; -} - -BtifCsipEvent::~BtifCsipEvent() { DeepFree(); } - -std::string BtifCsipEvent::ToString() const { - return BtifCsipEvent::EventName(event_); -} - -std::string BtifCsipEvent::EventName(uint32_t event) { - std::string name = dump_csip_event_name((btif_csip_sm_event_t)event); - std::stringstream ss_value; - ss_value << "(0x" << std::hex << event << ")"; - return name + ss_value.str(); -} - -void BtifCsipEvent::DeepCopy(uint32_t event, const void* p_data, - size_t data_length) { - event_ = event; - data_length_ = data_length; - if (data_length == 0) { - data_ = nullptr; - } else { - data_ = osi_malloc(data_length_); - memcpy(data_, p_data, data_length); - } -} - -void BtifCsipEvent::DeepFree() { - osi_free_and_reset((void**)&data_); - data_length_ = 0; -} - -BtifAcmPeer::BtifAcmPeer(const RawAddress& peer_address, uint8_t peer_sep, - uint8_t set_id, uint8_t cig_id, uint8_t cis_id) - : peer_address_(peer_address), - peer_sep_(peer_sep), - set_id_(set_id), - cig_id_(cig_id), - cis_id_(cis_id), - state_machine_(*this), - flags_(0) {} - -BtifAcmPeer::~BtifAcmPeer() { /*alarm_free(av_open_on_rc_timer_);*/ } - -std::string BtifAcmPeer::FlagsToString() const { - std::string result; - - if (flags_ & BtifAcmPeer::kFlagPendingLocalSuspend) { - if (!result.empty()) result += "|"; - result += "LOCAL_SUSPEND_PENDING"; - } - if (flags_ & BtifAcmPeer::kFlagPendingReconfigure) { - if (!result.empty()) result += "|"; - result += "PENDING_RECONFIGURE"; - } - if (flags_ & BtifAcmPeer::kFlagPendingStart) { - if (!result.empty()) result += "|"; - result += "PENDING_START"; - } - if (flags_ & BtifAcmPeer::kFlagPendingStop) { - if (!result.empty()) result += "|"; - result += "PENDING_STOP"; - } - if (flags_ & BtifAcmPeer::kFLagPendingStartAfterReconfig) { - if (!result.empty()) result += "|"; - result += "PENDING_START_AFTER_RECONFIG"; - } - if (result.empty()) result = "None"; - - return base::StringPrintf("0x%x(%s)", flags_, result.c_str()); -} - -bt_status_t BtifAcmPeer::Init() { - state_machine_.Start(); - return BT_STATUS_SUCCESS; -} - -void BtifAcmPeer::Cleanup() { - state_machine_.Quit(); -} - -bool BtifAcmPeer::CanBeDeleted() const { - return ( - (state_machine_.StateId() == BtifAcmStateMachine::kStateIdle) && - (state_machine_.PreviousStateId() != BtifAcmStateMachine::kStateInvalid)); -} - -const RawAddress& BtifAcmPeer::MusicActivePeerAddress() const { - return btif_acm_initiator.MusicActivePeer(); -} -const RawAddress& BtifAcmPeer::VoiceActivePeerAddress() const { - return btif_acm_initiator.VoiceActivePeer(); -} -uint8_t BtifAcmPeer::MusicActiveSetId() const { - return btif_acm_initiator.MusicActiveCSetId(); -} -uint8_t BtifAcmPeer::VoiceActiveSetId() const { - return btif_acm_initiator.VoiceActiveCSetId(); -} - -bool BtifAcmPeer::IsConnected() const { - int state = state_machine_.StateId(); - return ((state == BtifAcmStateMachine::kStateOpened) || - (state == BtifAcmStateMachine::kStateStarted)); -} - -bool BtifAcmPeer::IsStreaming() const { - int state = state_machine_.StateId(); - return (state == BtifAcmStateMachine::kStateStarted); -} - -BtifAcmInitiator::~BtifAcmInitiator() { - CleanupAllPeers(); -} - -void init_local_capabilities() { - unicast_codecs_capabilities.push_back(acm_local_capability); -} - -void BtifAcmInitiator::Cleanup() { - LOG_INFO(LOG_TAG, "%s", __PRETTY_FUNCTION__); - if (!enabled_) return; - std::promise peer_ready_promise; - btif_disable_service(BTA_ACM_INITIATOR_SERVICE_ID); // ACM deregistration required? - CleanupAllPeers(); - alarm_free(music_set_lock_release_timer_); - music_set_lock_release_timer_ = nullptr; - alarm_free(music_set_lock_release_timer_); - music_set_lock_release_timer_ = nullptr; - alarm_free(acm_group_procedure_timer_); - acm_group_procedure_timer_ = nullptr; - alarm_free(acm_conn_interval_timer_); - acm_conn_interval_timer_ = nullptr; - callbacks_ = nullptr; - enabled_ = false; - if (sUcastClientInterface != nullptr) { - sUcastClientInterface->Cleanup(); - sUcastClientInterface = nullptr; - } -} - -BtifAcmPeer* BtifAcmInitiator::FindPeer(const RawAddress& peer_address) { - auto it = peers_.find(peer_address); - if (it != peers_.end()) return it->second; - return nullptr; -} - -uint8_t BtifAcmInitiator:: FindPeerSetId(const RawAddress& peer_address) { - auto it = addr_setid_pair.find(peer_address); - if (it != addr_setid_pair.end()) return it->second; - return 0xff; -} - -uint8_t BtifAcmInitiator:: FindPeerBySetId(uint8_t setid) { - for (auto it : addr_setid_pair) { - if (it.second == setid) { - return setid; - } - } - return 0xff; -} - -uint8_t BtifAcmInitiator:: FindPeerCigId(uint8_t setid) { - auto it = set_cig_pair.find(setid); - if (it != set_cig_pair.end()) return it->second; - return 0xff; -} - -uint8_t BtifAcmInitiator:: FindPeerByCigId(uint8_t cigid) { - for (auto it : set_cig_pair) { - if (it.second == cigid) { - return cigid; - } - } - return 0xff; -} - -uint8_t BtifAcmInitiator:: FindPeerByCisId(uint8_t cigid, uint8_t cisid) { - for (auto itr = cig_cis_pair.begin(); itr != cig_cis_pair.end(); itr++) { - for (auto ptr = itr->second.begin(); ptr != itr->second.end(); ptr++) { - if (ptr->first == cigid) { - if (ptr->second == cisid) { - return cisid; - } - } - } - } - return 0xff; -} - -BtifAcmPeer* BtifAcmInitiator::FindOrCreatePeer(const RawAddress& peer_address) { - BTIF_TRACE_DEBUG("%s: peer_address=%s ", __PRETTY_FUNCTION__, - peer_address.ToString().c_str()); - - BtifAcmPeer* peer = FindPeer(peer_address); - if (peer != nullptr) return peer; - - uint8_t SetId, CigId, CisId; - //get the set id from CSIP. - //TODO: need UUID ? - Uuid uuid = Uuid::kEmpty; - LOG_INFO(LOG_TAG, "%s ACM UUID = %s", __func__, uuid.ToString().c_str()); - SetId = BTA_CsipGetDeviceSetId(peer_address, uuid); - BTIF_TRACE_EVENT("%s: set id from csip : %d", __func__, SetId); - if (SetId == INVALID_SET_ID) { - SetId = FindPeerSetId(peer_address); - // Find next available SET ID to use - if (SetId == 0xff) { - for (SetId = kPeerMinSetId; SetId < kPeerMaxSetId; SetId++) { - if (FindPeerBySetId(SetId) == 0xff) break; - } - } - } - if (SetId == kPeerMaxSetId) { - BTIF_TRACE_ERROR( - "%s: Cannot create peer for peer_address=%s : " - "cannot allocate unique SET ID", - __PRETTY_FUNCTION__, peer_address.ToString().c_str()); - return nullptr; - } - addr_setid_pair.insert(std::make_pair(peer_address, SetId)); - - //Find next available CIG ID to use - CigId = FindPeerCigId(SetId); - if (CigId == 0xff) { - for (CigId = kCigIdMin; CigId < kCigIdMax; ) { - if (FindPeerByCigId(CigId) == 0xff) break; - CigId += 4; - } - } - if (CigId == kCigIdMax) { - BTIF_TRACE_ERROR( - "%s: cannot allocate unique CIG ID to = %s ", - __func__, peer_address.ToString().c_str()); - return nullptr; - } - set_cig_pair.insert(std::make_pair(SetId, CigId)); - - //Find next available CIS ID to use - for (CisId = kCigIdMin; CisId < kCigIdMax; CisId++) { - if (FindPeerByCisId(CigId, CisId) == 0xff) break; - } - if (CisId == kCigIdMax) { - BTIF_TRACE_ERROR( - "%s: cannot allocate unique CIS ID to = %s ", - __func__, peer_address.ToString().c_str()); - return nullptr; - } - cig_cis_pair.insert(std::make_pair(peer_address, map())); - cig_cis_pair[peer_address].insert(std::make_pair(CigId, CisId)); - - LOG_INFO(LOG_TAG, - "%s: Create peer: peer_address=%s, set_id=%d, cig_id=%d, cis_id=%d", - __PRETTY_FUNCTION__, peer_address.ToString().c_str(), SetId, CigId, CisId); - peer = new BtifAcmPeer(peer_address, ACM_TSEP_SNK, SetId, CigId, CisId); - peer->SetPeerVoiceTxState(StreamState::DISCONNECTED); - peer->SetPeerVoiceRxState(StreamState::DISCONNECTED); - peer->SetPeerMusicTxState(StreamState::DISCONNECTED); - peer->SetPeerMusicRxState(StreamState::DISCONNECTED); - if (SetId >= kPeerMinSetId && SetId < kPeerMaxSetId) { - LOG_INFO(LOG_TAG, - "%s: Created peer is TWM device",__PRETTY_FUNCTION__); - peer->SetIsStereoHsType(true); - } - peers_.insert(std::make_pair(peer_address, peer)); - peer->Init(); - return peer; -} - -BtifAcmPeer* BtifAcmInitiator::FindMusicActivePeer() { - for (auto it : peers_) { - BtifAcmPeer* peer = it.second; - if (peer->IsPeerActiveForMusic()) { - return peer; - } - } - return nullptr; -} - -bool BtifAcmInitiator::AllowedToConnect(const RawAddress& peer_address) const { - int connected = 0; - - // Count peers that are in the process of connecting or already connected - for (auto it : peers_) { - const BtifAcmPeer* peer = it.second; - switch (peer->StateMachine().StateId()) { - case BtifAcmStateMachine::kStateOpening: - case BtifAcmStateMachine::kStateOpened: - case BtifAcmStateMachine::kStateStarted: - case BtifAcmStateMachine::kStateReconfiguring: - if (peer->PeerAddress() == peer_address) { - return true; // Already connected or accounted for - } - connected++; - break; - default: - break; - } - } - return (connected < max_connected_peers_); -} - -bool BtifAcmInitiator::IsAcmIdle() const { - int connected = 0; - - // Count peers that are in the process of connecting or already connected - for (auto it : peers_) { - const BtifAcmPeer* peer = it.second; - switch (peer->StateMachine().StateId()) { - case BtifAcmStateMachine::kStateOpening: - case BtifAcmStateMachine::kStateOpened: - case BtifAcmStateMachine::kStateStarted: - case BtifAcmStateMachine::kStateReconfiguring: - case BtifAcmStateMachine::kStateClosing: - connected++; - break; - default: - break; - } - } - return (connected == 0); -} - -bool BtifAcmInitiator::IsSetIdle(uint8_t setId) const { - int connected = 0; - tBTA_CSIP_CSET cset_info = BTA_CsipGetCoordinatedSet(setId); - std::vector::iterator itr; - if ((cset_info.set_members).size() > 0) { - for (itr = (cset_info.set_members).begin(); itr != (cset_info.set_members).end(); itr++) { - BtifAcmPeer* peer = btif_acm_initiator.FindPeer(*itr); - switch (peer->StateMachine().StateId()) { - case BtifAcmStateMachine::kStateOpening: - case BtifAcmStateMachine::kStateOpened: - case BtifAcmStateMachine::kStateStarted: - case BtifAcmStateMachine::kStateReconfiguring: - case BtifAcmStateMachine::kStateClosing: - connected++; - break; - default: - break; - } - } - } - return (connected == 0); -} - -bool BtifAcmInitiator::IsOtherSetPeersIdle(const RawAddress& peer_address, uint8_t setId) const { - int connected = 0; - tBTA_CSIP_CSET cset_info = BTA_CsipGetCoordinatedSet(setId); - std::vector::iterator itr; - if ((cset_info.set_members).size() > 0) { - for (itr = (cset_info.set_members).begin(); itr != (cset_info.set_members).end(); itr++) { - if (*itr == peer_address) continue; - BtifAcmPeer* peer = btif_acm_initiator.FindPeer(*itr); - if (peer == nullptr) continue; - switch (peer->StateMachine().StateId()) { - case BtifAcmStateMachine::kStateOpening: - case BtifAcmStateMachine::kStateOpened: - case BtifAcmStateMachine::kStateStarted: - case BtifAcmStateMachine::kStateReconfiguring: - case BtifAcmStateMachine::kStateClosing: - connected++; - break; - default: - break; - } - } - } - return (connected == 0); -} - -bool BtifAcmInitiator::DeletePeer(const RawAddress& peer_address) { - auto it = peers_.find(peer_address); - if (it == peers_.end()) return false; - BtifAcmPeer* peer = it->second; - for (auto itr = addr_setid_pair.begin(); itr != addr_setid_pair.end(); ++itr) { - if (itr->second == peer->SetId()) { - addr_setid_pair.erase(itr); - break; - } - } - for (auto itr = set_cig_pair.begin(); itr != set_cig_pair.end(); ++itr) { - if (itr->second == peer->SetId()) { - set_cig_pair.erase(itr); - break; - } - } - bool found = false; - for (auto itr = cig_cis_pair.begin(); itr != cig_cis_pair.end(); itr++) { - for (auto ptr = itr->second.begin(); ptr != itr->second.end(); ptr++) { - if (ptr->first == peer->CigId()) { - if (ptr->second == peer->CisId()) { - cig_cis_pair.erase(itr); - found = true; - break; - } - } - } - if (found) - break; - } - peer->Cleanup(); - peers_.erase(it); - delete peer; - return true; -} - -void BtifAcmInitiator::DeleteIdlePeers() { - for (auto it = peers_.begin(); it != peers_.end();) { - BtifAcmPeer* peer = it->second; - auto prev_it = it++; - if (!peer->CanBeDeleted()) continue; - LOG_INFO(LOG_TAG, "%s: Deleting idle peer: %s ", __func__, - peer->PeerAddress().ToString().c_str()); - for (auto itr = addr_setid_pair.begin(); itr != addr_setid_pair.end(); ++itr) { - if (itr->second == peer->SetId()) { - addr_setid_pair.erase(itr); - break; - } - } - for (auto itr = set_cig_pair.begin(); itr != set_cig_pair.end(); ++itr) { - if (itr->second == peer->SetId()) { - set_cig_pair.erase(itr); - break; - } - } - bool found = false; - for (auto itr = cig_cis_pair.begin(); itr != cig_cis_pair.end(); itr++) { - for (auto ptr = itr->second.begin(); ptr != itr->second.end(); ptr++) { - if (ptr->first == peer->CigId()) { - if (ptr->second == peer->CisId()) { - cig_cis_pair.erase(itr); - found = true; - break; - } - } - } - if (found) - break; - } - peer->Cleanup(); - peers_.erase(prev_it); - delete peer; - } -} - -void BtifAcmInitiator::CleanupAllPeers() { - while (!peers_.empty()) { - auto it = peers_.begin(); - BtifAcmPeer* peer = it->second; - for (auto itr = addr_setid_pair.begin(); itr != addr_setid_pair.end(); ++itr) { - if (itr->second == peer->SetId()) { - addr_setid_pair.erase(itr); - break; - } - } - for (auto itr = set_cig_pair.begin(); itr != set_cig_pair.end(); ++itr) { - if (itr->second == peer->SetId()) { - set_cig_pair.erase(itr); - break; - } - } - bool found = false; - for (auto itr = cig_cis_pair.begin(); itr != cig_cis_pair.end(); itr++) { - for (auto ptr = itr->second.begin(); ptr != itr->second.end(); ptr++) { - if (ptr->first == peer->CigId()) { - if (ptr->second == peer->CisId()) { - cig_cis_pair.erase(itr); - found = true; - break; - } - } - } - if (found) - break; - } - peer->Cleanup(); - peers_.erase(it); - delete peer; - } -} - -class UcastClientCallbacksImpl : public UcastClientCallbacks { - public: - ~UcastClientCallbacksImpl() = default; - void OnStreamState(const RawAddress& address, - std::vector streams_state_info) override { - LOG(INFO) << __func__; - BtifAcmPeer* peer = btif_acm_initiator.FindPeer(address); - if (peer == nullptr) { - BTIF_TRACE_DEBUG("%s: Peer is NULL", __PRETTY_FUNCTION__); - } - for (auto it = streams_state_info.begin(); it != streams_state_info.end(); ++it) { - LOG(WARNING) << __func__ << ": address: " << address; - LOG(WARNING) << __func__ << ": stream type: " - << GetStreamType(it->stream_type.type); - LOG(WARNING) << __func__ << ": stream context: " - << GetStreamType(it->stream_type.audio_context); - LOG(WARNING) << __func__ << ": stream dir: " - << GetStreamDirection(it->stream_type.direction); - LOG(WARNING) << __func__ << ": stream state: " - << GetStreamState(static_cast (it->stream_state)); - switch (it->stream_state) { - case StreamState::DISCONNECTED: - case StreamState::DISCONNECTING: { - tBTA_ACM_STATE_INFO data = {.bd_addr = address, .stream_type = it->stream_type, - .stream_state = it->stream_state, .reason = it->reason}; - btif_acm_handle_evt(BTA_ACM_DISCONNECT_EVT, (char*)&data); - } break; - - case StreamState::CONNECTING: - case StreamState::CONNECTED: { - tBTA_ACM_STATE_INFO data = {.bd_addr = address, .stream_type = it->stream_type, - .stream_state = it->stream_state, .reason = it->reason}; - btif_acm_handle_evt(BTA_ACM_CONNECT_EVT, (char*)&data); - } break; - - case StreamState::STARTING: - case StreamState::STREAMING: { - tBTA_ACM_STATE_INFO data = {.bd_addr = address, .stream_type = it->stream_type, - .stream_state = it->stream_state, .reason = it->reason}; - btif_acm_handle_evt(BTA_ACM_START_EVT, (char*)&data); - } break; - - case StreamState::STOPPING: { - tBTA_ACM_STATE_INFO data = {.bd_addr = address, .stream_type = it->stream_type, - .stream_state = it->stream_state, .reason = it->reason}; - btif_acm_handle_evt(BTA_ACM_STOP_EVT, (char*)&data); - } break; - - case StreamState::RECONFIGURING: { - tBTA_ACM_STATE_INFO data = {.bd_addr = address, .stream_type = it->stream_type, - .stream_state = it->stream_state, .reason = it->reason}; - btif_acm_handle_evt(BTA_ACM_RECONFIG_EVT, (char*)&data); - } break; - default: - break; - } - } - } - - void OnStreamConfig(const RawAddress& address, - std::vector streams_config_info) override { - LOG(INFO) << __func__; - BtifAcmPeer* peer = btif_acm_initiator.FindPeer(address); - if (peer == nullptr) { - BTIF_TRACE_DEBUG("%s: Peer is NULL", __PRETTY_FUNCTION__); - } - for (auto it = streams_config_info.begin(); it != streams_config_info.end(); ++it) { - tBTA_ACM_CONFIG_INFO data = {.bd_addr = address, .stream_type = it->stream_type, - .codec_config = it->codec_config, .audio_location = it->audio_location, - .qos_config = it->qos_config, .codecs_selectable = it->codecs_selectable}; - btif_acm_handle_evt(BTA_ACM_CONFIG_EVT, (char*)&data); - } - } - - void OnStreamAvailable(const RawAddress& bd_addr, uint16_t src_audio_contexts, - uint16_t sink_audio_contexts) override { - LOG(INFO) << __func__; - //Need to use during START of src and sink audio context - BTIF_TRACE_DEBUG("%s: Peer %s, src_audio_context: 0x%x, sink_audio_contexts: 0x%x", - __func__, - bd_addr.ToString().c_str(), src_audio_contexts, sink_audio_contexts); - } - - const char* GetStreamType(uint16_t stream_type) { - switch (stream_type) { - CASE_RETURN_STR(CONTENT_TYPE_UNSPECIFIED) - CASE_RETURN_STR(CONTENT_TYPE_CONVERSATIONAL) - CASE_RETURN_STR(CONTENT_TYPE_MEDIA) - CASE_RETURN_STR(CONTENT_TYPE_INSTRUCTIONAL) - CASE_RETURN_STR(CONTENT_TYPE_NOTIFICATIONS) - CASE_RETURN_STR(CONTENT_TYPE_ALERT) - CASE_RETURN_STR(CONTENT_TYPE_MAN_MACHINE) - CASE_RETURN_STR(CONTENT_TYPE_EMERGENCY) - CASE_RETURN_STR(CONTENT_TYPE_RINGTONE) - CASE_RETURN_STR(CONTENT_TYPE_SOUND_EFFECTS) - CASE_RETURN_STR(CONTENT_TYPE_LIVE) - CASE_RETURN_STR(CONTENT_TYPE_GAME) - default: - return "Unknown StreamType"; - } - } - - const char* GetStreamDirection(uint8_t event) { - switch (event) { - CASE_RETURN_STR(ASE_DIRECTION_SINK) - CASE_RETURN_STR(ASE_DIRECTION_SRC) - default: - return "Unknown StreamDirection"; - } - } - - const char* GetStreamState(uint8_t event) { - switch (event) { - CASE_RETURN_STR(STREAM_STATE_DISCONNECTED) - CASE_RETURN_STR(STREAM_STATE_CONNECTING) - CASE_RETURN_STR(STREAM_STATE_CONNECTED) - CASE_RETURN_STR(STREAM_STATE_STARTING) - CASE_RETURN_STR(STREAM_STATE_STREAMING) - CASE_RETURN_STR(STREAM_STATE_STOPPING) - CASE_RETURN_STR(STREAM_STATE_DISCONNECTING) - CASE_RETURN_STR(STREAM_STATE_RECONFIGURING) - default: - return "Unknown StreamState"; - } - } -}; - -static UcastClientCallbacksImpl sUcastClientCallbacks; - -bt_status_t BtifAcmInitiator::Init( - btacm_initiator_callbacks_t* callbacks, int max_connected_acceptors, - const std::vector& codec_priorities) { - LOG_INFO(LOG_TAG, "%s: max_connected_acceptors=%d", __PRETTY_FUNCTION__, - max_connected_acceptors); - if (enabled_) return BT_STATUS_SUCCESS; - CleanupAllPeers(); - max_connected_peers_ = max_connected_acceptors; - alarm_free(music_set_lock_release_timer_); - alarm_free(voice_set_lock_release_timer_); - alarm_free(acm_group_procedure_timer_); - alarm_free(acm_conn_interval_timer_); - music_set_lock_release_timer_ = alarm_new("btif_acm_initiator.music_set_lock_release_timer"); - voice_set_lock_release_timer_ = alarm_new("btif_acm_initiator.voice_set_lock_release_timer"); - acm_group_procedure_timer_ = alarm_new("btif_acm_initiator.acm_group_procedure_timer"); - acm_conn_interval_timer_ = alarm_new("btif_acm_initiator.acm_conn_interval_timer"); - - callbacks_ = callbacks; - //init local capabilties - init_local_capabilities(); - - // register ACM with AHIM - btif_register_cb(); - - btif_vmcp_init(); - bt_status_t status1 = btif_acm_initiator_execute_service(true); - if (status1 == BT_STATUS_SUCCESS) { - BTIF_TRACE_EVENT("%s: status success", __func__); - } - if (sUcastClientInterface != nullptr) { - LOG_INFO(LOG_TAG, "%s Cleaning up BAP client Interface before initializing...", - __PRETTY_FUNCTION__); - sUcastClientInterface->Cleanup(); - sUcastClientInterface = nullptr; - } - sUcastClientInterface = bluetooth::bap::ucast::btif_bap_uclient_get_interface(); - - - if (sUcastClientInterface == nullptr) { - LOG_ERROR(LOG_TAG, "%s Failed to get BAP Interface", __PRETTY_FUNCTION__); - return BT_STATUS_FAIL; - } - char value[PROPERTY_VALUE_MAX]; - if(property_get("persist.vendor.service.bt.bap.conn_update", value, "false") - && !strcmp(value, "true")) { - is_conn_update_enabled_ = true; - } else { - is_conn_update_enabled_ = false; - } - sUcastClientInterface->Init(&sUcastClientCallbacks); - enabled_ = true; - return BT_STATUS_SUCCESS; -} - -void BtifAcmStateMachine::StateIdle::OnEnter() { - BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str()); - if(btif_acm_initiator.IsConnUpdateEnabled()) { - if ((peer_.StateMachine().PreviousStateId() == BtifAcmStateMachine::kStateOpened) || - (peer_.StateMachine().PreviousStateId() == BtifAcmStateMachine::kStateStarted)) - { - if (alarm_is_scheduled(btif_acm_initiator.AcmConnIntervalTimer())) { - btif_acm_check_and_cancel_conn_Interval_timer(); - peer_.SetConnUpdateMode(BtifAcmPeer::kFlagRelaxedMode); - } else { - LOG_ERROR(LOG_TAG, "%s Already in relaxed intervals", __PRETTY_FUNCTION__); - } - } else if (peer_.StateMachine().PreviousStateId() != BtifAcmStateMachine::kStateInvalid) { - if (alarm_is_scheduled(btif_acm_initiator.AcmConnIntervalTimer())) { - btif_acm_check_and_cancel_conn_Interval_timer(); - } - peer_.SetConnUpdateMode(BtifAcmPeer::kFlagRelaxedMode); - } - } - peer_.ClearConnUpdateMode(); - peer_.ClearAllFlags(); - peer_.SetProfileType(0); - peer_.SetRcfgProfileType(0); - memset(¤t_media_config, 0, sizeof(current_media_config)); - - // Delete peers that are re-entering the Idle state - if (peer_.IsAcceptor()) { - do_in_bta_thread(FROM_HERE, base::Bind(&BtifAcmInitiator::DeleteIdlePeers, - base::Unretained(&btif_acm_initiator))); - } -} - -void BtifAcmStateMachine::StateIdle::OnExit() { - BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str()); -} - -bool BtifAcmStateMachine::StateIdle::ProcessEvent(uint32_t event, void* p_data) { - BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s music_active_peer=%s voice_active_peer=%s", - __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str(), - peer_.FlagsToString().c_str(), - logbool(peer_.IsPeerActiveForMusic()).c_str(), - logbool(peer_.IsPeerActiveForVoice()).c_str()); - - switch (event) { - case BTIF_ACM_STOP_STREAM_REQ_EVT: - case BTIF_ACM_SUSPEND_STREAM_REQ_EVT: - break; -#if 0 - case BTIF_ACM_DISCONNECT_REQ_EVT: { - tBTIF_ACM_CONN_DISC* p_bta_data = (tBTIF_ACM_CONN_DISC*)p_data; - std::vector disconnect_streams; - if (p_bta_data->contextType == CONTEXT_TYPE_MUSIC) { - StreamType type_1; - if (peer_.GetProfileType() & (BAP|GCP)) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_MEDIA, - .direction = ASE_DIRECTION_SINK - }; - disconnect_streams.push_back(type_1); - } - if (peer_.GetProfileType() & WMCP) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_LIVE, - .direction = ASE_DIRECTION_SRC - }; - disconnect_streams.push_back(type_1); - } - } else if (p_bta_data->contextType == CONTEXT_TYPE_MUSIC_VOICE) { - StreamType type_2 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SRC - }; - StreamType type_3 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SINK - }; - disconnect_streams.push_back(type_2); - disconnect_streams.push_back(type_3); - StreamType type_1; - if (peer_.GetProfileType() & (BAP|GCP)) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_MEDIA, - .direction = ASE_DIRECTION_SINK - }; - disconnect_streams.push_back(type_1); - } - if (peer_.GetProfileType() & WMCP) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_LIVE, - .direction = ASE_DIRECTION_SRC - }; - disconnect_streams.push_back(type_1); - } - } - LOG(WARNING) << __func__ << " size of disconnect_streams " << disconnect_streams.size(); - if (!sUcastClientInterface) break; - sUcastClientInterface->Disconnect(peer_.PeerAddress(), disconnect_streams); - - // Re-enter Idle so the peer can be deleted - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - } - break; -#endif - - case BTIF_ACM_CONNECT_REQ_EVT: { - tBTIF_ACM_CONN_DISC* p_bta_data = (tBTIF_ACM_CONN_DISC*)p_data; - bool can_connect = true; - // Check whether connection is allowed - if (peer_.IsAcceptor()) { - //There is no char in current spec. Should we check VMCP role here? - // shall we assume VMCP role would have been checked in apps and no need to check here? - can_connect = btif_acm_initiator.AllowedToConnect(peer_.PeerAddress()); - if (!can_connect) disconnect_acm_initiator(peer_.PeerAddress(), p_bta_data->contextType); - } - if (!can_connect) { - BTIF_TRACE_ERROR( - "%s: Cannot connect to peer %s: too many connected " - "peers", - __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str()); - break; - } - std::vector streams; - if (p_bta_data->contextType == CONTEXT_TYPE_MUSIC) { - StreamConnect conn_media; - if (peer_.GetProfileType() & (BAP|GCP)) { - //keeping media tx as BAP/GCP config - memset(&conn_media, 0, sizeof(conn_media)); - fetch_media_tx_codec_qos_config(peer_.PeerAddress(), peer_.GetProfileType() & (BAP|GCP), &conn_media); - streams.push_back(conn_media); -#if 0 - if (false) {//enable when GCP support is available - SelectCodecQosConfig(peer_.PeerAddress(), (peer_.GetProfileType() & ~WMCP), VOICE_CONTEXT, SRC, EB_CONFIG); - StreamConnect conn_voice; - CodecQosConfig config; - conn_voice.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - conn_voice.stream_type.audio_context = CONTENT_TYPE_CONVERSATIONAL; - config = peer_.get_peer_voice_rx_codec_qos_config(); - print_codec_parameters(config.codec_config); - print_qos_parameters(config.qos_config); - conn_voice.stream_type.direction = ASE_DIRECTION_SRC; - conn_voice.codec_qos_config_pair.push_back(config); - streams.push_back(conn_voice); - } -#endif - } - if (peer_.GetProfileType() & WMCP) { - //keeping media rx as WMCP config - memset(&conn_media, 0, sizeof(conn_media)); - fetch_media_rx_codec_qos_config(peer_.PeerAddress(), WMCP, &conn_media); - streams.push_back(conn_media); - } - } else if (p_bta_data->contextType == CONTEXT_TYPE_MUSIC_VOICE) { - StreamConnect conn_media, conn_voice; - //keeping voice tx as BAP config - memset(&conn_voice, 0, sizeof(conn_voice)); - fetch_voice_tx_codec_qos_config(peer_.PeerAddress(), BAP, &conn_voice); - streams.push_back(conn_voice); - //keeping voice rx as BAP config - memset(&conn_voice, 0, sizeof(conn_voice)); - fetch_voice_rx_codec_qos_config(peer_.PeerAddress(), BAP, &conn_voice); - streams.push_back(conn_voice); - if (peer_.GetProfileType() & (BAP|GCP)) { - //keeping media tx as BAP/GCP config - memset(&conn_media, 0, sizeof(conn_media)); - fetch_media_tx_codec_qos_config(peer_.PeerAddress(), peer_.GetProfileType() & (BAP|GCP), &conn_media); - streams.push_back(conn_media); - } - if (peer_.GetProfileType() & WMCP) { - //keeping media rx as WMCP config - memset(&conn_media, 0, sizeof(conn_media)); - fetch_media_rx_codec_qos_config(peer_.PeerAddress(), WMCP, &conn_media); - streams.push_back(conn_media); - } - } else if (p_bta_data->contextType == CONTEXT_TYPE_VOICE) { - StreamConnect conn_voice; - //keeping voice tx as BAP config - memset(&conn_voice, 0, sizeof(conn_voice)); - fetch_voice_tx_codec_qos_config(peer_.PeerAddress(), BAP, &conn_voice); - streams.push_back(conn_voice); - //keeping voice rx as BAP config - memset(&conn_voice, 0, sizeof(conn_voice)); - fetch_voice_rx_codec_qos_config(peer_.PeerAddress(), BAP, &conn_voice); - streams.push_back(conn_voice); - } - LOG(WARNING) << __func__ << " size of streams " << streams.size(); - if (!sUcastClientInterface) break; - // intiate background connection - std::vector address; - address.push_back(peer_.PeerAddress()); - sUcastClientInterface->Connect(address, false, streams); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateOpening); - } break; -#if 0 - case BTA_ACM_DISCONNECT_EVT: { - tBTIF_ACM* p_acm = (tBTIF_ACM*)p_data; - int context_type = p_acm->state_info.stream_type.type; - if (p_acm->state_info.stream_state == StreamState::DISCONNECTED) { - if (context_type == CONTENT_TYPE_MEDIA) { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - BTIF_TRACE_DEBUG("%s: received Media Rx disconnected state from BAP, set state & ignore", __func__); - peer_.SetPeerMusicRxState(p_acm->state_info.stream_state); - } - } - } else if (p_acm->state_info.stream_state == StreamState::DISCONNECTING) { - if (context_type == CONTENT_TYPE_MEDIA) { - BTIF_TRACE_DEBUG("%s: received Media disconnecting state from BAP, ignore", __func__); - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) - peer_.SetPeerMusicRxState(p_acm->state_info.stream_state); - } - } - } break; -#endif - - case BTA_ACM_CONN_UPDATE_TIMEOUT_EVT: - peer_.SetConnUpdateMode(BtifAcmPeer::kFlagRelaxedMode); - break; - - default: - BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s", - __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str()); - return false; - } - - return true; -} - -void BtifAcmStateMachine::StateOpening::OnEnter() { - BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str()); - - if(btif_acm_initiator.IsConnUpdateEnabled()) { - //Cancel the timer if start streamng comes before - // 5 seconds while moving the interval to relaxed mode. - if (alarm_is_scheduled(btif_acm_initiator.AcmConnIntervalTimer())) { - btif_acm_check_and_cancel_conn_Interval_timer(); - } - else { - peer_.SetConnUpdateMode(BtifAcmPeer::kFlagAggresiveMode); - } - } - -} - -void BtifAcmStateMachine::StateOpening::OnExit() { - BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str()); -} - -bool BtifAcmStateMachine::StateOpening::ProcessEvent(uint32_t event, void* p_data) { - BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s music_active_peer=%s voice_active_peer=%s", - __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str(), - peer_.FlagsToString().c_str(), - logbool(peer_.IsPeerActiveForMusic()).c_str(), - logbool(peer_.IsPeerActiveForVoice()).c_str()); - - switch (event) { - case BTIF_ACM_STOP_STREAM_REQ_EVT: - case BTIF_ACM_SUSPEND_STREAM_REQ_EVT: - break; // Ignore - - case BTA_ACM_CONNECT_EVT: { - tBTIF_ACM* p_bta_data = (tBTIF_ACM*)p_data; - btacm_connection_state_t state; - uint8_t status = (uint8_t)p_bta_data->state_info.stream_state; - uint16_t contextType = p_bta_data->state_info.stream_type.type; - - LOG_INFO( - LOG_TAG, "%s: Peer %s : event=%s flags=%s status=%d contextType=%d", - __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str(), peer_.FlagsToString().c_str(), - status, contextType); - if (contextType == CONTENT_TYPE_MEDIA) { - if (p_bta_data->state_info.stream_state == StreamState::CONNECTED) { - state = BTACM_CONNECTION_STATE_CONNECTED; - // Report the connection state to the application - btif_report_connection_state(peer_.PeerAddress(), state, CONTEXT_TYPE_MUSIC); - if (p_bta_data->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerMusicTxState(p_bta_data->state_info.stream_state); - BTIF_TRACE_DEBUG("%s: received connected state from BAP for mediaTx, move in opened state", __func__); - } else if (p_bta_data->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerMusicRxState(p_bta_data->state_info.stream_state); - BTIF_TRACE_DEBUG("%s: received connected state from BAP for mediaRx, move in opened state", __func__); - } - // Change state to OPENED - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateOpened); - } else if (p_bta_data->state_info.stream_state == StreamState::CONNECTING) { - BTIF_TRACE_DEBUG("%s: received connecting state from BAP for MEDIA Tx or Rx, ignore", __func__); - if (p_bta_data->state_info.stream_type.direction == ASE_DIRECTION_SINK) - peer_.SetPeerMusicTxState(p_bta_data->state_info.stream_state); - else if (p_bta_data->state_info.stream_type.direction == ASE_DIRECTION_SRC) - peer_.SetPeerMusicRxState(p_bta_data->state_info.stream_state); - } - } else if (contextType == CONTENT_TYPE_CONVERSATIONAL) { - if (p_bta_data->state_info.stream_state == StreamState::CONNECTED) { - state = BTACM_CONNECTION_STATE_CONNECTED; - if (p_bta_data->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerVoiceTxState(p_bta_data->state_info.stream_state); - if (peer_.GetPeerVoiceRxState() == StreamState::CONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), state, CONTEXT_TYPE_VOICE); - BTIF_TRACE_DEBUG("%s: received connected state from BAP for voice Tx, move in opened state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateOpened); - } - } else if (p_bta_data->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerVoiceRxState(p_bta_data->state_info.stream_state); - if (peer_.GetPeerVoiceTxState() == StreamState::CONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), state, CONTEXT_TYPE_VOICE); - BTIF_TRACE_DEBUG("%s: received connected state from BAP for voice Rx, move in opened state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateOpened); - } - } - } else if (p_bta_data->state_info.stream_state == StreamState::CONNECTING) { - BTIF_TRACE_DEBUG("%s: received connecting state from BAP for CONVERSATIONAL Tx or Rx, ignore", __func__); - if (p_bta_data->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerVoiceTxState(p_bta_data->state_info.stream_state); - } else if (p_bta_data->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerVoiceRxState(p_bta_data->state_info.stream_state); - } - } - } - } break; - - case BTA_ACM_DISCONNECT_EVT: { - tBTIF_ACM* p_acm = (tBTIF_ACM*)p_data; - int context_type = p_acm->state_info.stream_type.type; - if (p_acm->state_info.stream_state == StreamState::DISCONNECTED) { - if (context_type == CONTENT_TYPE_MEDIA) { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerMusicTxState(p_acm->state_info.stream_state); - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerMusicRxState(p_acm->state_info.stream_state); - } - if (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), - BTACM_CONNECTION_STATE_DISCONNECTED, CONTEXT_TYPE_MUSIC); - } - if (peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTED && - peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - BTIF_TRACE_DEBUG("%s: received Media Tx/Rx disconnected state from BAP" - " when Voice Tx+Rx & Media Rx/Tx was disconnected, move in idle state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - } else { - BTIF_TRACE_DEBUG("%s: received Media Tx/Rx disconnected state from BAP" - " when either Voice Tx or Rx or Media Rx/Tx is connecting, remain in opening state", __func__); - } - } else if (context_type == CONTENT_TYPE_CONVERSATIONAL) { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerVoiceTxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTED, CONTEXT_TYPE_VOICE); - if (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Tx," - " voice Rx, music Tx+Rx are disconnected move in idle state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - } else if (peer_.GetPeerMusicTxState() == StreamState::CONNECTING || - peer_.GetPeerMusicRxState() == StreamState::CONNECTING) { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Tx," - " voice Rx is disconnected but either music Tx or Rx still connecting," - " remain in opening state", __func__); - } - } - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerVoiceRxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTED, CONTEXT_TYPE_VOICE); - if (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Rx," - " voice Tx, music Tx+Rx are disconnected move in idle state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - } else if (peer_.GetPeerMusicTxState() == StreamState::CONNECTING || - peer_.GetPeerMusicRxState() == StreamState::CONNECTING) { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Rx," - " voice Tx is disconnected but music Tx or Rx still connecting," - " remain in opening state", __func__); - } - } - } - } - } else if (p_acm->state_info.stream_state == StreamState::DISCONNECTING) { - if (context_type == CONTENT_TYPE_MEDIA) { - BTIF_TRACE_DEBUG("%s: received disconnecting state from BAP for MEDIA Tx or Rx, ignore", __func__); - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerMusicTxState(p_acm->state_info.stream_state); - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerMusicRxState(p_acm->state_info.stream_state); - } - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTING, CONTEXT_TYPE_MUSIC); - } else if (context_type == CONTENT_TYPE_CONVERSATIONAL) { - BTIF_TRACE_DEBUG("%s: received disconnecting state from BAP for CONVERSATIONAL Tx or Rx, ignore", __func__); - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerVoiceTxState(p_acm->state_info.stream_state); - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerVoiceRxState(p_acm->state_info.stream_state); - } - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTING, CONTEXT_TYPE_VOICE); - } - } - } - break; - - case BTIF_ACM_DISCONNECT_REQ_EVT:{ - tBTIF_ACM_CONN_DISC* p_bta_data = (tBTIF_ACM_CONN_DISC*)p_data; - std::vector disconnect_streams; - if (p_bta_data->contextType == CONTEXT_TYPE_MUSIC) { - StreamType type_1; - if (p_bta_data->profileType & (BAP|GCP)) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_MEDIA, - .direction = ASE_DIRECTION_SINK - }; - disconnect_streams.push_back(type_1); - } - if (p_bta_data->profileType & WMCP) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_LIVE, - .direction = ASE_DIRECTION_SRC - }; - disconnect_streams.push_back(type_1); - } - } else if (p_bta_data->contextType == CONTEXT_TYPE_MUSIC_VOICE) { - StreamType type_2 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SRC - }; - StreamType type_3 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SINK - }; - disconnect_streams.push_back(type_3); - disconnect_streams.push_back(type_2); - StreamType type_1; - if (p_bta_data->profileType & (BAP|GCP)) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_MEDIA, - .direction = ASE_DIRECTION_SINK - }; - disconnect_streams.push_back(type_1); - } - if (p_bta_data->profileType & WMCP) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_LIVE, - .direction = ASE_DIRECTION_SRC - }; - disconnect_streams.push_back(type_1); - } - } else if (p_bta_data->contextType == CONTEXT_TYPE_VOICE) { - StreamType type_2 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SRC - }; - StreamType type_3 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SINK - }; - disconnect_streams.push_back(type_3); - disconnect_streams.push_back(type_2); - } - LOG(WARNING) << __func__ << " size of disconnect_streams " << disconnect_streams.size(); - if (!sUcastClientInterface) break; - sUcastClientInterface->Disconnect(peer_.PeerAddress(), disconnect_streams); - - if ((p_bta_data->contextType == CONTEXT_TYPE_MUSIC) && ((peer_.GetPeerVoiceRxState() == StreamState::CONNECTING) || - (peer_.GetPeerVoiceTxState() == StreamState::CONNECTING))) { - LOG(WARNING) << __func__ << " voice connecting remain in opening "; - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTED, CONTEXT_TYPE_MUSIC); - } else if ((p_bta_data->contextType == CONTEXT_TYPE_VOICE) && (peer_.GetPeerMusicTxState() == StreamState::CONNECTING || - (peer_.GetPeerMusicRxState() == StreamState::CONNECTING))) { - LOG(WARNING) << __func__ << " Music connecting remain in opening "; - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTED, CONTEXT_TYPE_VOICE); - } else { - LOG(WARNING) << __func__ << " Move in idle state "; - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTED, CONTEXT_TYPE_MUSIC_VOICE); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - } - } - break; - - case BTIF_ACM_CONNECT_REQ_EVT: { - BTIF_TRACE_WARNING( - "%s: Peer %s : event=%s : device is already connecting, " - "ignore Connect request", - __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str()); - } break; - - case BTA_ACM_CONFIG_EVT: { - tBTIF_ACM* p_acm_data = (tBTIF_ACM*)p_data; - uint16_t contextType = p_acm_data->state_info.stream_type.type; - uint16_t peer_latency_ms = 0; - uint32_t presen_delay = 0; - bool is_update_require = false; - if (contextType == CONTENT_TYPE_MEDIA) { - if (p_acm_data->state_info.stream_type.audio_context == CONTENT_TYPE_MEDIA) { - BTIF_TRACE_DEBUG("%s: compare with current media config", __PRETTY_FUNCTION__); - is_update_require = compare_codec_config_(current_media_config, p_acm_data->config_info.codec_config); - } else if (p_acm_data->state_info.stream_type.audio_context == CONTENT_TYPE_LIVE) { - BTIF_TRACE_DEBUG("%s: cache current_recording_config", __PRETTY_FUNCTION__); - current_recording_config = p_acm_data->config_info.codec_config; - } - if (mandatory_codec_selected) { - BTIF_TRACE_DEBUG("%s: Mandatory codec selected, do not store config", __PRETTY_FUNCTION__); - } else { - BTIF_TRACE_DEBUG("%s: store configuration", __PRETTY_FUNCTION__); - } - //Cache the peer latency in WMCP case - if (p_acm_data->state_info.stream_type.audio_context == CONTENT_TYPE_LIVE) { - BTIF_TRACE_DEBUG("%s: presentation delay[0] = %x", __func__, - p_acm_data->config_info.qos_config.ascs_configs[0].presentation_delay[0]); - BTIF_TRACE_DEBUG("%s: presentation delay[1] = %x", __func__, - p_acm_data->config_info.qos_config.ascs_configs[0].presentation_delay[1]); - BTIF_TRACE_DEBUG("%s: presentation delay[2] = %x", __func__, - p_acm_data->config_info.qos_config.ascs_configs[0].presentation_delay[2]); - presen_delay = static_cast(p_acm_data->config_info.qos_config.ascs_configs[0].presentation_delay[0]) | - static_cast(p_acm_data->config_info.qos_config.ascs_configs[0].presentation_delay[1] << 8) | - static_cast(p_acm_data->config_info.qos_config.ascs_configs[0].presentation_delay[2] << 16); - BTIF_TRACE_DEBUG("%s: presen_delay = %dus", __func__, presen_delay); - peer_latency_ms = presen_delay/1000; - BTIF_TRACE_DEBUG("%s: s_to_m latency = %dms", __func__, - p_acm_data->config_info.qos_config.cig_config.max_tport_latency_s_to_m); - peer_latency_ms += p_acm_data->config_info.qos_config.cig_config.max_tport_latency_s_to_m; - peer_.SetPeerLatency(peer_latency_ms); - BTIF_TRACE_DEBUG("%s: cached peer Latency = %dms", __func__, peer_.GetPeerLatency()); - } - if (is_update_require) { - current_media_config = p_acm_data->config_info.codec_config; - BTIF_TRACE_DEBUG("%s: current_media_config.codec_specific_3: %" - PRIi64, __func__, current_media_config.codec_specific_3); - btif_acm_update_lc3q_params(¤t_media_config.codec_specific_3, p_acm_data); - btif_acm_report_source_codec_state(peer_.PeerAddress(), current_media_config, - unicast_codecs_capabilities, - unicast_codecs_capabilities, CONTEXT_TYPE_MUSIC); - } - } else if (contextType == CONTENT_TYPE_CONVERSATIONAL && - p_acm_data->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - BTIF_TRACE_DEBUG("%s: cache current_voice_config", __PRETTY_FUNCTION__); - current_voice_config = p_acm_data->config_info.codec_config; - BTIF_TRACE_DEBUG("%s: current_voice_config.codec_specific_3: %" - PRIi64, __func__, current_voice_config.codec_specific_3); - btif_acm_update_lc3q_params(¤t_voice_config.codec_specific_3, p_acm_data); - btif_acm_report_source_codec_state(peer_.PeerAddress(), current_voice_config, - unicast_codecs_capabilities, - unicast_codecs_capabilities, CONTEXT_TYPE_VOICE); - } - //Handle BAP START if reconfig comes in mid of streaming - //peer_.SetStreamReconfigInfo(p_acm->acm_reconfig); - //TODO: local capabilities - //CodecConfig record = p_bta_data->acm_reconfig.codec_config; - //saving codec config as negotiated parameter as true - //btif_pacs_add_record(peer_.PeerAddress(), true, CodecDirection::CODEC_DIR_SRC, &record); - - } break; - - case BTA_ACM_CONN_UPDATE_TIMEOUT_EVT: - peer_.SetConnUpdateMode(BtifAcmPeer::kFlagRelaxedMode); - break; - - default: - BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s", - __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str()); - return false; - } - return true; -} - -bool btif_peer_device_is_streaming(uint8_t Id) { - bool is_streaming = false; - tBTA_CSIP_CSET cset_info; - memset(&cset_info, 0, sizeof(tBTA_CSIP_CSET)); - cset_info = BTA_CsipGetCoordinatedSet(Id); - if (cset_info.size == 0) { - BTIF_TRACE_ERROR("%s: CSET info size is zero, return", __func__); - return false; - } - std::vector::iterator itr; - BTIF_TRACE_DEBUG("%s: size of set members %d", __func__, (cset_info.set_members).size()); - if ((cset_info.set_members).size() > 0) { - for (itr =(cset_info.set_members).begin(); itr != (cset_info.set_members).end(); itr++) { - BtifAcmPeer* peer = btif_acm_initiator.FindPeer(*itr); - if (peer != nullptr && (peer->IsStreaming() || peer->CheckFlags(BtifAcmPeer::kFlagPendingStart)) && - !peer->CheckFlags(BtifAcmPeer::kFlagPendingLocalSuspend)) { - BTIF_TRACE_DEBUG("%s: fellow device is streaming %s ", __func__, peer->PeerAddress().ToString().c_str()); - is_streaming = true; - break; - } - } - } - return is_streaming; -} - -bool btif_peer_device_is_reconfiguring(uint8_t Id) { - bool is_reconfigured = false; - if (Id < INVALID_SET_ID) { - tBTA_CSIP_CSET cset_info; - memset(&cset_info, 0, sizeof(tBTA_CSIP_CSET)); - cset_info = BTA_CsipGetCoordinatedSet(Id); - if (cset_info.size == 0) { - BTIF_TRACE_ERROR("%s: CSET info size is zero, return", __func__); - return false; - } - std::vector::iterator itr; - BTIF_TRACE_DEBUG("%s: size of set members %d", __func__, (cset_info.set_members).size()); - if ((cset_info.set_members).size() > 0) { - for (itr =(cset_info.set_members).begin(); itr != (cset_info.set_members).end(); itr++) { - BtifAcmPeer* peer = btif_acm_initiator.FindPeer(*itr); - if (peer != nullptr && peer->CheckFlags(BtifAcmPeer::kFlagPendingReconfigure)) { - BTIF_TRACE_DEBUG("%s: peer is reconfiguring %s ", __func__, peer->PeerAddress().ToString().c_str()); - is_reconfigured = true; - break; - } - } - } - } else { - is_reconfigured = true; - BTIF_TRACE_ERROR("%s: peer is TWM device, return is_reconfigured %d", __func__, is_reconfigured); - } - return is_reconfigured; -} - -void BtifAcmStateMachine::StateOpened::OnEnter() { - BTIF_TRACE_DEBUG("%s: Peer %s, Peer SetId = %d, MusicActiveSetId = %d, ContextType = %d", __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str(), peer_.SetId(), - btif_acm_initiator.MusicActiveCSetId(), peer_.GetContextType()); - - //Starting the timer for 5 seconds before moving to relaxed state as - //stop event or start streaming event moght immediately come - //which requires aggresive interval - if(btif_acm_initiator.IsConnUpdateEnabled()) { - btif_acm_check_and_start_conn_Interval_timer(&peer_); - } - peer_.ClearFlags(BtifAcmPeer::kFlagPendingLocalSuspend | - BtifAcmPeer::kFlagPendingStart | - BtifAcmPeer::kFlagPendingStop); - - BTIF_TRACE_DEBUG("%s: kFlagPendingReconfigure %d and kFLagPendingStartAfterReconfig %d", __PRETTY_FUNCTION__, - peer_.CheckFlags(BtifAcmPeer::kFlagPendingReconfigure), - peer_.CheckFlags(BtifAcmPeer::kFLagPendingStartAfterReconfig)); - - if (peer_.CheckFlags(BtifAcmPeer::kFlagPendingReconfigure)) { - peer_.ClearFlags(BtifAcmPeer::kFlagPendingReconfigure); - if ((peer_.GetRcfgProfileType() != BAP_CALL) && - (current_active_profile_type != peer_.GetRcfgProfileType())) { - current_active_profile_type = peer_.GetRcfgProfileType(); - if (current_active_profile_type != WMCP) - current_active_config = current_media_config; - else - current_active_config = current_recording_config; - - if (btif_peer_device_is_reconfiguring(peer_.SetId())) - btif_acm_source_restart_session(active_bda, active_bda); - - if (current_active_profile_type == WMCP) { - uint16_t sink_latency = btif_acm_get_active_device_latency(); - BTIF_TRACE_EVENT("%s: sink_latency = %dms", __func__, sink_latency); - if ((sink_latency > 0) && !btif_acm_update_sink_latency_change(sink_latency * 10)) { - BTIF_TRACE_ERROR("%s: unable to update latency", __func__); - } - } - if (current_active_profile_type == BAP) { - peer_.ResetProfileType(GCP); - peer_.SetProfileType(BAP); - } else if (current_active_profile_type == GCP) { - peer_.ResetProfileType(BAP); - peer_.SetProfileType(GCP); - } - BTIF_TRACE_DEBUG("%s: cummulative_profile_type %d", __func__, peer_.GetProfileType()); - BTIF_TRACE_DEBUG("%s: Reconfig + restart session completed for media, signal session ready", __func__); - btif_acm_signal_session_ready(); - } else if (current_active_profile_type == peer_.GetRcfgProfileType()) { - BTIF_TRACE_DEBUG("%s: Reconfig to remote is completed for media, restart session wasn't needed", __func__); - } else { - BTIF_TRACE_DEBUG("%s: Reconfig completed for BAP_CALL", __func__); - } - } - //Start the lock release timer here. - //check if peer device is in started state - if (btif_peer_device_is_streaming(peer_.SetId()) || - peer_.CheckFlags(BtifAcmPeer::kFLagPendingStartAfterReconfig)) { - StreamType type_1, type_2; - std::vector start_streams; - if (peer_.GetRcfgProfileType() != BAP_CALL) { - if ((current_active_profile_type == BAP || current_active_profile_type == GCP) && - (peer_.GetPeerMusicTxState() == StreamState::CONNECTED)) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_MEDIA, - .direction = ASE_DIRECTION_SINK - }; - start_streams.push_back(type_1); - } else if ((current_active_profile_type == WMCP) && - (peer_.GetPeerMusicRxState() == StreamState::CONNECTED)) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_LIVE, - .direction = ASE_DIRECTION_SRC - }; - start_streams.push_back(type_1); - } - } else { - if ((peer_.GetPeerVoiceTxState() == StreamState::CONNECTED) && - (peer_.GetPeerVoiceRxState() == StreamState::CONNECTED)) { - type_1 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SINK - }; - type_2 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SRC - }; - start_streams.push_back(type_1); - start_streams.push_back(type_2); - } - } - - if(btif_acm_initiator.IsConnUpdateEnabled()) { - //Cancel the timer if start streamng comes before - // 5 seconds while moving the interval to relaxed mode. - if (alarm_is_scheduled(btif_acm_initiator.AcmConnIntervalTimer())) { - btif_acm_check_and_cancel_conn_Interval_timer(); - } else { - peer_.SetConnUpdateMode(BtifAcmPeer::kFlagAggresiveMode); - } - } - sUcastClientInterface->Start(peer_.PeerAddress(), start_streams); - peer_.SetFlags(BtifAcmPeer::kFlagPendingStart); - peer_.ClearFlags(BtifAcmPeer::kFLagPendingStartAfterReconfig); - } - peer_.SetRcfgProfileType(0); - - if (peer_.StateMachine().PreviousStateId() == BtifAcmStateMachine::kStateStarted) { - BTIF_TRACE_DEBUG("%s: Entering Opened from Started State", __PRETTY_FUNCTION__); - if ((btif_acm_initiator.GetGroupLockStatus(peer_.SetId()) != - BtifAcmInitiator::kFlagStatusUnknown) && - alarm_is_scheduled(btif_acm_initiator.AcmGroupProcedureTimer())) { - BTIF_TRACE_DEBUG("%s: All locked and stop/suspend requested device have stopped, ack mm audio", __func__); - btif_acm_check_and_cancel_group_procedure_timer(btif_acm_initiator.MusicActiveCSetId()); - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_SUCCESS); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_SUCCESS); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - btif_acm_check_and_start_lock_release_timer(btif_acm_initiator.MusicActiveCSetId()); - } - } - - if (peer_.StateMachine().PreviousStateId() == BtifAcmStateMachine::kStateStarted) { - if ((btif_acm_initiator.MusicActiveCSetId() > 0) && - (btif_acm_initiator.GetGroupLockStatus(btif_acm_initiator.MusicActiveCSetId()) == BtifAcmInitiator::kFlagStatusLocked)) { - BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str()); - btif_acm_check_and_start_lock_release_timer(btif_acm_initiator.MusicActiveCSetId()); - } - } -} - -void BtifAcmStateMachine::StateOpened::OnExit() { - BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str()); - - peer_.ClearFlags(BtifAcmPeer::kFlagPendingStart); -} - -bool BtifAcmStateMachine::StateOpened::ProcessEvent(uint32_t event, - void* p_data) { - tBTIF_ACM* p_acm = (tBTIF_ACM*)p_data; - - BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s music_active_peer=%s voice_active_peer=%s", - __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str(), - peer_.FlagsToString().c_str(), - logbool(peer_.IsPeerActiveForMusic()).c_str(), - logbool(peer_.IsPeerActiveForVoice()).c_str()); - - switch (event) { - case BTIF_ACM_CONNECT_REQ_EVT: { - tBTIF_ACM_CONN_DISC* p_bta_data = (tBTIF_ACM_CONN_DISC*)p_data; - bool can_connect = true; - // Check whether connection is allowed - if (peer_.IsAcceptor()) { - //There is no char in current spec. Should we check VMCP role here? - // shall we assume VMCP role would have been checked in apps and no need to check here? - can_connect = btif_acm_initiator.AllowedToConnect(peer_.PeerAddress()); - if (!can_connect) disconnect_acm_initiator(peer_.PeerAddress(), p_bta_data->contextType); - } - if (!can_connect) { - BTIF_TRACE_ERROR( - "%s: Cannot connect to peer %s: too many connected " - "peers", - __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str()); - break; - } - std::vector streams; - if (p_bta_data->contextType == CONTEXT_TYPE_MUSIC) { - StreamConnect conn_media; - if (peer_.GetProfileType() & (BAP|GCP)) { - //keeping media tx as BAP/GCP config - memset(&conn_media, 0, sizeof(conn_media)); - fetch_media_tx_codec_qos_config(peer_.PeerAddress(), peer_.GetProfileType() & (BAP|GCP), &conn_media); - streams.push_back(conn_media); -#if 0 - if (false) {//enable when GCP support is available - SelectCodecQosConfig(peer_.PeerAddress(), (peer_.GetProfileType() & ~WMCP), VOICE_CONTEXT, SRC, EB_CONFIG); - StreamConnect conn_voice; - CodecQosConfig config; - conn_voice.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - conn_voice.stream_type.audio_context = CONTENT_TYPE_CONVERSATIONAL; - config = peer_.get_peer_voice_rx_codec_qos_config(); - print_codec_parameters(config.codec_config); - print_qos_parameters(config.qos_config); - conn_voice.stream_type.direction = ASE_DIRECTION_SRC; - conn_voice.codec_qos_config_pair.push_back(config); - streams.push_back(conn_voice); - } -#endif - } - if (peer_.GetProfileType() & WMCP) { - //keeping media rx as WMCP config - memset(&conn_media, 0, sizeof(conn_media)); - fetch_media_rx_codec_qos_config(peer_.PeerAddress(), WMCP, &conn_media); - streams.push_back(conn_media); - } - } else if (p_bta_data->contextType == CONTEXT_TYPE_MUSIC_VOICE) { - StreamConnect conn_media, conn_voice; - //keeping voice tx as BAP config - memset(&conn_voice, 0, sizeof(conn_voice)); - fetch_voice_tx_codec_qos_config(peer_.PeerAddress(), BAP, &conn_voice); - streams.push_back(conn_voice); - //keeping voice rx as BAP config - memset(&conn_voice, 0, sizeof(conn_voice)); - fetch_voice_rx_codec_qos_config(peer_.PeerAddress(), BAP, &conn_voice); - streams.push_back(conn_voice); - if (peer_.GetProfileType() & (BAP|GCP)) { - //keeping media tx as BAP/GCP config - memset(&conn_media, 0, sizeof(conn_media)); - fetch_media_tx_codec_qos_config(peer_.PeerAddress(), peer_.GetProfileType() & (BAP|GCP), &conn_media); - streams.push_back(conn_media); - } - if (peer_.GetProfileType() & WMCP) { - //keeping media rx as WMCP config - memset(&conn_media, 0, sizeof(conn_media)); - fetch_media_rx_codec_qos_config(peer_.PeerAddress(), WMCP, &conn_media); - streams.push_back(conn_media); - } - } else if (p_bta_data->contextType == CONTEXT_TYPE_VOICE) { - StreamConnect conn_voice; - //keeping voice tx as BAP config - memset(&conn_voice, 0, sizeof(conn_voice)); - fetch_voice_tx_codec_qos_config(peer_.PeerAddress(), BAP, &conn_voice); - streams.push_back(conn_voice); - //keeping voice rx as BAP config - memset(&conn_voice, 0, sizeof(conn_voice)); - fetch_voice_rx_codec_qos_config(peer_.PeerAddress(), BAP, &conn_voice); - streams.push_back(conn_voice); - } - LOG(WARNING) << __func__ << " size of streams " << streams.size(); - if (!sUcastClientInterface) break; - std::vector address; - address.push_back(peer_.PeerAddress()); - sUcastClientInterface->Connect(address, false, streams); - //peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateOpening); - } break; - - case BTIF_ACM_STOP_STREAM_REQ_EVT: - case BTIF_ACM_SUSPEND_STREAM_REQ_EVT: { - BTIF_TRACE_DEBUG("%s: Already in OPENED state, ACK success", __PRETTY_FUNCTION__); - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_SUCCESS); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_SUCCESS); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - } break; - - case BTIF_ACM_START_STREAM_REQ_EVT: { - LOG_INFO(LOG_TAG, "%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str(), - peer_.FlagsToString().c_str()); - if (peer_.CheckFlags(BtifAcmPeer::kFlagPendingStart)) { - BTIF_TRACE_DEBUG("%s: Ignore Start req", __PRETTY_FUNCTION__); - break; - } -#if 0 - //Can be either music or voice, prior to coming here, - //this must have been evaluated for locking logic + grp logic - StreamType type_1; - std::vector start_streams; - if (current_active_profile_type != WMCP) { - if (peer_.GetStreamContextType() == CONTEXT_TYPE_MUSIC) { - StreamType type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_MEDIA, - .direction = ASE_DIRECTION_SINK - }; - start_streams.push_back(type_1); - } else if (peer_.GetStreamContextType() == CONTEXT_TYPE_VOICE) { - StreamType type_1 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SINK - }; - StreamType type_2 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SRC - }; - start_streams.push_back(type_1); - start_streams.push_back(type_2); - LOG_INFO(LOG_TAG, "%s: sending start for voice###", __PRETTY_FUNCTION__); - } - } else { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_LIVE, - .direction = ASE_DIRECTION_SRC - }; - start_streams.push_back(type_1); - } - - if(btif_acm_initiator.IsConnUpdateEnabled()) { - //Cancel the timer if start streamng comes before - // 5 seconds while moving the interval to relaxed mode. - if (alarm_is_scheduled(btif_acm_initiator.AcmConnIntervalTimer())) { - btif_acm_check_and_cancel_conn_Interval_timer(); - } else { - peer_.SetConnUpdateMode(BtifAcmPeer::kFlagAggresiveMode); - } - } - if (!sUcastClientInterface) break; - sUcastClientInterface->Start(peer_.PeerAddress(), start_streams); -#endif -#if 1 - if (peer_.GetStreamContextType() == CONTEXT_TYPE_MUSIC) { - reconfig_acm_initiator(peer_.PeerAddress(), current_active_profile_type); - } else if (peer_.GetStreamContextType() == CONTEXT_TYPE_VOICE) { - reconfig_acm_initiator(peer_.PeerAddress(), BAP_CALL); - } - peer_.SetFlags(BtifAcmPeer::kFLagPendingStartAfterReconfig); -#endif - } - break; - - case BTA_ACM_START_EVT: { - tBTIF_ACM_STATUS status = (uint8_t)p_acm->state_info.stream_state; - //int contextType = p_acm->state_info.stream_type.type; - LOG_INFO(LOG_TAG, - "%s: Peer %s : event=%s status=%d ", - __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str(),status); - - if (p_acm->state_info.stream_state == StreamState::STARTING) { - //Check what to do in this case - BTIF_TRACE_DEBUG("%s: BAP returned as starting, ignore", __PRETTY_FUNCTION__); - break; - } else if (p_acm->state_info.stream_state == StreamState::STREAMING){ - peer_.ClearFlags(BtifAcmPeer::kFlagPendingStart); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateStarted); - } - } break; - - case BTIF_ACM_DISCONNECT_REQ_EVT:{ - tBTIF_ACM_CONN_DISC* p_bta_data = (tBTIF_ACM_CONN_DISC*)p_data; - std::vector disconnect_streams; - if (peer_.CheckFlags(BtifAcmPeer::kFlagPendingStart)) { - peer_.ClearFlags(BtifAcmPeer::kFlagPendingStart); - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS); - } - } - if (p_bta_data->contextType == CONTEXT_TYPE_MUSIC) { - StreamType type_1; - if (p_bta_data->profileType & (BAP|GCP)) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_MEDIA, - .direction = ASE_DIRECTION_SINK - }; - disconnect_streams.push_back(type_1); - } - if (p_bta_data->profileType & WMCP) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_LIVE, - .direction = ASE_DIRECTION_SRC - }; - disconnect_streams.push_back(type_1); - } - } else if (p_bta_data->contextType == CONTEXT_TYPE_MUSIC_VOICE) { - StreamType type_2 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SRC - }; - StreamType type_3 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SINK - }; - disconnect_streams.push_back(type_3); - disconnect_streams.push_back(type_2); - StreamType type_1; - if (p_bta_data->profileType & (BAP|GCP)) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_MEDIA, - .direction = ASE_DIRECTION_SINK - }; - disconnect_streams.push_back(type_1); - } - if (p_bta_data->profileType & WMCP) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_LIVE, - .direction = ASE_DIRECTION_SRC - }; - disconnect_streams.push_back(type_1); - } - } else if (p_bta_data->contextType == CONTEXT_TYPE_VOICE) { - StreamType type_2 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SRC - }; - StreamType type_3 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SINK - }; - disconnect_streams.push_back(type_3); - disconnect_streams.push_back(type_2); - } - LOG(WARNING) << __func__ << " size of disconnect_streams " << disconnect_streams.size(); - if (!sUcastClientInterface) break; - sUcastClientInterface->Disconnect(peer_.PeerAddress(), disconnect_streams); - - if ((p_bta_data->contextType == CONTEXT_TYPE_MUSIC) && ((peer_.GetPeerVoiceRxState() == StreamState::CONNECTED) || - (peer_.GetPeerVoiceTxState() == StreamState::CONNECTED))) { - LOG(WARNING) << __func__ << " voice connected remain in opened "; - } else if ((p_bta_data->contextType == CONTEXT_TYPE_VOICE) && ((peer_.GetPeerMusicTxState() == StreamState::CONNECTED) || - (peer_.GetPeerMusicRxState() == StreamState::CONNECTED))) { - LOG(WARNING) << __func__ << " Music connected remain in opened "; - } else { - LOG(WARNING) << __func__ << " Move in closing state "; - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateClosing); - } - } break; - - case BTA_ACM_STOP_EVT: { //Sumit: what is this case? - int contextType = p_acm->acm_connect.streams_info.stream_type.type; - btif_report_audio_state(peer_.PeerAddress(), BTACM_AUDIO_STATE_STOPPED, peer_.GetStreamContextType()); - if (contextType == CONTENT_TYPE_MEDIA) - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - } break; - - case BTA_ACM_CONNECT_EVT: {// above evnt can come and handle for voice/media case - tBTIF_ACM_STATUS status = (uint8_t)p_acm->state_info.stream_state; - int contextType = p_acm->state_info.stream_type.type; - - LOG_INFO( - LOG_TAG, "%s: Peer %s : event=%s status=%d", - __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str(),status); - if (peer_.CheckFlags(BtifAcmPeer::kFlagPendingLocalSuspend)) { - peer_.ClearFlags(BtifAcmPeer::kFlagPendingLocalSuspend); - BTIF_TRACE_DEBUG("%s: peer device is suspended, send MM any pending ACK", __func__); - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_SUCCESS); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_SUCCESS); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - break; - } - if (p_acm->state_info.stream_state == StreamState::CONNECTED) { - if (contextType == CONTENT_TYPE_MEDIA) { - if ((btif_acm_initiator.MusicActivePeer() == peer_.PeerAddress()) && - peer_.CheckFlags(BtifAcmPeer::kFlagPendingReconfigure)) { //recheck - LOG(INFO) << __PRETTY_FUNCTION__ << " : Peer " << peer_.PeerAddress() - << " : Reconfig done - calling startSession() to audio HAL"; - std::promise peer_ready_promise; - std::future peer_ready_future = peer_ready_promise.get_future(); - //TODO: cannot use peer addr here, must need group address. - btif_acm_source_start_session(peer_.PeerAddress()); - //Perform group operation here - } else if (((peer_.GetPeerVoiceRxState() == StreamState::CONNECTED) || - (peer_.GetPeerVoiceTxState() == StreamState::CONNECTED) || - (peer_.GetPeerMusicRxState() == StreamState::CONNECTED)) && - (peer_.GetPeerMusicTxState() == StreamState::CONNECTING) && - (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK)) { - BTIF_TRACE_DEBUG("%s: music Tx connected when either Voice Tx/Rx or Music Rx was connected," - "remain in opened state", __func__); - peer_.SetPeerMusicTxState(p_acm->state_info.stream_state); - BTIF_TRACE_DEBUG("%s: received connected state from BAP for Music TX, update state", __func__); - btif_report_connection_state(peer_.PeerAddress(), - BTACM_CONNECTION_STATE_CONNECTED, CONTEXT_TYPE_MUSIC); - } else if ((peer_.GetPeerMusicRxState() == StreamState::CONNECTING) && - (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC)) { - BTIF_TRACE_DEBUG("%s: received connected state from BAP for Music RX(recording), update state", __func__); - peer_.SetPeerMusicRxState(p_acm->state_info.stream_state); - btif_report_connection_state(peer_.PeerAddress(), - BTACM_CONNECTION_STATE_CONNECTED, CONTEXT_TYPE_MUSIC); - } -#if 0 - if (peer_.CheckFlags(BtifAcmPeer::kFlagPendingStart)) { - LOG(INFO) << __PRETTY_FUNCTION__ << " : Peer " << peer_.PeerAddress() - << " : Reconfig done - calling BTA_AvStart()"; - StreamType type_1; - if (current_active_profile_type != WMCP) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_MEDIA, - .direction = ASE_DIRECTION_SINK - }; - } else { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_LIVE, - .direction = ASE_DIRECTION_SRC - }; - } - std::vector start_streams; - start_streams.push_back(type_1); - if (!sUcastClientInterface) break; - sUcastClientInterface->Start(peer_.PeerAddress(), start_streams); - } -#endif - } else if (contextType == CONTENT_TYPE_CONVERSATIONAL) { - BTIF_TRACE_DEBUG("%s: voice context connected, remain in opened state" - " peer_.GetPeerVoiceTxState() %d peer_.GetPeerVoiceRxState() %d", - __func__, peer_.GetPeerVoiceTxState(), peer_.GetPeerVoiceRxState()); - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK && - (peer_.GetPeerVoiceTxState() != StreamState::CONNECTED)) { - peer_.SetPeerVoiceTxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceRxState() == StreamState::CONNECTED) { - BTIF_TRACE_DEBUG("%s: received connected state from BAP for voice TX, update state", __func__); - btif_report_connection_state(peer_.PeerAddress(), - BTACM_CONNECTION_STATE_CONNECTED, CONTEXT_TYPE_VOICE); - } - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC && - (peer_.GetPeerVoiceRxState() != StreamState::CONNECTED)) { - peer_.SetPeerVoiceRxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceTxState() == StreamState::CONNECTED) { - BTIF_TRACE_DEBUG("%s: received connected state from BAP for voice RX, update state", __func__); - btif_report_connection_state(peer_.PeerAddress(), - BTACM_CONNECTION_STATE_CONNECTED, CONTEXT_TYPE_VOICE); - } - } - } - } else if (p_acm->state_info.stream_state == StreamState::CONNECTING){ - if (contextType == CONTENT_TYPE_MEDIA) { - BTIF_TRACE_DEBUG("%s: received connecting state from BAP for MEDIA Tx or Rx, ignore", __func__); - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) - peer_.SetPeerMusicTxState(p_acm->state_info.stream_state); - else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) - peer_.SetPeerMusicRxState(p_acm->state_info.stream_state); - } else if (contextType == CONTENT_TYPE_CONVERSATIONAL) { - BTIF_TRACE_DEBUG("%s: received connecting state from BAP for CONVERSATIONAL Tx or Rx, ignore", __func__); - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerVoiceTxState(p_acm->state_info.stream_state); - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerVoiceRxState(p_acm->state_info.stream_state); - } - } - } - } break; - - case BTA_ACM_DISCONNECT_EVT: { - int context_type = p_acm->state_info.stream_type.type; - if (p_acm->state_info.stream_state == StreamState::DISCONNECTED) { - if (context_type == CONTENT_TYPE_MEDIA) { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerMusicTxState(p_acm->state_info.stream_state); - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerMusicRxState(p_acm->state_info.stream_state); - } - if (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), - BTACM_CONNECTION_STATE_DISCONNECTED, CONTEXT_TYPE_MUSIC); - } - if (peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTED && - peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - BTIF_TRACE_DEBUG("%s: received Media Tx/Rx disconnected state from BAP" - " when Voice Tx+Rx & Media Rx/Tx was disconnected, move in idle state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - } else { - BTIF_TRACE_DEBUG("%s: received Media Tx/Rx disconnected state from BAP" - " when either Voice Tx or Rx or Media Rx/Tx is connected, remain in opened state", __func__); - } - } else if (context_type == CONTENT_TYPE_CONVERSATIONAL) { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerVoiceTxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTED, CONTEXT_TYPE_VOICE); - if (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Tx," - " voice Rx, Music Tx & Rx are disconnected move in idle state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - } else { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Tx," - " voice Rx is disconnected but music Tx or Rx still not disconnected," - " remain in opened state", __func__); - } - } - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerVoiceRxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTED, CONTEXT_TYPE_VOICE); - if (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Rx," - " voice Tx, Music Tx & Rx are disconnected move in idle state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - } else { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Rx," - " voice Rx is disconnected but music Tx or Rx still not disconnected," - " remain in opened state", __func__); - } - } - } - } - } else if (p_acm->state_info.stream_state == StreamState::DISCONNECTING) { - if (context_type == CONTENT_TYPE_MEDIA) { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerMusicTxState(p_acm->state_info.stream_state); - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerMusicRxState(p_acm->state_info.stream_state); - } - btif_report_connection_state(peer_.PeerAddress(), - BTACM_CONNECTION_STATE_DISCONNECTING, CONTEXT_TYPE_MUSIC); - if ((peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTED || - peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTING) && - (peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTED || - peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTING) && - (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED || - peer_.GetPeerMusicTxState() == StreamState::DISCONNECTING) && - (peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED || - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTING)) { - BTIF_TRACE_DEBUG("%s: received Media Tx/Rx disconnecting state from BAP" - " when Voice Tx+Rx and Media Rx/Tx disconnected/ing, move in closing state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateClosing); - } else { - BTIF_TRACE_DEBUG("%s: received Media Tx/Rx disconnecting state from BAP" - " when either Voice Tx or Rx or Media Rx/Tx is connected, remain in opened state", __func__); - } - } else if (context_type == CONTENT_TYPE_CONVERSATIONAL) { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerVoiceTxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTING || - peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTING, CONTEXT_TYPE_VOICE); - if (((peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED) || - (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTING)) && - ((peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) || - (peer_.GetPeerMusicRxState() == StreamState::DISCONNECTING))) { - BTIF_TRACE_DEBUG("%s: received disconnecting state from BAP for voice Tx," - " voice Rx, music Tx+Rx are disconnected/ing move in closing state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateClosing); - } else { - BTIF_TRACE_DEBUG("%s: received disconnecting state from BAP for voice Tx," - " voice Rx is disconncted/ing but music Tx or Rx still not disconnected/ing," - " remain in opened state", __func__); - } - } - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerVoiceRxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTING || - peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTING, CONTEXT_TYPE_VOICE); - if (((peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED) || - (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTING)) && - ((peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) || - (peer_.GetPeerMusicRxState() == StreamState::DISCONNECTING))) { - BTIF_TRACE_DEBUG("%s: received disconnecting state from BAP for voice Rx," - " voice Tx, music Tx+Rx are disconnected/ing move in closing state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateClosing); - } else { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Rx," - " voice Tx is disconncted/ing but music Tx or Rx still not disconnected/ing," - " remain in opened state", __func__); - } - } - } - } - } - } - break; - - case BTIF_ACM_RECONFIG_REQ_EVT: { - std::vector reconf_streams; - StreamReconfig reconf_info; - CodecQosConfig cfg; - if (p_acm->acm_reconfig.streams_info.stream_type.type != CONTENT_TYPE_CONVERSATIONAL) { - reconf_info.stream_type.type = p_acm->acm_reconfig.streams_info.stream_type.type; - reconf_info.stream_type.audio_context = - p_acm->acm_reconfig.streams_info.stream_type.audio_context; - reconf_info.stream_type.direction = p_acm->acm_reconfig.streams_info.stream_type.direction; - reconf_info.reconf_type = p_acm->acm_reconfig.streams_info.reconf_type; - cfg = peer_.get_peer_media_codec_qos_config(); - reconf_info.codec_qos_config_pair.push_back(cfg); - reconf_streams.push_back(reconf_info); - } else { - reconf_info.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - reconf_info.stream_type.audio_context = CONTENT_TYPE_CONVERSATIONAL; - reconf_info.stream_type.direction = ASE_DIRECTION_SRC; - reconf_info.reconf_type = bluetooth::bap::ucast::StreamReconfigType::CODEC_CONFIG; - if (peer_.IsStereoHsType()) { - SelectCodecQosConfig(peer_.PeerAddress(), BAP, VOICE_CONTEXT, SRC, STEREO_HS_CONFIG_1); - } else { - SelectCodecQosConfig(peer_.PeerAddress(), BAP, VOICE_CONTEXT, SRC, EB_CONFIG); - } - cfg = peer_.get_peer_voice_rx_codec_qos_config(); - print_codec_parameters(cfg.codec_config); - print_qos_parameters(cfg.qos_config); - reconf_info.codec_qos_config_pair.push_back(cfg); - reconf_streams.push_back(reconf_info); - - reconf_info.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - reconf_info.stream_type.audio_context = CONTENT_TYPE_CONVERSATIONAL; - reconf_info.stream_type.direction = ASE_DIRECTION_SINK; - reconf_info.reconf_type = bluetooth::bap::ucast::StreamReconfigType::CODEC_CONFIG; - if (peer_.IsStereoHsType()) { - SelectCodecQosConfig(peer_.PeerAddress(), BAP, VOICE_CONTEXT, SRC, STEREO_HS_CONFIG_1); - } else { - SelectCodecQosConfig(peer_.PeerAddress(), BAP, VOICE_CONTEXT, SRC, EB_CONFIG); - } - cfg = peer_.get_peer_voice_tx_codec_qos_config(); - print_codec_parameters(cfg.codec_config); - print_qos_parameters(cfg.qos_config); - reconf_info.codec_qos_config_pair.push_back(cfg); - reconf_streams.push_back(reconf_info); - - peer_.SetPeerVoiceRxState(StreamState::RECONFIGURING); - peer_.SetPeerVoiceTxState(StreamState::RECONFIGURING); - } - if (!sUcastClientInterface) break; - sUcastClientInterface->Reconfigure(peer_.PeerAddress(), reconf_streams); - peer_.SetFlags(BtifAcmPeer::kFlagPendingReconfigure); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateReconfiguring); - } - break; - case BTA_ACM_CONFIG_EVT: { - tBTIF_ACM* p_acm_data = (tBTIF_ACM*)p_data; - uint16_t contextType = p_acm_data->state_info.stream_type.type; - uint16_t peer_latency_ms = 0; - uint32_t presen_delay = 0; - bool is_update_require = false; - if (contextType == CONTENT_TYPE_MEDIA) { - if (p_acm_data->state_info.stream_type.audio_context == CONTENT_TYPE_MEDIA) { - BTIF_TRACE_DEBUG("%s: compare with current media config", __PRETTY_FUNCTION__); - is_update_require = compare_codec_config_(current_media_config, p_acm_data->config_info.codec_config); - } else if (p_acm_data->state_info.stream_type.audio_context == CONTENT_TYPE_LIVE) { - BTIF_TRACE_DEBUG("%s: cache current_recording_config", __PRETTY_FUNCTION__); - current_recording_config = p_acm_data->config_info.codec_config; - } - if (mandatory_codec_selected) { - BTIF_TRACE_DEBUG("%s: Mandatory codec selected, do not store config", __PRETTY_FUNCTION__); - } else { - BTIF_TRACE_DEBUG("%s: store configuration", __PRETTY_FUNCTION__); - } - //Cache the peer latency in WMCP case - if (p_acm_data->state_info.stream_type.audio_context == CONTENT_TYPE_LIVE) { - BTIF_TRACE_DEBUG("%s: presentation delay[0] = %x", __func__, - p_acm_data->config_info.qos_config.ascs_configs[0].presentation_delay[0]); - BTIF_TRACE_DEBUG("%s: presentation delay[1] = %x", __func__, - p_acm_data->config_info.qos_config.ascs_configs[0].presentation_delay[1]); - BTIF_TRACE_DEBUG("%s: presentation delay[2] = %x", __func__, - p_acm_data->config_info.qos_config.ascs_configs[0].presentation_delay[2]); - presen_delay = static_cast(p_acm_data->config_info.qos_config.ascs_configs[0].presentation_delay[0]) | - static_cast(p_acm_data->config_info.qos_config.ascs_configs[0].presentation_delay[1] << 8) | - static_cast(p_acm_data->config_info.qos_config.ascs_configs[0].presentation_delay[2] << 16); - BTIF_TRACE_DEBUG("%s: presen_delay = %dus", __func__, presen_delay); - peer_latency_ms = presen_delay/1000; - BTIF_TRACE_DEBUG("%s: s_to_m latency = %dms", __func__, - p_acm_data->config_info.qos_config.cig_config.max_tport_latency_s_to_m); - peer_latency_ms += p_acm_data->config_info.qos_config.cig_config.max_tport_latency_s_to_m; - peer_.SetPeerLatency(peer_latency_ms); - BTIF_TRACE_DEBUG("%s: cached peer Latency = %dms", __func__, peer_.GetPeerLatency()); - } - if (is_update_require) { - current_media_config = p_acm_data->config_info.codec_config; - BTIF_TRACE_DEBUG("%s: current_media_config.codec_specific_3: %" - PRIi64, __func__, current_media_config.codec_specific_3); - btif_acm_update_lc3q_params(¤t_media_config.codec_specific_3, p_acm_data); - btif_acm_report_source_codec_state(peer_.PeerAddress(), current_media_config, - unicast_codecs_capabilities, - unicast_codecs_capabilities, CONTEXT_TYPE_MUSIC); - } - } else if (contextType == CONTENT_TYPE_CONVERSATIONAL && - p_acm_data->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - BTIF_TRACE_DEBUG("%s: cache current_voice_config", __PRETTY_FUNCTION__); - current_voice_config = p_acm_data->config_info.codec_config; - BTIF_TRACE_DEBUG("%s: current_voice_config.codec_specific_3: %" - PRIi64, __func__, current_voice_config.codec_specific_3); - btif_acm_update_lc3q_params(¤t_voice_config.codec_specific_3, p_acm_data); - btif_acm_report_source_codec_state(peer_.PeerAddress(), current_voice_config, - unicast_codecs_capabilities, - unicast_codecs_capabilities, CONTEXT_TYPE_VOICE); - } - //Handle BAP START if reconfig comes in mid of streaming - //peer_.SetStreamReconfigInfo(p_acm->acm_reconfig); - //TODO: local capabilities - //CodecConfig record = p_bta_data->acm_reconfig.codec_config; - //saving codec config as negotiated parameter as true - //btif_pacs_add_record(peer_.PeerAddress(), true, CodecDirection::CODEC_DIR_SRC, &record); - - } break; - - case BTA_ACM_CONN_UPDATE_TIMEOUT_EVT: - peer_.SetConnUpdateMode(BtifAcmPeer::kFlagRelaxedMode); - break; - - default: - BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s", - __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str()); - return false; - } - return true; -} - -bool btif_acm_check_if_requested_devices_started() { - std::vector::iterator itr; - if ((btif_acm_initiator.locked_devices).size() > 0) { - for (itr = (btif_acm_initiator.locked_devices).begin(); itr != (btif_acm_initiator.locked_devices).end(); itr++) { - BTIF_TRACE_DEBUG("%s: address =%s", __func__, *itr->ToString().c_str()); - BtifAcmPeer* peer = btif_acm_initiator.FindPeer(*itr); - if ((peer == nullptr) || (peer != nullptr && !peer->IsStreaming())) { - break; - } - } - if (itr == (btif_acm_initiator.locked_devices).end()) { - return true; - } - } - return false; -} - -bool btif_acm_check_if_requested_devices_stopped() { - std::vector::iterator itr; - if ((btif_acm_initiator.locked_devices).size() > 0) { - for (itr = (btif_acm_initiator.locked_devices).begin(); itr != (btif_acm_initiator.locked_devices).end(); itr++) { - BTIF_TRACE_DEBUG("%s: address =%s", __func__, *itr->ToString().c_str()); - BtifAcmPeer* peer = btif_acm_initiator.FindPeer(*itr); - if ((peer == nullptr) || (peer != nullptr /*&& !peer->IsSuspended()*/)) { - break; - } - } - if (itr == (btif_acm_initiator.locked_devices).end()) { - return true; - } - } - return false; -} - -void BtifAcmStateMachine::StateStarted::OnEnter() { - BTIF_TRACE_DEBUG("%s: Peer %s, Peer SetId = %d, MusicActiveSetId = %d, ContextType = %d", __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str(), - peer_.SetId(), btif_acm_initiator.MusicActiveCSetId(), peer_.GetContextType()); - - if(btif_acm_initiator.IsConnUpdateEnabled()) { - //Starting the timer for 5 seconds before moving to relaxed state as - //stop event or start streaming event moght immediately come - //which requires aggresive interval - btif_acm_check_and_start_conn_Interval_timer(&peer_); - } - - // Report that we have entered the Streaming stage. Usually, this should - // be followed by focus grant. See update_audio_focus_state() - btif_report_audio_state(peer_.PeerAddress(), BTACM_AUDIO_STATE_STARTED, peer_.GetStreamContextType()); - if (alarm_is_scheduled(btif_acm_initiator.AcmGroupProcedureTimer())) { - btif_acm_check_and_cancel_group_procedure_timer(btif_acm_initiator.MusicActiveCSetId()); - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_SUCCESS); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_SUCCESS); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - } else { - BTIF_TRACE_DEBUG("%s:no group procedure timer running ACK pending cmd", __func__); - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_SUCCESS); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_SUCCESS); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - } -#if 0 - if ((btif_acm_initiator.GetGroupLockStatus(peer_.SetId()) != BtifAcmInitiator::kFlagStatusUnknown) && - alarm_is_scheduled(btif_acm_initiator.AcmGroupProcedureTimer())) { - BTIF_TRACE_DEBUG("%s: All locked and start requested device have started, ack mm audio", __func__); - //in this case, we need to change channel mode to stereo - btif_acm_check_and_cancel_group_procedure_timer(btif_acm_initiator.MusicActiveCSetId()); - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_SUCCESS); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_SUCCESS); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - btif_acm_check_and_start_lock_release_timer(btif_acm_initiator.MusicActiveCSetId()); - } - - //Start the lock release timer here. - if ((btif_acm_initiator.MusicActiveCSetId() != INVALID_SET_ID) && - (btif_acm_initiator.GetGroupLockStatus(btif_acm_initiator.MusicActiveCSetId()) == BtifAcmInitiator::kFlagStatusLocked)) { - BTIF_TRACE_DEBUG("%s: ", __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str()); - btif_acm_check_and_start_lock_release_timer(btif_acm_initiator.MusicActiveCSetId()); - } - if (!btif_acm_initiator.IsMusicActiveGroupStarted()) { - if (peer_.SetId() == btif_acm_initiator.MusicActiveCSetId()) - btif_acm_initiator.SetMusicActiveGroupStarted(true); - } -#endif - -} - -void BtifAcmStateMachine::StateStarted::OnExit() { - BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str()); -} - -bool BtifAcmStateMachine::StateStarted::ProcessEvent(uint32_t event, void* p_data) { - tBTIF_ACM* p_acm = (tBTIF_ACM*)p_data; - - BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s music_active_peer=%s voice_active_peer=%s", - __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str(), - peer_.FlagsToString().c_str(), - logbool(peer_.IsPeerActiveForMusic()).c_str(), - logbool(peer_.IsPeerActiveForVoice()).c_str()); - - switch (event) { - case BTIF_ACM_STOP_STREAM_REQ_EVT: - case BTIF_ACM_SUSPEND_STREAM_REQ_EVT: { - LOG_INFO(LOG_TAG, "%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str(), - peer_.FlagsToString().c_str()); - peer_.SetFlags(BtifAcmPeer::kFlagPendingLocalSuspend); - - StreamType type_1; - std::vector stop_streams; - if (peer_.GetStreamContextType() == CONTEXT_TYPE_MUSIC) { - if (current_active_profile_type != WMCP) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_MEDIA, - .direction = ASE_DIRECTION_SINK - }; - stop_streams.push_back(type_1); - } else { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_LIVE, - .direction = ASE_DIRECTION_SRC - }; - stop_streams.push_back(type_1); - } - } else if (peer_.GetStreamContextType() == CONTEXT_TYPE_VOICE) { - StreamType type_2; - type_1 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SINK - }; - type_2 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SRC - }; - stop_streams.push_back(type_2); - stop_streams.push_back(type_1); - } - if(btif_acm_initiator.IsConnUpdateEnabled()) { - //Cancel the timer if start streamng comes before - // 5 seconds while moving the interval to relaxed mode. - if (alarm_is_scheduled(btif_acm_initiator.AcmConnIntervalTimer())) { - btif_acm_check_and_cancel_conn_Interval_timer(); - } - else { - peer_.SetConnUpdateMode(BtifAcmPeer::kFlagAggresiveMode); - } - } - - if (!sUcastClientInterface) break; - sUcastClientInterface->Stop(peer_.PeerAddress(), stop_streams); - } - break; - - case BTIF_ACM_DISCONNECT_REQ_EVT: { - int contextType = p_acm->state_info.stream_type.type; - LOG_INFO(LOG_TAG, "%s: Peer %s : event=%s flags=%s contextType=%d", __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str(), - peer_.FlagsToString().c_str(), contextType); - - tBTIF_ACM_CONN_DISC* p_bta_data = (tBTIF_ACM_CONN_DISC*)p_data; - std::vector disconnect_streams; - if (p_bta_data->contextType == CONTEXT_TYPE_MUSIC) { - StreamType type_1; - if (p_bta_data->profileType & (BAP|GCP)) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_MEDIA, - .direction = ASE_DIRECTION_SINK - }; - disconnect_streams.push_back(type_1); - } - if (p_bta_data->profileType & WMCP) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_LIVE, - .direction = ASE_DIRECTION_SRC - }; - disconnect_streams.push_back(type_1); - } - } else if (p_bta_data->contextType == CONTEXT_TYPE_MUSIC_VOICE) { - StreamType type_2 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SRC - }; - StreamType type_3 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SINK - }; - disconnect_streams.push_back(type_3); - disconnect_streams.push_back(type_2); - StreamType type_1; - if (p_bta_data->profileType & (BAP|GCP)) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_MEDIA, - .direction = ASE_DIRECTION_SINK - }; - disconnect_streams.push_back(type_1); - } - if (p_bta_data->profileType & WMCP) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_LIVE, - .direction = ASE_DIRECTION_SRC - }; - disconnect_streams.push_back(type_1); - } - } else if (p_bta_data->contextType == CONTEXT_TYPE_VOICE) { - StreamType type_2 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SRC - }; - StreamType type_3 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SINK - }; - disconnect_streams.push_back(type_3); - disconnect_streams.push_back(type_2); - } - LOG(WARNING) << __func__ << " size of disconnect_streams " << disconnect_streams.size(); - if (!sUcastClientInterface) break; - sUcastClientInterface->Disconnect(peer_.PeerAddress(), disconnect_streams); - - // Inform the application that we are disconnecting - if ((p_bta_data->contextType == CONTEXT_TYPE_MUSIC) && ((peer_.GetPeerVoiceRxState() == StreamState::CONNECTED) || - (peer_.GetPeerVoiceTxState() == StreamState::CONNECTED))) { - LOG(WARNING) << __func__ << " voice connected move in opened state "; - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateOpened); - } else if ((p_bta_data->contextType == CONTEXT_TYPE_VOICE) && ((peer_.GetPeerMusicTxState() == StreamState::CONNECTED) || - (peer_.GetPeerMusicRxState() == StreamState::CONNECTED))) { - LOG(WARNING) << __func__ << " Music connected remain in started state "; - } else { - LOG(WARNING) << __func__ << " Move in closing state "; - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateClosing); - } - } - break; - - case BTA_ACM_STOP_EVT: { - int contextType = p_acm->state_info.stream_type.type; - LOG_INFO(LOG_TAG, "%s: Peer %s : event=%s flags=%s", __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str(), - peer_.FlagsToString().c_str()); - if (contextType == CONTENT_TYPE_MEDIA) { - BTIF_TRACE_DEBUG("%s: STOPPING event came from BAP for Media, ignore", __func__); - } else if (contextType == CONTENT_TYPE_CONVERSATIONAL) { - BTIF_TRACE_DEBUG("%s: STOPPING event came from BAP for Voice, ignore", __func__); - } - } - break; - - case BTA_ACM_DISCONNECT_EVT: { - int context_type = p_acm->state_info.stream_type.type; - if (p_acm->state_info.stream_state == StreamState::DISCONNECTED) { - if (context_type == CONTENT_TYPE_MEDIA) { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerMusicTxState(p_acm->state_info.stream_state); - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerMusicRxState(p_acm->state_info.stream_state); - } - if (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), - BTACM_CONNECTION_STATE_DISCONNECTED, CONTEXT_TYPE_MUSIC); - } - if (peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTED && - peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - BTIF_TRACE_DEBUG("%s: received Media Tx/Rx disconnected state from BAP" - " when Voice Tx+Rx & Media Rx/Tx was disconnected, move in idle state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - } else { - BTIF_TRACE_DEBUG("%s: received Media Tx/Rx disconnected state from BAP" - " when either Voice Tx or Rx or Media Rx/Tx is connected, remain in started state", __func__); - } - } else if (context_type == CONTENT_TYPE_CONVERSATIONAL) { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerVoiceTxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTED, CONTEXT_TYPE_VOICE); - if (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Tx," - " voice Rx, Music Tx & Rx are disconnected move in idle state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - } else { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Tx," - " voice Rx is disconnected but music Tx or Rx still not disconnected," - " remain in started state", __func__); - } - } - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerVoiceRxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTED, CONTEXT_TYPE_VOICE); - if (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Rx," - " voice Tx, Music Tx & Rx are disconnected move in idle state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - } else { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Rx," - " voice Rx is disconnected but music Tx or Rx still not disconnected," - " remain in started state", __func__); - } - } - } - } - } else if (p_acm->state_info.stream_state == StreamState::DISCONNECTING) { - if (context_type == CONTENT_TYPE_MEDIA) { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerMusicTxState(p_acm->state_info.stream_state); - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerMusicRxState(p_acm->state_info.stream_state); - } - if ((peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTED || - peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTING) && - (peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTED || - peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTING) && - (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED || - peer_.GetPeerMusicTxState() == StreamState::DISCONNECTING) && - (peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED || - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTING)) { - BTIF_TRACE_DEBUG("%s: received Media Tx/Rx disconnecting state from BAP" - " when Voice Tx+Rx and Media Rx/Tx disconnected/ing, move in closing state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateClosing); - } else { - if (peer_.GetStreamContextType() == CONTEXT_TYPE_MUSIC) { - std::vector disconnect_streams; - btif_report_audio_state(peer_.PeerAddress(), BTACM_AUDIO_STATE_STOPPED, CONTEXT_TYPE_MUSIC); - BTIF_TRACE_DEBUG("%s: received Media Tx/Rx disconnecting state from BAP while streaming" - " when either Voice Tx or Rx or Media Rx/Tx is connected, move to opened state", __func__); - if (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTING) { - BTIF_TRACE_DEBUG("%s: Received disconnecting for Music-Tx, initiate for Rx also", __func__); - StreamType type_1; - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_LIVE, - .direction = ASE_DIRECTION_SRC - }; - disconnect_streams.push_back(type_1); - if (!sUcastClientInterface) break; - sUcastClientInterface->Disconnect(peer_.PeerAddress(), disconnect_streams); - } - if (peer_.GetPeerMusicRxState() == StreamState::DISCONNECTING) { - BTIF_TRACE_DEBUG("%s: Received disconnecting for Music-Rx, initiate for Tx also", __func__); - StreamType type_1; - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_MEDIA, - .direction = ASE_DIRECTION_SINK - }; - disconnect_streams.push_back(type_1); - if (!sUcastClientInterface) break; - sUcastClientInterface->Disconnect(peer_.PeerAddress(), disconnect_streams); - } - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateOpened); - } else { - BTIF_TRACE_DEBUG("%s: received Media Tx/Rx disconnecting state from BAP" - " when either Voice Tx or Rx or Media Rx/Tx is connected, remain in started state", __func__); - } - } - btif_report_connection_state(peer_.PeerAddress(), - BTACM_CONNECTION_STATE_DISCONNECTING, CONTEXT_TYPE_MUSIC); - } else if (context_type == CONTENT_TYPE_CONVERSATIONAL) { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerVoiceTxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTING || - peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTED) { - if (((peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED) || - (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTING)) && - ((peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) || - (peer_.GetPeerMusicRxState() == StreamState::DISCONNECTING))) { - BTIF_TRACE_DEBUG("%s: received disconnecting state from BAP for voice Tx," - " voice Rx, music Tx+Rx are disconnected/ing move in closing state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateClosing); - } else { - if (peer_.GetStreamContextType() == CONTEXT_TYPE_VOICE) { - btif_report_audio_state(peer_.PeerAddress(), BTACM_AUDIO_STATE_STOPPED, CONTEXT_TYPE_VOICE); - BTIF_TRACE_DEBUG("%s: received disconnecting state from BAP for voice Tx while streaming," - " voice Rx is disconncted/ing but music Tx or Rx still not disconnected/ing," - " move to opened state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateOpened); - } else { - BTIF_TRACE_DEBUG("%s: received disconnecting state from BAP for voice Tx," - " voice Rx is disconncted/ing but music Tx or Rx still not disconnected/ing," - " remain in started state", __func__); - } - } - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTING, CONTEXT_TYPE_VOICE); - } - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerVoiceRxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTING || - peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTED) { - if (((peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED) || - (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTING)) && - ((peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) || - (peer_.GetPeerMusicRxState() == StreamState::DISCONNECTING))) { - BTIF_TRACE_DEBUG("%s: received disconnecting state from BAP for voice Rx," - " voice Tx, music Tx+Rx are disconnected/ing move in closing state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateClosing); - } else { - if (peer_.GetStreamContextType() == CONTEXT_TYPE_VOICE) { - btif_report_audio_state(peer_.PeerAddress(), BTACM_AUDIO_STATE_STOPPED, CONTEXT_TYPE_VOICE); - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Rx while streaming," - " voice Tx is disconncted/ing but music Tx or Rx still not disconnected/ing," - " move to Opened state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateOpened); - } else { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Rx," - " voice Tx is disconncted/ing but music Tx or Rx still not disconnected/ing," - " remain in started state", __func__); - } - } - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTING, CONTEXT_TYPE_VOICE); - } - } - } - } - } - break; - - case BTA_ACM_CONNECT_EVT: {// above evnt can come and handle for voice/media case - int contextType = p_acm->state_info.stream_type.type; - LOG_INFO( - LOG_TAG, "%s: Peer %s : event=%s context=%d", - __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str(), contextType); - LOG_INFO( - LOG_TAG, "%s: context=%d, converted=%d, Streaming context=%d", - __PRETTY_FUNCTION__, contextType, btif_acm_bap_to_acm_context(contextType), peer_.GetStreamContextType()); - if (btif_acm_bap_to_acm_context(contextType) != peer_.GetStreamContextType()) { - if (contextType == CONTENT_TYPE_MEDIA) { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - if (p_acm->state_info.stream_state == StreamState::CONNECTED) { - BTIF_TRACE_DEBUG("%s: received connected state from BAP for Music Rx, update state", __func__); - peer_.SetPeerMusicRxState(p_acm->state_info.stream_state); - } else if (p_acm->state_info.stream_state == StreamState::CONNECTING){ - BTIF_TRACE_DEBUG("%s: received connecting state from BAP for Music Rx, ignore", __func__); - peer_.SetPeerMusicRxState(p_acm->state_info.stream_state); - } - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - if (p_acm->state_info.stream_state == StreamState::CONNECTED) { - BTIF_TRACE_DEBUG("%s: received connected state from BAP for Music Tx, update state", __func__); - peer_.SetPeerMusicTxState(p_acm->state_info.stream_state); - } else if (p_acm->state_info.stream_state == StreamState::CONNECTING){ - BTIF_TRACE_DEBUG("%s: received connecting state from BAP for Music Tx, ignore", __func__); - peer_.SetPeerMusicTxState(p_acm->state_info.stream_state); - } - } - if (p_acm->state_info.stream_state == StreamState::CONNECTED) - btif_report_connection_state(peer_.PeerAddress(), - BTACM_CONNECTION_STATE_CONNECTED, CONTEXT_TYPE_MUSIC); - } else if (contextType == CONTENT_TYPE_CONVERSATIONAL) { - if (p_acm->state_info.stream_state == StreamState::CONNECTED) { - BTIF_TRACE_DEBUG("%s: voice context connected, remain in started state", __func__); - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerVoiceTxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceRxState() == StreamState::CONNECTED) { - BTIF_TRACE_DEBUG("%s: received connected state from BAP for voice Tx, update state", __func__); - btif_report_connection_state(peer_.PeerAddress(), - BTACM_CONNECTION_STATE_CONNECTED, CONTEXT_TYPE_VOICE); - } - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerVoiceRxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceTxState() == StreamState::CONNECTED) { - BTIF_TRACE_DEBUG("%s: received connected state from BAP for voice Rx, update state", __func__); - btif_report_connection_state(peer_.PeerAddress(), - BTACM_CONNECTION_STATE_CONNECTED, CONTEXT_TYPE_VOICE); - } - } - } else if (p_acm->state_info.stream_state == StreamState::CONNECTING) { - BTIF_TRACE_DEBUG("%s: received connecting state from BAP for voice Tx or Rx, ignore", __func__); - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerVoiceTxState(p_acm->state_info.stream_state); - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerVoiceRxState(p_acm->state_info.stream_state); - } - } - } - } else { - if (peer_.CheckFlags(BtifAcmPeer::kFlagPendingLocalSuspend)) { - peer_.ClearFlags(BtifAcmPeer::kFlagPendingLocalSuspend); - BTIF_TRACE_DEBUG("%s: peer device is suspended, send MM any pending ACK", __func__); - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_SUCCESS); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_SUCCESS); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - BTIF_TRACE_DEBUG("%s: report STOP to apps and move to Opened", __func__); - btif_report_audio_state(peer_.PeerAddress(), BTACM_AUDIO_STATE_STOPPED, peer_.GetStreamContextType()); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateOpened); - } - } - if (alarm_is_scheduled(btif_acm_initiator.AcmGroupProcedureTimer())) - btif_acm_check_and_cancel_group_procedure_timer(btif_acm_initiator.MusicActiveCSetId()); - - } break; - - case BTIF_ACM_RECONFIG_REQ_EVT: { - BTIF_TRACE_DEBUG("%s: sending stop to BAP before reconfigure", __func__); - btif_a2dp_source_end_session(active_bda); - peer_.SetFlags(BtifAcmPeer::kFlagPendingLocalSuspend); - StreamType type_1; - std::vector stop_streams; - if (peer_.GetStreamContextType() == CONTEXT_TYPE_MUSIC) { - if (current_active_profile_type != WMCP) { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_MEDIA, - .direction = ASE_DIRECTION_SINK - }; - stop_streams.push_back(type_1); - } else { - type_1 = {.type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_LIVE, - .direction = ASE_DIRECTION_SRC - }; - stop_streams.push_back(type_1); - } - } else if (peer_.GetStreamContextType() == CONTEXT_TYPE_VOICE) { - StreamType type_2; - type_1 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SINK - }; - type_2 = {.type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SRC - }; - stop_streams.push_back(type_2); - stop_streams.push_back(type_1); - } - if (!sUcastClientInterface) break; - sUcastClientInterface->Stop(peer_.PeerAddress(), stop_streams); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateReconfiguring); - } - break; - - case BTA_ACM_CONFIG_EVT: { - tBTIF_ACM* p_acm_data = (tBTIF_ACM*)p_data; - uint16_t contextType = p_acm_data->state_info.stream_type.type; - uint16_t peer_latency_ms = 0; - uint32_t presen_delay = 0; - bool is_update_require = false; - if (contextType == CONTENT_TYPE_MEDIA) { - if (p_acm_data->state_info.stream_type.audio_context == CONTENT_TYPE_MEDIA) { - BTIF_TRACE_DEBUG("%s: compare current_media_config", __PRETTY_FUNCTION__); - is_update_require = compare_codec_config_(current_media_config, p_acm_data->config_info.codec_config); - } else if (p_acm_data->state_info.stream_type.audio_context == CONTENT_TYPE_LIVE) { - BTIF_TRACE_DEBUG("%s: cache current_recording_config", __PRETTY_FUNCTION__); - current_recording_config = p_acm_data->config_info.codec_config; - } - if (mandatory_codec_selected) { - BTIF_TRACE_DEBUG("%s: Mandatory codec selected, do not store config", __PRETTY_FUNCTION__); - } else { - BTIF_TRACE_DEBUG("%s: store configuration", __PRETTY_FUNCTION__); - } - //Cache the peer latency in WMCP case - if (p_acm_data->state_info.stream_type.audio_context == CONTENT_TYPE_LIVE) { - BTIF_TRACE_DEBUG("%s: presentation delay[0] = %x", __func__, - p_acm_data->config_info.qos_config.ascs_configs[0].presentation_delay[0]); - BTIF_TRACE_DEBUG("%s: presentation delay[1] = %x", __func__, - p_acm_data->config_info.qos_config.ascs_configs[0].presentation_delay[1]); - BTIF_TRACE_DEBUG("%s: presentation delay[2] = %x", __func__, - p_acm_data->config_info.qos_config.ascs_configs[0].presentation_delay[2]); - presen_delay = static_cast(p_acm_data->config_info.qos_config.ascs_configs[0].presentation_delay[0]) | - static_cast(p_acm_data->config_info.qos_config.ascs_configs[0].presentation_delay[1] << 8) | - static_cast(p_acm_data->config_info.qos_config.ascs_configs[0].presentation_delay[2] << 16); - BTIF_TRACE_DEBUG("%s: presen_delay = %dus", __func__, presen_delay); - peer_latency_ms = presen_delay/1000; - BTIF_TRACE_DEBUG("%s: s_to_m latency = %dms", __func__, - p_acm_data->config_info.qos_config.cig_config.max_tport_latency_s_to_m); - peer_latency_ms += p_acm_data->config_info.qos_config.cig_config.max_tport_latency_s_to_m; - peer_.SetPeerLatency(peer_latency_ms); - BTIF_TRACE_DEBUG("%s: cached peer Latency = %dms", __func__, peer_.GetPeerLatency()); - } - if (is_update_require) { - current_media_config = p_acm_data->config_info.codec_config; - BTIF_TRACE_DEBUG("%s: current_media_config.codec_specific_3: %" - PRIi64, __func__, current_media_config.codec_specific_3); - btif_acm_update_lc3q_params(¤t_media_config.codec_specific_3, p_acm_data); - btif_acm_report_source_codec_state(peer_.PeerAddress(), current_media_config, - unicast_codecs_capabilities, - unicast_codecs_capabilities, CONTEXT_TYPE_MUSIC); - } - } else if (contextType == CONTENT_TYPE_CONVERSATIONAL && - p_acm_data->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - BTIF_TRACE_DEBUG("%s: cache current_voice_config", __PRETTY_FUNCTION__); - current_voice_config = p_acm_data->config_info.codec_config; - BTIF_TRACE_DEBUG("%s: current_voice_config.codec_specific_3: %" - PRIi64, __func__, current_voice_config.codec_specific_3); - btif_acm_update_lc3q_params(¤t_voice_config.codec_specific_3, p_acm_data); - btif_acm_report_source_codec_state(peer_.PeerAddress(), current_voice_config, - unicast_codecs_capabilities, - unicast_codecs_capabilities, CONTEXT_TYPE_VOICE); - } - //Handle BAP START if reconfig comes in mid of streaming - //peer_.SetStreamReconfigInfo(p_acm->acm_reconfig); - //TODO: local capabilities - //CodecConfig record = p_bta_data->acm_reconfig.codec_config; - //saving codec config as negotiated parameter as true - //btif_pacs_add_record(peer_.PeerAddress(), true, CodecDirection::CODEC_DIR_SRC, &record); - - } break; - - case BTA_ACM_CONN_UPDATE_TIMEOUT_EVT: - peer_.SetConnUpdateMode(BtifAcmPeer::kFlagRelaxedMode); - break; - - default: - BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s", - __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str()); - return false; - } - - return true; -} - -void BtifAcmStateMachine::StateReconfiguring::OnEnter() { - BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str()); - if(btif_acm_initiator.IsConnUpdateEnabled()) { - //Cancel the timer if running if not, move to aggressive mode - if (alarm_is_scheduled(btif_acm_initiator.AcmConnIntervalTimer())) { - btif_acm_check_and_cancel_conn_Interval_timer(); - } else { - BTIF_TRACE_DEBUG("%s: conn timer not running, push aggressive intervals", __func__); - peer_.SetConnUpdateMode(BtifAcmPeer::kFlagAggresiveMode); - } - } -} - -void BtifAcmStateMachine::StateReconfiguring::OnExit() { - BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str()); -} - -bool BtifAcmStateMachine::StateReconfiguring::ProcessEvent(uint32_t event, void* p_data) { - tBTIF_ACM* p_acm = (tBTIF_ACM*)p_data; - BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s music_active_peer=%s voice_active_peer=%s", - __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str(), - peer_.FlagsToString().c_str(), - logbool(peer_.IsPeerActiveForMusic()).c_str(), - logbool(peer_.IsPeerActiveForVoice()).c_str()); - - switch (event) { - case BTIF_ACM_SUSPEND_STREAM_REQ_EVT: - - case BTA_ACM_STOP_EVT: { - BTIF_TRACE_DEBUG("%s: STOPPING event from BAP, ignore", __func__); - } break; - - case BTA_ACM_RECONFIG_EVT: { - BTIF_TRACE_DEBUG("%s: received reconfiguring state from BAP, ignore", __func__); - } break; - - case BTA_ACM_CONFIG_EVT: { - uint16_t contextType = p_acm->state_info.stream_type.type; - uint16_t peer_latency_ms = 0; - uint32_t presen_delay = 0; - bool is_update_require = false; - if (contextType == CONTENT_TYPE_MEDIA) { - if (p_acm->state_info.stream_type.audio_context == CONTENT_TYPE_MEDIA) { - BTIF_TRACE_DEBUG("%s: compare current_media_config", __PRETTY_FUNCTION__); - is_update_require = compare_codec_config_(current_media_config, p_acm->config_info.codec_config); - } else if (p_acm->state_info.stream_type.audio_context == CONTENT_TYPE_LIVE) { - BTIF_TRACE_DEBUG("%s: cache current_recording_config", __PRETTY_FUNCTION__); - current_recording_config = p_acm->config_info.codec_config; - } - //Cache the peer latency in WMCP case - if (peer_.GetRcfgProfileType() == WMCP) { - BTIF_TRACE_DEBUG("%s: presentation delay[0] = %x", __func__, - p_acm->config_info.qos_config.ascs_configs[0].presentation_delay[0]); - BTIF_TRACE_DEBUG("%s: presentation delay[1] = %x", __func__, - p_acm->config_info.qos_config.ascs_configs[0].presentation_delay[1]); - BTIF_TRACE_DEBUG("%s: presentation delay[2] = %x", __func__, - p_acm->config_info.qos_config.ascs_configs[0].presentation_delay[2]); - presen_delay = static_cast(p_acm->config_info.qos_config.ascs_configs[0].presentation_delay[0]) | - static_cast(p_acm->config_info.qos_config.ascs_configs[0].presentation_delay[1] << 8) | - static_cast(p_acm->config_info.qos_config.ascs_configs[0].presentation_delay[2] << 16); - BTIF_TRACE_DEBUG("%s: presen_delay = %dus", __func__, presen_delay); - peer_latency_ms = presen_delay/1000; - BTIF_TRACE_DEBUG("%s: s_to_m latency = %dms", __func__, - p_acm->config_info.qos_config.cig_config.max_tport_latency_s_to_m); - peer_latency_ms += p_acm->config_info.qos_config.cig_config.max_tport_latency_s_to_m; - peer_.SetPeerLatency(peer_latency_ms); - BTIF_TRACE_DEBUG("%s: cached peer Latency = %dms", __func__, peer_.GetPeerLatency()); - } - if (is_update_require) { - current_media_config = p_acm->config_info.codec_config; - BTIF_TRACE_DEBUG("%s: current_media_config.codec_specific_3: %" - PRIi64, __func__, current_media_config.codec_specific_3); - btif_acm_update_lc3q_params(¤t_media_config.codec_specific_3, p_acm); - btif_acm_report_source_codec_state(peer_.PeerAddress(), current_media_config, - unicast_codecs_capabilities, - unicast_codecs_capabilities, CONTEXT_TYPE_MUSIC); - } - } else if (contextType == CONTENT_TYPE_CONVERSATIONAL) { - BTIF_TRACE_DEBUG("%s: cache current_voice_config"); - current_voice_config = p_acm->config_info.codec_config; - BTIF_TRACE_DEBUG("%s: current_voice_config.codec_specific_3: %" - PRIi64, __func__, current_voice_config.codec_specific_3); - btif_acm_update_lc3q_params(¤t_voice_config.codec_specific_3, p_acm); - } - } break; - - case BTA_ACM_CONNECT_EVT: { - uint8_t status = (uint8_t)p_acm->state_info.stream_state; - LOG_INFO( - LOG_TAG, "%s: Peer %s : event=%s flags=%s status=%d", - __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str(), peer_.FlagsToString().c_str(), - status); - if (peer_.CheckFlags(BtifAcmPeer::kFlagPendingReconfigure)) { - if (p_acm->state_info.stream_state == StreamState::CONNECTED) { - if (p_acm->state_info.stream_type.type == CONTENT_TYPE_MEDIA) { - BTIF_TRACE_DEBUG("%s: Reconfig complete, move in opened state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateOpened); - } else { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerVoiceTxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceRxState() == StreamState::CONNECTED) { - BTIF_TRACE_DEBUG("%s: Report Call audio config to apps? move to opened when both Voice Tx and Rx done", __func__); - BTIF_TRACE_DEBUG("%s: received connected state from BAP for voice Tx, move in opened state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateOpened); - } - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerVoiceRxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceTxState() == StreamState::CONNECTED) { - BTIF_TRACE_DEBUG("%s: Report Call audio config to apps? move to opened when both Voice Tx and Rx done", __func__); - BTIF_TRACE_DEBUG("%s: received connected state from BAP for voice Rx, move in opened state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateOpened); - } - } - } - } - break; - } - if (peer_.CheckFlags(BtifAcmPeer::kFlagPendingLocalSuspend)) { - peer_.ClearFlags(BtifAcmPeer::kFlagPendingLocalSuspend); - BTIF_TRACE_DEBUG("%s: peer device is suspended, send MM any pending ACK", __func__); - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_SUCCESS); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_SUCCESS); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - if (alarm_is_scheduled(btif_acm_initiator.AcmGroupProcedureTimer())) - btif_acm_check_and_cancel_group_procedure_timer(btif_acm_initiator.MusicActiveCSetId()); - btif_report_audio_state(peer_.PeerAddress(), BTACM_AUDIO_STATE_STOPPED, peer_.GetStreamContextType()); - std::vector reconf_streams; - StreamReconfig reconf_info; - CodecQosConfig cfg; - reconf_info.stream_type.type = CONTENT_TYPE_MEDIA; - // TODO to change audio context based on use case ( media or gaming or Live audio) - if (peer_.GetRcfgProfileType() != WMCP) { - reconf_info.stream_type.audio_context = CONTENT_TYPE_MEDIA; - reconf_info.stream_type.direction = ASE_DIRECTION_SINK; - } else { - reconf_info.stream_type.audio_context = CONTENT_TYPE_LIVE; - reconf_info.stream_type.direction = ASE_DIRECTION_SRC; - } - reconf_info.reconf_type = bluetooth::bap::ucast::StreamReconfigType::CODEC_CONFIG; - cfg = peer_.get_peer_media_codec_qos_config(); - reconf_info.codec_qos_config_pair.push_back(cfg); - reconf_streams.push_back(reconf_info); - peer_.SetFlags(BtifAcmPeer::kFlagPendingReconfigure); - if (!sUcastClientInterface) break; - sUcastClientInterface->Reconfigure(peer_.PeerAddress(), reconf_streams); - } - } break; - - case BTA_ACM_DISCONNECT_EVT: { - int context_type = p_acm->state_info.stream_type.type; - if (p_acm->state_info.stream_state == StreamState::DISCONNECTED) { - if (context_type == CONTENT_TYPE_MEDIA) { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerMusicTxState(p_acm->state_info.stream_state); - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerMusicRxState(p_acm->state_info.stream_state); - } - if (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), - BTACM_CONNECTION_STATE_DISCONNECTED, CONTEXT_TYPE_MUSIC); - } - if (peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTED && - peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - BTIF_TRACE_DEBUG("%s: received Media Tx/Rx disconnected state from BAP" - " when Voice Tx+Rx & Media Rx/Tx was disconnected, move in idle state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - } else { - BTIF_TRACE_DEBUG("%s: received Media Tx/Rx disconnected state from BAP" - " when either Voice Tx or Rx or Media Rx/Tx is connected, remain in reconfiguring state", __func__); - } - } else if (context_type == CONTENT_TYPE_CONVERSATIONAL) { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerVoiceTxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTED, CONTEXT_TYPE_VOICE); - if (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Tx," - " voice Rx, Music Tx & Rx are disconnected move in idle state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - } else { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Tx," - " voice Rx is disconnected but music Tx or Rx still not disconnected," - " remain in reconfiguring state", __func__); - } - } - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerVoiceRxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTED, CONTEXT_TYPE_VOICE); - if (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Rx," - " voice Tx, Music Tx & Rx are disconnected move in idle state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - } else { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Rx," - " voice Rx is disconnected but music Tx or Rx still not disconnected," - " remain in reconfiguring state", __func__); - } - } - } - } - } else if (p_acm->state_info.stream_state == StreamState::DISCONNECTING) { - if (context_type == CONTENT_TYPE_MEDIA) { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerMusicTxState(p_acm->state_info.stream_state); - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerMusicRxState(p_acm->state_info.stream_state); - } - btif_report_connection_state(peer_.PeerAddress(), - BTACM_CONNECTION_STATE_DISCONNECTING, CONTEXT_TYPE_MUSIC); - if ((peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTED || - peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTING) && - (peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTED || - peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTING) && - (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED || - peer_.GetPeerMusicTxState() == StreamState::DISCONNECTING) && - (peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED || - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTING)) { - BTIF_TRACE_DEBUG("%s: received Media Tx/Rx disconnecting state from BAP" - " when Voice Tx+Rx and Media Rx/Tx disconnected/ing, move in closing state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateClosing); - } else { - BTIF_TRACE_DEBUG("%s: received Media Tx/Rx disconnecting state from BAP" - " when either Voice Tx or Rx or Media Rx/Tx is connected, remain in reconfiguring state", __func__); - } - } else if (context_type == CONTENT_TYPE_CONVERSATIONAL) { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerVoiceTxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTING || - peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTING, CONTEXT_TYPE_VOICE); - if (((peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED) || - (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTING)) && - ((peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) || - (peer_.GetPeerMusicRxState() == StreamState::DISCONNECTING))) { - BTIF_TRACE_DEBUG("%s: received disconnecting state from BAP for voice Tx," - " voice Rx, music Tx+Rx are disconnected/ing move in closing state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateClosing); - } else { - BTIF_TRACE_DEBUG("%s: received disconnecting state from BAP for voice Tx," - " voice Rx is disconncted/ing but music Tx or Rx still not disconnected/ing," - " remain in reconfiguring state", __func__); - } - } - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerVoiceRxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTING || - peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTING, CONTEXT_TYPE_VOICE); - if (((peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED) || - (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTING)) && - ((peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) || - (peer_.GetPeerMusicRxState() == StreamState::DISCONNECTING))) { - BTIF_TRACE_DEBUG("%s: received disconnecting state from BAP for voice Rx," - " voice Tx, music Tx+Rx are disconnected/ing move in closing state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateClosing); - } else { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Rx," - " voice Tx is disconncted/ing but music Tx or Rx still not disconnected/ing," - " remain in reconfiguring state", __func__); - } - } - } - } - } - } break; - - case BTA_ACM_CONN_UPDATE_TIMEOUT_EVT: - peer_.SetConnUpdateMode(BtifAcmPeer::kFlagRelaxedMode); - break; - - default: - BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s", - __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str()); - return false; - } - return true; -} - -void BtifAcmStateMachine::StateClosing::OnEnter() { - BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str()); - if(btif_acm_initiator.IsConnUpdateEnabled()) { - //Cancel the timer if running if not, move to aggressive mode - if (alarm_is_scheduled(btif_acm_initiator.AcmConnIntervalTimer())) { - btif_acm_check_and_cancel_conn_Interval_timer(); - } - else { - BTIF_TRACE_DEBUG("%s: conn timer not running, push aggressive intervals", __func__); - peer_.SetConnUpdateMode(BtifAcmPeer::kFlagAggresiveMode); - } - } - -} - -void BtifAcmStateMachine::StateClosing::OnExit() { - BTIF_TRACE_DEBUG("%s: Peer %s", __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str()); -} - -bool BtifAcmStateMachine::StateClosing::ProcessEvent(uint32_t event, void* p_data) { - tBTIF_ACM* p_acm = (tBTIF_ACM*)p_data; - BTIF_TRACE_DEBUG("%s: Peer %s : event=%s flags=%s music_active_peer=%s voice_active_peer=%s", - __PRETTY_FUNCTION__, peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str(), - peer_.FlagsToString().c_str(), - logbool(peer_.IsPeerActiveForMusic()).c_str(), - logbool(peer_.IsPeerActiveForVoice()).c_str()); - - switch (event) { - case BTIF_ACM_SUSPEND_STREAM_REQ_EVT: - case BTIF_ACM_START_STREAM_REQ_EVT: - case BTA_ACM_STOP_EVT: - case BTIF_ACM_STOP_STREAM_REQ_EVT: - break; - - case BTA_ACM_DISCONNECT_EVT: { - int context_type = p_acm->state_info.stream_type.type; - if (p_acm->state_info.stream_state == StreamState::DISCONNECTED) { - if (context_type == CONTENT_TYPE_MEDIA) { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerMusicTxState(p_acm->state_info.stream_state); - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerMusicRxState(p_acm->state_info.stream_state); - } - if (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), - BTACM_CONNECTION_STATE_DISCONNECTED, CONTEXT_TYPE_MUSIC); - } - if (peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTED && - peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - BTIF_TRACE_DEBUG("%s: received Media Tx/Rx disconnected state from BAP" - " when Voice Tx+Rx & Media Rx/Tx was disconnected, move in idle state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - } else { - BTIF_TRACE_DEBUG("%s: received Media Tx/Rx disconnected state from BAP" - " when either Voice Tx or Rx or Media Rx/Tx is connected, remain in closing state", __func__); - } - } else if (context_type == CONTENT_TYPE_CONVERSATIONAL) { - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerVoiceTxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceRxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTED, CONTEXT_TYPE_VOICE); - if (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Tx," - " voice Rx, Music Tx & Rx are disconnected move in idle state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - } else { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Tx," - " voice Rx is disconnected but music Tx or Rx still not disconnected," - " remain in closing state", __func__); - } - } - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerVoiceRxState(p_acm->state_info.stream_state); - if (peer_.GetPeerVoiceTxState() == StreamState::DISCONNECTED) { - btif_report_connection_state(peer_.PeerAddress(), BTACM_CONNECTION_STATE_DISCONNECTED, CONTEXT_TYPE_VOICE); - if (peer_.GetPeerMusicTxState() == StreamState::DISCONNECTED && - peer_.GetPeerMusicRxState() == StreamState::DISCONNECTED) { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Rx," - " voice Tx, Music Tx & Rx are disconnected move in idle state", __func__); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - } else { - BTIF_TRACE_DEBUG("%s: received disconnected state from BAP for voice Rx," - " voice Rx is disconnected but music Tx or Rx still not disconnected," - " remain in closing state", __func__); - } - } - } - } - } else if (p_acm->state_info.stream_state == StreamState::DISCONNECTING) { - if (context_type == CONTENT_TYPE_MEDIA) { - BTIF_TRACE_DEBUG("%s: received Music Tx or Rx disconnecting state from BAP, ignore", __func__); - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) - peer_.SetPeerMusicTxState(p_acm->state_info.stream_state); - else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) - peer_.SetPeerMusicRxState(p_acm->state_info.stream_state); - } else if (context_type == CONTENT_TYPE_CONVERSATIONAL) { - BTIF_TRACE_DEBUG("%s: received voice Tx or Rx disconnecting state from BAP, ignore", __func__); - if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SINK) { - peer_.SetPeerVoiceTxState(p_acm->state_info.stream_state); - } else if (p_acm->state_info.stream_type.direction == ASE_DIRECTION_SRC) { - peer_.SetPeerVoiceRxState(p_acm->state_info.stream_state); - } - } - } - } - break; - - case BTA_ACM_CONN_UPDATE_TIMEOUT_EVT: - peer_.SetConnUpdateMode(BtifAcmPeer::kFlagRelaxedMode); - break; - - default: - BTIF_TRACE_WARNING("%s: Peer %s : Unhandled event=%s", - __PRETTY_FUNCTION__, - peer_.PeerAddress().ToString().c_str(), - BtifAcmEvent::EventName(event).c_str()); - peer_.StateMachine().TransitionTo(BtifAcmStateMachine::kStateIdle); - return false; - } - return true; -} - -void btif_acm_update_lc3q_params(int64_t* cs3, tBTIF_ACM* p_data) { - - /* ================================================================== - * CS3: Res |LC3Q-len| QTI | VMT | VML | ver/For_Als |LC3Q-support - * ================================================================== - * 0x00 |0B | 000A | FF | 0F | 01/03 | 10 - * ================================================================== - * CS4: Res - * ============================== - * 0x00,00,00,00,00,00,00,00 - * ============================== */ - - if (GetVendorMetaDataLc3QPref( - &p_data->config_info.codec_config)) { - *cs3 &= ~((int64_t)0xFF << (LE_AUDIO_CS_3_1ST_BYTE_INDEX * 8)); - *cs3 |= ((int64_t)0x10 << (LE_AUDIO_CS_3_1ST_BYTE_INDEX * 8)); - - uint8_t lc3q_ver = GetVendorMetaDataLc3QVer(&p_data->config_info.codec_config); - BTIF_TRACE_DEBUG("%s: lc3q_ver: %d", __func__, lc3q_ver); - *cs3 &= ~((int64_t)0xFF << (LE_AUDIO_CS_3_2ND_BYTE_INDEX * 8)); - *cs3 |= ((int64_t)lc3q_ver << (LE_AUDIO_CS_3_2ND_BYTE_INDEX * 8)); - - //*cs3 &= ~((int64_t)LE_AUDIO_MASK); - *cs3 |= (int64_t)LE_AUDIO_AVAILABLE_LICENSED; - - *cs3 &= ~((int64_t)0xFF << (LE_AUDIO_CS_3_3RD_BYTE_INDEX * 8)); - *cs3 |= ((int64_t)0x0F << (LE_AUDIO_CS_3_3RD_BYTE_INDEX * 8)); - - *cs3 &= ~((int64_t)0xFF << (LE_AUDIO_CS_3_4TH_BYTE_INDEX * 8)); - *cs3 |= ((int64_t)0xFF << (LE_AUDIO_CS_3_4TH_BYTE_INDEX * 8)); - - *cs3 &= ~((int64_t)0xFFFF << (LE_AUDIO_CS_3_5TH_BYTE_INDEX * 8)); - *cs3 |= ((int64_t)0x000A << (LE_AUDIO_CS_3_5TH_BYTE_INDEX * 8)); - - *cs3 &= ~((int64_t)0xFF << (LE_AUDIO_CS_3_7TH_BYTE_INDEX * 8)); - *cs3 |= ((int64_t)0x0B << (LE_AUDIO_CS_3_7TH_BYTE_INDEX * 8)); - - CodecConfig temp = unicast_codecs_capabilities.back(); - unicast_codecs_capabilities.pop_back(); - temp.codec_specific_3 = *cs3; - unicast_codecs_capabilities.push_back(temp); - } - BTIF_TRACE_DEBUG("%s: cs3: %" PRIi64, __func__, *cs3); - BTIF_TRACE_DEBUG("%s: cs3= 0x%" PRIx64, __func__, *cs3); -} - -static void btif_report_connection_state(const RawAddress& peer_address, - btacm_connection_state_t state, uint16_t contextType) { - LOG_INFO(LOG_TAG, "%s: peer_address=%s state=%d contextType=%d", __func__, - peer_address.ToString().c_str(), state, contextType); - if (btif_acm_initiator.Enabled()) { - do_in_jni_thread(FROM_HERE, - Bind(btif_acm_initiator.Callbacks()->connection_state_cb, - peer_address, state, contextType)); - } -} - -static void btif_report_audio_state(const RawAddress& peer_address, - btacm_audio_state_t state, uint16_t contextType) { - LOG_INFO(LOG_TAG, "%s: peer_address=%s state=%d contextType=%d", __func__, - peer_address.ToString().c_str(), state, contextType); - if (btif_acm_initiator.Enabled()) { - do_in_jni_thread(FROM_HERE, - Bind(btif_acm_initiator.Callbacks()->audio_state_cb, - peer_address, state, contextType)); - } -} - -void btif_acm_report_source_codec_state( - const RawAddress& peer_address, - const CodecConfig& codec_config, - const std::vector& codecs_local_capabilities, - const std::vector& - codecs_selectable_capabilities, int contextType) { - BTIF_TRACE_EVENT("%s: peer_address=%s contextType=%d", __func__, - peer_address.ToString().c_str(), contextType); - if (btif_acm_initiator.Enabled()) { - do_in_jni_thread(FROM_HERE, - Bind(btif_acm_initiator.Callbacks()->audio_config_cb, peer_address, - codec_config, codecs_local_capabilities, - codecs_selectable_capabilities, contextType)); - } -} - -static void btif_acm_handle_evt(uint16_t event, char* p_param) { - BtifAcmPeer* peer = nullptr; - BTIF_TRACE_DEBUG("Handle the ACM event = %d ", event); - switch (event) { - case BTIF_ACM_DISCONNECT_REQ_EVT: { - if (p_param == NULL) { - BTIF_TRACE_ERROR("%s: Invalid p_param, dropping event: %d", __func__, event); - return; - } - tBTIF_ACM_CONN_DISC* p_acm = (tBTIF_ACM_CONN_DISC*)p_param; - peer = btif_acm_initiator.FindOrCreatePeer(p_acm->bd_addr); - if (peer == nullptr) { - BTIF_TRACE_ERROR( - "%s: Cannot find peer for peer_address=%s" - ": event dropped: %d", - __func__, p_acm->bd_addr.ToString().c_str(), - event); - return; - } else { - BTIF_TRACE_EVENT( - "%s: BTIF_ACM_DISCONNECT_REQ_EVT peer_address=%s" - ": contextType=%d", - __func__, p_acm->bd_addr.ToString().c_str(), - p_acm->contextType); - } - break; - } - case BTIF_ACM_START_STREAM_REQ_EVT: - case BTIF_ACM_SUSPEND_STREAM_REQ_EVT: - case BTIF_ACM_STOP_STREAM_REQ_EVT: { - if (p_param == NULL) { - BTIF_TRACE_ERROR("%s: Invalid p_param, dropping event: %d", __func__, event); - return; - } - tBTIF_ACM_CONN_DISC* p_acm = (tBTIF_ACM_CONN_DISC*)p_param; - peer = btif_acm_initiator.FindOrCreatePeer(p_acm->bd_addr); - if (peer == nullptr) { - BTIF_TRACE_ERROR("%s: Cannot find peer for peer_address=%s" - ": event dropped: %d", - __func__, p_acm->bd_addr.ToString().c_str(), event); - return; - } - } break; - case BTA_ACM_DISCONNECT_EVT: - case BTA_ACM_CONNECT_EVT: - case BTA_ACM_START_EVT: - case BTA_ACM_STOP_EVT: - case BTA_ACM_RECONFIG_EVT: { - if (p_param == NULL) { - BTIF_TRACE_ERROR("%s: Invalid p_param, dropping event: %d", __func__, event); - return; - } - tBTA_ACM_STATE_INFO* p_acm = (tBTA_ACM_STATE_INFO*)p_param; - peer = btif_acm_initiator.FindOrCreatePeer(p_acm->bd_addr); - if (peer == nullptr) { - BTIF_TRACE_ERROR("%s: Cannot find or create peer for peer_address=%s" - ": event dropped: %d", - __func__, p_acm->bd_addr.ToString().c_str(), event); - return; - } - } break; - case BTA_ACM_CONFIG_EVT: { - if (p_param == NULL) { - BTIF_TRACE_ERROR("%s: Invalid p_param, dropping event: %d", __func__, event); - return; - } - tBTA_ACM_CONFIG_INFO* p_acm = (tBTA_ACM_CONFIG_INFO*)p_param; - peer = btif_acm_initiator.FindPeer(p_acm->bd_addr); - if (peer == nullptr) { - BTIF_TRACE_ERROR("%s: Cannot find or create peer for peer_address=%s" - ": event dropped: %d", - __func__, p_acm->bd_addr.ToString().c_str(), event); - return; - } - } break; - case BTIF_ACM_RECONFIG_REQ_EVT: { - if (p_param == NULL) { - BTIF_TRACE_ERROR("%s: Invalid p_param, dropping event: %d", __func__, event); - return; - } - tBTIF_ACM_RECONFIG* p_acm = (tBTIF_ACM_RECONFIG*)p_param; - peer = btif_acm_initiator.FindPeer(p_acm->bd_addr); - if (peer == nullptr) { - BTIF_TRACE_ERROR("%s: Cannot find or create peer for peer_address=%s" - ": event dropped: %d", - __func__, p_acm->bd_addr.ToString().c_str(), event); - return; - } - } break; - - case BTA_ACM_CONN_UPDATE_TIMEOUT_EVT: { - if (p_param == NULL) { - BTIF_TRACE_ERROR("%s: Invalid p_param, dropping event: %d", __func__, event); - return; - } - tBTA_ACM_CONN_UPDATE_TIMEOUT_INFO * p_acm = - (tBTA_ACM_CONN_UPDATE_TIMEOUT_INFO *)p_param; - peer = btif_acm_initiator.FindPeer(p_acm->bd_addr); - if (peer == nullptr) { - BTIF_TRACE_ERROR("%s: Cannot find or create peer for peer_address=%s" - ": event dropped: %d", - __func__, p_acm->bd_addr.ToString().c_str(), event); - return; - } - } break; - - default : - BTIF_TRACE_DEBUG("UNHandled ACM event = %d ", event); - break; - } - peer->StateMachine().ProcessEvent(event, (void*)p_param); -} - -/** - * Process BTA CSIP events. The processing is done on the JNI - * thread. - */ -static void btif_acm_handle_bta_csip_event(uint16_t evt, char* p_param) { - BtifCsipEvent btif_csip_event(evt, p_param, sizeof(tBTA_CSIP_DATA)); - tBTA_CSIP_EVT event = btif_csip_event.Event(); - tBTA_CSIP_DATA* p_data = (tBTA_CSIP_DATA*)btif_csip_event.Data(); - BTIF_TRACE_DEBUG("%s: event=%s", __func__, btif_csip_event.ToString().c_str()); - - switch (event) { - case BTA_CSIP_LOCK_STATUS_CHANGED_EVT: { - const tBTA_LOCK_STATUS_CHANGED& lock_status_param = p_data->lock_status_param; - BTIF_TRACE_DEBUG("%s: app_id=%d, set_id=%d, status=%d ", __func__, - lock_status_param.app_id, lock_status_param.set_id, - lock_status_param.status); - - std::vector set_members =lock_status_param.addr; - - for (int j = 0; j < (int)set_members.size(); j++) { - BTIF_TRACE_DEBUG("%s: address =%s", __func__, set_members[j].ToString().c_str()); - } - - BTIF_TRACE_DEBUG("%s: Get current lock status: %d ", __func__, - btif_acm_initiator.GetGroupLockStatus(lock_status_param.set_id)); - if (btif_acm_initiator.GetGroupLockStatus(lock_status_param.set_id) == BtifAcmInitiator::kFlagStatusPendingLock) { - BTIF_TRACE_DEBUG("%s: lock was awaited for this set ", __func__); - } - - if (btif_acm_initiator.GetGroupLockStatus(lock_status_param.set_id) == BtifAcmInitiator::kFlagStatusPendingUnlock) { - BTIF_TRACE_DEBUG("%s: Unlock was awaited for this set ", __func__); - } - - BTIF_TRACE_DEBUG("%s: Get CSIP app id: %d ", __func__, - btif_acm_initiator.GetCsipAppId()); - if (btif_acm_initiator.GetCsipAppId() != lock_status_param.app_id) { - BTIF_TRACE_DEBUG("%s: app id mismatch ERROR!!! ", __func__); - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_FAILURE); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_FAILURE); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - return; - } - - switch (lock_status_param.status) { - case LOCK_RELEASED: - BTIF_TRACE_DEBUG("%s: unlocked attempt succeeded ", __func__); - btif_acm_initiator.SetOrUpdateGroupLockStatus(lock_status_param.set_id, BtifAcmInitiator::kFlagStatusUnlocked); - break; - case LOCK_RELEASED_TIMEOUT: - BTIF_TRACE_DEBUG("%s: peer unlocked due to timeout ", __func__); - //in this case evaluate which device has sent TO and how to use it ? - btif_acm_initiator.SetOrUpdateGroupLockStatus(lock_status_param.set_id, BtifAcmInitiator::kFlagStatusUnlocked); - break; - case ALL_LOCKS_ACQUIRED: - btif_acm_initiator.SetOrUpdateGroupLockStatus(lock_status_param.set_id, BtifAcmInitiator::kFlagStatusLocked); - btif_acm_handle_csip_status_locked(lock_status_param.addr, lock_status_param.set_id); - BTIF_TRACE_DEBUG("%s: All locks acquired ", __func__); - break; - case SOME_LOCKS_ACQUIRED_REASON_TIMEOUT: - //proceed to continue use case; - /*case SOME_LOCKS_ACQUIRED_REASON_DISC: - //proceed to continue use case; - BTIF_TRACE_DEBUG("%s: locked attempt succeeded with status = %d", __func__, lock_status_param.status); - BTIF_TRACE_DEBUG("%s: locked set member count = %d, setsize = %d", - __func__, (lock_status_param.addr).size(), setSize); - btif_acm_initiator.music_active_set_locked_dev_count_ += (lock_status_param.addr).size(); - btif_acm_initiator.locked_devices.insert(btif_acm_initiator.locked_devices.end(), - lock_status_param.addr.begin(), lock_status_param.addr.end()); - btif_acm_handle_csip_status_locked(lock_status_param.addr, lock_status_param.set_id); - if (btif_acm_initiator.music_active_set_locked_dev_count_ < setSize) { - btif_acm_initiator.SetOrUpdateGroupLockStatus(lock_status_param.set_id, BtifAcmInitiator::kFlagStatusSubsetLocked); - } else { - btif_acm_initiator.SetOrUpdateGroupLockStatus(lock_status_param.set_id, BtifAcmInitiator::kFlagStatusLocked); - } - break;*/ - case LOCK_DENIED: { - //proceed to discontinue use case; - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_FAILURE); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_FAILURE); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - btif_acm_check_and_cancel_group_procedure_timer(lock_status_param.set_id); - btif_acm_initiator.SetOrUpdateGroupLockStatus(lock_status_param.set_id, BtifAcmInitiator::kFlagStatusUnlocked); - } break; - case INVALID_REQUEST_PARAMS: { - BTIF_TRACE_DEBUG("%s: invalid lock request ", __func__); - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_FAILURE); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_FAILURE); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - btif_acm_check_and_cancel_group_procedure_timer(lock_status_param.set_id); - if (btif_acm_initiator.GetGroupLockStatus(lock_status_param.set_id) == BtifAcmInitiator::kFlagStatusPendingLock) - btif_acm_initiator.SetOrUpdateGroupLockStatus(lock_status_param.set_id, BtifAcmInitiator::kFlagStatusUnlocked); - else - btif_acm_initiator.SetOrUpdateGroupLockStatus(lock_status_param.set_id, BtifAcmInitiator::kFlagStatusLocked); - } break; - default: - break; - } - } break; - case BTA_CSIP_SET_MEMBER_FOUND_EVT: { - const tBTA_SET_MEMBER_FOUND& set_member_param = p_data->set_member_param; - BTIF_TRACE_DEBUG("%s: set_id=%d, uuid=%d ", __func__, - set_member_param.set_id, - set_member_param.uuid); - } break; - - case BTA_CSIP_LOCK_AVAILABLE_EVT: { - const tBTA_LOCK_AVAILABLE& lock_available_param = p_data->lock_available_param; - BTIF_TRACE_DEBUG("%s: app_id=%d, set_id=%d ", __func__, - lock_available_param.app_id, lock_available_param.set_id); - } break; - } -} - -static void btif_acm_handle_csip_status_locked(std::vector addr, uint8_t setId) { - if (addr.empty()) { - BTIF_TRACE_ERROR("%s: vector size is empty", __func__); - return; - } - tA2DP_CTRL_CMD pending_cmd;// = A2DP_CTRL_CMD_START;//TODO: change to None - pending_cmd = btif_ahim_get_pending_command(); - std::vector::iterator itr; - int req = 0; - if (pending_cmd == A2DP_CTRL_CMD_START) { - req = BTIF_ACM_START_STREAM_REQ_EVT; - } else if (pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - req = BTIF_ACM_SUSPEND_STREAM_REQ_EVT; - } else if (pending_cmd == A2DP_CTRL_CMD_STOP) { - req = BTIF_ACM_STOP_STREAM_REQ_EVT; - } else { - BTIF_TRACE_EVENT("%s: No pending command, check if this list of peers belong to MusicActive streaming started group", __func__); -//if (btif_acm_initiator.IsMusicActiveGroupStarted() && (setId == btif_acm_initiator.MusicActiveCSetId())) -//req = BTIF_ACM_START_STREAM_REQ_EVT; - } - if (req) { - for (itr = addr.begin(); itr != addr.end(); itr++) { - btif_acm_initiator_dispatch_sm_event(*itr, static_cast(req)); - } - } -// BtifAcmPeer* peer_ = btif_acm_initiator.FindPeer(peer_address); - /*if ((peer_.IsPeerActiveForMusic() || !btif_acm_stream_started_ready())) { - // Immediately stop transmission of frames while suspend is pending - if (req == BTIF_ACM_STOP_STREAM_REQ_EVT) { - //btif_acm_on_stopped(nullptr); - } else if (req == BTIF_ACM_SUSPEND_STREAM_REQ_EVT) { - // ensure tx frames are immediately suspended - //btif_acm_source_set_tx_flush(true); - } - }*/ -} - -static void btif_acm_check_and_start_conn_Interval_timer(BtifAcmPeer* peer) { - - btif_acm_check_and_cancel_conn_Interval_timer(); - BTIF_TRACE_DEBUG("%s: ", __func__); - - alarm_set_on_mloop(btif_acm_initiator.AcmConnIntervalTimer(), - BtifAcmInitiator::kTimeoutConnIntervalMs, - btif_acm_initiator_conn_Interval_timer_timeout, - (void *)peer); -} - -static void btif_acm_check_and_cancel_conn_Interval_timer() { - - BTIF_TRACE_DEBUG("%s: ", __func__); - if (alarm_is_scheduled(btif_acm_initiator.AcmConnIntervalTimer())) { - alarm_cancel(btif_acm_initiator.AcmConnIntervalTimer()); - } -} - - -static void btif_acm_initiator_conn_Interval_timer_timeout(void *data) { - - BTIF_TRACE_DEBUG("%s: ", __func__); - BtifAcmPeer *peer = (BtifAcmPeer *)data; - tBTA_ACM_CONN_UPDATE_TIMEOUT_INFO p_data; - p_data.bd_addr = peer->PeerAddress(); - btif_transfer_context(btif_acm_handle_evt, BTA_ACM_CONN_UPDATE_TIMEOUT_EVT, - (char*)&p_data, - sizeof(tBTA_ACM_CONN_UPDATE_TIMEOUT_INFO), NULL); -} - -static void btif_acm_check_and_start_group_procedure_timer(uint8_t setId) { - uint8_t *arg = NULL; - arg = (uint8_t *) osi_malloc(sizeof(uint8_t)); - BTIF_TRACE_DEBUG("%s: ", __func__); - btif_acm_check_and_cancel_group_procedure_timer(setId); - - *arg = setId; - alarm_set_on_mloop(btif_acm_initiator.AcmGroupProcedureTimer(), - BtifAcmInitiator::kTimeoutAcmGroupProcedureMs, - btif_acm_initiator_group_procedure_timer_timeout, - (void*) arg); - -} - -static void btif_acm_check_and_cancel_group_procedure_timer(uint8_t setId) { - if (alarm_is_scheduled(btif_acm_initiator.AcmGroupProcedureTimer())) { - BTIF_TRACE_ERROR("%s: acm group procedure already running for setId = %d, cancel", __func__, setId); - alarm_cancel(btif_acm_initiator.AcmGroupProcedureTimer()); - } -} - -static void btif_acm_initiator_group_procedure_timer_timeout(void *data) { - BTIF_TRACE_DEBUG("%s: ", __func__); - tBTA_CSIP_CSET cset_info; // need to do memset ? - memset(&cset_info, 0, sizeof(tBTA_CSIP_CSET)); - std::vector streaming_devices; - std::vector non_streaming_devices; - uint8_t *arg = (uint8_t*) data; - if (!arg) { - BTIF_TRACE_ERROR("%s: coordinate arg is null, return", __func__); - return; - } - uint8_t setId = *arg; - if (setId == INVALID_SET_ID) { - BTIF_TRACE_ERROR("%s: coordinate SetId is invalid, return", __func__); - if (arg) osi_free(arg); - return; - } - - cset_info = BTA_CsipGetCoordinatedSet(setId); - if (cset_info.size == 0) { - BTIF_TRACE_ERROR("%s: CSET info size is zero, return", __func__); - if (arg) osi_free(arg); - return; - } - std::vector::iterator itr; - BTIF_TRACE_DEBUG("%s: size of set members %d", __func__, (cset_info.set_members).size()); - if ((cset_info.set_members).size() > 0) { - for (itr =(cset_info.set_members).begin(); itr != (cset_info.set_members).end(); itr++) { - //BTIF_TRACE_DEBUG("%s: address = %s", __func__, itr->ToString().c_str()); - BtifAcmPeer* peer = btif_acm_initiator.FindPeer(*itr); - if ((peer == nullptr) || (peer != nullptr && !peer->IsStreaming())) { - non_streaming_devices.push_back(*itr); - } else { - streaming_devices.push_back(*itr); - } - } - } - - if (streaming_devices.size() > 0) { - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_SUCCESS); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_SUCCESS); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - BTIF_TRACE_DEBUG("%s: Get music active setid: %d", __func__, - btif_acm_initiator.MusicActiveCSetId()); - btif_acm_check_and_start_lock_release_timer(btif_acm_initiator.MusicActiveCSetId()); - if (streaming_devices.size() < (cset_info.set_members).size()) { - // this case should continue with mono mode since all set members are not streaming - } - } else { - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_FAILURE); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_FAILURE); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - } - - if (non_streaming_devices.size() > 0) //do we need to unlock and then disconnect ?? - // le_Acl_disconnect (non_streaming_devices); - - if (arg) osi_free(arg); -} - -static void btif_acm_check_and_start_lock_release_timer(uint8_t setId) { - uint8_t *arg = NULL; - arg = (uint8_t *) osi_malloc(sizeof(uint8_t)); - - btif_acm_check_and_cancel_lock_release_timer(setId); - - *arg = setId; - alarm_set_on_mloop(btif_acm_initiator.MusicSetLockReleaseTimer(), - BtifAcmPeer::kTimeoutLockReleaseMs, - btif_acm_initiator_lock_release_timer_timeout, - (void*) arg); -} - -static void btif_acm_check_and_cancel_lock_release_timer(uint8_t setId) { - if (alarm_is_scheduled(btif_acm_initiator.MusicSetLockReleaseTimer())) { - BTIF_TRACE_ERROR("%s: lock release already running for setId = %d, cancel ", __func__, setId); - alarm_cancel(btif_acm_initiator.MusicSetLockReleaseTimer()); - } -} - -static void btif_acm_initiator_lock_release_timer_timeout(void *data) { - uint8_t *arg = (uint8_t*) data; - if (!arg) { - BTIF_TRACE_ERROR("%s: coordinate arg is null, return", __func__); - return; - } - uint8_t setId = *arg; - if (setId == INVALID_SET_ID) { - BTIF_TRACE_ERROR("%s: coordinate SetId is invalid, return", __func__); - if (arg) osi_free(arg); - return; - } - if ((btif_acm_initiator.GetGroupLockStatus(setId) != BtifAcmInitiator::kFlagStatusLocked) || - (btif_acm_initiator.GetGroupLockStatus(setId) != BtifAcmInitiator::kFlagStatusSubsetLocked)) { - BTIF_TRACE_ERROR("%s: SetId = %d Lock Status = %d returning", - __func__, setId, btif_acm_initiator.GetGroupLockStatus(setId)); - if (arg) osi_free(arg); - return; - } - if (!btif_acm_request_csip_unlock(setId)) { - BTIF_TRACE_ERROR("%s: error unlocking", __func__); - } - if (arg) osi_free(arg); -} - -static void bta_csip_callback(tBTA_CSIP_EVT event, tBTA_CSIP_DATA* p_data) { - BTIF_TRACE_DEBUG("%s: event: %d", __func__, event); - btif_transfer_context(btif_acm_handle_bta_csip_event, event, (char*)p_data, - sizeof(tBTA_CSIP_DATA), NULL); -} - -// Initializes the ACM interface for initiator mode -static bt_status_t init_acm_initiator( - btacm_initiator_callbacks_t* callbacks, int max_connected_acceptors, - const std::vector& codec_priorities) { - BTIF_TRACE_EVENT("%s", __func__); - return btif_acm_initiator.Init(callbacks, max_connected_acceptors, - codec_priorities); -} - -// Establishes the BAP connection with the remote acceptor device -static void connect_int(uint16_t uuid, char* p_param) { - tBTIF_ACM_CONN_DISC connection; - memset(&connection, 0, sizeof(tBTIF_ACM_CONN_DISC)); - memcpy(&connection, p_param, sizeof(connection)); - RawAddress peer_address = RawAddress::kEmpty; - BtifAcmPeer* peer = nullptr; - peer_address = connection.bd_addr; - if (uuid == ACM_UUID) { - peer = btif_acm_initiator.FindOrCreatePeer(peer_address); - } - if (peer == nullptr) { - BTIF_TRACE_ERROR("%s: peer is NULL", __func__); - return; - } - peer->SetContextType(connection.contextType); - peer->SetProfileType(connection.profileType); - BTIF_TRACE_DEBUG("%s: cummulative_profile_type %d", __func__, peer->GetProfileType()); - //peer->SetPrefContextType(preferredContext); - peer->StateMachine().ProcessEvent(BTIF_ACM_CONNECT_REQ_EVT, &connection); -} - -// Set the active peer for contexttype -static void set_acm_active_peer_int(const RawAddress& peer_address, - uint16_t contextType, uint16_t profileType, - std::promise peer_ready_promise) { - BTIF_TRACE_EVENT("%s: peer_address=%s", __func__, peer_address.ToString().c_str()); - if (peer_address.IsEmpty()) { - int setid = INVALID_SET_ID; - if (contextType == CONTEXT_TYPE_MUSIC) - setid = btif_acm_initiator.MusicActiveCSetId(); - else if (contextType == CONTEXT_TYPE_VOICE) - setid = btif_acm_initiator.VoiceActiveCSetId(); - - if (setid < INVALID_SET_ID) { - tBTA_CSIP_CSET cset_info; - memset(&cset_info, 0, sizeof(tBTA_CSIP_CSET)); - cset_info = BTA_CsipGetCoordinatedSet(setid); - if (cset_info.size != 0) { - std::vector::iterator itr; - BTIF_TRACE_DEBUG("%s: size of set members %d", __func__, (cset_info.set_members).size()); - if ((cset_info.set_members).size() > 0) { - for (itr =(cset_info.set_members).begin(); itr != (cset_info.set_members).end(); itr++) { - BtifAcmPeer* peer = btif_acm_initiator.FindPeer(*itr); - if (peer != nullptr && peer->IsStreaming() && - (contextType == peer->GetStreamContextType())) { - BTIF_TRACE_DEBUG("%s: peer is streaming %s ", __func__, peer->PeerAddress().ToString().c_str()); - btif_acm_initiator_dispatch_sm_event(*itr, BTIF_ACM_STOP_STREAM_REQ_EVT); - } - } - } - } - } else { - BTIF_TRACE_DEBUG("%s: set active for twm device ", __func__); - BtifAcmPeer* peer = nullptr; - if (contextType == CONTEXT_TYPE_MUSIC) - peer = btif_acm_initiator.FindPeer(btif_acm_initiator.MusicActivePeer()); - else if (contextType == CONTEXT_TYPE_VOICE) - peer = btif_acm_initiator.FindPeer(btif_acm_initiator.VoiceActivePeer()); - if (peer != nullptr && peer->IsStreaming() && - (contextType == peer->GetStreamContextType())) { - BTIF_TRACE_DEBUG("%s: peer is streaming %s ", __func__, peer->PeerAddress().ToString().c_str()); - if (contextType == CONTEXT_TYPE_MUSIC) - btif_acm_initiator_dispatch_sm_event(btif_acm_initiator.MusicActivePeer(), BTIF_ACM_STOP_STREAM_REQ_EVT); - else if (contextType == CONTEXT_TYPE_VOICE) - btif_acm_initiator_dispatch_sm_event(btif_acm_initiator.VoiceActivePeer(), BTIF_ACM_STOP_STREAM_REQ_EVT); - } - } - } - if (!btif_acm_initiator.SetAcmActivePeer(peer_address, contextType, profileType, - std::move(peer_ready_promise))) { - BTIF_TRACE_ERROR("%s: Error setting %s as active peer", __func__, - peer_address.ToString().c_str()); - } -} - -static bt_status_t connect_acm_initiator(const RawAddress& peer_address, - uint16_t contextType, uint16_t profileType, - uint16_t preferredContext) { - BTIF_TRACE_EVENT("%s: Peer %s contextType=%d profileType=%d preferredContext=%d", __func__, - peer_address.ToString().c_str(), contextType, profileType, preferredContext); - - if (!btif_acm_initiator.Enabled()) { - BTIF_TRACE_WARNING("%s: BTIF ACM Initiator is not enabled", __func__); - return BT_STATUS_NOT_READY; - } - - tBTIF_ACM_CONN_DISC conn; - conn.contextType = contextType; - conn.profileType = profileType; - conn.bd_addr = peer_address; - return btif_transfer_context(connect_int, ACM_UUID, (char*)&conn, - sizeof(tBTIF_ACM_CONN_DISC), NULL); -} - -static bt_status_t disconnect_acm_initiator(const RawAddress& peer_address, - uint16_t contextType) { - BTIF_TRACE_EVENT("%s: Peer %s contextType=%d", __func__, - peer_address.ToString().c_str(), contextType); - - if (!btif_acm_initiator.Enabled()) { - BTIF_TRACE_WARNING("%s: BTIF ACM Initiator is not enabled", __func__); - return BT_STATUS_NOT_READY; - } - - BtifAcmPeer* peer = btif_acm_initiator.FindOrCreatePeer(peer_address); - if (peer == nullptr) { - BTIF_TRACE_ERROR("%s: peer is NULL", __func__); - return BT_STATUS_FAIL; - } - - tBTIF_ACM_CONN_DISC disc; - peer->ResetContextType(contextType); - if (contextType == CONTEXT_TYPE_MUSIC) { - peer->ResetProfileType(BAP|GCP|WMCP); - disc.profileType = BAP|GCP|WMCP; - } else if (contextType == CONTEXT_TYPE_VOICE) { - peer->ResetProfileType(BAP_CALL); - disc.profileType = BAP_CALL; - } else if (contextType == CONTEXT_TYPE_MUSIC_VOICE) { - peer->ResetProfileType(BAP|GCP|WMCP|BAP_CALL); - disc.profileType = BAP|GCP|WMCP|BAP_CALL; - } - BTIF_TRACE_DEBUG("%s: cummulative_profile_type %d", __func__, peer->GetProfileType()); - - disc.bd_addr = peer_address; - disc.contextType = contextType; - btif_transfer_context(btif_acm_handle_evt, BTIF_ACM_DISCONNECT_REQ_EVT, (char*)&disc, - sizeof(tBTIF_ACM_CONN_DISC), NULL); - return BT_STATUS_SUCCESS; -} - -static bt_status_t set_active_acm_initiator(const RawAddress& peer_address, - uint16_t profileType) { - uint16_t contextType = CONTEXT_TYPE_MUSIC; - if (profileType == BAP || profileType == GCP || profileType == WMCP) - contextType = CONTEXT_TYPE_MUSIC; - else if (profileType == BAP_CALL) - contextType = CONTEXT_TYPE_VOICE; - - BTIF_TRACE_EVENT("%s: Peer %s contextType=%d profileType=%d", __func__, - peer_address.ToString().c_str(), contextType, profileType); - if (!btif_acm_initiator.Enabled()) { - LOG(WARNING) << __func__ << ": BTIF ACM Initiator is not enabled"; - return BT_STATUS_NOT_READY; - } - - BtifAcmPeer* peer = nullptr; - if (contextType == CONTEXT_TYPE_MUSIC) { - peer = btif_acm_initiator.FindPeer(btif_acm_initiator.MusicActivePeer()); - if ((peer != nullptr) && (peer->GetStreamContextType() == CONTEXT_TYPE_MUSIC) && - (peer->CheckFlags(BtifAcmPeer::kFlagPendingStart | BtifAcmPeer::kFlagPendingLocalSuspend | - BtifAcmPeer::kFlagPendingReconfigure))) { - LOG(WARNING) << __func__ << ": Active music device is pending start or suspend or reconfig"; - return BT_STATUS_NOT_READY; - } - } else if (contextType == CONTEXT_TYPE_VOICE) { - peer = btif_acm_initiator.FindPeer(btif_acm_initiator.VoiceActivePeer()); - if ((peer != nullptr) && (peer->GetStreamContextType() == CONTEXT_TYPE_VOICE) && - (peer->CheckFlags(BtifAcmPeer::kFlagPendingStart | - BtifAcmPeer::kFlagPendingLocalSuspend))) { - LOG(WARNING) << __func__ << ": Active voice device is pending start or suspend"; - return BT_STATUS_NOT_READY; - } - } - std::promise peer_ready_promise; - std::future peer_ready_future = peer_ready_promise.get_future(); - set_acm_active_peer_int(peer_address, contextType, profileType, - std::move(peer_ready_promise)); - return BT_STATUS_SUCCESS; -} - -static bt_status_t start_stream_acm_initiator(const RawAddress& peer_address, - uint16_t contextType) { - LOG_INFO(LOG_TAG, "%s: Peer %s", __func__, peer_address.ToString().c_str()); - - if (!btif_acm_initiator.Enabled()) { - BTIF_TRACE_WARNING("%s: BTIF ACM Initiator is not enabled", __func__); - return BT_STATUS_NOT_READY; - } - int id = btif_acm_initiator.VoiceActiveCSetId(); - if (id < INVALID_SET_ID) { - tBTA_CSIP_CSET cset_info; - memset(&cset_info, 0, sizeof(tBTA_CSIP_CSET)); - cset_info = BTA_CsipGetCoordinatedSet(id); - std::vector::iterator itr; - BTIF_TRACE_DEBUG("%s: size of set members %d", __func__, (cset_info.set_members).size()); - if ((cset_info.set_members).size() > 0) { - for (itr =(cset_info.set_members).begin(); itr != (cset_info.set_members).end(); itr++) { - BTIF_TRACE_DEBUG("%s: Sending start request ", __func__); - BtifAcmPeer* p = btif_acm_initiator.FindPeer(*itr); - if (p && p->IsConnected()) { - p->SetStreamContextType(contextType); - btif_acm_initiator_dispatch_sm_event(*itr, BTIF_ACM_START_STREAM_REQ_EVT); - } - } - } - btif_acm_check_and_start_group_procedure_timer(btif_acm_initiator.VoiceActiveCSetId()); - } else { - BTIF_TRACE_DEBUG("%s: Sending start to twm device ", __func__); - BtifAcmPeer* p = btif_acm_initiator.FindPeer(btif_acm_initiator.VoiceActivePeer()); - if (p != nullptr && p->IsConnected()) { - p->SetStreamContextType(CONTEXT_TYPE_VOICE); - btif_acm_initiator_dispatch_sm_event(btif_acm_initiator.VoiceActivePeer(), BTIF_ACM_START_STREAM_REQ_EVT); - } else { - BTIF_TRACE_DEBUG("%s: Unable to send start to twm device ", __func__); - } - } - return BT_STATUS_SUCCESS; -} - -static bt_status_t stop_stream_acm_initiator(const RawAddress& peer_address, - uint16_t contextType) { - LOG_INFO(LOG_TAG, "%s: Peer %s", __func__, peer_address.ToString().c_str()); - - if (!btif_acm_initiator.Enabled()) { - BTIF_TRACE_WARNING("%s: BTIF ACM Initiator is not enabled", __func__); - return BT_STATUS_NOT_READY; - } - - int id = btif_acm_initiator.VoiceActiveCSetId(); - if (id < INVALID_SET_ID) { - tBTA_CSIP_CSET cset_info; - memset(&cset_info, 0, sizeof(tBTA_CSIP_CSET)); - cset_info = BTA_CsipGetCoordinatedSet(id); - std::vector::iterator itr; - BTIF_TRACE_DEBUG("%s: size of set members %d", __func__, (cset_info.set_members).size()); - if ((cset_info.set_members).size() > 0) { - for (itr =(cset_info.set_members).begin(); itr != (cset_info.set_members).end(); itr++) { - BTIF_TRACE_DEBUG("%s: Sending stop request ", __func__); - BtifAcmPeer* p = btif_acm_initiator.FindPeer(*itr); - if (p && p->IsConnected()) { - p->SetStreamContextType(contextType); - btif_acm_initiator_dispatch_sm_event(*itr, BTIF_ACM_STOP_STREAM_REQ_EVT); - } - } - } - btif_acm_check_and_start_group_procedure_timer(btif_acm_initiator.VoiceActiveCSetId()); - } else { - BTIF_TRACE_DEBUG("%s: Sending stop to twm device ", __func__); - BtifAcmPeer* p = btif_acm_initiator.FindPeer(btif_acm_initiator.VoiceActivePeer()); - if (p != nullptr && p->IsConnected()) { - p->SetStreamContextType(CONTEXT_TYPE_VOICE); - btif_acm_initiator_dispatch_sm_event(btif_acm_initiator.VoiceActivePeer(), BTIF_ACM_STOP_STREAM_REQ_EVT); - } else { - BTIF_TRACE_DEBUG("%s: Unable to send stop to twm device ", __func__); - } - } - return BT_STATUS_SUCCESS; -} - -static bt_status_t codec_config_acm_initiator(const RawAddress& peer_address, - std::vector codec_preferences, - uint16_t contextType, uint16_t profileType) { - BTIF_TRACE_EVENT("%s", __func__); - - if (!btif_acm_initiator.Enabled()) { - LOG(WARNING) << __func__ << ": BTIF ACM Initiator is not enabled"; - return BT_STATUS_NOT_READY; - } - - if (peer_address.IsEmpty()) { - LOG(WARNING) << __func__ << ": BTIF ACM Initiator, peer empty"; - return BT_STATUS_PARM_INVALID; - } - - std::promise peer_ready_promise; - std::future peer_ready_future = peer_ready_promise.get_future(); - bt_status_t status = BT_STATUS_SUCCESS; - if (status == BT_STATUS_SUCCESS) { - peer_ready_future.wait(); - } else { - LOG(WARNING) << __func__ << ": BTIF ACM Initiator fails to config codec"; - } - return status; -} - -static bt_status_t change_codec_config_acm_initiator(const RawAddress& peer_address, - char* msg) { - BTIF_TRACE_DEBUG("%s: codec change string: %s", __func__, msg); - tBTIF_ACM_RECONFIG data; - if (!btif_acm_initiator.Enabled()) { - LOG(WARNING) << __func__ << ": BTIF ACM Initiator is not enabled"; - return BT_STATUS_NOT_READY; - } - - if (peer_address.IsEmpty()) { - LOG(WARNING) << __func__ << ": BTIF ACM Initiator, peer empty"; - return BT_STATUS_PARM_INVALID; - } - BtifAcmPeer* peer = btif_acm_initiator.FindPeer(peer_address); - if (peer == nullptr) - LOG(ERROR) << __func__ << ": BTIF ACM Initiator, peer is null"; - return BT_STATUS_FAIL; - - CodecQosConfig codec_qos_cfg; - memset(&codec_qos_cfg, 0, sizeof(codec_qos_cfg)); - if (!strcmp(msg, "GCP_TX") && peer->GetContextType() == CONTEXT_TYPE_MUSIC) { - data.bd_addr = peer_address; - data.streams_info.stream_type.type = CONTENT_TYPE_MEDIA; - data.streams_info.stream_type.audio_context = CONTENT_TYPE_MEDIA; - data.streams_info.stream_type.direction = ASE_DIRECTION_SINK; - data.streams_info.reconf_type = bluetooth::bap::ucast::StreamReconfigType::CODEC_CONFIG; - if (peer->IsStereoHsType()) { - SelectCodecQosConfig(peer_address, GCP, MEDIA_CONTEXT, SNK, STEREO_HS_CONFIG_1); - } else { - SelectCodecQosConfig(peer_address, GCP, MEDIA_CONTEXT, SNK, EB_CONFIG); - } - codec_qos_cfg = peer->get_peer_media_codec_qos_config(); - data.streams_info.codec_qos_config_pair.push_back(codec_qos_cfg); - } else if (!strcmp(msg, "GCP_TX_RX") && peer->GetContextType() == CONTEXT_TYPE_MUSIC) { - data.bd_addr = peer_address; - data.streams_info.stream_type.type = CONTENT_TYPE_MEDIA; - data.streams_info.stream_type.direction = ASE_DIRECTION_SINK; - data.streams_info.reconf_type = bluetooth::bap::ucast::StreamReconfigType::CODEC_CONFIG; - SelectCodecQosConfig(peer_address, GCP, MEDIA_CONTEXT, SNK, EB_CONFIG); - codec_qos_cfg = peer->get_peer_media_codec_qos_config(); - codec_qos_cfg.qos_config.cig_config.cig_id++; - codec_qos_cfg.qos_config.ascs_configs[0].cig_id++; - peer->set_peer_media_qos_config(codec_qos_cfg.qos_config); - peer->set_peer_media_codec_qos_config(codec_qos_cfg); - data.streams_info.codec_qos_config_pair.push_back(codec_qos_cfg); - } else if (!strcmp(msg, "MEDIA_TX")) { - data.bd_addr = peer_address; - data.streams_info.stream_type.type = CONTENT_TYPE_MEDIA; - data.streams_info.reconf_type = bluetooth::bap::ucast::StreamReconfigType::CODEC_CONFIG; - data.streams_info.stream_type.direction = ASE_DIRECTION_SINK; - if (peer->IsStereoHsType()) { - SelectCodecQosConfig(peer_address, BAP, MEDIA_CONTEXT, SNK, STEREO_HS_CONFIG_1); - } else { - SelectCodecQosConfig(peer_address, BAP, MEDIA_CONTEXT, SNK, EB_CONFIG); - } - codec_qos_cfg = peer->get_peer_media_codec_qos_config(); - data.streams_info.codec_qos_config_pair.push_back(codec_qos_cfg); - } else if (!strcmp(msg, "MEDIA_RX")) { - data.bd_addr = peer_address; - data.streams_info.stream_type.type = CONTENT_TYPE_MEDIA; - data.streams_info.stream_type.audio_context = CONTENT_TYPE_LIVE; //Live Audio Context - data.streams_info.reconf_type = bluetooth::bap::ucast::StreamReconfigType::CODEC_CONFIG; - data.streams_info.stream_type.direction = ASE_DIRECTION_SRC; - SelectCodecQosConfig(peer_address, WMCP, MEDIA_CONTEXT, SRC, EB_CONFIG); - codec_qos_cfg = peer->get_peer_media_codec_qos_config(); - data.streams_info.codec_qos_config_pair.push_back(codec_qos_cfg); - } - print_codec_parameters(codec_qos_cfg.codec_config); - print_qos_parameters(codec_qos_cfg.qos_config); - btif_transfer_context(btif_acm_handle_evt, BTIF_ACM_RECONFIG_REQ_EVT, (char*)&data, - sizeof(tBTIF_ACM_RECONFIG), NULL); - return BT_STATUS_SUCCESS; -} - -bool reconfig_acm_initiator(const RawAddress& peer_address, int profileType) { - BTIF_TRACE_DEBUG("%s: profileType: %d", __func__, profileType); - tBTIF_ACM_RECONFIG data; - if (!btif_acm_initiator.Enabled()) { - LOG(WARNING) << __func__ << ": BTIF ACM Initiator is not enabled"; - return false; - } - - if (peer_address.IsEmpty()) { - LOG(WARNING) << __func__ << ": BTIF ACM Initiator, peer empty"; - return false; - } - BtifAcmPeer* peer = btif_acm_initiator.FindPeer(peer_address); - if (peer == nullptr) { - LOG(ERROR) << __func__ << ": BTIF ACM Initiator, peer is null"; - return false; - } - - CodecQosConfig codec_qos_cfg; - memset(&codec_qos_cfg, 0, sizeof(codec_qos_cfg)); - if ((profileType == GCP) && (peer->GetContextType() & CONTEXT_TYPE_MUSIC)) { - data.bd_addr = peer_address; - data.streams_info.stream_type.type = CONTENT_TYPE_MEDIA; - data.streams_info.stream_type.audio_context = CONTENT_TYPE_MEDIA; - data.streams_info.stream_type.direction = ASE_DIRECTION_SINK; - data.streams_info.reconf_type = bluetooth::bap::ucast::StreamReconfigType::CODEC_CONFIG; - if (peer->IsStereoHsType()) { - SelectCodecQosConfig(peer_address, GCP, MEDIA_CONTEXT, SNK, STEREO_HS_CONFIG_1); - } else { - SelectCodecQosConfig(peer_address, GCP, MEDIA_CONTEXT, SNK, EB_CONFIG); - } - codec_qos_cfg = peer->get_peer_media_codec_qos_config(); - data.streams_info.codec_qos_config_pair.push_back(codec_qos_cfg); - } else if ((profileType == GCP_TX_RX) && (peer->GetContextType() & CONTEXT_TYPE_MUSIC)) { - data.bd_addr = peer_address; - data.streams_info.stream_type.type = CONTENT_TYPE_MEDIA; - data.streams_info.stream_type.direction = ASE_DIRECTION_SINK; - data.streams_info.reconf_type = bluetooth::bap::ucast::StreamReconfigType::CODEC_CONFIG; - SelectCodecQosConfig(peer_address, GCP, MEDIA_CONTEXT, SNK, EB_CONFIG); - codec_qos_cfg = peer->get_peer_media_codec_qos_config(); - codec_qos_cfg.qos_config.cig_config.cig_id++; - codec_qos_cfg.qos_config.ascs_configs[0].cig_id++; - peer->set_peer_media_qos_config(codec_qos_cfg.qos_config); - peer->set_peer_media_codec_qos_config(codec_qos_cfg); - data.streams_info.codec_qos_config_pair.push_back(codec_qos_cfg); - } else if ((profileType == BAP) && (peer->GetContextType() & CONTEXT_TYPE_MUSIC)) { - data.bd_addr = peer_address; - data.streams_info.stream_type.type = CONTENT_TYPE_MEDIA; - data.streams_info.stream_type.audio_context = CONTENT_TYPE_MEDIA; - data.streams_info.stream_type.direction = ASE_DIRECTION_SINK; - data.streams_info.reconf_type = bluetooth::bap::ucast::StreamReconfigType::CODEC_CONFIG; - if (peer->IsStereoHsType()) { - SelectCodecQosConfig(peer_address, BAP, MEDIA_CONTEXT, SNK, STEREO_HS_CONFIG_1); - } else { - SelectCodecQosConfig(peer_address, BAP, MEDIA_CONTEXT, SNK, EB_CONFIG); - } - codec_qos_cfg = peer->get_peer_media_codec_qos_config(); - data.streams_info.codec_qos_config_pair.push_back(codec_qos_cfg); - } else if ((profileType == WMCP) && (peer->GetContextType() & CONTEXT_TYPE_MUSIC)) { - data.bd_addr = peer_address; - data.streams_info.stream_type.type = CONTENT_TYPE_MEDIA; - data.streams_info.stream_type.audio_context = CONTENT_TYPE_LIVE; //Live Audio Context - data.streams_info.stream_type.direction = ASE_DIRECTION_SRC; - data.streams_info.reconf_type = bluetooth::bap::ucast::StreamReconfigType::CODEC_CONFIG; - if (peer->IsStereoHsType()) { - SelectCodecQosConfig(peer_address, WMCP, MEDIA_CONTEXT, SRC, STEREO_HS_CONFIG_1); - } else { - SelectCodecQosConfig(peer_address, WMCP, MEDIA_CONTEXT, SRC, EB_CONFIG); - } - codec_qos_cfg = peer->get_peer_media_codec_qos_config(); - data.streams_info.codec_qos_config_pair.push_back(codec_qos_cfg); - } else if ((profileType == BAP_CALL) && (peer->GetContextType() & CONTEXT_TYPE_VOICE)) { - data.bd_addr = peer_address; - data.streams_info.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - } - - peer->SetRcfgProfileType(profileType); - if (profileType != BAP_CALL) { - print_codec_parameters(codec_qos_cfg.codec_config); - print_qos_parameters(codec_qos_cfg.qos_config); - } - btif_transfer_context(btif_acm_handle_evt, BTIF_ACM_RECONFIG_REQ_EVT, (char*)&data, - sizeof(tBTIF_ACM_RECONFIG), NULL); - return true; -} - -static void cleanup_acm_initiator(void) { - BTIF_TRACE_EVENT("%s", __func__); - do_in_bta_thread(FROM_HERE, Bind(&BtifAcmInitiator::Cleanup, - base::Unretained(&btif_acm_initiator))); -} - -static const btacm_initiator_interface_t bt_acm_initiator_interface = { - sizeof(btacm_initiator_interface_t), - init_acm_initiator, - connect_acm_initiator, - disconnect_acm_initiator, - set_active_acm_initiator, - start_stream_acm_initiator, - stop_stream_acm_initiator, - codec_config_acm_initiator, - change_codec_config_acm_initiator, - cleanup_acm_initiator, -}; - -RawAddress btif_acm_initiator_music_active_peer(void) { - return btif_acm_initiator.MusicActivePeer(); -} - -RawAddress btif_acm_initiator_voice_active_peer(void) { - return btif_acm_initiator.VoiceActivePeer(); -} - -bool btif_acm_request_csip_lock(uint8_t setId) { - LOG_INFO(LOG_TAG, "%s", __func__); - tBTA_CSIP_CSET cset_info; // need to do memset ? - memset(&cset_info, 0, sizeof(tBTA_CSIP_CSET)); - cset_info = BTA_CsipGetCoordinatedSet(setId); - /*if (cset_info.p_srvc_uuid != ACM_UUID) { - return false; - }*/ - if (cset_info.size > cset_info.total_discovered) { - LOG_INFO(LOG_TAG, "%s not complete set discovered yet. size = %d discovered = %d", - __func__, cset_info.size, cset_info.total_discovered); - } - if (setId == cset_info.set_id) { - LOG_INFO(LOG_TAG, "%s correct set id", __func__); - } else { - return false; - } - - btif_acm_check_and_cancel_lock_release_timer(setId); - - //Aquire lock for entire group. - tBTA_SET_LOCK_PARAMS lock_params; //need to do memset ? - lock_params.app_id = btif_acm_initiator.GetCsipAppId(); - lock_params.set_id = cset_info.set_id; - lock_params.lock_value = LOCK_VALUE;//For lock - lock_params.members_addr = cset_info.set_members; - BTA_CsipSetLockValue (lock_params); - btif_acm_initiator.SetLockFlags(BtifAcmInitiator::kFlagStatusPendingLock); - btif_acm_initiator.SetOrUpdateGroupLockStatus(cset_info.set_id, - btif_acm_initiator.CheckLockFlags(BtifAcmInitiator::kFlagStatusPendingLock)); - return true; -} - -bool btif_acm_request_csip_unlock(uint8_t setId) { - tBTA_CSIP_CSET cset_info; // need to do memset ? - memset(&cset_info, 0, sizeof(tBTA_CSIP_CSET)); - cset_info = BTA_CsipGetCoordinatedSet(setId); - /*if (cset_info.p_srvc_uuid != Uuid::FromString("2B86")) { - return false; - }*/ - if (cset_info.size > cset_info.total_discovered) { - LOG_INFO(LOG_TAG, "%s not complete set discovered yet. size = %d discovered = %d", - __func__, cset_info.size, cset_info.total_discovered); - } - if (setId == cset_info.set_id) { - LOG_INFO(LOG_TAG, "%s correct app id", __func__); - } else { - return false; - } - //Aquire lock for entire group. - tBTA_SET_LOCK_PARAMS lock_params; //need to do memset ? - lock_params.app_id = btif_acm_initiator.GetCsipAppId(); - lock_params.set_id = cset_info.set_id; - lock_params.lock_value = UNLOCK_VALUE;//For Unlock - lock_params.members_addr = cset_info.set_members; - BTA_CsipSetLockValue (lock_params); - btif_acm_initiator.SetLockFlags(BtifAcmInitiator::kFlagStatusPendingUnlock); - btif_acm_initiator.SetOrUpdateGroupLockStatus(cset_info.set_id, - btif_acm_initiator.CheckLockFlags(BtifAcmInitiator::kFlagStatusPendingUnlock)); - return true; -} - -bool btif_acm_is_call_active(void) { - BtifAcmPeer* peer = nullptr; - peer = btif_acm_initiator.FindPeer(btif_acm_initiator.VoiceActivePeer()); - if (peer != nullptr && (peer->IsStreaming() || peer->CheckFlags(BtifAcmPeer::kFlagPendingStart)) && - (peer->GetStreamContextType() == CONTEXT_TYPE_VOICE)) - return true; - - return false; -} - -void btif_acm_stream_start(void) { - LOG_INFO(LOG_TAG, "%s", __func__); - if (!btif_acm_initiator.Enabled()) - return; - bool ret = false; - if (false/*btif_acm_initiator.IsCsipRegistered() && (btif_acm_initiator.MusicActiveCSetId() != INVALID_SET_ID)*/) { - ret = btif_acm_request_csip_lock(btif_acm_initiator.MusicActiveCSetId()); - if (ret == false) { - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_FAILURE); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_FAILURE); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - return; - } - //call below in lock changed success CB - //should be dispatched to list of peers in active music group. - btif_acm_check_and_start_group_procedure_timer(btif_acm_initiator.MusicActiveCSetId()); - } else { - int id = btif_acm_initiator.MusicActiveCSetId(); - if (id < INVALID_SET_ID) { - bool send_neg_ack = true; - tBTA_CSIP_CSET cset_info; - memset(&cset_info, 0, sizeof(tBTA_CSIP_CSET)); - cset_info = BTA_CsipGetCoordinatedSet(id); - std::vector::iterator itr; - BTIF_TRACE_DEBUG("%s: size of set members %d", __func__, (cset_info.set_members).size()); - if ((cset_info.set_members).size() > 0) { - for (itr =(cset_info.set_members).begin(); itr != (cset_info.set_members).end(); itr++) { - BTIF_TRACE_DEBUG("%s: Sending start request ", __func__); - BtifAcmPeer* p = btif_acm_initiator.FindPeer(*itr); - if (p != nullptr && p->IsConnected()) { - send_neg_ack = false; - p->SetStreamContextType(CONTEXT_TYPE_MUSIC); - btif_acm_initiator_dispatch_sm_event(*itr, BTIF_ACM_START_STREAM_REQ_EVT); - } - } - } - if (send_neg_ack) { - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - return; - } - btif_acm_check_and_start_group_procedure_timer(btif_acm_initiator.MusicActiveCSetId()); - } else { - BTIF_TRACE_DEBUG("%s: Sending start to twm device ", __func__); - BtifAcmPeer* p = btif_acm_initiator.FindPeer(btif_acm_initiator_music_active_peer()); - - if (p != nullptr && p->IsStreaming()) { - BTIF_TRACE_DEBUG("%s: Already streaming ongoing", __func__); - btif_acm_on_started(A2DP_CTRL_ACK_SUCCESS); - return; - } - - if (p != nullptr && p->IsConnected()) { - p->SetStreamContextType(CONTEXT_TYPE_MUSIC); - btif_acm_initiator_dispatch_sm_event(btif_acm_initiator_music_active_peer(), BTIF_ACM_START_STREAM_REQ_EVT); - } else { - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - } - } - } -} - -void btif_acm_stream_stop(void) { - LOG_INFO(LOG_TAG, "%s ", __func__); - bool ret = false; - if (false /*btif_acm_initiator.IsCsipRegistered() && (btif_acm_initiator.MusicActiveCSetId() != INVALID_SET_ID)*/) { - ret = btif_acm_request_csip_lock(btif_acm_initiator.MusicActiveCSetId()); - if (ret == false) { - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_FAILURE); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_FAILURE); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - return; - } - btif_acm_check_and_start_group_procedure_timer(btif_acm_initiator.MusicActiveCSetId()); - } else { - BTIF_TRACE_DEBUG("%s: Sending stop to twm device ", __func__); - BtifAcmPeer* p = btif_acm_initiator.FindPeer(btif_acm_initiator_music_active_peer()); - if (p != nullptr && p->IsConnected()) { - p->SetStreamContextType(CONTEXT_TYPE_MUSIC); - btif_acm_initiator_dispatch_sm_event(btif_acm_initiator_music_active_peer(), BTIF_ACM_STOP_STREAM_REQ_EVT); - } else { - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - } - } -} - -void btif_acm_stream_suspend(void) { - LOG_INFO(LOG_TAG, "%s", __func__); - if (!btif_acm_initiator.Enabled()) - return; - bool ret = false; - if (false /*btif_acm_initiator.IsCsipRegistered() && (btif_acm_initiator.MusicActiveCSetId() != INVALID_SET_ID)*/) { - ret = btif_acm_request_csip_lock(btif_acm_initiator.MusicActiveCSetId()); - //call below in lock changed success CB. - //should be dispatched to list of peers in active music group. - if (ret == false) { - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_FAILURE); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_FAILURE); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - return; - } - btif_acm_check_and_start_group_procedure_timer(btif_acm_initiator.MusicActiveCSetId()); - } else { - int id = btif_acm_initiator.MusicActiveCSetId(); - if (id < INVALID_SET_ID) { - bool send_neg_ack = true; - tBTA_CSIP_CSET cset_info; // need to do memset ? - memset(&cset_info, 0, sizeof(tBTA_CSIP_CSET)); - cset_info = BTA_CsipGetCoordinatedSet(id); - std::vector::iterator itr; - BTIF_TRACE_DEBUG("%s: size of set members %d", __func__, (cset_info.set_members).size()); - if ((cset_info.set_members).size() > 0) { - for (itr =(cset_info.set_members).begin(); itr != (cset_info.set_members).end(); itr++) { - BTIF_TRACE_DEBUG("%s: Sending suspend request ", __func__); - BtifAcmPeer* p = btif_acm_initiator.FindPeer(*itr); - if (p != nullptr && p->IsConnected()) { - send_neg_ack = false; - p->SetStreamContextType(CONTEXT_TYPE_MUSIC); - btif_acm_initiator_dispatch_sm_event(*itr, BTIF_ACM_SUSPEND_STREAM_REQ_EVT); - } - } - } - if (send_neg_ack) { - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - return; - } - btif_acm_check_and_start_group_procedure_timer(btif_acm_initiator.MusicActiveCSetId()); - } else { - BTIF_TRACE_DEBUG("%s: Sending suspend to twm device ", __func__); - BtifAcmPeer* p = btif_acm_initiator.FindPeer(btif_acm_initiator_music_active_peer()); - if (p != nullptr && p->IsConnected()) { - p->SetStreamContextType(CONTEXT_TYPE_MUSIC); - btif_acm_initiator_dispatch_sm_event(btif_acm_initiator_music_active_peer(), BTIF_ACM_SUSPEND_STREAM_REQ_EVT); - } else { - tA2DP_CTRL_CMD pending_cmd = btif_ahim_get_pending_command(); - if (pending_cmd == A2DP_CTRL_CMD_STOP || - pending_cmd == A2DP_CTRL_CMD_SUSPEND) { - btif_acm_source_on_suspended(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS); - } else if (pending_cmd == A2DP_CTRL_CMD_START) { - btif_acm_on_started(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS); - } else { - BTIF_TRACE_DEBUG("%s: no pending command to ack mm audio", __func__); - } - } - } - } -} - -void btif_acm_disconnect(const RawAddress& peer_address, int context_type) { - LOG_INFO(LOG_TAG, "%s: peer %s", __func__, peer_address.ToString().c_str()); - disconnect_acm_initiator(peer_address, context_type); -} - -static void btif_acm_initiator_dispatch_sm_event(const RawAddress& peer_address, - btif_acm_sm_event_t event) { - BtifAcmEvent btif_acm_event(event, nullptr, 0); - BTIF_TRACE_EVENT("%s: peer_address=%s event=%s", __func__, - peer_address.ToString().c_str(), - btif_acm_event.ToString().c_str()); - - btif_transfer_context(btif_acm_handle_evt, event, (char *)&peer_address, - sizeof(RawAddress), NULL); -} - -bt_status_t btif_acm_initiator_execute_service(bool enable) { - BTIF_TRACE_EVENT("%s: service: %s", __func__, - (enable) ? "enable" : "disable"); - - if (enable) { - BTA_RegisterCsipApp(bta_csip_callback, base::Bind([](uint8_t status, uint8_t app_id) { - if (status != BTA_CSIP_SUCCESS) { - LOG(ERROR) << "Can't register CSIP module "; - return; - } - BTIF_TRACE_DEBUG("App ID: %d", app_id); - btif_acm_initiator.SetCsipAppId(app_id); - btif_acm_initiator.SetCsipRegistration(true);} )); - return BT_STATUS_SUCCESS; - } - - // Disable the service - //BTA_UnregisterCsipApp(); - return BT_STATUS_FAIL; -} - -// Get the ACM callback interface for ACM Initiator profile -const btacm_initiator_interface_t* btif_acm_initiator_get_interface(void) { - BTIF_TRACE_EVENT("%s", __func__); - return &bt_acm_initiator_interface; -} - -uint16_t btif_acm_get_active_device_latency() { - BtifAcmPeer* peer = btif_acm_initiator.FindMusicActivePeer(); - if (peer == nullptr) { - BTIF_TRACE_WARNING("%s: peer is NULL", __func__); - return 0; - } else { - return peer->GetPeerLatency(); - } -} - -static void SelectCodecQosConfig(const RawAddress& bd_addr, - int profile_type, int context_type, - int direction, int config_type) { - - BTIF_TRACE_DEBUG("%s: Peer %s , context type: %d, profile_type: %d," - " direction: %d config_type %d", __func__, - bd_addr.ToString().c_str(), context_type, - profile_type, direction, config_type); - - BtifAcmPeer* peer = btif_acm_initiator.FindPeer(bd_addr); - if (peer == nullptr) { - BTIF_TRACE_WARNING("%s: peer is NULL", __func__); - return; - } - - uint8_t CigId = peer->CigId(); - uint8_t set_size = 0; - tBTA_CSIP_CSET cset_info; - memset(&cset_info, 0, sizeof(cset_info)); - cset_info = BTA_CsipGetCoordinatedSet(peer->SetId()); - BTIF_TRACE_DEBUG("%s: cset members size: %d", - __func__, (uint8_t)(cset_info.size)); - - if (cset_info.size == 0) { - BTIF_TRACE_WARNING("%s: this shud be case for stereo-HS, config_type %d", - __func__, config_type); - set_size = (config_type == STEREO_HS_CONFIG_1) ? 2 : 1; - } else { - set_size = cset_info.size; - } - - CodecConfig codec_config_; - CodecQosConfig codec_qos_config; - QosConfig qos_configs; - CISConfig cis_config; - std::vector vmcp_qos_config; - BTIF_TRACE_WARNING("%s: going for best config", __func__); - memset(&codec_config_, 0, sizeof(codec_config_)); - select_best_codec_config(bd_addr, context_type, profile_type, - &codec_config_, direction, config_type); - codec_qos_config.codec_config = codec_config_; - BTIF_TRACE_DEBUG("%s: sample rate : %d, frame_duration: %d, octets: %d, ", - __func__, static_cast(codec_config_.sample_rate), - GetFrameDuration(&codec_config_), - GetOctsPerFrame(&codec_config_)); - - if (context_type == MEDIA_CONTEXT) { - if (profile_type != WMCP) { - vmcp_qos_config = get_qos_params_for_codec(profile_type, - MEDIA_LL_CONTEXT, - codec_config_.sample_rate, - GetFrameDuration(&codec_config_), - GetOctsPerFrame(&codec_config_)); - } else { - vmcp_qos_config = get_qos_params_for_codec(profile_type, - MEDIA_HR_CONTEXT, - codec_config_.sample_rate, - GetFrameDuration(&codec_config_), - GetOctsPerFrame(&codec_config_)); - } - } else if (context_type == VOICE_CONTEXT) { - vmcp_qos_config = get_qos_params_for_codec(profile_type, - VOICE_CONTEXT, - codec_config_.sample_rate, - GetFrameDuration(&codec_config_), - GetOctsPerFrame(&codec_config_)); - } - BTIF_TRACE_DEBUG("%s: vmcp qos size: %d", - __func__, (uint8_t)vmcp_qos_config.size()); - - bool qhs_enable = false; - char qhs_value[PROPERTY_VALUE_MAX] = "false"; - property_get("persist.vendor.btstack.qhs_enable", qhs_value, "false"); - if (!strncmp("true", qhs_value, 4)) { - if (btm_acl_qhs_phy_supported(bd_addr, BT_TRANSPORT_LE)) { - qhs_enable = true; - } - } else { - qhs_enable = false; - } - - //TODO: fill cig id and cis count from - //Currently it is a single size vector - for (uint8_t j = 0; j < (uint8_t)vmcp_qos_config.size(); j++) { - if (vmcp_qos_config[j].mandatory == 0) { - uint32_t sdu_interval = vmcp_qos_config[j].sdu_int_micro_secs; - codec_qos_config.qos_config.cig_config = { - .cig_id = CigId, - .cis_count = set_size, - .packing = 0x01, // interleaved - .framing = vmcp_qos_config[j].framing, // unframed - .max_tport_latency_m_to_s = vmcp_qos_config[j].max_trans_lat, - .max_tport_latency_s_to_m = vmcp_qos_config[j].max_trans_lat, - .sdu_interval_m_to_s = { - static_cast(sdu_interval & 0xFF), - static_cast((sdu_interval >> 8)& 0xFF), - static_cast((sdu_interval >> 16)& 0xFF) - }, - .sdu_interval_s_to_m = { - static_cast(sdu_interval & 0xFF), - static_cast((sdu_interval >> 8)& 0xFF), - static_cast((sdu_interval >> 16)& 0xFF) - } - }; - BTIF_TRACE_DEBUG("%s: framing: %d, transport latency: %d" - " sdu_interval: %d", __func__, - vmcp_qos_config[j].framing, - vmcp_qos_config[j].max_trans_lat, - vmcp_qos_config[j].sdu_int_micro_secs); - BTIF_TRACE_DEBUG("%s: CIG: packing: %d, transport latency m to s: %d," - " transport latency s to m: %d", __func__, - codec_qos_config.qos_config.cig_config.packing, - codec_qos_config.qos_config.cig_config.max_tport_latency_m_to_s, - codec_qos_config.qos_config.cig_config.max_tport_latency_s_to_m); - BTIF_TRACE_DEBUG("%s: Filled CIG config ", __func__); - } - } - - for (uint8_t i = 0; i < set_size; i++) { - //Currently it is a single size vector - uint8_t check_memset = 0; - for (uint8_t j = 0; j < (uint8_t)vmcp_qos_config.size(); j++) { - if (vmcp_qos_config[j].mandatory == 0) { - memset(&cis_config, 0, sizeof(cis_config)); - if (!check_memset) - check_memset = 1; - cis_config.cis_id = i; - if (profile_type != WMCP) - cis_config.max_sdu_m_to_s = vmcp_qos_config[j].max_sdu_size; - else - cis_config.max_sdu_m_to_s = 0; - if ((context_type == VOICE_CONTEXT) || (profile_type == WMCP)) - cis_config.max_sdu_s_to_m = vmcp_qos_config[j].max_sdu_size; - else - cis_config.max_sdu_s_to_m = 0; - - BTIF_TRACE_DEBUG("%s: qhs_enable: %d", __func__, qhs_enable); - - if (qhs_enable) { - cis_config.phy_m_to_s = LE_QHS_PHY; - cis_config.phy_s_to_m = LE_QHS_PHY; - } else { - cis_config.phy_m_to_s = LE_2M_PHY;//2mbps - cis_config.phy_s_to_m = LE_2M_PHY; - } - cis_config.rtn_m_to_s = vmcp_qos_config[j].retrans_num; - cis_config.rtn_s_to_m = vmcp_qos_config[j].retrans_num; - } - } - if (!check_memset) - memset(&cis_config, 0, sizeof(cis_config)); - codec_qos_config.qos_config.cis_configs.push_back(cis_config); - BTIF_TRACE_DEBUG("%s: Filled CIS config for %d", __func__, i); - } - - for (uint8_t j = 0; j < (uint8_t)vmcp_qos_config.size(); j++) { - if (vmcp_qos_config[j].mandatory == 0) { - uint32_t presen_delay = vmcp_qos_config[j].presentation_delay; - ASCSConfig ascs_config_1 = { - .cig_id = CigId, - .cis_id = peer->CisId(), - .target_latency = 0x03,//Target higher reliability - .bi_directional = false, - .presentation_delay = {static_cast(presen_delay & 0xFF), - static_cast((presen_delay >> 8)& 0xFF), - static_cast((presen_delay >> 16)& 0xFF)} - }; - codec_qos_config.qos_config.ascs_configs.push_back(ascs_config_1); - BTIF_TRACE_DEBUG("%s: presentation delay = %d", __func__, presen_delay); - BTIF_TRACE_DEBUG("%s: Filled ASCS config for %d", __func__, ascs_config_1.cis_id); - if (config_type == STEREO_HS_CONFIG_1) { - ASCSConfig ascs_config_2 = ascs_config_1; - ascs_config_2.cis_id = peer->CisId()+1; - codec_qos_config.qos_config.ascs_configs.push_back(ascs_config_2); - BTIF_TRACE_DEBUG("%s: Filled ASCS config for %d", __func__, ascs_config_2.cis_id); - } - } - } - - if (profile_type == BAP) { - if (context_type == VOICE_CONTEXT) { - if (direction == SNK) { - codec_qos_config.qos_config.cig_config.cig_id = CigId + 2; - codec_qos_config.qos_config.ascs_configs[0].cig_id = CigId + 2; - codec_qos_config.qos_config.ascs_configs[0].target_latency = 0x01; - codec_qos_config.qos_config.ascs_configs[0].bi_directional = true; - if (config_type == STEREO_HS_CONFIG_1) { - codec_qos_config.qos_config.ascs_configs[1].cig_id = CigId + 2; - codec_qos_config.qos_config.ascs_configs[1].target_latency = 0x01; - codec_qos_config.qos_config.ascs_configs[1].bi_directional = true; - } - peer->set_peer_voice_tx_codec_config(codec_config_); - peer->set_peer_voice_tx_qos_config(codec_qos_config.qos_config); - peer->set_peer_voice_tx_codec_qos_config(codec_qos_config); - } else if (direction == SRC) { - codec_qos_config.qos_config.cig_config.cig_id = CigId + 2; - codec_qos_config.qos_config.ascs_configs[0].cig_id = CigId + 2; - codec_qos_config.qos_config.ascs_configs[0].target_latency = 0x01; - codec_qos_config.qos_config.ascs_configs[0].bi_directional = true; - if (config_type == STEREO_HS_CONFIG_1) { - codec_qos_config.qos_config.ascs_configs[1].cig_id = CigId + 2; - codec_qos_config.qos_config.ascs_configs[1].target_latency = 0x01; - codec_qos_config.qos_config.ascs_configs[1].bi_directional = true; - } - peer->set_peer_voice_rx_codec_config(codec_config_); - peer->set_peer_voice_rx_qos_config(codec_qos_config.qos_config); - peer->set_peer_voice_rx_codec_qos_config(codec_qos_config); - } - } else { - peer->set_peer_media_codec_config(codec_config_); - peer->set_peer_media_qos_config(codec_qos_config.qos_config); - peer->set_peer_media_codec_qos_config(codec_qos_config); - } - } else if (profile_type == GCP) { - if (context_type == VOICE_CONTEXT) { - codec_qos_config.qos_config.cig_config.cig_id = CigId + 1; - codec_qos_config.qos_config.ascs_configs[0].cig_id = CigId + 1; - codec_qos_config.qos_config.ascs_configs[0].target_latency = 0x01; - codec_qos_config.qos_config.ascs_configs[0].bi_directional = true; - peer->set_peer_voice_rx_codec_config(codec_config_); - peer->set_peer_voice_rx_qos_config(codec_qos_config.qos_config); - peer->set_peer_voice_rx_codec_qos_config(codec_qos_config); - } else { - peer->set_peer_media_codec_config(codec_config_); - peer->set_peer_media_qos_config(codec_qos_config.qos_config); - peer->set_peer_media_codec_qos_config(codec_qos_config); - } - } else if (profile_type == WMCP) { - if (context_type == MEDIA_CONTEXT) { - codec_qos_config.qos_config.cig_config.cig_id = CigId + 3; - codec_qos_config.qos_config.ascs_configs[0].cig_id = CigId + 3; - if (config_type == STEREO_HS_CONFIG_1) - codec_qos_config.qos_config.ascs_configs[1].cig_id = CigId + 3; - peer->set_peer_media_codec_config(codec_config_); - peer->set_peer_media_qos_config(codec_qos_config.qos_config); - peer->set_peer_media_codec_qos_config(codec_qos_config); - } - } - //print_codec_parameters(codec_config_); - //print_qos_parameters(codec_qos_config.qos_config); -} - -static bool select_best_sample_rate(uint16_t samp_freq, CodecConfig *result_config) { - BTIF_TRACE_DEBUG("%s: samp_freq: %d", __func__, samp_freq); - if (samp_freq & static_cast(CodecSampleRate::CODEC_SAMPLE_RATE_48000)) { - result_config->sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_48000; - return true; - } - if (samp_freq & static_cast(CodecSampleRate::CODEC_SAMPLE_RATE_44100)) { - result_config->sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_44100; - return true; - } - if (samp_freq & static_cast(CodecSampleRate::CODEC_SAMPLE_RATE_32000)) { - result_config->sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_32000; - return true; - } - if (samp_freq & static_cast(CodecSampleRate::CODEC_SAMPLE_RATE_24000)) { - result_config->sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_24000; - return true; - } - if (samp_freq & static_cast(CodecSampleRate::CODEC_SAMPLE_RATE_16000)) { - result_config->sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_16000; - return true; - } - if (samp_freq & static_cast(CodecSampleRate::CODEC_SAMPLE_RATE_8000)) { - result_config->sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_8000; - return true; - } - return false; -} - -static bool select_best_frame_dura(uint8_t frame_dura, - CodecConfig *result_config) { - BTIF_TRACE_DEBUG("%s: frame_duration: %d", __func__, frame_dura); - if (frame_dura & static_cast(CodecFrameDuration::FRAME_DUR_10)) { - BTIF_TRACE_DEBUG("%s: selecting 10ms as best frame duration", __func__); - UpdateFrameDuration(result_config, - static_cast(CodecFrameDuration::FRAME_DUR_10)); - return true; - } - - if ((frame_dura & - static_cast(CodecFrameDuration::FRAME_DUR_7_5)) == 0) { - BTIF_TRACE_DEBUG("%s: selecting 7.5ms as best frame duration", __func__); - UpdateFrameDuration(result_config, - static_cast(CodecFrameDuration::FRAME_DUR_7_5)); - return true; - } - return true; -} - -void select_best_codec_config(const RawAddress& bd_addr, - uint16_t context_type, - uint8_t profile_type, - CodecConfig *codec_config, - int dir, int config_type) { - - BTIF_TRACE_DEBUG("%s: select best codec config for context type: %d," - " profile type %d config_type %d", __func__, - context_type, profile_type, config_type); - - CodecConfig result_codec_config; - uint16_t vmcp_samp_freq = 0; - uint8_t vmcp_fram_dur = 0; - uint32_t vmcp_octets_per_frame = 0; - std::vector pac_record; - std::vector local_codec_config; - memset(&result_codec_config, 0, sizeof(result_codec_config)); - bool pac_found = false; - uint16_t audio_context_type = CONTENT_TYPE_UNSPECIFIED; - - bool is_lc3q_supported = false; - char lc3q_value[PROPERTY_VALUE_MAX] = "false"; - property_get("persist.vendor.service.bt.is_lc3q_supported", lc3q_value, "false"); - if (!strncmp("true", lc3q_value, 4)) { - is_lc3q_supported = true; - } else { - is_lc3q_supported = false; - } - BTIF_TRACE_IMP("%s: is_lc3q_supported: %d", __func__, is_lc3q_supported); - - if (context_type == MEDIA_CONTEXT) { - audio_context_type |= - (profile_type == WMCP) ? CONTENT_TYPE_LIVE : CONTENT_TYPE_MEDIA; - } else if (context_type == VOICE_CONTEXT) { - audio_context_type |= CONTENT_TYPE_CONVERSATIONAL; - } - BTIF_TRACE_IMP("%s: audio_context_type: %d", __func__, audio_context_type); - - pac_found = btif_bap_get_records(bd_addr, REC_TYPE_CAPABILITY, audio_context_type, - ((dir == SRC) ? CodecDirection::CODEC_DIR_SRC : CodecDirection::CODEC_DIR_SINK), - &pac_record); - - if (pac_found) { - BTIF_TRACE_DEBUG("%s: PAC record found, select best codec config", __func__); - uint16_t peer_samp_freq = 0; - uint8_t peer_channel_mode = 0; - uint8_t peer_fram_dur = 0; - uint16_t peer_min_octets_per_frame = 0; - uint16_t peer_max_octets_per_frame = 0; - uint8_t peer_max_sup_lc3_frames = 0; - uint16_t peer_preferred_context = 0; - bool peer_lc3q_pref = 0; - uint8_t peer_lc3q_ver = 0; - - //currently differentiating based on frequency later we will do on context type - for (auto it = pac_record.begin(); it != pac_record.end(); ++it) { - if (it->codec_type == CodecIndex::CODEC_INDEX_SOURCE_LC3) { - //performing only for MUSIC context type based on 44.1KHz and 48KHz - BTIF_TRACE_DEBUG("%s: pac_record sample_rate: %d", __func__, it->sample_rate); - if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_48000) { - peer_samp_freq |= static_cast(it->sample_rate); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_44100) { - peer_samp_freq |= static_cast(it->sample_rate); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_32000) { - peer_samp_freq |= static_cast(it->sample_rate); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_24000) { - peer_samp_freq |= static_cast(it->sample_rate); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_16000) { - peer_samp_freq |= static_cast(it->sample_rate); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_8000) { - peer_samp_freq |= static_cast(it->sample_rate); - } - } - } - - local_codec_config = get_all_codec_configs(profile_type, context_type); - BTIF_TRACE_DEBUG("%s: vmcp codec size: %d", - __func__, (uint8_t)local_codec_config.size()); - for (auto it = local_codec_config.begin(); - it != local_codec_config.end(); ++it) { - if (it->codec_type == CodecIndex::CODEC_INDEX_SOURCE_LC3) { - BTIF_TRACE_DEBUG("%s: local_codec_config sample_rate: %d", - __func__, it->sample_rate); - if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_48000) { - vmcp_samp_freq |= static_cast(it->sample_rate); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_44100) { - vmcp_samp_freq |= static_cast(it->sample_rate); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_32000) { - vmcp_samp_freq |= static_cast(it->sample_rate); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_24000) { - vmcp_samp_freq |= static_cast(it->sample_rate); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_16000) { - vmcp_samp_freq |= static_cast(it->sample_rate); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_8000) { - vmcp_samp_freq |= static_cast(it->sample_rate); - } - } - } - - select_best_sample_rate(peer_samp_freq & vmcp_samp_freq, - &result_codec_config); - for (auto it = pac_record.begin(); it != pac_record.end(); ++it) { - if (it->codec_type == CodecIndex::CODEC_INDEX_SOURCE_LC3) { - BTIF_TRACE_DEBUG("%s: pac_record sample_rate: %d," - " result_codec_config.sample_rate: %d", - __func__, it->sample_rate, - result_codec_config.sample_rate); - if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_48000 && - result_codec_config.sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_48000) { - BTIF_TRACE_DEBUG("%s: selecting 48KHz for config", __func__); - peer_channel_mode = static_cast(it->channel_mode); - peer_fram_dur = GetCapaSupFrameDurations(&(*it)); - peer_min_octets_per_frame = GetCapaSupOctsPerFrame(&(*it)) & 0xFFFF; - peer_max_octets_per_frame = (GetCapaSupOctsPerFrame(&(*it)) & 0xFFFF0000) >> 16; - peer_max_sup_lc3_frames = GetCapaMaxSupLc3Frames(&(*it)); - peer_lc3q_pref = GetCapaVendorMetaDataLc3QPref(&(*it)); - peer_lc3q_ver = GetCapaVendorMetaDataLc3QVer(&(*it)); - peer_preferred_context = GetCapaPreferredContexts(&(*it)); - break; - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_44100 && - result_codec_config.sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_44100) { - BTIF_TRACE_DEBUG("%s: selecting 44.1KHz for config", __func__); - peer_channel_mode = static_cast(it->channel_mode); - peer_fram_dur = GetCapaSupFrameDurations(&(*it)); - peer_min_octets_per_frame = GetCapaSupOctsPerFrame(&(*it)) & 0xFFFF; - peer_max_octets_per_frame = (GetCapaSupOctsPerFrame(&(*it)) & 0xFFFF0000) >> 16; - peer_max_sup_lc3_frames = GetCapaMaxSupLc3Frames(&(*it)); - peer_lc3q_pref = GetCapaVendorMetaDataLc3QPref(&(*it)); - peer_lc3q_ver = GetCapaVendorMetaDataLc3QVer(&(*it)); - peer_preferred_context = GetCapaPreferredContexts(&(*it)); - break; - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_32000 && - result_codec_config.sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_32000) { - BTIF_TRACE_DEBUG("%s: selecting 32KHz for config", __func__); - peer_channel_mode = static_cast(it->channel_mode); - peer_fram_dur = GetCapaSupFrameDurations(&(*it)); - peer_min_octets_per_frame = GetCapaSupOctsPerFrame(&(*it)) & 0xFFFF; - peer_max_octets_per_frame = (GetCapaSupOctsPerFrame(&(*it)) & 0xFFFF0000) >> 16; - peer_max_sup_lc3_frames = GetCapaMaxSupLc3Frames(&(*it)); - peer_lc3q_pref = GetCapaVendorMetaDataLc3QPref(&(*it)); - peer_lc3q_ver = GetCapaVendorMetaDataLc3QVer(&(*it)); - peer_preferred_context = GetCapaPreferredContexts(&(*it)); - break; - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_24000 && - result_codec_config.sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_24000) { - BTIF_TRACE_DEBUG("%s: selecting 24KHz for config", __func__); - peer_channel_mode = static_cast(it->channel_mode); - peer_fram_dur = GetCapaSupFrameDurations(&(*it)); - peer_min_octets_per_frame = GetCapaSupOctsPerFrame(&(*it)) & 0xFFFF; - peer_max_octets_per_frame = (GetCapaSupOctsPerFrame(&(*it)) & 0xFFFF0000) >> 16; - peer_max_sup_lc3_frames = GetCapaMaxSupLc3Frames(&(*it)); - peer_lc3q_pref = GetCapaVendorMetaDataLc3QPref(&(*it)); - peer_lc3q_ver = GetCapaVendorMetaDataLc3QVer(&(*it)); - peer_preferred_context = GetCapaPreferredContexts(&(*it)); - break; - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_16000 && - result_codec_config.sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_16000) { - BTIF_TRACE_DEBUG("%s: selecting 16KHz for config", __func__); - peer_channel_mode = static_cast(it->channel_mode); - peer_fram_dur = GetCapaSupFrameDurations(&(*it)); - peer_min_octets_per_frame = GetCapaSupOctsPerFrame(&(*it)) & 0xFFFF; - peer_max_octets_per_frame = (GetCapaSupOctsPerFrame(&(*it)) & 0xFFFF0000) >> 16; - peer_max_sup_lc3_frames = GetCapaMaxSupLc3Frames(&(*it)); - peer_lc3q_pref = GetCapaVendorMetaDataLc3QPref(&(*it)); - peer_lc3q_ver = GetCapaVendorMetaDataLc3QVer(&(*it)); - peer_preferred_context = GetCapaPreferredContexts(&(*it)); - break; - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_8000 && - result_codec_config.sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_8000) { - BTIF_TRACE_DEBUG("%s: selecting 8KHz for config", __func__); - peer_channel_mode = static_cast(it->channel_mode); - peer_fram_dur = GetCapaSupFrameDurations(&(*it)); - peer_min_octets_per_frame = GetCapaSupOctsPerFrame(&(*it)) & 0xFFFF; - peer_max_octets_per_frame = (GetCapaSupOctsPerFrame(&(*it)) & 0xFFFF0000) >> 16; - peer_max_sup_lc3_frames = GetCapaMaxSupLc3Frames(&(*it)); - peer_lc3q_pref = GetCapaVendorMetaDataLc3QPref(&(*it)); - peer_lc3q_ver = GetCapaVendorMetaDataLc3QVer(&(*it)); - peer_preferred_context = GetCapaPreferredContexts(&(*it)); - break; - } - } - } - - BTIF_TRACE_DEBUG("%s: PAC parameters, peer supported sample_freqncies=%d," - " channel_mode=%d, frame_dura=%d", __func__, - peer_samp_freq, peer_channel_mode, peer_fram_dur); - BTIF_TRACE_DEBUG("%s: PAC parameters, min_octets_per_frame=%d," - " max_octets_per_frame=%d, peer_max_sup_lc3_frames=%d", - __func__, peer_min_octets_per_frame, peer_max_octets_per_frame, - peer_max_sup_lc3_frames); - BTIF_TRACE_DEBUG("%s: PAC parameters, peer_preferred_context=%d", - __func__, peer_preferred_context); - BTIF_TRACE_DEBUG("%s: PAC parameters, peer_lc3q_pref=%d, peer_lc3q_ver=%d", - __func__, peer_lc3q_pref, peer_lc3q_ver); - - local_codec_config = get_all_codec_configs(profile_type, context_type); - BTIF_TRACE_DEBUG("%s: vmcp codec size: %d", - __func__, (uint8_t)local_codec_config.size()); - for (auto it = local_codec_config.begin(); - it != local_codec_config.end(); ++it) { - if (it->codec_type == CodecIndex::CODEC_INDEX_SOURCE_LC3) { - BTIF_TRACE_DEBUG("%s: local_codec_config sample_rate: %d," - " result_codec_config.sample_rate: %d", - __func__, it->sample_rate, result_codec_config.sample_rate); - if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_48000 && - result_codec_config.sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_48000) { - vmcp_fram_dur |= GetFrameDuration(&(*it)); - if (vmcp_octets_per_frame < GetOctsPerFrame(&(*it))) - vmcp_octets_per_frame = GetOctsPerFrame(&(*it)); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_44100 && - result_codec_config.sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_44100) { - vmcp_fram_dur |= GetFrameDuration(&(*it)); - if (vmcp_octets_per_frame < GetOctsPerFrame(&(*it))) - vmcp_octets_per_frame = GetOctsPerFrame(&(*it)); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_32000 && - result_codec_config.sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_32000) { - vmcp_fram_dur |= GetFrameDuration(&(*it)); - if (vmcp_octets_per_frame < GetOctsPerFrame(&(*it))) - vmcp_octets_per_frame = GetOctsPerFrame(&(*it)); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_24000 && - result_codec_config.sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_24000) { - vmcp_fram_dur |= GetFrameDuration(&(*it)); - if (vmcp_octets_per_frame < GetOctsPerFrame(&(*it))) - vmcp_octets_per_frame = GetOctsPerFrame(&(*it)); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_16000 && - result_codec_config.sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_16000) { - vmcp_fram_dur |= GetFrameDuration(&(*it)); - if (vmcp_octets_per_frame < GetOctsPerFrame(&(*it))) - vmcp_octets_per_frame = GetOctsPerFrame(&(*it)); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_8000 && - result_codec_config.sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_8000) { - vmcp_fram_dur |= GetFrameDuration(&(*it)); - if (vmcp_octets_per_frame < GetOctsPerFrame(&(*it))) - vmcp_octets_per_frame = GetOctsPerFrame(&(*it)); - } - } - } - - if (config_type == STEREO_HS_CONFIG_2) - vmcp_octets_per_frame = vmcp_octets_per_frame * 2; - - BTIF_TRACE_DEBUG("%s: VMCP parameters, sample_freq=%d," - " frame_duration=%d, octets=%d", __func__, - vmcp_samp_freq, vmcp_fram_dur, vmcp_octets_per_frame); - - result_codec_config.codec_type = CodecIndex::CODEC_INDEX_SOURCE_LC3; - result_codec_config.codec_priority = CodecPriority::CODEC_PRIORITY_DEFAULT; - - if (config_type == STEREO_HS_CONFIG_2) { - result_codec_config.channel_mode = CodecChannelMode::CODEC_CHANNEL_MODE_STEREO; - } else { - result_codec_config.channel_mode = CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - } - - select_best_frame_dura((peer_fram_dur >> 1) & vmcp_fram_dur, &result_codec_config); - - if (vmcp_octets_per_frame < peer_min_octets_per_frame || - vmcp_octets_per_frame > peer_max_octets_per_frame) { - BTIF_TRACE_DEBUG("%s: octets per frame is out of bound: %d ", - __func__, vmcp_octets_per_frame); - UpdateOctsPerFrame(&result_codec_config, vmcp_octets_per_frame); - } else { - BTIF_TRACE_DEBUG("%s: octets per frame is in limit update 100 octets: %d ", - __func__, vmcp_octets_per_frame); - UpdateOctsPerFrame(&result_codec_config, vmcp_octets_per_frame);//TODO: make this as peer octets - } - - if (is_lc3q_supported) { - UpdateLc3QPreference(&result_codec_config, true); - } - UpdateCapaMaxSupLc3Frames(&result_codec_config, peer_max_sup_lc3_frames); - UpdateLc3BlocksPerSdu(&result_codec_config, 1); - UpdatePreferredAudioContext(&result_codec_config, audio_context_type); - *codec_config = result_codec_config; - } else { - BTIF_TRACE_DEBUG("%s: PAC record not found, select mandatory config", __func__); - mandatory_codec_selected = true; - std::vector codec_pref_config; - codec_pref_config = get_all_codec_configs(profile_type, context_type); - BTIF_TRACE_DEBUG("%s: vmcp codec size %d", __func__, (uint8_t)codec_pref_config.size()); - for (auto it = codec_pref_config.begin(); it != codec_pref_config.end(); ++it) { - if (it->codec_type == CodecIndex::CODEC_INDEX_SOURCE_LC3) { - if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_48000) { - BTIF_TRACE_DEBUG("%s: selecting 48KHz from VMCP", __func__); - result_codec_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_48000; - vmcp_fram_dur |= GetFrameDuration(&(*it)); - if (vmcp_octets_per_frame < GetOctsPerFrame(&(*it))) - vmcp_octets_per_frame = GetOctsPerFrame(&(*it)); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_44100) { - BTIF_TRACE_DEBUG("%s: selecting 44.1KHz from VMCP", __func__); - result_codec_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_44100; - vmcp_fram_dur |= GetFrameDuration(&(*it)); - if (vmcp_octets_per_frame < GetOctsPerFrame(&(*it))) - vmcp_octets_per_frame = GetOctsPerFrame(&(*it)); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_32000) { - BTIF_TRACE_DEBUG("%s: selecting 32KHz from VMCP", __func__); - result_codec_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_32000; - vmcp_fram_dur |= GetFrameDuration(&(*it)); - if (vmcp_octets_per_frame < GetOctsPerFrame(&(*it))) - vmcp_octets_per_frame = GetOctsPerFrame(&(*it)); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_24000) { - BTIF_TRACE_DEBUG("%s: selecting 24KHz from VMCP", __func__); - result_codec_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_24000; - vmcp_fram_dur |= GetFrameDuration(&(*it)); - if (vmcp_octets_per_frame < GetOctsPerFrame(&(*it))) - vmcp_octets_per_frame = GetOctsPerFrame(&(*it)); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_16000) { - BTIF_TRACE_DEBUG("%s: selecting 16KHz from VMCP", __func__); - result_codec_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_16000; - vmcp_fram_dur |= GetFrameDuration(&(*it)); - if (vmcp_octets_per_frame < GetOctsPerFrame(&(*it))) - vmcp_octets_per_frame = GetOctsPerFrame(&(*it)); - } else if (it->sample_rate == CodecSampleRate::CODEC_SAMPLE_RATE_8000) { - BTIF_TRACE_DEBUG("%s: selecting 8KHz from VMCP", __func__); - result_codec_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_8000; - vmcp_fram_dur |= GetFrameDuration(&(*it)); - if (vmcp_octets_per_frame < GetOctsPerFrame(&(*it))) - vmcp_octets_per_frame = GetOctsPerFrame(&(*it)); - } - } - } - - if (config_type == STEREO_HS_CONFIG_2) - vmcp_octets_per_frame = vmcp_octets_per_frame * 2; - - BTIF_TRACE_DEBUG("%s: VMCP parameters, frame_duration=%d, octets=%d", - __func__, vmcp_fram_dur, vmcp_octets_per_frame); - - result_codec_config.codec_type = CodecIndex::CODEC_INDEX_SOURCE_LC3; - result_codec_config.codec_priority = CodecPriority::CODEC_PRIORITY_DEFAULT; - if (config_type == STEREO_HS_CONFIG_2) - result_codec_config.channel_mode = CodecChannelMode::CODEC_CHANNEL_MODE_STEREO; - else - result_codec_config.channel_mode = CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - //select_best_sample_rate(peer_samp_freq & vmcp_samp_freq, &result_codec_config, context_type); - select_best_frame_dura(vmcp_fram_dur, &result_codec_config); - UpdateOctsPerFrame(&result_codec_config, vmcp_octets_per_frame); - if (is_lc3q_supported) { - UpdateLc3QPreference(&result_codec_config, true); - } - UpdateLc3BlocksPerSdu(&result_codec_config, 1);//currently making it for media case - UpdatePreferredAudioContext(&result_codec_config, audio_context_type); - BTIF_TRACE_DEBUG("%s: saved codec config", __func__); - *codec_config = result_codec_config; - } -} - -uint16_t btif_acm_get_sample_rate() { - if (current_active_config.sample_rate != - CodecSampleRate::CODEC_SAMPLE_RATE_NONE) { - BTIF_TRACE_DEBUG("[ACM]:%s: sample_rate = %d", - __func__, current_active_config.sample_rate); - return static_cast(current_active_config.sample_rate); - } else { - BTIF_TRACE_DEBUG("[ACM]:%s: default sample_rate = %d", - __func__, default_config.sample_rate); - return static_cast(default_config.sample_rate); - } -} - -uint8_t btif_acm_get_ch_mode() { - if (current_active_config.channel_mode != - CodecChannelMode::CODEC_CHANNEL_MODE_NONE) { - BTIF_TRACE_DEBUG("[ACM]:%s: channel mode = %d", - __func__, current_active_config.channel_mode); - return static_cast(current_active_config.channel_mode); - } else { - BTIF_TRACE_DEBUG("[ACM]:%s: channel mode = %d", - __func__, default_config.channel_mode); - return static_cast(default_config.channel_mode); - } -} - -uint32_t btif_acm_get_bitrate() { - //based on bitrate set (100(80kbps), 120 (96kbps), 155 (128kbps)) - uint32_t bitrate = 0; - uint16_t octets = static_cast(GetOctsPerFrame(¤t_active_config)); - BTIF_TRACE_DEBUG("[ACM]:%s: octets = %d",__func__, octets); - - switch (octets) { - case 26: - bitrate = 27800; - break; - - case 30: - if (btif_acm_get_sample_rate() == - (static_cast(CodecSampleRate::CODEC_SAMPLE_RATE_8000))) { - bitrate = 24000; - } else { - bitrate = 32000; - } - break; - - case 40: - bitrate = 32000; - break; - - case 45: - bitrate = 48000; - break; - - case 60: - if (btif_acm_get_sample_rate() == - (static_cast(CodecSampleRate::CODEC_SAMPLE_RATE_24000))) { - bitrate = 48000; - } else { - bitrate = 64000; - } - break; - - case 80: - bitrate = 64000; - break; - - case 98: - case 130: - bitrate = 95550; - break; - - case 75: - case 100: - bitrate = 80000; - break; - - case 90: - case 120: - bitrate = 96000; - break; - - case 117: - case 155: - bitrate = 124000; - break; - - default: - bitrate = 124000; - break; - } - BTIF_TRACE_DEBUG("[ACM]%s: bitrate = %d",__func__,bitrate); - return bitrate; -} - -uint32_t btif_acm_get_octets(uint32_t bit_rate) { - uint32_t octets = 0; - octets = GetOctsPerFrame(¤t_active_config); - BTIF_TRACE_DEBUG("[ACM]%s: octets = %d",__func__,octets); - return octets; -} - -uint16_t btif_acm_get_framelength() { - uint16_t frame_duration; - switch (GetFrameDuration(¤t_active_config)) { - case 0: - frame_duration = 7500; //7.5msec - break; - - case 1: - frame_duration = 10000; //10msec - break; - - default: - frame_duration = 10000; - } - BTIF_TRACE_DEBUG("[ACM]%s: frame duration = %d", - __func__,frame_duration); - return frame_duration; -} - -uint16_t btif_acm_get_current_active_profile() { - return current_active_profile_type; -} -uint8_t btif_acm_get_ch_count() {//update channel mode based on device connection - uint8_t ch_mode = 0; - if (current_active_config.channel_mode == - CodecChannelMode::CODEC_CHANNEL_MODE_STEREO) { - ch_mode = 0x02; - } else if (current_active_config.channel_mode == - CodecChannelMode::CODEC_CHANNEL_MODE_MONO) { - ch_mode = 0x01; - } - BTIF_TRACE_DEBUG("[ACM]%s: channel count = %d",__func__,ch_mode); - return ch_mode; -} - -bool btif_acm_is_codec_type_lc3q() { - BTIF_TRACE_DEBUG("[ACM]%s",__func__); - return GetVendorMetaDataLc3QPref(¤t_active_config); -} - -uint8_t btif_acm_lc3q_ver() { - BTIF_TRACE_DEBUG("[ACM]%s",__func__); - return GetVendorMetaDataLc3QVer(¤t_active_config); -} - -uint16_t btif_acm_bap_to_acm_context(uint16_t bap_context) { - switch (bap_context) { - case CONTENT_TYPE_MEDIA: - case CONTENT_TYPE_LIVE: - return CONTEXT_TYPE_MUSIC; - - case CONTENT_TYPE_CONVERSATIONAL: - return CONTEXT_TYPE_VOICE; - - default: - BTIF_TRACE_DEBUG("%s: Unknown bap context",__func__); - return CONTEXT_TYPE_UNKNOWN; - } -} - -static void btif_debug_acm_peer_dump(int fd, const BtifAcmPeer& peer) { - std::string state_str; - int state = peer.StateMachine().StateId(); - switch (state) { - case BtifAcmStateMachine::kStateIdle: - state_str = "Idle"; - break; - - case BtifAcmStateMachine::kStateOpening: - state_str = "Opening"; - break; - - case BtifAcmStateMachine::kStateOpened: - state_str = "Opened"; - break; - - case BtifAcmStateMachine::kStateStarted: - state_str = "Started"; - break; - - case BtifAcmStateMachine::kStateReconfiguring: - state_str = "Reconfiguring"; - break; - - case BtifAcmStateMachine::kStateClosing: - state_str = "Closing"; - break; - - default: - state_str = "Unknown(" + std::to_string(state) + ")"; - break; - } - - dprintf(fd, " Peer: %s\n", peer.PeerAddress().ToString().c_str()); - dprintf(fd, " Connected: %s\n", peer.IsConnected() ? "true" : "false"); - dprintf(fd, " Streaming: %s\n", peer.IsStreaming() ? "true" : "false"); - dprintf(fd, " State Machine: %s\n", state_str.c_str()); - dprintf(fd, " Flags: %s\n", peer.FlagsToString().c_str()); - -} - -bool compare_codec_config_(CodecConfig &first, CodecConfig &second) { - if (first.codec_type != second.codec_type) { - BTIF_TRACE_DEBUG("[ACM] Codec type mismatch %s",__func__); - return true; - } else if (first.sample_rate != second.sample_rate) { - BTIF_TRACE_DEBUG("[ACM] Sample rate mismatch %s",__func__); - return true; - } else if (first.bits_per_sample != second.bits_per_sample) { - BTIF_TRACE_DEBUG("[ACM] Bits per sample mismatch %s",__func__); - return true; - } else if (first.channel_mode != second.channel_mode) { - BTIF_TRACE_DEBUG("[ACM] Channel mode mismatch %s",__func__); - return true; - } else { - uint8_t frame_first = GetFrameDuration(&first); - uint8_t frame_second = GetFrameDuration(&second); - if (frame_first != frame_second) { - BTIF_TRACE_DEBUG("[ACM] frame duration mismatch %s",__func__); - return true; - } - uint8_t lc3blockspersdu_first = GetLc3BlocksPerSdu(&first); - uint8_t lc3blockspersdu_second = GetLc3BlocksPerSdu(&second); - if (lc3blockspersdu_first != lc3blockspersdu_second) { - BTIF_TRACE_DEBUG("[ACM] LC3blocks per SDU mismatch %s",__func__); - return true; - } - uint16_t octets_first = GetOctsPerFrame(&first); - uint16_t octets_second = GetOctsPerFrame(&second); - if (octets_first != octets_second) { - BTIF_TRACE_DEBUG("[ACM] LC3 octets mismatch %s",__func__); - return true; - } - return false; - } -} - -void print_codec_parameters(CodecConfig config) { - uint8_t frame = GetFrameDuration(&config); - uint8_t lc3blockspersdu = GetLc3BlocksPerSdu(&config); - uint16_t octets = GetOctsPerFrame(&config); - bool vendormetadatalc3qpref = GetCapaVendorMetaDataLc3QPref(&config); - uint8_t vendormetadatalc3qver = GetCapaVendorMetaDataLc3QVer(&config); - LOG_DEBUG( - LOG_TAG, - "codec_type=%d codec_priority=%d " - "sample_rate=0x%x bits_per_sample=0x%x " - "channel_mode=0x%x", - config.codec_type, config.codec_priority, - config.sample_rate, config.bits_per_sample, - config.channel_mode); - LOG_DEBUG( - LOG_TAG, - "frame_duration=%d, lc3_blocks_per_SDU=%d," - " octets_per_frame=%d, vendormetadatalc3qpref=%d," - " vendormetadatalc3qver=%d ", - frame, lc3blockspersdu, octets, - vendormetadatalc3qpref, vendormetadatalc3qver); -} - -void print_qos_parameters(QosConfig qos) { - LOG_DEBUG( - LOG_TAG, - "CIG --> cig_id=%d cis_count=%d " - "packing=%d framing=%d " - "max_tport_latency_m_to_s=%d " - "max_tport_latency_s_to_m=%d " - "sdu_interval_m_to_s[0] = %x " - "sdu_interval_m_to_s[1] = %x " - "sdu_interval_m_to_s[2] = %x ", - qos.cig_config.cig_id, qos.cig_config.cis_count, - qos.cig_config.packing, qos.cig_config.framing, - qos.cig_config.max_tport_latency_m_to_s, - qos.cig_config.max_tport_latency_s_to_m, - qos.cig_config.sdu_interval_m_to_s[0], - qos.cig_config.sdu_interval_m_to_s[1], - qos.cig_config.sdu_interval_m_to_s[2]); - for (auto it = qos.cis_configs.begin(); it != qos.cis_configs.end(); ++it) { - LOG_DEBUG( - LOG_TAG, - "CIS --> cis_id = %d max_sdu_m_to_s = %d " - "max_sdu_s_to_m=%d " - "phy_m_to_s = %d " - "phy_s_to_m = %d " - "rtn_m_to_s = %d " - "rtn_s_to_m = %d", - it->cis_id, it->max_sdu_m_to_s, - it->max_sdu_s_to_m, - it->phy_m_to_s, it->phy_s_to_m, - it->rtn_m_to_s, it->rtn_s_to_m); - } - for (auto it = qos.ascs_configs.begin(); it != qos.ascs_configs.end(); ++it) { - LOG_DEBUG( - LOG_TAG, - "ASCS --> cig_id = %d cis_id = %d " - "target_latency=%d " - "bi_directional = %d " - "presentation_delay[0] = %x " - "presentation_delay[1] = %x " - "presentation_delay[2] = %x ", - it->cig_id, - it->cis_id, - it->target_latency, - it->bi_directional, - it->presentation_delay[0], - it->presentation_delay[1], - it->presentation_delay[2]); - } -} - -static void btif_debug_acm_initiator_dump(int fd) { - bool enabled = btif_acm_initiator.Enabled(); - - dprintf(fd, "\nA2DP Source State: %s\n", (enabled) ? "Enabled" : "Disabled"); - if (!enabled) return; - //dprintf(fd, " Active peer: %s\n", - // btif_acm_initiator.ActivePeer().ToString().c_str()); - for (auto it : btif_acm_initiator.Peers()) { - const BtifAcmPeer* peer = it.second; - btif_debug_acm_peer_dump(fd, *peer); - } -} - -void btif_debug_acm_dump(int fd) { - btif_debug_acm_initiator_dump(fd); -} diff --git a/le_audio/system/bt/btif/src/btif_acm_source.cc b/le_audio/system/bt/btif/src/btif_acm_source.cc deleted file mode 100644 index f9b99bf41966aa92d9e4ce5ae2c9d583ab759745..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/src/btif_acm_source.cc +++ /dev/null @@ -1,242 +0,0 @@ -/****************************************************************************** - * - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - - -#include -#include "bt_trace.h" -#include "btif_acm_source.h" -#include "btif_ahim.h" -#include "btif_acm.h" -#include "osi/include/thread.h" - -extern thread_t* get_worker_thread(); - -#if AHIM_ENABLED - - -void btif_acm_process_request(tA2DP_CTRL_CMD cmd) -{ - tA2DP_CTRL_ACK status = A2DP_CTRL_ACK_FAILURE; - // update pending command - btif_ahim_update_pending_command(cmd, AUDIO_GROUP_MGR); - - BTIF_TRACE_IMP("%s: cmd %u", __func__, cmd); - - switch (cmd) { - case A2DP_CTRL_CMD_START: - { - if (btif_acm_is_call_active()) { - BTIF_TRACE_IMP("%s: call active, return incall_failure", __func__); - status = A2DP_CTRL_ACK_INCALL_FAILURE; - } else { - // ACM is in right state - status = A2DP_CTRL_ACK_PENDING; - btif_acm_stream_start(); - } - btif_ahim_ack_stream_started(status, AUDIO_GROUP_MGR); - break; - } - - case A2DP_CTRL_CMD_SUSPEND: - { - if (btif_acm_is_call_active()) { - BTIF_TRACE_IMP("%s: call active, return success", __func__); - status = A2DP_CTRL_ACK_SUCCESS; - } else { - status = A2DP_CTRL_ACK_PENDING; - btif_acm_stream_suspend(); - } - btif_ahim_ack_stream_suspended(status, AUDIO_GROUP_MGR); - break; - } - - case A2DP_CTRL_CMD_STOP: - { - status = A2DP_CTRL_ACK_SUCCESS; - if (btif_acm_is_call_active()) { - BTIF_TRACE_IMP("%s: call active, return success", __func__); - } else { - btif_acm_stream_stop(); - } - btif_ahim_ack_stream_suspended(status, AUDIO_GROUP_MGR); - break; - } - default: - APPL_TRACE_ERROR("%s: unsupported command %d", __func__, cmd); - break; - } -} - - -void btif_acm_handle_event(uint16_t event, char* p_param) -{ - - switch(event) { - case BTIF_ACM_PROCESS_HIDL_REQ_EVT: - btif_acm_process_request((tA2DP_CTRL_CMD ) *p_param); - break; - default: - BTIF_TRACE_IMP("%s: unhandled event", __func__); - break; - } -} - -void process_hidl_req_acm(tA2DP_CTRL_CMD cmd) -{ - btif_transfer_context(btif_acm_handle_event, BTIF_ACM_PROCESS_HIDL_REQ_EVT, (char*)&cmd, sizeof(cmd), NULL); -} - -static btif_ahim_client_callbacks_t sAhimAcmCallbacks = { - 1, // mode - process_hidl_req_acm, - btif_acm_get_sample_rate, - btif_acm_get_ch_mode, - btif_acm_get_bitrate, - btif_acm_get_octets, - btif_acm_get_framelength, - btif_acm_get_ch_count, - nullptr, - btif_acm_get_current_active_profile, - btif_acm_is_codec_type_lc3q, - btif_acm_lc3q_ver -}; - -void btif_register_cb() -{ - reg_cb_with_ahim(AUDIO_GROUP_MGR, &sAhimAcmCallbacks); -} - -bt_status_t btif_acm_source_setup_codec() { - APPL_TRACE_EVENT("%s", __func__); - - bt_status_t status = BT_STATUS_FAIL; - - - APPL_TRACE_EVENT("%s ## setup_codec ##", __func__); - btif_ahim_setup_codec(AUDIO_GROUP_MGR); - - // TODO: check the status - return status; -} - -bool btif_acm_source_start_session(const RawAddress& peer_address) { - bt_status_t status = BT_STATUS_FAIL; - APPL_TRACE_DEBUG("%s: starting session for BD addr %s",__func__, - peer_address.ToString().c_str()); - - // initialize hal. - btif_ahim_init_hal(get_worker_thread(), AUDIO_GROUP_MGR); - - status = btif_acm_source_setup_codec(); - - btif_ahim_start_session(); - - return true; -} - -bool btif_acm_source_end_session(const RawAddress& peer_address) { - APPL_TRACE_DEBUG("%s: starting session for BD addr %s",__func__, - peer_address.ToString().c_str()); - - btif_ahim_end_session(); - - return true; -} - -bool btif_acm_source_restart_session(const RawAddress& old_peer_address, - const RawAddress& new_peer_address) { - bool is_streaming = btif_ahim_is_streaming(); - SessionType session_type = btif_ahim_get_session_type(); - - APPL_TRACE_IMP("%s: old_peer_address=%s, new_peer_address=%s, is_streaming=%d ", - __func__, old_peer_address.ToString().c_str(), - new_peer_address.ToString().c_str(), is_streaming); - - // TODO: do we need to check for new empty address - //CHECK(!new_peer_address.IsEmpty()); - - // If the old active peer was valid or if session is not - // unknown, end the old session. - if (!old_peer_address.IsEmpty() || - session_type != SessionType::UNKNOWN) { - btif_acm_source_end_session(old_peer_address); - } - - btif_acm_source_start_session(new_peer_address); - - return true; -} - -bool btif_acm_update_sink_latency_change(uint16_t sink_latency) { - APPL_TRACE_DEBUG("%s: update_sink_latency %d for active session ",__func__, - sink_latency); - - btif_ahim_set_remote_delay(sink_latency); - - return true; -} - -void btif_acm_source_command_ack(tA2DP_CTRL_CMD cmd, tA2DP_CTRL_ACK status) { - switch (cmd) { - case A2DP_CTRL_CMD_START: - btif_ahim_ack_stream_started(status, AUDIO_GROUP_MGR); - break; - case A2DP_CTRL_CMD_SUSPEND: - case A2DP_CTRL_CMD_STOP: - btif_ahim_ack_stream_suspended(status, AUDIO_GROUP_MGR); - break; - default: - break; - } -} - -void btif_acm_source_on_stopped(tA2DP_CTRL_ACK status) { - APPL_TRACE_EVENT("%s: status %u", __func__, status); - - btif_ahim_ack_stream_suspended(status, AUDIO_GROUP_MGR); - - btif_ahim_reset_pending_command(AUDIO_GROUP_MGR); -} - -void btif_acm_source_on_suspended(tA2DP_CTRL_ACK status) { - APPL_TRACE_EVENT("%s: status %u", __func__, status); - - btif_ahim_ack_stream_suspended(status, AUDIO_GROUP_MGR); - - btif_ahim_reset_pending_command(AUDIO_GROUP_MGR); -} - -bool btif_acm_on_started(tA2DP_CTRL_ACK status) { - APPL_TRACE_EVENT("%s: status %u", __func__, status); - bool retval = false; - - if(0/* TODO: check if call is in progress*/) { - APPL_TRACE_WARNING("%s: call in progress, sending failure", __func__); - btif_ahim_ack_stream_started(A2DP_CTRL_ACK_INCALL_FAILURE, AUDIO_GROUP_MGR); - } - else { - btif_ahim_ack_stream_started(status, AUDIO_GROUP_MGR); - retval = true; - } - - btif_ahim_reset_pending_command(AUDIO_GROUP_MGR); - return retval; -} - - -#endif // AHIM_ENABLED diff --git a/le_audio/system/bt/btif/src/btif_apm.cc b/le_audio/system/bt/btif/src/btif_apm.cc deleted file mode 100644 index 02f5a6f5457cad638543faf223e7fbb680c2b63a..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/src/btif_apm.cc +++ /dev/null @@ -1,189 +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. - * - ******************************************************************************/ - - -#define LOG_TAG "btif_apm" - -#include -#include - -#include -#include - -#include "bt_common.h" -#include "btif_common.h" -#include "btif_ahim.h" - -#define A2DP_PROFILE 0x0001 -#define BROADCAST_BREDR 0x0400 -#define BROADCAST_LE 0x0800 -#define ACTIVE_VOICE_PROFILE_HFP 0x0002 - -std::mutex apm_mutex; -btapm_initiator_callbacks_t* callbacks_; - -static bt_status_t init(btapm_initiator_callbacks_t* callbacks); -static void cleanup(); -static bt_status_t update_active_device(const RawAddress& bd_addr, uint16_t profile, uint16_t audio_type); -static bt_status_t set_content_control_id(uint16_t content_control_id, uint16_t audio_type); -static bool apm_enabled = false; - - -#define CHECK_BTAPM_INIT() \ - do { \ - if (!apm_enabled) { \ - BTIF_TRACE_WARNING("%s: BTAV not initialized", __func__); \ - return BT_STATUS_NOT_READY; \ - } \ - } while (0) - -typedef enum { - BTIF_APM_AUDIO_TYPE_VOICE = 0x0, - BTIF_APM_AUDIO_TYPE_MEDIA, - - BTIF_APM_AUDIO_TYPE_SIZE -} btif_av_state_t; - -typedef struct { - RawAddress peer_bda; - int profile; -} btif_apm_device_profile_combo_t; - -typedef struct { - RawAddress peer_bda; -} btif_apm_get_active_profile; - -int active_profile_info; - -static btif_apm_device_profile_combo_t active_device_profile[BTIF_APM_AUDIO_TYPE_SIZE]; -static uint16_t content_control_id[BTIF_APM_AUDIO_TYPE_SIZE]; - -static void btif_update_active_device(uint16_t audio_type, char* param); -void btif_get_active_device(btif_av_state_t audio_type, RawAddress* peer_bda); -static void btif_update_content_control(uint16_t audio_type, char* param); -uint16_t btif_get_content_control_id(btif_av_state_t audio_type); - -static void btif_update_active_device(uint16_t audio_type, char* param) { - btif_apm_device_profile_combo_t new_device_profile; - if(audio_type != BTIF_APM_AUDIO_TYPE_MEDIA) - return; - - memcpy(&new_device_profile, param, sizeof(new_device_profile)); - active_device_profile[audio_type].peer_bda = new_device_profile.peer_bda; - active_device_profile[audio_type].profile = new_device_profile.profile; - BTIF_TRACE_WARNING("%s() New Active Device: %s, Profile: %x\n", __func__, - active_device_profile[audio_type].peer_bda.ToString().c_str(), - active_device_profile[audio_type].profile); - if(active_device_profile[audio_type].profile == A2DP_PROFILE) { - btif_ahim_update_current_profile(A2DP); - } else if(active_device_profile[audio_type].profile == BROADCAST_LE) { - btif_ahim_update_current_profile(BROADCAST); - } else { - btif_ahim_update_current_profile(AUDIO_GROUP_MGR); - } -} - -void btif_get_active_device(btif_av_state_t audio_type, RawAddress* peer_bda) { - if(audio_type >= BTIF_APM_AUDIO_TYPE_SIZE) - return; - peer_bda = &active_device_profile[audio_type].peer_bda; -} - -static void btif_update_content_control(uint16_t audio_type, char* param) { - if(audio_type >= BTIF_APM_AUDIO_TYPE_SIZE) - return; - uint16_t cc_id = (uint16_t)(*param); - content_control_id[audio_type] = cc_id; - /*Update ACM here*/ -} - -uint16_t btif_get_content_control_id(btif_av_state_t audio_type) { - if(audio_type >= BTIF_APM_AUDIO_TYPE_SIZE) - return 0; - return content_control_id[audio_type]; -} - -static const bt_apm_interface_t bt_apm_interface = { - sizeof(bt_apm_interface_t), - init, - update_active_device, - set_content_control_id, - cleanup, -}; - -const bt_apm_interface_t* btif_apm_get_interface(void) { - BTIF_TRACE_EVENT("%s", __func__); - return &bt_apm_interface; -} - -static bt_status_t init(btapm_initiator_callbacks_t* callbacks) { - BTIF_TRACE_EVENT("%s", __func__); - callbacks_ = callbacks; - apm_enabled = true; - - return BT_STATUS_SUCCESS; -} - -static void cleanup() { - BTIF_TRACE_EVENT("%s", __func__); - apm_enabled = false; -} - -static bt_status_t update_active_device(const RawAddress& bd_addr, uint16_t profile, uint16_t audio_type) { - BTIF_TRACE_EVENT("%s", __func__); - CHECK_BTAPM_INIT(); - btif_apm_device_profile_combo_t new_device_profile; - new_device_profile.peer_bda = bd_addr; - new_device_profile.profile = profile; - - std::unique_lock guard(apm_mutex); - - return btif_transfer_context(btif_update_active_device, (uint8_t)audio_type, - (char *)&new_device_profile, sizeof(btif_apm_device_profile_combo_t), NULL); -} - -static bt_status_t set_content_control_id(uint16_t content_control_id, uint16_t audio_type) { - BTIF_TRACE_EVENT("%s", __func__); - CHECK_BTAPM_INIT(); - - std::unique_lock guard(apm_mutex); - - return btif_transfer_context(btif_update_content_control, - (uint8_t)audio_type, (char *)&content_control_id, sizeof(content_control_id), NULL); -} - -void call_active_profile_info(const RawAddress& bd_addr, uint16_t audio_type) { - if (apm_enabled == true) { - BTIF_TRACE_WARNING("%s", __func__); - active_profile_info = callbacks_->active_profile_cb(bd_addr, audio_type); - BTIF_TRACE_WARNING("%s: profile info is %d", __func__, active_profile_info); - } -} - -int get_active_profile(const RawAddress& bd_addr, uint16_t audio_type) { - if (apm_enabled == true) { - BTIF_TRACE_WARNING("%s: active profile is %d ", __func__, active_profile_info); - return active_profile_info; - } - else { - BTIF_TRACE_WARNING("%s: APM is not enabled, returning HFP as active profile %d ", - __func__, ACTIVE_VOICE_PROFILE_HFP); - return ACTIVE_VOICE_PROFILE_HFP; - } -} - diff --git a/le_audio/system/bt/btif/src/btif_ascs_client.cc b/le_audio/system/bt/btif/src/btif_ascs_client.cc deleted file mode 100644 index d5853e6eec2653e16f5ea2d786d7f8b1d710e1c2..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/src/btif_ascs_client.cc +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/****************************************************************************** - * - * 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 "bta_closure_api.h" -#include "bta_ascs_client_api.h" -#include "btif_common.h" -#include "btif_storage.h" - -#include -#include -#include -#include -#include -#include -#include "osi/include/thread.h" - -using base::Bind; -using base::Unretained; -using bluetooth::bap::ascs::AscsClient; -using bluetooth::bap::ascs::GattState; -using bluetooth::bap::ascs::AscsClientCallbacks; -using bluetooth::bap::ascs::AscsClientInterface; -using bluetooth::bap::ascs::AseOpId; -using bluetooth::bap::ascs::AseOpStatus; -using bluetooth::bap::ascs::AseParams; -using bluetooth::bap::ascs::AseCodecConfigOp; -using bluetooth::bap::ascs::AseQosConfigOp; -using bluetooth::bap::ascs::AseEnableOp; -using bluetooth::bap::ascs::AseDisableOp; -using bluetooth::bap::ascs::AseStartReadyOp; -using bluetooth::bap::ascs::AseStopReadyOp; -using bluetooth::bap::ascs::AseReleaseOp; -using bluetooth::bap::ascs::AseUpdateMetadataOp; - -namespace { - -class AscsClientInterfaceImpl; -std::unique_ptr AscsClientInstance; - -class AscsClientInterfaceImpl - : public AscsClientInterface, - public AscsClientCallbacks { - ~AscsClientInterfaceImpl() = default; - - void Init(AscsClientCallbacks* callbacks) override { - DVLOG(2) << __func__; - this->callbacks = callbacks; - - do_in_bta_thread( - FROM_HERE, - Bind(&AscsClient::Init, this)); - } - - void OnAscsInitialized(int status, int client_id) override { - do_in_jni_thread(FROM_HERE, Bind(&AscsClientCallbacks::OnAscsInitialized, - Unretained(callbacks), status, - client_id)); - } - - void OnConnectionState(const RawAddress& address, - GattState state) override { - DVLOG(2) << __func__ << " address: " << address; - do_in_jni_thread(FROM_HERE, Bind(&AscsClientCallbacks::OnConnectionState, - Unretained(callbacks), address, state)); - } - - void OnAseOpFailed(const RawAddress& address, AseOpId ase_op_id, - std::vector status) override { - do_in_jni_thread(FROM_HERE, - Bind(&AscsClientCallbacks::OnAseOpFailed, - Unretained(callbacks), - address, ase_op_id, status)); - } - - void OnAseState(const RawAddress& address, AseParams ase) override { - do_in_jni_thread(FROM_HERE, - Bind(&AscsClientCallbacks::OnAseState, - Unretained(callbacks), address, ase)); - } - - void OnSearchComplete(int status, - const RawAddress& address, - std::vector sink_ase_list, - std::vector src_ase_list) override { - do_in_jni_thread(FROM_HERE, Bind(&AscsClientCallbacks::OnSearchComplete, - Unretained(callbacks), - status, - address, - sink_ase_list, - src_ase_list)); - } - - void Connect(uint16_t client_id, const RawAddress& address) override { - do_in_bta_thread(FROM_HERE, Bind(&AscsClient::Connect, - Unretained(AscsClient::Get()), - client_id, address, false)); - } - - void Disconnect(uint16_t client_id, const RawAddress& address) override { - do_in_bta_thread(FROM_HERE, Bind(&AscsClient::Disconnect, - Unretained(AscsClient::Get()), - client_id, address)); - } - - void StartDiscovery(uint16_t client_id, const RawAddress& address) override { - do_in_bta_thread(FROM_HERE, Bind(&AscsClient::StartDiscovery, - Unretained(AscsClient::Get()), - client_id, address)); - } - - void GetAseState(uint16_t client_id, const RawAddress& address, - uint8_t ase_id) override { - do_in_bta_thread(FROM_HERE, Bind(&AscsClient::GetAseState, - Unretained(AscsClient::Get()), - client_id, address, ase_id)); - } - - void CodecConfig(uint16_t client_id, const RawAddress& address, - std::vector codec_configs) override { - do_in_bta_thread(FROM_HERE, Bind(&AscsClient::CodecConfig, - Unretained(AscsClient::Get()), - client_id, address, codec_configs)); - } - - void QosConfig(uint16_t client_id, const RawAddress& address, - std::vector qos_configs) override { - do_in_bta_thread(FROM_HERE, Bind(&AscsClient::QosConfig, - Unretained(AscsClient::Get()), - client_id, address, qos_configs)); - } - - void Enable(uint16_t client_id, const RawAddress& address, - std::vector enable_ops) override { - do_in_bta_thread(FROM_HERE, Bind(&AscsClient::Enable, - Unretained(AscsClient::Get()), - client_id, address, enable_ops)); - } - - void Disable(uint16_t client_id, const RawAddress& address, - std::vector disable_ops) override { - do_in_bta_thread(FROM_HERE, Bind(&AscsClient::Disable, - Unretained(AscsClient::Get()), - client_id, address, disable_ops)); - } - - void StartReady(uint16_t client_id, const RawAddress& address, - std::vector start_ready_ops) override { - do_in_bta_thread(FROM_HERE, Bind(&AscsClient::StartReady, - Unretained(AscsClient::Get()), - client_id, address, start_ready_ops)); - } - - void StopReady(uint16_t client_id, const RawAddress& address, - std::vector stop_ready_ops) override { - do_in_bta_thread(FROM_HERE, Bind(&AscsClient::StopReady, - Unretained(AscsClient::Get()), - client_id, address, stop_ready_ops)); - } - - void Release(uint16_t client_id, const RawAddress& address, - std::vector release_ops) override { - do_in_bta_thread(FROM_HERE, Bind(&AscsClient::Release, - Unretained(AscsClient::Get()), - client_id, address, release_ops)); - } - - void UpdateStream(uint16_t client_id, const RawAddress& address, - std::vector metadata_ops) override { - do_in_bta_thread(FROM_HERE, Bind(&AscsClient::UpdateStream, - Unretained(AscsClient::Get()), - client_id, address, metadata_ops)); - } - - void Cleanup(uint16_t client_id) override { - DVLOG(2) << __func__; - do_in_bta_thread(FROM_HERE, Bind(&AscsClient::CleanUp, client_id)); - } - - private: - AscsClientCallbacks* callbacks; -}; - -} // namespace - -AscsClientInterface* btif_ascs_client_get_interface() { - if (!AscsClientInstance) - AscsClientInstance.reset(new AscsClientInterfaceImpl()); - - return AscsClientInstance.get(); -} diff --git a/le_audio/system/bt/btif/src/btif_bap_broadcast.cc b/le_audio/system/bt/btif/src/btif_bap_broadcast.cc deleted file mode 100644 index 0bd393ca1e34c2a7f961028f6f35fd909680e119..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/src/btif_bap_broadcast.cc +++ /dev/null @@ -1,1822 +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. - * - ******************************************************************************/ - -#define LOG_TAG "btif_bap_broadcast" - -#include "btif_bap_broadcast.h" - -#include -#include -#include -#include -#include -#include - -#include "bt_common.h" -#include "bt_utils.h" -#include "btif_storage.h" -#include "btif_a2dp.h" -#include "btif_hf.h" -#include "btif_a2dp_control.h" -#include "btif_util.h" -#include "btu.h" -#include "osi/include/allocator.h" -#include "osi/include/osi.h" -#include "osi/include/properties.h" -#include "btif/include/btif_a2dp_source.h" -#include "device/include/interop.h" -#include "device/include/controller.h" -#include "btif_bat.h" -#include "btif_av.h" -#include "hcimsgs.h" -#include "btif_config.h" -#include "audio_a2dp_hw/include/audio_a2dp_hw.h" -#include -#include -#include -#include "btm_ble_api.h" -#include "btm_ble_api_types.h" -#include "ble_advertiser.h" -#if (OFF_TARGET_TEST_ENABLED == FALSE) -#include "audio_hal_interface/a2dp_encoding.h" -#endif -#include "controller.h" -#if (OFF_TARGET_TEST_ENABLED == TRUE) -#include "log/log.h" -#include "service/a2dp_hal_sim/audio_a2dp_hal_stub.h" -#endif -#include "state_machine.h" - -#define BIG_COMPILE 1 - -#define BTIF_BAP_BA_NUM_CB 1 -#define kDefaultMaxBroadcastSupported 1 -#define BTIF_BAP_BA_NUM_BMS 1 - -#define INPUT_DATAPATH 0x01 -#define OUTPUT_DATAPATH 0x02 -#define BROADCAST_SPLIT_STEREO 2 -#define BROADCAST_MONO_JOINT 1 -#define BROADCAST_MODE_HR 0x1000 -#define BROADCAST_MODE_LL 0x2000 -/***************************************************************************** - * Local type definitions - *****************************************************************************/ - typedef enum { - BIG_TERMINATED = 0, - BIG_CREATING, - BIG_CREATED, - BIG_RECONFIG, - BIG_TERMINATING, - BIG_DISABLING, - } btif_big_state_t; - -std::vector broadcast_codecs_capabilities; -btav_a2dp_codec_index_t lc3_codec_id = (btav_a2dp_codec_index_t)9; -static const btav_a2dp_codec_config_t broadcast_local_capability = - {lc3_codec_id, BTAV_A2DP_CODEC_PRIORITY_DEFAULT, - (BTAV_A2DP_CODEC_SAMPLE_RATE_48000 | - BTAV_A2DP_CODEC_SAMPLE_RATE_24000 | - BTAV_A2DP_CODEC_SAMPLE_RATE_16000), - BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24, - ((btav_a2dp_codec_channel_mode_t)(BTAV_A2DP_CODEC_CHANNEL_MODE_MONO | - BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO | - BTBAP_CODEC_CHANNEL_MODE_JOINT_STEREO)), 0, 0, 0, 0}; - -static btav_a2dp_codec_config_t default_config; -static btav_a2dp_codec_config_t current_config; -static int mBisMultiplier = 0; -//static bool isSplitEnabled = false; -static bool notify_key_generated = false; -Octet16 encryption_key; -std::vector mBroadcastID(3,0); -struct keyCalculator { - Octet16 rand; -}; -uint8_t enc_keylength = 16; -char local_param[3]; -RawAddress mBapBADevice = RawAddress({0xFA, 0xCE, 0xFA, 0xCE, 0xFA, 0xCE}); -std::mutex session_wait_; -std::condition_variable session_wait_cv_; -bool mSession_wait; -bool mEncryptionEnabled = true; -bool restart_session = false; -extern int btif_max_av_clients; -extern const btgatt_interface_t* btif_gatt_get_interface(); -extern int btif_av_get_latest_device_idx_to_start(); -extern thread_t* get_worker_thread(); -int total_bises = 0; -typedef enum { - iso_unknown = 0, - setup_iso = 1, - remove_iso = 2, -}tBAP_BA_ISO_CMD; - -typedef struct { - uint32_t sdu_int; - uint16_t max_sdu; - uint16_t max_transport_latency; - uint8_t rtn; - uint8_t phy; - uint8_t packing; - uint8_t framing; -} tBAP_BA_BIG_PARAMS; - -tBAP_BA_BIG_PARAMS mBigParams = {10000, 100, 10, 2, 2/*LE 2M*/, 1/*Interleaved*/, 0/*unframed*/}; -#define PATH_ID 1 -tBAP_BA_ISO_CMD pending_cmd = iso_unknown; -int current_handle = -1; -int current_iso_index = 0; - -int config_req_handle = -1; -/** - * Local functions - */ -static void btif_bap_ba_generate_enc_key_local(int length); -static void btif_bap_ba_create_big(int adv_id); -static void btif_bap_ba_terminate_big(int adv_id, int big_handle); -static bool btif_bap_ba_setup_iso_datapath(int big_handle); -static bool btif_bap_ba_remove_iso_datapath(int big_handle); -static void btif_bap_ba_process_iso_setup(uint8_t status, uint16_t bis_handle); -static void btif_bap_ba_update_big_params(); -static void btif_bap_ba_handle_event(uint32_t event, char* p_param); -static void init_local_capabilities(); -static void btif_report_broadcast_state(int adv_id, - btbap_broadcast_state_t state); -static void btif_report_broadcast_audio_state(int adv_id, - btbap_broadcast_audio_state_t state); -static void btif_report_audio_config(int adv_id, - btav_a2dp_codec_config_t codec_config); -static void btif_report_setup_big(int setup, int adv_id, int big_handle, int num_bises); -static void btif_report_broadcast_id(); -static void btif_bap_process_request(tA2DP_CTRL_CMD cmd); -static void btif_broadcast_process_hidl_event(tA2DP_CTRL_CMD cmd); -static uint16_t btif_bap_get_transport_latency(); -static void btif_bap_ba_copy_broadcast_id(); -static void btif_bap_ba_generate_broadcast_id(); -static void btif_bap_ba_signal_session_ready() { - std::unique_lock guard(session_wait_); - if(!mSession_wait) { - mSession_wait = true; - session_wait_cv_.notify_all(); - } else { - BTIF_TRACE_WARNING("%s: already signalled ",__func__); - } -} - -const char* dump_bap_ba_sm_event_name(btif_bap_broadcast_sm_event_t event) { - switch ((int)event) { - CASE_RETURN_STR(BTIF_BAP_BROADCAST_ENABLE_EVT) - CASE_RETURN_STR(BTIF_BAP_BROADCAST_DISABLE_EVT) - CASE_RETURN_STR(BTIF_BAP_BROADCAST_START_STREAM_REQ_EVT) - CASE_RETURN_STR(BTIF_BAP_BROADCAST_STOP_STREAM_REQ_EVT) - CASE_RETURN_STR(BTIF_BAP_BROADCAST_SUSPEND_STREAM_REQ_EVT) - CASE_RETURN_STR(BTIF_BAP_BROADCAST_SOURCE_CONFIG_REQ_EVT) - CASE_RETURN_STR(BTIF_BAP_BROADCAST_CLEANUP_REQ_EVT) - CASE_RETURN_STR(BTIF_BAP_BROADCAST_SET_ACTIVE_REQ_EVT) - CASE_RETURN_STR(BTIF_BAP_BROADCAST_REMOVE_ACTIVE_REQ_EVT) - CASE_RETURN_STR(BTIF_BAP_BROADCAST_SETUP_ISO_DATAPATH_EVT) - CASE_RETURN_STR(BTIF_BAP_BROADCAST_REMOVE_ISO_DATAPATH_EVT) - CASE_RETURN_STR(BTIF_BAP_BROADCAST_GENERATE_ENC_KEY_EVT) - CASE_RETURN_STR(BTIF_BAP_BROADCAST_BISES_SETUP_EVT) - CASE_RETURN_STR(BTIF_BAP_BROADCAST_BISES_REMOVE_EVT) - CASE_RETURN_STR(BTIF_BAP_BROADCAST_BIG_SETUP_EVT) - CASE_RETURN_STR(BTIF_BAP_BROADCAST_BIG_REMOVED_EVT) - CASE_RETURN_STR(BTIF_BAP_BROADCAST_PROCESS_HIDL_REQ_EVT) - CASE_RETURN_STR(BTIF_BAP_BROADCAST_SETUP_NEXT_BIS_EVENT) - CASE_RETURN_STR(BTIF_SM_ENTER_EVT) - CASE_RETURN_STR(BTIF_SM_EXIT_EVT) - default: - return "UNKNOWN_EVENT"; - } -} - -void btif_bap_broadcast_update_source_codec(void *p_data) { - btav_a2dp_codec_config_t * codec_req = (btav_a2dp_codec_config_t*)p_data; - if (codec_req->sample_rate != current_config.sample_rate || - codec_req->channel_mode != current_config.channel_mode || - codec_req->codec_specific_1 != current_config.codec_specific_1 || - codec_req->codec_specific_2 != current_config.codec_specific_2) { - restart_session = true; - } - - if (codec_req->codec_specific_4 > 0) { - if (current_config.codec_specific_4 == BROADCAST_MODE_HR) { - mBigParams.max_transport_latency = 60; - } else if (codec_req->codec_specific_4 == BROADCAST_MODE_LL) { - mBigParams.max_transport_latency = 20; - } - } - memcpy(¤t_config, codec_req, sizeof(btav_a2dp_codec_config_t)); - BTIF_TRACE_DEBUG("[BapBroadcast]%s:sample rate: %d",__func__, current_config.sample_rate); - BTIF_TRACE_DEBUG("[BapBroadcast]%s:channel mode: %d",__func__, current_config.channel_mode); - BTIF_TRACE_DEBUG("[BapBroadcast]%s:cs1: %d",__func__, current_config.codec_specific_1); - btif_bap_ba_update_big_params(); -} - -void reverseCode(uint8_t *array) { - uint8_t *p_array = array; - for (int i = 0; i < 8; i++) { - uint8_t temp = p_array[i]; - p_array[i] = p_array[15-i]; - p_array[15-i] = temp; - } -} - -bool isUnencrypted(uint8_t *array) { - uint8_t *p_array = array; - for (int i = 0; i < 16; i++) { - if (p_array[i] != 0x00) { - return false; - } - } - BTIF_TRACE_DEBUG("[BapBroadcast]: isUnencrypted is true"); - return true; -} -class BtifBapBroadcaster; - -class BtifBapBroadcastStateMachine : public bluetooth::common::StateMachine{ - public: - enum { - kStateIdle, // Broadcast idle - kStateConfigured, // Broadcast configured - kStateStreaming, // Broadcast streaming - }; - - class StateIdle : public State { - public: - StateIdle(BtifBapBroadcastStateMachine& sm) - : State(sm, kStateIdle), bms_(sm.Bms()) {} - void OnEnter() override; - void OnExit() override; - bool ProcessEvent(uint32_t event, void* p_data) override; - - private: - BtifBapBroadcaster& bms_; - }; - - class StateConfigured : public State { - public: - StateConfigured(BtifBapBroadcastStateMachine& sm) - : State(sm, kStateConfigured), bms_(sm.Bms()) {} - void OnEnter() override; - void OnExit() override; - bool ProcessEvent(uint32_t event, void* p_data) override; - - private: - BtifBapBroadcaster& bms_; - }; - - class StateStreaming : public State { - public: - StateStreaming(BtifBapBroadcastStateMachine& sm) - : State(sm, kStateStreaming), bms_(sm.Bms()) {} - void OnEnter() override; - void OnExit() override; - bool ProcessEvent(uint32_t event, void* p_data) override; - - private: - BtifBapBroadcaster& bms_; - }; - - BtifBapBroadcastStateMachine(BtifBapBroadcaster& bms) : bms_(bms) { - state_idle_ = new StateIdle(*this); - state_configured_ = new StateConfigured(*this); - state_streaming_ = new StateStreaming(*this); - - AddState(state_idle_); - AddState(state_configured_); - AddState(state_streaming_); - SetInitialState(state_idle_); - } - BtifBapBroadcaster& Bms() { return bms_; } - private: - BtifBapBroadcaster& bms_; - StateIdle* state_idle_; - StateConfigured* state_configured_; - StateStreaming* state_streaming_; -}; - -class BtifBapBroadcaster{ - public: - enum { - kFlagBIGPending = 0x1, - kFlagISOPending = 0x2, - kFlagISOError = 0x4, - KFlagISOSetup = 0x8, - }; - - BtifBapBroadcaster(int adv_handle, int big_handle) - :adv_handle_(adv_handle), - big_handle_(big_handle), - state_machine_(*this), - flags_(0), - big_state_(BIG_TERMINATED){} - - ~BtifBapBroadcaster(); - - bt_status_t Init(); - void Cleanup(); - - bool CanBeDeleted() {return ( - (state_machine_.StateId() == BtifBapBroadcastStateMachine::kStateIdle) && - (state_machine_.PreviousStateId() != BtifBapBroadcastStateMachine::kStateInvalid)); }; - - int AdvHandle() const { return adv_handle_; } - int BIGHandle() const { return big_handle_; } - void SetBIGHandle(int handle) { big_handle_ = handle; } - void SetAdvHandle(int handle) { adv_handle_ = handle; } - BtifBapBroadcastStateMachine& StateMachine() { return state_machine_; } - const BtifBapBroadcastStateMachine& StateMachine() const { return state_machine_; } - bool CheckFlags(uint8_t bitflags_mask) const { - return ((flags_ & bitflags_mask) != 0); - } - - void ClearFlag(uint8_t bitflags_mask) { flags_ &= ~bitflags_mask;} - - void ClearAllFlags() { flags_ = 0; } - /** - * Set only the flags as specified by the bitflags mask. - * - * @param bitflags_mask the bitflags to set - */ - void SetFlags(uint8_t bitflags_mask) { flags_ |= bitflags_mask; } - - void SetNumBises(uint8_t num_bises) {num_bises_ = num_bises; } - - uint8_t NumBises() const { return num_bises_; } - - void SetBIGState(btif_big_state_t state) { big_state_ = state; } - - btif_big_state_t BIGState() const { return big_state_; } - - /*void SetMandatoryCodecPreferred(bool preferred) { - mandatory_codec_preferred_ = preferred; - } - bool IsMandatoryCodecPreferred() const { return mandatory_codec_preferred_; }*/ - - std::vector GetBISHandles() const { return bis_handle_list_;} - void SetBISHandles(std::vector handle_list) { bis_handle_list_ = handle_list; } - - private: - int adv_handle_; - int big_handle_; // SEP type of peer device - uint8_t num_bises_; - BtifBapBroadcastStateMachine state_machine_; - uint8_t flags_; - btif_big_state_t big_state_; - //bool mandatory_codec_preferred_ = false; - std::vector bis_handle_list_; -}; -//BtifBapBroadcaster::BtifBapBroadcaster(int adv_handle, int big_handle) -// :adv_handle_(adv_handle), big_handle_(big_handle){} - -class BtifBapBroadcastSource{ - public: - // The PeerId is used as AppId for BTA_AvRegister() purpose - static constexpr uint8_t kPeerIdMin = 0; - static constexpr uint8_t kPeerIdMax = BTIF_BAP_BA_NUM_BMS; - public: - enum { - kFlagIdle = 0x1, - kFlagConfigured = 0x2, - kFlagStreaming = 0x4, - KFlagDisabling = 0x8, - }; - BtifBapBroadcastSource() - : callbacks_(nullptr), - enabled_(false), - offload_enabled_(false), - max_broadcast_(kDefaultMaxBroadcastSupported) {} - ~BtifBapBroadcastSource(); - - bt_status_t Init( - btbap_broadcast_callbacks_t* callbacks, int max_broadcast, - btav_a2dp_codec_config_t codec_config,int mode); - - bt_status_t EnableBroadcast(btav_a2dp_codec_config_t codec_config); - bt_status_t DisableBroadcast(int adv_handle); - void Cleanup(); - void CleanupIdleBms(); - btbap_broadcast_callbacks_t* Callbacks() { return callbacks_; } - void SetEnabled(bool state) { enabled_ = state; } - bool Enabled() const { return enabled_; } - bool BapBroadcastOffloadEnabled() const { return offload_enabled_; } - - BtifBapBroadcaster* FindBmsFromAdvHandle(uint8_t adv_handle); -// BtifBapBroadcaster* FindEmptyBms(); - BtifBapBroadcaster* FindBmsFromBIGHandle(uint8_t big_handle); - BtifBapBroadcaster* FindStreamingBms(); - BtifBapBroadcaster* FindConfiguredBms(); - BtifBapBroadcaster* CreateBMS(int adv_handle); - //void SetDefaultConfig(btav_a2dp_codec_config_t config) { default_config_ = config; } - btav_a2dp_codec_config_t GetDefaultConfig () const { return default_config_; } - //void SetCurrentConfig (btav_a2dp_codec_config_t config) { current_config_ = config; } - btav_a2dp_codec_config_t GetCurrentConfig() const { return current_config_; } - bt_status_t SetEncryption(int length); - bt_status_t SetBroadcastActive(bool setup, uint8_t adv_id); - bool BroadcastActive() const { return ((broadcast_state_ == kFlagConfigured) - ||(broadcast_state_ == kFlagStreaming)); } - void SetBroadcastState(uint8_t flag) { broadcast_state_ = flag; } - uint8_t GetBroadcastState() { return broadcast_state_; } - bt_status_t SetUserConfig(uint8_t adv_hdl, btav_a2dp_codec_config_t codec_config); - - const std::map& Bms() const { return bms_; } - - private: - void CleanupAllBms(); - - btbap_broadcast_callbacks_t* callbacks_; - bool enabled_; - bool offload_enabled_; - int max_broadcast_; - std::map bms_; - btav_a2dp_codec_config_t default_config_; - btav_a2dp_codec_config_t current_config_; - uint8_t broadcast_state_; -}; - -static BtifBapBroadcastSource btif_bap_bms; - -bt_status_t BtifBapBroadcaster::Init() { - state_machine_.Start(); - return BT_STATUS_SUCCESS; -} - -void BtifBapBroadcaster::Cleanup() { - state_machine_.Quit(); -} - -void BtifBapBroadcastStateMachine::StateIdle::OnEnter() { - BTIF_TRACE_IMP("%s", __PRETTY_FUNCTION__); - - bms_.ClearAllFlags(); - bms_.SetAdvHandle(-1); - bms_.SetBIGHandle(-1); - bms_.SetBIGState(BIG_TERMINATED); - btif_bap_bms.SetBroadcastState(BtifBapBroadcastSource::kFlagIdle); - btif_bap_bms.SetEnabled(false); - btif_bap_bms.CleanupIdleBms(); -} - -void BtifBapBroadcastStateMachine::StateIdle::OnExit() { - BTIF_TRACE_IMP("%s", __PRETTY_FUNCTION__); -} - -bool BtifBapBroadcastStateMachine::StateIdle::ProcessEvent(uint32_t event, void* p_data) { - BTIF_TRACE_IMP("[BapBroadcast]:%s: event = %s",__func__, - dump_bap_ba_sm_event_name((btif_bap_broadcast_sm_event_t)event)); - switch (event) { - case BTIF_BAP_BROADCAST_SET_ACTIVE_REQ_EVT: - bms_.StateMachine().TransitionTo(BtifBapBroadcastStateMachine::kStateConfigured); - break; - case BTIF_BAP_BROADCAST_SOURCE_CONFIG_REQ_EVT: - //copy config - break; - default: - BTIF_TRACE_WARNING("%s: unhandled event=%s", __func__, - dump_bap_ba_sm_event_name((btif_bap_broadcast_sm_event_t)event)); - return false; - } - return true; -} - -void BtifBapBroadcastStateMachine::StateConfigured::OnEnter() { - BTIF_TRACE_IMP("%s", __PRETTY_FUNCTION__); - - // Inform the application that we are entering connecting state - btif_bap_bms.SetBroadcastState(BtifBapBroadcastSource::kFlagConfigured); - btif_bap_bms.SetEnabled(true); - if (bms_.BIGState() == BIG_TERMINATED) { -#if AHIM_ENABLED - btif_ahim_init_hal(get_worker_thread(), BROADCAST); - btif_ahim_start_session(); -#else - btif_a2dp_source_restart_session(RawAddress::kEmpty, mBapBADevice); -#endif - btif_bap_ba_signal_session_ready(); - btif_bap_ba_update_big_params(); - } else if (bms_.BIGState() == BIG_DISABLING) { - ProcessEvent(BTIF_BAP_BROADCAST_DISABLE_EVT, nullptr); - return; - } - bms_.SetBIGState(BIG_TERMINATED); - bms_.ClearAllFlags(); - btif_report_broadcast_state(bms_.AdvHandle(), BTBAP_BROADCAST_STATE_CONFIGURED); -} - -void BtifBapBroadcastStateMachine::StateConfigured::OnExit() { - BTIF_TRACE_IMP("%s", __PRETTY_FUNCTION__); -} - -bool BtifBapBroadcastStateMachine::StateConfigured::ProcessEvent(uint32_t event, - void* p_data) { - BTIF_TRACE_IMP("[BapBroadcast]:%s: event = %s",__func__, - dump_bap_ba_sm_event_name((btif_bap_broadcast_sm_event_t)event)); - switch (event) { - - case BTIF_BAP_BROADCAST_DISABLE_EVT: - BTIF_TRACE_DEBUG("[BapBroadcast]:BTIF_BAP_BROADCAST_DISABLE_EVT, moving to idle"); - if (bms_.CheckFlags(BtifBapBroadcaster::kFlagBIGPending) || - bms_.CheckFlags(BtifBapBroadcaster::kFlagISOPending)) { -#if AHIM_ENABLED - btif_ahim_ack_stream_started(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS, BROADCAST); - btif_ahim_reset_pending_command(BROADCAST); -#else - bluetooth::audio::a2dp::ack_stream_started(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS); - bluetooth::audio::a2dp::reset_pending_command(); -#endif - } - bms_.SetBIGState(BIG_DISABLING); - bms_.ClearFlag(BtifBapBroadcaster::kFlagISOPending); - btif_report_broadcast_state(bms_.AdvHandle(), BTBAP_BROADCAST_STATE_IDLE); - bms_.StateMachine().TransitionTo(BtifBapBroadcastStateMachine::kStateIdle); - break; - case BTIF_BAP_BROADCAST_SET_ACTIVE_REQ_EVT: - BTIF_TRACE_DEBUG("Not handled in configured state"); - break; - case BTIF_BAP_BROADCAST_START_STREAM_REQ_EVT: - if (bms_.CheckFlags(BtifBapBroadcaster::kFlagBIGPending) || - bms_.CheckFlags(BtifBapBroadcaster::kFlagISOPending)) { - BTIF_TRACE_DEBUG("[BapBroadcast]%s: BIG/ISO setup pending, dup req",__func__); -#if AHIM_ENABLED - btif_ahim_ack_stream_started(A2DP_CTRL_ACK_PENDING, BROADCAST); -#else - btif_ahim_ack_stream_started(A2DP_CTRL_ACK_PENDING, BROADCAST); -#endif - break; - } - bms_.SetFlags(BtifBapBroadcaster::kFlagBIGPending); - bms_.SetNumBises(btif_bap_broadcast_get_ch_count()); - bms_.SetBIGState(BIG_CREATING); - btif_bap_ba_create_big(bms_.AdvHandle()); - break; - case BTIF_BAP_BROADCAST_SETUP_ISO_DATAPATH_EVT: - { - if (bms_.CheckFlags(BtifBapBroadcaster::kFlagBIGPending)) - bms_.ClearFlag(BtifBapBroadcaster::kFlagBIGPending); - bms_.SetFlags(BtifBapBroadcaster::kFlagISOPending); - total_bises = bms_.NumBises(); - current_iso_index = 0; - current_handle = bms_.BIGHandle(); - btif_bap_ba_setup_iso_datapath(current_handle); - } - break; - case BTIF_BAP_BROADCAST_REMOVE_ISO_DATAPATH_EVT: - total_bises = bms_.NumBises(); - current_iso_index = 0; - current_handle = bms_.BIGHandle(); - btif_bap_ba_remove_iso_datapath(current_handle); - break; - case BTIF_BAP_BROADCAST_BISES_SETUP_EVT: - { - char *p_p = (char *) p_data; - p_p++; - uint8_t status = *p_p; - if (status != BT_STATUS_SUCCESS && - bms_.CheckFlags(BtifBapBroadcaster::kFlagISOPending)) { - BTIF_TRACE_ERROR("[BapBroadcast]%s: setup iso failed",__func__); - bms_.ClearAllFlags(); - bms_.SetFlags(BtifBapBroadcaster::kFlagISOError); -#if AHIM_ENABLED - btif_ahim_ack_stream_started(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS, BROADCAST); - btif_ahim_reset_pending_command(BROADCAST); -#else - bluetooth::audio::a2dp::ack_stream_started(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS); - bluetooth::audio::a2dp::reset_pending_command(); -#endif - - btif_bap_ba_terminate_big(bms_.AdvHandle(), bms_.BIGHandle()); - break; - } - bms_.ClearFlag(BtifBapBroadcaster::kFlagISOPending); - bms_.SetFlags(BtifBapBroadcaster::KFlagISOSetup); -#if AHIM_ENABLED - btif_ahim_ack_stream_started(A2DP_CTRL_ACK_SUCCESS, BROADCAST); - btif_ahim_reset_pending_command(BROADCAST); -#else - bluetooth::audio::a2dp::ack_stream_started(A2DP_CTRL_ACK_SUCCESS); - bluetooth::audio::a2dp::reset_pending_command(); -#endif - btif_report_setup_big(1, bms_.AdvHandle(), bms_.BIGHandle(), bms_.NumBises()); - btif_report_broadcast_state(bms_.AdvHandle(), BTBAP_BROADCAST_STATE_STREAMING); - bms_.StateMachine().TransitionTo(BtifBapBroadcastStateMachine::kStateStreaming); - } - break; - case BTIF_BAP_BROADCAST_BISES_REMOVE_EVT: -#if AHIM_ENABLED - btif_ahim_ack_stream_started(A2DP_CTRL_ACK_SUCCESS, BROADCAST); - btif_ahim_reset_pending_command(BROADCAST); -#else - bluetooth::audio::a2dp::ack_stream_started(A2DP_CTRL_ACK_SUCCESS); - bluetooth::audio::a2dp::reset_pending_command(); -#endif - break; - case BTIF_BAP_BROADCAST_BIG_SETUP_EVT: - break; - case BTIF_BAP_BROADCAST_BIG_REMOVED_EVT: - btif_report_setup_big(0, bms_.AdvHandle(), -1, 0); - if (bms_.CheckFlags(BtifBapBroadcaster::kFlagISOError)) { - bms_.StateMachine().TransitionTo(BtifBapBroadcastStateMachine::kStateIdle); - btif_report_broadcast_state(bms_.AdvHandle(),BTBAP_BROADCAST_STATE_IDLE); - } - break; - case BTIF_BAP_BROADCAST_SOURCE_CONFIG_REQ_EVT: - btif_bap_broadcast_update_source_codec(p_data); - if (restart_session) { -#if AHIM_ENABLED - btif_ahim_end_session(); - btif_ahim_init_hal(get_worker_thread(), BROADCAST); - btif_ahim_start_session(); -#else - btif_a2dp_source_restart_session(RawAddress::kEmpty, mBapBADevice); -#endif - btif_report_audio_config(bms_.AdvHandle(), current_config); - } - break; - case BTIF_BAP_BROADCAST_SUSPEND_STREAM_REQ_EVT: -#if AHIM_ENABLED - btif_ahim_ack_stream_suspended(A2DP_CTRL_ACK_SUCCESS, BROADCAST); - btif_ahim_reset_pending_command(BROADCAST); -#else - bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_SUCCESS); - bluetooth::audio::a2dp::reset_pending_command(); -#endif - BTIF_TRACE_WARNING("%s: SUSPEND_STEAM_REQ unhandled in Configured state", __func__); - break; - default: - BTIF_TRACE_WARNING("%s: unhandled event=%s", __func__, - dump_bap_ba_sm_event_name((btif_bap_broadcast_sm_event_t)event)); - return false; - } - return true; - -} - -void BtifBapBroadcastStateMachine::StateStreaming::OnEnter() { - BTIF_TRACE_IMP("%s", __PRETTY_FUNCTION__); - btif_bap_bms.SetBroadcastState(BtifBapBroadcastSource::kFlagStreaming); - btif_report_broadcast_audio_state(bms_.AdvHandle(), BTBAP_BROADCAST__AUDIO_STATE_STARTED); -} - -void BtifBapBroadcastStateMachine::StateStreaming::OnExit() { - BTIF_TRACE_IMP("%s", __PRETTY_FUNCTION__); -} - -bool BtifBapBroadcastStateMachine::StateStreaming::ProcessEvent(uint32_t event, - void* p_data) { - BTIF_TRACE_IMP("[BapBroadcast]:%s: event = %s",__func__, - dump_bap_ba_sm_event_name((btif_bap_broadcast_sm_event_t)event)); - switch (event) { - case BTIF_BAP_BROADCAST_DISABLE_EVT: - if (bms_.BIGState() == BIG_CREATED) { - bms_.SetBIGState(BIG_DISABLING); - btif_bap_bms.SetBroadcastState(BtifBapBroadcastSource::KFlagDisabling); - if (bms_.CheckFlags(BtifBapBroadcaster::KFlagISOSetup)) { - btif_bap_ba_terminate_big(bms_.AdvHandle(), bms_.BIGHandle()); - } - } else { - bms_.SetBIGState(BIG_DISABLING); - BTIF_TRACE_DEBUG("[BapBroadcast]: BIG Terminate under process"); - } - break; - case BTIF_BAP_BROADCAST_SUSPEND_STREAM_REQ_EVT: - if (bms_.BIGState() != BIG_CREATED) { - BTIF_TRACE_WARNING("[BapBroadcast]:%s: BIG is getting terminated already",__func__); -#if AHIM_ENABLED - btif_ahim_ack_stream_suspended(A2DP_CTRL_ACK_SUCCESS, BROADCAST); - btif_ahim_reset_pending_command(BROADCAST); -#else - bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_SUCCESS); - bluetooth::audio::a2dp::reset_pending_command(); -#endif - break; - } - bms_.SetFlags(BtifBapBroadcaster::kFlagISOPending); - total_bises = bms_.NumBises(); - current_iso_index = 0; - current_handle = bms_.BIGHandle(); - btif_bap_ba_remove_iso_datapath(current_handle); - - break; - case BTIF_BAP_BROADCAST_SETUP_ISO_DATAPATH_EVT: - { - char *p_p = (char *)p_data; - if (*p_p) { - BTIF_TRACE_WARNING("[BapBroadcast]:%s: We shouldn't be in streaming state if ISO datapath is not setup yet",__func__); - } else { - if (bms_.CheckFlags(BtifBapBroadcaster::KFlagISOSetup)) { - BTIF_TRACE_WARNING("[BapBroadcast] We shouldn't be here, ISO Datapath is removed first before BIG"); - btif_bap_ba_remove_iso_datapath(bms_.BIGHandle()); - } else { - BTIF_TRACE_WARNING("[BapBroadcast]:%s:IsoDatapah is already removed",__func__); - bms_.StateMachine().TransitionTo(BtifBapBroadcastStateMachine::kStateConfigured); - } - } - } - break; - case BTIF_BAP_BROADCAST_REMOVE_ISO_DATAPATH_EVT: - btif_bap_ba_terminate_big(bms_.AdvHandle(), bms_.BIGHandle()); - break; - case BTIF_BAP_BROADCAST_BISES_REMOVE_EVT: - bms_.ClearFlag(BtifBapBroadcaster::kFlagISOPending); - if (bms_.BIGState() == BIG_CREATED) - bms_.SetBIGState(BIG_TERMINATING); - btif_bap_ba_terminate_big(bms_.AdvHandle(), bms_.BIGHandle()); - break; - case BTIF_BAP_BROADCAST_BIG_REMOVED_EVT: - if (bms_.BIGState() == BIG_DISABLING) { - btif_report_broadcast_state(bms_.AdvHandle(), BTBAP_BROADCAST_STATE_IDLE); - bms_.StateMachine().TransitionTo(BtifBapBroadcastStateMachine::kStateIdle); - } else if (bms_.BIGState() == BIG_TERMINATING) { - bms_.StateMachine().TransitionTo(BtifBapBroadcastStateMachine::kStateConfigured); - } else if (bms_.BIGState() == BIG_RECONFIG) { -#if AHIM_ENABLED - btif_ahim_end_session(); - btif_ahim_init_hal(get_worker_thread(), BROADCAST); - btif_ahim_start_session(); -#else - btif_a2dp_source_restart_session(RawAddress::kEmpty, mBapBADevice); -#endif - btif_report_audio_config(bms_.AdvHandle(), current_config); - bms_.StateMachine().TransitionTo(BtifBapBroadcastStateMachine::kStateConfigured); - break; - } -#if AHIM_ENABLED - btif_ahim_ack_stream_suspended(A2DP_CTRL_ACK_SUCCESS, BROADCAST); - btif_ahim_reset_pending_command(BROADCAST); -#else - bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_SUCCESS); - bluetooth::audio::a2dp::reset_pending_command(); -#endif - - break; - case BTIF_BAP_BROADCAST_SOURCE_CONFIG_REQ_EVT: - btif_bap_broadcast_update_source_codec(p_data); - if (restart_session) { - bms_.SetBIGState(BIG_RECONFIG); - btif_bap_ba_terminate_big(bms_.AdvHandle(), bms_.BIGHandle()); - } - break; - default: - BTIF_TRACE_WARNING("%s: unhandled event=%s", __func__, - dump_bap_ba_sm_event_name((btif_bap_broadcast_sm_event_t)event)); - return false; - } - return true; -} - -static btif_ahim_client_callbacks_t sAhimBroadcastCallbacks = { - 2, // mode - btif_broadcast_process_hidl_event, - btif_bap_broadcast_get_sample_rate, - btif_bap_broadcast_get_ch_mode, - btif_bap_broadcast_get_bitrate, - btif_bap_broadcast_get_mtu, - btif_bap_broadcast_get_framelength, - btif_bap_broadcast_get_ch_count, - btif_bap_broadcast_is_simulcast_enabled, - nullptr, - nullptr, - nullptr -}; - -bt_status_t BtifBapBroadcastSource::Init(btbap_broadcast_callbacks_t* callbacks, - int max_broadcast, - btav_a2dp_codec_config_t codec_config,int mode) { - BTIF_TRACE_DEBUG("[BapBroadcast]:%s", __func__); - char value[PROPERTY_VALUE_MAX] = {'\0'}; - if (mode == 1) offload_enabled_ = true; - callbacks_ = callbacks; - default_config_ = codec_config; - memset(encryption_key.data(), 0, OCTET16_LEN); - init_local_capabilities(); - osi_property_get("persist.vendor.btstack.partial_simulcast",value,"false"); - if (strcmp(value, "true") == 0) { - BTIF_TRACE_IMP("[BapBroadcast]%s:Partial simulcast enabled",__func__); - mBisMultiplier = 2; - } else { - mBisMultiplier = 1; - } - osi_property_get("persist.vendor.btstack.transport_latency",value,"0"); - mBigParams.max_transport_latency = atoi(value); - osi_property_get("persist.vendor.btstack.bis_rtn",value,"2"); - mBigParams.rtn = atoi(value); - BTIF_TRACE_IMP("%s: transport_latency: %d, rtn: %d", - __func__, mBigParams.max_transport_latency, mBigParams.rtn); - BTIF_TRACE_IMP("%s: Fetch broadcast encryption key", __func__); - - size_t length = OCTET16_LEN; - bool ret = btif_config_get_bin("Adapter", "BAP_BA_ENC_KEY", encryption_key.data(), &length); - - if (!ret) { - btif_bap_ba_generate_enc_key_local(OCTET16_LEN); - } else { - reverseCode(encryption_key.data()); - if (isUnencrypted(encryption_key.data())) { - mEncryptionEnabled = false; - } - for (int i = 0; i < OCTET16_LEN; i++) { - BTIF_TRACE_IMP("[bapbroadcast]%s: encryption_key[%d] = %d",__func__,i,encryption_key[i]); - } - } -#if AHIM_ENABLED - reg_cb_with_ahim(BROADCAST, &sAhimBroadcastCallbacks); -#endif - return BT_STATUS_SUCCESS; -} - -bt_status_t BtifBapBroadcastSource::EnableBroadcast(btav_a2dp_codec_config_t codec_config) { - BTIF_TRACE_DEBUG("[BapBroadcast]:%s", __func__); - current_config_ = codec_config; - btif_bap_ba_generate_broadcast_id(); - return BT_STATUS_SUCCESS; -} - -bt_status_t BtifBapBroadcastSource::DisableBroadcast(int adv_handle) { - BTIF_TRACE_DEBUG("[BapBroadcast]:%s", __func__); - local_param[0] = adv_handle; - do_in_bta_thread( - FROM_HERE, base::Bind(&btif_bap_ba_handle_event, - BTIF_BAP_BROADCAST_DISABLE_EVT, local_param)); - return BT_STATUS_SUCCESS; -} - -bt_status_t BtifBapBroadcastSource::SetEncryption(int length) { - BTIF_TRACE_DEBUG("[BapBroadcast]:%s", __func__); - local_param[0] = length; - do_in_bta_thread( - FROM_HERE, base::Bind(&btif_bap_ba_handle_event, - BTIF_BAP_BROADCAST_GENERATE_ENC_KEY_EVT, local_param)); - return BT_STATUS_SUCCESS; -} - -bt_status_t BtifBapBroadcastSource::SetBroadcastActive(bool setup, uint8_t adv_id) { - if (btif_a2dp_source_is_hal_v2_supported()) { - std::unique_lock guard(session_wait_); - mSession_wait = false; - if (setup) { - do_in_bta_thread( - FROM_HERE, base::Bind(&btif_bap_ba_handle_event, - BTIF_BAP_BROADCAST_SET_ACTIVE_REQ_EVT, (char *)&adv_id)); - } else { - do_in_bta_thread( - FROM_HERE, base::Bind(&btif_bap_ba_handle_event, - BTIF_BAP_BROADCAST_REMOVE_ACTIVE_REQ_EVT,(char *)&adv_id)); - } - BTIF_TRACE_EVENT("%s: wating for signal",__func__); - session_wait_cv_.wait_for(guard, std::chrono::milliseconds(1000), - []{return mSession_wait;}); - BTIF_TRACE_EVENT("%s: done with signal",__func__); - return BT_STATUS_SUCCESS; - } - return BT_STATUS_SUCCESS; -} -void BtifBapBroadcastSource::Cleanup() { - BTIF_TRACE_DEBUG("[BapBroadcast]:%s", __func__); - //while(!bms_.empty()) { - for (auto it = bms_.begin();it != bms_.end();){ - BtifBapBroadcaster *bms = it->second; - auto prev_it = it++; - bms->Cleanup(); - bms_.erase(prev_it); - //delete bms; - } -} - -void BtifBapBroadcastSource::CleanupIdleBms() { - BTIF_TRACE_DEBUG("[BapBroadcast]:%s", __func__); - for (auto it = bms_.begin();it != bms_.end();){ - BtifBapBroadcaster *bms = it->second; - auto prev_it = it++; - if (bms->CanBeDeleted()) { - BTIF_TRACE_DEBUG("[BapBroadcast]%s: Cleaning up idle bms", __func__); - bms->Cleanup(); - bms_.erase(prev_it); - //delete bms; - } - //delete bms; - } - BTIF_TRACE_DEBUG("[BapBroadcast]%s:Exit",__func__); -} - -bt_status_t BtifBapBroadcastSource::SetUserConfig(uint8_t adv_handle, - btav_a2dp_codec_config_t codec_config) { - BTIF_TRACE_DEBUG("[BapBroadcast]:%s", __func__); - config_req_handle = (int) adv_handle; - do_in_bta_thread( - FROM_HERE, base::Bind(&btif_bap_ba_handle_event, - BTIF_BAP_BROADCAST_SOURCE_CONFIG_REQ_EVT, (char *)&codec_config)); - return BT_STATUS_SUCCESS; -} -BtifBapBroadcaster * BtifBapBroadcastSource::CreateBMS(int adv_handle) { - BtifBapBroadcaster *bms = new BtifBapBroadcaster(adv_handle, -1); -// bms_.insert(bms); - bms_.insert(std::make_pair(adv_handle, bms)); - bms->Init(); - return bms; -} - -BtifBapBroadcaster * BtifBapBroadcastSource::FindBmsFromAdvHandle(uint8_t adv_handle) { - BTIF_TRACE_DEBUG("[BapBroadcast]:%s: adv_handle = %d", __func__, adv_handle); - for(auto it : bms_) { - BtifBapBroadcaster *bms = it.second; - if (bms->AdvHandle() == adv_handle) - return bms; - } - return nullptr; -} - -BtifBapBroadcaster * BtifBapBroadcastSource::FindBmsFromBIGHandle(uint8_t big_handle) { - for(auto it : bms_) { - BtifBapBroadcaster *bms = it.second; - if (bms->BIGHandle() == big_handle) - return bms; - } - return nullptr; -} - -BtifBapBroadcaster * BtifBapBroadcastSource::FindStreamingBms() { - for(auto it : bms_) { - BtifBapBroadcaster *bms = it.second; - if (bms->StateMachine().StateId() == BtifBapBroadcastStateMachine::kStateStreaming) - return bms; - } - return nullptr; -} - -BtifBapBroadcaster * BtifBapBroadcastSource::FindConfiguredBms() { - for(auto it : bms_) { - BtifBapBroadcaster *bms = it.second; - if (bms->StateMachine().StateId() == BtifBapBroadcastStateMachine::kStateConfigured) - return bms; - } - return nullptr; -} -BtifBapBroadcastSource::~BtifBapBroadcastSource(){} -/***************************************************************************** - * Local event handlers - *****************************************************************************/ -void print_config(btav_a2dp_codec_config_t config) { - BTIF_TRACE_WARNING("[BapBroadcast]%d: Sampling rate = %d", __func__,config.sample_rate); - BTIF_TRACE_WARNING("[BapBroadcast]%d: channel mode = %d", __func__, config.channel_mode); - BTIF_TRACE_WARNING("[BapBroadcast]%d: codec_specific_1 = %d", __func__, config.codec_specific_1); - BTIF_TRACE_WARNING("[BapBroadcast]%d: codec_specific_2 = %d", __func__, config.codec_specific_2); -} - -static void btif_report_encyption_key() { - do_in_jni_thread(FROM_HERE, - base::Bind(btif_bap_bms.Callbacks()->enc_key_cb, - std::string(reinterpret_cast(encryption_key.data()), OCTET16_LEN))); -} - -static void btif_report_broadcast_state(int adv_id, - btbap_broadcast_state_t state) { - if (btif_bap_bms.Enabled()) { - do_in_jni_thread(FROM_HERE, - base::Bind(btif_bap_bms.Callbacks()->broadcast_state_cb, - adv_id, state)); - } -} - -static void btif_report_broadcast_audio_state(int adv_id, - btbap_broadcast_audio_state_t state) { - if (btif_bap_bms.Enabled()) { - do_in_jni_thread(FROM_HERE, - base::Bind(btif_bap_bms.Callbacks()->audio_state_cb, - adv_id, state)); - } -} - -static void btif_report_audio_config(int adv_id, - btav_a2dp_codec_config_t codec_config) { - if (btif_bap_bms.Enabled()) { - do_in_jni_thread(FROM_HERE, - base::Bind(btif_bap_bms.Callbacks()->audio_config_cb, - adv_id, codec_config, broadcast_codecs_capabilities)); - } -} - -static void btif_report_setup_big(int setup, int adv_id, int big_handle, int num_bises) { - - BtifBapBroadcaster *bms = btif_bap_bms.FindBmsFromAdvHandle(adv_id); - if (bms == nullptr) return; - if (btif_bap_bms.Enabled()) { - do_in_jni_thread(FROM_HERE, - base::Bind(btif_bap_bms.Callbacks()->create_big_cb, setup, - adv_id, big_handle, num_bises, bms->GetBISHandles())); - } - -} - -static void btif_report_broadcast_id() { - do_in_jni_thread(FROM_HERE, - base::Bind(btif_bap_bms.Callbacks()->broadcast_id_cb, mBroadcastID)); -} - -static void btif_bap_ba_handle_event(uint32_t event, char* p_param) { - int big_handle, adv_id; - big_handle = adv_id = 0; - BtifBapBroadcaster *broadcaster; - BTIF_TRACE_DEBUG("[BapBroadcast]:%s: event %s", - __func__, dump_bap_ba_sm_event_name((btif_bap_broadcast_sm_event_t)event)); - switch(event) { - case BTIF_BAP_BROADCAST_DISABLE_EVT: - adv_id = (int)*p_param; - broadcaster = btif_bap_bms.FindBmsFromAdvHandle(adv_id); - if (broadcaster == nullptr) { - BTIF_TRACE_ERROR("[BapBroadcast]:%s:invalid index, Broadcast is already disabled",__func__); - return; - } - break; - case BTIF_BAP_BROADCAST_START_STREAM_REQ_EVT: - broadcaster = btif_bap_bms.FindConfiguredBms(); - if (broadcaster == nullptr) { - BTIF_TRACE_ERROR("[BapBroadcast]:%s:cannot find empty index",__func__); - return; - } - break; - case BTIF_BAP_BROADCAST_STOP_STREAM_REQ_EVT: - case BTIF_BAP_BROADCAST_SUSPEND_STREAM_REQ_EVT: - broadcaster = btif_bap_bms.FindStreamingBms(); - if (broadcaster == nullptr) { - BTIF_TRACE_ERROR("[BapBroadcast]:%s:cannot find empty index",__func__); - return; - } - break; - case BTIF_BAP_BROADCAST_SOURCE_CONFIG_REQ_EVT: - broadcaster = btif_bap_bms.FindBmsFromAdvHandle(config_req_handle); - if (broadcaster == nullptr) { - BTIF_TRACE_ERROR("[BapBroadcast]:%s:cannot find empty index",__func__); - return; - } - break; - case BTIF_BAP_BROADCAST_CLEANUP_REQ_EVT: - broadcaster = btif_bap_bms.FindStreamingBms(); //TODO:add proper check - if (broadcaster == nullptr) { - BTIF_TRACE_ERROR("[BapBroadcast]:%s:cannot find empty index",__func__); - return; - } - break; - case BTIF_BAP_BROADCAST_SET_ACTIVE_REQ_EVT: - { - char *p_p = p_param; - int adv_handle = (int)*p_p; - BTIF_TRACE_ERROR("[BapBroadcast]:%s:adv_handle %d",__func__,adv_handle); - broadcaster = btif_bap_bms.CreateBMS((int)adv_handle); - if (broadcaster == nullptr) { - BTIF_TRACE_ERROR("[BapBroadcast]:%s: cannot find empty index",__func__); - return; - } - broadcaster->SetAdvHandle(adv_handle); - BTIF_TRACE_ERROR("[BapBroadcast]:%s:adv_id = %d, big_handle = %d",__func__, adv_handle); - } - break; - case BTIF_BAP_BROADCAST_REMOVE_ACTIVE_REQ_EVT: - BTIF_TRACE_DEBUG("[BapBroadcast]:%s:End session", __func__); -#if AHIM_ENABLED - btif_ahim_end_session(); -#else - bluetooth::audio::a2dp::end_session(); -#endif - btif_bap_ba_signal_session_ready(); - return; - case BTIF_BAP_BROADCAST_SETUP_ISO_DATAPATH_EVT: - { - char *p_p = p_param; - int adv_handle = (int)*p_p; - BTIF_TRACE_DEBUG("[BapBroadcast]:%s:adv_handle = %d",__func__,adv_handle); - broadcaster = btif_bap_bms.FindBmsFromAdvHandle(adv_handle); - if (broadcaster == nullptr) { - BTIF_TRACE_ERROR("[BapBroadcast]:%s: cannot find empty index",__func__); - return; - } - } - break; - case BTIF_BAP_BROADCAST_REMOVE_ISO_DATAPATH_EVT: - { - char *p_p = p_param; - adv_id = *p_p++; - big_handle = *p_p; - broadcaster = btif_bap_bms.FindBmsFromBIGHandle(big_handle); - if (broadcaster == nullptr) { - BTIF_TRACE_ERROR("[BapBroadcast]:%s: cannot find empty index",__func__); - return; - } - } - break; - case BTIF_BAP_BROADCAST_GENERATE_ENC_KEY_EVT: - enc_keylength = (uint8_t)(*p_param); - notify_key_generated = true; - btif_bap_ba_generate_enc_key_local(enc_keylength); - return; - case BTIF_BAP_BROADCAST_BISES_SETUP_EVT: - case BTIF_BAP_BROADCAST_BISES_REMOVE_EVT: - big_handle = *p_param; - broadcaster = btif_bap_bms.FindBmsFromBIGHandle(big_handle); - if (broadcaster == nullptr) { - BTIF_TRACE_ERROR("[BapBroadcast]:%s: cannot find empty index",__func__); - return; - } - break; - case BTIF_BAP_BROADCAST_BIG_REMOVED_EVT: - adv_id = (int)*p_param; - btif_report_setup_big(0, adv_id,-1, 0); - broadcaster = btif_bap_bms.FindBmsFromAdvHandle(adv_id); - if (broadcaster == nullptr) { - BTIF_TRACE_ERROR("[BapBroadcast]:%s: cannot find empty index",__func__); - return; - } - break; - case BTIF_BAP_BROADCAST_PROCESS_HIDL_REQ_EVT: - btif_bap_process_request((tA2DP_CTRL_CMD ) *p_param); - return; - case BTIF_BAP_BROADCAST_SETUP_NEXT_BIS_EVENT: - { - char *p = p_param; - uint8_t status = *p++; - uint16_t bis_handle = *p++; - bis_handle = (bis_handle | (*p <<8)); - btif_bap_ba_process_iso_setup(status, bis_handle); - return; - } - default: - BTIF_TRACE_ERROR("[BapBroadcast]:%s: invalid event = %d",__func__, event); - return; - } - if (broadcaster == nullptr) { - BTIF_TRACE_ERROR("[BapBroadcast]:%s:Invalid broadcaster",__func__); - } - broadcaster->StateMachine().ProcessEvent(event, (void*)p_param); -} - -static void btif_bap_process_request(tA2DP_CTRL_CMD cmd) { - BTIF_TRACE_DEBUG("[BapBroadcast]:%s",__func__); - tA2DP_CTRL_ACK status = A2DP_CTRL_ACK_FAILURE; - //BtifBapBroadcaster *broadcaster; - uint32_t event = 0; -#if AHIM_ENABLED - btif_ahim_update_pending_command(cmd, BROADCAST); -#else - bluetooth::audio::a2dp::update_pending_command(cmd); -#endif - - switch(cmd) { - case A2DP_CTRL_CMD_START: - if (!bluetooth::headset::btif_hf_is_call_vr_idle()) { - status = A2DP_CTRL_ACK_INCALL_FAILURE; - break; - } - if (btif_bap_bms.FindStreamingBms() != nullptr) { - BTIF_TRACE_DEBUG("%s: Broadcast already streaming, crash recover(?)",__func__); - status = A2DP_CTRL_ACK_SUCCESS; - break; - } - if (btif_bap_bms.FindConfiguredBms() == nullptr) { - BTIF_TRACE_DEBUG("%s: Broadcast is disabled",__func__); - status = A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS; - break; - } - btif_bap_ba_dispatch_sm_event(BTIF_BAP_BROADCAST_START_STREAM_REQ_EVT, NULL, 0); - event = BTIF_BAP_BROADCAST_START_STREAM_REQ_EVT; - //broadcaster = btif_bap_bms.FindConfiguredBms(); - status = A2DP_CTRL_ACK_PENDING; - break; - case A2DP_CTRL_CMD_STOP: - btif_bap_ba_dispatch_sm_event(BTIF_BAP_BROADCAST_STOP_STREAM_REQ_EVT, NULL, 0); - //broadcaster = btif_bap_bms.FindStreamingBms(); - status = A2DP_CTRL_ACK_SUCCESS; - break; - case A2DP_CTRL_CMD_SUSPEND: - if (btif_bap_bms.FindStreamingBms() != nullptr) { - btif_bap_ba_dispatch_sm_event(BTIF_BAP_BROADCAST_SUSPEND_STREAM_REQ_EVT, NULL, 0); - //broadcaster = btif_bap_bms.FindStreamingBms(); - status = A2DP_CTRL_ACK_PENDING; - } else { - status = A2DP_CTRL_ACK_SUCCESS; - } - break; - default: - APPL_TRACE_ERROR("UNSUPPORTED CMD (%d)", cmd); - status = A2DP_CTRL_ACK_FAILURE; - break; - } - // send the response now based on status - switch (cmd) { - case A2DP_CTRL_CMD_START: -#if AHIM_ENABLED - btif_ahim_ack_stream_started(status, BROADCAST); -#else - bluetooth::audio::a2dp::ack_stream_started(status); -#endif - break; - case A2DP_CTRL_CMD_SUSPEND: - case A2DP_CTRL_CMD_STOP: -#if AHIM_ENABLED - btif_ahim_ack_stream_suspended(status, BROADCAST); -#else - bluetooth::audio::a2dp::ack_stream_suspended(status); -#endif - break; - default: - break; - } - if (status != A2DP_CTRL_ACK_PENDING) { -#if AHIM_ENABLED - btif_ahim_reset_pending_command(BROADCAST); -#else - bluetooth::audio::a2dp::reset_pending_command(); -#endif - } -} - -static bool btif_bap_is_broadcaster_valid(uint8_t big_handle) { - BTIF_TRACE_DEBUG("[BapBroadcat]%s: handle = %d",__func__, big_handle); - BtifBapBroadcaster *bms = btif_bap_bms.FindBmsFromBIGHandle(big_handle); - if (bms == nullptr) return false; - if (pending_cmd == setup_iso) { - if (!bms->CheckFlags(BtifBapBroadcaster::kFlagISOPending) || - bms->StateMachine().StateId() != BtifBapBroadcastStateMachine::kStateConfigured) { - BTIF_TRACE_WARNING("[BapBroadcast]:%s Broadcast disabled",__func__); - return false; - } - } else { - if (bms->BIGState() != BIG_CREATED) { - BTIF_TRACE_WARNING("[BapBroadcast]:%s Broadcast disabled",__func__); - return false; - } - } - return true; -} - -static void btif_bap_ba_process_iso_setup(uint8_t status, uint16_t bis_handle) { - BTIF_TRACE_WARNING("[BapBroadcast]:%s",__func__); - if (!btif_bap_is_broadcaster_valid(current_handle)) return; - if (pending_cmd == setup_iso) { - local_param[0] = current_handle; - local_param[1] = status; - if (!btif_bap_ba_setup_iso_datapath(current_handle)) { - BTIF_TRACE_WARNING("[BapBroadcast]:%s: notify bis setup",__func__); - pending_cmd = iso_unknown; - btif_bap_ba_handle_event(BTIF_BAP_BROADCAST_BISES_SETUP_EVT, (char *)local_param); - } - } else if (pending_cmd == remove_iso) { - if (!btif_bap_ba_remove_iso_datapath(current_handle)) { - local_param[0] = current_handle; - local_param[1] = status; - pending_cmd = iso_unknown; - BTIF_TRACE_WARNING("[BapBroadcast]:%s: notify bis removed",__func__); - btif_bap_ba_handle_event(BTIF_BAP_BROADCAST_BISES_REMOVE_EVT, (char *)local_param); - } - } -} -static void btif_bap_ba_isodatapath_setup_cb(uint8_t status, uint16_t bis_handle) { - BTIF_TRACE_WARNING("[BapBroadcast]:%s, status = %d for handle = %d",__func__, status, bis_handle); - if (!btif_bap_is_broadcaster_valid(current_handle)) return; - if (pending_cmd == setup_iso) { - memset(local_param, 0, 3); - local_param[0] = status; - local_param[1] = bis_handle & 0x00FF; - local_param[2] = (bis_handle & 0xFF00) >> 8; - if (status == 0) { - total_bises--; - btif_bap_ba_handle_event(BTIF_BAP_BROADCAST_SETUP_NEXT_BIS_EVENT, (char *)local_param); - } else { - local_param[0] = current_handle; - local_param[1] = status; - btif_bap_ba_handle_event(BTIF_BAP_BROADCAST_BISES_SETUP_EVT, (char *)local_param); - } - } else if (pending_cmd == remove_iso) { - memset(local_param, 0, 3); - local_param[0] = status; - local_param[1] = bis_handle & 0x00FF; - local_param[2] = (bis_handle & 0xFF00) >> 8; - btif_bap_ba_handle_event(BTIF_BAP_BROADCAST_SETUP_NEXT_BIS_EVENT, (char*)local_param); - } -} - -static bool btif_bap_ba_setup_iso_datapath(int big_handle) { - BTIF_TRACE_WARNING("[BapBroadcast]:%s",__func__); - BtifBapBroadcaster *bms = btif_bap_bms.FindBmsFromBIGHandle(big_handle); - if (bms == nullptr) { - BTIF_TRACE_WARNING("[BapBroadcast]:%s bms is null",__func__); - return false; - } - if (!btif_bap_is_broadcaster_valid(big_handle)) return false; - if (current_iso_index == bms->NumBises()) { - BTIF_TRACE_WARNING("[BapBroadcast]:%s completed",__func__); - return false; - } - pending_cmd = setup_iso; - std::vector BisHandles = bms->GetBISHandles(); - tBTM_BLE_SET_ISO_DATA_PATH_PARAM *p_param = new tBTM_BLE_SET_ISO_DATA_PATH_PARAM; - p_param->conn_handle = BisHandles[current_iso_index++]; - p_param->data_path_dir = 0; - p_param->data_path_id = PATH_ID;//6; - p_param->codec_id[0] = 6; - p_param->cont_delay[0] = 0; - p_param->cont_delay[1] = 0; - p_param->cont_delay[2] = 0; - p_param->codec_config_length = 0; - //param.codec_config = NULL; - p_param->p_cb = (tBTM_BLE_SETUP_ISO_DATA_PATH_CMPL_CB*)&btif_bap_ba_isodatapath_setup_cb; - - BTIF_TRACE_WARNING("[BapBroadcast]:%s for handle = %d",__func__, p_param->conn_handle); - do_in_bta_thread(FROM_HERE,base::Bind(base::IgnoreResult(&BTM_BleSetIsoDataPath), std::move(p_param))); - return true; -} - -static bool btif_bap_ba_remove_iso_datapath(int big_handle) { - BTIF_TRACE_WARNING("[BapBroadcast]:%s",__func__); - BtifBapBroadcaster *bms = btif_bap_bms.FindBmsFromBIGHandle(big_handle); - if (bms == nullptr) { - BTIF_TRACE_WARNING("[BapBroadcast]%s: broadcaster not found",__func__); - return false; - } - if (current_iso_index == bms->NumBises()) { - return false; - } - pending_cmd = remove_iso; - std::vector BisHandles = bms->GetBISHandles(); - uint16_t bis_handle = BisHandles[current_iso_index++]; - do_in_bta_thread(FROM_HERE, base::Bind(base::IgnoreResult(&BTM_BleRemoveIsoDataPath), bis_handle, - INPUT_DATAPATH,&btif_bap_ba_isodatapath_setup_cb)); - return true; -} - -void btif_bap_ba_creat_big_cb(uint8_t adv_id, uint8_t status, uint8_t big_handle, - uint32_t sync_delay, uint32_t transport_latency, uint8_t phy, uint8_t nse, uint8_t bn, uint8_t pto, - uint8_t irc, uint16_t max_pdu, uint16_t iso_int, uint8_t num_bis, std::vector conn_handle_list) { - BTIF_TRACE_IMP("[BapBroadcast]%s: callback: status = %d, adv_id = %d",__func__, status, adv_id); - if (status == BT_STATUS_SUCCESS) { - BtifBapBroadcaster *bms = btif_bap_bms.FindBmsFromAdvHandle(adv_id); - if (bms == nullptr) { - BTIF_TRACE_ERROR("%s: broadcaster not found",__func__); - return; - } - if (bms->StateMachine().StateId() != BtifBapBroadcastStateMachine::kStateConfigured || - bms->BIGState() != BIG_CREATING) { - BTIF_TRACE_WARNING("[BapBroadcast]%s: Broadcast is disabling",__func__); - return; - } - bms->SetBIGHandle(big_handle); - BTIF_TRACE_DEBUG("[BapBroadcast]%s: callback: big_handle = %d",__func__, bms->BIGHandle()); - bms->SetNumBises(num_bis); - BTIF_TRACE_DEBUG("[BapBroadcast]%s: callback: num_bis = %d",__func__, bms->NumBises()); - bms->SetBISHandles(conn_handle_list); - bms->SetBIGState(BIG_CREATED); - local_param[0] = adv_id; - do_in_bta_thread(FROM_HERE, - base::Bind(&btif_bap_ba_handle_event, - BTIF_BAP_BROADCAST_SETUP_ISO_DATAPATH_EVT, local_param)); - } else { - local_param[0] = adv_id; - do_in_bta_thread(FROM_HERE, - base::Bind(&btif_bap_ba_handle_event, - BTIF_BAP_BROADCAST_DISABLE_EVT, local_param)); - } -} - -static void btif_bap_ba_create_big(int adv_handle) { - BTIF_TRACE_IMP("[BapBroadcast]:%s",__func__); - //char ba_enc[PROPERTY_VALUE_MAX] = {0}; -#if BIG_COMPILE - BtifBapBroadcaster *bms = btif_bap_bms.FindBmsFromAdvHandle(adv_handle); - if (bms == nullptr) { - BTIF_TRACE_ERROR("%s: broadcaster not found",__func__); - return; - } - CreateBIGParameters param; - param.adv_handle = adv_handle; - param.num_bis = bms->NumBises(); - param.sdu_int = mBigParams.sdu_int; - param.max_sdu = mBigParams.max_sdu; - param.max_transport_latency = btif_bap_get_transport_latency(); - param.rtn = mBigParams.rtn; - param.phy = mBigParams.phy; - param.packing = mBigParams.packing;;//0 : sequential, 1: interleaved - param.framing = mBigParams.framing; - //osi_property_get("persist.bluetooth.ba_encryption", ba_enc, "true"); - //if (!(strncmp(ba_enc,"true",4))) { - if (mEncryptionEnabled) { - //mEncryptionEnabled = true; - param.encryption = 0x01; - } else { - mEncryptionEnabled = false; - param.encryption = 0x00; - } - uint8_t code[16] = {0}; - if (mEncryptionEnabled) { - memcpy(&code[0], encryption_key.data(),encryption_key.size()); - } - for(int i =0; i < 16; i++) { - param.broadcast_code.push_back(code[15-i]); - BTIF_TRACE_VERBOSE("[BapBroadcast]%s: code[%d] = %x, bc[%d] = %d",__func__,i,code[i],i,param.broadcast_code[i]); - } - - btif_gatt_get_interface()->advertiser->CreateBIG(adv_handle, param, - base::Bind(&btif_bap_ba_creat_big_cb)); -#endif /* BIG_COMPILE */ -} - -#if BIG_COMPILE -static void btif_bap_ba_terminate_big_cb(uint8_t status, uint8_t adv_id, - uint8_t big_handle, uint8_t reason) { - BTIF_TRACE_IMP("[BapBroadcast]:%s",__func__); - local_param[0] = adv_id; - do_in_bta_thread(FROM_HERE, - base::Bind(&btif_bap_ba_handle_event, - BTIF_BAP_BROADCAST_BIG_REMOVED_EVT, /*(char*)&adv_id)*/local_param)); - -} -#endif /* BIG_COMPILE */ - -static void btif_bap_ba_terminate_big(int adv_handle, int big_handle) { - BTIF_TRACE_IMP("[BapBroadcast]:%s",__func__); -#if BIG_COMPILE - int reason = 0x16; //user terminated - btif_gatt_get_interface()->advertiser->TerminateBIG(adv_handle, big_handle, reason, - base::Bind(&btif_bap_ba_terminate_big_cb)); -#endif /* BIG_COMPILE */ -} - -void btif_bap_ba_dispatch_sm_event(btif_bap_broadcast_sm_event_t event, void* p_data, int len) { - BTIF_TRACE_DEBUG("%s: event: %d, len: %d", __FUNCTION__, event, len); - do_in_bta_thread(FROM_HERE, - base::Bind(&btif_bap_ba_handle_event, event, (char*)p_data)); - BTIF_TRACE_DEBUG("%s: event %d sent", __FUNCTION__, event); -} - -void btif_broadcast_process_hidl_event(tA2DP_CTRL_CMD cmd) { - btif_bap_ba_dispatch_sm_event(BTIF_BAP_BROADCAST_PROCESS_HIDL_REQ_EVT, - (char*)&cmd, sizeof(cmd)); -} -bool btif_bap_broadcast_is_active() { - BTIF_TRACE_DEBUG("[BapBroadcast]:%s",__func__); - if (btif_bap_bms.BroadcastActive()) { - return true; - } - return false; -} - -void btif_bap_ba_update_big_params() { - uint32_t bitrate = btif_bap_broadcast_get_bitrate(); - mBigParams.max_sdu = btif_bap_broadcast_get_mtu(bitrate); - mBigParams.sdu_int = btif_bap_broadcast_get_framelength(); - BTIF_TRACE_DEBUG("[BapBroadcast]:%s: max_sdu = %d, sdu_int = %d",__func__, - mBigParams.max_sdu, mBigParams.sdu_int); -} -uint16_t btif_bap_broadcast_get_sample_rate() { - if (current_config.sample_rate != BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) { - BTIF_TRACE_DEBUG("[BapBroadcast]:%s: sample_rate = %d",__func__, current_config.sample_rate); - return current_config.sample_rate; - } else { - BTIF_TRACE_DEBUG("[BapBroadcast]:%s: default sample_rate = %d",__func__, default_config.sample_rate); - return default_config.sample_rate; - } -} -uint8_t btif_bap_broadcast_get_ch_mode() { - if (current_config.channel_mode != BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) { - return current_config.channel_mode; - } else { - return default_config.channel_mode; - } -} -uint32_t btif_bap_broadcast_get_mtu(uint32_t bitrate) { - //based on bitrate set (100(80kbps), 120 (96kbps), 155 (128kbps)) - uint32_t mtu; - switch (bitrate) { - case 24000: - mtu = 30; - break; - case 27734: - mtu = 26; - break; - case 48000: {//HAP HQ - if (current_config.codec_specific_2 == 0) - mtu = 45; - else - mtu = 60; - break; - } - case 32000: { - if (current_config.codec_specific_2 == 0) - mtu = 30; - else - mtu = 40; - break; - } - case 64000: { - if (current_config.codec_specific_2 == 0) - mtu = 60; - else - mtu = 80; - break; - } - case 80000: { - if (current_config.codec_specific_2 == 0) - mtu = 75; - else - mtu = 100; - break; - } - case 95060: - mtu = 97; - break; - case 95550: - mtu = 130; - break; - case 96000: { - if (current_config.codec_specific_2 == 0) - mtu = 90; - else - mtu = 120; - break; - } - case 124800: - mtu = 117; - break; - case 124000: - mtu = 155; - break; - default: - mtu = 100; - } - BTIF_TRACE_DEBUG("[BapBroadcast]%s: mtu = %d",__func__,mtu); - return mtu; -} - -uint16_t btif_bap_broadcast_get_framelength() { - uint16_t frame_duration; - switch (current_config.codec_specific_2) { - case 0: - frame_duration = 7500; //7.5msec - break; - case 1: - frame_duration = 10000; //10msec - break; - default: - frame_duration = 10000; - } - BTIF_TRACE_DEBUG("[BapBroadcast]%s: bitrate = %d",__func__,frame_duration); - return frame_duration; -} - -uint32_t btif_bap_broadcast_get_bitrate() { - //based on bitrate set (100(80kbps), 120 (96kbps), 155 (128kbps)) - uint32_t bitrate = 0; - switch (current_config.codec_specific_1) { - case 1000: //32kbps - if (current_config.codec_specific_2 == 0) { - bitrate = 27734; - } else { - bitrate = 24000; - } - break; - case 1001: //32kbps - bitrate = 32000; - break; - case 1002: //48kbps - bitrate = 48000; - break; - case 1003: //64kbps - bitrate = 64000; - break; - case 1004: //80kbps - bitrate = 80000; - break; - case 1005: //955.55kbps - if (current_config.codec_specific_2 == 0) { - bitrate = 95060; - } else { - bitrate = 95550; - } - break; - case 1006: //96kbps - bitrate = 96000; - break; - case 1007: //96kbps - if (current_config.codec_specific_2 == 0) { - bitrate = 124800; - } else { - bitrate = 124000; - } - break; - default: - bitrate = 80000; - } - BTIF_TRACE_DEBUG("[BapBroadcast]%s: bitrate = %d",__func__,bitrate); - return bitrate; -} - -uint8_t btif_bap_broadcast_get_ch_count() { - if (current_config.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO) { - return BROADCAST_SPLIT_STEREO * mBisMultiplier; - } else if (current_config.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_MONO || - current_config.channel_mode == BTBAP_CODEC_CHANNEL_MODE_JOINT_STEREO) { - return BROADCAST_MONO_JOINT * mBisMultiplier; - } - return BROADCAST_SPLIT_STEREO;//default split stereo -} - -static uint16_t btif_bap_get_transport_latency() { - uint16_t latency; - if (mBigParams.max_transport_latency != 0) { - BTIF_TRACE_DEBUG("[BapBroadcast]%s: latency set by property: %d", - __func__, mBigParams.max_transport_latency); - return mBigParams.max_transport_latency; - } - switch (current_config.codec_specific_2) { - case 0: - latency = 45;//45msec for 7.5msec frame duration - break; - case 1: - default: - latency = 61;//61msec for 10msec frame duration - break; - } - BTIF_TRACE_DEBUG("[BapBroadcast]%s: transport latency = %d", - __func__, latency); - return latency; -} - -bool btif_bap_broadcast_is_simulcast_enabled() { - char value[PROPERTY_VALUE_MAX] = {'\0'}; - osi_property_get("persist.vendor.btstack.partial_simulcast",value,"false"); - if (strcmp(value, "true") == 0) { - BTIF_TRACE_IMP("[BapBroadcast]%s:Partial simulcast enabled",__func__); - return true; - } - return false; -} - -static void btif_bap_ba_copy_broadcast_id() { - BTIF_TRACE_DEBUG("[BapBroadcast]:%s",__func__); - for(int j = 0; j < 3; j++) { - BTIF_TRACE_DEBUG("Broadcast_ID[%d] = %d",j, mBroadcastID[j]); - } - btif_report_broadcast_id(); -} - -static void btif_bap_ba_generate_broadcast_id() { - BTIF_TRACE_DEBUG("[BapBroadcast]:%s",__func__); - btsnd_hcic_ble_rand(base::Bind([](BT_OCTET8 rand) { - for(int a = 0; a < 3; a++) { - uint8_t val = rand[a]; - BTIF_TRACE_DEBUG("val = %d", val); - mBroadcastID[a] = val; - } - btif_bap_ba_copy_broadcast_id(); - })); -} - -static void btif_bap_ba_generate_enc_key_local(int length) { - BTIF_TRACE_DEBUG("[BapBroadcast]:%s length = %d",__func__, length); - srand(time(NULL)); - int i = 0; - uint8_t random_key[OCTET16_LEN] = {0}; - while (i < length) { - uint8_t gen = (uint8_t)(rand() % 256); - uint8_t range = (gen % 75) + 48;//Alphanumeric range - if ((range > 57 && range < 65) || - (range > 90 && range < 97)) { - //Ascii range 58 to 64 - //:,;, <, =, >, ?, @] - //range 91 to 96 - //[, \, ], ^, _, ` - BTIF_TRACE_DEBUG("Generate key: Invalid character"); - continue; - } - random_key[i] = range; - i++; - } - - memset(encryption_key.data(), 0, OCTET16_LEN); - memcpy(encryption_key.data(),random_key, OCTET16_LEN); - reverseCode(random_key); - BTIF_TRACE_DEBUG("[BapBroadcast]:%s storing new excryption key of length %d",__func__, OCTET16_LEN); - if (btif_config_set_bin("Adapter", "BAP_BA_ENC_KEY", /*encryption_key.data()*/random_key, OCTET16_LEN)) { - BTIF_TRACE_DEBUG("%s: stored new key", __func__); - btif_config_flush(); - } else { - BTIF_TRACE_DEBUG("%s: failed to store new key", __func__);; - } - if (notify_key_generated) { - notify_key_generated = false; - btif_report_encyption_key(); - } -} -void init_local_capabilities() { - broadcast_codecs_capabilities.push_back(broadcast_local_capability); -} - -static bt_status_t init_broadcast( - btbap_broadcast_callbacks_t* callbacks, - int max_broadcast, btav_a2dp_codec_config_t codec_config, int mode) { - if(max_broadcast > BTIF_BAP_BA_NUM_CB) { - BTIF_TRACE_WARNING("%s: App setting maximum allowable broadcast(%d) \ - to more than limit(%d)", - __func__, max_broadcast, BTIF_BAP_BA_NUM_CB); - max_broadcast = BTIF_BAP_BA_NUM_CB; - } - return btif_bap_bms.Init(callbacks, max_broadcast, codec_config, mode); -} -static bt_status_t enable_broadcast(btav_a2dp_codec_config_t codec_config) { - BTIF_TRACE_IMP("[BapBroadcast]:%s", __func__); - current_config = codec_config; - print_config(current_config); - return btif_bap_bms.EnableBroadcast(codec_config); -} -static bt_status_t disable_broadcast(int adv_id) { - BTIF_TRACE_IMP("[BapBroadcast]:%s", __func__); - return btif_bap_bms.DisableBroadcast(adv_id); -} -static bt_status_t set_broadcast_active(bool setup, uint8_t adv_id) { - BTIF_TRACE_EVENT("[BapBroadcast]:%s", __func__); - return btif_bap_bms.SetBroadcastActive(setup, adv_id); -} -static bt_status_t config_codec(uint8_t adv_handle, btav_a2dp_codec_config_t codec_config) { - BTIF_TRACE_IMP("[BapBroadcast]:%s", __func__); - bool config_changed = false; - print_config(codec_config); - if (codec_config.sample_rate != current_config.sample_rate || - codec_config.channel_mode != current_config.channel_mode || - codec_config.codec_specific_1 != current_config.codec_specific_1 || - codec_config.codec_specific_2 != current_config.codec_specific_2 || - codec_config.codec_specific_4 > 0) { - config_changed = true; - } - - if (config_changed) { - return btif_bap_bms.SetUserConfig(adv_handle, codec_config); - } - return BT_STATUS_SUCCESS; -} -static bt_status_t set_encryption(bool enabled, uint8_t enc_length) { - BTIF_TRACE_DEBUG("[BapBroadcast]:%s: length %d", __func__, enc_length); - mEncryptionEnabled = enabled; - /*if (!mEncryptionEnabled) { - btif_config_remove("Adapter", "BAP_BA_ENC_KEY"); - return BT_STATUS_SUCCESS; - }*/ - return btif_bap_bms.SetEncryption(enc_length); -} - -static std::string get_encryption_key() { - BTIF_TRACE_DEBUG("[BapBroadcast]:%s", __func__); - return std::string(reinterpret_cast(encryption_key.data()), OCTET16_LEN); -} - -static bt_status_t setup_audio_data_path(bool enable, uint8_t adv_id, - uint8_t big_handle, int num_bises, int *bis_handles) { - BTIF_TRACE_DEBUG("[BapBroadcast]:%s", __func__); - return BT_STATUS_SUCCESS; -} -static void cleanup_broadcast() { - BTIF_TRACE_ERROR("[BapBroadcast]:%s", __func__); - btif_bap_bms.Cleanup(); -} - -static const btbap_broadcast_interface_t bt_bap_broadcast_src_interface = { - sizeof(btbap_broadcast_interface_t), - init_broadcast, - enable_broadcast, - disable_broadcast, - set_broadcast_active, - config_codec, - setup_audio_data_path, - get_encryption_key, - set_encryption, - cleanup_broadcast, -}; - -/******************************************************************************* - * - * Function btif_bap_broadcast_get_interface - * - * Description Get the Bap broadcast callback interface - * - * Returns btbap_broadcast_interface_t - * - ******************************************************************************/ -const btbap_broadcast_interface_t* btif_bap_broadcast_get_interface(void) { - BTIF_TRACE_EVENT("%s", __func__); - return &bt_bap_broadcast_src_interface; -} - - diff --git a/le_audio/system/bt/btif/src/btif_bap_codec_utils.cc b/le_audio/system/bt/btif/src/btif_bap_codec_utils.cc deleted file mode 100644 index 447c3f62e2b6af2310fb68438adc5ecd93dda5eb..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/src/btif_bap_codec_utils.cc +++ /dev/null @@ -1,395 +0,0 @@ -/****************************************************************************** - * - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - - -#include "bta_closure_api.h" -#include "bta_bap_uclient_api.h" -#include "btif_common.h" -#include "btif_storage.h" -#include "osi/include/thread.h" - -// Capabilities to be stored on CodecConfig structure : -// Supported_Sampling_Frequencies  ( codec config sampling rate ) -// Audio_Channel_Counts ( codec config channel mode ) -// Supported_Frame_Durations ( 1st byte of codec specific 1 )  -// Max_Supported_LC3_Frames_Per_SDU  ( 2nd byte of codec specific 1) -// Preferred_Audio_Contexts ( 3&4 bytes of codec specific 1 ) -// Supported_Octets_Per_Codec_Frame ( first 4 bytes codec specific 2 ) -/* Vendor_Specific Metadata ( first 4 bytes of codec specific 3) - * 1st byte conveys LC3Q support, - * 2nd byte conveys LC3Q version - */ - -// Configurations to be stored in CodecConfig structure : -// Sampling_Frequency  ( codec config sampling rate ) -// Audio_Channel_Allocation ( codec config channel mode ) -// Frame_Duration  ( 5th bye of codec specific 1 )  -// LC3_Blocks_Per_SDU ( 6th byte of codec specific 1 ) -// Preferred_Audio_Contexts ( 7&8 bytes of codec specific 1 ) -// Octets_Per_Codec_Frame ( 2 bytes  )  ( 5&6th bytes of codec specific 2 ) -// LC3Q preferred (1 byte) ( 7th byte of codec specific 2 ) -/* Vendor_Specific Metadata ( first 4 bytes of codec specific 3) - * 1st byte conveys LC3Q support, - * 2nd byte conveys LC3Q version - */ - -#include -#include -#include - -using bluetooth::bap::pacs::CodecConfig; -using bluetooth::bap::pacs::CodecChannelMode; - -constexpr uint8_t CAPA_SUP_FRAME_DUR_INDEX = 0x00; // CS1 -constexpr uint8_t CAPA_MAX_SUP_LC3_FRAMES_INDEX = 0x01; // CS1 -constexpr uint8_t CAPA_PREF_AUDIO_CONT_INDEX = 0x02; // CS1 -constexpr uint8_t CAPA_SUP_OCTS_PER_FRAME_INDEX = 0x00; // CS2 - -constexpr uint8_t CAPA_VENDOR_METADATA_LC3Q_PREF_INDEX = 0x00; // CS3 -constexpr uint8_t CAPA_VENDOR_METADATA_LC3Q_VER_INDEX = 0x01; // CS3 - -constexpr uint8_t CONFIG_FRAME_DUR_INDEX = 0x04; // CS1 -constexpr uint8_t CONFIG_LC3_BLOCKS_INDEX = 0x05; // CS1 -constexpr uint8_t CONFIG_PREF_AUDIO_CONT_INDEX = 0x06; // CS1 -constexpr uint8_t CONFIG_OCTS_PER_FRAME_INDEX = 0x04; // CS2 -constexpr uint8_t CONFIG_LC3Q_PREF_INDEX = 0x06; // CS2 -constexpr uint8_t CONFIG_VENDOR_METADATA_LC3Q_PREF_INDEX = 0x00; // CS3 -constexpr uint8_t CONFIG_VENDOR_METADATA_LC3Q_VER_INDEX = 0x01; // CS3 - -// capabilities -bool UpdateCapaSupFrameDurations(CodecConfig *config , uint8_t sup_frame) { - config->codec_specific_1 &= ~(0xFF << (CAPA_SUP_FRAME_DUR_INDEX * 8)); - config->codec_specific_1 |= sup_frame << (CAPA_SUP_FRAME_DUR_INDEX * 8); - return true; -} - -bool UpdateCapaMaxSupLc3Frames(CodecConfig *config, - uint8_t max_sup_lc3_frames) { - config->codec_specific_1 &= ~(0xFF << (CAPA_MAX_SUP_LC3_FRAMES_INDEX * 8)); - config->codec_specific_1 |= max_sup_lc3_frames << - (CAPA_MAX_SUP_LC3_FRAMES_INDEX * 8); - return true; -} - -bool UpdateCapaPreferredContexts(CodecConfig *config, uint16_t contexts) { - config->codec_specific_1 &= ~(0xFFFF << (CAPA_PREF_AUDIO_CONT_INDEX * 8)); - config->codec_specific_1 |= contexts << (CAPA_PREF_AUDIO_CONT_INDEX * 8); - return true; -} - -bool UpdateCapaSupOctsPerFrame(CodecConfig *config, - uint32_t octs_per_frame) { - config->codec_specific_2 &= ~(0xFFFFFFFF << - (CAPA_SUP_OCTS_PER_FRAME_INDEX * 8)); - config->codec_specific_2 |= octs_per_frame << - (CAPA_SUP_OCTS_PER_FRAME_INDEX * 8); - return true; -} - -bool UpdateCapaVendorMetaDataLc3QPref(CodecConfig *config, bool lc3q_pref) { - config->codec_specific_3 &= ~(0xFF << (CAPA_VENDOR_METADATA_LC3Q_PREF_INDEX * 8)); - config->codec_specific_3 |= lc3q_pref << (CAPA_VENDOR_METADATA_LC3Q_PREF_INDEX * 8); - return true; -} - -bool UpdateCapaVendorMetaDataLc3QVer(CodecConfig *config, uint8_t lc3q_ver) { - config->codec_specific_3 &= ~(0xFF << (CAPA_VENDOR_METADATA_LC3Q_VER_INDEX * 8)); - config->codec_specific_3 |= lc3q_ver << (CAPA_VENDOR_METADATA_LC3Q_VER_INDEX * 8); - return true; -} - -uint8_t GetCapaSupFrameDurations(CodecConfig *config) { - return (config->codec_specific_1 >> (8*CAPA_SUP_FRAME_DUR_INDEX)) & 0xff; -} - -uint8_t GetCapaMaxSupLc3Frames(CodecConfig *config) { - if (((config->codec_specific_1 >> - (8*CAPA_MAX_SUP_LC3_FRAMES_INDEX)) & 0xff) == 0x0) { - uint8_t max_chnl_count = 0; - LOG(ERROR) << __func__ - << ": Max Sup LC3 frames is 0, deriving based on chnl count"; - if(static_cast (config->channel_mode) & - static_cast (CodecChannelMode::CODEC_CHANNEL_MODE_STEREO)) { - max_chnl_count = 2; - } else if(static_cast (config->channel_mode) & - static_cast (CodecChannelMode::CODEC_CHANNEL_MODE_MONO)) { - max_chnl_count = 1; - } - return max_chnl_count; - } else { - return (config->codec_specific_1 >> - (8*CAPA_MAX_SUP_LC3_FRAMES_INDEX)) & 0xff; - } -} - -uint16_t GetCapaPreferredContexts(CodecConfig *config) { - return (config->codec_specific_1 >> - (8*CAPA_PREF_AUDIO_CONT_INDEX)) & 0xffff; -} - -uint32_t GetCapaSupOctsPerFrame(CodecConfig *config) { - return (config->codec_specific_2 >> - (8*CAPA_SUP_OCTS_PER_FRAME_INDEX)) & 0xffffffff; -} - -bool GetCapaVendorMetaDataLc3QPref(CodecConfig *config) { - if (((config->codec_specific_3 >> - (8*CAPA_VENDOR_METADATA_LC3Q_PREF_INDEX)) & 0xff) == 0x0) { - return false; - } else - return true; -} - -uint8_t GetCapaVendorMetaDataLc3QVer(CodecConfig *config) { - return (config->codec_specific_3 >> - (8*CAPA_VENDOR_METADATA_LC3Q_VER_INDEX)) & 0xff; -} - -// Configurations -bool UpdateFrameDuration(CodecConfig *config , uint8_t frame_dur) { - uint64_t value = 0xFF; - config->codec_specific_1 &= ~(value << (CONFIG_FRAME_DUR_INDEX*8)); - config->codec_specific_1 |= static_cast(frame_dur) << - (CONFIG_FRAME_DUR_INDEX * 8); - return true; -} - -bool UpdateLc3BlocksPerSdu(CodecConfig *config, uint8_t lc3_blocks_per_sdu) { - uint64_t value = 0xFF; - config->codec_specific_1 &= ~(value << (CONFIG_LC3_BLOCKS_INDEX * 8)); - config->codec_specific_1 |= static_cast(lc3_blocks_per_sdu) << - (CONFIG_LC3_BLOCKS_INDEX * 8); - return true; -} - -bool UpdatePreferredAudioContext(CodecConfig *config , - uint16_t pref_audio_context) { - uint64_t value = 0xFFFF; - config->codec_specific_1 &= ~(value << (CONFIG_PREF_AUDIO_CONT_INDEX*8)); - config->codec_specific_1 |= static_cast(pref_audio_context) << - (CONFIG_PREF_AUDIO_CONT_INDEX * 8); - return true; -} - -bool UpdateOctsPerFrame(CodecConfig *config , uint16_t octs_per_frame) { - uint64_t value = 0xFFFF; - config->codec_specific_2 &= ~(value << (CONFIG_OCTS_PER_FRAME_INDEX * 8)); - config->codec_specific_2 |= - static_cast(octs_per_frame) << - (CONFIG_OCTS_PER_FRAME_INDEX * 8); - return true; -} - -bool UpdateLc3QPreference(CodecConfig *config , bool lc3q_pref) { - uint64_t value = 0xFF; - config->codec_specific_2 &= ~(value << (CONFIG_LC3Q_PREF_INDEX * 8)); - config->codec_specific_2 |= - static_cast(lc3q_pref) << - (CONFIG_LC3Q_PREF_INDEX * 8); - LOG(WARNING) << __func__ - << ": lc3q_pref cs2: " << loghex(config->codec_specific_2); - return true; -} - - -bool UpdateVendorMetaDataLc3QPref(CodecConfig *config, bool lc3q_pref) { - uint64_t value = 0xFF; - config->codec_specific_3 &= ~(value << (CONFIG_VENDOR_METADATA_LC3Q_PREF_INDEX * 8)); - config->codec_specific_3 |= static_cast(lc3q_pref) << - (CONFIG_VENDOR_METADATA_LC3Q_PREF_INDEX * 8); - return true; -} - -bool UpdateVendorMetaDataLc3QVer(CodecConfig *config, uint8_t lc3q_ver) { - uint64_t value = 0xFF; - config->codec_specific_3 &= ~(value << (CONFIG_VENDOR_METADATA_LC3Q_VER_INDEX * 8)); - config->codec_specific_3 |= static_cast(lc3q_ver) << - (CONFIG_VENDOR_METADATA_LC3Q_VER_INDEX * 8); - return true; -} - -uint8_t GetFrameDuration(CodecConfig *config) { - return (config->codec_specific_1 >> (8*CONFIG_FRAME_DUR_INDEX)) & 0xff; -} - -uint8_t GetLc3BlocksPerSdu(CodecConfig *config) { - return (config->codec_specific_1 >> (8*CONFIG_LC3_BLOCKS_INDEX)) & 0xff; -} - -uint16_t GetPreferredAudioContext(CodecConfig *config) { - return (config->codec_specific_1 >> - (8*CONFIG_PREF_AUDIO_CONT_INDEX)) & 0xffff; -} - -uint16_t GetOctsPerFrame(CodecConfig *config) { - return (config->codec_specific_2 >> (8*CONFIG_OCTS_PER_FRAME_INDEX)) & 0xffff; -} - -uint8_t GetLc3QPreference(CodecConfig *config) { - LOG(WARNING) << __func__ << ": lc3q_pref cs2: " - << loghex((config->codec_specific_2 >> (8*CONFIG_LC3Q_PREF_INDEX)) & 0xff); - return (config->codec_specific_2 >> - (8*CONFIG_LC3Q_PREF_INDEX)) & 0xff; -} - -uint8_t GetVendorMetaDataLc3QPref(CodecConfig *config) { - return (config->codec_specific_3 >> - (8*CONFIG_VENDOR_METADATA_LC3Q_PREF_INDEX)) & 0xff; -} - -uint8_t GetVendorMetaDataLc3QVer(CodecConfig *config) { - return (config->codec_specific_3 >> - (8*CONFIG_VENDOR_METADATA_LC3Q_VER_INDEX)) & 0xff; -} - -bool IsCodecConfigEqual(CodecConfig *src_config, CodecConfig *dst_config) { - // first check if passed codec configs are configurations or - // capabilities using first byte of codec specific 1 - if(src_config == nullptr || dst_config == nullptr) { - return false; - } - - bool is_src_capability = src_config->codec_specific_1 & 0XFF; - bool is_dst_capability = dst_config->codec_specific_1 & 0XFF; - - // check the codec type - if(src_config->codec_type != dst_config->codec_type) { - LOG(ERROR) << __func__ << ": No match for codec type "; - return false; - } - - // check sample rate - if(src_config->sample_rate != dst_config->sample_rate) { - LOG(ERROR) << __func__ << ": No match for sample rate"; - return false; - } - - // check channel mode - if(!(static_cast(src_config->channel_mode) & - static_cast(dst_config->channel_mode))) { - LOG(ERROR) << __func__ << ": No match for channel mode "; - return false; - } - - LOG(WARNING) << __func__ - << ": is_src_capability: " << loghex(is_src_capability) - << ", is_dst_capability: " << loghex(is_dst_capability); - - if(is_src_capability && is_dst_capability) { - if(src_config->codec_specific_1 != dst_config->codec_specific_1 || - src_config->codec_specific_2 != dst_config->codec_specific_2 || - src_config->codec_specific_3 != dst_config->codec_specific_3) { - LOG(WARNING) << __func__ << ": No match for CS params. "; - return false; - } - } else if (!is_src_capability && !is_dst_capability) { - LOG(INFO) << __func__ << ": Comparison for both configs "; - uint8_t src_frame_dur = GetFrameDuration(src_config); - uint8_t src_lc3_blocks_per_sdu = GetLc3BlocksPerSdu(src_config); - uint16_t src_octs_per_frame = GetOctsPerFrame(src_config); - uint8_t src_lc3q_pref = GetLc3QPreference(src_config); - uint16_t src_pref_audio_context = GetPreferredAudioContext(src_config); - - uint8_t dst_frame_dur = GetFrameDuration(dst_config); - uint8_t dst_lc3_blocks_per_sdu = GetLc3BlocksPerSdu(dst_config); - uint16_t dst_octs_per_frame = GetOctsPerFrame(dst_config); - uint8_t dst_lc3q_pref = GetLc3QPreference(dst_config); - uint16_t dst_pref_audio_context = GetPreferredAudioContext(dst_config); - - if(src_frame_dur != dst_frame_dur) { - LOG(ERROR) << __func__ << ": Frame Dur not match with existing config "; - return false; - } - - if(src_lc3_blocks_per_sdu != dst_lc3_blocks_per_sdu) { - LOG(ERROR) << __func__ << ": Lc3 blocks not match with existing config "; - return false; - } - - if(src_octs_per_frame != dst_octs_per_frame) { - LOG(ERROR) << __func__ << ": Octs per frame not match with existing config "; - return false; - } - - if(src_lc3q_pref != dst_lc3q_pref) { - LOG(ERROR) << __func__ << ": Lc3Q pref not match with existing config "; - return false; - } - - if (!(src_pref_audio_context & dst_pref_audio_context)) { - LOG(ERROR) << __func__ << ": pref_audio_context not match with existing config "; - return false; - } - - } else if(is_src_capability || is_dst_capability) { - CodecConfig *capa_config = is_src_capability ? src_config:dst_config; - CodecConfig *oth_config = is_src_capability ? dst_config:src_config; - - uint8_t capa_sup_frames = GetCapaSupFrameDurations(capa_config); - uint8_t capa_max_sup_lc3_frames = GetCapaMaxSupLc3Frames(capa_config); - uint16_t capa_min_sup_octs = GetCapaSupOctsPerFrame(capa_config) & 0xFFFF; - uint16_t capa_max_sup_octs = (GetCapaSupOctsPerFrame(capa_config) - & 0xFFFF0000) >> 16; - bool capa_lc3q_pref = GetCapaVendorMetaDataLc3QPref(capa_config); - uint16_t capa_pref_audio_context = GetCapaPreferredContexts(capa_config); - - uint8_t frame_dur = GetFrameDuration(oth_config); - uint8_t lc3_blocks_per_sdu = GetLc3BlocksPerSdu(oth_config); - uint16_t octs_per_frame = GetOctsPerFrame(oth_config); - uint8_t lc3q_pref = GetLc3QPreference(oth_config); - uint16_t dst_pref_audio_context = GetPreferredAudioContext(oth_config); - - LOG(WARNING) << __func__ - << ": capa_sup_frames: " << loghex(capa_sup_frames) - << ", frame_dur: " << loghex(frame_dur); - - LOG(WARNING) << __func__ - << ": capa_lc3q_pref: " << capa_lc3q_pref - << ", lc3q_pref: " << loghex(lc3q_pref); - - LOG(WARNING) << __func__ - << ": capa_pref_audio_context: " << capa_pref_audio_context - << ", dst_pref_audio_context: " << dst_pref_audio_context; - - if(!(capa_sup_frames & (0x01 << frame_dur))) { - LOG(ERROR) << __func__ << ": No match for frame duration "; - return false; - } - - if(capa_max_sup_lc3_frames && lc3_blocks_per_sdu) { - if(capa_max_sup_lc3_frames < lc3_blocks_per_sdu * - static_cast (oth_config->channel_mode)) { - LOG(ERROR) << __func__ << ": blocks per sdu exceeds the capacity "; - return false; - } - } - - if( octs_per_frame < capa_min_sup_octs || - octs_per_frame > capa_max_sup_octs) { - LOG(ERROR) << __func__ << ": octs per frame not in limits "; - return true; - } - - if (!(capa_pref_audio_context & dst_pref_audio_context)) { - LOG(ERROR) << __func__ << ": No Match for Audio context"; - return false; - } - - } - return true; -} diff --git a/le_audio/system/bt/btif/src/btif_bap_config.cc b/le_audio/system/bt/btif/src/btif_bap_config.cc deleted file mode 100644 index 6daeb6ad6557ebc212c0e021167408ef200fdf8f..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/src/btif_bap_config.cc +++ /dev/null @@ -1,860 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/****************************************************************************** - * - * Copyright (C) 2014 Google, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - -#define LOG_TAG "bt_btif_bap_config" - -#include "btif_bap_config.h" -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "bt_types.h" -#include "btcore/include/module.h" -#include "btif_api.h" -#include "btif_common.h" -#include "btif_util.h" -#include "osi/include/alarm.h" -#include "osi/include/allocator.h" -#include "osi/include/compat.h" -#include "osi/include/config.h" -#include "osi/include/log.h" -#include "osi/include/osi.h" -#include "osi/include/properties.h" -#include "btif_bap_codec_utils.h" - -#define BT_CONFIG_SOURCE_TAG_NUM 1010001 - -#define INFO_SECTION "Info" -#define FILE_TIMESTAMP "TimeCreated" -#define FILE_SOURCE "FileSource" -#define TIME_STRING_LENGTH sizeof("YYYY-MM-DD HH:MM:SS") -#define INDEX_FREE (0x00) -#define INDEX_OCCUPIED (0x01) -#define MAX_INDEX (255) -#define MAX_INDEX_LEN (0x04) -#define MAX_SECTION_LEN (255) - -using bluetooth::bap::pacs::CodecSampleRate; - -static const char* TIME_STRING_FORMAT = "%Y-%m-%d %H:%M:%S"; - -// TODO(armansito): Find a better way than searching by a hardcoded path. -#if defined(OS_GENERIC) -static const char* CONFIG_FILE_PATH = "bap_config.conf"; -static const char* CONFIG_BACKUP_PATH = "bap_config.bak"; -#else // !defined(OS_GENERIC) -static const char* CONFIG_FILE_PATH = "/data/misc/bluedroid/bap_config.conf"; -static const char* CONFIG_BACKUP_PATH = "/data/misc/bluedroid/bap_config.bak"; -#endif // defined(OS_GENERIC) -static const period_ms_t CONFIG_SETTLE_PERIOD_MS = 3000; - -static void timer_config_save_cb(void* data); -static void btif_bap_config_write(uint16_t event, char* p_param); -static bool is_factory_reset(void); -static void delete_config_files(void); -static void btif_bap_config_remove_restricted(config_t* config); -static config_t* btif_bap_config_open(const char* filename); - -static enum ConfigSource { - NOT_LOADED, - ORIGINAL, - BACKUP, - NEW_FILE, - RESET -} btif_bap_config_source = NOT_LOADED; - -//static int btif_bap_config_devices_loaded = -1; -static char btif_bap_config_time_created[TIME_STRING_LENGTH]; - -static config_t* config; -static std::recursive_mutex config_lock; // protects operations on |config|. -static alarm_t* config_timer; - -#define BAP_DIRECTION_KEY "Direction" -#define BAP_CODEC_TYPE_KEY "CodecType" - -#define BAP_RECORD_TYPE_KEY "RecordType" -#define BAP_RECORD_TYPE_CAPA "Capability" -#define BAP_RECORD_TYPE_CONF "Configuration" - -#define BAP_SAMP_FREQS_KEY "SamplingRate" -#define BAP_CONTEXT_TYPE_KEY "ContextType" - -#define BAP_SUPP_FRM_DURATIONS_KEY "SupFrameDurations" -#define BAP_SUP_MIN_OCTS_PER_FRAME_KEY "SupMinOctsPerFrame" -#define BAP_SUP_MAX_OCTS_PER_FRAME_KEY "SupMaxOctsPerFrame" -#define BAP_MAX_SUP_CODEC_FRAMES_PER_SDU "SupMaxFramesPerSDU" -#define BAP_LC3Q_SUP_KEY "LC3QSupport" -#define BAP_LC3Q_VER_KEY "LC3QVersion" - -#define BAP_CONF_FRAME_DUR_KEY "ConfiguredFrameDur" -#define BAP_CONF_OCTS_PER_FRAME_KEY "ConfiguredOctsPerFrame" -#define BAP_LC3_FRAMES_PER_SDU_KEY "Lc3FramesPerSDU" -#define BAP_CHNL_ALLOCATION_KEY "ChannelAllocation" - -#define BAP_SRC_LOCATIONS_KEY "SrcLocation" -#define BAP_SINK_LOCATIONS_KEY "SinkLocation" -#define BAP_SUP_AUDIO_CONTEXTS_KEY "SupAudioContexts" - -// Module lifecycle functions -static future_t* init(void) { - std::unique_lock lock(config_lock); - - if (is_factory_reset()) delete_config_files(); - - std::string file_source; - - config = btif_bap_config_open(CONFIG_FILE_PATH); - btif_bap_config_source = ORIGINAL; - if (!config) { - LOG_WARN(LOG_TAG, "%s unable to load config file: %s; using backup.", - __func__, CONFIG_FILE_PATH); - config = btif_bap_config_open(CONFIG_BACKUP_PATH); - btif_bap_config_source = BACKUP; - file_source = "Backup"; - } - - if (!config) { - LOG_ERROR(LOG_TAG, - "%s unable to transcode legacy file; creating empty config.", - __func__); - config = config_new_empty(); - btif_bap_config_source = NEW_FILE; - file_source = "Empty"; - } - - if (!config) { - LOG_ERROR(LOG_TAG, "%s unable to allocate a config object.", __func__); - goto error; - } - - if (!file_source.empty()) - config_set_string(config, INFO_SECTION, FILE_SOURCE, file_source.c_str()); - - // Cleanup temporary pairings if we have left guest mode - if (!is_restricted_mode()) btif_bap_config_remove_restricted(config); - - // Read or set config file creation timestamp - const char* time_str; - time_str = config_get_string(config, INFO_SECTION, FILE_TIMESTAMP, NULL); - if (time_str != NULL) { - strlcpy(btif_bap_config_time_created, time_str, TIME_STRING_LENGTH); - } else { - time_t current_time = time(NULL); - struct tm* time_created = localtime(¤t_time); - if (time_created) { - if (strftime(btif_bap_config_time_created, TIME_STRING_LENGTH, - TIME_STRING_FORMAT, time_created)) { - config_set_string(config, INFO_SECTION, FILE_TIMESTAMP, - btif_bap_config_time_created); - } - } - } - // TODO(sharvil): use a non-wake alarm for this once we have - // API support for it. There's no need to wake the system to - // write back to disk. - config_timer = alarm_new("btif_bap.config"); - if (!config_timer) { - LOG_ERROR(LOG_TAG, "%s unable to create alarm.", __func__); - goto error; - } - - LOG_EVENT_INT(BT_CONFIG_SOURCE_TAG_NUM, btif_bap_config_source); - - return future_new_immediate(FUTURE_SUCCESS); - -error: - alarm_free(config_timer); - if (config != NULL) - config_free(config); - config_timer = NULL; - config = NULL; - btif_bap_config_source = NOT_LOADED; - return future_new_immediate(FUTURE_FAIL); -} - -static config_t* btif_bap_config_open(const char* filename) { - config_t* config = config_new(filename); - if (!config) return NULL; - - return config; -} - -static void btif_bap_config_save(void) { - CHECK(config != NULL); - CHECK(config_timer != NULL); - - if (config_timer == NULL) { - LOG(WARNING) << __func__ << "config_timer is null"; - return; - } - alarm_set(config_timer, CONFIG_SETTLE_PERIOD_MS, timer_config_save_cb, NULL); -} - -static void btif_bap_config_flush(void) { - CHECK(config != NULL); - CHECK(config_timer != NULL); - - alarm_cancel(config_timer); - btif_bap_config_write(0, NULL); -} - -bool btif_bap_config_clear(void) { - CHECK(config != NULL); - CHECK(config_timer != NULL); - - alarm_cancel(config_timer); - - std::unique_lock lock(config_lock); - if (config != NULL) - config_free(config); - - config = config_new_empty(); - if (config == NULL) return false; - - bool ret = config_save(config, CONFIG_FILE_PATH); - btif_bap_config_source = RESET; - return ret; -} - -static future_t* shut_down(void) { - btif_bap_config_flush(); - return future_new_immediate(FUTURE_SUCCESS); -} - -static future_t* clean_up(void) { - btif_bap_config_flush(); - - alarm_free(config_timer); - config_timer = NULL; - - std::unique_lock lock(config_lock); - config_free(config); - config = NULL; - return future_new_immediate(FUTURE_SUCCESS); -} - -EXPORT_SYMBOL module_t btif_bap_config_module = {.name = BTIF_BAP_CONFIG_MODULE, - .init = init, - .start_up = NULL, - .shut_down = shut_down, - .clean_up = clean_up}; - -static void timer_config_save_cb(UNUSED_ATTR void* data) { - // Moving file I/O to btif context instead of timer callback because - // it usually takes a lot of time to be completed, introducing - // delays during A2DP playback causing blips or choppiness. - btif_transfer_context(btif_bap_config_write, 0, NULL, 0, NULL); -} - -static void btif_bap_config_write(UNUSED_ATTR uint16_t event, - UNUSED_ATTR char* p_param) { - CHECK(config != NULL); - CHECK(config_timer != NULL); - - std::unique_lock lock(config_lock); - rename(CONFIG_FILE_PATH, CONFIG_BACKUP_PATH); - if (config == NULL) { - LOG(WARNING) << __func__ << "config is null"; - return; - } - config_t* config_paired = config_new_clone(config); - - if (config_paired != NULL) { - //btif_bap_config_remove_unpaired(config_paired); - config_save(config_paired, CONFIG_FILE_PATH); - config_free(config_paired); - } -} - -static void btif_bap_config_remove_restricted(config_t* config) { - CHECK(config != NULL); - - if (config == NULL) { - LOG(WARNING) << __func__ << "config is null"; - return; - } - const config_section_node_t* snode = config_section_begin(config); - for(; snode != config_section_end(config); - snode = config_section_next(snode)) { - const char* section = config_section_name(snode); - // first check the address - if (config_has_key(config, section, "Restricted")) { - config_remove_section(config, section); - } - } -} - -static bool is_factory_reset(void) { - char factory_reset[PROPERTY_VALUE_MAX] = {0}; - osi_property_get("persist.bluetooth.factoryreset", factory_reset, "false"); - return strncmp(factory_reset, "true", 4) == 0; -} - -static void delete_config_files(void) { - remove(CONFIG_FILE_PATH); - remove(CONFIG_BACKUP_PATH); - osi_property_set("persist.bluetooth.factoryreset", "false"); -} - -static bool btif_bap_get_section_index(const std::string §ion, - uint16_t *index) { - char *temp = nullptr; - if (section.length() != 20) return false; - - std::vector byte_tokens = - base::SplitString(section, ":", base::TRIM_WHITESPACE, - base::SPLIT_WANT_ALL); - - LOG(WARNING) << __func__ << ": LC# codec "; - if (byte_tokens.size() != 7) return false; - - // get the last nibble - const auto& token = byte_tokens[6]; - - if (token.length() != 2) return false; - - *index = strtol(token.c_str(), &temp, 16); - - if (*temp != '\0') return false; - - return true; -} - -static bool btif_bap_get_free_section_id(const RawAddress& bd_addr, - char *section) { - uint16_t i = 0; - uint8_t index_status[MAX_INDEX] = {0}; - std::string addrstr = bd_addr.ToString(); - const char* bdstr = addrstr.c_str(); - - // reserve the first index for sink, src, locations - index_status[0] = INDEX_OCCUPIED; - - const config_section_node_t* snode = config_section_begin(config); - for(; snode != config_section_end(config); - snode = config_section_next(snode)) { - const char* section = config_section_name(snode); - uint16_t index; - - // first check the address - if(!strcasestr(section, bdstr)) { - continue; - } - - if(btif_bap_get_section_index(section, &index)) { - index_status[index] = INDEX_OCCUPIED; - } - } - - // find the unused index - for(i = 0; i < MAX_INDEX; i++) { - if(index_status[i] == INDEX_FREE) break; - } - - if(i != MAX_INDEX) { - char index_str[MAX_INDEX_LEN]; - // form the section entry ( bd address plus index) - snprintf(index_str, sizeof(index_str), ":%02x", i); - strlcpy(section, bdstr, MAX_SECTION_LEN); - strlcat(section, index_str, MAX_SECTION_LEN); - return true; - } else { - return false; - } -} - -static bool btif_bap_find_sections(const RawAddress& bd_addr, - btif_bap_record_type_t rec_type, - uint16_t context_type, - CodecDirection direction, - CodecConfig *record, - std::vector *sections) { - std::string addrstr = bd_addr.ToString(); - const char* bdstr = addrstr.c_str(); - const config_section_node_t* snode = config_section_begin(config); - for(; snode != config_section_end(config); - snode = config_section_next(snode)) { - const char *section = config_section_name(snode); - // first check the address - if(!strcasestr(section, bdstr)) { - continue; - } - - // next check the record type - const char* value_str = config_get_string(config, section, - BAP_RECORD_TYPE_KEY, NULL); - if(value_str == nullptr || - ((rec_type == REC_TYPE_CAPABILITY && - strcasecmp(value_str, BAP_RECORD_TYPE_CAPA)) || - (rec_type == REC_TYPE_CONFIGURATION && - strcasecmp(value_str, BAP_RECORD_TYPE_CONF)))) { - continue; - } - - // next check the record type - uint16_t context = config_get_uint16(config, section, - BAP_CONTEXT_TYPE_KEY, 0XFFFF); - LOG(WARNING) << __func__ << ": context " << context - << ": context_type " << context_type; - if(context != context_type) { - continue; - } - - // next check the direction - value_str = config_get_string(config, section, - BAP_DIRECTION_KEY, NULL); - if(value_str == nullptr || - ((direction == CodecDirection::CODEC_DIR_SRC && - strcasecmp(value_str, "SRC")) || - (direction == CodecDirection::CODEC_DIR_SINK && - strcasecmp(value_str, "SINK")))) { - continue; - } - - if(record == nullptr) { - sections->push_back((char*) section); - } else { - // next check codec type - value_str = config_get_string(config, section, - BAP_CODEC_TYPE_KEY, NULL); - - if(value_str == nullptr || - (record->codec_type == CodecIndex::CODEC_INDEX_SOURCE_LC3 && - strcasecmp(value_str, "LC3"))) { - continue; - } - - // next check the freqency - uint16_t value = config_get_uint16(config, section, - BAP_SAMP_FREQS_KEY, 0); - if(value == static_cast (record->sample_rate)) { - sections->push_back((char*) section); - } - } - } - - if(sections->size()) { - return true; - } else { - return false; - } -} - -static bool btif_bap_update_LC3_codec_info(char *section, CodecConfig *record, - btif_bap_record_type_t rec_type) { - if(section == nullptr || record == nullptr) { - return false; - } - - if(rec_type == REC_TYPE_CAPABILITY) { - - config_set_string(config, section, BAP_RECORD_TYPE_KEY, - BAP_RECORD_TYPE_CAPA); - - if(record->codec_type == CodecIndex::CODEC_INDEX_SOURCE_LC3) { - config_set_string(config, section, BAP_CODEC_TYPE_KEY, "LC3"); - } - // update freqs - config_set_uint16(config, section, BAP_SAMP_FREQS_KEY , - static_cast(record->sample_rate)); - - // update chnl count - config_set_uint16(config, section, BAP_CHNL_ALLOCATION_KEY, - static_cast (record->channel_mode)); - - // update supp frames - config_set_uint16(config, section, BAP_SUPP_FRM_DURATIONS_KEY , - static_cast (GetCapaSupFrameDurations(record))); - - // update chnl supp min octs per frame - config_set_uint16(config, section, BAP_SUP_MIN_OCTS_PER_FRAME_KEY , - static_cast (GetCapaSupOctsPerFrame(record) & - 0xFFFF)); - - // update chnl supp max octs per frame - config_set_uint16(config, section, BAP_SUP_MAX_OCTS_PER_FRAME_KEY, - static_cast ((GetCapaSupOctsPerFrame(record) & - 0xFFFF0000) >> 16)); - - // update max supp codec frames per sdu - config_set_uint16(config, section, BAP_MAX_SUP_CODEC_FRAMES_PER_SDU, - static_cast (GetCapaMaxSupLc3Frames(record))); - - // update LC3Q support - if (GetCapaVendorMetaDataLc3QPref(record)) { - config_set_string(config, section, BAP_LC3Q_SUP_KEY, "true"); - } else { - config_set_string(config, section, BAP_LC3Q_SUP_KEY, "false"); - } - - // update LC3Q Version - config_set_uint16(config, section, BAP_LC3Q_VER_KEY, - static_cast (GetCapaVendorMetaDataLc3QVer(record))); - } else { - - config_set_string(config, section, BAP_RECORD_TYPE_KEY, - BAP_RECORD_TYPE_CONF); - - if(record->codec_type == CodecIndex::CODEC_INDEX_SOURCE_LC3) { - config_set_string(config, section, BAP_CODEC_TYPE_KEY, "LC3"); - } - - // update freqs - config_set_uint16(config, section, BAP_SAMP_FREQS_KEY , - static_cast(record->sample_rate)); - - // update chnl count - config_set_uint16(config, section, BAP_CHNL_ALLOCATION_KEY, - static_cast (record->channel_mode)); - - // update configured frame duration - config_set_uint16(config, section, BAP_CONF_FRAME_DUR_KEY, - static_cast (GetFrameDuration(record))); - - // update configured octs per frame - config_set_uint16(config, section, BAP_CONF_OCTS_PER_FRAME_KEY, - static_cast (GetOctsPerFrame(record))); - - // update LC3 frames per SDU - config_set_uint16(config, section, BAP_LC3_FRAMES_PER_SDU_KEY, - static_cast (GetLc3BlocksPerSdu(record))); - } - - if (is_restricted_mode()) { - LOG(WARNING) << __func__ << ": records will be removed if unrestricted"; - config_set_uint16(config, section, "Restricted", 1); - } - - return true; -} - -bool btif_bap_add_record(const RawAddress& bd_addr, - btif_bap_record_type_t rec_type, - uint16_t context_type, - CodecDirection direction, - CodecConfig *record) { - // first check if same record already exists - std::unique_lock lock(config_lock); - std::vector sections; - - if(btif_bap_find_sections(bd_addr, rec_type, context_type, - direction, record, §ions)) { - for (auto it = sections.begin(); - it != sections.end(); it++) { - btif_bap_update_LC3_codec_info((*it), record , rec_type); - } - } else { - LOG(WARNING) << __func__ << ": section not found"; - char section[MAX_SECTION_LEN]; - btif_bap_get_free_section_id(bd_addr, section); - - config_set_uint16(config, section, BAP_CONTEXT_TYPE_KEY, context_type); - - if(direction == CodecDirection::CODEC_DIR_SRC) { - config_set_string(config, section, BAP_DIRECTION_KEY, "SRC"); - } else { - config_set_string(config, section, BAP_DIRECTION_KEY, "SINK"); - } - btif_bap_update_LC3_codec_info(section, record , rec_type); - } - btif_bap_config_save(); - return true; -} - -bool btif_bap_remove_record(const RawAddress& bd_addr, - btif_bap_record_type_t rec_type, - uint16_t context_type, - CodecDirection direction, - CodecConfig *record) { - // first check if same record exists - // if exists remove the record by complete section - std::unique_lock lock(config_lock); - bool record_removed = false; - std::vector sections; - - if(btif_bap_find_sections(bd_addr, rec_type, context_type, - direction, record, §ions)) { - for (auto it = sections.begin(); - it != sections.end(); it++) { - config_remove_section(config, (*it)); - } - record_removed = true; - btif_bap_config_flush(); - } - return record_removed; -} - -bool btif_bap_remove_record_by_context(const RawAddress& bd_addr, - btif_bap_record_type_t rec_type, - uint16_t context_type, - CodecDirection direction) { - // first check if same record exists - // if exists remove the record by complete section - std::unique_lock lock(config_lock); - bool record_removed = false; - std::vector sections; - - if(btif_bap_find_sections(bd_addr, rec_type, context_type, - direction, nullptr, §ions)) { - for (auto it = sections.begin(); - it != sections.end(); it++) { - config_remove_section(config, (*it)); - } - record_removed = true; - btif_bap_config_flush(); - } - return record_removed; -} - -bool btif_bap_remove_all_records(const RawAddress& bd_addr) { - // loop through the file if any record is found delete it - std::unique_lock lock(config_lock); - std::string addrstr = bd_addr.ToString(); - const char* bdstr = addrstr.c_str(); - bool record_removed = false; - const config_section_node_t* snode = config_section_begin(config); - for(; snode != config_section_end(config); - snode = config_section_next(snode)) { - const char* section = config_section_name(snode); - // first check the address - if(strcasestr(section, bdstr)) { - record_removed = true; - config_remove_section(config, section); - } - } - btif_bap_config_flush(); - return record_removed; -} - -bool btif_bap_get_records(const RawAddress& bd_addr, - btif_bap_record_type_t rec_type, - uint16_t context_type, - CodecDirection direction, - std::vector *pac_records) { - std::unique_lock lock(config_lock); - std::vector sections; - - if(btif_bap_find_sections(bd_addr, rec_type, context_type, - direction, nullptr, §ions)) { - for (auto it = sections.begin(); - it != sections.end(); it++) { - CodecConfig record; - memset(&record, 0, sizeof(record)); - - if(config_has_key(config, (*it), BAP_SAMP_FREQS_KEY)) { - record.sample_rate = static_cast - (config_get_uint16(config, (*it), - BAP_SAMP_FREQS_KEY, - 0x00)); - } - - if (config_has_key(config, (*it), BAP_LC3Q_SUP_KEY)) { - bool lc3q_sup = false; - const char* is_lc3q_sup = config_get_string(config, (*it), - BAP_LC3Q_SUP_KEY, - ""); - if(!strcmp(is_lc3q_sup, "true")) { - lc3q_sup = true; - } - LOG(WARNING) << __func__ << ": lc3q_sup: " << lc3q_sup; - if (lc3q_sup) { - UpdateCapaVendorMetaDataLc3QPref(&record, lc3q_sup); - } - } - - if(config_has_key(config, (*it), BAP_LC3Q_VER_KEY)) { - uint16_t lc3q_ver = config_get_uint16(config, (*it), - BAP_LC3Q_VER_KEY, - 0x00); - LOG(WARNING) << __func__ << ": lc3q_ver: " << lc3q_ver; - UpdateCapaVendorMetaDataLc3QVer(&record, lc3q_ver); - } - - record.codec_type = CodecIndex::CODEC_INDEX_SOURCE_LC3; - if(rec_type == REC_TYPE_CAPABILITY) { - - if(config_has_key(config, (*it), BAP_SUPP_FRM_DURATIONS_KEY)) { - uint16_t supp_frames = config_get_uint16(config, (*it), - BAP_SUPP_FRM_DURATIONS_KEY, - 0x00); - UpdateCapaSupFrameDurations(&record, supp_frames); - } - - // update chnl supp octs per frame - if(config_has_key(config, (*it), BAP_SUP_MIN_OCTS_PER_FRAME_KEY) && - config_has_key(config, (*it), BAP_SUP_MAX_OCTS_PER_FRAME_KEY)) { - uint16_t sup_min_octs = config_get_uint16(config, (*it), - BAP_SUP_MIN_OCTS_PER_FRAME_KEY, - 0x00); - uint16_t sup_max_octs = config_get_uint16(config, (*it), - BAP_SUP_MAX_OCTS_PER_FRAME_KEY, - 0x00); - UpdateCapaSupOctsPerFrame(&record, sup_min_octs | sup_max_octs << 16); - } - - // update max supp codec frames per sdu - if(config_has_key(config, (*it), BAP_MAX_SUP_CODEC_FRAMES_PER_SDU)) { - uint16_t max_sup_codec_frames_per_sdu = config_get_uint16(config, (*it), - BAP_MAX_SUP_CODEC_FRAMES_PER_SDU, - 0x00); - UpdateCapaMaxSupLc3Frames(&record, max_sup_codec_frames_per_sdu); - } - - // update preferred context type. - if(config_has_key(config, (*it), BAP_CONTEXT_TYPE_KEY)) { - uint16_t context_type = config_get_uint16(config, (*it), - BAP_CONTEXT_TYPE_KEY, - 0x00); - UpdateCapaPreferredContexts(&record, context_type); - } - } else { - - if(config_has_key(config, (*it), BAP_CONF_FRAME_DUR_KEY)) { - uint16_t conf_frames = config_get_uint16(config, (*it), - BAP_CONF_FRAME_DUR_KEY, - 0x00); - UpdateFrameDuration(&record, conf_frames); - } - - if(config_has_key(config, (*it), BAP_CONF_OCTS_PER_FRAME_KEY)) { - uint16_t conf_octs_per_frame = config_get_uint16(config, (*it), - BAP_CONF_OCTS_PER_FRAME_KEY, - 0x00); - UpdateOctsPerFrame(&record, conf_octs_per_frame); - } - - if(config_has_key(config, (*it), BAP_LC3_FRAMES_PER_SDU_KEY)) { - uint16_t lc3_frms_per_sdu = config_get_uint16(config, (*it), - BAP_LC3_FRAMES_PER_SDU_KEY, - 0x00); - UpdateLc3BlocksPerSdu(&record, lc3_frms_per_sdu); - } - } - pac_records->push_back(record); - } - } - - if(pac_records->size()) { - return true; - } else { - return false; - } -} - -bool btif_bap_add_audio_loc(const RawAddress& bd_addr, - CodecDirection direction, uint32_t audio_loc) { - // first check if same already exists - // if exists update the same entry - // audio location will always be stored @ 0th index - // form the section entry ( bd address plus index) - std::string addrstr = bd_addr.ToString(); - const char* bdstr = addrstr.c_str(); - char section[MAX_SECTION_LEN]; - char index[MAX_INDEX_LEN]; - snprintf(index, sizeof(index), ":%02x", 0); - strlcpy(section, bdstr, sizeof(section)); - strlcat(section, index, sizeof(section)); - if(direction == CodecDirection::CODEC_DIR_SRC) { - config_set_int(config, section, BAP_SRC_LOCATIONS_KEY, audio_loc); - } else { - config_set_int(config, section, BAP_SINK_LOCATIONS_KEY, audio_loc); - } - btif_bap_config_save(); - return true; -} - -bool btif_bap_rem_audio_loc(const RawAddress& bd_addr, - CodecDirection direction) { - // first check if same record already exists - // if exists remove the record by complete section - std::string addrstr = bd_addr.ToString(); - const char* bdstr = addrstr.c_str(); - char section[MAX_SECTION_LEN]; - char index[MAX_INDEX_LEN]; - snprintf(index, sizeof(index), ":%02x", 0); - strlcpy(section, bdstr, sizeof(section)); - strlcat(section, index, sizeof(section)); - if(direction == CodecDirection::CODEC_DIR_SRC) { - config_remove_key(config, section, "BAP_SRC_LOCATIONS_KEY"); - } else { - config_remove_key(config, section, "BAP_SINK_LOCATIONS_KEY"); - } - btif_bap_config_flush(); - return true; -} - -bool btif_bap_add_supp_contexts(const RawAddress& bd_addr, - uint32_t supp_contexts) { - // first check if same already exists - // if exists update the same entry - // supp contexts will always be stored @ 0th index - // form the section entry ( bd address plus index) - std::string addrstr = bd_addr.ToString(); - const char* bdstr = addrstr.c_str(); - char section[MAX_SECTION_LEN]; - char index[MAX_INDEX_LEN]; - snprintf(index, sizeof(index), ":%02x", 0); - strlcpy(section, bdstr, sizeof(section)); - strlcat(section, index, sizeof(section)); - LOG(WARNING) << __func__ << " supp_contexts " << supp_contexts; - config_set_uint64(config, section, - BAP_SUP_AUDIO_CONTEXTS_KEY, supp_contexts); - btif_bap_config_save(); - return true; -} - -bool btif_bap_get_supp_contexts(const RawAddress& bd_addr, - uint32_t *supp_contexts) { - std::string addrstr = bd_addr.ToString(); - const char* bdstr = addrstr.c_str(); - char section[MAX_SECTION_LEN]; - char index[MAX_INDEX_LEN]; - snprintf(index, sizeof(index), ":%02x", 0); - strlcpy(section, bdstr, sizeof(section)); - strlcat(section, index, sizeof(section)); - *supp_contexts = config_get_uint64(config, section, - BAP_SUP_AUDIO_CONTEXTS_KEY, 0); - return true; -} - -bool btif_bap_rem_supp_contexts(const RawAddress& bd_addr) { - std::string addrstr = bd_addr.ToString(); - const char* bdstr = addrstr.c_str(); - char section[MAX_SECTION_LEN]; - char index[MAX_INDEX_LEN]; - snprintf(index, sizeof(index), ":%02x", 0); - strlcpy(section, bdstr, sizeof(section)); - strlcat(section, index, sizeof(section)); - config_remove_key(config, section, BAP_SUP_AUDIO_CONTEXTS_KEY); - btif_bap_config_flush(); - return true; -} diff --git a/le_audio/system/bt/btif/src/btif_bap_uclient.cc b/le_audio/system/bt/btif/src/btif_bap_uclient.cc deleted file mode 100644 index 7a049a5253c6c1475c2ddc65e9c64bc47c0ad981..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/src/btif_bap_uclient.cc +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/****************************************************************************** - * - * 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 "bta_closure_api.h" -#include "bta_bap_uclient_api.h" -#include "btif_common.h" -#include "btif_storage.h" -#include "osi/include/thread.h" -#include "btif_bap_codec_utils.h" - -#include "osi/include/properties.h" - -extern void do_in_bta_thread(const base::Location& from_here, - const base::Closure& task); -#include -#include -#include -#include -#include -#include -#include -#include "btif_api.h" - -using base::Bind; -using base::Unretained; -using bluetooth::bap::ucast::UcastClient; -using bluetooth::bap::pacs::CodecConfig; -using bluetooth::bap::pacs::ConnectionState; -using bluetooth::bap::ucast::UcastClientCallbacks; -using bluetooth::bap::ucast::UcastClientInterface; -using bluetooth::bap::ucast::StreamConnect; -using bluetooth::bap::ucast::StreamType; -using bluetooth::bap::ucast::StreamStateInfo; -using bluetooth::bap::ucast::StreamConfigInfo; -using bluetooth::bap::ucast::StreamReconfig; - -namespace bluetooth { -namespace bap { -namespace ucast { - -class UcastClientInterfaceImpl; -static std::unique_ptr UcastClientInstance = nullptr; - -class UcastClientInterfaceImpl - : public UcastClientInterface, - public UcastClientCallbacks { - ~UcastClientInterfaceImpl() = default; - void Init(UcastClientCallbacks* client_callbacks) override { - if(is_initialized) { - LOG(WARNING) << __func__ << " Already initialized, return"; - return; - } - is_initialized = true; - callbacks = client_callbacks; - char value[PROPERTY_VALUE_MAX]; - if(property_get("persist.vendor.service.bt.bap.enable_ucast", value, "false") - && !strcmp(value, "true")) { - LOG(INFO) << __func__ << " Registering PACS UUID "; - btif_register_uuid_srvc_disc(Uuid::FromString("1850")); - btif_register_uuid_srvc_disc(Uuid::FromString("184E")); - } - do_in_bta_thread( FROM_HERE, Bind(&UcastClient::Initialize, this)); - } - - void OnStreamState(const RawAddress &address, - std::vector streams_state_info) override { - if(!is_initialized) return; - do_in_jni_thread(FROM_HERE, Bind(&UcastClientCallbacks::OnStreamState, - Unretained(callbacks), address, - streams_state_info)); - } - - void OnStreamConfig(const RawAddress &address, - std::vector streams_config_info) override { - if(!is_initialized) return; - do_in_jni_thread(FROM_HERE, Bind(&UcastClientCallbacks::OnStreamConfig, - Unretained(callbacks), - address, streams_config_info)); - } - - void OnStreamAvailable(const RawAddress &address, - uint16_t src_audio_contexts, - uint16_t sink_audio_contexts) override { - if(!is_initialized) return; - do_in_jni_thread(FROM_HERE, - Bind(&UcastClientCallbacks::OnStreamAvailable, - Unretained(callbacks), - address, src_audio_contexts, - sink_audio_contexts)); - } - - void Reconfigure(const RawAddress& address, - std::vector &streams_info) override { - LOG(INFO) << __func__ << " " << address; - if(!is_initialized) return; - do_in_bta_thread(FROM_HERE, Bind(&UcastClient::Reconfigure, - Unretained(UcastClient::Get()), - address, streams_info)); - } - - void Start(const RawAddress& address, - std::vector &streams_info) override { - LOG(INFO) << __func__ << " " << address; - if(!is_initialized) return; - do_in_bta_thread(FROM_HERE, Bind(&UcastClient::Start, - Unretained(UcastClient::Get()), - address, streams_info)); - } - - void Connect(std::vector &address, bool is_direct, - std::vector &streams_info) override { - for (auto it = address.begin(); it != address.end(); it++) { - LOG(INFO) << __func__ << " " << (*it); - } - if(!is_initialized) return; - do_in_bta_thread(FROM_HERE, Bind(&UcastClient::Connect, - Unretained(UcastClient::Get()), - address, is_direct, streams_info)); - } - - void Disconnect(const RawAddress& address, - std::vector &streams_info) override { - LOG(INFO) << __func__ << " " << address; - if(!is_initialized) return; - do_in_bta_thread(FROM_HERE, Bind(&UcastClient::Disconnect, - Unretained(UcastClient::Get()), - address, streams_info)); - } - - void Stop(const RawAddress& address, - std::vector &streams_info) override { - LOG(INFO) << __func__ << " " << address; - if(!is_initialized) return; - do_in_bta_thread(FROM_HERE, Bind(&UcastClient::Stop, - Unretained(UcastClient::Get()), - address, streams_info)); - } - - void UpdateStream(const RawAddress& address, - std::vector &update_streams) override { - LOG(INFO) << __func__ << " " << address; - if(!is_initialized) return; - do_in_bta_thread(FROM_HERE, Bind(&UcastClient::UpdateStream, - Unretained(UcastClient::Get()), - address, update_streams)); - } - - void Cleanup() override { - if(!is_initialized) return; - do_in_bta_thread(FROM_HERE, Bind(&UcastClient::CleanUp)); - is_initialized = false; - } - - private: - bool is_initialized = false;; - UcastClientCallbacks* callbacks; -}; - -UcastClientInterface* btif_bap_uclient_get_interface() { - if (!UcastClientInstance) - UcastClientInstance.reset(new UcastClientInterfaceImpl()); - return UcastClientInstance.get(); -} - -} // namespace ucast -} // namespace bap -} // namespace bluetooth diff --git a/le_audio/system/bt/btif/src/btif_bap_uclient_test.cc b/le_audio/system/bt/btif/src/btif_bap_uclient_test.cc deleted file mode 100644 index ffa3745633d253e5846693118ee4c18637fe2dfc..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/src/btif_bap_uclient_test.cc +++ /dev/null @@ -1,2971 +0,0 @@ -/****************************************************************************** - * - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - -#include "bta_closure_api.h" -#include "bta_bap_uclient_api.h" -#include "btif_common.h" -#include "btif_storage.h" -#include "osi/include/thread.h" -#include "btif_bap_codec_utils.h" - -#include "osi/include/properties.h" - -extern void do_in_bta_thread(const base::Location& from_here, - const base::Closure& task); -#include -#include -#include -#include -#include -#include -#include -#include "btif_bap_config.h" - -using base::Bind; -using base::Unretained; -using bluetooth::bap::ucast::UcastClient; -using bluetooth::bap::pacs::CodecConfig; -using bluetooth::bap::pacs::ConnectionState; -using bluetooth::bap::ucast::UcastClientCallbacks; -using bluetooth::bap::ucast::UcastClientInterface; -using bluetooth::bap::ucast::StreamConnect; -using bluetooth::bap::ucast::StreamType; -using bluetooth::bap::ucast::StreamStateInfo; -using bluetooth::bap::ucast::StreamConfigInfo; -using bluetooth::bap::ucast::StreamReconfig; - -using bluetooth::bap::pacs::CodecIndex; -using bluetooth::bap::pacs::CodecPriority; -using bluetooth::bap::pacs::CodecSampleRate; -using bluetooth::bap::pacs::CodecFrameDuration; -using bluetooth::bap::pacs::CodecChannelMode; -using bluetooth::bap::ucast::CodecQosConfig; -using bluetooth::bap::ucast::CISConfig; -using bluetooth::bap::ucast::CONTENT_TYPE_MEDIA; -using bluetooth::bap::ucast::CONTENT_TYPE_CONVERSATIONAL; -using bluetooth::bap::ucast::CONTENT_TYPE_GAME; -using bluetooth::bap::ucast::CONTENT_TYPE_LIVE; -using bluetooth::bap::ucast::CONTENT_TYPE_UNSPECIFIED; -using bluetooth::bap::ucast::ASE_DIRECTION_SRC; -using bluetooth::bap::ucast::ASE_DIRECTION_SINK; -using bluetooth::bap::ucast::StreamReconfigType; -using bluetooth::bap::ucast::ASCSConfig; - -static thread_t *test_thread; -static UcastClientInterface* sUcastClientInterface = nullptr; -static RawAddress bap_bd_addr; - -extern bluetooth::bap::pacs::PacsClientInterface* btif_pacs_client_get_interface(); - -class UcastClientCallbacksImpl : public UcastClientCallbacks { - public: - ~UcastClientCallbacksImpl() = default; - void OnStreamState(const RawAddress &address, - std::vector streams_state_info) override { - for (auto it = streams_state_info.begin(); - it != streams_state_info.end(); it++) { - LOG(WARNING) << __func__ << " stream type " << (it->stream_type.type); - LOG(WARNING) << __func__ << " stream dir " << loghex(it->stream_type.direction); - LOG(WARNING) << __func__ << " stream state " << static_cast (it->stream_state); - } - } - void OnStreamConfig(const RawAddress &address, - std::vector streams_config_info) override { - LOG(WARNING) << __func__; - for (auto it = streams_config_info.begin(); - it != streams_config_info.end(); it++) { - LOG(WARNING) << __func__ << " stream type " << (it->stream_type.type); - LOG(WARNING) << __func__ << " stream dir " << loghex(it->stream_type.direction); - LOG(WARNING) << __func__ << " location " << static_cast (it->audio_location); - btif_bap_add_record(address, REC_TYPE_CONFIGURATION, - it->stream_type.type, - static_cast (it->stream_type.direction), - &it->codec_config); - - std::vector acm_pac_records; - - btif_bap_get_records(address, - REC_TYPE_CAPABILITY, - CONTENT_TYPE_MEDIA | - CONTENT_TYPE_UNSPECIFIED, - static_cast - (it->stream_type.direction), - &acm_pac_records); - - LOG(WARNING) << __func__ << " acm len to be 3" << (acm_pac_records.size()); - - std::vector config_pac_records; - btif_bap_get_records(address, - REC_TYPE_CONFIGURATION, - CONTENT_TYPE_MEDIA, - static_cast - (it->stream_type.direction), - &config_pac_records); - - LOG(WARNING) << __func__ << " configs len to be 1" << (config_pac_records.size()); - - btif_bap_remove_record_by_context (address, REC_TYPE_CONFIGURATION, - it->stream_type.type, - static_cast - (it->stream_type.direction)); - - config_pac_records.clear(); - btif_bap_get_records(address, - REC_TYPE_CONFIGURATION, - CONTENT_TYPE_MEDIA, - static_cast - (it->stream_type.direction), - &config_pac_records); - - LOG(WARNING) << __func__ << " configs len to be 0" << (config_pac_records.size()); - -#if 0 - btif_bap_remove_record_by_context (address, REC_TYPE_CAPABILITY, - CONTENT_TYPE_MEDIA | - CONTENT_TYPE_UNSPECIFIED, - static_cast - (it->stream_type.direction)); - - acm_pac_records.clear(); - btif_bap_get_records(address, - REC_TYPE_CAPABILITY, - CONTENT_TYPE_MEDIA | - CONTENT_TYPE_UNSPECIFIED, - static_cast - (it->stream_type.direction), - &acm_pac_records); - - LOG(WARNING) << __func__ << " acm len to be 0" << (acm_pac_records.size()); -#endif - } - } - void OnStreamAvailable(const RawAddress &address, - uint16_t src_audio_contexts, - uint16_t sink_audio_contexts) override { - LOG(WARNING) << __func__; - } -}; - -static UcastClientCallbacksImpl sUcastClientCallbacks; - -static void event_test_bap_uclient(UNUSED_ATTR void* context) { - LOG(INFO) << __func__ << " start " ; - sUcastClientInterface = bluetooth::bap::ucast::btif_bap_uclient_get_interface(); - sUcastClientInterface->Init(&sUcastClientCallbacks); - sleep(1); - - StreamConnect conn_info; - CodecQosConfig codec_qos_config; - codec_qos_config.codec_config.codec_type = CodecIndex::CODEC_INDEX_SOURCE_LC3; - codec_qos_config.codec_config.codec_priority = - CodecPriority::CODEC_PRIORITY_DEFAULT; - codec_qos_config.codec_config.sample_rate = - CodecSampleRate::CODEC_SAMPLE_RATE_48000; - codec_qos_config.codec_config.channel_mode = - CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - //Frame_Duration - UpdateFrameDuration(&codec_qos_config.codec_config, - static_cast(CodecFrameDuration::FRAME_DUR_10)); - // LC3_Blocks_Per_SDU - UpdateLc3BlocksPerSdu(&codec_qos_config.codec_config, 1); - UpdateOctsPerFrame(&codec_qos_config.codec_config, 100); - codec_qos_config.qos_config.cig_config = { - .cig_id = 1, - .cis_count = 2, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x10, 0x27, 0x00}, - .sdu_interval_s_to_m = {0x10, 0x27, 0x00} - }; - CISConfig cis_config_1 = { - .cis_id = 0, - .max_sdu_m_to_s = 100, - .max_sdu_s_to_m = 0, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x02, - .rtn_s_to_m = 0x02 - }; - CISConfig cis_config_2 = { - .cis_id = 1, - .max_sdu_m_to_s = 100, - .max_sdu_s_to_m = 0, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x02, - .rtn_s_to_m = 0x02 - }; - codec_qos_config.qos_config.cis_configs.push_back(cis_config_1); - codec_qos_config.qos_config.cis_configs.push_back(cis_config_2); - - ASCSConfig ascs_config = { - .cig_id = 1, - .cis_id = 0, - .bi_directional = false, - .presentation_delay = {0x20, 0x4E, 0x00} - }; - codec_qos_config.qos_config.ascs_configs.push_back(ascs_config); - conn_info.stream_type.type = 0x0004; // media - conn_info.stream_type.direction = ASE_DIRECTION_SINK; - conn_info.stream_type.audio_context = - CONTENT_TYPE_MEDIA; - conn_info.codec_qos_config_pair.push_back(codec_qos_config); - std::vector streams; - streams.push_back(conn_info); - - ASCSConfig ascs_config_2 = { - .cig_id = 1, - .cis_id = 1, - .bi_directional = false, - .presentation_delay = {0x20, 0x4E, 0x00} - }; - - codec_qos_config.qos_config.ascs_configs.clear(); - codec_qos_config.qos_config.ascs_configs.push_back(ascs_config_2); - StreamConnect conn_info_2; - conn_info_2.stream_type.type = 0x0004; // media - conn_info_2.stream_type.direction = ASE_DIRECTION_SINK; - conn_info_2.stream_type.audio_context = - CONTENT_TYPE_MEDIA; - conn_info_2.codec_qos_config_pair.push_back(codec_qos_config); - std::vector streams_2; - streams_2.push_back(conn_info_2); - - // reconfig information - std::vector reconf_streams; - codec_qos_config.qos_config.ascs_configs[0].cis_id = 1; - UpdateFrameDuration(&codec_qos_config.codec_config, - static_cast(CodecFrameDuration::FRAME_DUR_7_5)); - - codec_qos_config.qos_config.cig_config = { - .cig_id = 1, - .cis_count = 2, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x4C, 0x1D, 0x00}, - .sdu_interval_s_to_m = {0x4C, 0x1D, 0x00} - }; - - StreamReconfig reconf_info; - reconf_info.stream_type.type = 0x0004; // media - reconf_info.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_info.stream_type.direction = ASE_DIRECTION_SINK; - reconf_info.codec_qos_config_pair.push_back(codec_qos_config); - reconf_streams.push_back(reconf_info); - - std::vector reconf_qos_streams; - StreamReconfig reconf_qos_info; - reconf_qos_info.stream_type.type = 0x0004; // media - reconf_qos_info.reconf_type = StreamReconfigType::QOS_CONFIG; - reconf_qos_info.stream_type.direction = ASE_DIRECTION_SINK; - codec_qos_config.qos_config.cis_configs.clear(); - - cis_config_1.rtn_m_to_s = 1; - cis_config_1.rtn_s_to_m = 1; - cis_config_2.rtn_m_to_s = 1; - cis_config_2.rtn_s_to_m = 1; - codec_qos_config.qos_config.cis_configs.push_back(cis_config_1); - codec_qos_config.qos_config.cis_configs.push_back(cis_config_2); - reconf_qos_info.codec_qos_config_pair.push_back(codec_qos_config); - reconf_qos_streams.push_back(reconf_qos_info); - - StreamType type_1 = { .type = 0x0004, - .direction = ASE_DIRECTION_SINK - }; - - RawAddress bap_bd_addr_2; - RawAddress::FromString("00:02:5B:00:FF:01", bap_bd_addr_2); - - std::vector start_streams; - start_streams.push_back(type_1); - - char bap_test[150] = "generic"; - - property_get("persist.vendor.service.bt.bap.test", bap_test, "generic"); - - LOG(INFO) << __func__ << " property" << bap_test; - - if(!strcmp(bap_test, "generic")) { - LOG(INFO) << __func__ << " going for generic test case"; - LOG(INFO) << __func__ << " going for connect"; - sUcastClientInterface->Connect( bap_bd_addr, true, streams); - - sUcastClientInterface->Connect( bap_bd_addr_2, true, streams_2); - - sleep(10); - - LOG(INFO) << __func__ << " going for stream start 1 "; - //sUcastClientInterface->Start( bap_bd_addr, start_streams); - - LOG(INFO) << __func__ << " going for stream start 2"; - //sUcastClientInterface->Start( bap_bd_addr_2, start_streams); - - sleep(10); - - LOG(INFO) << __func__ << "going for stream disconnect 1 "; - sUcastClientInterface->Disconnect( bap_bd_addr, start_streams); - LOG(INFO) << __func__ << "going for stream disconnect 2 "; - sUcastClientInterface->Disconnect( bap_bd_addr_2, start_streams); - - } else if(!strcmp(bap_test, "stereo_recording_stereo_dual_cis")) { - LOG(INFO) << __func__ << " going for rxonly test case"; - LOG(INFO) << __func__ << " going for connect"; - StreamConnect conn_info_media_recording; - - CodecQosConfig codec_qos_config_media_rx_1; - CodecQosConfig codec_qos_config_media_rx_2; - - CISConfig cis_config_1_media_rx = { - .cis_id = 0, - .max_sdu_m_to_s = 0, - .max_sdu_s_to_m = 100, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x05, - .rtn_s_to_m = 0x05 - }; - - CISConfig cis_config_2_media_rx = { - .cis_id = 1, - .max_sdu_m_to_s = 0, - .max_sdu_s_to_m = 100, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x05, - .rtn_s_to_m = 0x05 - }; - - CISConfig cis_config_1_media_rx_2 = { - .cis_id = 0, - .max_sdu_m_to_s = 0, - .max_sdu_s_to_m = 200, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x05, - .rtn_s_to_m = 0x05 - }; - - ASCSConfig ascs_config_1 = { - .cig_id = 1, - .cis_id = 0, - .bi_directional = false, - .presentation_delay = {0x20, 0x4E, 0x00} - }; - - ASCSConfig ascs_config_2 = { - .cig_id = 1, - .cis_id = 1, - .bi_directional = false, - .presentation_delay = {0x20, 0x4E, 0x00} - }; - - codec_qos_config_media_rx_1.codec_config.codec_type = - CodecIndex::CODEC_INDEX_SOURCE_LC3; - codec_qos_config_media_rx_1.codec_config.codec_priority = - CodecPriority::CODEC_PRIORITY_DEFAULT; - codec_qos_config_media_rx_1.codec_config.sample_rate = - CodecSampleRate::CODEC_SAMPLE_RATE_48000; - codec_qos_config_media_rx_1.codec_config.channel_mode = - CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - //Frame_Duration - UpdateFrameDuration(&codec_qos_config_media_rx_1.codec_config, - static_cast(CodecFrameDuration::FRAME_DUR_10)); - // LC3_Blocks_Per_SDU - UpdateLc3BlocksPerSdu(&codec_qos_config_media_rx_1.codec_config, 1); - UpdateOctsPerFrame(&codec_qos_config_media_rx_1.codec_config, 100); - - - codec_qos_config_media_rx_2 = codec_qos_config_media_rx_1; - UpdateOctsPerFrame(&codec_qos_config_media_rx_2.codec_config, 200); - - codec_qos_config_media_rx_1.qos_config.cig_config = { - .cig_id = 1, - .cis_count = 2, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x10, 0x27, 0x00}, - .sdu_interval_s_to_m = {0x10, 0x27, 0x00} - }; - - codec_qos_config_media_rx_1.qos_config.cis_configs.push_back(cis_config_1_media_rx); - codec_qos_config_media_rx_1.qos_config.cis_configs.push_back(cis_config_2_media_rx); - - codec_qos_config_media_rx_1.qos_config.ascs_configs.push_back(ascs_config_1); - codec_qos_config_media_rx_1.qos_config.ascs_configs.push_back(ascs_config_2); - - codec_qos_config_media_rx_2.qos_config.cig_config = { - .cig_id = 1, - .cis_count = 1, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x10, 0x27, 0x00}, - .sdu_interval_s_to_m = {0x10, 0x27, 0x00} - }; - - codec_qos_config_media_rx_2.qos_config.cis_configs.push_back(cis_config_1_media_rx_2); - - codec_qos_config_media_rx_2.qos_config.ascs_configs.push_back(ascs_config_1); - - StreamType type_media_rx = { .type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_LIVE, - .direction = ASE_DIRECTION_SRC - }; - - conn_info_media_recording.stream_type.type = CONTENT_TYPE_MEDIA; - conn_info_media_recording.stream_type.audio_context = CONTENT_TYPE_LIVE; - conn_info_media_recording.stream_type.direction = ASE_DIRECTION_SRC; - conn_info_media_recording.codec_qos_config_pair.push_back(codec_qos_config_media_rx_1); - conn_info_media_recording.codec_qos_config_pair.push_back(codec_qos_config_media_rx_2); - - std::vector media_rx_streams; - media_rx_streams.push_back(conn_info_media_recording); - - std::vector streams; - streams.push_back(type_media_rx); - - - sUcastClientInterface->Connect( bap_bd_addr, true, media_rx_streams); - - sleep(15); - - LOG(INFO) << __func__ << " going for stream start 1 "; - sUcastClientInterface->Start( bap_bd_addr, streams); - - sleep(10); - - sUcastClientInterface->Stop( bap_bd_addr, streams); - - sleep(10); - - LOG(INFO) << __func__ << "going for stream disconnect 1 "; - sUcastClientInterface->Disconnect( bap_bd_addr, streams); - - } else if(!strcmp(bap_test, "dual_streams_media_tx_voice_rx")) { - StreamConnect conn_info_media; - StreamConnect conn_info_gaming; - - // reconfig information - CodecQosConfig codec_qos_config_media_tx_1; - CodecQosConfig codec_qos_config_gaming_tx; - CodecQosConfig codec_qos_config_gaming_tx_rx; - - CISConfig cis_config_1_media_tx = { - .cis_id = 0, - .max_sdu_m_to_s = 155, - .max_sdu_s_to_m = 0, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x02, - .rtn_s_to_m = 0x02 - }; - - CISConfig cis_config_2_media_tx = { - .cis_id = 1, - .max_sdu_m_to_s = 155, - .max_sdu_s_to_m = 0, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x02, - .rtn_s_to_m = 0x02 - }; - - CISConfig cis_config_1_gaming_tx = { - .cis_id = 0, - .max_sdu_m_to_s = 100, - .max_sdu_s_to_m = 0, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x02, - .rtn_s_to_m = 0x02 - }; - - CISConfig cis_config_2_gaming_tx = { - .cis_id = 1, - .max_sdu_m_to_s = 100, - .max_sdu_s_to_m = 0, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x02, - .rtn_s_to_m = 0x02 - }; - - CISConfig cis_config_1_gaming_tx_rx = { - .cis_id = 0, - .max_sdu_m_to_s = 100, - .max_sdu_s_to_m = 40, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x02, - .rtn_s_to_m = 0x02 - }; - CISConfig cis_config_2_gaming_tx_rx = { - .cis_id = 1, - .max_sdu_m_to_s = 100, - .max_sdu_s_to_m = 40, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x02, - .rtn_s_to_m = 0x02 - }; - - ASCSConfig ascs_config = { - .cig_id = 1, - .cis_id = 0, - .bi_directional = false, - .presentation_delay = {0x20, 0x4E, 0x00} - }; - - codec_qos_config_media_tx_1.codec_config.codec_type = - CodecIndex::CODEC_INDEX_SOURCE_LC3; - codec_qos_config_media_tx_1.codec_config.codec_priority = - CodecPriority::CODEC_PRIORITY_DEFAULT; - codec_qos_config_media_tx_1.codec_config.sample_rate = - CodecSampleRate::CODEC_SAMPLE_RATE_48000; - codec_qos_config_media_tx_1.codec_config.channel_mode = - CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - //Frame_Duration - UpdateFrameDuration(&codec_qos_config_media_tx_1.codec_config, - static_cast(CodecFrameDuration::FRAME_DUR_10)); - // LC3_Blocks_Per_SDU - UpdateLc3BlocksPerSdu(&codec_qos_config_media_tx_1.codec_config, 1); - UpdateOctsPerFrame(&codec_qos_config_media_tx_1.codec_config, 155); - codec_qos_config_media_tx_1.qos_config.cig_config = { - .cig_id = 1, - .cis_count = 2, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x10, 0x27, 0x00}, - .sdu_interval_s_to_m = {0x10, 0x27, 0x00} - }; - - codec_qos_config_media_tx_1.qos_config.cis_configs.push_back(cis_config_1_media_tx); - codec_qos_config_media_tx_1.qos_config.cis_configs.push_back(cis_config_2_media_tx); - - codec_qos_config_media_tx_1.qos_config.ascs_configs.push_back(ascs_config); - codec_qos_config_gaming_tx.codec_config.codec_type = - CodecIndex::CODEC_INDEX_SOURCE_LC3; - codec_qos_config_gaming_tx.codec_config.codec_priority = - CodecPriority::CODEC_PRIORITY_DEFAULT; - codec_qos_config_gaming_tx.codec_config.sample_rate = - CodecSampleRate::CODEC_SAMPLE_RATE_48000; - codec_qos_config_gaming_tx.codec_config.channel_mode = - CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - //Frame_Duration - UpdateFrameDuration(&codec_qos_config_gaming_tx.codec_config, - static_cast(CodecFrameDuration::FRAME_DUR_10)); - // LC3_Blocks_Per_SDU - UpdateLc3BlocksPerSdu(&codec_qos_config_gaming_tx.codec_config, 1); - UpdateOctsPerFrame(&codec_qos_config_gaming_tx.codec_config, 100); - codec_qos_config_gaming_tx.qos_config.cig_config = { - .cig_id = 1, - .cis_count = 2, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x10, 0x27, 0x00}, - .sdu_interval_s_to_m = {0x10, 0x27, 0x00} - }; - - codec_qos_config_gaming_tx.qos_config.cis_configs.push_back(cis_config_1_gaming_tx); - codec_qos_config_gaming_tx.qos_config.cis_configs.push_back(cis_config_2_gaming_tx); - - codec_qos_config_gaming_tx.qos_config.ascs_configs.push_back(ascs_config); - codec_qos_config_gaming_tx_rx.codec_config.codec_type = - CodecIndex::CODEC_INDEX_SOURCE_LC3; - codec_qos_config_gaming_tx_rx.codec_config.codec_priority = - CodecPriority::CODEC_PRIORITY_DEFAULT; - codec_qos_config_gaming_tx_rx.codec_config.sample_rate = - CodecSampleRate::CODEC_SAMPLE_RATE_16000; - codec_qos_config_gaming_tx_rx.codec_config.channel_mode = - CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - //Frame_Duration - UpdateFrameDuration(&codec_qos_config_gaming_tx_rx.codec_config, - static_cast(CodecFrameDuration::FRAME_DUR_10)); - // LC3_Blocks_Per_SDU - UpdateLc3BlocksPerSdu(&codec_qos_config_gaming_tx_rx.codec_config, 1); - UpdateOctsPerFrame(&codec_qos_config_gaming_tx_rx.codec_config, 40); - codec_qos_config_gaming_tx_rx.qos_config.cig_config = { - .cig_id = 2, - .cis_count = 2, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x10, 0x27, 0x00}, - .sdu_interval_s_to_m = {0x10, 0x27, 0x00} - }; - - codec_qos_config_gaming_tx_rx.qos_config.cis_configs.push_back(cis_config_1_gaming_tx_rx); - codec_qos_config_gaming_tx_rx.qos_config.cis_configs.push_back(cis_config_2_gaming_tx_rx); - ASCSConfig ascs_config_gaming = { - .cig_id = 2, - .cis_id = 0, - .bi_directional = true, - .presentation_delay = {0x20, 0x4E, 0x00} - }; - codec_qos_config_gaming_tx_rx.qos_config.ascs_configs.push_back(ascs_config_gaming); - conn_info_media.stream_type.type = CONTENT_TYPE_MEDIA; - conn_info_media.stream_type.audio_context = CONTENT_TYPE_MEDIA; - conn_info_media.stream_type.direction = ASE_DIRECTION_SINK; - conn_info_media.codec_qos_config_pair.push_back(codec_qos_config_media_tx_1); - - conn_info_gaming.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - conn_info_gaming.stream_type.audio_context = - CONTENT_TYPE_CONVERSATIONAL; - conn_info_gaming.stream_type.direction = ASE_DIRECTION_SRC; - conn_info_gaming.codec_qos_config_pair.push_back(codec_qos_config_gaming_tx_rx); - - std::vector dual_streams; - dual_streams.push_back(conn_info_media); - dual_streams.push_back(conn_info_gaming); - - StreamType type_media = { .type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_MEDIA, - .direction = ASE_DIRECTION_SINK - }; - - StreamType type_voice = { .type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SRC - }; - - std::vector media_streams; - media_streams.push_back(type_media); - std::vector voice_streams; - voice_streams.push_back(type_voice); - - LOG(INFO) << __func__ << " going for generic test case"; - LOG(INFO) << __func__ << " going for connect with media tx and gaming rx"; - sUcastClientInterface->Connect( bap_bd_addr, true, dual_streams); - - //sUcastClientInterface->Connect( bap_bd_addr_2, true, streams_2); - - sleep(10); - - std::vector reconf_streams; - - StreamReconfig reconf_gaming_tx_info; - reconf_gaming_tx_info.stream_type.type = CONTENT_TYPE_MEDIA; // media - reconf_gaming_tx_info.stream_type.audio_context = CONTENT_TYPE_MEDIA; // media - reconf_gaming_tx_info.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_gaming_tx_info.stream_type.direction = ASE_DIRECTION_SINK; - reconf_gaming_tx_info.codec_qos_config_pair.push_back(codec_qos_config_gaming_tx); - - StreamReconfig reconf_gaming_tx_rx_info; - reconf_gaming_tx_rx_info.stream_type.type = CONTENT_TYPE_MEDIA; // media - reconf_gaming_tx_rx_info.stream_type.audio_context = CONTENT_TYPE_MEDIA; // media - reconf_gaming_tx_rx_info.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_gaming_tx_rx_info.stream_type.direction = ASE_DIRECTION_SINK; - reconf_gaming_tx_rx_info.codec_qos_config_pair.push_back(codec_qos_config_gaming_tx_rx); - - StreamReconfig reconf_media_info; - reconf_media_info.stream_type.type = CONTENT_TYPE_MEDIA; // media - reconf_media_info.stream_type.audio_context = CONTENT_TYPE_MEDIA; // media - reconf_media_info.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_media_info.stream_type.direction = ASE_DIRECTION_SINK; - reconf_media_info.codec_qos_config_pair.push_back(codec_qos_config_media_tx_1); - - sleep(5); - LOG(INFO) << __func__ << " going for stream start 1 "; - sUcastClientInterface->Start( bap_bd_addr, media_streams); - - // switch to Gaming tx - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, media_streams); - - sleep(5); - // reconfig the first stream - LOG(INFO) << __func__ << " going for stream codec reconfig"; - reconf_streams.clear(); - reconf_streams.push_back(reconf_gaming_tx_info); - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, media_streams); - - // switch to media tx - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, media_streams); - - sleep(5); - // reconfig the first stream - reconf_streams.clear(); - reconf_streams.push_back(reconf_media_info); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, media_streams); - - // switch to Gaming tx & rx - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, media_streams); - - sleep(5); - // reconfig the first stream - reconf_streams.clear(); - reconf_streams.push_back(reconf_gaming_tx_rx_info); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, media_streams); - sUcastClientInterface->Start( bap_bd_addr, voice_streams); - - // switch to Gaming tx (2nd time) (4th) - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, media_streams); - sUcastClientInterface->Stop( bap_bd_addr, voice_streams); - - sleep(5); - // reconfig the first stream - LOG(INFO) << __func__ << " going for stream codec reconfig"; - reconf_streams.clear(); - reconf_gaming_tx_info.reconf_type = StreamReconfigType::QOS_CONFIG; - reconf_streams.push_back(reconf_gaming_tx_info); - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, media_streams); - - - // switch to Gaming tx & rx (2nd time) (5th) - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, media_streams); - - sleep(5); - // reconfig the first stream - reconf_streams.clear(); - reconf_gaming_tx_rx_info.reconf_type = StreamReconfigType::QOS_CONFIG; - reconf_streams.push_back(reconf_gaming_tx_rx_info); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, media_streams); - sUcastClientInterface->Start( bap_bd_addr, voice_streams); - - // switch to media tx (6th) - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, media_streams); - sUcastClientInterface->Stop( bap_bd_addr, voice_streams); - - sleep(5); - // reconfig the first stream - reconf_streams.clear(); - reconf_streams.push_back(reconf_media_info); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, media_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for stream disconnect 1 "; - sUcastClientInterface->Disconnect( bap_bd_addr, media_streams); - sUcastClientInterface->Disconnect( bap_bd_addr, voice_streams); - //LOG(INFO) << __func__ << "going for stream disconnect 2 "; - //sUcastClientInterface->Disconnect( bap_bd_addr_2, start_streams); - - } else if(!strcmp(bap_test, "tri_streams_media_tx_voice_tx_voice_rx")) { - StreamConnect conn_info_media; - StreamConnect conn_info_gaming; - StreamConnect conn_info_voice_tx; - StreamConnect conn_info_voice_rx; - - // reconfig information - CodecQosConfig codec_qos_config_media_tx_1; - CodecQosConfig codec_qos_config_gaming_tx; - CodecQosConfig codec_qos_config_gaming_tx_rx; - CodecQosConfig codec_qos_config_gaming_rx; - CodecQosConfig codec_qos_config_voice_tx_rx; - - CodecQosConfig codec_qos_config_media_tx_2; - CodecQosConfig codec_qos_config_gaming_tx_2; - CodecQosConfig codec_qos_config_gaming_tx_rx_2; - CodecQosConfig codec_qos_config_gaming_rx_2; - CodecQosConfig codec_qos_config_voice_tx_rx_2; - - CISConfig cis_config_1_media_tx = { - .cis_id = 0, - .max_sdu_m_to_s = 155, - .max_sdu_s_to_m = 0, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x05, - .rtn_s_to_m = 0x05 - }; - - CISConfig cis_config_2_media_tx = { - .cis_id = 1, - .max_sdu_m_to_s = 155, - .max_sdu_s_to_m = 0, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x05, - .rtn_s_to_m = 0x05 - }; - - CISConfig cis_config_1_gaming_tx = { - .cis_id = 0, - .max_sdu_m_to_s = 100, - .max_sdu_s_to_m = 0, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x05, - .rtn_s_to_m = 0x05 - }; - - CISConfig cis_config_2_gaming_tx = { - .cis_id = 1, - .max_sdu_m_to_s = 100, - .max_sdu_s_to_m = 0, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x05, - .rtn_s_to_m = 0x05 - }; - - CISConfig cis_config_1_gaming_tx_rx = { - .cis_id = 0, - .max_sdu_m_to_s = 100, - .max_sdu_s_to_m = 40, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x05, - .rtn_s_to_m = 0x05 - }; - CISConfig cis_config_2_gaming_tx_rx = { - .cis_id = 1, - .max_sdu_m_to_s = 100, - .max_sdu_s_to_m = 40, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x05, - .rtn_s_to_m = 0x05 - }; - - CISConfig cis_config_1_voice_tx_rx = { - .cis_id = 0, - .max_sdu_m_to_s = 40, - .max_sdu_s_to_m = 40, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x05, - .rtn_s_to_m = 0x05 - }; - CISConfig cis_config_2_voice_tx_rx = { - .cis_id = 1, - .max_sdu_m_to_s = 40, - .max_sdu_s_to_m = 40, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x05, - .rtn_s_to_m = 0x05 - }; - - ASCSConfig ascs_config = { - .cig_id = 1, - .cis_id = 0, - .bi_directional = false, - .presentation_delay = {0x20, 0x4E, 0x00} - }; - - ASCSConfig ascs_config_gaming = { - .cig_id = 2, - .cis_id = 0, - .bi_directional = true, - .presentation_delay = {0x20, 0x4E, 0x00} - }; - - ASCSConfig ascs_config_voice = { - .cig_id = 3, - .cis_id = 0, - .bi_directional = true, - .presentation_delay = {0x20, 0x4E, 0x00} - }; - - ASCSConfig ascs_config_2 = { - .cig_id = 1, - .cis_id = 1, - .bi_directional = false, - .presentation_delay = {0x20, 0x4E, 0x00} - }; - - ASCSConfig ascs_config_gaming_2 = { - .cig_id = 2, - .cis_id = 1, - .bi_directional = true, - .presentation_delay = {0x20, 0x4E, 0x00} - }; - - ASCSConfig ascs_config_voice_2 = { - .cig_id = 3, - .cis_id = 1, - .bi_directional = true, - .presentation_delay = {0x20, 0x4E, 0x00} - }; - - codec_qos_config_media_tx_1.codec_config.codec_type = - CodecIndex::CODEC_INDEX_SOURCE_LC3; - codec_qos_config_media_tx_1.codec_config.codec_priority = - CodecPriority::CODEC_PRIORITY_DEFAULT; - codec_qos_config_media_tx_1.codec_config.sample_rate = - CodecSampleRate::CODEC_SAMPLE_RATE_48000; - codec_qos_config_media_tx_1.codec_config.channel_mode = - CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - //Frame_Duration - UpdateFrameDuration(&codec_qos_config_media_tx_1.codec_config, - static_cast(CodecFrameDuration::FRAME_DUR_10)); - // LC3_Blocks_Per_SDU - UpdateLc3BlocksPerSdu(&codec_qos_config_media_tx_1.codec_config, 1); - UpdateOctsPerFrame(&codec_qos_config_media_tx_1.codec_config, 155); - codec_qos_config_media_tx_1.qos_config.cig_config = { - .cig_id = 1, - .cis_count = 2, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x10, 0x27, 0x00}, - .sdu_interval_s_to_m = {0x10, 0x27, 0x00} - }; - - codec_qos_config_media_tx_1.qos_config.cis_configs.push_back(cis_config_1_media_tx); - codec_qos_config_media_tx_1.qos_config.cis_configs.push_back(cis_config_2_media_tx); - - codec_qos_config_media_tx_1.qos_config.ascs_configs.push_back(ascs_config); - - codec_qos_config_media_tx_2 = codec_qos_config_media_tx_1; - codec_qos_config_media_tx_2.qos_config.ascs_configs.clear(); - codec_qos_config_media_tx_2.qos_config.ascs_configs.push_back(ascs_config_2); - - codec_qos_config_gaming_tx.codec_config.codec_type = - CodecIndex::CODEC_INDEX_SOURCE_LC3; - codec_qos_config_gaming_tx.codec_config.codec_priority = - CodecPriority::CODEC_PRIORITY_DEFAULT; - codec_qos_config_gaming_tx.codec_config.sample_rate = - CodecSampleRate::CODEC_SAMPLE_RATE_48000; - codec_qos_config_gaming_tx.codec_config.channel_mode = - CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - //Frame_Duration - UpdateFrameDuration(&codec_qos_config_gaming_tx.codec_config, - static_cast(CodecFrameDuration::FRAME_DUR_10)); - // LC3_Blocks_Per_SDU - UpdateLc3BlocksPerSdu(&codec_qos_config_gaming_tx.codec_config, 1); - UpdateOctsPerFrame(&codec_qos_config_gaming_tx.codec_config, 100); - codec_qos_config_gaming_tx.qos_config.cig_config = { - .cig_id = 1, - .cis_count = 2, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x10, 0x27, 0x00}, - .sdu_interval_s_to_m = {0x10, 0x27, 0x00} - }; - - codec_qos_config_gaming_tx.qos_config.cis_configs.push_back(cis_config_1_gaming_tx); - codec_qos_config_gaming_tx.qos_config.cis_configs.push_back(cis_config_2_gaming_tx); - - codec_qos_config_gaming_tx.qos_config.ascs_configs.push_back(ascs_config); - - - codec_qos_config_gaming_tx_2 = codec_qos_config_gaming_tx; - codec_qos_config_gaming_tx_2.qos_config.ascs_configs.clear(); - codec_qos_config_gaming_tx_2.qos_config.ascs_configs.push_back(ascs_config_2); - - codec_qos_config_gaming_tx_rx.codec_config.codec_type = - CodecIndex::CODEC_INDEX_SOURCE_LC3; - codec_qos_config_gaming_tx_rx.codec_config.codec_priority = - CodecPriority::CODEC_PRIORITY_DEFAULT; - codec_qos_config_gaming_tx_rx.codec_config.sample_rate = - CodecSampleRate::CODEC_SAMPLE_RATE_48000; - codec_qos_config_gaming_tx_rx.codec_config.channel_mode = - CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - //Frame_Duration - UpdateFrameDuration(&codec_qos_config_gaming_tx_rx.codec_config, - static_cast(CodecFrameDuration::FRAME_DUR_10)); - // LC3_Blocks_Per_SDU - UpdateLc3BlocksPerSdu(&codec_qos_config_gaming_tx_rx.codec_config, 1); - UpdateOctsPerFrame(&codec_qos_config_gaming_tx_rx.codec_config, 100); - codec_qos_config_gaming_tx_rx.qos_config.cig_config = { - .cig_id = 2, - .cis_count = 2, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x10, 0x27, 0x00}, - .sdu_interval_s_to_m = {0x10, 0x27, 0x00} - }; - - codec_qos_config_gaming_tx_rx.qos_config.cis_configs.push_back(cis_config_1_gaming_tx_rx); - codec_qos_config_gaming_tx_rx.qos_config.cis_configs.push_back(cis_config_2_gaming_tx_rx); - - codec_qos_config_gaming_tx_rx.qos_config.ascs_configs.push_back(ascs_config_gaming); - - codec_qos_config_gaming_tx_rx_2 = codec_qos_config_gaming_tx_rx; - codec_qos_config_gaming_tx_rx_2.qos_config.ascs_configs.clear(); - codec_qos_config_gaming_tx_rx_2.qos_config.ascs_configs.push_back(ascs_config_gaming_2); - - - codec_qos_config_gaming_rx.codec_config.codec_type = - CodecIndex::CODEC_INDEX_SOURCE_LC3; - codec_qos_config_gaming_rx.codec_config.codec_priority = - CodecPriority::CODEC_PRIORITY_DEFAULT; - codec_qos_config_gaming_rx.codec_config.sample_rate = - CodecSampleRate::CODEC_SAMPLE_RATE_16000; - codec_qos_config_gaming_rx.codec_config.channel_mode = - CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - //Frame_Duration - UpdateFrameDuration(&codec_qos_config_gaming_rx.codec_config, - static_cast(CodecFrameDuration::FRAME_DUR_10)); - // LC3_Blocks_Per_SDU - UpdateLc3BlocksPerSdu(&codec_qos_config_gaming_rx.codec_config, 1); - UpdateOctsPerFrame(&codec_qos_config_gaming_rx.codec_config, 40); - codec_qos_config_gaming_rx.qos_config.cig_config = { - .cig_id = 2, - .cis_count = 2, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x10, 0x27, 0x00}, - .sdu_interval_s_to_m = {0x10, 0x27, 0x00} - }; - - codec_qos_config_gaming_rx.qos_config.cis_configs.push_back(cis_config_1_gaming_tx_rx); - codec_qos_config_gaming_rx.qos_config.cis_configs.push_back(cis_config_2_gaming_tx_rx); - - codec_qos_config_gaming_rx.qos_config.ascs_configs.push_back(ascs_config_gaming); - - codec_qos_config_gaming_rx_2 = codec_qos_config_gaming_rx; - codec_qos_config_gaming_rx_2.qos_config.ascs_configs.clear(); - codec_qos_config_gaming_rx_2.qos_config.ascs_configs.push_back(ascs_config_gaming_2); - - - // voice tx rx - codec_qos_config_voice_tx_rx.codec_config.codec_type = - CodecIndex::CODEC_INDEX_SOURCE_LC3; - codec_qos_config_voice_tx_rx.codec_config.codec_priority = - CodecPriority::CODEC_PRIORITY_DEFAULT; - codec_qos_config_voice_tx_rx.codec_config.sample_rate = - CodecSampleRate::CODEC_SAMPLE_RATE_16000; - codec_qos_config_voice_tx_rx.codec_config.channel_mode = - CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - //Frame_Duration - UpdateFrameDuration(&codec_qos_config_voice_tx_rx.codec_config, - static_cast(CodecFrameDuration::FRAME_DUR_10)); - // LC3_Blocks_Per_SDU - UpdateLc3BlocksPerSdu(&codec_qos_config_voice_tx_rx.codec_config, 1); - UpdateOctsPerFrame(&codec_qos_config_voice_tx_rx.codec_config, 40); - codec_qos_config_voice_tx_rx.qos_config.cig_config = { - .cig_id = 3, - .cis_count = 2, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x10, 0x27, 0x00}, - .sdu_interval_s_to_m = {0x10, 0x27, 0x00} - }; - - codec_qos_config_voice_tx_rx.qos_config.cis_configs.push_back(cis_config_1_voice_tx_rx); - codec_qos_config_voice_tx_rx.qos_config.cis_configs.push_back(cis_config_2_voice_tx_rx); - - codec_qos_config_voice_tx_rx.qos_config.ascs_configs.push_back(ascs_config_voice); - - codec_qos_config_voice_tx_rx_2 = codec_qos_config_voice_tx_rx; - codec_qos_config_voice_tx_rx_2.qos_config.ascs_configs.clear(); - codec_qos_config_voice_tx_rx_2.qos_config.ascs_configs.push_back(ascs_config_voice_2); - - conn_info_media.stream_type.type = CONTENT_TYPE_MEDIA; - conn_info_media.stream_type.audio_context = CONTENT_TYPE_MEDIA; - conn_info_media.stream_type.direction = ASE_DIRECTION_SINK; - conn_info_media.codec_qos_config_pair.push_back(codec_qos_config_media_tx_1); - - conn_info_gaming.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - conn_info_gaming.stream_type.audio_context = - CONTENT_TYPE_CONVERSATIONAL; - conn_info_gaming.stream_type.direction = ASE_DIRECTION_SRC; - conn_info_gaming.codec_qos_config_pair.push_back(codec_qos_config_gaming_tx_rx); - - conn_info_voice_tx.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - conn_info_voice_tx.stream_type.audio_context = - CONTENT_TYPE_CONVERSATIONAL; - conn_info_voice_tx.stream_type.direction = ASE_DIRECTION_SINK; - conn_info_voice_tx.codec_qos_config_pair.push_back(codec_qos_config_voice_tx_rx); - - conn_info_voice_rx.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - conn_info_voice_rx.stream_type.audio_context = - CONTENT_TYPE_CONVERSATIONAL; - conn_info_voice_rx.stream_type.direction = ASE_DIRECTION_SRC; - conn_info_voice_rx.codec_qos_config_pair.push_back(codec_qos_config_voice_tx_rx); - - std::vector tri_streams; - tri_streams.push_back(conn_info_media); - tri_streams.push_back(conn_info_voice_tx); - tri_streams.push_back(conn_info_voice_rx); - - conn_info_media.codec_qos_config_pair.clear(); - conn_info_media.codec_qos_config_pair.push_back(codec_qos_config_media_tx_2); - - conn_info_voice_tx.codec_qos_config_pair.clear(); - conn_info_voice_tx.codec_qos_config_pair.push_back(codec_qos_config_voice_tx_rx_2); - - conn_info_voice_rx.codec_qos_config_pair.clear(); - conn_info_voice_rx.codec_qos_config_pair.push_back(codec_qos_config_voice_tx_rx_2); - - std::vector tri_streams_2; - tri_streams_2.push_back(conn_info_media); - tri_streams_2.push_back(conn_info_voice_tx); - tri_streams_2.push_back(conn_info_voice_rx); - - StreamType type_media = { .type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_MEDIA, - .direction = ASE_DIRECTION_SINK - }; - - StreamType type_voice_tx = { .type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SINK - }; - - StreamType type_voice_rx = { .type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SRC - }; - - - std::vector media_streams; - media_streams.push_back(type_media); - - std::vector gaming_tx_streams; - gaming_tx_streams.push_back(type_media); - - std::vector gaming_rx_streams; - gaming_rx_streams.push_back(type_voice_rx); - - std::vector voice_streams; - voice_streams.push_back(type_voice_tx); - voice_streams.push_back(type_voice_rx); - - std::vector all_three_streams; - all_three_streams.push_back(type_media); - all_three_streams.push_back(type_voice_tx); - all_three_streams.push_back(type_voice_rx); - -#if 0 - LOG(INFO) << __func__ << " going for generic test case"; - LOG(INFO) << __func__ << " going for connect with media tx and voice tx& rx"; - sUcastClientInterface->Connect( bap_bd_addr, true, tri_streams); - sUcastClientInterface->Connect( bap_bd_addr_2, true, tri_streams_2); - sleep(15); - - LOG(INFO) << __func__ << "going for stream disconnect all 3 streams "; - sUcastClientInterface->Disconnect( bap_bd_addr, all_three_streams); - sUcastClientInterface->Disconnect( bap_bd_addr_2, all_three_streams); - - sleep(5); - - LOG(INFO) << __func__ << " going for connect all 3 streams"; - sUcastClientInterface->Connect( bap_bd_addr, true, tri_streams); - sUcastClientInterface->Connect( bap_bd_addr_2, true, tri_streams_2); - - sleep(15); - - LOG(INFO) << __func__ << "going for stream disconnect all 3 streams "; - sUcastClientInterface->Disconnect( bap_bd_addr, all_three_streams); - sUcastClientInterface->Disconnect( bap_bd_addr_2, all_three_streams); - - sleep(5); -#endif - - LOG(INFO) << __func__ << " going for connect all 3 streams"; - sUcastClientInterface->Connect( bap_bd_addr, true, tri_streams); - sUcastClientInterface->Connect( bap_bd_addr_2, true, tri_streams_2); - - std::vector reconf_streams; - std::vector reconf_streams_2; - - StreamReconfig reconf_gaming_tx_info; - reconf_gaming_tx_info.stream_type.type = CONTENT_TYPE_MEDIA; - reconf_gaming_tx_info.stream_type.audio_context = CONTENT_TYPE_MEDIA; - reconf_gaming_tx_info.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_gaming_tx_info.stream_type.direction = ASE_DIRECTION_SINK; - reconf_gaming_tx_info.codec_qos_config_pair. - push_back(codec_qos_config_gaming_tx); - - StreamReconfig reconf_gaming_tx_info_2; - reconf_gaming_tx_info_2.stream_type.type = CONTENT_TYPE_MEDIA; - reconf_gaming_tx_info_2.stream_type.audio_context = CONTENT_TYPE_MEDIA; - reconf_gaming_tx_info_2.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_gaming_tx_info_2.stream_type.direction = ASE_DIRECTION_SINK; - reconf_gaming_tx_info_2.codec_qos_config_pair. - push_back(codec_qos_config_gaming_tx_2); - - StreamReconfig reconf_gaming_tx_rx_info; - reconf_gaming_tx_rx_info.stream_type.type = CONTENT_TYPE_MEDIA; - reconf_gaming_tx_rx_info.stream_type.audio_context = CONTENT_TYPE_MEDIA; - reconf_gaming_tx_rx_info.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_gaming_tx_rx_info.stream_type.direction = ASE_DIRECTION_SINK; - reconf_gaming_tx_rx_info.codec_qos_config_pair. - push_back(codec_qos_config_gaming_tx_rx); - - StreamReconfig reconf_gaming_tx_rx_info_2; - reconf_gaming_tx_rx_info_2.stream_type.type = CONTENT_TYPE_MEDIA; - reconf_gaming_tx_rx_info_2.stream_type.audio_context = CONTENT_TYPE_MEDIA; - reconf_gaming_tx_rx_info_2.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_gaming_tx_rx_info_2.stream_type.direction = ASE_DIRECTION_SINK; - reconf_gaming_tx_rx_info_2.codec_qos_config_pair. - push_back(codec_qos_config_gaming_tx_rx_2); - - StreamReconfig reconf_gaming_rx_info; - reconf_gaming_rx_info.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - reconf_gaming_rx_info.stream_type.audio_context = - CONTENT_TYPE_CONVERSATIONAL; - reconf_gaming_rx_info.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_gaming_rx_info.stream_type.direction = ASE_DIRECTION_SRC; - reconf_gaming_rx_info.codec_qos_config_pair. - push_back(codec_qos_config_gaming_rx); - - StreamReconfig reconf_gaming_rx_info_2; - reconf_gaming_rx_info_2.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - reconf_gaming_rx_info_2.stream_type.audio_context = - CONTENT_TYPE_CONVERSATIONAL; - reconf_gaming_rx_info_2.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_gaming_rx_info_2.stream_type.direction = ASE_DIRECTION_SRC; - reconf_gaming_rx_info_2.codec_qos_config_pair. - push_back(codec_qos_config_gaming_rx_2); - - StreamReconfig reconf_media_info; - reconf_media_info.stream_type.type = CONTENT_TYPE_MEDIA; - reconf_media_info.stream_type.audio_context = CONTENT_TYPE_MEDIA; - reconf_media_info.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_media_info.stream_type.direction = ASE_DIRECTION_SINK; - reconf_media_info.codec_qos_config_pair.push_back(codec_qos_config_media_tx_1); - - StreamReconfig reconf_media_info_2; - reconf_media_info_2.stream_type.type = CONTENT_TYPE_MEDIA; - reconf_media_info_2.stream_type.audio_context = CONTENT_TYPE_MEDIA; - reconf_media_info_2.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_media_info_2.stream_type.direction = ASE_DIRECTION_SINK; - reconf_media_info_2.codec_qos_config_pair.push_back(codec_qos_config_media_tx_2); - - - StreamReconfig reconf_voice_tx_info; - reconf_voice_tx_info.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - reconf_voice_tx_info.stream_type.audio_context = CONTENT_TYPE_CONVERSATIONAL; - reconf_voice_tx_info.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_voice_tx_info.stream_type.direction = ASE_DIRECTION_SINK; - reconf_voice_tx_info.codec_qos_config_pair. - push_back(codec_qos_config_voice_tx_rx); - - StreamReconfig reconf_voice_tx_info_2; - reconf_voice_tx_info_2.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - reconf_voice_tx_info_2.stream_type.audio_context = CONTENT_TYPE_CONVERSATIONAL; - reconf_voice_tx_info_2.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_voice_tx_info_2.stream_type.direction = ASE_DIRECTION_SINK; - reconf_voice_tx_info_2.codec_qos_config_pair. - push_back(codec_qos_config_voice_tx_rx_2); - - StreamReconfig reconf_voice_rx_info; - reconf_voice_rx_info.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - reconf_voice_rx_info.stream_type.audio_context = CONTENT_TYPE_CONVERSATIONAL; - reconf_voice_rx_info.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_voice_rx_info.stream_type.direction = ASE_DIRECTION_SRC; - reconf_voice_rx_info.codec_qos_config_pair. - push_back(codec_qos_config_voice_tx_rx); - - StreamReconfig reconf_voice_rx_info_2; - reconf_voice_rx_info_2.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - reconf_voice_rx_info_2.stream_type.audio_context = CONTENT_TYPE_CONVERSATIONAL; - reconf_voice_rx_info_2.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_voice_rx_info_2.stream_type.direction = ASE_DIRECTION_SRC; - reconf_voice_rx_info_2.codec_qos_config_pair. - push_back(codec_qos_config_voice_tx_rx_2); - - sleep(15); - LOG(INFO) << __func__ << " going for stream start 1 "; - sUcastClientInterface->Start( bap_bd_addr, media_streams); - sUcastClientInterface->Start( bap_bd_addr_2, media_streams); - - // switch to Gaming tx - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, media_streams); - sUcastClientInterface->Stop( bap_bd_addr_2, media_streams); - - sleep(5); - // reconfig the first stream - LOG(INFO) << __func__ << " going for stream codec reconfig"; - reconf_streams.clear(); - reconf_streams.push_back(reconf_gaming_tx_info); - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - reconf_streams_2.clear(); - reconf_streams_2.push_back(reconf_gaming_tx_info_2); - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams_2); - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, media_streams); - sUcastClientInterface->Start( bap_bd_addr_2, media_streams); - - // switch to media tx - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, media_streams); - sUcastClientInterface->Stop( bap_bd_addr_2, media_streams); - - sleep(5); - // reconfig the first stream - reconf_streams.clear(); - reconf_streams.push_back(reconf_media_info); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - reconf_streams_2.clear(); - reconf_streams_2.push_back(reconf_media_info_2); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams_2); - - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, media_streams); - sUcastClientInterface->Start( bap_bd_addr_2, media_streams); - - // switch to Gaming tx & rx - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, media_streams); - sUcastClientInterface->Stop( bap_bd_addr_2, media_streams); - - sleep(5); - // reconfig the first stream - reconf_streams.clear(); - reconf_streams.push_back(reconf_gaming_tx_rx_info); - reconf_streams.push_back(reconf_gaming_rx_info); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - reconf_streams_2.clear(); - reconf_streams_2.push_back(reconf_gaming_tx_rx_info_2); - reconf_streams_2.push_back(reconf_gaming_rx_info_2); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams_2); - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, gaming_tx_streams); - sUcastClientInterface->Start( bap_bd_addr, gaming_rx_streams); - sUcastClientInterface->Start( bap_bd_addr_2, gaming_tx_streams); - sUcastClientInterface->Start( bap_bd_addr_2, gaming_rx_streams); - - // switch to Gaming tx (2nd time) (4th) - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, gaming_tx_streams); - sUcastClientInterface->Stop( bap_bd_addr, gaming_rx_streams); - sUcastClientInterface->Stop( bap_bd_addr_2, gaming_tx_streams); - sUcastClientInterface->Stop( bap_bd_addr_2, gaming_rx_streams); - - sleep(5); - // reconfig the first stream - LOG(INFO) << __func__ << " going for stream codec reconfig"; - reconf_streams.clear(); - reconf_gaming_tx_info.reconf_type = StreamReconfigType::QOS_CONFIG; - reconf_streams.push_back(reconf_gaming_tx_info); - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - reconf_streams_2.clear(); - reconf_gaming_tx_info_2.reconf_type = StreamReconfigType::QOS_CONFIG; - reconf_streams_2.push_back(reconf_gaming_tx_info_2); - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams_2); - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, media_streams); - sUcastClientInterface->Start( bap_bd_addr_2, media_streams); - - // switch to Gaming tx & rx (2nd time) (5th) - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, media_streams); - sUcastClientInterface->Stop( bap_bd_addr_2, media_streams); - - sleep(5); - // reconfig the first stream - reconf_streams.clear(); - reconf_gaming_tx_rx_info.reconf_type = StreamReconfigType::QOS_CONFIG; - reconf_streams.push_back(reconf_gaming_tx_rx_info); - reconf_streams.push_back(reconf_gaming_rx_info); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - reconf_streams_2.clear(); - reconf_gaming_tx_rx_info_2.reconf_type = StreamReconfigType::QOS_CONFIG; - reconf_streams_2.push_back(reconf_gaming_tx_rx_info_2); - reconf_streams_2.push_back(reconf_gaming_rx_info_2); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams_2); - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, gaming_tx_streams); - sUcastClientInterface->Start( bap_bd_addr, gaming_rx_streams); - sUcastClientInterface->Start( bap_bd_addr_2, gaming_tx_streams); - sUcastClientInterface->Start( bap_bd_addr_2, gaming_rx_streams); - - // switch to media tx (6th) - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, gaming_tx_streams); - sUcastClientInterface->Stop( bap_bd_addr, gaming_rx_streams); - sUcastClientInterface->Stop( bap_bd_addr_2, gaming_tx_streams); - sUcastClientInterface->Stop( bap_bd_addr_2, gaming_rx_streams); - - sleep(5); - // reconfig the first stream - reconf_streams.clear(); - reconf_streams.push_back(reconf_media_info); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - reconf_streams_2.clear(); - reconf_streams_2.push_back(reconf_media_info_2); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams_2); - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, media_streams); - sUcastClientInterface->Start( bap_bd_addr_2, media_streams); - - // switch to voice tx & Rx (7th) - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, media_streams); - sUcastClientInterface->Stop( bap_bd_addr_2, media_streams); - - sleep(5); - // reconfig the first stream - reconf_streams.clear(); - reconf_streams.push_back(reconf_voice_rx_info); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - reconf_streams_2.clear(); - reconf_streams_2.push_back(reconf_voice_rx_info_2); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams_2); - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, voice_streams); - sUcastClientInterface->Start( bap_bd_addr_2, voice_streams); - - // switch to gaming tx (8th) - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, voice_streams); - sUcastClientInterface->Stop( bap_bd_addr_2, voice_streams); - - sleep(5); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - reconf_streams.clear(); - reconf_gaming_tx_info.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_streams.push_back(reconf_gaming_tx_info); - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - reconf_streams_2.clear(); - reconf_gaming_tx_info_2.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_streams_2.push_back(reconf_gaming_tx_info_2); - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams_2); - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, media_streams); - sUcastClientInterface->Start( bap_bd_addr_2, media_streams); - - - // switch to voice tx & Rx (9th) - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, media_streams); - sUcastClientInterface->Stop( bap_bd_addr_2, media_streams); - - sleep(5); - // reconfig the first stream - reconf_streams.clear(); - reconf_streams.push_back(reconf_voice_rx_info); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - reconf_streams_2.clear(); - reconf_streams_2.push_back(reconf_voice_rx_info_2); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams_2); - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, voice_streams); - sUcastClientInterface->Start( bap_bd_addr_2, voice_streams); - - // switch to Gaming tx & rx (10th) - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, voice_streams); - sUcastClientInterface->Stop( bap_bd_addr_2, voice_streams); - - sleep(5); - // reconfig the first stream - reconf_streams.clear(); - reconf_gaming_tx_rx_info.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_streams.push_back(reconf_gaming_tx_rx_info); - reconf_streams.push_back(reconf_gaming_rx_info); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - reconf_streams_2.clear(); - reconf_gaming_tx_rx_info_2.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_streams_2.push_back(reconf_gaming_tx_rx_info_2); - reconf_streams_2.push_back(reconf_gaming_rx_info_2); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams_2); - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, gaming_tx_streams); - sUcastClientInterface->Start( bap_bd_addr, gaming_rx_streams); - sUcastClientInterface->Start( bap_bd_addr_2, gaming_tx_streams); - sUcastClientInterface->Start( bap_bd_addr_2, gaming_rx_streams); - - - // switch to voice tx & Rx (11th) - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, gaming_tx_streams); - sUcastClientInterface->Stop( bap_bd_addr, gaming_rx_streams); - sUcastClientInterface->Stop( bap_bd_addr_2, gaming_tx_streams); - sUcastClientInterface->Stop( bap_bd_addr_2, gaming_rx_streams); - - sleep(5); - // reconfig the first stream - reconf_streams.clear(); - reconf_streams.push_back(reconf_voice_rx_info); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - reconf_streams_2.clear(); - reconf_streams_2.push_back(reconf_voice_rx_info_2); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams_2); - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, voice_streams); - sUcastClientInterface->Start( bap_bd_addr_2, voice_streams); - - // switch to media tx (12th) - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, voice_streams); - sUcastClientInterface->Stop( bap_bd_addr_2, voice_streams); - - sleep(5); - // reconfig the first stream - reconf_streams.clear(); - reconf_streams.push_back(reconf_media_info); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - reconf_streams_2.clear(); - reconf_streams_2.push_back(reconf_media_info_2); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams_2); - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, media_streams); - sUcastClientInterface->Start( bap_bd_addr_2, media_streams); - - // switch to voice tx & Rx (13th) - sleep(5); - LOG(INFO) << __func__ << " going for stream stop 1 "; - sUcastClientInterface->Stop( bap_bd_addr, media_streams); - sUcastClientInterface->Stop( bap_bd_addr_2, media_streams); - - sleep(5); - // reconfig the first stream - reconf_streams.clear(); - reconf_streams.push_back(reconf_voice_rx_info); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - reconf_streams_2.clear(); - reconf_streams_2.push_back(reconf_voice_rx_info_2); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams_2); - - sleep(5); - LOG(INFO) << __func__ << " going for stream reconfgured .start "; - sUcastClientInterface->Start( bap_bd_addr, voice_streams); - sUcastClientInterface->Start( bap_bd_addr_2, voice_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for stream disconnect 1 "; - sUcastClientInterface->Disconnect( bap_bd_addr, all_three_streams); - sUcastClientInterface->Disconnect( bap_bd_addr_2, all_three_streams); - - sleep(5); - - LOG(INFO) << __func__ << " going for connect all 3 streams"; - sUcastClientInterface->Connect( bap_bd_addr, true, tri_streams); - sUcastClientInterface->Connect( bap_bd_addr_2, true, tri_streams_2); - - sleep(15); - LOG(INFO) << __func__ << "going for stream disconnect all 3 streams "; - sUcastClientInterface->Disconnect( bap_bd_addr, all_three_streams); - - sUcastClientInterface->Disconnect( bap_bd_addr_2, all_three_streams); - - sleep(5); - - } else if(!strcmp(bap_test, "stereo_headset_dual_cis")) { - StreamConnect conn_info_media; - StreamConnect conn_info_gaming; - StreamConnect conn_info_voice_tx; - StreamConnect conn_info_voice_rx; - StreamConnect conn_info_media_recording; - - // reconfig information - CodecQosConfig codec_qos_config_media_tx_1; - CodecQosConfig codec_qos_config_media_tx_2; - CodecQosConfig codec_qos_config_gaming_tx_1; - CodecQosConfig codec_qos_config_gaming_tx_2; - CodecQosConfig codec_qos_config_gaming_tx_rx; - CodecQosConfig codec_qos_config_voice_tx_rx; - CodecQosConfig codec_qos_config_voice_tx_rx_2; - CodecQosConfig codec_qos_config_media_rx_1; - CodecQosConfig codec_qos_config_media_rx_2; - - CISConfig cis_config_1_media_tx = { - .cis_id = 0, - .max_sdu_m_to_s = 155, - .max_sdu_s_to_m = 0, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x02, - .rtn_s_to_m = 0x02 - }; - - CISConfig cis_config_2_media_tx = { - .cis_id = 1, - .max_sdu_m_to_s = 155, - .max_sdu_s_to_m = 0, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x02, - .rtn_s_to_m = 0x02 - }; - - CISConfig cis_config_1_media_tx_2 = { - .cis_id = 0, - .max_sdu_m_to_s = 310, - .max_sdu_s_to_m = 0, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x02, - .rtn_s_to_m = 0x02 - }; - - - CISConfig cis_config_1_gaming_tx = { - .cis_id = 0, - .max_sdu_m_to_s = 100, - .max_sdu_s_to_m = 0, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x02, - .rtn_s_to_m = 0x02 - }; - - CISConfig cis_config_2_gaming_tx = { - .cis_id = 1, - .max_sdu_m_to_s = 100, - .max_sdu_s_to_m = 0, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x02, - .rtn_s_to_m = 0x02 - }; - - CISConfig cis_config_1_gaming_tx_2 = { - .cis_id = 0, - .max_sdu_m_to_s = 200, - .max_sdu_s_to_m = 0, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x02, - .rtn_s_to_m = 0x02 - }; - - - CISConfig cis_config_1_gaming_tx_rx = { - .cis_id = 0, - .max_sdu_m_to_s = 100, - .max_sdu_s_to_m = 40, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x02, - .rtn_s_to_m = 0x02 - }; - CISConfig cis_config_2_gaming_tx_rx = { - .cis_id = 1, - .max_sdu_m_to_s = 100, - .max_sdu_s_to_m = 40, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x02, - .rtn_s_to_m = 0x02 - }; - - CISConfig cis_config_1_voice_tx_rx = { - .cis_id = 0, - .max_sdu_m_to_s = 80, - .max_sdu_s_to_m = 80, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x02, - .rtn_s_to_m = 0x02 - }; - CISConfig cis_config_2_voice_tx_rx = { - .cis_id = 1, - .max_sdu_m_to_s = 80, - .max_sdu_s_to_m = 80, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x02, - .rtn_s_to_m = 0x02 - }; - - CISConfig cis_config_1_media_rx = { - .cis_id = 0, - .max_sdu_m_to_s = 0, - .max_sdu_s_to_m = 100, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x05, - .rtn_s_to_m = 0x05 - }; - - CISConfig cis_config_2_media_rx = { - .cis_id = 1, - .max_sdu_m_to_s = 0, - .max_sdu_s_to_m = 100, - .phy_m_to_s = 0x02, - .phy_s_to_m = 0x02, - .rtn_m_to_s = 0x05, - .rtn_s_to_m = 0x05 - }; - ASCSConfig ascs_config_1 = { - .cig_id = 1, - .cis_id = 0, - .bi_directional = false, - .presentation_delay = {0x20, 0x4E, 0x00} - }; - - ASCSConfig ascs_config_2 = { - .cig_id = 1, - .cis_id = 1, - .bi_directional = false, - .presentation_delay = {0x20, 0x4E, 0x00} - }; - - ASCSConfig ascs_config_gaming_1 = { - .cig_id = 1, - .cis_id = 0, - .bi_directional = true, - .presentation_delay = {0x20, 0x4E, 0x00} - }; - - ASCSConfig ascs_config_gaming_2 = { - .cig_id = 1, - .cis_id = 1, - .bi_directional = true, - .presentation_delay = {0x20, 0x4E, 0x00} - }; - - ASCSConfig ascs_config_voice_1 = { - .cig_id = 3, - .cis_id = 0, - .bi_directional = true, - .presentation_delay = {0x40, 0x9C, 0x00} - }; - - ASCSConfig ascs_config_voice_2 = { - .cig_id = 3, - .cis_id = 1, - .bi_directional = true, - .presentation_delay = {0x40, 0x9C, 0x00} - }; - - ASCSConfig ascs_config_media_rx_1 = { - .cig_id = 4, - .cis_id = 0, - .bi_directional = false, - .presentation_delay = {0x20, 0x4E, 0x00} - }; - - ASCSConfig ascs_config_media_rx_2 = { - .cig_id = 4, - .cis_id = 1, - .bi_directional = false, - .presentation_delay = {0x20, 0x4E, 0x00} - }; - - codec_qos_config_media_tx_1.codec_config.codec_type = - CodecIndex::CODEC_INDEX_SOURCE_LC3; - codec_qos_config_media_tx_1.codec_config.codec_priority = - CodecPriority::CODEC_PRIORITY_DEFAULT; - codec_qos_config_media_tx_1.codec_config.sample_rate = - CodecSampleRate::CODEC_SAMPLE_RATE_48000; - codec_qos_config_media_tx_1.codec_config.channel_mode = - CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - //Frame_Duration - UpdateFrameDuration(&codec_qos_config_media_tx_1.codec_config, - static_cast(CodecFrameDuration::FRAME_DUR_10)); - // LC3_Blocks_Per_SDU - UpdateLc3BlocksPerSdu(&codec_qos_config_media_tx_1.codec_config, 1); - UpdateOctsPerFrame(&codec_qos_config_media_tx_1.codec_config, 155); - - codec_qos_config_media_tx_2 = codec_qos_config_media_tx_1; - UpdateOctsPerFrame(&codec_qos_config_media_tx_2.codec_config, 310); - - codec_qos_config_media_tx_1.qos_config.cig_config = { - .cig_id = 1, - .cis_count = 2, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x10, 0x27, 0x00}, - .sdu_interval_s_to_m = {0x10, 0x27, 0x00} - }; - - codec_qos_config_media_tx_1.qos_config.cis_configs.push_back(cis_config_1_media_tx); - codec_qos_config_media_tx_1.qos_config.cis_configs.push_back(cis_config_2_media_tx); - - codec_qos_config_media_tx_1.qos_config.ascs_configs.push_back(ascs_config_1); - codec_qos_config_media_tx_1.qos_config.ascs_configs.push_back(ascs_config_2); - - codec_qos_config_media_tx_2.qos_config.cig_config = { - .cig_id = 1, - .cis_count = 1, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x10, 0x27, 0x00}, - .sdu_interval_s_to_m = {0x10, 0x27, 0x00} - }; - - codec_qos_config_media_tx_2.qos_config.cis_configs.push_back(cis_config_1_media_tx_2); - - codec_qos_config_media_tx_2.qos_config.ascs_configs.push_back(ascs_config_1); - - codec_qos_config_gaming_tx_1.codec_config.codec_type = - CodecIndex::CODEC_INDEX_SOURCE_LC3; - codec_qos_config_gaming_tx_1.codec_config.codec_priority = - CodecPriority::CODEC_PRIORITY_DEFAULT; - codec_qos_config_gaming_tx_1.codec_config.sample_rate = - CodecSampleRate::CODEC_SAMPLE_RATE_48000; - codec_qos_config_gaming_tx_1.codec_config.channel_mode = - CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - //Frame_Duration - UpdateFrameDuration(&codec_qos_config_gaming_tx_1.codec_config, - static_cast(CodecFrameDuration::FRAME_DUR_10)); - // LC3_Blocks_Per_SDU - UpdateLc3BlocksPerSdu(&codec_qos_config_gaming_tx_1.codec_config, 1); - UpdateOctsPerFrame(&codec_qos_config_gaming_tx_1.codec_config, 100); - - codec_qos_config_gaming_tx_2 = codec_qos_config_gaming_tx_1; - UpdateOctsPerFrame(&codec_qos_config_gaming_tx_2.codec_config, 200); - - codec_qos_config_gaming_tx_1.qos_config.cig_config = { - .cig_id = 1, - .cis_count = 2, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x10, 0x27, 0x00}, - .sdu_interval_s_to_m = {0x10, 0x27, 0x00} - }; - - codec_qos_config_gaming_tx_1.qos_config.cis_configs.push_back(cis_config_1_gaming_tx); - codec_qos_config_gaming_tx_1.qos_config.cis_configs.push_back(cis_config_2_gaming_tx); - - codec_qos_config_gaming_tx_1.qos_config.ascs_configs.push_back(ascs_config_gaming_1); - codec_qos_config_gaming_tx_1.qos_config.ascs_configs.push_back(ascs_config_gaming_2); - - codec_qos_config_gaming_tx_2.qos_config.cig_config = { - .cig_id = 1, - .cis_count = 1, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x10, 0x27, 0x00}, - .sdu_interval_s_to_m = {0x10, 0x27, 0x00} - }; - - codec_qos_config_gaming_tx_2.qos_config.cis_configs.push_back(cis_config_1_gaming_tx_2); - - codec_qos_config_gaming_tx_2.qos_config.ascs_configs.push_back(ascs_config_gaming_1); - - codec_qos_config_gaming_tx_rx.codec_config.codec_type = - CodecIndex::CODEC_INDEX_SOURCE_LC3; - codec_qos_config_gaming_tx_rx.codec_config.codec_priority = - CodecPriority::CODEC_PRIORITY_DEFAULT; - codec_qos_config_gaming_tx_rx.codec_config.sample_rate = - CodecSampleRate::CODEC_SAMPLE_RATE_16000; - codec_qos_config_gaming_tx_rx.codec_config.channel_mode = - CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - //Frame_Duration - UpdateFrameDuration(&codec_qos_config_gaming_tx_rx.codec_config, - static_cast(CodecFrameDuration::FRAME_DUR_10)); - // LC3_Blocks_Per_SDU - UpdateLc3BlocksPerSdu(&codec_qos_config_gaming_tx_rx.codec_config, 1); - UpdateOctsPerFrame(&codec_qos_config_gaming_tx_rx.codec_config, 40); - codec_qos_config_gaming_tx_rx.qos_config.cig_config = { - .cig_id = 2, - .cis_count = 2, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x10, 0x27, 0x00}, - .sdu_interval_s_to_m = {0x10, 0x27, 0x00} - }; - - codec_qos_config_gaming_tx_rx.qos_config.cis_configs.push_back(cis_config_1_gaming_tx_rx); - codec_qos_config_gaming_tx_rx.qos_config.cis_configs.push_back(cis_config_2_gaming_tx_rx); - - codec_qos_config_gaming_tx_rx.qos_config.ascs_configs.push_back(ascs_config_gaming_1); - - // voice tx rx - codec_qos_config_voice_tx_rx.codec_config.codec_type = - CodecIndex::CODEC_INDEX_SOURCE_LC3; - codec_qos_config_voice_tx_rx.codec_config.codec_priority = - CodecPriority::CODEC_PRIORITY_DEFAULT; - codec_qos_config_voice_tx_rx.codec_config.sample_rate = - CodecSampleRate::CODEC_SAMPLE_RATE_32000; - codec_qos_config_voice_tx_rx.codec_config.channel_mode = - CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - //Frame_Duration - UpdateFrameDuration(&codec_qos_config_voice_tx_rx.codec_config, - static_cast(CodecFrameDuration::FRAME_DUR_10)); - // LC3_Blocks_Per_SDU - UpdateLc3BlocksPerSdu(&codec_qos_config_voice_tx_rx.codec_config, 1); - UpdateOctsPerFrame(&codec_qos_config_voice_tx_rx.codec_config, 80); - codec_qos_config_voice_tx_rx.qos_config.cig_config = { - .cig_id = 3, - .cis_count = 2, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x10, 0x27, 0x00}, - .sdu_interval_s_to_m = {0x10, 0x27, 0x00} - }; - - codec_qos_config_voice_tx_rx.qos_config.cis_configs.push_back(cis_config_1_voice_tx_rx); - codec_qos_config_voice_tx_rx.qos_config.cis_configs.push_back(cis_config_2_voice_tx_rx); - - codec_qos_config_voice_tx_rx.qos_config.ascs_configs.push_back(ascs_config_voice_1); - codec_qos_config_voice_tx_rx.qos_config.ascs_configs.push_back(ascs_config_voice_2); - - - codec_qos_config_media_rx_1.codec_config.codec_type = - CodecIndex::CODEC_INDEX_SOURCE_LC3; - codec_qos_config_media_rx_1.codec_config.codec_priority = - CodecPriority::CODEC_PRIORITY_DEFAULT; - codec_qos_config_media_rx_1.codec_config.sample_rate = - CodecSampleRate::CODEC_SAMPLE_RATE_48000; - codec_qos_config_media_rx_1.codec_config.channel_mode = - CodecChannelMode::CODEC_CHANNEL_MODE_MONO; - //Frame_Duration - UpdateFrameDuration(&codec_qos_config_media_rx_1.codec_config, - static_cast(CodecFrameDuration::FRAME_DUR_10)); - // LC3_Blocks_Per_SDU - UpdateLc3BlocksPerSdu(&codec_qos_config_media_rx_1.codec_config, 1); - UpdateOctsPerFrame(&codec_qos_config_media_rx_1.codec_config, 100); - - codec_qos_config_media_rx_1.qos_config.cig_config = { - .cig_id = 4, - .cis_count = 2, - .packing = 0x01, // interleaved - .framing = 0x00, // unframed - .max_tport_latency_m_to_s = 0x000a, - .max_tport_latency_s_to_m = 0x000a, - .sdu_interval_m_to_s = {0x10, 0x27, 0x00}, - .sdu_interval_s_to_m = {0x10, 0x27, 0x00} - }; - - codec_qos_config_media_rx_1.qos_config.cis_configs.push_back(cis_config_1_media_rx); - codec_qos_config_media_rx_1.qos_config.cis_configs.push_back(cis_config_2_media_rx); - - codec_qos_config_media_rx_1.qos_config.ascs_configs.push_back(ascs_config_media_rx_1); - codec_qos_config_media_rx_1.qos_config.ascs_configs.push_back(ascs_config_media_rx_2); - - conn_info_media.stream_type.type = CONTENT_TYPE_MEDIA; - conn_info_media.stream_type.audio_context = CONTENT_TYPE_MEDIA; - conn_info_media.stream_type.direction = ASE_DIRECTION_SINK; - conn_info_media.codec_qos_config_pair.push_back(codec_qos_config_media_tx_1); - conn_info_media.codec_qos_config_pair.push_back(codec_qos_config_media_tx_2); - - conn_info_gaming.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - conn_info_gaming.stream_type.audio_context = CONTENT_TYPE_GAME; - conn_info_gaming.stream_type.direction = ASE_DIRECTION_SRC; - conn_info_gaming.codec_qos_config_pair.push_back(codec_qos_config_gaming_tx_1); - - conn_info_voice_tx.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - conn_info_voice_tx.stream_type.audio_context = CONTENT_TYPE_CONVERSATIONAL; - conn_info_voice_tx.stream_type.direction = ASE_DIRECTION_SINK; - conn_info_voice_tx.codec_qos_config_pair.push_back(codec_qos_config_voice_tx_rx); - - conn_info_voice_rx.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - conn_info_voice_rx.stream_type.audio_context = CONTENT_TYPE_CONVERSATIONAL; - conn_info_voice_rx.stream_type.direction = ASE_DIRECTION_SRC; - conn_info_voice_rx.codec_qos_config_pair.push_back(codec_qos_config_voice_tx_rx); - - conn_info_media_recording.stream_type.type = CONTENT_TYPE_MEDIA; - conn_info_media_recording.stream_type.audio_context = CONTENT_TYPE_LIVE; - conn_info_media_recording.stream_type.direction = ASE_DIRECTION_SRC; - conn_info_media_recording.codec_qos_config_pair.push_back(codec_qos_config_media_rx_1); - - std::vector four_streams; - four_streams.push_back(conn_info_media); - four_streams.push_back(conn_info_media_recording); - four_streams.push_back(conn_info_voice_tx); - four_streams.push_back(conn_info_voice_rx); - - std::vector voice_conn_streams; - voice_conn_streams.push_back(conn_info_voice_tx); - voice_conn_streams.push_back(conn_info_voice_rx); - - std::vector media_conn_streams; - media_conn_streams.push_back(conn_info_media); - - StreamType type_media = { .type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_MEDIA, - .direction = ASE_DIRECTION_SINK - }; - - StreamType type_gaming_tx = { .type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_GAME, - .direction = ASE_DIRECTION_SINK - }; - - StreamType type_voice_tx = { .type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SINK - }; - - StreamType type_voice_rx = { .type = CONTENT_TYPE_CONVERSATIONAL, - .audio_context = CONTENT_TYPE_CONVERSATIONAL, - .direction = ASE_DIRECTION_SRC - }; - - StreamType type_media_rx = { .type = CONTENT_TYPE_MEDIA, - .audio_context = CONTENT_TYPE_LIVE, - .direction = ASE_DIRECTION_SRC - }; - - std::vector media_streams; - media_streams.push_back(type_media); - - std::vector gaming_tx_streams; - gaming_tx_streams.push_back(type_gaming_tx); - - std::vector media_rx_streams; - media_rx_streams.push_back(type_media_rx); - - std::vector voice_streams; - voice_streams.push_back(type_voice_tx); - voice_streams.push_back(type_voice_rx); - - std::vector all_four_streams; - all_four_streams.push_back(type_media); - all_four_streams.push_back(type_voice_tx); - all_four_streams.push_back(type_voice_rx); - all_four_streams.push_back(type_media_rx); - - std::vector reconf_streams; - - StreamReconfig reconf_media_info; - reconf_media_info.stream_type.type = CONTENT_TYPE_MEDIA; - reconf_media_info.stream_type.audio_context = CONTENT_TYPE_MEDIA; - reconf_media_info.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_media_info.stream_type.direction = ASE_DIRECTION_SINK; - reconf_media_info.codec_qos_config_pair.push_back(codec_qos_config_media_tx_1); - reconf_media_info.codec_qos_config_pair.push_back(codec_qos_config_media_tx_2); - - StreamReconfig reconf_gaming_tx_info; - reconf_gaming_tx_info.stream_type.type = CONTENT_TYPE_MEDIA; - reconf_gaming_tx_info.stream_type.audio_context = CONTENT_TYPE_MEDIA; - reconf_gaming_tx_info.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_gaming_tx_info.stream_type.direction = ASE_DIRECTION_SINK; - reconf_gaming_tx_info.codec_qos_config_pair.push_back(codec_qos_config_gaming_tx_1); - reconf_gaming_tx_info.codec_qos_config_pair.push_back(codec_qos_config_gaming_tx_2); - - StreamReconfig reconf_voice_tx_info; - reconf_voice_tx_info.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - reconf_voice_tx_info.stream_type.audio_context = CONTENT_TYPE_CONVERSATIONAL; - reconf_voice_tx_info.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_voice_tx_info.stream_type.direction = ASE_DIRECTION_SINK; - reconf_voice_tx_info.codec_qos_config_pair. - push_back(codec_qos_config_voice_tx_rx); - - StreamReconfig reconf_voice_rx_info; - reconf_voice_rx_info.stream_type.type = CONTENT_TYPE_CONVERSATIONAL; - reconf_voice_rx_info.stream_type.audio_context = CONTENT_TYPE_CONVERSATIONAL; - reconf_voice_rx_info.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_voice_rx_info.stream_type.direction = ASE_DIRECTION_SRC; - reconf_voice_rx_info.codec_qos_config_pair. - push_back(codec_qos_config_voice_tx_rx); - - StreamReconfig reconf_media_rx_info; - reconf_media_rx_info.stream_type.type = CONTENT_TYPE_MEDIA; - reconf_media_rx_info.stream_type.audio_context = CONTENT_TYPE_LIVE; - reconf_media_rx_info.reconf_type = StreamReconfigType::CODEC_CONFIG; - reconf_media_rx_info.stream_type.direction = ASE_DIRECTION_SRC; - reconf_media_rx_info.codec_qos_config_pair.push_back(codec_qos_config_media_rx_1); - - LOG(INFO) << __func__ << " going for generic test case"; - LOG(INFO) << __func__ << " going for connect with voice tx and rx"; - sUcastClientInterface->Connect( bap_bd_addr_2, true, four_streams); - - sleep(15); - -#if 0 - // Recording to music switch (12) - LOG(INFO) << __func__ << " going for stream codec reconfig"; - reconf_streams.clear(); - reconf_streams.push_back(reconf_media_info); - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for music stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, media_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, media_streams); - - sleep(5); - - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - - LOG(INFO) << __func__ << "going for music stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, media_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, media_streams); - - //sleep(5); - LOG(INFO) << __func__ << "going for stream disconnect voice streams "; - sUcastClientInterface->Disconnect( bap_bd_addr_2, all_four_streams); - - sleep(10); - - LOG(INFO) << __func__ << " going for connect with voice tx and rx"; - sUcastClientInterface->Connect( bap_bd_addr_2, true, four_streams); - - sleep(15); - - LOG(INFO) << __func__ << " going for stream codec reconfig"; - reconf_streams.clear(); - reconf_streams.push_back(reconf_media_info); - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for music stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, media_streams); - - //sleep(5); - LOG(INFO) << __func__ << "going for stream disconnect voice streams "; - sUcastClientInterface->Disconnect( bap_bd_addr_2, all_four_streams); - - sleep(10); - - - LOG(INFO) << __func__ << " going for connect with voice tx and rx"; - sUcastClientInterface->Connect( bap_bd_addr_2, true, four_streams); - - sleep(15); - reconf_streams.clear(); - reconf_streams.push_back(reconf_voice_tx_info); - reconf_streams.push_back(reconf_voice_rx_info); - LOG(INFO) << __func__ << " going for voice stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for voice stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, voice_streams); - - - // Call Tx Rx to Gaming switch (4) - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, voice_streams); - sleep(5); - - LOG(INFO) << __func__ << " going for voice stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - sleep(5); - - LOG(INFO) << __func__ << "going for voice stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, voice_streams); - - - // Call Tx Rx to Gaming switch (4) - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, voice_streams); - - //sleep(5); - LOG(INFO) << __func__ << "going for stream disconnect voice streams "; - sUcastClientInterface->Disconnect( bap_bd_addr_2, all_four_streams); - - sleep(10); - - - LOG(INFO) << __func__ << " going for connect with voice tx and rx"; - sUcastClientInterface->Connect( bap_bd_addr_2, true, four_streams); - sleep(15); - - reconf_streams.clear(); - reconf_streams.push_back(reconf_voice_tx_info); - reconf_streams.push_back(reconf_voice_rx_info); - LOG(INFO) << __func__ << " going for voice stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for voice stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, voice_streams); - - //sleep(5); - LOG(INFO) << __func__ << "going for stream disconnect voice streams "; - sUcastClientInterface->Disconnect( bap_bd_addr_2, all_four_streams); - - sleep(10); - - sUcastClientInterface->Connect( bap_bd_addr_2, true, four_streams); - - sleep(1); - - LOG(INFO) << __func__ << "going for stream disconnect voice streams "; - sUcastClientInterface->Disconnect( bap_bd_addr_2, all_four_streams); - - sleep(10); - - sUcastClientInterface->Connect( bap_bd_addr_2, true, four_streams); - - sleep(15); - -#endif -#if 1 - reconf_streams.clear(); - reconf_streams.push_back(reconf_voice_tx_info); - reconf_streams.push_back(reconf_voice_rx_info); - LOG(INFO) << __func__ << " going for voice stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - //usleep(200000); - - sleep(5); - - LOG(INFO) << __func__ << "going for voice stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, voice_streams); - - - // Call Tx Rx to Gaming switch (4) - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, voice_streams); - - sleep(5); - - LOG(INFO) << __func__ << " going for voice stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - - LOG(INFO) << __func__ << "going for voice stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, voice_streams); - - - // Call Tx Rx to Gaming switch (4) - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, voice_streams); - - sleep(5); - - LOG(INFO) << __func__ << "going for voice stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, voice_streams); - - sleep(5); - //usleep(200000); - LOG(INFO) << __func__ << "going for stream disconnect voice streams "; - sUcastClientInterface->Disconnect( bap_bd_addr_2, all_four_streams); - - sleep(10); - - sUcastClientInterface->Connect( bap_bd_addr_2, true, four_streams); -#endif - - sleep(15); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - reconf_streams.clear(); - reconf_streams.push_back(reconf_media_info); - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - - // Music streaming - LOG(INFO) << __func__ << "going for media stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, media_streams); - - // music to gaming Tx switch (1) - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, media_streams); - - sleep(5); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - reconf_streams.clear(); - reconf_streams.push_back(reconf_gaming_tx_info); - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for gaming stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, gaming_tx_streams); - - // Gaming Tx to music switch (2) - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, gaming_tx_streams); - - sleep(5); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - reconf_streams.clear(); - reconf_streams.push_back(reconf_media_info); - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for gaming stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, media_streams); - - // music to Call Tx Rx switch (3) - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, media_streams); - - sleep(5); - reconf_streams.clear(); - reconf_streams.push_back(reconf_voice_tx_info); - reconf_streams.push_back(reconf_voice_rx_info); - LOG(INFO) << __func__ << " going for voice stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for voice stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, voice_streams); - - - // Call Tx Rx to Gaming switch (4) - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, voice_streams); - - sleep(5); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - reconf_streams.clear(); - reconf_streams.push_back(reconf_gaming_tx_info); - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for gaming stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, gaming_tx_streams); - - - // Gaming to Cal Audio switch (5) - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, gaming_tx_streams); - - sleep(5); - reconf_streams.clear(); - reconf_streams.push_back(reconf_voice_tx_info); - reconf_streams.push_back(reconf_voice_rx_info); - LOG(INFO) << __func__ << " going for voice stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for voice stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, voice_streams); - - - - // Cal Audio to music switch (6) - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, voice_streams); - - sleep(5); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - reconf_streams.clear(); - reconf_streams.push_back(reconf_media_info); - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for music stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, media_streams); - - - // music to Recording switch (7) - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, media_streams); - - sleep(5); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - reconf_streams.clear(); - reconf_streams.push_back(reconf_media_rx_info); - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for recording stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, media_rx_streams); - - - // Recording to Gaming switch (8) - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, media_rx_streams); - - sleep(5); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - reconf_streams.clear(); - reconf_streams.push_back(reconf_gaming_tx_info); - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for gaming stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, gaming_tx_streams); - - - // Gaming to Recording switch (9) - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, gaming_tx_streams); - - sleep(5); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - reconf_streams.clear(); - reconf_streams.push_back(reconf_media_rx_info); - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for recording stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, media_rx_streams); - - - // Recording to Call Audio switch (10) - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, media_rx_streams); - - sleep(5); - reconf_streams.clear(); - reconf_streams.push_back(reconf_voice_tx_info); - reconf_streams.push_back(reconf_voice_rx_info); - LOG(INFO) << __func__ << " going for voice stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for voice stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, voice_streams); - - - // Call Audio to Recording switch (11) - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, voice_streams); - - sleep(5); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - reconf_streams.clear(); - reconf_streams.push_back(reconf_media_rx_info); - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for recording stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, media_rx_streams); - - - // Recording to music switch (12) - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, media_rx_streams); - - sleep(5); - LOG(INFO) << __func__ << " going for stream codec reconfig"; - reconf_streams.clear(); - reconf_streams.push_back(reconf_media_info); - sUcastClientInterface->Reconfigure( bap_bd_addr_2, reconf_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for music stream start "; - sUcastClientInterface->Start( bap_bd_addr_2, media_streams); - - sleep(5); - LOG(INFO) << __func__ << "going for media stream stop "; - sUcastClientInterface->Stop( bap_bd_addr_2, media_streams); - - //sleep(5); - LOG(INFO) << __func__ << "going for stream disconnect voice streams "; - sUcastClientInterface->Disconnect( bap_bd_addr_2, all_four_streams); - - sleep(10); - - } else if(!strcmp(bap_test, "connect")) { - LOG(INFO) << __func__ << " going for connect test case"; - - for ( uint8_t i = 0; i < 5; i++) { - LOG(INFO) << __func__ << " iteration " << loghex(i); - LOG(INFO) << __func__ << " going for connect"; - sUcastClientInterface->Connect( bap_bd_addr, true, streams); - usleep( i* 1000 * 1000); - LOG(INFO) << __func__ << " going for stream disconnect"; - sUcastClientInterface->Disconnect( bap_bd_addr, start_streams); - } - } else if(!strcmp(bap_test, "release_in_streaming")) { - LOG(INFO) << __func__ << " going for release_in_streaming test case"; - - LOG(INFO) << __func__ << " going for connect"; - sUcastClientInterface->Connect( bap_bd_addr, true, streams); - - sleep(10); - - LOG(INFO) << __func__ << " going for stream start"; - sUcastClientInterface->Start( bap_bd_addr, start_streams); - - sleep(10); - - LOG(INFO) << __func__ << "going for stream disconnect"; - sUcastClientInterface->Disconnect( bap_bd_addr, start_streams); - - - } else if(!strcmp(bap_test, "release_in_enabling")) { - LOG(INFO) << __func__ << " going for release_in_enabling test case"; - - LOG(INFO) << __func__ << " going for connect"; - sUcastClientInterface->Connect( bap_bd_addr, true, streams); - - sleep(10); - - LOG(INFO) << __func__ << " going for stream start"; - sUcastClientInterface->Start( bap_bd_addr, start_streams); - - usleep(150 *1000); - - LOG(INFO) << __func__ << "going for stream disconnect"; - sUcastClientInterface->Disconnect( bap_bd_addr, start_streams); - - - } else if(!strcmp(bap_test, "release_in_disabling")) { - LOG(INFO) << __func__ << " going for release_in_disabling test case"; - - LOG(INFO) << __func__ << " going for connect"; - sUcastClientInterface->Connect( bap_bd_addr, true, streams); - - sleep(10); - - LOG(INFO) << __func__ << " going for stream start"; - sUcastClientInterface->Start( bap_bd_addr, start_streams); - - sleep(10); - - LOG(INFO) << __func__ << " going for stream stop"; - sUcastClientInterface->Stop( bap_bd_addr, start_streams); - - usleep(100 * 1000); - LOG(INFO) << __func__ << "going for stream disconnect"; - sUcastClientInterface->Disconnect( bap_bd_addr, start_streams); - - } else if(!strcmp(bap_test, "disable_in_enabling")) { - LOG(INFO) << __func__ << " going for disable_in_enabling test case"; - - LOG(INFO) << __func__ << " going for connect"; - sUcastClientInterface->Connect( bap_bd_addr, true, streams); - - sleep(10); - - LOG(INFO) << __func__ << " going for stream start"; - sUcastClientInterface->Start( bap_bd_addr, start_streams); - - usleep(200 * 1000); - LOG(INFO) << __func__ << "going for stream stop"; - sUcastClientInterface->Stop( bap_bd_addr, start_streams); - - } else if(!strcmp(bap_test, "disable_in_streaming")) { - LOG(INFO) << __func__ << " going for disable_in_streaming test case"; - - LOG(INFO) << __func__ << " going for connect"; - sUcastClientInterface->Connect( bap_bd_addr, true, streams); - - sleep(10); - - LOG(INFO) << __func__ << " going for stream start"; - sUcastClientInterface->Start( bap_bd_addr, start_streams); - - sleep(5); - - LOG(INFO) << __func__ << "going for stream stop"; - sUcastClientInterface->Stop( bap_bd_addr, start_streams); - - } else if(!strcmp(bap_test, "release_in_codec_configured")) { - LOG(INFO) << __func__ << " going for release_in_codec_configured test case"; - - LOG(INFO) << __func__ << " going for connect"; - sUcastClientInterface->Connect( bap_bd_addr, true, streams); - - usleep(2600 * 1000); - LOG(INFO) << __func__ << "going for stream disconnect"; - sUcastClientInterface->Disconnect( bap_bd_addr, start_streams); - - } else if(!strcmp(bap_test, "release_in_qos_configured")) { - LOG(INFO) << __func__ << " going for release_in_qos_configured test case"; - - LOG(INFO) << __func__ << " going for connect"; - sUcastClientInterface->Connect( bap_bd_addr, true, streams); - - sleep(10); - - LOG(INFO) << __func__ << "going for stream disconnect"; - sUcastClientInterface->Disconnect( bap_bd_addr, start_streams); - - } else if(!strcmp(bap_test, "enable_in_qos_configured")) { - LOG(INFO) << __func__ << " going for enable_in_qos_configured test case"; - - LOG(INFO) << __func__ << " going for connect"; - sUcastClientInterface->Connect( bap_bd_addr, true, streams); - - sleep(10); - - LOG(INFO) << __func__ << "going for stream start"; - sUcastClientInterface->Start( bap_bd_addr, start_streams); - - } else if(!strcmp(bap_test, "start")) { - LOG(INFO) << __func__ << " going for start test case"; - - LOG(INFO) << __func__ << " going for stop while starting test case"; - - - for ( uint8_t i = 0; i < 5; i++) { - LOG(INFO) << __func__ << " iteration " << loghex(i); - LOG(INFO) << __func__ << " going for connect"; - sUcastClientInterface->Connect( bap_bd_addr, true, streams); - - sleep(5); - LOG(INFO) << __func__ << " going for stream start"; - sUcastClientInterface->Start( bap_bd_addr, start_streams); - usleep( i* 200 * 1000); - LOG(INFO) << __func__ << " going for stream stop"; - sUcastClientInterface->Stop( bap_bd_addr, start_streams); - sleep(5); - - LOG(INFO) << __func__ << " going for stream disconnect"; - sUcastClientInterface->Disconnect( bap_bd_addr, start_streams); - } - - LOG(INFO) << __func__ << " going for disconnect while starting test case"; - - for ( uint8_t i = 0; i < 5; i++) { - LOG(INFO) << __func__ << " iteration " << loghex(i); - LOG(INFO) << __func__ << " going for connect"; - sUcastClientInterface->Connect( bap_bd_addr, true, streams); - - sleep(5); - - LOG(INFO) << __func__ << " going for stream start"; - sUcastClientInterface->Start( bap_bd_addr, start_streams); - usleep( i* 200 * 1000); - LOG(INFO) << __func__ << " going for stream disconnect"; - sUcastClientInterface->Disconnect( bap_bd_addr, start_streams); - sleep(5); - } - - } else if(!strcmp(bap_test, "stop")) { - LOG(INFO) << __func__ << " going for stop test case"; - LOG(INFO) << __func__ << " going for connect"; - - for ( uint8_t i = 0; i < 5; i++) { - LOG(INFO) << __func__ << " iteration " << loghex(i); - LOG(INFO) << __func__ << " going for disconnect while stopping"; - sUcastClientInterface->Connect( bap_bd_addr, true, streams); - - sleep(5); - - LOG(INFO) << __func__ << " going for stream start"; - sUcastClientInterface->Start( bap_bd_addr, start_streams); - - sleep(5); - - LOG(INFO) << __func__ << " going for stream stop"; - sUcastClientInterface->Stop( bap_bd_addr, start_streams); - usleep( i* 200 * 1000); - - LOG(INFO) << __func__ << " going for stream disconnect"; - sUcastClientInterface->Disconnect( bap_bd_addr, start_streams); - } - - } else if(!strcmp(bap_test, "stop")) { - LOG(INFO) << __func__ << " going for stop test case"; - LOG(INFO) << __func__ << " going for connect"; - - for ( uint8_t i = 0; i < 5; i++) { - LOG(INFO) << __func__ << " iteration " << loghex(i); - LOG(INFO) << __func__ << " going for disconnect while stopping"; - sUcastClientInterface->Connect( bap_bd_addr, true, streams); - - sleep(5); - - LOG(INFO) << __func__ << " going for stream start"; - sUcastClientInterface->Start( bap_bd_addr, start_streams); - - sleep(5); - - LOG(INFO) << __func__ << " going for stream stop"; - sUcastClientInterface->Stop( bap_bd_addr, start_streams); - usleep( i* 200 * 1000); - - LOG(INFO) << __func__ << " going for stream disconnect"; - sUcastClientInterface->Disconnect( bap_bd_addr, start_streams); - } - } else if(!strcmp(bap_test, "reconfigure")) { - LOG(INFO) << __func__ << " going for reconfigure test case"; - LOG(INFO) << __func__ << " going for connect"; - - sUcastClientInterface->Connect( bap_bd_addr, true, streams); - - sleep(5); - - LOG(INFO) << __func__ << " going for stream codec reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_streams); - - sleep(5); - - LOG(INFO) << __func__ << " going for stream qos reconfig"; - sUcastClientInterface->Reconfigure( bap_bd_addr, reconf_qos_streams); - - sleep(5); - - LOG(INFO) << __func__ << " going for stream disconnect"; - sUcastClientInterface->Disconnect( bap_bd_addr, start_streams); - - } - - LOG(INFO) << __func__ << " Test completed"; -#if 0 - sleep(2); - LOG(INFO) << __func__ << "going for connect"; - sUcastClientInterface->Connect( bap_bd_addr); - sleep(7); - LOG(INFO) << __func__ << "going for discovery"; - sUcastClientInterface->StartDiscovery( bap_bd_addr); - sleep(2); - LOG(INFO) << __func__ << "going for getAudiocontexts"; - sUcastClientInterface->GetAvailableAudioContexts( bap_bd_addr); - sleep(2); - LOG(INFO) << __func__ << "going for disconnect"; - sUcastClientInterface->Disconnect( bap_bd_addr); - sleep(1); - sUcastClientInterface->Cleanup(); - sleep(1); - sUcastClientInterface->Init(&sUcastClientCallbacks); - sleep(1); - LOG(INFO) << __func__ << "going for connect 2 "; - sUcastClientInterface->Connect( bap_bd_addr); - sleep(7); - LOG(INFO) << __func__ << "going for discovery 2"; - sUcastClientInterface->StartDiscovery( bap_bd_addr); - sleep(2); - LOG(INFO) << __func__ << "going for getAudiocontexts 2"; - sUcastClientInterface->GetAvailableAudioContexts( bap_bd_addr); - sleep(2); - LOG(INFO) << __func__ << "going for disconnect 2"; - sUcastClientInterface->Disconnect( bap_bd_addr); - sleep(1); - sUcastClientInterface->Cleanup(); -#endif -} - -bool test_bap_uclient () { - RawAddress::FromString("00:02:5b:00:ff:00", bap_bd_addr); - test_thread = thread_new("test_bap_uclient"); - LOG(INFO) << __func__ << "going for test setup"; - thread_post(test_thread, event_test_bap_uclient, NULL); - return true; -} - -// PACS related test code -using bluetooth::bap::pacs::PacsClientInterface; -using bluetooth::bap::pacs::PacsClientCallbacks; - -static PacsClientInterface* sPacsClientInterface = nullptr; -static uint16_t pacs_client_id = 0; -static RawAddress pac_bd_addr; - -class PacsClientCallbacksImpl : public PacsClientCallbacks { - public: - ~PacsClientCallbacksImpl() = default; - void OnInitialized(int status, - int client_id) override { - LOG(WARNING) << __func__ << client_id; - pacs_client_id = client_id; - } - void OnConnectionState(const RawAddress& bd_addr, - ConnectionState state) override { - LOG(WARNING) << __func__; - if(state == ConnectionState::CONNECTED) { - LOG(WARNING) << __func__ << "connected"; - } else if(state == ConnectionState::DISCONNECTED) { - LOG(WARNING) << __func__ << "Disconnected"; - } - - } - void OnAudioContextAvailable(const RawAddress& bd_addr, - uint32_t available_contexts) override { - LOG(INFO) << __func__; - } - void OnSearchComplete(int status, const RawAddress& address, - std::vector sink_pac_records, - std::vector src_pac_records, - uint32_t sink_locations, - uint32_t src_locations, - uint32_t available_contexts, - uint32_t supported_contexts) override { - LOG(WARNING) << __func__; - } -}; - -static PacsClientCallbacksImpl sPacsClientCallbacks; - -static void event_test_pacs(UNUSED_ATTR void* context) { - sPacsClientInterface = btif_pacs_client_get_interface(); - sPacsClientInterface->Init(&sPacsClientCallbacks); - sleep(1); - LOG(INFO) << __func__ << "going for connect"; - sPacsClientInterface->Connect(pacs_client_id, pac_bd_addr); - sleep(7); - LOG(INFO) << __func__ << "going for discovery"; - sPacsClientInterface->StartDiscovery(pacs_client_id, pac_bd_addr); - sleep(2); - LOG(INFO) << __func__ << "going for getAudiocontexts"; - sPacsClientInterface->GetAvailableAudioContexts(pacs_client_id, pac_bd_addr); - sleep(2); - LOG(INFO) << __func__ << "going for disconnect"; - sPacsClientInterface->Disconnect(pacs_client_id, pac_bd_addr); - - sleep(2); - LOG(INFO) << __func__ << "going for connect"; - sPacsClientInterface->Connect(pacs_client_id, pac_bd_addr); - sleep(7); - LOG(INFO) << __func__ << "going for discovery"; - sPacsClientInterface->StartDiscovery(pacs_client_id, pac_bd_addr); - sleep(2); - LOG(INFO) << __func__ << "going for getAudiocontexts"; - sPacsClientInterface->GetAvailableAudioContexts(pacs_client_id, pac_bd_addr); - sleep(2); - LOG(INFO) << __func__ << "going for disconnect"; - sPacsClientInterface->Disconnect(pacs_client_id, pac_bd_addr); - - sleep(1); - sPacsClientInterface->Cleanup(pacs_client_id); - - sleep(1); - - sPacsClientInterface->Init(&sPacsClientCallbacks); - sleep(1); - LOG(INFO) << __func__ << "going for connect 2 "; - sPacsClientInterface->Connect(pacs_client_id, pac_bd_addr); - sleep(7); - LOG(INFO) << __func__ << "going for discovery 2"; - sPacsClientInterface->StartDiscovery(pacs_client_id, pac_bd_addr); - sleep(2); - LOG(INFO) << __func__ << "going for getAudiocontexts 2"; - sPacsClientInterface->GetAvailableAudioContexts(pacs_client_id, pac_bd_addr); - sleep(2); - LOG(INFO) << __func__ << "going for disconnect 2"; - sPacsClientInterface->Disconnect(pacs_client_id, pac_bd_addr); - - sleep(1); - sPacsClientInterface->Cleanup(pacs_client_id); - -} - -bool test_pacs (RawAddress& bd_addr) { - - test_thread = thread_new("test_pacs"); - pac_bd_addr = bd_addr; - thread_post(test_thread, event_test_pacs, NULL); - return true; -} diff --git a/le_audio/system/bt/btif/src/btif_cc.cc b/le_audio/system/bt/btif/src/btif_cc.cc deleted file mode 100644 index 59c355da1b56884e92c2e5e5b491af3cf21a3efa..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/src/btif_cc.cc +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. - */ - -/* - * 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. - */ - -/* CC Interface */ -#define LOG_TAG "bt_btif_cc" - -#include "bt_target.h" -#include "bta_closure_api.h" -#include "btif_common.h" -#include "btif_storage.h" -#include "bta_cc_api.h" - -#include -#include -#include -#include -#include -#include -#include - -using base::Bind; -using base::Unretained; -using base::Owned; -using bluetooth::Uuid; -using std::vector; - -using base::Unretained; -using bluetooth::call_control::CallControllerInterface; -using bluetooth::call_control::CallControllerCallbacks; - -namespace { -class CallControllerInterfaceImpl; -std::unique_ptr CallControllerInstance; - -class CallControllerInterfaceImpl - : public CallControllerInterface, public CallControllerCallbacks { - ~CallControllerInterfaceImpl() = default; - - bt_status_t Init(CallControllerCallbacks* callbacks, Uuid uuid, int max_ccs_clients, - bool inband_ringing_enabled) override { - - LOG(INFO) << __func__ ; - this->callbacks = callbacks; - do_in_bta_thread(FROM_HERE,Bind(&CallController::Initialize, - this, uuid,max_ccs_clients, inband_ringing_enabled)); - return BT_STATUS_SUCCESS; - } - - bt_status_t UpdateBearerName(uint8_t* operator_str) { - - LOG(INFO) << __func__ << ": bearer name " << operator_str; - uint8_t* bName = (uint8_t*)malloc(sizeof(uint8_t)*strlen((char*)operator_str)+1); - if (bName != NULL) { - memcpy(bName, operator_str, strlen((char*)operator_str)+1); - do_in_bta_thread(FROM_HERE,Bind(&CallController::BearerInfoName, - Unretained(CallController::Get()), bName)); - free(bName); - } - return BT_STATUS_SUCCESS; - } - - void Cleanup() { - LOG(INFO) << __func__ ; - do_in_bta_thread(FROM_HERE,Bind(&CallController::CleanUp)); - } - -bt_status_t UpdateBearerTechnology(int bearer_tech) { - - LOG(INFO) << __func__ << ": " << bearer_tech; - do_in_bta_thread(FROM_HERE,Bind(&CallController::UpdateBearerTechnology, - Unretained(CallController::Get()), bearer_tech)); - return BT_STATUS_SUCCESS; -} - -bt_status_t UpdateSupportedBearerList(uint8_t* supportedbearer_list) { - - LOG(INFO) << __func__ << ": " << supportedbearer_list; - uint8_t* sList = (uint8_t*)malloc(sizeof(uint8_t)*strlen((char*)supportedbearer_list)+1); - if (sList != NULL) { - memcpy(sList, supportedbearer_list, strlen((char*)supportedbearer_list)+1); - do_in_bta_thread(FROM_HERE,Bind(&CallController::UpdateSupportedBearerList, - Unretained(CallController::Get()), sList)); - free(sList); - } - return BT_STATUS_SUCCESS; - -} -bt_status_t UpdateStatusFlags(uint8_t status_flag) { - LOG(INFO) << __func__ << ": " << status_flag; - do_in_bta_thread(FROM_HERE,Bind(&CallController::UpdateStatusFlags, - Unretained(CallController::Get()), status_flag)); - return BT_STATUS_SUCCESS; -} - -bt_status_t UpdateSignalStatus(int signal) { - - LOG(INFO) << __func__ << ": " << signal; - do_in_bta_thread(FROM_HERE,Bind(&CallController::UpdateBearerSignalStrength, - Unretained(CallController::Get()), signal)); - return BT_STATUS_SUCCESS; - -} - -bt_status_t CallControlOptionalOpSupported(int feature) { - - LOG(INFO) << __func__ << ": " << feature; - do_in_bta_thread(FROM_HERE,Bind(&CallController::CallControlOptionalOpSupported, - Unretained(CallController::Get()), feature)); - return BT_STATUS_SUCCESS; -} - -bt_status_t CallState(int len, std::vector call_state_list) { - - LOG(INFO) << __func__ << ": "; - do_in_bta_thread(FROM_HERE,Bind(&CallController::CallState, - Unretained(CallController::Get()), len, std::move(call_state_list))); - return BT_STATUS_SUCCESS; - -} - -void UpdateIncomingCall(int index, uint8_t* Uri) { - LOG(INFO) << __func__ << ": " < -#include -#include -#include -#include -#include -#include -#include -#include -#include "device/include/controller.h" -#include "bta_csip_api.h" - -#include "btif_api.h" -#include "btif_common.h" -#include "btif_util.h" - -#include - -using base::Bind; -using bluetooth::Uuid; - -static btcsip_callbacks_t* bt_csip_callbacks = NULL; - -void btif_new_set_found_cb(tBTA_CSIP_NEW_SET_FOUND params) { - HAL_CBACK(bt_csip_callbacks, new_set_found_cb, params.set_id, params.addr, - params.size, params.sirk, params.including_srvc_uuid, - params.lock_support); -} - -void btif_conn_state_changed_cb(tBTA_CSIP_CONN_STATE_CHANGED params) { - HAL_CBACK(bt_csip_callbacks, conn_state_cb, params.app_id, params.addr, - params.state, params.status); -} - -void btif_new_set_member_found_cb(tBTA_SET_MEMBER_FOUND params) { - HAL_CBACK(bt_csip_callbacks, new_set_member_cb, params.set_id, params.addr); -} - -void btif_lock_status_changed_cb(tBTA_LOCK_STATUS_CHANGED params) { - HAL_CBACK(bt_csip_callbacks, lock_status_cb, params.app_id, params.set_id, - params.value, params.status, params.addr); -} - -void btif_lock_available_cb(tBTA_LOCK_AVAILABLE params) { - HAL_CBACK(bt_csip_callbacks, lock_available_cb, params.app_id, params.set_id, - params.addr); -} - -void btif_set_size_changed_cb (tBTA_CSIP_SET_SIZE_CHANGED params) { - HAL_CBACK(bt_csip_callbacks, size_changed_cb, params.set_id, params.size, - params.addr); -} - -void btif_set_sirk_changed_cb (tBTA_CSIP_SET_SIRK_CHANGED params) { - HAL_CBACK(bt_csip_callbacks, sirk_changed_cb, params.set_id, params.sirk, - params.addr); -} - -const char* btif_csip_get_event_name(tBTA_CSIP_EVT event) { - switch(event) { - case BTA_CSIP_LOCK_STATUS_CHANGED_EVT: - return "BTA_CSIP_LOCK_STATUS_CHANGED_EVT"; - case BTA_CSIP_SET_MEMBER_FOUND_EVT: - return "BTA_CSIP_SET_MEMBER_FOUND_EVT"; - case BTA_CSIP_LOCK_AVAILABLE_EVT: - return "BTA_CSIP_LOCK_AVAILABLE_EVT"; - case BTA_CSIP_NEW_SET_FOUND_EVT: - return "BTA_CSIP_NEW_SET_FOUND_EVT"; - case BTA_CSIP_CONN_STATE_CHG_EVT: - return "BTA_CSIP_CONN_STATE_CHG_EVT"; - case BTA_CSIP_SET_SIZE_CHANGED: - return "BTA_CSIP_SET_SIZE_CHANGED"; - case BTA_CSIP_SET_SIRK_CHANGED: - return "BTA_CSIP_SET_SIRK_CHANGED"; - default: - return "UNKNOWN_EVENT"; - } -} - -void btif_csip_evt (tBTA_CSIP_EVT event, tBTA_CSIP_DATA* p_data) { - BTIF_TRACE_EVENT("%s: Event = %02x (%s)", __func__, event, btif_csip_get_event_name(event)); - - switch (event) { - case BTA_CSIP_LOCK_STATUS_CHANGED_EVT: { - tBTA_LOCK_STATUS_CHANGED lock_status_params = p_data->lock_status_param; - do_in_jni_thread(Bind(btif_lock_status_changed_cb, lock_status_params)); - } - break; - - case BTA_CSIP_LOCK_AVAILABLE_EVT: { - tBTA_LOCK_AVAILABLE lock_avl_param = p_data->lock_available_param; - do_in_jni_thread(Bind(btif_lock_available_cb, lock_avl_param)); - } - break; - - case BTA_CSIP_NEW_SET_FOUND_EVT: { - tBTA_CSIP_NEW_SET_FOUND new_set_params = p_data->new_set_params; - memcpy(new_set_params.sirk, p_data->new_set_params.sirk, SIRK_SIZE); - do_in_jni_thread(Bind(btif_new_set_found_cb, new_set_params)); - } - break; - - case BTA_CSIP_SET_MEMBER_FOUND_EVT: { - tBTA_SET_MEMBER_FOUND new_member_params = p_data->set_member_param; - do_in_jni_thread(Bind(btif_new_set_member_found_cb, new_member_params)); - } - break; - - case BTA_CSIP_CONN_STATE_CHG_EVT: { - tBTA_CSIP_CONN_STATE_CHANGED conn_params = p_data->conn_params; - do_in_jni_thread(Bind(btif_conn_state_changed_cb, conn_params)); - } - break; - - case BTA_CSIP_SET_SIZE_CHANGED: { - tBTA_CSIP_SET_SIZE_CHANGED size_chg_param = p_data->size_chg_params; - do_in_jni_thread(Bind(btif_set_size_changed_cb, size_chg_param)); - } - break; - - case BTA_CSIP_SET_SIRK_CHANGED: { - tBTA_CSIP_SET_SIRK_CHANGED sirk_chg_param = p_data->sirk_chg_params; - do_in_jni_thread(Bind(btif_set_sirk_changed_cb, sirk_chg_param)); - } - break; - - default: - BTIF_TRACE_ERROR("%s: Unknown event %d", __func__, event); - } -} - -/* Initialization of CSIP module on BT ON*/ -bt_status_t btif_csip_init( btcsip_callbacks_t* callbacks ) { - bt_csip_callbacks = callbacks; - - do_in_jni_thread(Bind(BTA_CsipEnable, btif_csip_evt)); - btif_register_uuid_srvc_disc(Uuid::FromString("1846")); - - return BT_STATUS_SUCCESS; -} - -/* Connect call from upper layer for GATT Connecttion to a given Set Member */ -bt_status_t btif_csip_connect (uint8_t app_id, RawAddress *bd_addr) { - BTIF_TRACE_EVENT("%s: Address: %s", __func__, bd_addr->ToString().c_str()); - - do_in_jni_thread(Bind(BTA_CsipConnect, app_id, *bd_addr)); - - return BT_STATUS_SUCCESS; -} - -/* Call from upper layer to disconnect GATT Connection for given Set Member */ -bt_status_t btif_csip_disconnect (uint8_t app_id, RawAddress *bd_addr ) { - BTIF_TRACE_EVENT("%s", __func__); - - do_in_jni_thread(Bind(BTA_CsipDisconnect, app_id, *bd_addr)); - - return BT_STATUS_SUCCESS; -} - -/** register app/module with CSIP profile */ -bt_status_t btif_csip_app_register (const bluetooth::Uuid& uuid) { - BTIF_TRACE_EVENT("%s", __func__); - return do_in_jni_thread(Bind( - [](const Uuid& uuid) { - BTA_RegisterCsipApp( - btif_csip_evt, - base::Bind( - [](const Uuid& uuid, uint8_t status, uint8_t app_id) { - do_in_jni_thread(Bind( - [](const Uuid& uuid, uint8_t status, uint8_t app_id) { - HAL_CBACK(bt_csip_callbacks, app_registered_cb, - status, app_id, uuid); - }, - uuid, status, app_id)); - }, - uuid)); - }, uuid)); -} - -/** unregister csip App/Module */ -bt_status_t btif_csip_app_unregister (uint8_t app_id) { - BTIF_TRACE_EVENT("%s", __func__); - return do_in_jni_thread(Bind(BTA_UnregisterCsipApp, app_id)); -} - -/** change lock value */ -bt_status_t btif_csip_set_lock_value (uint8_t app_id, uint8_t set_id, uint8_t lock_value, - std::vector devices) { - BTIF_TRACE_EVENT("%s appId = %d setId = %d Lock Value = %02x ", __func__, - app_id, set_id, lock_value); - tBTA_SET_LOCK_PARAMS lock_params = {app_id, set_id, lock_value, devices}; - do_in_jni_thread(Bind(BTA_CsipSetLockValue, lock_params)); - return BT_STATUS_SUCCESS; -} - -void btif_csip_cleanup() { - BTIF_TRACE_EVENT("%s", __func__); - do_in_jni_thread(Bind(BTA_CsipDisable)); -} - -const btcsip_interface_t btcsipInterface = { - sizeof(btcsipInterface), - btif_csip_init, - btif_csip_connect, - btif_csip_disconnect, - btif_csip_app_register, - btif_csip_app_unregister, - btif_csip_set_lock_value, - btif_csip_cleanup, -}; - -/******************************************************************************* - * - * Function btif_csip_get_interface - * - * Description Get the csip callback interface - * - * Returns btcsip_interface_t - * - ******************************************************************************/ -const btcsip_interface_t* btif_csip_get_interface() { - BTIF_TRACE_EVENT("%s", __func__); - return &btcsipInterface; -} diff --git a/le_audio/system/bt/btif/src/btif_dm_adv_audio.cc b/le_audio/system/bt/btif/src/btif_dm_adv_audio.cc deleted file mode 100644 index ccebbfbaf0a5cd769c65ca6133c4d9240a8f176f..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/src/btif_dm_adv_audio.cc +++ /dev/null @@ -1,691 +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. - * - ******************************************************************************/ - -#define LOG_TAG "bt_btif_dm" - -#include "btif_dm.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include "hardware/vendor.h" - -#include -#include - -#include "advertise_data_parser.h" -#include "bt_common.h" -#include "bta_closure_api.h" -#include "bta_csip_api.h" -#include "bta_gatt_api.h" -#include "btif_api.h" -#include "btif_bqr.h" -#include "btif_config.h" -#include "btif_dm.h" -#include "btif_hh.h" -#include "btif_sdp.h" -#include "btif_storage.h" -#include "btif_util.h" -#include "btu.h" -#include "bta/include/bta_dm_api.h" -#include "device/include/controller.h" -#include "device/include/interop.h" -#include "internal_include/stack_config.h" -#include "osi/include/allocator.h" -#include "osi/include/log.h" -#include "osi/include/metrics.h" -#include "osi/include/osi.h" -#include "osi/include/properties.h" -#include "stack_config.h" -#include "stack/sdp/sdpint.h" -#include "btif_tws_plus.h" -#include "device/include/device_iot_config.h" -#include "btif_bap_config.h" -#include "bta_dm_adv_audio.h" -#include "btif_dm_adv_audio.h" - -using bluetooth::Uuid; - -/****************************************************************************** - * Constants & Macros - *****************************************************************************/ -#define BTIF_DM_GET_REMOTE_PROP(b,t,v,l,p) \ - {p.type=t;p.val=v;p.len=l;btif_storage_get_remote_device_property(b,&p);} - -extern std::vector uuid_srv_disc_search; -std::unordered_map adv_audio_device_db; -extern void bta_dm_adv_audio_gatt_conn(RawAddress p_bd_addr); -extern void bta_dm_adv_audio_close(RawAddress p_bd_addr); -extern bool btif_has_ble_keys(const char* bdstr); -bt_status_t btif_storage_get_remote_device_property( - const RawAddress* remote_bd_addr, bt_property_t* property); -extern tBTA_LEA_PAIRING_DB bta_lea_pairing_cb; -extern void search_services_copy_cb(uint16_t event, char* p_dest, char* p_src); - -extern void bond_state_changed(bt_status_t status, const RawAddress& bd_addr, - bt_bond_state_t state); - -#define BTIF_STORAGE_GET_REMOTE_PROP(b, t, v, l, p) \ - do { \ - (p).type = (t); \ - (p).val = (v); \ - (p).len = (l); \ - btif_storage_get_remote_device_property((b), &(p)); \ - } while (0) - -extern bool check_adv_audio_cod(uint32_t cod); -extern bool is_remote_support_adv_audio(const RawAddress remote_bdaddr); -extern bool is_le_audio_service(Uuid uuid); -extern void bta_adv_audio_update_bond_db(RawAddress p_bd_addr, uint8_t transport); - -#define BTIF_DM_MAX_SDP_ATTEMPTS_AFTER_PAIRING 2 - - -tBTA_TRANSPORT btif_dm_get_adv_audio_transport(const RawAddress& bd_addr) { - tBTM_INQ_INFO* p_inq_info; - - p_inq_info = BTM_InqDbRead(bd_addr); - if (p_inq_info != NULL) { - BTIF_TRACE_DEBUG("%s, inq_result_type %x", - __func__, p_inq_info->results.inq_result_type); - if (p_inq_info->results.inq_result_type & BTM_INQ_RESULT_BLE) { - return BT_TRANSPORT_LE; - } - } - return BT_TRANSPORT_BR_EDR; -} - -/******************************************************************************* - * - * Function btif_set_remote_device_uuid_property - * - * Description Store the remote LEA services in config file - * - * Returns void - * - ******************************************************************************/ -static void btif_set_remote_device_uuid_property(RawAddress p_addr, - int num_uuids, - bluetooth::Uuid *new_uuids) { - - Uuid remote_uuids[BT_MAX_NUM_UUIDS]; - bt_property_t prop; - - for (int j = 0; j < num_uuids; j++) { - remote_uuids[j] = new_uuids[j]; - BTIF_TRACE_EVENT("%s: UUID %s index %d ", __func__, - remote_uuids[j].ToString().c_str(), j); - } - prop.type = (bt_property_type_t)BT_PROPERTY_ADV_AUDIO_UUIDS; - prop.val = &remote_uuids[0]; - prop.len = (num_uuids) * (Uuid::kNumBytes128); - Uuid* tmp = (Uuid*)(prop.val); - BTIF_TRACE_EVENT("%s: Checking it %s", __func__, tmp->ToString().c_str()); - int ret = btif_storage_set_remote_device_property(&p_addr, &prop); - ASSERTC(ret == BT_STATUS_SUCCESS, "storing remote services failed", - ret); -} - -/******************************************************************************* - * - * Function btif_dm_lea_search_services_evt - * - * Description Executes search services event in btif context - * - * Returns void - * - ******************************************************************************/ -void btif_dm_lea_search_services_evt(uint16_t event, char* p_param) { - tBTA_DM_SEARCH* p_data = (tBTA_DM_SEARCH*)p_param; - - bt_bond_state_t pairing_state = BT_BOND_STATE_NONE; - uint8_t sdp_attempts = 0; - RawAddress pairing_bd_addr; - RawAddress static_bd_addr; - btif_get_pairing_cb_info(&pairing_state, &sdp_attempts, - &pairing_bd_addr, &static_bd_addr); - - BTIF_TRACE_EVENT("%s: event = %d", __func__, event); - switch (event) { - case BTA_DM_DISC_RES_EVT: { - uint32_t i = 0, j = 0; - bt_property_t prop[2]; - int num_properties = 0; - bt_status_t ret; - Uuid remote_uuids[BT_MAX_NUM_UUIDS]; - Uuid missed_remote_uuids[BT_MAX_NUM_UUIDS]; - uint8_t missing_uuids_len = 0; - bt_property_t remote_uuid_prop; - - RawAddress& bd_addr = p_data->disc_res.bd_addr; - - BTIF_TRACE_DEBUG("%s:(result=0x%x, services 0x%x)", __func__, - p_data->disc_res.result, p_data->disc_res.services); - - /* retry sdp service search, if sdp fails for pairing bd address, - ** report sdp results to APP immediately for non pairing addresses - */ - if ((p_data->disc_res.result != BTA_SUCCESS) && - (pairing_state == BT_BOND_STATE_BONDED) && - ((p_data->disc_res.bd_addr == pairing_bd_addr) || - (p_data->disc_res.bd_addr == static_bd_addr)) && - (sdp_attempts > 0)) { - if (sdp_attempts < BTIF_DM_MAX_SDP_ATTEMPTS_AFTER_PAIRING) { - BTIF_TRACE_WARNING("%s:SDP failed after bonding re-attempting", - - __func__); - btif_inc_sdp_attempts(); - btif_dm_get_remote_services_by_transport(&bd_addr, BT_TRANSPORT_BR_EDR); - return; - } else { - BTIF_TRACE_WARNING( - "%s: SDP reached to maximum attempts, sending bond fail to upper layers", - __func__); - btif_reset_sdp_attempts(); - if (bta_remote_device_is_dumo(bd_addr)) { - auto itr = bta_lea_pairing_cb.dev_addr_map.find(bd_addr); - if (itr != bta_lea_pairing_cb.dev_addr_map.end()) { - if ((itr->first != itr->second)) { - bta_lea_pairing_cb.is_sdp_discover = false; - bond_state_changed(BT_STATUS_FAIL, - bd_addr, BT_BOND_STATE_NONE); - } else { - btif_reset_pairing_cb(); - BTIF_TRACE_WARNING("%s: Skipping BOND_NONE for %s", __func__, - bd_addr.ToString().c_str()); - } - } else { - BTIF_TRACE_ERROR("%s: SDP shouldnt on random address. Wrong path %s", __func__, - bd_addr.ToString().c_str()); - btif_reset_pairing_cb(); - bond_state_changed(BT_STATUS_FAIL, - bd_addr, BT_BOND_STATE_NONE); - btif_storage_remove_bonded_device(&bd_addr); - BTA_DmRemoveDevice(bd_addr); - } - return; - } else { - BTIF_TRACE_ERROR("%s: SDP shouldnt called. Wrong path %s", __func__, - bd_addr.ToString().c_str()); - } - } - } - prop[0].type = BT_PROPERTY_UUIDS; - prop[0].len = 0; - if ((p_data->disc_res.result == BTA_SUCCESS) && - (p_data->disc_res.num_uuids > 0)) { - prop[0].val = p_data->disc_res.p_uuid_list; - prop[0].len = p_data->disc_res.num_uuids * Uuid::kNumBytes128; - - for (i = 0; i < p_data->disc_res.num_uuids; i++) { - std::string temp = ((p_data->disc_res.p_uuid_list + i))->ToString(); - LOG_INFO(LOG_TAG, "%s index:%d uuid:%s", __func__, i, temp.c_str()); - } - } - - /* onUuidChanged requires getBondedDevices to be populated. - ** bond_state_changed needs to be sent prior to remote_device_property - */ - if ((pairing_state == BT_BOND_STATE_BONDED && sdp_attempts) && - (p_data->disc_res.bd_addr == pairing_bd_addr || - p_data->disc_res.bd_addr == static_bd_addr)) { - LOG_INFO(LOG_TAG, "%s: SDP search done for %s", __func__, - bd_addr.ToString().c_str()); - btif_reset_sdp_attempts(); - BTA_DmResetPairingflag(bd_addr); - btif_reset_pairing_cb(); - - // Send one empty UUID to Java to unblock pairing intent when SDP failed - // or no UUID is discovered - if (p_data->disc_res.result != BTA_SUCCESS || - p_data->disc_res.num_uuids == 0) { - LOG_INFO(LOG_TAG, - "%s: SDP failed, send empty UUID to unblock bonding %s", - __func__, bd_addr.ToString().c_str()); - bt_property_t prop; - - Uuid uuid = {}; - //Updating in lea_pairing_database - if (bta_remote_device_is_dumo(bd_addr)) { - tBTA_DEV_PAIRING_CB *p_lea_pair_cb = NULL; - - p_lea_pair_cb = bta_get_lea_pair_cb(bd_addr); - if (p_lea_pair_cb) { - p_lea_pair_cb->sdp_disc_status = false; - } - } - - if (btif_dm_get_adv_audio_transport(bd_addr) == BT_TRANSPORT_BR_EDR) - { - prop.type = BT_PROPERTY_UUIDS; - } else { - prop.type = (bt_property_type_t)BT_PROPERTY_ADV_AUDIO_UUIDS; - } - prop.val = &uuid; - prop.len = Uuid::kNumBytes128; - - /* Send the event to the BTIF */ - HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, - BT_STATUS_SUCCESS, &bd_addr, 1, &prop); - break; - } - } - - // updates extra uuids which are discovered during - // new sdp search to existing uuid list present in conf file. - // If conf file has more UUIDs than the sdp search, it will - // update the conf file UUIDs as the final UUIDs - BTIF_STORAGE_FILL_PROPERTY(&remote_uuid_prop, BT_PROPERTY_UUIDS, - sizeof(remote_uuids), remote_uuids); - btif_storage_get_remote_device_property(&bd_addr, - &remote_uuid_prop); - if(remote_uuid_prop.len && p_data->disc_res.result == BTA_SUCCESS) { - // compare now - bool uuid_found = false; - uint8_t uuid_len = remote_uuid_prop.len / sizeof(Uuid); - for (i = 0; i < p_data->disc_res.num_uuids; i++) { - uuid_found = false; - Uuid* disc_uuid = reinterpret_cast (p_data->disc_res.p_uuid_list + i); - for (j = 0; j < uuid_len; j++) { - Uuid* base_uuid = reinterpret_cast (remote_uuid_prop.val) + j; - if(*disc_uuid == *base_uuid) { - uuid_found = true; - break; - } - } - if(!uuid_found) { - BTIF_TRACE_WARNING("%s:new uuid found ", __func__); - memcpy(&missed_remote_uuids[missing_uuids_len++], disc_uuid, sizeof(Uuid)); - } - } - - // add the missing uuids now - if(missing_uuids_len) { - BTIF_TRACE_WARNING("%s :missing_uuids_len = %d ", __func__, missing_uuids_len); - for (j = 0; j < missing_uuids_len && - (unsigned long)remote_uuid_prop.len < BT_MAX_NUM_UUIDS * sizeof(Uuid); j++) { - memcpy(&remote_uuids[uuid_len + j], &missed_remote_uuids[j], sizeof(Uuid)); - remote_uuid_prop.len += sizeof(Uuid); - } - } - - prop[0].type = BT_PROPERTY_UUIDS; - prop[0].val = remote_uuids; - prop[0].len = remote_uuid_prop.len; - ret = btif_storage_set_remote_device_property(&bd_addr, &prop[0]); - ASSERTC(ret == BT_STATUS_SUCCESS, "storing remote services failed", - ret); - //Send the UUID values to upper layer as BT_PROPERTY_ADV_AUDIO_UUIDS - num_properties++; - - if (bta_is_bredr_primary_transport(bd_addr)) { - BTIF_TRACE_WARNING("%s: Initiating LE connection ", __func__); - adv_audio_device_db[bd_addr] = MAJOR_LE_AUDIO_VENDOR_COD; - bta_le_audio_dev_cb.bond_progress = true; - bta_dm_adv_audio_gatt_conn(bd_addr); - } - } else if (p_data->disc_res.num_uuids != 0) { - /* Also write this to the NVRAM */ - ret = btif_storage_set_remote_device_property(&bd_addr, &prop[0]); - ASSERTC(ret == BT_STATUS_SUCCESS, "storing remote services failed", - ret); - num_properties++; - } - - /* Remote name update */ - if (strlen((const char *) p_data->disc_res.bd_name)) { - prop[1].type = BT_PROPERTY_BDNAME; - prop[1].val = p_data->disc_res.bd_name; - prop[1].len = strlen((char *)p_data->disc_res.bd_name); - - ret = btif_storage_set_remote_device_property(&bd_addr, &prop[1]); - ASSERTC(ret == BT_STATUS_SUCCESS, "failed to save remote device property", ret); - num_properties++; - } - - if (num_properties > 0) { - if (btif_dm_get_adv_audio_transport(bd_addr) == BT_TRANSPORT_BR_EDR) - { - prop[0].type = BT_PROPERTY_UUIDS; - } else { - prop[0].type = (bt_property_type_t)BT_PROPERTY_ADV_AUDIO_UUIDS; - } - /* Send the event to the BTIF */ - HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, BT_STATUS_SUCCESS, - &bd_addr, num_properties, prop); - } - - int validAddr = 1; - bt_property_t rem_prop; - BTIF_STORAGE_GET_REMOTE_PROP(&bd_addr, (bt_property_type_t)BT_PROPERTY_REM_DEViCE_VALID_ADDR, - &validAddr, sizeof(int), - rem_prop); - - if (validAddr != 0) { - bt_property_t prop_addr; - int is_valid = bta_is_adv_audio_valid_bdaddr(bd_addr); - prop_addr.type = (bt_property_type_t)BT_PROPERTY_REM_DEViCE_VALID_ADDR; - prop_addr.val = (void *)&is_valid; - prop_addr.len = sizeof(int); - ret = btif_storage_set_remote_device_property(&bd_addr, &prop_addr); - ASSERTC(ret == BT_STATUS_SUCCESS, "failed to save remote device property", ret); - } - - bt_device_type_t dev_type; - dev_type = (bt_device_type_t)BT_DEVICE_TYPE_DUMO; - bt_property_t prop_dev; - BTIF_STORAGE_FILL_PROPERTY(&prop_dev, - BT_PROPERTY_TYPE_OF_DEVICE, sizeof(dev_type), - &dev_type); - ret = btif_storage_set_remote_device_property(&bd_addr, &prop_dev); - ASSERTC(ret == BT_STATUS_SUCCESS, "failed to save remote device type", - ret); - - HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, BT_STATUS_SUCCESS, - &bd_addr, 1, &prop_dev); - - /* If below condition is true, it means LE random advertising - * has no ADV audio uuids, but identity address contains adv audio bit - * As per current design, if pairing initiated through non adv audio - * address then we dont need to fetch ADV audio role and services - */ - if ((btif_get_is_adv_audio_pair_info(bd_addr) == 0)) { - prop_dev.type = (bt_property_type_t)BT_PROPERTY_ADV_AUDIO_ACTION_UUID; - prop_dev.val = (void *)&validAddr; - prop_dev.len = sizeof(uint8_t); - HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, BT_STATUS_SUCCESS, - &bd_addr, 1, &prop_dev); - } - - } break; - - case BTA_DM_DISC_CMPL_EVT: - /* fixme */ - break; - - case BTA_DM_SEARCH_CANCEL_CMPL_EVT: - /* no-op */ - break; - - case BTA_DM_DISC_BLE_RES_EVT: { - BTIF_TRACE_DEBUG("%s: service %s", __func__, - p_data->disc_ble_res.service.ToString().c_str()); - bt_property_t prop; - bt_status_t ret; - RawAddress& bd_addr = p_data->disc_ble_res.bd_addr; - /* Remote name update */ - if (strnlen((const char*)p_data->disc_ble_res.bd_name, BD_NAME_LEN)) { - prop.type = BT_PROPERTY_BDNAME; - prop.val = p_data->disc_ble_res.bd_name; - prop.len = - strnlen((char*)p_data->disc_ble_res.bd_name, BD_NAME_LEN); - - ret = btif_storage_set_remote_device_property(&bd_addr, &prop); - ASSERTC(ret == BT_STATUS_SUCCESS, - "failed to save remote device property", ret); - /* Send the event to the BTIF */ - HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, BT_STATUS_SUCCESS, - &bd_addr, 1, &prop); - } - } break; - - case BTA_DM_LE_AUDIO_SEARCH_CMPL_EVT: - { - tBTA_DEV_PAIRING_CB *p_lea_pair_cb = NULL; - p_lea_pair_cb = bta_get_lea_pair_cb(p_data->disc_ble_res.bd_addr); - if (p_lea_pair_cb != NULL) { - btif_reset_pairing_cb(); - bt_property_t prop[5], prop_tmp[2]; - RawAddress& bd_addr = p_data->disc_ble_res.bd_addr; - int num_properties = 0; - bool id_addr_action_uuid = false; - RawAddress id_addr = bta_get_rem_dev_id_addr(bd_addr); - - prop[num_properties].type = (bt_property_type_t)BT_PROPERTY_ADV_AUDIO_UUIDS; - prop[num_properties].val = p_data->adv_audio_disc_cmpl.adv_audio_uuids; - prop[num_properties].len = p_data->adv_audio_disc_cmpl.num_uuids * - Uuid::kNumBytes128; - /* Also write this to the NVRAM */ - bt_property_t cod_prop1; - uint32_t cod_p; - - BTIF_STORAGE_FILL_PROPERTY(&cod_prop1, - BT_PROPERTY_CLASS_OF_DEVICE, sizeof(cod_p), &cod_p); - btif_storage_get_remote_device_property(&bd_addr, - &cod_prop1); - int ret; - cod_p |= MAJOR_LE_AUDIO_VENDOR_COD; - BTIF_STORAGE_FILL_PROPERTY(&cod_prop1, - BT_PROPERTY_CLASS_OF_DEVICE, sizeof(cod_p), &cod_p); - ret = btif_storage_set_remote_device_property(&bd_addr, &cod_prop1); - ASSERTC(ret == BT_STATUS_SUCCESS, - "failed to save remote device property", ret); - - if (bta_remote_device_is_dumo(bd_addr) - && (id_addr != bd_addr) && (bta_lea_pairing_cb.is_sdp_discover == true)) { - if(id_addr != RawAddress::kEmpty) { - BTIF_TRACE_DEBUG("%s: Found BT_PROPERTY_ADV_AUDIO_UUIDS %s", - p_data->adv_audio_disc_cmpl.adv_audio_uuids[0].ToString().c_str(), - id_addr.ToString().c_str()); - - bt_property_t cod_prop; - uint32_t cod; - - BTIF_STORAGE_FILL_PROPERTY(&cod_prop, - BT_PROPERTY_CLASS_OF_DEVICE, sizeof(cod), &cod); - btif_storage_get_remote_device_property(&id_addr, - &cod_prop); - BTIF_TRACE_DEBUG("%s: Cod is %x", __func__, cod); - cod |= MAJOR_LE_AUDIO_VENDOR_COD; - BTIF_STORAGE_FILL_PROPERTY(&cod_prop, - BT_PROPERTY_CLASS_OF_DEVICE, sizeof(cod), &cod); - ret = btif_storage_set_remote_device_property(&id_addr, &cod_prop); - ASSERTC(ret == BT_STATUS_SUCCESS, - "failed to save remote device property", ret); - num_properties++; - prop[num_properties].type = BT_PROPERTY_CLASS_OF_DEVICE; - prop[num_properties].val = (void *) &cod; - prop[num_properties].len = sizeof(cod); - - num_properties ++; - - BTIF_STORAGE_FILL_PROPERTY(&prop[num_properties], - (bt_property_type_t)BT_PROPERTY_REM_DEV_IDENT_BD_ADDR, sizeof(RawAddress), &bd_addr); - ret = btif_storage_set_remote_device_property(&id_addr, &prop[num_properties]); - ASSERTC(ret == BT_STATUS_SUCCESS, - "failed to save remote device property", ret); - - id_addr_action_uuid = true; - HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, BT_STATUS_SUCCESS, - &id_addr, 3, &prop[0]); - } - } - num_properties = 1; - - BTIF_STORAGE_FILL_PROPERTY(&prop[num_properties], - (bt_property_type_t)BT_PROPERTY_REM_DEV_IDENT_BD_ADDR, sizeof(RawAddress), &id_addr); - - ret = btif_storage_set_remote_device_property(&bd_addr, &prop[num_properties]); - ASSERTC(ret == BT_STATUS_SUCCESS, - "failed to save remote device property", ret); - - HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, BT_STATUS_SUCCESS, - &bd_addr, 2, &prop[0]); - - int validAddr = 1; - bt_property_t rem_prop; - BTIF_STORAGE_GET_REMOTE_PROP(&bd_addr, (bt_property_type_t)BT_PROPERTY_REM_DEViCE_VALID_ADDR, - &validAddr, sizeof(int), - rem_prop); - validAddr = bta_is_adv_audio_valid_bdaddr(bd_addr); - BTIF_TRACE_DEBUG("%s: is Valid Address Check value %d bd_addr %s", __func__, validAddr, bd_addr.ToString().c_str()); - prop_tmp[0].type = (bt_property_type_t)BT_PROPERTY_REM_DEViCE_VALID_ADDR; - prop_tmp[0].val = (void *)&validAddr; - prop_tmp[0].len = sizeof(int); - ret = btif_storage_set_remote_device_property(&bd_addr, &prop_tmp[0]); - ASSERTC(ret == BT_STATUS_SUCCESS, "failed to save remote device property", ret); - - prop_tmp[1].type = (bt_property_type_t)BT_PROPERTY_ADV_AUDIO_ACTION_UUID; - prop_tmp[1].val = (void *)&validAddr; - prop_tmp[1].len = sizeof(uint8_t); - - if (id_addr_action_uuid) { - BTIF_TRACE_DEBUG("%s: IDENTITY ADDR ACTION UUID %s ", __func__, - id_addr.ToString().c_str()); - HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, BT_STATUS_SUCCESS, - &id_addr, 1, &prop_tmp[1]); - } - - HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, BT_STATUS_SUCCESS, - &bd_addr, 2, &prop_tmp[0]); - if (id_addr_action_uuid) { - btif_set_remote_device_uuid_property(id_addr, - p_data->adv_audio_disc_cmpl.num_uuids, &p_data->adv_audio_disc_cmpl.adv_audio_uuids[0]); - } - btif_set_remote_device_uuid_property(bd_addr, - p_data->adv_audio_disc_cmpl.num_uuids, &p_data->adv_audio_disc_cmpl.adv_audio_uuids[0]); - - bta_dm_adv_audio_close(bd_addr); - bta_dm_reset_lea_pairing_info(bd_addr); - } else { - BTIF_TRACE_DEBUG("%s: ONCE AGAIN WRITING IDENTITY", __func__); - } - } - break; - default: { ASSERTC(0, "unhandled search services event", event); } break; - } -} - -/**************************************************************************** - * - * Function btif_register_uuid_srvc_disc - * - * Description Add to UUID to the service search queue - * - * Returns void - * - ****************************************************************************/ -void btif_register_uuid_srvc_disc(bluetooth::Uuid uuid) { - - uuid_srv_disc_search.push_back(uuid); - BTIF_TRACE_DEBUG("btif_register_uuid_srvc_disc, no of uuids %d %s", - uuid_srv_disc_search.size(), uuid.ToString().c_str()); -} - -void btif_dm_release_action_uuid(RawAddress bd_addr) { - - bt_property_t prop_dev; - int status = 1; - prop_dev.type = (bt_property_type_t)BT_PROPERTY_ADV_AUDIO_ACTION_UUID; - prop_dev.val = (void *)&status; - prop_dev.len = sizeof(uint8_t); - HAL_CBACK(bt_hal_cbacks, remote_device_properties_cb, BT_STATUS_SUCCESS, - &bd_addr, 1, &prop_dev); -} - -/**************************************************************************** - * - * Function check_adv_audio_cod - * - * Description This API is used to check whether COD contains LE Audio - * COD or not? - * - * Returns bool - * - ****************************************************************************/ -bool check_adv_audio_cod(uint32_t cod) { - - BTIF_TRACE_DEBUG("check_adv_audio_cod "); - - if (cod & MAJOR_LE_AUDIO_VENDOR_COD) { - return true; - } - return false; -} - -/******************************************************************************* - * - * Function is_remote_support_adv_audio - * - * Description is remote device is supporting LE audio or not - * - * Returns bool - * - ******************************************************************************/ - -bool is_remote_support_adv_audio(const RawAddress p_addr) { - if (adv_audio_device_db.find(p_addr) - != adv_audio_device_db.end()) { - BTIF_TRACE_DEBUG("%s %s LE AUDIO Support ", __func__, - p_addr.ToString().c_str()); - return true; - } - - bool status = bta_is_remote_support_lea(p_addr); - if (status) return true; - - bt_property_t cod_prop; - uint32_t cod_p; - - BTIF_STORAGE_FILL_PROPERTY(&cod_prop, - BT_PROPERTY_CLASS_OF_DEVICE, sizeof(cod_p), &cod_p); - btif_storage_get_remote_device_property(&p_addr, - &cod_prop); - - if ((cod_p & MAJOR_LE_AUDIO_VENDOR_COD) - == MAJOR_LE_AUDIO_VENDOR_COD) { - BTIF_TRACE_DEBUG("%s ADV AUDIO COD is matched ", __func__); - return true; - } - - return false; -} - -void bte_dm_adv_audio_search_services_evt(tBTA_DM_SEARCH_EVT event, - tBTA_DM_SEARCH* p_data) { - BTIF_TRACE_DEBUG(" %s ", __func__); - uint16_t param_len = 0; - if (p_data) param_len += sizeof(tBTA_DM_SEARCH); - switch (event) { - case BTA_DM_DISC_RES_EVT: { - if ((p_data && p_data->disc_res.result == BTA_SUCCESS) && - (p_data->disc_res.num_uuids > 0)) { - param_len += (p_data->disc_res.num_uuids * Uuid::kNumBytes128); - } - } break; - } - /* TODO: The only other member that needs a deep copy is the p_raw_data. But - * * not sure - * * if raw_data is needed. */ - btif_transfer_context( - btif_dm_lea_search_services_evt, event, (char*)p_data, param_len, - (param_len > sizeof(tBTA_DM_SEARCH)) ? search_services_copy_cb : NULL); -} - diff --git a/le_audio/system/bt/btif/src/btif_mcp.cc b/le_audio/system/bt/btif/src/btif_mcp.cc deleted file mode 100644 index 35b4ee952911a65a90c032842f9368dc15e9c2d3..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/src/btif_mcp.cc +++ /dev/null @@ -1,185 +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. - * - ******************************************************************************/ - - -/* MCP Interface */ -#define LOG_TAG "bt_btif_mcp" - -#include "bt_target.h" -#include "bta_closure_api.h" -#include "bta_mcp_api.h" -#include "btif_common.h" -#include "btif_storage.h" - -#include -#include -#include -#include - -using base::Bind; -using base::Unretained; -using base::Owned; -using bluetooth::Uuid; -using std::vector; -using base::Bind; -using base::Unretained; - -using bluetooth::mcp_server::McpServerCallbacks; -using bluetooth::mcp_server::McpServerInterface; - -namespace { -class McpServerInterfaceImpl; -std::unique_ptr McpServerInstance; - -class McpServerInterfaceImpl - : public McpServerInterface, public McpServerCallbacks { - ~McpServerInterfaceImpl() = default; - - void Init(McpServerCallbacks* callback, Uuid bt_uuid) override { - LOG(INFO) << __func__ ; - this->callbacks = callback; - do_in_bta_thread(FROM_HERE, - Bind(&McpServer::Initialize, this, bt_uuid)); - } - - void MediaState(uint8_t state) override { - LOG(INFO) << __func__ << ": state " << state; - do_in_bta_thread(FROM_HERE, - Bind(&McpServer::MediaState, Unretained(McpServer::Get()), state)); - } - - void MediaPlayerName(uint8_t* name) override { - LOG(INFO) << __func__ << ": name" << name; - do_in_bta_thread(FROM_HERE, - Bind(&McpServer::MediaPlayerName, Unretained(McpServer::Get()), name)); - } - - void MediaControlPointOpcodeSupported(uint32_t feature) override { - LOG(INFO) << __func__ << ": feature" << feature; - do_in_bta_thread(FROM_HERE, - Bind(&McpServer::MediaControlPointOpcodeSupported, Unretained(McpServer::Get()), feature)); - } - - void MediaControlPoint(uint8_t value) override { - LOG(INFO) << __func__ << ": value" << value; - do_in_bta_thread(FROM_HERE, - Bind(&McpServer::MediaControlPoint, Unretained(McpServer::Get()), value)); - } - - void TrackChanged(bool status) override { - LOG(INFO) << __func__ << ": status" << status; - do_in_bta_thread(FROM_HERE, - Bind(&McpServer::TrackChanged, Unretained(McpServer::Get()), status)); - } - - void TrackTitle(uint8_t* title) override { - LOG(INFO) << __func__ << ": title" << title; - do_in_bta_thread(FROM_HERE, - Bind(&McpServer::TrackTitle, Unretained(McpServer::Get()), title)); - } - - void TrackPosition(int32_t position) override { - LOG(INFO) << __func__ << ": position" << position; - do_in_bta_thread(FROM_HERE, - Bind(&McpServer::TrackPosition, Unretained(McpServer::Get()), position)); - } - - void TrackDuration(int32_t duration) override { - LOG(INFO) << __func__ << ": duration" << duration; - do_in_bta_thread(FROM_HERE, - Bind(&McpServer::TrackDuration, Unretained(McpServer::Get()), duration)); - } - - void ContentControlId(uint8_t ccid) override { - LOG(INFO) << __func__ << ": ccid" << ccid; - do_in_bta_thread(FROM_HERE, - Bind(&McpServer::ContentControlId, Unretained(McpServer::Get()), ccid)); - } - - void PlayingOrderSupported(uint16_t order) override { - LOG(INFO) << __func__ << ": order" << order; - do_in_bta_thread(FROM_HERE, - Bind(&McpServer::PlayingOrderSupported, Unretained(McpServer::Get()), order)); - } - - void PlayingOrder(uint8_t value) override { - LOG(INFO) << __func__ << ": value" << value; - do_in_bta_thread(FROM_HERE, - Bind(&McpServer::PlayingOrder, Unretained(McpServer::Get()), value)); - } - - void SetActiveDevice(const RawAddress& address, int set_id, int profile) override { - LOG(INFO) << __func__ << ": set_id" << set_id<< ": device"<< address; - do_in_bta_thread(FROM_HERE, - Bind(&McpServer::SetActiveDevice, Unretained(McpServer::Get()), address, set_id, profile)); - } - - void DisconnectMcp(const RawAddress& address) override { - LOG(INFO) << __func__ << ": device"<< address; - do_in_bta_thread(FROM_HERE, - Bind(&McpServer::DisconnectMcp, Unretained(McpServer::Get()), address)); - } - - void BondStateChange(const RawAddress& address, int state) override { - LOG(INFO) << __func__ << ": device"<< address << " state : " << state; - do_in_bta_thread(FROM_HERE, - Bind(&McpServer::BondStateChange, Unretained(McpServer::Get()), address, state)); - } - - void Cleanup(void) override { - LOG(INFO) << __func__; - do_in_bta_thread(FROM_HERE, Bind(&McpServer::CleanUp)); - } - - void OnConnectionStateChange(int status, - const RawAddress& address) override { - LOG(INFO) << __func__ << ": device=" << address << " state=" << (int)status; - do_in_jni_thread(FROM_HERE, Bind(&McpServerCallbacks::OnConnectionStateChange, - Unretained(callbacks), status, address)); - } - - void MediaControlPointChangeReq(uint8_t state, - const RawAddress& address) override { - LOG(INFO) << __func__ << ": device=" << address << " state=" << (int)state; - do_in_jni_thread(FROM_HERE, Bind(&McpServerCallbacks::MediaControlPointChangeReq, - Unretained(callbacks), state, address)); - } - - void TrackPositionChangeReq(int32_t position) override { - LOG(INFO) << __func__ << " position=" << (int)position; - do_in_jni_thread(FROM_HERE, Bind(&McpServerCallbacks::TrackPositionChangeReq, - Unretained(callbacks), position)); - } - - void PlayingOrderChangeReq(uint32_t order) override { - LOG(INFO) << __func__ << ": order=" << order; - do_in_jni_thread(FROM_HERE, Bind(&McpServerCallbacks::PlayingOrderChangeReq, - Unretained(callbacks), order)); - } - - private: - McpServerCallbacks* callbacks; - }; -}//namespace - -const McpServerInterface* btif_mcp_server_get_interface(void) { - LOG(INFO) << __func__; - if (!McpServerInstance) - McpServerInstance.reset(new McpServerInterfaceImpl()); - return McpServerInstance.get(); -} diff --git a/le_audio/system/bt/btif/src/btif_pacs_client.cc b/le_audio/system/bt/btif/src/btif_pacs_client.cc deleted file mode 100644 index 8c0867a6562c56b558002845015c369a6c45b7c0..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/src/btif_pacs_client.cc +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/****************************************************************************** - * - * 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 "bta_closure_api.h" -#include "bta_pacs_client_api.h" -#include "btif_common.h" -#include "btif_storage.h" - -#include -#include -#include -#include -#include -#include -#include "osi/include/thread.h" - -using base::Bind; -using base::Unretained; -using bluetooth::bap::pacs::PacsClient; -using bluetooth::bap::pacs::CodecConfig; -using bluetooth::bap::pacs::ConnectionState; -using bluetooth::bap::pacs::PacsClientCallbacks; -using bluetooth::bap::pacs::PacsClientInterface; - - -namespace { - -class PacsClientInterfaceImpl; -std::unique_ptr PacsClientInstance; - -class PacsClientInterfaceImpl - : public PacsClientInterface, - public PacsClientCallbacks { - ~PacsClientInterfaceImpl() = default; - - void Init(PacsClientCallbacks* callbacks) override { - DVLOG(2) << __func__; - this->callbacks = callbacks; - - do_in_bta_thread( - FROM_HERE, - Bind(&PacsClient::Initialize, this)); - } - - void OnInitialized(int status, int client_id) override { - do_in_jni_thread(FROM_HERE, Bind(&PacsClientCallbacks::OnInitialized, - Unretained(callbacks), status, - client_id)); - } - - void OnConnectionState(const RawAddress& address, - ConnectionState state) override { - DVLOG(2) << __func__ << " address: " << address; - do_in_jni_thread(FROM_HERE, Bind(&PacsClientCallbacks::OnConnectionState, - Unretained(callbacks), address, state)); - } - - void OnAudioContextAvailable(const RawAddress& address, - uint32_t available_contexts) override { - do_in_jni_thread(FROM_HERE, - Bind(&PacsClientCallbacks::OnAudioContextAvailable, - Unretained(callbacks), - address, available_contexts)); - } - - void OnSearchComplete(int status, - const RawAddress& address, - std::vector sink_pac_records, - std::vector src_pac_records, - uint32_t sink_locations, - uint32_t src_locations, - uint32_t available_contexts, - uint32_t supported_contexts) override { - do_in_jni_thread(FROM_HERE, Bind(&PacsClientCallbacks::OnSearchComplete, - Unretained(callbacks), - status, - address, - sink_pac_records, - src_pac_records, - sink_locations, - src_locations, - available_contexts, - supported_contexts)); - } - - void Connect(uint16_t client_id, const RawAddress& address) override { - do_in_bta_thread(FROM_HERE, Bind(&PacsClient::Connect, - Unretained(PacsClient::Get()), - client_id, address, false)); - } - - void Disconnect(uint16_t client_id, const RawAddress& address) override { - do_in_bta_thread(FROM_HERE, Bind(&PacsClient::Disconnect, - Unretained(PacsClient::Get()), - client_id, address)); - } - - void StartDiscovery(uint16_t client_id, - const RawAddress& address) override { - do_in_bta_thread(FROM_HERE, Bind(&PacsClient::StartDiscovery, - Unretained(PacsClient::Get()), - client_id, address)); - } - - void GetAvailableAudioContexts(uint16_t client_id, - const RawAddress& address) override { - do_in_bta_thread(FROM_HERE, Bind(&PacsClient::GetAudioAvailability, - Unretained(PacsClient::Get()), - client_id, address)); - } - - void Cleanup(uint16_t client_id) override { - DVLOG(2) << __func__; - do_in_bta_thread(FROM_HERE, Bind(&PacsClient::CleanUp, client_id)); - } - - private: - PacsClientCallbacks* callbacks; -}; - -} // namespace - -PacsClientInterface* btif_pacs_client_get_interface() { - if (!PacsClientInstance) - PacsClientInstance.reset(new PacsClientInterfaceImpl()); - - return PacsClientInstance.get(); -} diff --git a/le_audio/system/bt/btif/src/btif_vcp_controller.cc b/le_audio/system/bt/btif/src/btif_vcp_controller.cc deleted file mode 100644 index 10ba2acab167f4f74cfacabbb0ad0911b7c4c1e5..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/src/btif_vcp_controller.cc +++ /dev/null @@ -1,131 +0,0 @@ -/* - *Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/****************************************************************************** - * - * 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. - * - ******************************************************************************/ - -/* Volume Control Profile Interface */ - -#include "bt_target.h" -#include "bta_closure_api.h" -#include "bta_vcp_controller_api.h" -#include "btif_common.h" -#include "btif_storage.h" - -#include -#include -#include -#include -#include -#include - -using base::Bind; -using base::Unretained; -using bluetooth::vcp_controller::ConnectionState; -using bluetooth::vcp_controller::VcpControllerCallbacks; -using bluetooth::vcp_controller::VcpControllerInterface; - -namespace { -class VcpControllerInterfaceImpl; -std::unique_ptr VcpControllerInstance; - -class VcpControllerInterfaceImpl - : public VcpControllerInterface, public VcpControllerCallbacks { - ~VcpControllerInterfaceImpl() = default; - - void Init(VcpControllerCallbacks* callbacks) override { - LOG(INFO) << __func__ ; - this->callbacks = callbacks; - - do_in_bta_thread( - FROM_HERE, - Bind(&VcpController::Initialize, this)); - } - - void OnConnectionState(ConnectionState state, - const RawAddress& address) override { - LOG(INFO) << __func__ << ": device=" << address << " state=" << (int)state; - do_in_jni_thread(FROM_HERE, Bind(&VcpControllerCallbacks::OnConnectionState, - Unretained(callbacks), state, address)); - } - - void OnVolumeStateChange(uint8_t volume, uint8_t mute, - const RawAddress& address) override { - LOG(INFO) << __func__ << ": device=" << address << " volume=" << loghex(volume) - << " mute=" << (int)mute; - do_in_jni_thread(FROM_HERE, Bind(&VcpControllerCallbacks::OnVolumeStateChange, - Unretained(callbacks), volume, mute, address)); - } - - void OnVolumeFlagsChange(uint8_t flags, - const RawAddress& address) override { - LOG(INFO) << __func__ << ": device=" << address << " flags=" << loghex(flags); - do_in_jni_thread(FROM_HERE, Bind(&VcpControllerCallbacks::OnVolumeFlagsChange, - Unretained(callbacks), flags, address)); - } - - void Connect(const RawAddress& address, bool isDirect) override { - LOG(INFO) << __func__ << ": device=" << address; - do_in_bta_thread(FROM_HERE, Bind(&VcpController::Connect, - Unretained(VcpController::Get()), address, isDirect)); - } - - void Disconnect(const RawAddress& address) override { - LOG(INFO) << __func__ << ": device=" << address; - do_in_bta_thread(FROM_HERE, Bind(&VcpController::Disconnect, - Unretained(VcpController::Get()), address)); - } - - void SetAbsVolume(uint8_t volume, const RawAddress& address) override { - LOG(INFO) << __func__ << ": device=" << address << " volume=" << loghex(volume); - do_in_bta_thread(FROM_HERE, Bind(&VcpController::SetAbsVolume, - Unretained(VcpController::Get()), address, volume)); - } - - void Mute(const RawAddress& address) override { - LOG(INFO) << __func__ << ": device=" << address; - do_in_bta_thread(FROM_HERE, Bind(&VcpController::Mute, - Unretained(VcpController::Get()), address)); - } - - void Unmute(const RawAddress& address) override { - LOG(INFO) << __func__ << ": device=" << address; - do_in_bta_thread(FROM_HERE, Bind(&VcpController::Unmute, - Unretained(VcpController::Get()), address)); - } - - void Cleanup(void) override { - LOG(INFO) << __func__; - do_in_bta_thread(FROM_HERE, Bind(&VcpController::CleanUp)); - } - - private: - VcpControllerCallbacks* callbacks; -}; - -} // namespace - -VcpControllerInterface* btif_vcp_get_controller_interface() { - LOG(INFO) << __func__; - if (!VcpControllerInstance) - VcpControllerInstance.reset(new VcpControllerInterfaceImpl()); - - return VcpControllerInstance.get(); -} - diff --git a/le_audio/system/bt/btif/src/btif_vmcp.cc b/le_audio/system/bt/btif/src/btif_vmcp.cc deleted file mode 100644 index 844ac9bd91a3ce3c8a66a94bf923dfe2f0dae784..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/btif/src/btif_vmcp.cc +++ /dev/null @@ -1,775 +0,0 @@ -/****************************************************************************** - * - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ******************************************************************************/ - - -#include -#include -#include -#include -#include - -#include "bt_types.h" -#include "bt_trace.h" - -#include -#include "btif_bap_codec_utils.h" -#include "btif_vmcp.h" -#include "btif_api.h" -#include - -using namespace std; - -unsigned long voice_codec_count, media_codec_count, qos_settings_count; - -// holds the value of current profile being parsed from xml -uint8_t current_profile = 1; - -std::vectorvmcp_voice_codec; -std::vectorvmcp_media_codec; -std::vectorvmcp_qos_low_lat_voice; -std::vectorvmcp_qos_low_lat_media; -std::vectorvmcp_qos_high_rel_media; - -std::vectorbap_voice_codec; -std::vectorbap_media_codec; -std::vectorbap_qos_low_lat_voice; -std::vectorbap_qos_low_lat_media; -std::vectorbap_qos_high_rel_media; - -std::vectorgcp_voice_codec; -std::vectorgcp_media_codec; -std::vectorgcp_qos_low_lat_voice; -std::vectorgcp_qos_low_lat_media; - -std::vectorwmcp_media_codec; -std::vectorwmcp_qos_high_rel_media; - -vector get_all_codec_configs(uint8_t profile, uint8_t context) -{ - vector ret_config; - CodecConfig temp_config; - vector *vptr = NULL; - - if (profile == VMCP) { - if (context == VOICE_CONTEXT) { - vptr = &vmcp_voice_codec; - } - else if(context == MEDIA_CONTEXT) { - vptr = &vmcp_media_codec; - } else { - // if no valid context is provided, use voice context - vptr = &vmcp_voice_codec; - } - } else if (profile == BAP) { - if (context == VOICE_CONTEXT) { - vptr = &bap_voice_codec; - } - else if(context == MEDIA_CONTEXT) { - vptr = &bap_media_codec; - } else { - // if no valid context is provided, use voice context - vptr = &bap_voice_codec; - } - } else if (profile == GCP) { - if (context == VOICE_CONTEXT) { - vptr = &gcp_voice_codec; - } - else if(context == MEDIA_CONTEXT) { - vptr = &gcp_media_codec; - } else { - // if no valid context is provided, use media context - vptr = &gcp_media_codec; - } - } else if (profile == WMCP) { - if(context == MEDIA_CONTEXT) { - vptr = &wmcp_media_codec; - } else { - // if no valid context is provided, use media context - vptr = &wmcp_media_codec; - } - } - - if (!vptr){ - return { }; - } - - for (uint8_t i = 0; i < (uint8_t)vptr->size(); i++) { - memset(&temp_config, 0, sizeof(CodecConfig)); - - temp_config.codec_type = CodecIndex::CODEC_INDEX_SOURCE_LC3; - - switch (vptr->at(i).freq_in_hz) - { - case SAMPLE_RATE_8000: - temp_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_8000; - break; - case SAMPLE_RATE_16000: - temp_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_16000; - break; - case SAMPLE_RATE_24000: - temp_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_24000; - break; - case SAMPLE_RATE_32000: - temp_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_32000; - break; - case SAMPLE_RATE_44100: - temp_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_44100; - break; - case SAMPLE_RATE_48000: - temp_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_48000; - break; - default: - break; - } - - if (vptr->at(i).frame_dur_msecs == FRM_DURATION_7_5_MS) - UpdateFrameDuration(&temp_config, static_cast(CodecFrameDuration::FRAME_DUR_7_5)); - else if (vptr->at(i).frame_dur_msecs == FRM_DURATION_10_MS) - UpdateFrameDuration(&temp_config, static_cast(CodecFrameDuration::FRAME_DUR_10)); - - UpdateOctsPerFrame(&temp_config, vptr->at(i).oct_per_codec_frm); - - ret_config.push_back(temp_config); - } - - return ret_config; -} - -vector get_preferred_codec_configs(uint8_t profile, uint8_t context) -{ - vector ret_config; - CodecConfig temp_config; - vector *vptr = NULL; - - if (profile == VMCP) { - if (context == VOICE_CONTEXT) { - vptr = &vmcp_voice_codec; - } - else if(context == MEDIA_CONTEXT) { - vptr = &vmcp_media_codec; - } else { - // if no valid context is provided, use voice context - vptr = &vmcp_voice_codec; - } - } else if (profile == BAP) { - if (context == VOICE_CONTEXT) { - vptr = &bap_voice_codec; - } - else if(context == MEDIA_CONTEXT) { - vptr = &bap_media_codec; - } else { - // if no valid context is provided, use voice context - vptr = &bap_voice_codec; - } - } else if (profile == GCP) { - if (context == VOICE_CONTEXT) { - vptr = &gcp_voice_codec; - } - else if(context == MEDIA_CONTEXT) { - vptr = &gcp_media_codec; - } else { - // if no valid context is provided, use media context - vptr = &gcp_media_codec; - } - } else if (profile == WMCP) { - if(context == MEDIA_CONTEXT) { - vptr = &wmcp_media_codec; - } else { - // if no valid context is provided, use media context - vptr = &wmcp_media_codec; - } - } - - if (!vptr) { - return {}; - } - - for (uint8_t i = 0; i < (uint8_t)vptr->size(); i++) { - if (vptr->at(i).mandatory == 1) { - memset(&temp_config, 0, sizeof(CodecConfig)); - - temp_config.codec_type = CodecIndex::CODEC_INDEX_SOURCE_LC3; - - switch (vptr->at(i).freq_in_hz) - { - case SAMPLE_RATE_8000: - temp_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_8000; - break; - case SAMPLE_RATE_16000: - temp_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_16000; - break; - case SAMPLE_RATE_24000: - temp_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_24000; - break; - case SAMPLE_RATE_32000: - temp_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_32000; - break; - case SAMPLE_RATE_44100: - temp_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_44100; - break; - case SAMPLE_RATE_48000: - temp_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_48000; - break; - default: - break; - } - - if (vptr->at(i).frame_dur_msecs == FRM_DURATION_7_5_MS) - UpdateFrameDuration(&temp_config, static_cast(CodecFrameDuration::FRAME_DUR_7_5)); - else if (vptr->at(i).frame_dur_msecs == FRM_DURATION_10_MS) - UpdateFrameDuration(&temp_config, static_cast(CodecFrameDuration::FRAME_DUR_10)); - - UpdateOctsPerFrame(&temp_config, vptr->at(i).oct_per_codec_frm); - - ret_config.push_back(temp_config); - } - } - - return ret_config; -} - -vector get_all_qos_params(uint8_t profile, uint8_t context) -{ - vector ret_config; - QoSConfig temp_config; - vector *vptr = NULL; - - if (profile == VMCP) { - if (context == VOICE_CONTEXT) - vptr = &vmcp_qos_low_lat_voice; - else if (context == MEDIA_LL_CONTEXT) - vptr = &vmcp_qos_low_lat_media; - else if (context == MEDIA_HR_CONTEXT) - vptr = &vmcp_qos_high_rel_media; - } else if (profile == BAP) { - if (context == VOICE_CONTEXT) - vptr = &bap_qos_low_lat_voice; - else if (context == MEDIA_LL_CONTEXT) - vptr = &bap_qos_low_lat_media; - else if (context == MEDIA_HR_CONTEXT) - vptr = &bap_qos_high_rel_media; - } else if (profile == GCP) { - if (context == VOICE_CONTEXT) - vptr = &gcp_qos_low_lat_voice; - else if (context == MEDIA_LL_CONTEXT) - vptr = &gcp_qos_low_lat_media; - } else if (profile == WMCP) { - if (context == MEDIA_HR_CONTEXT) - vptr = &wmcp_qos_high_rel_media; - } - - if (!vptr) { - return {}; - } - - for (uint8_t i = 0; i < (uint8_t)vptr->size(); i++) { - memset(&temp_config, 0, sizeof(QoSConfig)); - - switch (vptr->at(i).freq_in_hz) - { - case SAMPLE_RATE_8000: - temp_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_8000; - break; - case SAMPLE_RATE_16000: - temp_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_16000; - break; - case SAMPLE_RATE_24000: - temp_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_24000; - break; - case SAMPLE_RATE_32000: - temp_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_32000; - break; - case SAMPLE_RATE_44100: - temp_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_44100; - break; - case SAMPLE_RATE_48000: - temp_config.sample_rate = CodecSampleRate::CODEC_SAMPLE_RATE_48000; - break; - default: - break; - } - - temp_config.sdu_int_micro_secs = vptr->at(i).sdu_int_micro_secs; - temp_config.framing = vptr->at(i).framing; - temp_config.max_sdu_size = vptr->at(i).max_sdu_size; - temp_config.retrans_num = vptr->at(i).retrans_num; - temp_config.max_trans_lat = vptr->at(i).max_trans_lat; - temp_config.presentation_delay = vptr->at(i).presentation_delay; - temp_config.mandatory = vptr->at(i).mandatory; - - ret_config.push_back(temp_config); - } - - return ret_config; -} - -vector get_qos_params_for_codec(uint8_t profile, uint8_t context, CodecSampleRate freq, uint8_t frame_dur, uint8_t octets) -{ - vector ret_config; - QoSConfig temp_config; - vector *vptr = NULL; - uint32_t frame_dur_micro_sec = 0; - uint32_t local_freq = 0; - - if (frame_dur == static_cast(CodecFrameDuration::FRAME_DUR_7_5)) - frame_dur_micro_sec = FRM_DURATION_7_5_MS * 1000; - else if (frame_dur == static_cast(CodecFrameDuration::FRAME_DUR_10)) - frame_dur_micro_sec = FRM_DURATION_10_MS * 1000; - - switch (freq) - { - case CodecSampleRate::CODEC_SAMPLE_RATE_8000: - local_freq = SAMPLE_RATE_8000; - break; - case CodecSampleRate::CODEC_SAMPLE_RATE_16000: - local_freq = SAMPLE_RATE_16000; - break; - case CodecSampleRate::CODEC_SAMPLE_RATE_24000: - local_freq = SAMPLE_RATE_24000; - break; - case CodecSampleRate::CODEC_SAMPLE_RATE_32000: - local_freq = SAMPLE_RATE_32000; - break; - case CodecSampleRate::CODEC_SAMPLE_RATE_44100: - local_freq = SAMPLE_RATE_44100; - break; - case CodecSampleRate::CODEC_SAMPLE_RATE_48000: - local_freq = SAMPLE_RATE_48000; - break; - default: - break; - } - - if (profile == VMCP) { - if (context == VOICE_CONTEXT) - vptr = &vmcp_qos_low_lat_voice; - else if (context == MEDIA_LL_CONTEXT) - vptr = &vmcp_qos_low_lat_media; - else if (context == MEDIA_HR_CONTEXT) - vptr = &vmcp_qos_high_rel_media; - } else if (profile == BAP) { - if (context == VOICE_CONTEXT) - vptr = &bap_qos_low_lat_voice; - else if (context == MEDIA_LL_CONTEXT) { - BTIF_TRACE_IMP("%s: filling BAP LL vptr", __func__); - vptr = &bap_qos_low_lat_media; - } else if (context == MEDIA_HR_CONTEXT) { - BTIF_TRACE_IMP("%s: filling BAP HR vptr", __func__); - vptr = &bap_qos_high_rel_media; - } - } else if (profile == GCP) { - if (context == VOICE_CONTEXT) - vptr = &gcp_qos_low_lat_voice; - else if (context == MEDIA_LL_CONTEXT) - vptr = &gcp_qos_low_lat_media; - } else if (profile == WMCP) { - if (context == MEDIA_HR_CONTEXT) { - BTIF_TRACE_IMP("%s: filling WMCP HR vptr", __func__); - vptr = &wmcp_qos_high_rel_media; - } - } - - if (!vptr) { - return { }; - } - - BTIF_TRACE_IMP("%s: vptr size: %d", __func__, (uint8_t)vptr->size()); - BTIF_TRACE_IMP("%s: local_freq: %d, frame_dur_micro_sec: %d, octets: %d", - __func__, local_freq, frame_dur_micro_sec, octets); - - for (uint8_t i = 0; i < (uint8_t)vptr->size(); i++) { - BTIF_TRACE_IMP("%s: freq_in_hz: %d, sdu_int_micro_secs: %d, max_sdu_size: %d", - __func__, vptr->at(i).freq_in_hz, vptr->at(i).sdu_int_micro_secs, - vptr->at(i).max_sdu_size); - if (vptr->at(i).freq_in_hz == local_freq && - vptr->at(i).sdu_int_micro_secs == frame_dur_micro_sec && - vptr->at(i).max_sdu_size == octets) { - BTIF_TRACE_IMP("%s: Local and vptr matched.", __func__); - memset(&temp_config, 0, sizeof(QoSConfig)); - - temp_config.sample_rate = freq; - temp_config.sdu_int_micro_secs = vptr->at(i).sdu_int_micro_secs; - temp_config.framing = vptr->at(i).framing; - temp_config.max_sdu_size = vptr->at(i).max_sdu_size; - temp_config.retrans_num = vptr->at(i).retrans_num; - temp_config.max_trans_lat = vptr->at(i).max_trans_lat; - temp_config.presentation_delay = vptr->at(i).presentation_delay; - temp_config.mandatory = vptr->at(i).mandatory; - - ret_config.push_back(temp_config); - } - } - - return ret_config; -} - -bool is_leaf(xmlNode *node) -{ - xmlNode *child = node->children; - while(child) - { - if(child->type == XML_ELEMENT_NODE) - return false; - - child = child->next; - } - - return true; -} - -void parseCodecConfigs(xmlNode *input_node, int context) -{ - stack profile_node_stack; - unsigned int TempCodecCount = 0; - unsigned int TempFieldsCount = 0; - xmlNode *FirstChild = xmlFirstElementChild(input_node); - unsigned long CodecFields = xmlChildElementCount(FirstChild); - codec_config temp_codec_config; - memset(&temp_codec_config, 0, sizeof(codec_config)); - - - BTIF_TRACE_IMP("codec Fields count is %ld \n", CodecFields); - for (xmlNode *node = input_node->children; node != NULL || !profile_node_stack.empty(); node = node->children) - { - if (node == NULL) - { - node = profile_node_stack.top(); - profile_node_stack.pop(); - } - - if(node) - { - if(node->type == XML_ELEMENT_NODE) - { - if((is_leaf(node))) - { - string content = (const char*)(xmlNodeGetContent(node)); - if (content[0] == '\0') { - return; - } - if(!xmlStrcmp(node->name,(const xmlChar*)"SamplingFrequencyInHz")) - { - temp_codec_config.freq_in_hz = atoi(content.c_str()); - TempFieldsCount++; - } - else if(!xmlStrcmp(node->name, (const xmlChar*)"FrameDurationInMicroSecs")) - { - temp_codec_config.frame_dur_msecs = (float)atoi(content.c_str())/1000; - TempFieldsCount++; - } - else if(!xmlStrcmp(node->name, (const xmlChar*)"OctetsPerCodecFrame")) - { - temp_codec_config.oct_per_codec_frm = atoi(content.c_str()); - TempFieldsCount++; - } - else if(!xmlStrcmp(node->name, (const xmlChar*)"Mandatory")) - { - temp_codec_config.mandatory = atoi(content.c_str()); - TempFieldsCount++; - } - } - if(TempFieldsCount == CodecFields) - { - if (current_profile == VMCP) { - if (context == VOICE_CONTEXT) { - vmcp_voice_codec.push_back(temp_codec_config); - } else if (context == MEDIA_CONTEXT) { - vmcp_media_codec.push_back(temp_codec_config); - } - } else if (current_profile == BAP) { - if (context == VOICE_CONTEXT) { - bap_voice_codec.push_back(temp_codec_config); - } else if (context == MEDIA_CONTEXT) { - bap_media_codec.push_back(temp_codec_config); - } - } else if (current_profile == GCP) { - if (context == VOICE_CONTEXT) { - gcp_voice_codec.push_back(temp_codec_config); - } else if (context == MEDIA_CONTEXT) { - gcp_media_codec.push_back(temp_codec_config); - } - } else if (current_profile == WMCP) { - if (context == MEDIA_CONTEXT) { - BTIF_TRACE_IMP("%s: parsed codec config for wmcp", __func__); - wmcp_media_codec.push_back(temp_codec_config); - } - } - - TempFieldsCount = 0; - TempCodecCount++; - } - } - - if(node->next != NULL) - { - profile_node_stack.push(node->next); - node = node->next; - } - } // end of if (node) - } // end of for - if(context == VOICE_CONTEXT && TempCodecCount == voice_codec_count) - { - if (current_profile < GCP) { - BTIF_TRACE_IMP("All %ld CG codecs are parsed successfully\n", voice_codec_count); - } else { - BTIF_TRACE_IMP("All %ld GAT Rx codecs are parsed successfully\n", voice_codec_count); - } - } - else if(context == MEDIA_CONTEXT && TempCodecCount == media_codec_count) - { - if (current_profile < GCP) { - BTIF_TRACE_IMP("All %ld UMS codecs are parsed successfully\n", media_codec_count); - } else if (current_profile == GCP) { - BTIF_TRACE_IMP("All %ld GAT Tx codecs are parsed successfully\n", media_codec_count); - } else if (current_profile == WMCP) { - BTIF_TRACE_IMP("All %ld WM Rx codecs are parsed successfully\n", media_codec_count); - } - } -} - -void parseQoSConfigs(xmlNode *QoSInputNode, int context) -{ - stack QoS_Stack; - unsigned int TempQoSCodecCount = 0; - unsigned int TempQoSFieldsCount = 0; - xmlNode * FirstChild = xmlFirstElementChild(QoSInputNode); - unsigned long QoSCodecFields = xmlChildElementCount(FirstChild); - qos_config temp_qos_config ; - memset(&temp_qos_config, 0, sizeof(qos_config)); - - BTIF_TRACE_IMP("QoS Fields count %ld \n", QoSCodecFields); - for (xmlNode *node = QoSInputNode->children; node != NULL || !QoS_Stack.empty(); node = node->children) - { - if (node == NULL) - { - node = QoS_Stack.top(); - QoS_Stack.pop(); - } - if(node) - { - if(node->type == XML_ELEMENT_NODE) - { - if(is_leaf(node)) - { - string content = (const char*)(xmlNodeGetContent(node)); - if (content[0] == '\0') { - return; - } - if(!xmlStrcmp(node->name,(const xmlChar*)"SamplingFrequencyInHz")) - { - temp_qos_config.freq_in_hz = atoi(content.c_str()); - TempQoSFieldsCount++; - } - else if(!xmlStrcmp(node->name, (const xmlChar*)"SDUIntervalInMicroSecs")) - { - temp_qos_config.sdu_int_micro_secs = atoi(content.c_str()); - TempQoSFieldsCount++; - } - else if(!xmlStrcmp(node->name, (const xmlChar*)"Framing")) - { - temp_qos_config.framing = atoi(content.c_str()); - TempQoSFieldsCount++; - } - else if(!xmlStrcmp(node->name, (const xmlChar*)"MaxSDUSize")) - { - temp_qos_config.max_sdu_size = atoi(content.c_str()); - TempQoSFieldsCount++; - } - else if(!xmlStrcmp(node->name, (const xmlChar*)"RetransmissionNumber")) - { - temp_qos_config.retrans_num = atoi(content.c_str()); - TempQoSFieldsCount++; - } - else if(!xmlStrcmp(node->name, (const xmlChar*)"MaxTransportLatency")) - { - temp_qos_config.max_trans_lat = atoi(content.c_str()); - TempQoSFieldsCount++; - } - else if(!xmlStrcmp(node->name, (const xmlChar*)"PresentationDelay")) - { - temp_qos_config.presentation_delay = atoi(content.c_str()); - TempQoSFieldsCount++; - } - else if(!xmlStrcmp(node->name, (const xmlChar*)"Mandatory")) - { - temp_qos_config.mandatory = atoi(content.c_str()); - TempQoSFieldsCount++; - } - } - if(TempQoSFieldsCount == QoSCodecFields) - { - if(current_profile == VMCP) { - if (context == VOICE_CONTEXT) { - vmcp_qos_low_lat_voice.push_back(temp_qos_config); - } else if (context == MEDIA_LL_CONTEXT) { - vmcp_qos_low_lat_media.push_back(temp_qos_config); - } else if (context == MEDIA_HR_CONTEXT) { - vmcp_qos_high_rel_media.push_back(temp_qos_config); - } - } else if(current_profile == BAP) { - if (context == VOICE_CONTEXT) { - bap_qos_low_lat_voice.push_back(temp_qos_config); - } else if (context == MEDIA_LL_CONTEXT) { - bap_qos_low_lat_media.push_back(temp_qos_config); - } else if (context == MEDIA_HR_CONTEXT) { - bap_qos_high_rel_media.push_back(temp_qos_config); - } - } else if(current_profile == GCP) { - if (context == VOICE_CONTEXT) { - gcp_qos_low_lat_voice.push_back(temp_qos_config); - } else if (context == MEDIA_LL_CONTEXT) { - gcp_qos_low_lat_media.push_back(temp_qos_config); - } - } else if(current_profile == WMCP) { - if (context == MEDIA_HR_CONTEXT) { - BTIF_TRACE_IMP("%s: parsed qos config for wmcp", __func__); - wmcp_qos_high_rel_media.push_back(temp_qos_config); - } - } - - TempQoSFieldsCount = 0; - TempQoSCodecCount++; - } - } - if(node->next != NULL) - { - QoS_Stack.push(node->next); - node = node->next; - } - - } - } - if(TempQoSCodecCount == qos_settings_count) - { - if(context == VOICE_CONTEXT) - { - if (current_profile < GCP) { - BTIF_TRACE_IMP("All %ld CG Qos Config are parsed successfully\n", qos_settings_count); - } else { - BTIF_TRACE_IMP("All %ld GAT Rx Qos Config are parsed successfully\n", qos_settings_count); - } - } - else if(context == MEDIA_CONTEXT) - { - if (current_profile < GCP) { - BTIF_TRACE_IMP("All %ld UMS Qos Config are parsed successfully\n", qos_settings_count); - } else if (current_profile == GCP) { - BTIF_TRACE_IMP("All %ld GAT Tx Qos Config are parsed successfully\n", qos_settings_count); - } else if (current_profile == WMCP) { - BTIF_TRACE_IMP("All %ld WM Rx Qos Config are parsed successfully\n", qos_settings_count); - } - } - } -} - -void parse_xml(xmlNode *inputNode) -{ - stack S; - for (xmlNode *node = inputNode; node != NULL || !S.empty(); node = node->children) - { - if (node == NULL) - { - node = S.top(); - S.pop(); - } - if (node) - { - if (node->type == XML_ELEMENT_NODE) - { - if (!(is_leaf(node))) - { - string content = (const char *) (xmlNodeGetContent (node)); - if (content[0] == '\0') { - return; - } - if (!xmlStrcmp (node->name, (const xmlChar *) "VMCP")) - { - BTIF_TRACE_IMP("VMCP configs being parsed\n"); - current_profile = VMCP; - } - if (!xmlStrcmp (node->name, (const xmlChar *) "BAP")) - { - BTIF_TRACE_IMP("BAP configs being parsed\n"); - current_profile = BAP; - } - if (!xmlStrcmp (node->name, (const xmlChar *) "GCP")) - { - BTIF_TRACE_IMP("GCP configs being parsed\n"); - current_profile = GCP; - } - if (!xmlStrcmp (node->name, (const xmlChar *) "WMCP")) - { - BTIF_TRACE_IMP("WMCP configs being parsed\n"); - current_profile = WMCP; - } - - if (!xmlStrcmp (node->name, (const xmlChar *) "CodecCapabilitiesForVoice")) - { - voice_codec_count = xmlChildElementCount(node); - parseCodecConfigs(node, VOICE_CONTEXT); - } - else if (!xmlStrcmp (node->name, (const xmlChar *) "CodecCapabilitiesForMedia")) - { - media_codec_count = xmlChildElementCount(node); - parseCodecConfigs(node, MEDIA_CONTEXT); - } - else if (!xmlStrcmp (node->name, (const xmlChar *) "QosSettingsForLowLatencyVoice")) - { - qos_settings_count = xmlChildElementCount(node); - parseQoSConfigs(node, VOICE_CONTEXT); - } - else if (!xmlStrcmp (node->name, (const xmlChar *) "QosSettingsForLowLatencyMedia")) - { - qos_settings_count = xmlChildElementCount(node); - parseQoSConfigs(node, MEDIA_LL_CONTEXT); - } - else if (!xmlStrcmp (node->name, (const xmlChar *) "QosSettingsForHighReliabilityMedia")) - { - qos_settings_count = xmlChildElementCount(node); - parseQoSConfigs(node, MEDIA_HR_CONTEXT); - } - } - } - if(node->next != NULL) - { - S.push(node -> next); - } - } - } -} - -void btif_vmcp_init() { - xmlDoc *doc = NULL; - xmlNode *root_element = NULL; - - doc = xmlReadFile(LEAUDIO_CONFIG_PATH, NULL, 0); - if (doc == NULL) { - BTIF_TRACE_ERROR("Could not parse the XML file"); - } - - root_element = xmlDocGetRootElement(doc); - parse_xml(root_element); - xmlFreeDoc(doc); - xmlCleanupParser(); - - //Register Audio Gaming Service UUID (GCP) with Gattc - btif_register_uuid_srvc_disc(bluetooth::Uuid::FromString("12994b7e-6d47-4215-8c9e-aae9a1095ba3")); - - //Register Wireless Microphone Configuration Service UUID (WMCP) with Gattc - btif_register_uuid_srvc_disc(bluetooth::Uuid::FromString("2587db3c-ce70-4fc9-935f-777ab4188fd7")); -} diff --git a/le_audio/system/bt/common/state_machine.h b/le_audio/system/bt/common/state_machine.h deleted file mode 100644 index 62d92d2636f2f4846adf103389de48d06b070968..0000000000000000000000000000000000000000 --- a/le_audio/system/bt/common/state_machine.h +++ /dev/null @@ -1,214 +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 - -namespace bluetooth { - -namespace common { - -/** - * State machine used by Bluetooth native stack. - */ -class StateMachine { - public: - enum { kStateInvalid = -1 }; - - /** - * A class to represent the state in the State Machine. - */ - class State { - friend class StateMachine; - - public: - /** - * Constructor. - * - * @param sm the State Machine to use - * @param state_id the unique State ID. It should be a non-negative number. - */ - State(StateMachine& sm, int state_id) : sm_(sm), state_id_(state_id) {} - - virtual ~State() = default; - - /** - * Process an event. - * TODO: The arguments are wrong - used for backward compatibility. - * Will be replaced later. - * - * @param event the event type - * @param p_data the event data - * @return true if the processing was completed, otherwise false - */ - virtual bool ProcessEvent(uint32_t event, void* p_data) = 0; - - /** - * Get the State ID. - * - * @return the State ID - */ - int StateId() const { return state_id_; } - - protected: - /** - * Called when a state is entered. - */ - virtual void OnEnter() {} - - /** - * Called when a state is exited. - */ - virtual void OnExit() {} - - /** - * Transition the State Machine to a new state. - * - * @param dest_state_id the state ID to transition to. It must be one - * of the unique state IDs when the corresponding state was created. - */ - void TransitionTo(int dest_state_id) { sm_.TransitionTo(dest_state_id); } - - /** - * Transition the State Machine to a new state. - * - * @param dest_state the state to transition to. It cannot be nullptr. - */ - void TransitionTo(StateMachine::State* dest_state) { - sm_.TransitionTo(dest_state); - } - - private: - StateMachine& sm_; - int state_id_; - }; - - StateMachine() - : initial_state_(nullptr), - previous_state_(nullptr), - current_state_(nullptr) {} - ~StateMachine() { - for (auto& kv : states_) delete kv.second; - } - - /** - * Start the State Machine operation. - */ - void Start() { TransitionTo(initial_state_); } - - /** - * Quit the State Machine operation. - */ - void Quit() { previous_state_ = current_state_ = nullptr; } - - /** - * Get the current State ID. - * - * @return the current State ID - */ - int StateId() const { - if (current_state_ != nullptr) { - return current_state_->StateId(); - } - return kStateInvalid; - } - - /** - * Get the previous current State ID. - * - * @return the previous State ID - */ - int PreviousStateId() const { - if (previous_state_ != nullptr) { - return previous_state_->StateId(); - } - return kStateInvalid; - } - - /** - * Process an event. - * TODO: The arguments are wrong - used for backward compatibility. - * Will be replaced later. - * - * @param event the event type - * @param p_data the event data - * @return true if the processing was completed, otherwise false - */ - bool ProcessEvent(uint32_t event, void* p_data) { - if (current_state_ == nullptr) return false; - return current_state_->ProcessEvent(event, p_data); - } - - /** - * Transition the State Machine to a new state. - * - * @param dest_state_id the state ID to transition to. It must be one - * of the unique state IDs when the corresponding state was created. - */ - void TransitionTo(int dest_state_id) { - auto it = states_.find(dest_state_id); - - CHECK(it != states_.end()) << "Unknown State ID: " << dest_state_id; - State* dest_state = it->second; - TransitionTo(dest_state); - } - - /** - * Transition the State Machine to a new state. - * - * @param dest_state the state to transition to. It cannot be nullptr. - */ - void TransitionTo(StateMachine::State* dest_state) { - if (current_state_ != nullptr) { - current_state_->OnExit(); - } - previous_state_ = current_state_; - current_state_ = dest_state; - current_state_->OnEnter(); - } - - /** - * Add a state to the State Machine. - * The state machine takes ownership on the state - i.e., the state will - * be deleted by the State Machine itself. - * - * @param state the state to add - */ - void AddState(State* state) { - states_.insert(std::make_pair(state->StateId(), state)); - } - - /** - * Set the initial state of the State Machine. - * - * @param initial_state the initial state - */ - void SetInitialState(State* initial_state) { initial_state_ = initial_state; } - - private: - State* initial_state_; - State* previous_state_; - State* current_state_; - std::map states_; -}; - -} // namespace common - -} // namespace bluetooth diff --git a/le_audio/vhal/include/hardware/bluetooth_callcontrol_callbacks.h b/le_audio/vhal/include/hardware/bluetooth_callcontrol_callbacks.h deleted file mode 100644 index 7137867898ec4cddf7d3dfba32b22a19ea4e0954..0000000000000000000000000000000000000000 --- a/le_audio/vhal/include/hardware/bluetooth_callcontrol_callbacks.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - *Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. - */ - -/* - * Copyright 2017 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 call_control { - -/** - * CCS/GTBS related callbacks invoked from from the Bluetooth native stack - * All callbacks are invoked on the JNI thread - */ -class CallControllerCallbacks { - public: - virtual ~CallControllerCallbacks() = default; - /** - * Callback for notifying the CCS initialization status. - * - * @param state success if zero, failure otherwise - */ - virtual void CallControlInitializedCallback(uint8_t state - ) = 0; - /** - * Callback for connection state change. - * - * @param state one of the values from btcc_connection_state_t - * @param bd_addr remote device address - */ - virtual void ConnectionStateCallback(uint8_t state, - const RawAddress& address) = 0; - /** - * Callback for call control operations. - * - * @param op call control operation initiated from remote - * @param indicies Indicies for the call control operations - * @param count number of Indicies for the call control operations - * @uri uri for the call control operation - * @param bd_addr remote device address which initiated the call control op - */ - virtual void CallControlCallback(uint8_t op, std::vector indicies, int count, std::vector uri_data, - const RawAddress& address) = 0; -}; - -} // namespace callcontrol -} // namespace bluetooth diff --git a/le_audio/vhal/include/hardware/bluetooth_callcontrol_interface.h b/le_audio/vhal/include/hardware/bluetooth_callcontrol_interface.h deleted file mode 100644 index c2b784989950b2cd71b1707d6e1b2a63f2196dc0..0000000000000000000000000000000000000000 --- a/le_audio/vhal/include/hardware/bluetooth_callcontrol_interface.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - *Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. - */ - -/* - * Copyright 2017 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 "bluetooth_callcontrol_callbacks.h" -#include - -#define BT_PROFILE_CC_ID "cc_server" - -namespace bluetooth { -namespace call_control { - -/** - * Programming interface for CCS/GTBS profiles in the Fluoride stack - * Thread-safe - */ -class CallControllerInterface { - public: - virtual ~CallControllerInterface() = default; - /** - * Initialize the CCS/GTBS Interface - * - * @param callbacks callbacks for the user of the native stack - * @param max_ccs_clients maximum number of CCS/GTBS clients - * @param inband_ringing_enabled whether inband ringtone is enabled - * @return BT_STATUS_SUCCESS on success - */ - virtual bt_status_t Init(CallControllerCallbacks* callbacks, Uuid uuid, int max_ccs_clients, - bool inband_ringing_enabled) = 0; - /** - * Updates telephony bearer name - * - * @param operator_str bearer name of provider - * @return BT_STATUS_SUCCESS on success - */ - virtual bt_status_t UpdateBearerName(uint8_t* operator_str) = 0; - - /** - * Updates the bearer Technogly type - * - * @param bearer_tech bearer technology type of provider - * @return BT_STATUS_SUCCESS on success - */ - virtual bt_status_t UpdateBearerTechnology(int bearer_tech) = 0; - - /** - * Updates telephony network bearers supported - * - * @param supportedBearers supported bearers list - * @return BT_STATUS_SUCCESS on success - */ - virtual bt_status_t UpdateSupportedBearerList(uint8_t* supportedBearers) = 0; - - /** - * Updates optional Call control operations supported - * - * @param feature bitmask value representing the optional op code supported - * @return BT_STATUS_SUCCESS on success - */ - virtual bt_status_t CallControlOptionalOpSupported(int feature) = 0; - - /** - * Update network signal strength - * - * @param signal level - * @return BT_STATUS_SUCCESS on success - */ - virtual bt_status_t UpdateSignalStatus(int signal) = 0; - - /** - * Update status flag for GTBS - * - * @param bd_addr remote device address - * @return BT_STATUS_SUCCESS on success - */ - virtual bt_status_t UpdateStatusFlags(uint8_t status_flag) = 0; - - /** - * Update Content control for GTBS/CCS - * - * @param ccid content control Id for GTBS/CCS - * @return BT_STATUS_SUCCESS on success - */ - virtual void ContentControlId(uint32_t ccid) = 0; - - /** - * Update the Call State of CCS - * - * @param len of call state infos - * @param call_state_list array of call state list, where each call state - * comprised of index, state, flags - * @return BT_STATUS_SUCCESS on success - */ - virtual bt_status_t CallState(int len, std::vector call_state_list) = 0; - - /** - * Update Incoming call URI for the given Call Index - * - * @param index index of the call - * @param uri representing the Incoming call, will be Incoming call number for telephony - * @return BT_STATUS_SUCCESS on success - */ - - virtual void UpdateIncomingCall(int index, uint8_t* uri) = 0; - /** - * Response for Call control Operation initiated - * - * @param op Operation for which response is sent - * @param index index of call for operation - * @param status status of the operation performed - * @return BT_STATUS_SUCCESS on success - */ - virtual bt_status_t CallControlResponse(uint8_t op, uint8_t index, uint32_t status, const RawAddress& address) = 0; - - /** - * Set the current active device for GTBS/CCS - * - * @param active_device_addr remote device address - */ - virtual void SetActiveDevice(const RawAddress& address, int set_id) = 0; - - /** - * Disconnect GTBS/CTS profile for remote - * @param address remote device address - */ - virtual void Disconnect(const RawAddress& address) = 0; - /** - * Closes the GTBS/CCS interface. - */ - virtual void Cleanup() = 0; -}; - -} // namespace call_control -} // namespace bluetooth diff --git a/le_audio/vhal/include/hardware/bt_acm.h b/le_audio/vhal/include/hardware/bt_acm.h deleted file mode 100644 index f32fb90d96d56b8df3ebdb7ca9a588ebffa380a8..0000000000000000000000000000000000000000 --- a/le_audio/vhal/include/hardware/bt_acm.h +++ /dev/null @@ -1,126 +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. - * - ******************************************************************************/ - -#ifndef ANDROID_INCLUDE_BT_ACM_H -#define ANDROID_INCLUDE_BT_ACM_H - -#include - -#include -#include -#include - -__BEGIN_DECLS - -#define BT_PROFILE_ACM_ID "bt_acm_proflie" -using bluetooth::bap::pacs::CodecConfig; -/* Bluetooth ACM connection states */ -typedef enum { - BTACM_CONNECTION_STATE_DISCONNECTED = 0, - BTACM_CONNECTION_STATE_CONNECTING, - BTACM_CONNECTION_STATE_CONNECTED, - BTACM_CONNECTION_STATE_DISCONNECTING -} btacm_connection_state_t; - -/* Bluetooth ACM datapath states */ -typedef enum { - BTACM_AUDIO_STATE_REMOTE_SUSPEND = 0, - BTACM_AUDIO_STATE_STOPPED, - BTACM_AUDIO_STATE_STARTED, -} btacm_audio_state_t; - -/** Callback for connection state change. - * state will have one of the values from btacm_connection_state_t - */ -typedef void (*btacm_connection_state_callback)(const RawAddress& bd_addr, - btacm_connection_state_t state, - uint16_t contextType); - -/** Callback for audiopath state change. - * state will have one of the values from btacm_audio_state_t - */ -typedef void (*btacm_audio_state_callback)(const RawAddress& bd_addr, - btacm_audio_state_t state, - uint16_t contextType); - -/** Callback for audio configuration change. - * Used only for the ACM Initiator interface. - */ -typedef void (*btacm_audio_config_callback)( - const RawAddress& bd_addr, CodecConfig codec_config, - std::vector codecs_local_acmabilities, - std::vector codecs_selectable_acmabilities, - uint16_t contextType); - -/** BT-ACM Initiator callback structure. */ -typedef struct { - /** set to sizeof(btacm_initiator_callbacks_t) */ - size_t size; - btacm_connection_state_callback connection_state_cb; - btacm_audio_state_callback audio_state_cb; - btacm_audio_config_callback audio_config_cb; -} btacm_initiator_callbacks_t; - -/** Represents the standard BT-ACM Initiator interface. - */ -typedef struct { - /** set to sizeof(btacm_source_interface_t) */ - size_t size; - /** - * Register the BtAcm callbacks. - */ - bt_status_t (*init)( - btacm_initiator_callbacks_t* callbacks, int max_connected_audio_devices, - const std::vector& codec_priorities); - - /** connect to headset */ - bt_status_t (*connect)(const RawAddress& bd_addr, uint16_t context_type, - uint16_t profile_type, uint16_t preferred_context); - - /** dis-connect from headset */ - bt_status_t (*disconnect)(const RawAddress& bd_addr, uint16_t context_type); - - /** sets the connected device as active */ - bt_status_t (*set_active_device)(const RawAddress& bd_addr, - uint16_t context_type); - - /** start stream */ - bt_status_t (*start_stream)(const RawAddress& bd_addr, uint16_t context_type); - - /** stop stream */ - bt_status_t (*stop_stream)(const RawAddress& bd_addr, uint16_t context_type); - - /** configure the codecs settings preferences */ - bt_status_t (*config_codec)( - const RawAddress& bd_addr, - std::vector codec_preferences, - uint16_t context_type, uint16_t preferred_context); - - /** configure the codec based on ID*/ - bt_status_t (*change_config_codec)( - const RawAddress& bd_addr, - char* Id); - - /** Closes the interface. */ - void (*cleanup)(void); - -} btacm_initiator_interface_t; - -__END_DECLS - -#endif /* ANDROID_INCLUDE_BT_AV_H */ diff --git a/le_audio/vhal/include/hardware/bt_apm.h b/le_audio/vhal/include/hardware/bt_apm.h deleted file mode 100644 index 2eb95e32ac2f0809797e776f98b165d085e3e719..0000000000000000000000000000000000000000 --- a/le_audio/vhal/include/hardware/bt_apm.h +++ /dev/null @@ -1,75 +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. - * - ******************************************************************************/ - - -#ifndef ANDROID_INCLUDE_BT_APM_H -#define ANDROID_INCLUDE_BT_APM_H - -#define BT_APM_MODULE_ID "apm" - -#include - -#include - -__BEGIN_DECLS - -/* Bluetooth APM Audio Types */ -typedef enum { - BTAPM_VOICE_AUDIO = 0, - BTAPM_MEDIA_AUDIO, - BTAPM_BROADCAST_AUDIO -} btapm_audio_type_t; - -void call_active_profile_info(const RawAddress& bd_addr, uint16_t audio_type); -int get_active_profile(const RawAddress& bd_addr, uint16_t audio_type); -typedef int (*btapm_active_profile_callback)(const RawAddress& bd_addr, uint16_t audio_type); - - -typedef struct { - size_t size; - btapm_active_profile_callback active_profile_cb; -}btapm_initiator_callbacks_t; - - - -/** APM interface - */ -typedef struct { - - /** set to sizeof(bt_apm_interface_t) */ - size_t size; - /** - * Register the BtAv callbacks. - */ - bt_status_t (*init)(btapm_initiator_callbacks_t* callbacks); - - /** updates new active device to stack */ - bt_status_t (*active_device_change)(const RawAddress& bd_addr, uint16_t profile, uint16_t audio_type); - - /** send content control id to stack */ - bt_status_t (*set_content_control_id)(uint16_t content_control_id, uint16_t audio_type); - - /** Closes the interface. */ - void (*cleanup)( void ); - -}bt_apm_interface_t; - -__END_DECLS - -#endif /* ANDROID_INCLUDE_BT_APM_H */ - diff --git a/le_audio/vhal/include/hardware/bt_ascs_client.h b/le_audio/vhal/include/hardware/bt_ascs_client.h deleted file mode 100644 index cd9341b3d699a2538741114cea1c528647eaec58..0000000000000000000000000000000000000000 --- a/le_audio/vhal/include/hardware/bt_ascs_client.h +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - * - * 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. - */ - -#ifndef ANDROID_INCLUDE_BT_ASCS_CLIENT_H -#define ANDROID_INCLUDE_BT_ASCS_CLIENT_H - -#include - -namespace bluetooth { -namespace bap { -namespace ascs { - -#define BT_PROFILE_ASCS_CLIENT_ID "bt_ascs_client" - -constexpr uint8_t ASE_DIRECTION_SINK = 0x01; -constexpr uint8_t ASE_DIRECTION_SOURCE = 0x02; - -constexpr uint32_t CONTEXT_TYPE_CONVERSATIONAL = 0x0002; -constexpr uint32_t CONTEXT_TYPE_MEDIA = 0x0004; - -constexpr uint8_t ASE_STATE_IDLE = 0x00; -constexpr uint8_t ASE_STATE_CODEC_CONFIGURED = 0x01; -constexpr uint8_t ASE_STATE_QOS_CONFIGURED = 0x02; -constexpr uint8_t ASE_STATE_ENABLING = 0x03; -constexpr uint8_t ASE_STATE_STREAMING = 0x04; -constexpr uint8_t ASE_STATE_DISABLING = 0x05; -constexpr uint8_t ASE_STATE_RELEASING = 0x06; -constexpr uint8_t ASE_STATE_INVALID = 0xFF; - -typedef uint8_t sdu_interval_t[3]; -typedef uint8_t presentation_delay_t[3]; -typedef uint8_t codec_type_t[5]; - - -enum class ASCSEvent { - ASCS_DISCOVERY_CMPL_EVT = 0, - ASCS_DEV_CONNECTED, - ASCS_DEV_DISCONNECTED, - ASCS_ASE_STATE, -}; - -struct AudioContext { - uint8_t length; - uint8_t type; - uint16_t value; -}; - -enum class AseState { - IDLE = 0, - CODEC_CONFIGURED, - QOS_CONFIGURED, - ENABLING, - STREAMING, - DISABLING, - RELEASING, -}; - -enum class AseOpId { - CODEC_CONFIG = 0x01, - QOS_CONFIG, - ENABLE, - START_READY, - DISABLE, - STOP_READY, - UPDATE_META_DATA, - RELEASE -}; - -enum class GattState { - DISCONNECTED = 0, - CONNECTING, - CONNECTED, - DISCONNECTING -}; - -struct AseCodecConfigOp { - uint8_t ase_id; - uint8_t tgt_latency; - uint8_t tgt_phy; - codec_type_t codec_id; - uint8_t codec_params_len; - std::vector codec_params; -} __attribute__((packed)); - -struct AseQosConfigOp { - uint8_t ase_id; - uint8_t cig_id; - uint8_t cis_id; - sdu_interval_t sdu_interval; - uint8_t framing; - uint8_t phy; - uint16_t max_sdu_size; - uint8_t retrans_number; - uint16_t trans_latency; - presentation_delay_t present_delay; -} __attribute__((packed)); - -struct AseEnableOp { - uint8_t ase_id; - uint8_t meta_data_len; - std::vector meta_data; -} __attribute__((packed)); - -struct AseDisableOp { - uint8_t ase_id; -} __attribute__((packed)); - -struct AseStartReadyOp { - uint8_t ase_id; -} __attribute__((packed)); - -struct AseStopReadyOp { - uint8_t ase_id; -} __attribute__((packed)); - -struct AseReleaseOp { - uint8_t ase_id; -} __attribute__((packed)); - -struct AseUpdateMetadataOp { - uint8_t ase_id; - uint8_t meta_data_len; - std::vector meta_data; -} __attribute__((packed)); - -struct AseCodecConfigParams { - uint8_t framing; - uint8_t pref_phy; - uint8_t pref_rtn; - uint16_t mtl; - presentation_delay_t pd_min; - presentation_delay_t pd_max; - presentation_delay_t pref_pd_min; - presentation_delay_t pref_pd_max; - codec_type_t codec_id; - uint8_t codec_params_len; - std::vector codec_params; -} __attribute__((packed)); - -struct AseQosConfigParams { - uint8_t cig_id; - uint8_t cis_id; - sdu_interval_t sdu_interval; - uint8_t framing; - uint8_t phy; - uint16_t max_sdu_size; - uint8_t rtn; - uint16_t mtl; - presentation_delay_t pd; -} __attribute__((packed)); - -struct AseGenericParams { - uint8_t cig_id; - uint8_t cis_id; - uint8_t meta_data_len; - std::vector meta_data; -} __attribute__((packed)); - -union AseOp { - AseCodecConfigOp codec_config_op; - AseQosConfigOp qos_config_op; - AseEnableOp enable_op; - AseDisableOp disable_op; - AseStartReadyOp start_ready_op; - AseStopReadyOp stop_ready_op; - AseReleaseOp release_op; -}; - -struct AseOpStatus { - uint8_t ase_id; - uint8_t resp_code; - uint8_t reason; -}; - -struct AseParams { - uint8_t ase_id; - uint8_t ase_state; - AseCodecConfigParams codec_config_params; - AseQosConfigParams qos_config_params; - AseGenericParams generic_params; -} __attribute__((packed)); - -struct AseCpNotification { - uint8_t ase_opcode; - uint8_t num_ases; - std::vector status; -} __attribute__((packed)); - -struct Ase { - uint16_t ase_handle; - uint16_t ase_ccc_handle; - AseParams ase_params; -} __attribute__((packed)); - -struct AscsDiscoveryDb { - std::vector ase_list; - uint16_t ase_cp_handle; - uint16_t ase_cp_ccc_handle; - bool service_changed_rcvd; - bool active; -}; - -class AscsClientCallbacks { - public: - virtual ~AscsClientCallbacks() = default; - - /** Callback for ascs server registration status */ - virtual void OnAscsInitialized(int status, int client_id) = 0; - - /** Callback for ascs server connection state change */ - virtual void OnConnectionState(const RawAddress& address, - GattState state) = 0; - - /** Callback for ascs server control op failed status */ - virtual void OnAseOpFailed(const RawAddress& address, - AseOpId ase_op_id, - std::vector status) = 0; - - /** Callback for ascs ase state change */ - virtual void OnAseState(const RawAddress& address, - AseParams ase) = 0; - - /** Callback for ascs discovery results */ - virtual void OnSearchComplete(int status, const RawAddress& address, - std::vector sink_ase_list, - std::vector src_ase_list) = 0; -}; - -class AscsClientInterface { - public: - virtual ~AscsClientInterface() = default; - - /** Register the Ascs client callbacks */ - virtual void Init(AscsClientCallbacks* callbacks) = 0; - - /** Connect to ascs server */ - virtual void Connect(uint16_t client_id, const RawAddress& address) = 0; - - /** Disconnect ascs server */ - virtual void Disconnect(uint16_t client_id, const RawAddress& address) = 0; - - virtual void StartDiscovery(uint16_t client_id, - const RawAddress& address) = 0; - - virtual void GetAseState(uint16_t client_id, const RawAddress& address, - uint8_t ase_id) = 0; - - virtual void CodecConfig(uint16_t client_id, const RawAddress& address, - std::vector codec_configs); - - virtual void QosConfig(uint16_t client_id, const RawAddress& address, - std::vector qos_configs); - - virtual void Enable(uint16_t client_id, const RawAddress& address, - std::vector enable_ops); - - virtual void Disable(uint16_t client_id, const RawAddress& address, - std::vector disable_ops); - - virtual void StartReady(uint16_t client_id, const RawAddress& address, - std::vector start_ready_ops); - - virtual void StopReady(uint16_t client_id, const RawAddress& address, - std::vector stop_ready_ops); - - virtual void Release(uint16_t client_id, const RawAddress& address, - std::vector release_ops); - - virtual void UpdateStream(uint16_t client_id, const RawAddress& address, - std::vector metadata_ops); - - /** Closes the interface. */ - virtual void Cleanup(uint16_t client_id) = 0; -}; - -} // namespace ascs -} // namespace bap -} // namespace bluetooth - -#endif /* ANDROID_INCLUDE_BT_CLIENT_H */ diff --git a/le_audio/vhal/include/hardware/bt_bap_ba.h b/le_audio/vhal/include/hardware/bt_bap_ba.h deleted file mode 100644 index 58c5fbd91331b8955e0f9706091c659797255507..0000000000000000000000000000000000000000 --- a/le_audio/vhal/include/hardware/bt_bap_ba.h +++ /dev/null @@ -1,126 +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. - * - ******************************************************************************/ - -#ifndef ANDROID_INCLUDE_BT_BAP_BA_H -#define ANDROID_INCLUDE_BT_BAP_BA_H - -#include -#include "hardware/bt_av.h" - -__BEGIN_DECLS - -#define BT_PROFILE_BAP_BROADCAST_ID "bap_broadcast" - -/* Bluetooth BAP BROADCAST states */ -typedef enum { - BTBAP_BROADCAST_STATE_IDLE = 0, //Idle - BTBAP_BROADCAST_STATE_CONFIGURED, //Configured - BTBAP_BROADCAST_STATE_STREAMING, //Streaming -} btbap_broadcast_state_t; - -/* Bluetooth BAP BROADCAST Audio states */ -typedef enum { - BTBAP_BROADCAST_AUDIO_STATE_STOPPED = 0, - BTBAP_BROADCAST__AUDIO_STATE_STARTED, -} btbap_broadcast_audio_state_t; - -/** Callback for broadcast state change. - * state will have one of the values from btbap_broadcast_state_t - */ -typedef void (* bap_broadcast_state_callback)(int adv_id, - btbap_broadcast_state_t state); - -/** Callback for audiopath state change. - * state will have one of the values from btbap_broadcast_audio_state_t - */ -typedef void (* bap_broadcast_audio_state_callback)(int adv_id, - btbap_broadcast_audio_state_t state); - -/** Callback for audio configuration change. - */ -typedef void (* bap_broadcast_audio_config_callback)(int adv_id, - btav_a2dp_codec_config_t codec_config, - std::vector codec_capabilities); - -/** Callback for Iso datapath setup or removed. - */ -//typedef void (* bap_broadcast_iso_datapath_callback) (int big_handle, int enabled); - -/** Callback for encryption key generation notification - */ -typedef void (* bap_broadcast_enckey_callback) (std::string key); - -/** Callback to create/terminate BIG - */ - -typedef void (* bap_broadcast_setup_big_callback) (int enable, int adv_id, int big_handle, - int num_bises, std::vector bis_handles); - -typedef void (* bap_broadcast_bid_callback) (std::vector broadcast_id); - -/** BT-BAP-BROADCAST callback structure. */ -typedef struct { - /** set to sizeof(btbap_broadcast_callbacks_t) */ - size_t size; - bap_broadcast_state_callback broadcast_state_cb; - bap_broadcast_audio_state_callback audio_state_cb; - bap_broadcast_audio_config_callback audio_config_cb; - //bap_broadcast_iso_datapath_callback iso_datapath_cb; - bap_broadcast_enckey_callback enc_key_cb; - bap_broadcast_setup_big_callback create_big_cb; - bap_broadcast_bid_callback broadcast_id_cb; -} btbap_broadcast_callbacks_t; - -typedef struct { - - /** set to sizeof(btav_source_interface_t) */ - size_t size; - /** - * Register the btbap_broadcast callbacks. - */ - bt_status_t (*init)(btbap_broadcast_callbacks_t* callbacks, - int max_broadcast, btav_a2dp_codec_config_t config, int mode); - - /** Enable broadcast with provided codec config */ - bt_status_t (*enable_broadcast)(btav_a2dp_codec_config_t config); - - /** disable broadcast to move the state machine to idle state */ - bt_status_t (*disable_broadcast)(int adv_id); - - /** sets bap broadcast as active session */ - bt_status_t (*set_broadcast_active)(bool enable, uint8_t adv_id); - - /** configure the codecs settings preferences */ - bt_status_t (*codec_config_change)(uint8_t adv_id, btav_a2dp_codec_config_t config); - - /** Disable ISO datapath */ - bt_status_t (*setup_audiopath)(bool enable, uint8_t adv_id, uint8_t big_handle, int num_bises, int* bis_handles); - - /** Get stored encryption key */ - std::string (*get_encryption_key)( void ); - - /** Set Encryption with encryption lenght provided */ - bt_status_t (*set_encryption) (bool enabled, uint8_t key_length); - - /** Closes the interface. */ - void (*cleanup)( void ); - -} btbap_broadcast_interface_t; -__END_DECLS -#endif /*ANDROID_INCLUDE_BT_BAP_BA_H*/ - diff --git a/le_audio/vhal/include/hardware/bt_bap_uclient.h b/le_audio/vhal/include/hardware/bt_bap_uclient.h deleted file mode 100644 index 7f5a481fc627bdff538fdf2c243e6aeb97bc492b..0000000000000000000000000000000000000000 --- a/le_audio/vhal/include/hardware/bt_bap_uclient.h +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/* - * 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. - */ - -#ifndef ANDROID_INCLUDE_BT_BAP_UCLIENT_H -#define ANDROID_INCLUDE_BT_BAP_UCLIENT_H - -#include -#include -#include - - -namespace bluetooth { -namespace bap { -namespace ucast { - -#define BT_PROFILE_BAP_UCLIENT_ID "bt_bap_uclient" - -using bluetooth::bap::pacs::CodecConfig; - -constexpr uint8_t ASE_DIRECTION_SINK = 0x01 << 0; -constexpr uint8_t ASE_DIRECTION_SRC = 0x01 << 1; - -constexpr uint8_t LATENCY_LOW = 0x01; -constexpr uint8_t LATENCY_BALANCED = 0x02; -constexpr uint8_t LATENCY_HIGH = 0x03; - -// Content types -constexpr uint16_t CONTENT_TYPE_UNSPECIFIED = 0x0001; // Unspecified -constexpr uint16_t CONTENT_TYPE_CONVERSATIONAL = 0x0002; // Conversational - -// Media(music playback, radio, podcast or movie soundtrack, or tv audio) -constexpr uint16_t CONTENT_TYPE_MEDIA = 0x0004; -constexpr uint16_t CONTENT_TYPE_GAME = 0x0008; // Game Audio -constexpr uint16_t CONTENT_TYPE_INSTRUCTIONAL = 0x0010; // Instructional - -// ManMachine(with voice recognition or virtual assistants) -constexpr uint16_t CONTENT_TYPE_MAN_MACHINE = 0x0020; -constexpr uint16_t CONTENT_TYPE_LIVE = 0x0040; // Live audio - -// Sound Effects(including keyboard and touch feedback; -// menu and user interface sounds; and other system sounds) -constexpr uint16_t CONTENT_TYPE_SOUND_EFFECTS = 0x0080; - -// Notification and reminder sounds; attention-seeking audio, -//for example, in beeps signaling the arrival of a message -constexpr uint16_t CONTENT_TYPE_NOTIFICATIONS = 0x0100; -constexpr uint16_t CONTENT_TYPE_RINGTONE = 0x0200; // Ringtone -constexpr uint16_t CONTENT_TYPE_ALERT = 0x0400; // ImmediateAlert -constexpr uint16_t CONTENT_TYPE_EMERGENCY = 0x0800; // EmergencyAlert - -// Audio locations -constexpr uint32_t AUDIO_LOC_LEFT = 0x0001; -constexpr uint32_t AUDIO_LOC_RIGHT = 0x0002; -constexpr uint32_t AUDIO_LOC_CENTER = 0x0004; - -constexpr uint8_t LE_2M_PHY = 0x02; -constexpr uint8_t LE_QHS_PHY = 0x80; - -typedef uint8_t sdu_interval_t[3]; -typedef uint8_t presentation_delay_t[3]; -typedef uint8_t codec_type_t[5]; -typedef uint8_t codec_config[255]; - -struct CISConfig { - uint8_t cis_id; - uint16_t max_sdu_m_to_s; - uint16_t max_sdu_s_to_m; - uint8_t phy_m_to_s; - uint8_t phy_s_to_m; - uint8_t rtn_m_to_s; - uint8_t rtn_s_to_m; -}; - -struct CIGConfig { - uint8_t cig_id; - uint8_t cis_count; - uint8_t packing; - uint8_t framing; - uint16_t max_tport_latency_m_to_s; - uint16_t max_tport_latency_s_to_m; - sdu_interval_t sdu_interval_m_to_s; - sdu_interval_t sdu_interval_s_to_m; -}; - -struct ASCSConfig { - uint8_t cig_id; - uint8_t cis_id; - uint8_t target_latency; - bool bi_directional; - presentation_delay_t presentation_delay; -}; - -struct QosConfig { - CIGConfig cig_config; - std::vector cis_configs; // individual CIS configs - std::vector ascs_configs; -}; - -enum class AseState { - IDLE = 0, - CODEC_CONFIGURED, - QOS_CONFIGURED, - ENABLING, - STREAMING, - DISABLING, - RELEASING, -}; - -enum class StreamState { - DISCONNECTED = 0, - CONNECTING, - CONNECTED, - STARTING, - STREAMING, - STOPPING, - DISCONNECTING, - RECONFIGURING, - UPDATING -}; - -enum class DeviceState { - DISCONNECTED = 0, - CONNECTING, - CONNECTED -}; - -enum class StreamDiscReason { - REASON_NONE, - REASON_USER_DISC -}; - -struct CodecQosConfig { - CodecConfig codec_config; - QosConfig qos_config; -}; - -struct StreamType { - uint16_t type; - uint16_t audio_context; - uint8_t direction; -}; - -struct StreamConnect { - StreamType stream_type; - //CCID_List ccids; //TODO - std::vector codec_qos_config_pair; -}; - -enum class StreamReconfigType { - CODEC_CONFIG, - QOS_CONFIG -}; - -struct StreamReconfig { - StreamType stream_type; - StreamReconfigType reconf_type; - std::vector codec_qos_config_pair; -}; - -enum class StreamUpdateType { - STREAMING_CONTEXT, -}; - -struct StreamUpdate { - StreamType stream_type; - StreamUpdateType update_type; - uint16_t update_value; -}; - -struct StreamStateInfo { - StreamType stream_type; - StreamState stream_state; - StreamDiscReason reason; -}; - -struct StreamConfigInfo { - StreamType stream_type; - CodecConfig codec_config; // codec - uint32_t audio_location; // location info of remote dev for the stream - QosConfig qos_config; // current CIG, CISs configuration - std::vector codecs_selectable; // pacs codec capabilities -}; - -class UcastClientCallbacks { - public: - virtual ~UcastClientCallbacks() = default; - - virtual void OnStreamState(const RawAddress &address, - std::vector streams_state_info) = 0; - - virtual void OnStreamConfig(const RawAddress &address, - std::vector streams_config_info) = 0; - - virtual void OnStreamAvailable(const RawAddress &address, - uint16_t src_audio_contexts, - uint16_t sink_audio_contexts) = 0; -}; - -class UcastClientInterface { - public: - virtual ~UcastClientInterface() = default; - - /** Register the ucast client callbacks */ - virtual void Init(UcastClientCallbacks* callbacks) = 0; - - virtual void Connect(std::vector &address, bool is_direct, - std::vector &streams) = 0; - - virtual void Disconnect(const RawAddress& address, - std::vector &streams) = 0; - - virtual void Start(const RawAddress& address, - std::vector &streams) = 0; - - virtual void Stop(const RawAddress& address, - std::vector &streams) = 0; - - virtual void Reconfigure(const RawAddress& address, - std::vector &streams) = 0; - - virtual void UpdateStream(const RawAddress& address, - std::vector &update_streams) = 0; - - /** Closes the interface. */ - virtual void Cleanup() = 0; -}; - -UcastClientInterface* btif_bap_uclient_get_interface(); - -} // namespace ucast -} // namespace bap -} // namespace bluetooth - -#endif /* ANDROID_INCLUDE_BT_BAP_UCLIENT_H */ diff --git a/le_audio/vhal/include/hardware/bt_csip.h b/le_audio/vhal/include/hardware/bt_csip.h deleted file mode 100644 index 92eeef173a1d095ec49ed5e93fdc765c10892b7c..0000000000000000000000000000000000000000 --- a/le_audio/vhal/include/hardware/bt_csip.h +++ /dev/null @@ -1,119 +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. - * - ******************************************************************************/ - - -#ifndef ANDROID_INCLUDE_BT_CSIP_H -#define ANDROID_INCLUDE_BT_CSIP_H - -#include -#include -#include - -__BEGIN_DECLS - -#define BT_PROFILE_CSIP_CLIENT_ID "csip_client" - -/** Callback when app has registered with CSIP Client module - */ -typedef void (* btcsip_csip_app_registered_callback)(uint8_t status, uint8_t app_id, - const bluetooth::Uuid& app_uuid); - -/** Callback when connection state is changed for CSIP Profile - */ -typedef void (* btcsip_csip_connection_state_callback)(uint8_t app_id, RawAddress& bd_addr, - uint8_t state, uint8_t status); - -/** Callback when new set has been identified on remote device - */ -typedef void (* btcsip_new_set_found_callback) (uint8_t set_id, RawAddress& bd_addr, - uint8_t size, uint8_t* sirk, - const bluetooth::Uuid& p_srvc_uuid, - bool lock_support); - -/** Callback when new set member has been identified - */ -typedef void (* btcsip_new_set_member_found_callback) (uint8_t set_id, - RawAddress& bd_addr); - -/** Callback for lock status changed event to requesting client - */ -typedef void (* btcsip_lock_state_changed_callback) (uint8_t app_id, uint8_t set_id, - uint8_t value, uint8_t status, - std::vector addr); - -/** Callback when lock is available on earlier denying set member - */ -typedef void (* btcsip_lock_available_callback) (uint8_t app_id, uint8_t set_id, - RawAddress& bd_addr); - -/** Callback when size of coordinated set has been changed - */ -typedef void (* btcsip_set_size_changed_callback) (uint8_t set_id, uint8_t size, - RawAddress& bd_addr); - -/** Callback when SIRK of coordinated set has been changed - */ -typedef void (* btcsip_set_sirk_changed_callback) (uint8_t set_id, uint8_t* sirk, - RawAddress& bd_addr); - -/** BT-CSIP callback structure. */ -typedef struct { - size_t size; - btcsip_csip_app_registered_callback app_registered_cb; - btcsip_csip_connection_state_callback conn_state_cb; - btcsip_new_set_found_callback new_set_found_cb; - btcsip_new_set_member_found_callback new_set_member_cb; - btcsip_lock_state_changed_callback lock_status_cb; - btcsip_lock_available_callback lock_available_cb; - btcsip_set_size_changed_callback size_changed_cb; - btcsip_set_sirk_changed_callback sirk_changed_cb; -} btcsip_callbacks_t; - -/** Represents the standard BT-CSIP interface. */ -typedef struct { - - /** set to sizeof(BtCsipInterface) */ - size_t size; - - /** Register the BtCsipInterface callbacks - */ - bt_status_t (*init) (btcsip_callbacks_t* callbacks); - - /** CSIP opportunistic gatt client connection*/ - bt_status_t (*connect) (uint8_t app_id, RawAddress *bd_addr); - - /** disconnect csip gatt connection */ - bt_status_t (*disconnect) (uint8_t app_id, RawAddress *bd_addr ); - - /** register app/module with CSIP profile*/ - bt_status_t (*register_csip_app) (const bluetooth::Uuid& app_uuid); - - /** unregister app/module with CSIP profile */ - bt_status_t (*unregister_csip_app) (uint8_t app_id); - - /** change lock value */ - bt_status_t (*set_lock_value) (uint8_t app_id, uint8_t set_id, uint8_t lock_value, - std::vector devices); - - /** Closes the interface. */ - void (*cleanup) (void); - -} btcsip_interface_t; -__END_DECLS - -#endif /* ANDROID_INCLUDE_BT_CSIP_H */ diff --git a/le_audio/vhal/include/hardware/bt_mcp.h b/le_audio/vhal/include/hardware/bt_mcp.h deleted file mode 100644 index 8bde52dece2e810ffbc8691f73098cf700aef513..0000000000000000000000000000000000000000 --- a/le_audio/vhal/include/hardware/bt_mcp.h +++ /dev/null @@ -1,66 +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. - * - ******************************************************************************/ - - -#ifndef ANDROID_INCLUDE_BT_MCP_H -#define ANDROID_INCLUDE_BT_MCP_H - - - -#include -#include - -#define BT_PROFILE_MCP_ID "mcs_server" - -namespace bluetooth { -namespace mcp_server { - -class McpServerCallbacks { - public: - virtual ~McpServerCallbacks() = default; - virtual void OnConnectionStateChange(int status, const RawAddress& bd_addr) = 0; - virtual void MediaControlPointChangeReq(uint8_t state, const RawAddress& bd_addr) = 0; - virtual void TrackPositionChangeReq(int32_t position) = 0; - virtual void PlayingOrderChangeReq(uint32_t order) = 0; -}; - - -class McpServerInterface { - public: - virtual ~McpServerInterface() = default; - virtual void Init(McpServerCallbacks* callbacks, Uuid uuid) = 0; - virtual void MediaState(uint8_t state) = 0; - virtual void MediaPlayerName(uint8_t *name) = 0; - virtual void MediaControlPointOpcodeSupported(uint32_t feature) = 0; - virtual void MediaControlPoint(uint8_t value) = 0; - virtual void TrackChanged(bool status) = 0; - virtual void TrackTitle(uint8_t* title) = 0; - virtual void TrackPosition(int32_t position) = 0; - virtual void TrackDuration(int32_t duration) = 0; - virtual void PlayingOrderSupported(uint16_t order) = 0; - virtual void PlayingOrder(uint8_t value) = 0; - virtual void ContentControlId(uint8_t ccid) = 0; - virtual void SetActiveDevice(const RawAddress& address, int set_id, int profile) = 0; - virtual void DisconnectMcp(const RawAddress& address) = 0; - virtual void BondStateChange(const RawAddress& address, int state) = 0; - virtual void Cleanup(void) = 0; -}; - -} -} -#endif /* ANDROID_INCLUDE_BT_MCP_H */ diff --git a/le_audio/vhal/include/hardware/bt_pacs_client.h b/le_audio/vhal/include/hardware/bt_pacs_client.h deleted file mode 100644 index 7579b728e3bb027d46da8fb8e45819ac7e60d757..0000000000000000000000000000000000000000 --- a/le_audio/vhal/include/hardware/bt_pacs_client.h +++ /dev/null @@ -1,183 +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. - */ - -#ifndef ANDROID_INCLUDE_BT_PACS_CLIENT_H -#define ANDROID_INCLUDE_BT_PACS_CLIENT_H - -#include -#include - -namespace bluetooth { -namespace bap { -namespace pacs { - -#define BT_PROFILE_PACS_CLIENT_ID "bt_pacs_client" - -enum class CodecDirection { - CODEC_DIR_SINK = 0x1 << 0, - CODEC_DIR_SRC = 0x1 << 1 -}; - -enum class CodecCapFrameDuration { - FRAME_DUR_7_5 = 0x1 << 0, - FRAME_DUR_10 = 0x1 << 1, - FRAME_DUR_7_5_PREF = 0x1 << 4, - FRAME_DUR_10_PREF = 0x1 << 5, -}; - -enum class CodecFrameDuration { - FRAME_DUR_7_5 = 0x00, - FRAME_DUR_10 = 0x01, -}; - -enum class CodecCapChnlCount { - CHNL_COUNT_ONE = 0x1 << 0, - CHNL_COUNT_TWO = 0x1 << 1, - CHNL_COUNT_THREE = 0x1 << 2, - CHNL_COUNT_FOUR = 0x1 << 3, - CHNL_COUNT_FIVE = 0x1 << 4, - CHNL_COUNT_SIX = 0x1 << 5, - CHNL_COUNT_SEVEN = 0x1 << 6, - CHNL_COUNT_EIGHT = 0x1 << 7, -}; - -enum class ConnectionState { - DISCONNECTED = 0, - CONNECTING, - CONNECTED, - DISCONNECTING -}; - -enum class CodecIndex { - CODEC_INDEX_SOURCE_MIN = 0x09, - - // Add an entry for each source codec here. - // NOTE: The values should be same as those listed in the following file: - // BluetoothCodecConfig.java - CODEC_INDEX_SOURCE_LC3 = CODEC_INDEX_SOURCE_MIN, - CODEC_INDEX_SOURCE_MAX, - CODEC_INDEX_MIN = CODEC_INDEX_SOURCE_MIN, - CODEC_INDEX_MAX = CODEC_INDEX_SOURCE_MAX, -}; - -enum class CodecPriority { - // Disable the codec. - CODEC_PRIORITY_DISABLED = -1, - - // Reset the codec priority to its default value. - CODEC_PRIORITY_DEFAULT = 0, - - // Highest codec priority. - CODEC_PRIORITY_HIGHEST = 1000 * 1000 -}; - -enum class CodecSampleRate { - CODEC_SAMPLE_RATE_NONE = 0x0, - CODEC_SAMPLE_RATE_44100 = 0x1 << 0, - CODEC_SAMPLE_RATE_48000 = 0x1 << 1, - CODEC_SAMPLE_RATE_88200 = 0x1 << 2, - CODEC_SAMPLE_RATE_96000 = 0x1 << 3, - CODEC_SAMPLE_RATE_176400 = 0x1 << 4, - CODEC_SAMPLE_RATE_192000 = 0x1 << 5, - CODEC_SAMPLE_RATE_16000 = 0x1 << 6, - CODEC_SAMPLE_RATE_24000 = 0x1 << 7, - CODEC_SAMPLE_RATE_32000 = 0x1 << 8, - CODEC_SAMPLE_RATE_8000 = 0x1 << 9 -}; - -enum class CodecBPS { - CODEC_BITS_PER_SAMPLE_NONE = 0x0, - CODEC_BITS_PER_SAMPLE_16 = 0x1 << 0, - CODEC_BITS_PER_SAMPLE_24 = 0x1 << 1, - CODEC_BITS_PER_SAMPLE_32 = 0x1 << 2 -}; - -enum class CodecChannelMode { - CODEC_CHANNEL_MODE_NONE = 0x0, - CODEC_CHANNEL_MODE_MONO = 0x1 << 0, - CODEC_CHANNEL_MODE_STEREO = 0x1 << 1 -}; - -struct CodecConfig { - CodecIndex codec_type; - CodecPriority codec_priority; // Codec selection priority - // relative to other codecs: larger value - // means higher priority. If 0, reset to - // default. - CodecSampleRate sample_rate; - CodecBPS bits_per_sample; - CodecChannelMode channel_mode; - int64_t codec_specific_1; // Codec-specific value 1 - int64_t codec_specific_2; // Codec-specific value 2 - int64_t codec_specific_3; // Codec-specific value 3 - int64_t codec_specific_4; // Codec-specific value 4 -}; - -class PacsClientCallbacks { - public: - virtual ~PacsClientCallbacks() = default; - - /** Callback for pacs server registration status */ - virtual void OnInitialized(int status, int client_id) = 0; - - /** Callback for pacs server connection state change */ - virtual void OnConnectionState(const RawAddress& address, - ConnectionState state) = 0; - - /** Callback for audio ( media or voice) being available */ - virtual void OnAudioContextAvailable(const RawAddress& address, - uint32_t available_contexts) = 0; - - /** Callback for pacs discovery results */ - virtual void OnSearchComplete(int status, - const RawAddress& address, - std::vector sink_pac_records, - std::vector src_pac_records, - uint32_t sink_locations, - uint32_t src_locations, - uint32_t available_contexts, - uint32_t supported_contexts) = 0; -}; - -class PacsClientInterface { - public: - virtual ~PacsClientInterface() = default; - - /** Register the Pacs client callbacks */ - virtual void Init(PacsClientCallbacks* callbacks) = 0; - - /** Connect to pacs server */ - virtual void Connect(uint16_t client_id, const RawAddress& address) = 0; - - /** Disconnect pacs server */ - virtual void Disconnect(uint16_t client_id, const RawAddress& address) = 0; - - /** start pacs discovery */ - virtual void StartDiscovery(uint16_t client_id, - const RawAddress& address) = 0; - - /** get available audio context */ - virtual void GetAvailableAudioContexts(uint16_t client_id, - const RawAddress& address) = 0; - /** Closes the interface. */ - virtual void Cleanup(uint16_t client_id) = 0; -}; - -} // namespace pacs -} // namespace bap -} // namespace bluetooth - -#endif /* ANDROID_INCLUDE_BT_CLIENT_H */ diff --git a/le_audio/vhal/include/hardware/bt_vcp_controller.h b/le_audio/vhal/include/hardware/bt_vcp_controller.h deleted file mode 100644 index ea2e35a857058b3b7794dd441927ceb7ed606ca2..0000000000000000000000000000000000000000 --- a/le_audio/vhal/include/hardware/bt_vcp_controller.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - *Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -/* - * 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. - */ - -#ifndef ANDROID_INCLUDE_BT_VCP_CONTROLLER_H -#define ANDROID_INCLUDE_BT_VCP_CONTROLLER_H - -#include - -#define BT_PROFILE_VOLUME_CONTROL_ID "volume_control" - -namespace bluetooth { -namespace vcp_controller { - -enum class ConnectionState { - DISCONNECTED = 0, - CONNECTING, - CONNECTED, - DISCONNECTING -}; - -class VcpControllerCallbacks { - public: - virtual ~VcpControllerCallbacks() = default; - - /** Callback for profile connection state change */ - virtual void OnConnectionState(ConnectionState state, - const RawAddress& address) = 0; - - virtual void OnVolumeStateChange(uint8_t volume, uint8_t mute, - const RawAddress& address) = 0; - - virtual void OnVolumeFlagsChange(uint8_t flags, - const RawAddress& address) = 0; -}; - -class VcpControllerInterface { - public: - virtual ~VcpControllerInterface() = default; - - /** Register the Volume Controller callbacks */ - virtual void Init(VcpControllerCallbacks* callbacks) = 0; - - /** Connect to Volume Renderer device */ - virtual void Connect(const RawAddress& address, bool isDirect) = 0; - - /** Disconnect from Volume Renderer device */ - virtual void Disconnect(const RawAddress& address) = 0; - - /** Set absolute volume */ - virtual void SetAbsVolume(uint8_t volume, const RawAddress& address) = 0; - - virtual void Mute(const RawAddress& address) = 0; - - virtual void Unmute(const RawAddress& address) = 0; - - /** Closes the interface. */ - virtual void Cleanup(void) = 0; -}; - -} // namespace vcp_controller -} // namespace bluetooth - -#endif /* ANDROID_INCLUDE_BT_VCP_CONTROLLER_H */ - -