Merge "Bluetooth: Handle IllegalStateException during start service." into bt.lnx.5.0
diff --git a/packages_apps_bluetooth_ext/jni/com_android_bluetooth_hf_vendor.cpp b/packages_apps_bluetooth_ext/jni/com_android_bluetooth_hf_vendor.cpp
index f11d4cd..d9bee6a 100644
--- a/packages_apps_bluetooth_ext/jni/com_android_bluetooth_hf_vendor.cpp
+++ b/packages_apps_bluetooth_ext/jni/com_android_bluetooth_hf_vendor.cpp
@@ -38,6 +38,7 @@
static btvendor_hf_interface_t *sBluetoothVendorHfInterface = NULL;
static jobject mCallbacksObj = NULL;
static jmethodID method_onSWB;
+static jmethodID method_onTwsBatteryStateCallback;
static jbyteArray marshall_bda(RawAddress* bd_addr) {
CallbackEnv sCallbackEnv(__func__);
@@ -65,14 +66,41 @@
addr.get());
}
+void bt_twsp_battery_status_callback(char* at_string, RawAddress* bd_addr) {
+ ALOGD("TwsBatteryStateCallback :%s, BD_ADDR: %s",
+ at_string, bd_addr->ToString().c_str());
+ CallbackEnv sCallbackEnv(__func__);
+ if (!sCallbackEnv.valid() || !mCallbacksObj) return;
+
+ ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), marshall_bda(bd_addr));
+ if (addr.get() == nullptr) return;
+
+ char null_str[] = "";
+ if (!sCallbackEnv.isValidUtf(at_string)) {
+ android_errorWriteLog(0x534e4554, "109838537");
+ ALOGE("%s: at_string is not a valid UTF string.", __func__);
+ at_string = null_str;
+ }
+
+ ScopedLocalRef<jstring> js_at_string(sCallbackEnv.get(),
+ sCallbackEnv->NewStringUTF(at_string));
+
+ sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onTwsBatteryStateCallback,
+ js_at_string.get(), addr.get());
+}
+
static btvendor_hf_callbacks_t sBluetoothVendorHfCallbacks = {
sizeof(sBluetoothVendorHfCallbacks),
SwbCallback,
+ bt_twsp_battery_status_callback
};
static void classInitNative(JNIEnv* env, jclass clazz) {
method_onSWB = env->GetMethodID(clazz, "onSWB", "(I[B)V");
+ method_onTwsBatteryStateCallback =
+ env->GetMethodID(clazz, "onTwsBatteryStateCallback",
+ "(Ljava/lang/String;[B)V");
ALOGI("%s: succeeds", __FUNCTION__);
}
diff --git a/packages_apps_bluetooth_ext/src/hfp/vendorhfservice.java b/packages_apps_bluetooth_ext/src/hfp/vendorhfservice.java
index f0c38b1..aab40ef 100644
--- a/packages_apps_bluetooth_ext/src/hfp/vendorhfservice.java
+++ b/packages_apps_bluetooth_ext/src/hfp/vendorhfservice.java
@@ -73,6 +73,13 @@
sendMessageToService(event);
}
+ private void onTwsBatteryStateCallback(String atString, byte[] address) {
+ /*HeadsetStackEvent event = new HeadsetStackEvent(
+ HeadsetStackEvent.EVENT_TYPE_TWSP_BATTERY_STATE, atString,
+ getDevice(address));
+ sendMessageToService(event);*/
+ }
+
private void sendMessageToService(HeadsetStackEvent event) {
HeadsetService service = HeadsetService.getHeadsetService();
if (service != null) {
diff --git a/system_bt_ext/bta/include/bta_ag_twsp.h b/system_bt_ext/bta/include/bta_ag_twsp.h
index bd4d960..c9cfd95 100644
--- a/system_bt_ext/bta/include/bta_ag_twsp.h
+++ b/system_bt_ext/bta/include/bta_ag_twsp.h
@@ -34,6 +34,7 @@
#ifndef _BTA_AG_TWS_H_
#define _BTA_AG_TWS_H_
+#include "btif_twsp_hf.h"
#include "bta_ag_int.h"
#define VS_QHCI_TWS_ESCO_SETUP_OPCODE 0x0D
diff --git a/system_bt_ext/bta/include/bta_ag_twsp_dev.h b/system_bt_ext/bta/include/bta_ag_twsp_dev.h
index c1e2b23..fb6f5b5 100644
--- a/system_bt_ext/bta/include/bta_ag_twsp_dev.h
+++ b/system_bt_ext/bta/include/bta_ag_twsp_dev.h
@@ -47,6 +47,9 @@
#define TWSPLUS_MIN_BATTERY_CHARGE_STATE_POWERFAULT 2
#define TWSPLUS_MAX_BATTERY_CHARGE 255
+#define TWSPLUS_MIN_BATTERY_LEVEL 0
+#define TWSPLUS_MAX_BATTERY_LEVEL 100
+
#define TWSPLUS_INVALID_MICPATH_DELAY (-1)
#define TWSPLUS_MAX_MICPATH_DELAY (65535)
#define TWSPLUS_MIN_MICPATH_DELAY (0)
@@ -82,7 +85,8 @@
typedef struct {
tBTA_AG_SCB *p_scb;
uint8_t mic_quality;
- uint8_t battery_charge;
+ uint16_t battery_state;
+ uint16_t battery_level;
uint8_t state;
int16_t mic_path_delay;
uint8_t role;
@@ -91,8 +95,9 @@
uint8_t ring_sent;
} tTWSPLUS_DEVICE;
-void twsp_handle_vs_at_events(tBTA_AG_SCB* p_scb, uint16_t cmd, int16_t int_arg);
void update_twsp_device(tBTA_AG_SCB* p_scb);
+void twsp_handle_vs_at_events(tBTA_AG_SCB* p_scb, uint16_t cmd,
+ tBTA_AG_VAL* val , int16_t int_arg);
void reset_twsp_device(int eb_idx);
bool twsp_set_ring_sent(tBTA_AG_SCB *p_scb, bool ring_sent);
void twsp_clr_all_ring_sent();
diff --git a/system_bt_ext/bta/tws_plus/ag/bta_ag_twsp_dev.cc b/system_bt_ext/bta/tws_plus/ag/bta_ag_twsp_dev.cc
index 11642e3..d2c25c4 100644
--- a/system_bt_ext/bta/tws_plus/ag/bta_ag_twsp_dev.cc
+++ b/system_bt_ext/bta/tws_plus/ag/bta_ag_twsp_dev.cc
@@ -37,6 +37,7 @@
#include "bta_ag_twsp.h"
#include "internal_include/bt_trace.h"
#include "bta_ag_int.h"
+#include "utl.h"
#if (TWS_AG_ENABLED == TRUE)
@@ -94,15 +95,16 @@
}
}
- twsp_devices[eb_idx].p_scb = NULL;
- twsp_devices[eb_idx].battery_charge = TWSPLUS_MIN_BATTERY_CHARGE;
- twsp_devices[eb_idx].state = TWSPLUS_EB_STATE_UNKNOWN;
- twsp_devices[eb_idx].role = TWSPLUS_EB_ROLE_INVALID;
- twsp_devices[eb_idx].mic_path_delay = TWSPLUS_INVALID_MICPATH_DELAY;
- twsp_devices[eb_idx].mic_quality = TWSPLUS_MIN_MIC_QUALITY;
- twsp_devices[eb_idx].qdsp_nr = TWSPLUS_INVALID_QDSP_VALUE;
- twsp_devices[eb_idx].qdsp_ec = TWSPLUS_INVALID_QDSP_VALUE;
- twsp_devices[eb_idx].ring_sent = false;
+ twsp_devices[eb_idx].p_scb = NULL;
+ twsp_devices[eb_idx].battery_state = TWSPLUS_MIN_BATTERY_CHARGE_STATE_DISCHARGING;
+ twsp_devices[eb_idx].battery_level = TWSPLUS_MIN_BATTERY_LEVEL;
+ twsp_devices[eb_idx].state = TWSPLUS_EB_STATE_OFF;
+ twsp_devices[eb_idx].role = TWSPLUS_EB_ROLE_INVALID;
+ twsp_devices[eb_idx].mic_path_delay = TWSPLUS_INVALID_MICPATH_DELAY;
+ twsp_devices[eb_idx].mic_quality = TWSPLUS_MIN_MIC_QUALITY;
+ twsp_devices[eb_idx].qdsp_nr = TWSPLUS_INVALID_QDSP_VALUE;
+ twsp_devices[eb_idx].qdsp_ec = TWSPLUS_INVALID_QDSP_VALUE;
+ twsp_devices[eb_idx].ring_sent = false;
}
void update_twsp_device(tBTA_AG_SCB* p_scb) {
@@ -110,8 +112,10 @@
if (twsp_devices[i].p_scb == NULL) {
APPL_TRACE_WARNING("%s: idx: %d, p_scb: %x", __func__, i, p_scb);
twsp_devices[i].p_scb = p_scb;
- twsp_devices[i].battery_charge = TWSPLUS_MIN_BATTERY_CHARGE;
- twsp_devices[i].state = TWSPLUS_EB_STATE_UNKNOWN;
+ twsp_devices[i].battery_state =
+ TWSPLUS_MIN_BATTERY_CHARGE_STATE_DISCHARGING;
+ twsp_devices[i].battery_level = TWSPLUS_MIN_BATTERY_LEVEL;
+ twsp_devices[i].state = TWSPLUS_EB_STATE_OFF;
int other_idx = (i == PRIMARY_EB_IDX) ? SECONDARY_EB_IDX : PRIMARY_EB_IDX;
if (twsp_devices[other_idx].p_scb != NULL) {
@@ -156,8 +160,10 @@
APPL_TRACE_DEBUG("%s: p_scb : %x", __func__, twsp_devices[eb_idx].p_scb);
APPL_TRACE_DEBUG("%s: mic_quality : %d", __func__,
twsp_devices[eb_idx].mic_quality);
- APPL_TRACE_DEBUG("%s: battery_charge : %d", __func__,
- twsp_devices[eb_idx].battery_charge);
+ APPL_TRACE_DEBUG("%s: battery_state : %d", __func__,
+ twsp_devices[eb_idx].battery_state);
+ APPL_TRACE_DEBUG("%s: battery_level : %d", __func__,
+ twsp_devices[eb_idx].battery_level);
APPL_TRACE_DEBUG("%s: mic_path_delay : %d", __func__,
twsp_devices[eb_idx].mic_path_delay);
APPL_TRACE_DEBUG("%s: state : %d", __func__, twsp_devices[eb_idx].state);
@@ -350,20 +356,26 @@
return twsp_devices[eb_idx].qdsp_ec;
}
-bool set_twsp_battery_charge(int eb_idx, uint8_t battery_charge) {
- APPL_TRACE_DEBUG("%s: battery_charge : %d\n", __func__, battery_charge);
+bool set_twsp_battery_charge(int eb_idx, int16_t state, int16_t level) {
+ APPL_TRACE_DEBUG("%s: state : %d, level : %d\n", __func__, state, level);
if (eb_idx < PRIMARY_EB_IDX || eb_idx > SECONDARY_EB_IDX) {
APPL_TRACE_WARNING("%s: Invalid eb_idx: %d\n", __func__, eb_idx);
return false;
}
- if (battery_charge < TWSPLUS_MIN_BATTERY_CHARGE || battery_charge > TWSPLUS_MAX_BATTERY_CHARGE) {
- APPL_TRACE_WARNING("%s: Invalid battery_charge: %d\n", __func__, battery_charge);
+ if (state < TWSPLUS_MIN_BATTERY_CHARGE_STATE_CHARGING ||
+ state > TWSPLUS_MIN_BATTERY_CHARGE_STATE_POWERFAULT) {
+ APPL_TRACE_WARNING("%s: Invalid state: %d\n", __func__, state);
return false;
}
- twsp_devices[eb_idx].battery_charge = battery_charge;
+ if (level < TWSPLUS_MIN_BATTERY_LEVEL ||
+ state > TWSPLUS_MAX_BATTERY_LEVEL) {
+ APPL_TRACE_WARNING("%s: Invalid level: %d\n", __func__, level);
+ return false;
+ }
+
return true;
}
@@ -578,10 +590,50 @@
}
}
-void twsp_handle_vs_at_events(tBTA_AG_SCB* p_scb, uint16_t cmd, int16_t int_arg)
+bool bta_ag_twsp_parse_qbc(tBTA_AG_SCB* p_scb, char* p_s,
+ int16_t *state, int16_t *level) {
+ int16_t n[2] = {-1, -1};
+ int i;
+ char* p;
+
+ for (i = 0; i < 2; i++) {
+ /* skip to comma delimiter */
+ for (p = p_s; *p != ',' && *p != 0; p++)
+ ;
+
+ /* get integer value */
+ *p = 0;
+ n[i] = utl_str2int(p_s);
+ p_s = p + 1;
+ if (p_s == 0) {
+ break;
+ }
+ }
+
+ /* process values */
+ if (n[0] < TWSPLUS_MIN_BATTERY_CHARGE_STATE_CHARGING ||
+ n[0] > TWSPLUS_MAX_BATTERY_CHARGE) {
+ APPL_TRACE_ERROR("%s: Invalid QBC state: %d", __func__, n[0]);
+ return false;
+ }
+
+ if (n[1] < TWSPLUS_MIN_BATTERY_CHARGE_STATE_CHARGING ||
+ n[1] > TWSPLUS_MAX_BATTERY_CHARGE) {
+ APPL_TRACE_ERROR("%s: Invalid QBC level: %d", __func__, n[1]);
+ return false;
+ }
+
+ *state = n[0];
+ *level = n[1];
+ return true;
+}
+
+void twsp_handle_vs_at_events(tBTA_AG_SCB* p_scb, uint16_t cmd,
+ tBTA_AG_VAL* val, int16_t int_arg)
{
APPL_TRACE_DEBUG("%s: p_scb : %x cmd : %d", __func__, p_scb, cmd);
-
+ int16_t state, level;
+ char str_to_parse[BTA_AG_AT_MAX_LEN];
int idx = twsp_get_idx_by_scb(p_scb);
if (idx < 0) {
APPL_TRACE_ERROR("%s: Invalid SCB handle: %x", __func__, p_scb);
@@ -591,24 +643,38 @@
//bta_ag_send_ok(p_scb);
switch(cmd) {
- case BTA_AG_TWSP_AT_QMQ_EVT: {
- set_twsp_mic_quality(idx, int_arg);
- } break;
- case BTA_AG_TWSP_AT_QES_EVT: {
- set_twsp_state(idx, int_arg);
- } break;
- case BTA_AG_TWSP_AT_QER_EVT: {
+ case BTA_AG_TWSP_AT_QMQ_EVT: {
+ set_twsp_mic_quality(idx, int_arg);
+ } break;
+ case BTA_AG_TWSP_AT_QES_EVT: {
+ set_twsp_state(idx, int_arg);
+ } break;
+ case BTA_AG_TWSP_AT_QER_EVT: {
set_twsp_role(idx, int_arg);
- } break;
- case BTA_AG_TWSP_AT_QBC_EVT: {
- set_twsp_battery_charge(idx, int_arg);
- } break;
- case BTA_AG_TWSP_AT_QMD_EVT: {
+ } break;
+ case BTA_AG_TWSP_AT_QBC_EVT: {
+ strlcpy(str_to_parse, val->str, sizeof(str_to_parse));
+ int ret = bta_ag_twsp_parse_qbc(p_scb,
+ str_to_parse, &state, &level);
+ if (ret) {
+ APPL_TRACE_DEBUG("%s: QBC=%d, %d", __func__, state, level);
+ if(set_twsp_battery_charge(idx, state, level)) {
+ //Generate cb to BTIF/JNI
+ APPL_TRACE_DEBUG("%s: at_str : %s", __func__, val->str);
+ (*bta_ag_cb.p_cback)
+ ((tBTA_AG_EVT)BTA_AG_TWSP_BATTERY_UPDATE,
+ (tBTA_AG *)val);
+ }
+ } else {
+ APPL_TRACE_ERROR("%s: Fail to parse QBC", __func__)
+ }
+ } break;
+ case BTA_AG_TWSP_AT_QMD_EVT: {
set_twsp_mic_path_delay(idx, int_arg);
- } break;
- case BTA_AG_TWSP_AT_QDSP_EVT: {
+ } break;
+ case BTA_AG_TWSP_AT_QDSP_EVT: {
set_twsp_qdsp_features(idx, int_arg);
- } break;
+ } break;
}
}
diff --git a/system_bt_ext/btif/include/btif_twsp_hf.h b/system_bt_ext/btif/include/btif_twsp_hf.h
index 658312f..0b11ca9 100644
--- a/system_bt_ext/btif/include/btif_twsp_hf.h
+++ b/system_bt_ext/btif/include/btif_twsp_hf.h
@@ -32,6 +32,12 @@
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#define BTA_AG_TWSP_BATTERY_UPDATE 255
+
+#include "bta_ag_api.h"
+
+void btif_handle_vendor_hf_events(uint16_t event, tBTA_AG* data,
+ RawAddress *bd_addr);
namespace bluetooth {
namespace headset {
diff --git a/system_bt_ext/btif/src/btif_vendor_hf.cc b/system_bt_ext/btif/src/btif_vendor_hf.cc
index dc4895e..8468db9 100644
--- a/system_bt_ext/btif/src/btif_vendor_hf.cc
+++ b/system_bt_ext/btif/src/btif_vendor_hf.cc
@@ -39,6 +39,8 @@
#define LOG_TAG "bt_btif_vendor_hf"
#include <hardware/vendor_hf.h>
+#include "bta_ag_swb.h"
+#include "btif_twsp_hf.h"
#include "btif_api.h"
btvendor_hf_callbacks_t *bt_vendor_hf_callbacks = NULL;
@@ -85,8 +87,25 @@
enable_swb,
};
-void btif_handle_vendor_hf_events(uint16_t event, uint16_t swb_config, RawAddress *bd_addr) {
- HAL_CBACK(bt_vendor_hf_callbacks, swb_codec_cb, swb_config, bd_addr);
+void btif_handle_vendor_hf_events(uint16_t event, tBTA_AG* data,
+ RawAddress *bd_addr) {
+ BTIF_TRACE_EVENT("%s: event: %d", __func__, event)
+ switch (event) {
+ case BTA_AG_SWB_EVT:
+ HAL_CBACK(bt_vendor_hf_callbacks, swb_codec_cb, data->val.num,
+ bd_addr);
+ break;
+ case BTA_AG_AT_QCS_EVT:
+ HAL_CBACK(bt_vendor_hf_callbacks, swb_codec_cb, data->val.num,
+ bd_addr);
+ break;
+ case BTA_AG_TWSP_BATTERY_UPDATE:
+ HAL_CBACK(bt_vendor_hf_callbacks, twsp_batt_status_cb,
+ data->val.str, bd_addr);
+ break;
+ default:
+ BTIF_TRACE_EVENT("%s: unknown vendor hf event: %d", __func__,event);
+ }
}
bool get_swb_codec_status() {
diff --git a/vhal/include/hardware/vendor_hf.h b/vhal/include/hardware/vendor_hf.h
index 6b07c5c..242561c 100644
--- a/vhal/include/hardware/vendor_hf.h
+++ b/vhal/include/hardware/vendor_hf.h
@@ -43,11 +43,14 @@
/* SWB callback events */
typedef void (* bt_swb_update_callback)(uint16_t swb_codec_config, RawAddress *bd_addr);
+typedef void (* bt_twsp_battery_status_callback)(char* at_string, RawAddress *bd_addr);
+
/** BT-Vendor hf callback structure. */
typedef struct {
/** set to sizeof(BtVendorhfCallbacks) */
size_t size;
bt_swb_update_callback swb_codec_cb;
+ bt_twsp_battery_status_callback twsp_batt_status_cb;
} btvendor_hf_callbacks_t;