Merge "Support vendor AT command and response for Hfp Client in bt stack" am: 5b2eb835ac am: 86736a84fa
am: 3eeef397f9

Change-Id: I508031c431b38012da04c97a12e0de04b367c484
diff --git a/binder/android/bluetooth/IBluetoothHeadsetClient.aidl b/binder/android/bluetooth/IBluetoothHeadsetClient.aidl
index 13495ae..6341af4 100644
--- a/binder/android/bluetooth/IBluetoothHeadsetClient.aidl
+++ b/binder/android/bluetooth/IBluetoothHeadsetClient.aidl
@@ -59,6 +59,7 @@
     boolean disconnectAudio(in BluetoothDevice device);
     void setAudioRouteAllowed(in BluetoothDevice device, boolean allowed);
     boolean getAudioRouteAllowed(in BluetoothDevice device);
+    boolean sendVendorAtCommand(in BluetoothDevice device, int vendorId, String atCommand);
 
     Bundle getCurrentAgFeatures(in BluetoothDevice device);
 }
diff --git a/bta/hf_client/bta_hf_client_at.cc b/bta/hf_client/bta_hf_client_at.cc
index 5bcc68e..6e4fe26 100644
--- a/bta/hf_client/bta_hf_client_at.cc
+++ b/bta/hf_client/bta_hf_client_at.cc
@@ -724,9 +724,7 @@
  ******************************************************************************/
 void bta_hf_client_cnum(tBTA_HF_CLIENT_CB* client_cb, char* number,
                         uint16_t service) {
-  tBTA_HF_CLIENT evt;
-
-  memset(&evt, 0, sizeof(evt));
+  tBTA_HF_CLIENT evt = {};
 
   evt.cnum.service = service;
   strlcpy(evt.cnum.number, number, BTA_HF_CLIENT_NUMBER_LEN + 1);
@@ -736,6 +734,18 @@
   bta_hf_client_app_callback(BTA_HF_CLIENT_CNUM_EVT, &evt);
 }
 
+void bta_hf_client_unknown_response(tBTA_HF_CLIENT_CB* client_cb,
+                                    const char* evt_buffer) {
+  tBTA_HF_CLIENT evt = {};
+
+  strlcpy(evt.unknown.event_string, evt_buffer,
+          BTA_HF_CLIENT_UNKOWN_EVENT_LEN + 1);
+  evt.unknown.event_string[BTA_HF_CLIENT_UNKOWN_EVENT_LEN] = '\0';
+
+  evt.unknown.bd_addr = client_cb->peer_addr;
+  bta_hf_client_app_callback(BTA_HF_CLIENT_UNKNOWN_EVT, &evt);
+}
+
 /*******************************************************************************
  *
  * Function         bta_hf_client_binp
@@ -1436,6 +1446,36 @@
   return buffer;
 }
 
+static char* bta_hf_client_process_unknown(tBTA_HF_CLIENT_CB* client_cb,
+                                           char* buffer) {
+  char* start = strstr(buffer, "\r\n");
+  if (start == NULL) {
+    return NULL;
+  }
+  start += sizeof("\r\n") - 1;
+
+  char* end = strstr(start, "\r\n");
+  if (end == NULL) {
+    return NULL;
+  }
+
+  int evt_size = end - start + 1;
+
+  char tmp_buf[BTA_HF_CLIENT_UNKOWN_EVENT_LEN];
+  if (evt_size < BTA_HF_CLIENT_UNKOWN_EVENT_LEN) {
+    strlcpy(tmp_buf, start, evt_size);
+    bta_hf_client_unknown_response(client_cb, tmp_buf);
+    AT_CHECK_RN(end);
+  } else {
+    APPL_TRACE_ERROR("%s: exceed event buffer size. (%d, %d)", __func__,
+                     evt_size, BTA_HF_CLIENT_UNKOWN_EVENT_LEN);
+  }
+
+  APPL_TRACE_DEBUG("%s: %s", __func__, buffer);
+
+  return end;
+}
+
 /******************************************************************************
  *       SUPPORTED EVENT MESSAGES
  ******************************************************************************/
@@ -1461,7 +1501,7 @@
     bta_hf_client_parse_cnum,        bta_hf_client_parse_btrh,
     bta_hf_client_parse_busy,        bta_hf_client_parse_delayed,
     bta_hf_client_parse_no_carrier,  bta_hf_client_parse_no_answer,
-    bta_hf_client_parse_blacklisted, bta_hf_client_skip_unknown};
+    bta_hf_client_parse_blacklisted, bta_hf_client_process_unknown};
 
 /* calculate supported event list length */
 static const uint16_t bta_hf_client_parser_cb_count =
@@ -1996,6 +2036,25 @@
   bta_hf_client_send_at(client_cb, BTA_HF_CLIENT_AT_BIA, buf, at_len);
 }
 
+void bta_hf_client_send_at_vendor_specific_cmd(tBTA_HF_CLIENT_CB* client_cb,
+                                               const char* str) {
+  char buf[BTA_HF_CLIENT_AT_MAX_LEN];
+
+  APPL_TRACE_DEBUG("%s", __func__);
+
+  int at_len = snprintf(buf, sizeof(buf), "AT%s", str);
+
+  if (at_len < 1) {
+    APPL_TRACE_ERROR("%s: AT command Framing error", __func__);
+    return;
+  }
+
+  buf[at_len - 1] = '\r';
+
+  bta_hf_client_send_at(client_cb, BTA_HF_CLIENT_AT_VENDOR_SPECIFIC, buf,
+                        at_len);
+}
+
 void bta_hf_client_at_init(tBTA_HF_CLIENT_CB* client_cb) {
   alarm_free(client_cb->at_cb.resp_timer);
   alarm_free(client_cb->at_cb.hold_timer);
@@ -2087,6 +2146,9 @@
     case BTA_HF_CLIENT_AT_CMD_NREC:
       bta_hf_client_send_at_nrec(client_cb);
       break;
+    case BTA_HF_CLIENT_AT_CMD_VENDOR_SPECIFIC_CMD:
+      bta_hf_client_send_at_vendor_specific_cmd(client_cb, p_val->str);
+      break;
     default:
       APPL_TRACE_ERROR("Default case");
       snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN,
diff --git a/bta/hf_client/bta_hf_client_int.h b/bta/hf_client/bta_hf_client_int.h
index 15ceec2..99967f7 100644
--- a/bta/hf_client/bta_hf_client_int.h
+++ b/bta/hf_client/bta_hf_client_int.h
@@ -97,6 +97,7 @@
   BTA_HF_CLIENT_AT_CNUM,
   BTA_HF_CLIENT_AT_NREC,
   BTA_HF_CLIENT_AT_BINP,
+  BTA_HF_CLIENT_AT_VENDOR_SPECIFIC,
 };
 
 /*****************************************************************************
diff --git a/bta/include/bta_hf_client_api.h b/bta/include/bta_hf_client_api.h
index 69dc109..897555d 100644
--- a/bta/include/bta_hf_client_api.h
+++ b/bta/include/bta_hf_client_api.h
@@ -119,6 +119,9 @@
                                      */
 #define BTA_HF_CLIENT_BINP_EVT 20 /* binp number event */
 #define BTA_HF_CLIENT_RING_INDICATION 21 /* HF Client ring indication */
+
+#define BTA_HF_CLIENT_UNKNOWN_EVT 22 /* Unknown or vendor specific Event */
+
 #define BTA_HF_CLIENT_DISABLE_EVT 30     /* HF Client disabled */
 
 typedef uint8_t tBTA_HF_CLIENT_EVT;
@@ -159,6 +162,7 @@
 #define BTA_HF_CLIENT_AT_CMD_BINP 13
 #define BTA_HF_CLIENT_AT_CMD_BLDN 14
 #define BTA_HF_CLIENT_AT_CMD_NREC 15
+#define BTA_HF_CLIENT_AT_CMD_VENDOR_SPECIFIC_CMD 16
 
 typedef uint8_t tBTA_HF_CLIENT_AT_CMD_TYPE;
 
@@ -234,6 +238,13 @@
   uint16_t value;
 } tBTA_HF_CLIENT_VAL;
 
+/* data associated with BTA_HF_CLIENT_UNKNOWN_EVT event */
+#define BTA_HF_CLIENT_UNKOWN_EVENT_LEN 32
+typedef struct {
+  RawAddress bd_addr;
+  char event_string[BTA_HF_CLIENT_UNKOWN_EVENT_LEN + 1];
+} tBTA_HF_CLIENT_UNKNOWN;
+
 /* union of data associated with AG callback */
 typedef union {
   // Common BD ADDR field for all tyepdefs
@@ -248,6 +259,7 @@
   tBTA_HF_CLIENT_AT_RESULT result;
   tBTA_HF_CLIENT_CLCC clcc;
   tBTA_HF_CLIENT_CNUM cnum;
+  tBTA_HF_CLIENT_UNKNOWN unknown;
 } tBTA_HF_CLIENT;
 
 typedef uint32_t tBTA_HF_CLIENT_FEAT;
diff --git a/btif/src/btif_hf_client.cc b/btif/src/btif_hf_client.cc
index e84291d..c999885 100644
--- a/btif/src/btif_hf_client.cc
+++ b/btif/src/btif_hf_client.cc
@@ -999,6 +999,10 @@
     case BTA_HF_CLIENT_RING_INDICATION:
       HAL_CBACK(bt_hf_client_callbacks, ring_indication_cb, &cb->peer_bda);
       break;
+    case BTA_HF_CLIENT_UNKNOWN_EVT:
+      HAL_CBACK(bt_hf_client_callbacks, unknown_event_cb, &cb->peer_bda,
+                p_data->unknown.event_string);
+      break;
     default:
       BTIF_TRACE_WARNING("%s: Unhandled event: %d", __func__, event);
       break;
diff --git a/include/hardware/bt_hf_client.h b/include/hardware/bt_hf_client.h
index a31de0f..d8f3a50 100644
--- a/include/hardware/bt_hf_client.h
+++ b/include/hardware/bt_hf_client.h
@@ -292,6 +292,12 @@
  */
 typedef void (*bthf_client_ring_indication_callback)(const RawAddress* bd_addr);
 
+/**
+ * Callback for sending unknown (vendor specific) event
+ */
+typedef void (*bthf_client_unknown_event_callback)(const RawAddress* bd_addr,
+                                                   const char* unknow_event);
+
 /** BT-HF callback structure. */
 typedef struct {
   /** set to sizeof(BtHfClientCallbacks) */
@@ -317,6 +323,7 @@
   bthf_client_in_band_ring_tone_callback in_band_ring_tone_cb;
   bthf_client_last_voice_tag_number_callback last_voice_tag_number_callback;
   bthf_client_ring_indication_callback ring_indication_cb;
+  bthf_client_unknown_event_callback unknown_event_cb;
 } bthf_client_callbacks_t;
 
 /** Represents the standard BT-HF interface. */