Merge "Incremental stack ext changes for HAL 2.0" into bt.lnx.5.0
diff --git a/Android.mk b/Android.mk
index f0d1960..5701414 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,5 +1,8 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
+TMP_LOCAL_PATH := $(LOCAL_PATH)
+
include $(LOCAL_PATH)/BATestApp/Android.mk
+include $(TMP_LOCAL_PATH)/certification_tools/Android.mk
diff --git a/BATestApp/Android.mk b/BATestApp/Android.mk
index bc1f5d1..ba23089 100644
--- a/BATestApp/Android.mk
+++ b/BATestApp/Android.mk
@@ -2,7 +2,6 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := debug
LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/res
LOCAL_RESOURCE_DIR += frameworks/support/v7/appcompat/res
LOCAL_RESOURCE_DIR += frameworks/support/v7/recyclerview/res
diff --git a/certification_tools/blegatt_test/Android.mk b/certification_tools/blegatt_test/Android.mk
index 653c5e1..afb9a8c 100644
--- a/certification_tools/blegatt_test/Android.mk
+++ b/certification_tools/blegatt_test/Android.mk
@@ -6,7 +6,7 @@
LOCAL_C_INCLUDES += . \
vendor/qcom/opensource/commonsys/system/bt/stack/include \
- vendor/qcom/opensource/commonsys/system/bt/include \
+ system/bt/include \
system/bt/types \
vendor/qcom/opensource/commonsys/system/bt/internal_include \
vendor/qcom/opensource/commonsys/system/bt/stack/l2cap \
@@ -20,7 +20,6 @@
LOCAL_CFLAGS += -DHAS_NO_BDROID_BUILDCFG
LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)
-LOCAL_MODULE_TAGS := debug optional
LOCAL_MODULE:= gatt_tool_qti_internal
diff --git a/certification_tools/blegatt_test/gatt_test.cpp b/certification_tools/blegatt_test/gatt_test.cpp
index 74c5092..383ad5f 100644
--- a/certification_tools/blegatt_test/gatt_test.cpp
+++ b/certification_tools/blegatt_test/gatt_test.cpp
@@ -68,6 +68,7 @@
#include <time.h>
#include <base/bind.h>
+#include <base/callback.h>
using bluetooth::Uuid;
#define bluetooth_module_t "bluetooth_test"
@@ -117,6 +118,11 @@
#define INTERVAL_MEDIUM 2
#define INTERVAL_HIGH 3
+#define L2CAP_LE_DEFAULT_MTU 512
+#define L2CAP_LE_DEFAULT_MPS 230
+#define L2CAP_LE_MAX_CREDIT 65535
+#define L2CAP_LE_DEFAULT_CREDIT 1
+
/************************************************************************************
** Local type definitions
************************************************************************************/
@@ -320,18 +326,18 @@
tL2CAP_FCR_OPTS ertm_fcr_opts_def = {
L2CAP_FCR_ERTM_MODE,
3, /* Tx window size */
- MCA_FCR_OPT_MAX_TX_B4_DISCNT, /* Maximum transmissions before disconnecting */
+ 20, /* Maximum transmissions before disconnecting */
2000, /* Retransmission timeout (2 secs) */
- MCA_FCR_OPT_MONITOR_TOUT, /* Monitor timeout (12 secs) */
+ 12000, /* Monitor timeout (12 secs) */
100 /* MPS segment size */
};
tL2CAP_FCR_OPTS stream_fcr_opts_def = {
L2CAP_FCR_STREAM_MODE,
3,/* Tx window size */
- MCA_FCR_OPT_MAX_TX_B4_DISCNT, /* Maximum transmissions before disconnecting */
+ 20, /* Maximum transmissions before disconnecting */
2000, /* Retransmission timeout (2 secs) */
- MCA_FCR_OPT_MONITOR_TOUT, /* Monitor timeout (12 secs) */
+ 12000, /* Monitor timeout (12 secs) */
100 /* MPS segment size */
};
static tL2CAP_ERTM_INFO t_ertm_info = {0, 0, 0, 0, 0, 0};
@@ -451,13 +457,13 @@
std::vector<btgatt_db_element_t> service1;
//1st service
- btgatt_db_element_t svc1;
+ btgatt_db_element_t svc1 = {0};
svc1.uuid = Uuid::FromString(IMMEDIATE_ALERT_UUID, &is_valid);
svc1.type = BTGATT_DB_PRIMARY_SERVICE;
service1.push_back(svc1);
//1st char
- btgatt_db_element_t char1;
+ btgatt_db_element_t char1 = {0};
char1.uuid = Uuid::FromString(ALERT_LEVEL_UUID1, &is_valid);
char1.type = BTGATT_DB_CHARACTERISTIC;
char1.properties = 58;
@@ -466,7 +472,7 @@
service1.push_back(char1);
//1st desc
- btgatt_db_element_t desc1;
+ btgatt_db_element_t desc1 = {0};
desc1.uuid = Uuid::FromString(ClientCharConfigUUID, &is_valid);
desc1.type = BTGATT_DB_DESCRIPTOR;
desc1.permissions = 17;
@@ -474,7 +480,7 @@
service1.push_back(desc1);
//2nd char
- btgatt_db_element_t char2;
+ btgatt_db_element_t char2 = {0};
char2.uuid = Uuid::FromString(ALERT_LEVEL_UUID2, &is_valid);
char2.type = BTGATT_DB_CHARACTERISTIC;
char2.properties = 58;
@@ -483,7 +489,7 @@
service1.push_back(char2);
//2nd desc
- btgatt_db_element_t desc2;
+ btgatt_db_element_t desc2 = {0};
desc2.uuid = Uuid::FromString(ClientCharConfigUUID, &is_valid);
desc2.type = BTGATT_DB_DESCRIPTOR;
desc2.permissions = 34;
@@ -492,7 +498,7 @@
//3rd char
- btgatt_db_element_t char3;
+ btgatt_db_element_t char3 = {0};
char3.uuid = Uuid::FromString(ALERT_LEVEL_UUID3, &is_valid);
char3.type = BTGATT_DB_CHARACTERISTIC;
char3.properties = 58;
@@ -501,7 +507,7 @@
service1.push_back(char3);
//3rd desc
- btgatt_db_element_t desc3;
+ btgatt_db_element_t desc3 = {0};
desc3.uuid = Uuid::FromString(ClientCharConfigUUID, &is_valid);
desc3.type = BTGATT_DB_DESCRIPTOR;
desc3.permissions = 68;
@@ -510,7 +516,7 @@
//4th char
- btgatt_db_element_t char4;
+ btgatt_db_element_t char4 = {0};
char4.uuid = Uuid::FromString(AUTHENTICATION_LEVEL_UUID1, &is_valid);
char4.type = BTGATT_DB_CHARACTERISTIC;
char4.properties = 58;
@@ -519,7 +525,7 @@
service1.push_back(char4);
//4th desc
- btgatt_db_element_t desc4;
+ btgatt_db_element_t desc4 = {0};
desc4.uuid = Uuid::FromString(AUTHENTICATION_LEVEL_DESC_UUID1, &is_valid);
desc4.type = BTGATT_DB_DESCRIPTOR;
desc4.permissions = 34;
@@ -528,7 +534,7 @@
//5th char
- btgatt_db_element_t char5;
+ btgatt_db_element_t char5 = {0};
char5.uuid = Uuid::FromString(AUTHENTICATION_LEVEL_UUID2, &is_valid);
char5.type = BTGATT_DB_CHARACTERISTIC;
char5.properties = 58;
@@ -537,7 +543,7 @@
service1.push_back(char5);
//5th desc
- btgatt_db_element_t desc5;
+ btgatt_db_element_t desc5 = {0};
desc5.uuid = Uuid::FromString(AUTHENTICATION_LEVEL_DESC_UUID2, &is_valid);
desc5.type = BTGATT_DB_DESCRIPTOR;
desc5.permissions = 68;
@@ -545,7 +551,7 @@
service1.push_back(desc5);
//6th char
- btgatt_db_element_t char6;
+ btgatt_db_element_t char6 = {0};
char6.uuid = Uuid::FromString(ALERT_LEVEL_UUID4, &is_valid);
char6.type = BTGATT_DB_CHARACTERISTIC;
char6.properties = 4;
@@ -554,7 +560,7 @@
service1.push_back(char6);
//6th desc
- btgatt_db_element_t desc6;
+ btgatt_db_element_t desc6 = {0};
desc6.uuid = Uuid::FromString(DISC_LEVEL_UUID1, &is_valid);
desc6.type = BTGATT_DB_DESCRIPTOR;
desc6.permissions = 16;
@@ -562,7 +568,7 @@
service1.push_back(desc6);
//7th char
- btgatt_db_element_t char7;
+ btgatt_db_element_t char7 = {0};
char7.uuid = Uuid::FromString(ALERT_LEVEL_UUID5, &is_valid);
char7.type = BTGATT_DB_CHARACTERISTIC;
char7.properties = 114;
@@ -571,7 +577,7 @@
service1.push_back(char7);
//7th desc
- btgatt_db_element_t desc7;
+ btgatt_db_element_t desc7 = {0};
desc7.uuid = Uuid::FromString(ClientCharConfigUUID, &is_valid);
desc7.type = BTGATT_DB_DESCRIPTOR;
desc7.permissions = 129;
@@ -579,7 +585,7 @@
service1.push_back(desc7);
//8th char
- btgatt_db_element_t char8;
+ btgatt_db_element_t char8 = {0};
char8.uuid = Uuid::FromString(ALERT_LEVEL_UUID6, &is_valid);
char8.type = BTGATT_DB_CHARACTERISTIC;
char8.properties = 66;
@@ -588,7 +594,7 @@
service1.push_back(char8);
//8th desc
- btgatt_db_element_t desc8;
+ btgatt_db_element_t desc8 = {0};
desc8.uuid = Uuid::FromString(DISC_LEVEL_UUID2, &is_valid);
desc8.type = BTGATT_DB_DESCRIPTOR;
desc8.permissions = 129;
@@ -596,7 +602,7 @@
service1.push_back(desc8);
//9th char
- btgatt_db_element_t char9;
+ btgatt_db_element_t char9 = {0};
char9.uuid = Uuid::FromString(ALERT_LEVEL_WRITENORESPONSEWITHREADABLE2, &is_valid);
char9.type = BTGATT_DB_CHARACTERISTIC;
char9.properties = 6;
@@ -605,7 +611,7 @@
service1.push_back(char9);
//9th desc
- btgatt_db_element_t desc9;
+ btgatt_db_element_t desc9 = {0};
desc9.uuid = Uuid::FromString(DISC_LEVEL_UUID7, &is_valid);
desc9.type = BTGATT_DB_DESCRIPTOR;
desc9.permissions = 17;
@@ -613,7 +619,7 @@
service1.push_back(desc9);
//10th char
- btgatt_db_element_t char10;
+ btgatt_db_element_t char10 = {0};
char10.uuid = Uuid::FromString(ALERT_LEVEL_UUID18, &is_valid);
char10.type = BTGATT_DB_CHARACTERISTIC;
char10.properties = 58;
@@ -622,7 +628,7 @@
service1.push_back(char10);
//10th desc
- btgatt_db_element_t desc10;
+ btgatt_db_element_t desc10 = {0};
desc10.uuid = Uuid::FromString(ClientCharConfigUUID, &is_valid);
desc10.type = BTGATT_DB_DESCRIPTOR;
desc10.permissions = 17;
@@ -630,7 +636,7 @@
service1.push_back(desc10);
//11th char
- btgatt_db_element_t char11;
+ btgatt_db_element_t char11 = {0};
char11.uuid = Uuid::FromString(ALERT_LEVEL_UUID19, &is_valid);
char11.type = BTGATT_DB_CHARACTERISTIC;
char11.properties = 58;
@@ -639,7 +645,7 @@
service1.push_back(char11);
//11th desc
- btgatt_db_element_t desc11;
+ btgatt_db_element_t desc11 = {0};
desc11.uuid = Uuid::FromString(ClientCharConfigUUID, &is_valid);
desc11.type = BTGATT_DB_DESCRIPTOR;
desc11.permissions = 17;
@@ -653,7 +659,7 @@
//Second Service - longvalue service
std::vector<btgatt_db_element_t> service2;
//2nd service
- btgatt_db_element_t svc2;
+ btgatt_db_element_t svc2 = {0};
svc2.uuid = Uuid::FromString(IMMEDIATE_ALERT_UUID1, &is_valid);
svc2.type = BTGATT_DB_PRIMARY_SERVICE;
service2.push_back(svc2);
@@ -808,7 +814,7 @@
//3rd service
std::vector<btgatt_db_element_t> service3;
- btgatt_db_element_t svc3;
+ btgatt_db_element_t svc3 = {0};
svc3.uuid = Uuid::FromString(IMMEDIATE_ALERT_UUID2, &is_valid);
svc3.type = BTGATT_DB_PRIMARY_SERVICE;
service3.push_back(svc3);
@@ -854,7 +860,7 @@
//4th service with no value set
std::vector<btgatt_db_element_t> service4;
- btgatt_db_element_t svc4;
+ btgatt_db_element_t svc4 = {0};
svc4.uuid = Uuid::FromString(IMMEDIATE_ALERT_UUID3, &is_valid);
svc4.type = BTGATT_DB_PRIMARY_SERVICE;
service4.push_back(svc4);
@@ -875,7 +881,7 @@
//5th service will all kinds of descriptors
std::vector<btgatt_db_element_t> service5;
- btgatt_db_element_t svc5;
+ btgatt_db_element_t svc5 = {0};
svc5.uuid = Uuid::FromString(IMMEDIATE_ALERT_UUID6, &is_valid);
svc5.type = BTGATT_DB_PRIMARY_SERVICE;
service5.push_back(svc5);
@@ -965,7 +971,7 @@
service5.push_back(desc11);
//12th desc
- btgatt_db_element_t desc12;
+ btgatt_db_element_t desc12 = {0};
desc12.uuid = Uuid::FromString(CharacteristicAggregateFormat, &is_valid);
desc12.type = BTGATT_DB_DESCRIPTOR;
desc12.permissions = 17;
@@ -996,7 +1002,7 @@
btgatt_response_t gatt_resp;
int status = BT_STATUS_SUCCESS;
std::vector<uint8_t> cccd_val;
- uint8_t val[2];
+ uint8_t val[2] = {};
gatt_resp.handle = attr_handle;
gatt_resp.attr_value.handle = attr_handle;
gatt_resp.attr_value.offset = offset;
@@ -1056,7 +1062,7 @@
printf("%s:: conn_id=%d, trans_id=%d, attr_handle=%d \n", __FUNCTION__, conn_id, trans_id, attr_handle);
bt_status_t Ret;
int status = BT_STATUS_SUCCESS;
- uint8_t cccd_val[2];
+ uint8_t cccd_val[2] = {};
btgatt_response_t gatt_resp;
gatt_resp.handle = attr_handle;
gatt_resp.attr_value.handle = attr_handle;
@@ -2031,20 +2037,20 @@
if (psm == 200)
{
printf("No Resources Available\n");
- result = L2CAP_LE_NO_RESOURCES;
- sL2capInterface->LeConnectRsp (bd_addr, id, lcid, result,L2CAP_LE_CONN_OK,&local_coc_cfg);
+ result = L2CAP_LE_RESULT_NO_RESOURCES;
+ sL2capInterface->LeConnectRsp (bd_addr, id, lcid, result,L2CAP_LE_RESULT_CONN_OK,&local_coc_cfg);
}
else if(psm == 201)
{
printf("L2CAP_LE_CONN_INSUFFI_AUTHORIZATION \n");
- result = L2CAP_LE_INSUFFICIENT_AUTHORIZATION;
- sL2capInterface->LeConnectRsp (bd_addr, id, lcid, result,L2CAP_LE_CONN_OK,&local_coc_cfg);
+ result = L2CAP_LE_RESULT_INSUFFICIENT_AUTHORIZATION;
+ sL2capInterface->LeConnectRsp (bd_addr, id, lcid, result,L2CAP_LE_RESULT_CONN_OK,&local_coc_cfg);
}
else
{
- result = L2CAP_LE_CONN_OK;
- sL2capInterface->LeConnectRsp (bd_addr, id, lcid, result,L2CAP_LE_CONN_OK,&local_coc_cfg);
+ result = L2CAP_LE_RESULT_CONN_OK;
+ sL2capInterface->LeConnectRsp (bd_addr, id, lcid, result,L2CAP_LE_RESULT_CONN_OK,&local_coc_cfg);
}
return;
}
@@ -2073,7 +2079,7 @@
if (le_conn_info&&L2C_IS_VALID_LE_PSM(le_conn_info->psm))
{
- if (result == L2CAP_LE_CONN_OK) {
+ if (result == L2CAP_LE_RESULT_CONN_OK) {
g_ConnectionState = CONNECT;
}
else if(le_conn_info && !le_conn_info->is_server)
@@ -2524,7 +2530,8 @@
timeout = get_hex(&p, -1);
if(FALSE == GetBdAddr(p, &bd_addr)) return;
- Ret = sGattIfaceScan->client->conn_parameter_update(bd_addr, min_interval, max_interval, latency, timeout);
+ Ret = sGattIfaceScan->client->conn_parameter_update(bd_addr, min_interval,
+ max_interval, latency, timeout, 0, 0);
printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
}
@@ -2758,13 +2765,12 @@
{
int uuid_len = 0, uuid_len_bytes = 0;
tGATT_STATUS Ret =0;
- tGATT_DISC_PARAM param;
tGATT_DISC_TYPE disc_type; //GATT_DISC_SRVC_ALL , GATT_DISC_SRVC_BY_UUID
bool is_valid = false;
disc_type = get_int(&p, -1); // arg1
- param.s_handle = get_hex(&p, -1); // arg2
- param.e_handle = get_hex(&p, -1); // arg3
+ uint16_t s_handle = get_hex(&p, -1); // arg2
+ uint16_t e_handle = get_hex(&p, -1); // arg3
uuid_len = get_int(&p, -1); // arg4 - Size in bits for the uuid (16, 32, or 128)
if((16==uuid_len) || (32==uuid_len) || (128==uuid_len))
@@ -2778,12 +2784,12 @@
}
std::string uuid_str = get_uuid_str(&p, uuid_len_bytes);
- param.service = Uuid::FromString(uuid_str, &is_valid);
+ Uuid service = Uuid::FromString(uuid_str, &is_valid);
printf("%s:: disc_type = %d is_valid = %d\n", __FUNCTION__, disc_type, is_valid);
//if(FALSE == GetDiscType(p, &disc_type)) return; //TODO - add the function if user input is needed
- Ret = sGattInterface->cDiscover(g_conn_id, disc_type, ¶m);
+ Ret = sGattInterface->cDiscover(g_conn_id, disc_type, s_handle, e_handle, service);
printf("%s:: Ret=%d \n", __FUNCTION__, Ret);
}
@@ -2988,13 +2994,13 @@
std::vector<btgatt_db_element_t> service;
//1st service
- btgatt_db_element_t svc1;
+ btgatt_db_element_t svc1 = {0};
svc1.uuid = Uuid::FromString("00001800-0000-1000-8000-00805f9b34fb", &is_valid);//00001800-0000-1000-8000-00805f9b34fb
svc1.type = BTGATT_DB_PRIMARY_SERVICE;
service.push_back(svc1);
//2nd service
- btgatt_db_element_t svc2;
+ btgatt_db_element_t svc2 = {0};
svc2.uuid = Uuid::FromString("00001801-0000-1000-8000-00805f9b34fb", &is_valid);//00001801-0000-1000-8000-00805f9b34fb
svc2.type = BTGATT_DB_PRIMARY_SERVICE;
service.push_back(svc2);
diff --git a/certification_tools/l2test_ertm/Android.mk b/certification_tools/l2test_ertm/Android.mk
index 4ca568f..2adbb4f 100644
--- a/certification_tools/l2test_ertm/Android.mk
+++ b/certification_tools/l2test_ertm/Android.mk
@@ -6,7 +6,7 @@
LOCAL_C_INCLUDES += . \
vendor/qcom/opensource/commonsys/system/bt/stack/include \
- vendor/qcom/opensource/commonsys/system/bt/include \
+ system/bt/include \
system/bt/types \
vendor/qcom/opensource/commonsys/system/bt/internal_include \
vendor/qcom/opensource/commonsys/system/bt/stack/l2cap \
@@ -19,7 +19,6 @@
LOCAL_CFLAGS += -DHAS_NO_BDROID_BUILDCFG
LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)
-LOCAL_MODULE_TAGS := debug optional
LOCAL_MODULE:= l2test_ertm
LOCAL_SHARED_LIBRARIES += libcutils \
diff --git a/certification_tools/l2test_ertm/l2test_ertm.cpp b/certification_tools/l2test_ertm/l2test_ertm.cpp
index a97272c..2c3b4ae 100644
--- a/certification_tools/l2test_ertm/l2test_ertm.cpp
+++ b/certification_tools/l2test_ertm/l2test_ertm.cpp
@@ -139,18 +139,18 @@
tL2CAP_FCR_OPTS ertm_fcr_opts_def = {
L2CAP_FCR_ERTM_MODE,
3, /* Tx window size */
- MCA_FCR_OPT_MAX_TX_B4_DISCNT, /* Maximum transmissions before disconnecting */
+ 20, /* Maximum transmissions before disconnecting */
2000, /* Retransmission timeout (2 secs) */
- MCA_FCR_OPT_MONITOR_TOUT, /* Monitor timeout (12 secs) */
+ 12000, /* Monitor timeout (12 secs) */
100 /* MPS segment size */
};
tL2CAP_FCR_OPTS stream_fcr_opts_def = {
L2CAP_FCR_STREAM_MODE,
3,/* Tx window size */
- MCA_FCR_OPT_MAX_TX_B4_DISCNT, /* Maximum transmissions before disconnecting */
+ 20, /* Maximum transmissions before disconnecting */
2000, /* Retransmission timeout (2 secs) */
- MCA_FCR_OPT_MONITOR_TOUT, /* Monitor timeout (12 secs) */
+ 12000, /* Monitor timeout (12 secs) */
100 /* MPS segment size */
};
static tL2CAP_ERTM_INFO t_ertm_info = {0,0,0,0,0,0};
diff --git a/certification_tools/mcap_tool/Android.mk b/certification_tools/mcap_tool/Android.mk.disabled
similarity index 90%
rename from certification_tools/mcap_tool/Android.mk
rename to certification_tools/mcap_tool/Android.mk.disabled
index 602d3a2..93b8326 100644
--- a/certification_tools/mcap_tool/Android.mk
+++ b/certification_tools/mcap_tool/Android.mk.disabled
@@ -6,7 +6,7 @@
LOCAL_C_INCLUDES += . \
vendor/qcom/opensource/commonsys/system/bt/stack/include \
- vendor/qcom/opensource/commonsys/system/bt/include \
+ system/bt/include \
system/bt/types \
vendor/qcom/opensource/commonsys/system/bt/internal_include \
vendor/qcom/opensource/commonsys/system/bt/stack/l2cap \
@@ -19,7 +19,6 @@
LOCAL_CFLAGS += -DHAS_NO_BDROID_BUILDCFG
LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)
-LOCAL_MODULE_TAGS := debug optional
LOCAL_MODULE:= mcap_tool_qti_internal
diff --git a/certification_tools/rfcommtest/Android.mk b/certification_tools/rfcommtest/Android.mk
index dcd1d0e..ddd9197 100644
--- a/certification_tools/rfcommtest/Android.mk
+++ b/certification_tools/rfcommtest/Android.mk
@@ -6,7 +6,7 @@
LOCAL_C_INCLUDES += . \
vendor/qcom/opensource/commonsys/system/bt/stack/include \
- vendor/qcom/opensource/commonsys/system/bt/include \
+ system/bt/include \
system/bt/types \
vendor/qcom/opensource/commonsys/system/bt/internal_include \
vendor/qcom/opensource/commonsys/system/bt/stack/l2cap \
@@ -19,7 +19,6 @@
LOCAL_CFLAGS += -DHAS_NO_BDROID_BUILDCFG
LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)
-LOCAL_MODULE_TAGS := debug optional
LOCAL_MODULE:= rfc
LOCAL_SHARED_LIBRARIES += libcutils \
diff --git a/packages_apps_bluetooth_ext/jni/com_android_bluetooth_btservice_vendor.cpp b/packages_apps_bluetooth_ext/jni/com_android_bluetooth_btservice_vendor.cpp
index c89a78e..403df02 100644
--- a/packages_apps_bluetooth_ext/jni/com_android_bluetooth_btservice_vendor.cpp
+++ b/packages_apps_bluetooth_ext/jni/com_android_bluetooth_btservice_vendor.cpp
@@ -63,6 +63,8 @@
static jmethodID method_onBredrCleanup;
static jmethodID method_iotDeviceBroadcast;
static jmethodID method_devicePropertyChangedCallback;
+static jmethodID method_adapterPropertyChangedCallback;
+static jmethodID method_ssrCleanupCallback;
static btvendor_interface_t *sBluetoothVendorInterface = NULL;
static jobject mCallbacksObj = NULL;
@@ -115,6 +117,16 @@
sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onBredrCleanup, (jboolean)status);
}
+static void ssr_cleanup_callback(void){
+
+ ALOGI("%s", __FUNCTION__);
+ CallbackEnv sCallbackEnv(__func__);
+
+ if (!sCallbackEnv.valid()) return;
+
+ sCallbackEnv->CallVoidMethod(mCallbacksObj, method_ssrCleanupCallback);
+}
+
static void iot_device_broadcast_callback(RawAddress* bd_addr, uint16_t error,
uint16_t error_info, uint32_t event_mask, uint8_t lmp_ver, uint16_t lmp_subver,
uint16_t manufacturer_id, uint8_t power_level, int8_t rssi, uint8_t link_quality,
@@ -135,6 +147,49 @@
(jint)manufacturer_id, (jint)power_level, (jint)rssi, (jint)link_quality,
(jint)glitch_count);
}
+
+static void adapter_vendor_properties_callback(bt_status_t status,
+ int num_properties,
+ bt_vendor_property_t *properties) {
+ CallbackEnv sCallbackEnv(__func__);
+ if (!sCallbackEnv.valid()) return;
+ ALOGE("%s: Status is: %d, Properties: %d", __func__, status, num_properties);
+ if (status != BT_STATUS_SUCCESS) {
+ ALOGE("%s: Status %d is incorrect", __func__, status);
+ return;
+ }
+ ScopedLocalRef<jbyteArray> val(
+ sCallbackEnv.get(),
+ (jbyteArray)sCallbackEnv->NewByteArray(num_properties));
+ if (!val.get()) {
+ ALOGE("%s: Error allocating byteArray", __func__);
+ return;
+ }
+ ScopedLocalRef<jclass> mclass(sCallbackEnv.get(),
+ sCallbackEnv->GetObjectClass(val.get()));
+ ScopedLocalRef<jobjectArray> props(
+ sCallbackEnv.get(),
+ sCallbackEnv->NewObjectArray(num_properties, mclass.get(), NULL));
+ if (!props.get()) {
+ ALOGE("%s: Error allocating object Array for properties", __func__);
+ return;
+ }
+ ScopedLocalRef<jintArray> types(
+ sCallbackEnv.get(), (jintArray)sCallbackEnv->NewIntArray(num_properties));
+ if (!types.get()) {
+ ALOGE("%s: Error allocating int Array for values", __func__);
+ return;
+ }
+ jintArray typesPtr = types.get();
+ jobjectArray propsPtr = props.get();
+ if (get_properties(num_properties, properties, &typesPtr, &propsPtr) < 0) {
+ return;
+ }
+ sCallbackEnv->CallVoidMethod(mCallbacksObj,
+ method_adapterPropertyChangedCallback,
+ types.get(), props.get());
+}
+
static void remote_device_properties_callback(bt_status_t status,
RawAddress *bd_addr, int num_properties,
bt_vendor_property_t *properties) {
@@ -191,6 +246,8 @@
iot_device_broadcast_callback,
remote_device_properties_callback,
NULL,
+ adapter_vendor_properties_callback,
+ ssr_cleanup_callback,
};
static void classInitNative(JNIEnv* env, jclass clazz) {
@@ -199,6 +256,10 @@
method_iotDeviceBroadcast = env->GetMethodID(clazz, "iotDeviceBroadcast", "([BIIIIIIIIII)V");
method_devicePropertyChangedCallback = env->GetMethodID(
clazz, "devicePropertyChangedCallback", "([B[I[[B)V");
+ method_adapterPropertyChangedCallback = env->GetMethodID(
+ clazz, "adapterPropertyChangedCallback", "([I[[B)V");
+ method_ssrCleanupCallback = env->GetMethodID(
+ clazz, "ssr_cleanup_callback", "()V");
ALOGI("%s: succeeds", __FUNCTION__);
}
@@ -278,6 +339,17 @@
return JNI_TRUE;
}
+static bool hcicloseNative(JNIEnv *env, jobject obj) {
+
+ ALOGI("%s", __FUNCTION__);
+
+ jboolean result = JNI_FALSE;
+ if (!sBluetoothVendorInterface) return result;
+
+ sBluetoothVendorInterface->hciclose();
+ return JNI_TRUE;
+}
+
static bool setWifiStateNative(JNIEnv *env, jobject obj, jboolean status) {
ALOGI("%s", __FUNCTION__);
@@ -331,6 +403,7 @@
{"getProfileInfoNative", "(II)Z", (void*) getProfileInfoNative},
{"getQtiStackStatusNative", "()Z", (void*) getQtiStackStatusNative},
{"voipNetworkWifiInfoNative", "(ZZ)Z", (void *)voipNetworkWifiInfoNative},
+ {"hcicloseNative", "()V", (void*) hcicloseNative},
};
int register_com_android_bluetooth_btservice_vendor(JNIEnv* env)
diff --git a/packages_apps_bluetooth_ext/src/avrcp/AvrcpBipRsp.java b/packages_apps_bluetooth_ext/src/avrcp/AvrcpBipRsp.java
index 028667d..b621e73 100644
--- a/packages_apps_bluetooth_ext/src/avrcp/AvrcpBipRsp.java
+++ b/packages_apps_bluetooth_ext/src/avrcp/AvrcpBipRsp.java
@@ -83,7 +83,7 @@
public AvrcpBipRsp (Context context, int maxBipConnections) {
mContext = context;
- mMaxBipDevices = getMaxDevices();
+ mMaxBipDevices = maxBipConnections;
mAdapter = BluetoothAdapter.getDefaultAdapter();
mHandlerThread = new HandlerThread("BipHandlerThread");
mHandlerThread.start();
diff --git a/packages_apps_bluetooth_ext/src/avrcp/Avrcp_ext.java b/packages_apps_bluetooth_ext/src/avrcp/Avrcp_ext.java
index 1de651b..a57da3f 100644
--- a/packages_apps_bluetooth_ext/src/avrcp/Avrcp_ext.java
+++ b/packages_apps_bluetooth_ext/src/avrcp/Avrcp_ext.java
@@ -171,6 +171,7 @@
private byte changePathDirection;
HashMap<BluetoothDevice, Integer> mVolumeMap = new HashMap();
public static final String VOLUME_MAP = "bluetooth_volume_map";
+ private boolean isShoActive = false;
private boolean twsShoEnabled = false;
private static final String playerStateUpdateBlackListedAddr[] = {
@@ -234,6 +235,7 @@
private final static int MESSAGE_UPDATE_ABS_VOLUME_STATUS = 31;
private final static int MESSAGE_UPDATE_ABSOLUTE_VOLUME = 32;
private static final int MSG_PLAY_STATUS_CMD_TIMEOUT = 33;
+ private final static int MESSAGE_START_SHO = 34;
private static final int STACK_CLEANUP = 0;
private static final int APP_CLEANUP = 1;
@@ -406,6 +408,11 @@
};
DeviceDependentFeature[] deviceFeatures;
+ private static class SHOQueue {
+ static BluetoothDevice device;
+ static boolean PlayReq;
+ }
+
static {
classInitNative();
}
@@ -802,8 +809,21 @@
vol = convertToAvrcpVolume(vol);
Log.d(TAG,"vol = " + vol + "rem vol = " + deviceFeatures[deviceIndex].mRemoteVolume);
if(vol != deviceFeatures[deviceIndex].mRemoteVolume &&
- deviceFeatures[deviceIndex].isAbsoluteVolumeSupportingDevice)
+ deviceFeatures[deviceIndex].isAbsoluteVolumeSupportingDevice &&
+ deviceFeatures[deviceIndex].mCurrentDevice != null) {
setVolumeNative(vol , getByteAddress(deviceFeatures[deviceIndex].mCurrentDevice));
+ if (deviceFeatures[deviceIndex].mCurrentDevice.isTwsPlusDevice()) {
+ AdapterService adapterService = AdapterService.getAdapterService();
+ BluetoothDevice peer_device =
+ adapterService.getTwsPlusPeerDevice(deviceFeatures[deviceIndex].mCurrentDevice);
+ if (peer_device != null &&
+ getIndexForDevice(peer_device) != INVALID_DEVICE_INDEX) {
+ // Change volume to peer earbud as well
+ Log.d(TAG,"setting volume to TWS+ peer also");
+ setVolumeNative(vol, getByteAddress(peer_device));
+ }
+ }
+ }
}
//mLastLocalVolume = -1;
break;
@@ -1342,9 +1362,28 @@
// This is for some remote devices, which send PLAY/PAUSE based on AVRCP State.
BATService mBatService = BATService.getBATService();
if ((mBatService == null) || !mBatService.isA2dpSuspendFromBA()) {
- // if this suspend was triggered by BA, then don't update AVRCP state
+ // if this suspend was triggered by BA, then don't update AVRCP states
updateCurrentMediaState((BluetoothDevice)msg.obj);
}
+
+ if (mA2dpState == BluetoothA2dp.STATE_PLAYING) {
+ boolean shoComplete = false;
+ synchronized(Avrcp_ext.this) {
+ if(isShoActive) {
+ isShoActive = false;
+ shoComplete = true;
+ Log.e(TAG, "1: SHO complete");
+ }
+
+ if(mHandler.hasMessages(MESSAGE_START_SHO)) {
+ mHandler.removeMessages(MESSAGE_START_SHO);
+ triggerSHO(SHOQueue.device, SHOQueue.PlayReq);
+ }
+ }
+ if(shoComplete == true) {
+ CompleteSHO();
+ }
+ }
}
break;
@@ -1509,6 +1548,36 @@
deviceFeatures[deviceIndex].isPlayStatusTimeOut = true;
break;
+ case MESSAGE_START_SHO:
+ if (mA2dpService != null)
+ break;
+
+ synchronized (Avrcp_ext.this) {
+ if(mHandler.hasMessages(MESSAGE_START_SHO)) {
+ Log.e(TAG, "Queue already has another SHO pending");
+ break;
+ }
+ isShoActive = true;
+ Log.d(TAG, "2: SHO started. PlayReq = " + msg.arg1);
+ }
+
+ BluetoothDevice dev = (BluetoothDevice)msg.obj;
+ boolean PlayReq = (msg.arg1 == 1);
+ mA2dpService.startSHO(dev);
+
+ if(!PlayReq) {
+ synchronized (Avrcp_ext.this) {
+ isShoActive = false;
+ Log.d(TAG, "3: SHO complete");
+ if (mHandler.hasMessages(MESSAGE_START_SHO)) {
+ mHandler.removeMessages(MESSAGE_START_SHO);
+ triggerSHO(SHOQueue.device, SHOQueue.PlayReq);
+ }
+ }
+ CompleteSHO();
+ }
+ break;
+
default:
Log.e(TAG, "unknown message! msg.what=" + msg.what);
break;
@@ -2073,6 +2142,10 @@
&& (mA2dpState == BluetoothA2dp.STATE_PLAYING)) {
Log.i(TAG, "Players updated current playback state is none," +
" skip updating playback state");
+ } else if (device == null && newState != null &&
+ newState.getState() == PlaybackState.STATE_ERROR) {
+ Log.i(TAG, "Players updated current playback state is error," +
+ " skip updating playback state");
} else {
updatePlaybackState(newState, device);
}
@@ -2391,8 +2464,17 @@
SystemClock.elapsedRealtime() - deviceFeatures[deviceIndex].mLastStateUpdate;
currPosition = sinceUpdate + deviceFeatures[deviceIndex].mCurrentPlayState.getPosition();
} else {
- currPosition = deviceFeatures[deviceIndex].mCurrentPlayState.getPosition();
-
+ if (isPlayingState(deviceFeatures[deviceIndex].mCurrentPlayState) &&
+ (avrcp_playstatus_blacklist && isPlayerStateUpdateBlackListed(
+ deviceFeatures[deviceIndex].mCurrentDevice.getAddress(),
+ deviceFeatures[deviceIndex].mCurrentDevice.getName()))) {
+ currPosition = mCurrentPlayerState.getPosition();
+ Log.d(TAG, "Remote is BLed for playstatus, So send playposition by fetching from "+
+ "mCurrentPlayerState." + currPosition);
+ } else {
+ currPosition = deviceFeatures[deviceIndex].mCurrentPlayState.getPosition();
+ Log.d(TAG, "getPlayPosition(): currPosition = " + currPosition);
+ }
}
} else {
if (mCurrentPlayerState == null) {
@@ -3098,7 +3180,8 @@
(mDevice.isTwsPlusDevice() && device.isTwsPlusDevice()))) {
setActiveDevice(mDevice);
//below line to send setAbsolute volume if device is suporting absolute volume
- setAbsVolumeFlag(mDevice);
+ if (mDevice.equals(deviceFeatures[index].mCurrentDevice))
+ setAbsVolumeFlag(mDevice);//Do not call this funciton for second EB connect
//When A2dp playing on DUT and Remote got connected, send proper playstatus
if (isPlayingState(mCurrentPlayerState) &&
mA2dpService.isA2dpPlaying(device)) {
@@ -3549,7 +3632,9 @@
mPackageManager.queryIntentServices(intent, PackageManager.MATCH_ALL);
for (ResolveInfo info : playerList) {
- String displayableName = info.loadLabel(mPackageManager).toString();
+ CharSequence displayName = info.loadLabel(mPackageManager);
+ String displayableName =
+ (displayName != null) ? displayName.toString():new String();
String serviceName = info.serviceInfo.name;
String packageName = info.serviceInfo.packageName;
@@ -4620,7 +4705,7 @@
if((rspStatus == AvrcpConstants.RSP_NO_ERROR) && ((mA2dpService != null) &&
!Objects.equals(mA2dpService.getActiveDevice(), device))) {
Log.d(TAG, "Trigger Handoff by playItem");
- mA2dpService.setActiveDevice(device);
+ startSHO(device, true);
}
if (!playItemRspNative(address, rspStatus)) {
Log.e(TAG, "playItemRspNative failed!");
@@ -4792,7 +4877,43 @@
}
public boolean startSHO(BluetoothDevice device, boolean PlayReq) {
- return false;
+ synchronized (Avrcp_ext.this) {
+ if(isShoActive) {
+ mHandler.removeMessages (MESSAGE_START_SHO);
+ Message msg = mHandler.obtainMessage(MESSAGE_START_SHO, PlayReq?1:0, 0, device);
+ SHOQueue.device = device;
+ SHOQueue.PlayReq = PlayReq;
+ mHandler.sendMessageDelayed(msg, 3000);
+ Log.d(TAG, "4: SHO Queued");
+ return true;
+ } else {
+ isShoActive = true;
+ Log.d(TAG, "5: SHO started: PlayReq = " + PlayReq);
+ }
+ }
+ boolean ret = mA2dpService.startSHO(device);
+ synchronized (Avrcp_ext.this) {
+ if (!PlayReq) {
+ isShoActive = false;
+ Log.d(TAG, "6: SHO complete");
+
+ if (mHandler.hasMessages(MESSAGE_START_SHO)) {
+ mHandler.removeMessages(MESSAGE_START_SHO);
+ triggerSHO(SHOQueue.device, SHOQueue.PlayReq);
+ }
+ }
+ }
+ CompleteSHO();
+ return ret;
+ }
+
+ private void triggerSHO(BluetoothDevice device, boolean PlayReq) {
+ Message msg = mHandler.obtainMessage(MESSAGE_START_SHO, PlayReq?1:0, 0, device);
+ mHandler.sendMessage(msg);
+ }
+
+ public void CompleteSHO() {
+ /*For device setup after SHO*/
}
public void setActiveDevice(BluetoothDevice device) {
@@ -4993,7 +5114,7 @@
}
if (action == KeyEvent.ACTION_DOWN) {
Log.d(TAG, "AVRCP Trigger Handoff");
- mA2dpService.setActiveDevice(device);
+ startSHO(device, true);
} else {
Log.d(TAG, "release for play PT from inactive device");
}
diff --git a/packages_apps_bluetooth_ext/src/ba/BATService.java b/packages_apps_bluetooth_ext/src/ba/BATService.java
index c2583b3..1cd459f 100644
--- a/packages_apps_bluetooth_ext/src/ba/BATService.java
+++ b/packages_apps_bluetooth_ext/src/ba/BATService.java
@@ -486,8 +486,9 @@
} else {// a2dp active device is null.
// inform BA device as disconnected. we have to send noisy intent
// because BA seems to be last device.
- mAudioManager.setBluetoothA2dpDeviceConnectionState(
- mBADevice, BluetoothProfile.STATE_DISCONNECTED,BluetoothProfile.A2DP);
+ mAudioManager.setBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
+ mBADevice, BluetoothProfile.STATE_DISCONNECTED,BluetoothProfile.A2DP,
+ false, -1);
}
if (!checkAbsVolSupport()) {
//Abs vol not supported by AVRCP, we should update false from BA.
diff --git a/packages_apps_bluetooth_ext/src/btservice/Vendor.java b/packages_apps_bluetooth_ext/src/btservice/Vendor.java
index 07ecd8d..6acaf4e 100644
--- a/packages_apps_bluetooth_ext/src/btservice/Vendor.java
+++ b/packages_apps_bluetooth_ext/src/btservice/Vendor.java
@@ -92,6 +92,10 @@
setWifiStateNative(status);
}
+ public void HCIClose() {
+ hcicloseNative();
+ }
+
public boolean getProfileInfo(int profile_id , int profile_info) {
Log.d(TAG,"getProfileInfo profile_id: " + profile_id);
return getProfileInfoNative(profile_id, profile_info);
@@ -146,6 +150,12 @@
intent.putExtra(BluetoothDevice.EXTRA_GLITCH_COUNT, glitchCount);
mService.sendBroadcast(intent, AdapterService.BLUETOOTH_PERM);
}
+
+ void ssr_cleanup_callback() {
+ Log.e(TAG,"ssr_cleanup_callback");
+ mService.ssrCleanupCallback();
+ }
+
void devicePropertyChangedCallback(byte[] address, int[] types, byte[][] values) {
byte[] val;
int type;
@@ -184,6 +194,30 @@
}
}
}
+
+ void adapterPropertyChangedCallback(int[] types, byte[][] values) {
+ byte[] val;
+ int type;
+
+ if (types.length <= 0) {
+ Log.e(TAG, "No properties to update");
+ return;
+ }
+
+ for (int j = 0; j < types.length; j++) {
+ type = types[j];
+ val = values[j];
+ Log.d(TAG, "Property type: " + type);
+ switch (type) {
+ case AbstractionLayer.BT_VENDOR_PROPERTY_HOST_ADD_ON_FEATURES:
+ mService.updateHostFeatureSupport(val);
+ break;
+ case AbstractionLayer.BT_VENDOR_PROPERTY_SOC_ADD_ON_FEATURES:
+ mService.updateSocFeatureSupport(val);
+ break;
+ }
+ }
+ }
private native void bredrcleanupNative();
private native void bredrstartupNative();
private native void initNative();
@@ -193,4 +227,5 @@
private native boolean getProfileInfoNative(int profile_id , int profile_info);
private native boolean getQtiStackStatusNative();
private native boolean voipNetworkWifiInfoNative(boolean isVoipStarted, boolean isNetworkWifi);
+ private native void hcicloseNative();
}
diff --git a/packages_apps_bluetooth_ext/src/map/src/BluetoothMapContentObserverEmail.java b/packages_apps_bluetooth_ext/src/map/src/BluetoothMapContentObserverEmail.java
index 79fec27..0e3e56f 100644
--- a/packages_apps_bluetooth_ext/src/map/src/BluetoothMapContentObserverEmail.java
+++ b/packages_apps_bluetooth_ext/src/map/src/BluetoothMapContentObserverEmail.java
@@ -214,19 +214,10 @@
mMasInstance = masInstance;
mMasId = mMasInstance.getMasId();
mMapSupportedFeatures = mMasInstance.getRemoteFeatureMask();
- if (D) Log.d(TAG, "BluetoothMapContentObserverEmail: Supported features " +
- Integer.toHexString(mMapSupportedFeatures) ) ;
-
- if((BluetoothMapUtils.MAP_FEATURE_EXTENDED_EVENT_REPORT_11_BIT
- & mMapSupportedFeatures) != 0){
- mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V11;
- }
- // Make sure support for all formats result in latest version returned
- if((BluetoothMapUtils.MAP_FEATURE_EVENT_REPORT_V12_BIT
- & mMapSupportedFeatures) != 0){
- mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
- }
-
+ if (D) Log.d(TAG, "Supported features " +
+ Integer.toHexString(mMapSupportedFeatures));
+ setObserverRemoteFeatureMask(mMapSupportedFeatures);
+ super.setObserverRemoteFeatureMask(mMapSupportedFeatures);
if(account != null) {
mAuthority = Uri.parse(account.mBase_uri).getAuthority();
Log.d(TAG,"mAuthority: "+mAuthority);
@@ -279,9 +270,19 @@
if ((BluetoothMapUtils.MAP_FEATURE_EVENT_REPORT_V12_BIT
& mMapSupportedFeatures) != 0) {
mMapEventReportVersion = BluetoothMapUtils.MAP_EVENT_REPORT_V12;
+ } else if (((BluetoothMapUtils.MAP_FEATURE_PARTICIPANT_PRESENCE_CHANGE_BIT
+ | BluetoothMapUtils.MAP_FEATURE_PARTICIPANT_CHAT_STATE_CHANGE_BIT)
+ & mMapSupportedFeatures) != 0) {
+ // Warning according to page 46/123 of MAP 1.3 spec
+ Log.w(TAG, "setObserverRemoteFeatureMask: Extended Event Reports 1.2 is not set even"
+ + "though PARTICIPANT_PRESENCE_CHANGE_BIT or PARTICIPANT_CHAT_STATE_CHANGE_BIT"
+ + " were set, mMapSupportedFeatures=" + mMapSupportedFeatures);
}
- if (V) Log.d(TAG, "setObserverRemoteFeatureMask Email: " + mMapEventReportVersion
- + " mMapSupportedFeatures Email: " + mMapSupportedFeatures);
+ if (D) {
+ Log.d(TAG, "setObserverRemoteFeatureMask: mMapEventReportVersion="
+ + mMapEventReportVersion + " mMapSupportedFeatures= "
+ +Integer.toHexString(mMapSupportedFeatures));
+ }
}
private static boolean sendEventNewMessage(long eventFilter) {
@@ -542,8 +543,8 @@
/* We must filter out any actions made by the MCE, hence do not send e.g.
* a message deleted and/or MessageShift for messages deleted by the MCE. */
if (msg == null) {
- if(V) Log.v(TAG, "handleMsgListChangesMsg id: " + id + "folderId: "
- + folderId + " newFolder: " +newFolder);
+ if(V) Log.v(TAG, "handleMsgListChangesMsg id: " + id + ", folderId: "
+ + folderId + ", newFolder: " +newFolder);
listChanged = true;
/* New message - created with message unread */
msg = new Msg(id, folderId, readFlag);
@@ -846,13 +847,17 @@
if (D) Log.d(TAG, "pushMessage emailBaseUri: "+emailBaseUri);
ArrayList<BluetoothMapbMessage.VCard> recipientList = msg.getRecipients();
ArrayList<BluetoothMapbMessage.VCard> originatorList = msg.getOriginators();
+ ArrayList<String> emailsTo = msg.getmRecipientTo();
+ ArrayList<String> emailsCc = msg.getmRecipientCc();
+ ArrayList<String> emailsBcc = msg.getmRecipientBCc();
+ int max_env_level = 3; // The maximum level of encapsulation shall be three
int transparent = (ap.getTransparent() == BluetoothMapAppParams.INVALID_VALUE_PARAMETER) ?
0 : ap.getTransparent();
int retry = ap.getRetry();
int charset = ap.getCharset();
long handle = -1;
long folderId = -1;
- if (recipientList == null) {
+ if (recipientList == null || recipientList.size() == 0) {
if (D) Log.d(TAG, "empty recipient list");
return -1;
}
@@ -876,92 +881,127 @@
Log.v(TAG, "part " + i + ":" + messages[i]);
}
}
- String toAddress[] = null;
+ StringBuilder addressCc = new StringBuilder();
+ StringBuilder addressBcc = new StringBuilder();
+ StringBuilder addressTo = new StringBuilder();
+ if (D) Log.v(TAG," pushMessage recipientList size:" + recipientList.size());
for (BluetoothMapbMessage.VCard recipient : recipientList) {
- if(recipient.getEnvLevel() == 0) // Only send the message to the top level recipient
- toAddress = ((BluetoothMapbMessage.VCard)recipient).getEmailAddresses();
- Uri uriInsert = BluetoothMapEmailContract
- .buildEmailMessageUri(BluetoothMapEmailContract.EMAIL_AUTHORITY);
- if (D) Log.d(TAG, "pushMessage - uriInsert= " + uriInsert.toString() +
- ", intoFolder id=" + folderElement.getFolderId());
- synchronized(getMsgListMsg()) {
- // Now insert the empty message into folder
- ContentValues values = new ContentValues();
- Time timeObj = new Time();
- timeObj.setToNow();
- folderId = folderElement.getFolderId();
- values.put(BluetoothMapEmailContract.ExtEmailMessageColumns.MAILBOX_KEY,
- folderId);
- if(((BluetoothMapbMessageExtEmail)msg).getSubject() != null) {
- values.put(BluetoothMapContract.MessageColumns.SUBJECT,
- ((BluetoothMapbMessageExtEmail)msg).getSubject());
- } else {
- values.put(BluetoothMapContract.MessageColumns.SUBJECT, "");
+ if (recipient.getEnvLevel() < max_env_level) {
+ String address[] = ((BluetoothMapbMessage.VCard)recipient).getEmailAddresses();
+ for (String s : address) {
+ if (emailsTo.contains(s)) {
+ addressTo.append(s);
+ addressTo.append(";");
+ } else if (emailsCc.contains(s)) {
+ addressCc.append(s);
+ addressCc.append(";");
+ } else if (emailsBcc.contains(s)) {
+ addressBcc.append(s);
+ addressBcc.append(";");
+ } else {
+ if (D) Log.d(TAG, "Ignoring extra address < " + s + " >");
+ }
}
- values.put("syncServerTimeStamp", 0);
- values.put("timeStamp", timeObj.toMillis(false));
- values.put("flagLoaded", "1");
- values.put("flagFavorite", "0");
- values.put("flagAttachment", "0");
- if(folderElement.getName().equalsIgnoreCase(BluetoothMapContract
- .FOLDER_NAME_DRAFT) || folderElement.getName()
- .equalsIgnoreCase(BluetoothMapEmailContract.FOLDER_NAME_DRAFTS)) {
- values.put("flags", "1179648");
- } else
- values.put("flags", "0");
- String splitStr[] = emailBaseUri.split("/");
- for (String str: splitStr)
- Log.d(TAG,"seg for mBaseUri: "+ str);
- if (mAccount != null) {
- values.put("accountKey", mAccount.getAccountId());
- values.put("displayName", mAccount.getDisplayName());
- values.put("fromList", mAccount.getEmailAddress());
- }
- values.put("mailboxKey", folderId);
- StringBuilder address = new StringBuilder();
- for (String s : toAddress) {
- address.append(s);
- address.append(";");
- }
- values.put("toList", address.toString().trim());
- values.put("flagRead", 0);
- Uri uriNew = mProviderClient.insert(uriInsert, values);
- if (D) Log.d(TAG, "pushMessage - uriNew= " + uriNew.toString());
- handle = Long.parseLong(uriNew.getLastPathSegment());
- if (V) {
- Log.v(TAG, " NEW HANDLE " + handle);
- }
- if(handle == -1) {
- Log.v(TAG, " Inavlid Handle ");
- return -1;
- }
- //Insert msgBody in DB Provider BODY TABLE
- ContentValues valuesBody = new ContentValues();
- valuesBody.put("messageKey", String.valueOf(handle));
- valuesBody.put("textContent", msgBody);
- Uri uriMsgBdyInsert = BluetoothMapEmailContract
- .buildEmailMessageBodyUri(BluetoothMapEmailContract.EMAIL_AUTHORITY);
- Log.d(TAG, "pushMessage - uriMsgBdyInsert = " + uriMsgBdyInsert.toString());
- mProviderClient.insert(uriMsgBdyInsert, valuesBody);
- // Extract the data for the inserted message, and store in local mirror, to
- // avoid sending a NewMessage Event.
- //TODO: We need to add the new 1.1 parameter as well:-) e.g. read
- Msg newMsg = new Msg(handle, folderId, 1); // TODO: Create define for read-state
- newMsg.transparent = (transparent == 1) ? true : false;
- newMsg.localInitiatedSend = true;
- if ( folderId == folderElement.getFolderByName(
- BluetoothMapContract.FOLDER_NAME_OUTBOX).getFolderId() ) {
- //Trigger Email App to send the message over network.
- Intent emailIn = new Intent();
- long accountId = mAccount.getAccountId();
- if(V) Log.d(TAG, "sendIntent SEND: " + handle + "accounId: " +accountId);
- emailIn.setAction(BluetoothMapEmailContract.ACTION_SEND_PENDING_MAIL);
- emailIn.putExtra(BluetoothMapEmailContract.EXTRA_ACCOUNT, accountId);
- mContext.sendBroadcast(emailIn);
- }
- getMsgListMsg().put(handle, newMsg);
}
}
+ // Extra check to format email list, it's should not happen
+ if (addressTo.length() == 0 && addressCc.length() == 0 && addressBcc.length() == 0) {
+ if (D) Log.v(TAG, "Parse from recipientList");
+ for (BluetoothMapbMessage.VCard recipient : recipientList) {
+ if (recipient.getEnvLevel() < max_env_level) {
+ String address[] = ((BluetoothMapbMessage.VCard)recipient)
+ .getEmailAddresses();
+ for (String s : address) {
+ addressTo.append(s);
+ addressTo.append(";");
+ }
+ }
+ }
+ }
+ Uri uriInsert = BluetoothMapEmailContract
+ .buildEmailMessageUri(BluetoothMapEmailContract.EMAIL_AUTHORITY);
+ if (D) Log.d(TAG, "pushMessage - uriInsert= " + uriInsert.toString() +
+ ", intoFolder id=" + folderElement.getFolderId());
+ synchronized(getMsgListMsg()) {
+ // Now insert the empty message into folder
+ ContentValues values = new ContentValues();
+ Time timeObj = new Time();
+ timeObj.setToNow();
+ folderId = folderElement.getFolderId();
+ values.put(BluetoothMapEmailContract.ExtEmailMessageColumns.MAILBOX_KEY,
+ folderId);
+ if(((BluetoothMapbMessageExtEmail)msg).getSubject() != null) {
+ values.put(BluetoothMapContract.MessageColumns.SUBJECT,
+ ((BluetoothMapbMessageExtEmail)msg).getSubject());
+ } else {
+ values.put(BluetoothMapContract.MessageColumns.SUBJECT, "");
+ }
+ values.put("syncServerTimeStamp", 0);
+ values.put("timeStamp", timeObj.toMillis(false));
+ values.put("flagLoaded", "1");
+ values.put("flagFavorite", "0");
+ values.put("flagAttachment", "0");
+ if(folderElement.getName().equalsIgnoreCase(BluetoothMapContract
+ .FOLDER_NAME_DRAFT) || folderElement.getName()
+ .equalsIgnoreCase(BluetoothMapEmailContract.FOLDER_NAME_DRAFTS)) {
+ values.put("flags", "1179648");
+ } else
+ values.put("flags", "0");
+ String splitStr[] = emailBaseUri.split("/");
+ for (String str: splitStr)
+ Log.d(TAG,"seg for mBaseUri: "+ str);
+ if (mAccount != null) {
+ values.put("accountKey", mAccount.getAccountId());
+ values.put("displayName", mAccount.getDisplayName());
+ values.put("fromList", mAccount.getEmailAddress());
+ }
+ values.put("mailboxKey", folderId);
+ if (addressTo.length() != 0) {
+ values.put("toList", addressTo.toString().trim());
+ } if (addressCc.length() != 0) {
+ values.put("ccList", addressCc.toString().trim());
+ } if (addressBcc.length() != 0) {
+ values.put("bccList", addressBcc.toString().trim());
+ }
+ if (D) Log.d(TAG, " toList :" + addressTo + "\n ccList :" + addressCc +
+ "\n bccList:" + addressBcc);
+ values.put("flagRead", 0);
+ Uri uriNew = mProviderClient.insert(uriInsert, values);
+ if (D) Log.d(TAG, "pushMessage - uriNew= " + uriNew.toString());
+ handle = Long.parseLong(uriNew.getLastPathSegment());
+ if (V) {
+ Log.v(TAG, " NEW HANDLE " + handle);
+ }
+ if(handle == -1) {
+ Log.v(TAG, " Inavlid Handle ");
+ return -1;
+ }
+ //Insert msgBody in DB Provider BODY TABLE
+ ContentValues valuesBody = new ContentValues();
+ valuesBody.put("messageKey", String.valueOf(handle));
+ valuesBody.put("textContent", msgBody);
+ Uri uriMsgBdyInsert = BluetoothMapEmailContract
+ .buildEmailMessageBodyUri(BluetoothMapEmailContract.EMAIL_AUTHORITY);
+ Log.d(TAG, "pushMessage - uriMsgBdyInsert = " + uriMsgBdyInsert.toString());
+ mProviderClient.insert(uriMsgBdyInsert, valuesBody);
+ // Extract the data for the inserted message, and store in local mirror, to
+ // avoid sending a NewMessage Event.
+ //TODO: We need to add the new 1.1 parameter as well:-) e.g. read
+ Msg newMsg = new Msg(handle, folderId, 1); // TODO: Create define for read-state
+ newMsg.transparent = (transparent == 1) ? true : false;
+ newMsg.localInitiatedSend = true;
+ if ( folderId == folderElement.getFolderByName(
+ BluetoothMapContract.FOLDER_NAME_OUTBOX).getFolderId() ) {
+ //Trigger Email App to send the message over network.
+ Intent emailIn = new Intent();
+ long accountId = mAccount.getAccountId();
+ if(V) Log.d(TAG, "sendIntent SEND: " + handle + "accounId: " +accountId);
+ emailIn.setAction(BluetoothMapEmailContract.ACTION_SEND_PENDING_MAIL);
+ emailIn.putExtra(BluetoothMapEmailContract.EXTRA_ACCOUNT, accountId);
+ mContext.sendBroadcast(emailIn);
+ }
+ getMsgListMsg().put(handle, newMsg);
+ }
}
// If multiple recipients return handle of last
return handle;
diff --git a/packages_apps_bluetooth_ext/src/map/src/BluetoothMapFixes.java b/packages_apps_bluetooth_ext/src/map/src/BluetoothMapFixes.java
index ef166b9..443cfb1 100644
--- a/packages_apps_bluetooth_ext/src/map/src/BluetoothMapFixes.java
+++ b/packages_apps_bluetooth_ext/src/map/src/BluetoothMapFixes.java
@@ -29,16 +29,26 @@
package com.android.bluetooth.map;
-import android.bluetooth.BluetoothMap;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.NotificationChannel;
+import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
-import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.SparseArray;
+import com.android.bluetooth.Utils;
+import com.android.bluetooth.btservice.AdapterService;
+import com.android.bluetooth.btservice.AbstractionLayer;
-import com.android.bluetooth.map.BluetoothMapUtils.TYPE;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
public class BluetoothMapFixes {
@@ -48,6 +58,20 @@
public static final boolean VERBOSE = BluetoothMapService.VERBOSE;
+ private static final int SDP_MAP_MAS_FEATURES_ADV = 0x603ff,
+ SDP_MAP_MAS_VERSION_ADV = 0x0103;
+ // Stores map of BD address to isRebonded for the given BT Session
+ private static HashMap<String,String> mapSdpResponse = new HashMap <String,String>();
+ // Stores map of BD address to MCE version for the given BT Session
+ private static HashMap<String,Integer> remoteVersion = new HashMap <String,Integer>();
+ private static final String MAP_NOTIFICATION_ID = "map_notification",
+ MAP_NOTIFICATION_NAME = "BT_MAP_ADVANCE_SUPPORT";
+ private static final int RECORD_LENGTH = 6,
+ VERSION_LENGTH = 2,
+ MAP_ADV_NOTIFICATION_ID = -1000003,
+ ADDRESS_LENGTH = 3;
+ private static NotificationManager mNotificationManager;
+
/*to trigger MNS OFF to handle MCE that dosen't issue MNS OFF before MAS DISC*/
public static void handleMnsShutdown(SparseArray<BluetoothMapMasInstance>
mMasInstances, int masId) {
@@ -113,4 +137,140 @@
mService.createMasInstances();
}
+ static boolean isRemoteSupportsAdvMap(BluetoothDevice device) {
+ Log.d(TAG, "isRemoteSupportsAdvMap ");
+ try {
+ final String filePath = "/data/misc/bluedroid/mce_peer_entries.conf";
+ File file = new File(filePath);
+ Log.d(TAG, "file length = " + (int)file.length());
+ byte[] fileData = new byte[(int) file.length()];
+ DataInputStream dis = new DataInputStream(new FileInputStream(file));
+ dis.readFully(fileData);
+ dis.close();
+ return readRecord(fileData, device);
+ } catch (IOException io) {
+ Log.e(TAG, "File Read Failed: " + io);
+ }
+ return false;
+ }
+
+ /* Read all records and check if entry for remote device is found
+ * Returns true if 1.4 support is stored for remote else false */
+ static boolean readRecord(byte[] fileData, BluetoothDevice device) {
+ for (int j = 0 ; (j + RECORD_LENGTH) <= fileData.length;) {
+ // Read Version from MCE Entry
+ byte[] versionBytes = Arrays.copyOfRange(fileData, j, j + VERSION_LENGTH);
+ int version = byteArrayToInt(versionBytes);
+ j += VERSION_LENGTH;
+
+ // Read BD ADDRESS from MCE Entry
+ StringBuilder address = new StringBuilder();
+ address.append(String.format("%02X", fileData[j]) + ":"
+ + String.format("%02X", fileData[j+1]) + ":"
+ + String.format("%02X", fileData[j+2]));
+ j += ADDRESS_LENGTH;
+
+ // Read rebonded from MCE Entry
+ char isRebonded = (char)fileData[j++];
+ Log.d(TAG, "version: " + version + ", address = " + address.toString()
+ + ", isRebonded = "+ isRebonded +" Remote Address = "
+ + device.getAddress());
+
+ boolean isMatched = device.getAddress().toLowerCase()
+ .startsWith(address.toString().toLowerCase());
+ mapSdpResponse.put(address.toString(), Character.toString(isRebonded));
+ remoteVersion.put(address.toString(), Integer.valueOf(version));
+ if (isMatched) {
+ return (version >= SDP_MAP_MAS_VERSION_ADV ? true : false);
+ }
+ }
+ return false;
+ }
+
+ /* Convert 2 bytes of data to integer */
+ static int byteArrayToInt(byte[] b)
+ {
+ return b[0] & 0xFF |
+ (b[1] & 0xFF) << 8 ;
+ }
+
+ /*Creates Notification for MAP version upgrade/downgrade */
+ static void createNotification(BluetoothMapService context, boolean isUpgrade) {
+ if (VERBOSE) Log.v(TAG, "Create MAP Notification for Upgrade/Downgrade");
+ // create Notification channel.
+ if (mNotificationManager == null) {
+ mNotificationManager = (NotificationManager)
+ context.getSystemService(Context.NOTIFICATION_SERVICE);
+ NotificationChannel mChannel = new NotificationChannel(MAP_NOTIFICATION_ID,
+ MAP_NOTIFICATION_NAME, NotificationManager.IMPORTANCE_HIGH);
+ mNotificationManager.createNotificationChannel(mChannel);
+ }
+
+ // create notification
+ String title = isUpgrade ? "Message access Advance Feature Supported" :
+ "Remote Message access Feature Downgrade";
+ String contentText = isUpgrade ? "Re-pair for Advance Message access Feature.":
+ "Re-pair for Message access Version Compatibility";
+ Notification notification = new Notification.Builder(context,MAP_NOTIFICATION_ID)
+ .setContentTitle(title)
+ .setContentText(contentText)
+ .setSmallIcon(android.R.drawable.stat_sys_data_bluetooth)
+ .setAutoCancel(true)
+ .build();
+ if (mNotificationManager != null ) {
+ mNotificationManager.notify(MAP_ADV_NOTIFICATION_ID, notification);
+ } else {
+ Log.e(TAG,"mNotificationManager is null");
+ }
+ }
+
+ /* Checks if notification for Version Upgrade is required */
+ static void showNotification(BluetoothMapService service,
+ BluetoothDevice remoteDevice) {
+ if (service == null || remoteDevice == null || Utils.isPtsTestMode()
+ || isMapAdvDisabled()) {
+ Log.d(TAG, "Ignore showNotification , service: " + service + " remoteDevice: "
+ + remoteDevice +" isPtsTestMode :" + Utils.isPtsTestMode()
+ + " isMapAdvDisabled :" + isMapAdvDisabled());
+ return;
+ }
+ boolean hasMap14Support = isRemoteSupportsAdvMap(remoteDevice);
+ /* check if remote devices is rebonded by looking into its entry in hashmap using key
+ * (0,8) i.e. first 3 bytes of bd addr in string format including colon (XX:XX:XX) */
+ String isRebonded = mapSdpResponse.get(
+ remoteDevice.getAddress().substring(0,8));
+ /* fetch MCE version of remote (if present) in hashmap 'remoteVersion' from key
+ * (0,8) i.e. first 3 bytes of bd addr in string format including colon (XX:XX:XX) */
+ Integer remoteMceVersion = remoteVersion.get(
+ remoteDevice.getAddress().substring(0,8));
+ if (hasMap14Support && (isRebonded.equals("N"))) {
+ Log.d(TAG, "Remote Supports MAP 1.4 Notify user");
+ createNotification(service, true);
+ } else if (!hasMap14Support
+ && (remoteMceVersion != null &&
+ remoteMceVersion.intValue() < SDP_MAP_MAS_VERSION_ADV)
+ && (isRebonded != null && isRebonded.equals("N"))) {
+ Log.d(TAG, "Remote MAP profile support downgraded");
+ createNotification(service, false);
+ } else {
+ Log.d(TAG, "Notification Not Required.");
+ if (mNotificationManager != null)
+ mNotificationManager.cancel(MAP_ADV_NOTIFICATION_ID);
+ }
+ }
+
+ public static boolean isMapAdvDisabled(){
+ boolean ismap14Enabled = false;
+ int MAP_0104_SUPPORT = 7;
+ try {
+ AdapterService adapterService = AdapterService.getAdapterService();
+ if (adapterService != null) {
+ ismap14Enabled = adapterService.getProfileInfo(AbstractionLayer.MAP,
+ MAP_0104_SUPPORT);
+ }
+ } catch(Exception e) {
+ Log.w(TAG," isMapadvEnabled : " + e);
+ }
+ return !ismap14Enabled;
+ }
}
diff --git a/packages_apps_bluetooth_ext/src/map/src/BluetoothMapbMessageExtEmail.java b/packages_apps_bluetooth_ext/src/map/src/BluetoothMapbMessageExtEmail.java
index dbf10c8..8cbe2e0 100644
--- a/packages_apps_bluetooth_ext/src/map/src/BluetoothMapbMessageExtEmail.java
+++ b/packages_apps_bluetooth_ext/src/map/src/BluetoothMapbMessageExtEmail.java
@@ -25,6 +25,8 @@
import java.util.Date;
import java.util.Locale;
import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import com.android.bluetooth.map.BluetoothMapSmsPdu.SmsPdu;
@@ -100,6 +102,9 @@
int pos1 = 0;
//PARSE SUBJECT
setSubject(parseSubjectEmail(body));
+ setmRecipientTo(parseEmails(body, "To:"));
+ setmRecipientCc(parseEmails(body, "Cc:"));
+ setmRecipientBCc(parseEmails(body, "Bcc:"));
//Parse Boundary
String boundary = parseBoundaryEmail(body);
if (boundary != null && !boundary.equalsIgnoreCase("")) {
@@ -289,4 +294,37 @@
}
return encodeGeneric(bodyFragments);
}
+
+ private ArrayList<String> parseEmails(String body , String type){
+ ArrayList<String> emailList =new ArrayList<>();
+ try {
+ int pos = body.indexOf(type);
+ if (pos > 0) {
+ int beginVersionPos = pos + type.length();
+ int endVersionPos = body.indexOf("\n", beginVersionPos);
+ String data= body.substring(beginVersionPos, endVersionPos);
+ if (data == null || data.isEmpty()) {
+ return emailList;
+ }
+ Matcher m = Pattern.compile("[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+")
+ .matcher(data);
+ while (m.find()) {
+ String email = m.group();
+ if (email.startsWith(".")) {
+ email= email.substring(1);
+ } if (email.endsWith(".")) {
+ email= email.substring(0,email.length()-1);
+ }
+ if (emailList == null) {
+ emailList=new ArrayList<>();
+ } if(!emailList.contains(email)) {
+ emailList.add(email);
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.w(TAG," parseEmails " + e.toString());
+ }
+ return emailList;
+ }
}
diff --git a/packages_apps_bluetooth_ext/src/pbap/BluetoothPbapFixes.java b/packages_apps_bluetooth_ext/src/pbap/BluetoothPbapFixes.java
index 09d4851..3f16e74 100644
--- a/packages_apps_bluetooth_ext/src/pbap/BluetoothPbapFixes.java
+++ b/packages_apps_bluetooth_ext/src/pbap/BluetoothPbapFixes.java
@@ -111,7 +111,7 @@
private static final int ORDER_BY_ALPHABETICAL = 1;
- static final int MAX_CONNECTED_DEVICES = 2;
+ static final int MAX_CONNECTED_DEVICES = 5;
// Stores map of BD address to isRebonded for the given BT Session
protected static HashMap<String,String> PbapSdpResponse = new HashMap <String,String>();
diff --git a/packages_apps_bluetooth_ext/src/utils/ReflectionUtils.java b/packages_apps_bluetooth_ext/src/utils/ReflectionUtils.java
new file mode 100644
index 0000000..30abe57
--- /dev/null
+++ b/packages_apps_bluetooth_ext/src/utils/ReflectionUtils.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ package com.android.bluetooth;
+
+ import android.util.Log;
+
+ import java.lang.reflect.Method;
+ import java.lang.reflect.Field;
+ import java.lang.reflect.InvocationTargetException;
+ import java.util.ArrayList;
+ import java.util.HashMap;
+
+/* This API is added to access data members or member functions from the class which
+ * is defined in other component and the required memebers may not be available(or merged)
+ * in other component. This API helps avoiding compilation issues. */
+ public class ReflectionUtils {
+
+ private static final String TAG = "BluetoothReflectionUtils";
+
+ private static final HashMap<String, Class> primitiveClsMap =
+ new HashMap<String, Class>();
+
+ static {
+ primitiveClsMap.put("java.lang.Integer", int.class);
+ primitiveClsMap.put("java.lang.Long", long.class);
+ primitiveClsMap.put("java.lang.Character", char.class);
+ primitiveClsMap.put("java.lang.Byte", byte.class);
+ primitiveClsMap.put("java.lang.Float", float.class);
+ primitiveClsMap.put("java.lang.Double", double.class);
+ primitiveClsMap.put("java.lang.Short", short.class);
+ primitiveClsMap.put("java.lang.Boolean", boolean.class);
+ }
+
+ /**********************************************************************************
+ * Function : getField
+ *
+ * Description : fetches mentioned data member from the provided object.
+ * Access is restricted to public data members if package of the
+ * required object class is different from ReflectionUtils package.
+ * If package is same, protected and default can aslo be accessed.
+ * obj - Object in which data member could be present
+ * fieldName - name of the data member in string format
+ *
+ * Returns : data member as 'Field'
+ * null if data member is not found
+ **********************************************************************************/
+ public Field getField(Object obj, String fieldName) {
+ Log.d(TAG, "getField {" + fieldName + "} class: " + obj.getClass().getName());
+ Field field = null;
+ try {
+ // get object class
+ Class cls = obj.getClass();
+ // get required field. NoSuchFieldException is thrown if field is not found
+ field = cls.getDeclaredField(fieldName);
+ } catch(NoSuchFieldException e) {
+ Log.e(TAG, "Field(" + fieldName + ") not found in class:" + obj.getClass().getName()
+ +". Exception : " + e);
+ }
+ return field;
+ }
+
+ /**********************************************************************************
+ * Function : isMethodAvailable
+ *
+ * Description : checks if mentioned method is available in given object's class.
+ * Access is restricted to public member functions only if package
+ * of required object class is different from ReflectionUtils package.
+ * If package is same, protected and default func can also be accessed.
+ * obj - Object in which data member could be present
+ * methodName - name of the member function in string format
+ * args - all method arguments wrapped in Object format in
+ * arraylist
+ * Returns : true if method is present otherwise returns false
+ **********************************************************************************/
+ public boolean isMethodAvailable(Object obj, String methodName, ArrayList<Object> args) {
+ Log.d(TAG, "isMethodAvailable: " + methodName + ", Class: " + obj.getClass().getName());
+ boolean isAvailable = true;
+ Class[] cArgs = null;
+ try {
+ Class cls = obj.getClass();
+ // get parameter types of function call
+ if (args != null && args.size() > 0) {
+ int i =0;
+ cArgs = new Class[args.size()];
+ for (Object objs : args) {
+ if (isWrapperType(objs.getClass().getName())) {
+ cArgs[i++] = primitiveClsMap.get(objs.getClass().getName());
+ } else {
+ cArgs[i++] = objs.getClass();
+ }
+ }
+ }
+ Method m = cls.getDeclaredMethod(methodName, cArgs);
+ } catch (NoSuchMethodException e) {
+ isAvailable = false;
+ Log.e(TAG, "Method not found in class:" + obj.getClass().getName()
+ +". Exception :" + e);
+ }
+ return isAvailable;
+ }
+
+ /**********************************************************************************
+ * Function : invokeMethod
+ *
+ * Description : This is a generic method which calls required method.
+ * Access is restricted to public member functions only if package
+ * of required object class is different from ReflectionUtils package.
+ * If package is same, protected and default func can also be accessed.
+ * obj - Object in which data member could be present
+ * methodName - name of the member function in string format
+ * args - all method arguments wrapped in Object format in
+ * arraylist
+ * Returns : return type of the required method in 'Object' format.
+ * Typecasting should be done to required type.
+ **********************************************************************************/
+ public Object invokeMethod(Object obj, String methodName, ArrayList<Object> args) {
+ Log.d(TAG, "invokeMethod: " + methodName + ", From: " + obj.getClass().getName());
+ Object returnValue = null;
+ Class[] cArgs = null;
+ try {
+ // Obtain object class to call required method
+ Class cls = obj.getClass();
+
+ // create function param signeture
+ if (args != null && args.size() > 0) {
+ int i =0;
+ cArgs = new Class[args.size()];
+ for (Object objs : args) {
+ if (isWrapperType(objs.getClass().getName())) {
+ cArgs[i++] = primitiveClsMap.get(objs.getClass().getName());
+ } else {
+ cArgs[i++] = objs.getClass();
+
+ }
+ }
+ }
+
+ // Obtain required method.
+ // throws exeption NoSuchMethodException if method is not found
+ Method m = cls.getDeclaredMethod(methodName, cArgs);
+
+ // Invoke required method call
+ if (args != null)
+ returnValue = m.invoke(obj, args.toArray());
+ else
+ returnValue = m.invoke(obj);
+ } catch (NoSuchMethodException|IllegalAccessException|InvocationTargetException e) {
+ Log.e(TAG, "Exception in invokeMethod: " + e);
+ }
+ return returnValue;
+ }
+
+ // Checks if a class belongs to Wrapper class of primitive data types
+ public boolean isWrapperType(String classType) {
+ return primitiveClsMap.containsKey(classType);
+ }
+ }
+
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 9ae7678..592038c 100644
--- a/system_bt_ext/bta/include/bta_ag_twsp_dev.h
+++ b/system_bt_ext/bta/include/bta_ag_twsp_dev.h
@@ -91,7 +91,7 @@
} tTWSPLUS_DEVICE;
void twsp_handle_vs_at_events(tBTA_AG_SCB* p_scb, uint16_t cmd, int16_t int_arg);
-void update_twsp_device(int eb_idx, tBTA_AG_SCB* p_scb);
+void update_twsp_device(tBTA_AG_SCB* p_scb);
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();
@@ -101,5 +101,6 @@
bool twsp_get_left_eb_addr(RawAddress& eb_addr);
uint8_t get_twsp_role(tBTA_AG_SCB *p_scb);
tBTA_AG_SCB* twsp_get_best_mic_scb ();
+int twsp_get_idx_by_scb(tBTA_AG_SCB* p_scb);
#endif//__BTA_AG_TWSPLUS_DEV_H_
diff --git a/system_bt_ext/bta/include/bta_tws_plus_api.h b/system_bt_ext/bta/include/bta_tws_plus_api.h
index c0c8507..225303b 100644
--- a/system_bt_ext/bta/include/bta_tws_plus_api.h
+++ b/system_bt_ext/bta/include/bta_tws_plus_api.h
@@ -89,7 +89,7 @@
tBTA_TWS_PLUS_STATUS status;
RawAddress bd_addr;
RawAddress peer_eb_addr;
- LINK_KEY key; /* Link key associated with peer device. */
+ LinkKey key; /* Link key associated with peer device. */
uint8_t reason;
} tBTA_TWS_PLUS_LK_DERIVED;
@@ -162,7 +162,7 @@
extern tBTA_TWS_PLUS_STATUS BTA_TwsPlusSdpSearch(RawAddress bd_addr);
extern tBTA_TWS_PLUS_STATUS BTA_TwsPlusDeriveLinkKey(RawAddress eb_addr,
- RawAddress peer_eb_addr, LINK_KEY key, uint8_t reason);
+ RawAddress peer_eb_addr, LinkKey key, uint8_t reason);
extern tBTA_TWS_PLUS_STATUS BTA_TwsPlusUpdatePeerEbAddr(RawAddress eb_addr,
RawAddress peer_eb_addr);
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 11499ea..125e889 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
@@ -38,7 +38,11 @@
#include "internal_include/bt_trace.h"
#include "bta_ag_int.h"
+
#if (TWS_AG_ENABLED == TRUE)
+//forward declarations
+void select_microphone_path(tBTA_AG_SCB *best_scb);
+
tTWSPLUS_DEVICE twsp_devices[MAX_TWSPLUS_DEVICES];
@@ -48,38 +52,75 @@
return g_latest_selected_eb_role;
}
+tBTA_AG_SCB* get_twsp_with_role(uint8_t role) {
+ int i;
+ for (i=0; i<MAX_TWSPLUS_DEVICES; i++) {
+ if (twsp_devices[i].p_scb != NULL &&
+ twsp_devices[i].role == role) {
+ return twsp_devices[i].p_scb;
+ }
+ }
+ return NULL;
+}
+
void reset_twsp_device(int eb_idx) {
if (eb_idx < PRIMARY_EB_IDX || eb_idx > SECONDARY_EB_IDX) {
APPL_TRACE_WARNING("%s: Invalid eb_idx: %d\n", __func__, eb_idx);
return;
}
- 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_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;
+ if (get_lat_selected_mic_eb_role() == twsp_devices[eb_idx].role) {
+ //Trigger Microphone Switch
+ uint8_t other_twsp_role =
+ (twsp_devices[eb_idx].role == TWSPLUS_EB_ROLE_LEFT) ?
+ TWSPLUS_EB_ROLE_RIGHT : TWSPLUS_EB_ROLE_LEFT;
+ tBTA_AG_SCB *peer_scb = get_twsp_with_role(other_twsp_role);
+ if (peer_scb != NULL) {
+ select_microphone_path(peer_scb);
+ } else {
+ APPL_TRACE_WARNING("%s: peer_scb is NULL, No mic switch", __func__);
+ }
+ }
+
+ 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_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(int eb_idx, tBTA_AG_SCB* p_scb) {
- if (eb_idx < PRIMARY_EB_IDX || eb_idx > SECONDARY_EB_IDX) {
- APPL_TRACE_WARNING("%s: Invalid eb_idx: %d\n", __func__, eb_idx);
- return;
+void update_twsp_device(tBTA_AG_SCB* p_scb) {
+ for (int i=0; i<MAX_TWSPLUS_DEVICES; i++) {
+ 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_OFF;
+
+ int other_idx = (i == PRIMARY_EB_IDX) ? SECONDARY_EB_IDX : PRIMARY_EB_IDX;
+ if (twsp_devices[other_idx].p_scb != NULL &&
+ twsp_devices[other_idx].role == TWSPLUS_EB_ROLE_LEFT) {
+ twsp_devices[i].role = TWSPLUS_EB_ROLE_RIGHT;
+ } else {
+ twsp_devices[i].role = TWSPLUS_EB_ROLE_LEFT;
+ }
+
+ APPL_TRACE_WARNING("%s: idx: %d, role: %d", __func__, i, twsp_devices[i].role);
+ twsp_devices[i].mic_path_delay = TWSPLUS_INVALID_MICPATH_DELAY;
+ twsp_devices[i].mic_quality = TWSPLUS_MIN_MIC_QUALITY;
+ twsp_devices[i].qdsp_nr = TWSPLUS_INVALID_QDSP_VALUE;
+ twsp_devices[i].qdsp_ec = TWSPLUS_INVALID_QDSP_VALUE;
+ twsp_devices[i].ring_sent = false;
+ return;
+ }
}
- APPL_TRACE_WARNING("%s: idx: %d, p_scb: %x", __func__, eb_idx, p_scb);
- twsp_devices[eb_idx].p_scb = p_scb;
- twsp_devices[eb_idx].battery_charge = TWSPLUS_MIN_BATTERY_CHARGE;
- twsp_devices[eb_idx].state = TWSPLUS_EB_STATE_OFF;
- twsp_devices[eb_idx].role = TWSPLUS_EB_ROLE_LEFT;
- 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;
+
+ APPL_TRACE_WARNING("%s: Invalid p_scb %d\n", __func__);
+ return;
}
void init_twsp_devices() {
diff --git a/system_bt_ext/bta/tws_plus/ag/bta_ag_twsp_sco.cc b/system_bt_ext/bta/tws_plus/ag/bta_ag_twsp_sco.cc
index 58203fe..5f6af9b 100644
--- a/system_bt_ext/bta/tws_plus/ag/bta_ag_twsp_sco.cc
+++ b/system_bt_ext/bta/tws_plus/ag/bta_ag_twsp_sco.cc
@@ -276,6 +276,14 @@
bta_ag_create_sco(p_scb, false);
p_sco->state = BTA_AG_SCO_LISTEN_ST;
break;
+ case BTA_AG_SCO_SHUTDOWN_E:
+ /* remove listening connection */
+ bta_ag_remove_sco(p_scb, false);
+
+ if (p_scb == p_sco->p_curr_scb) p_sco->p_curr_scb = NULL;
+
+ p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
+ break;
default:
APPL_TRACE_WARNING("%s: BTA_AG_SCO_CODEC_ST: Ignoring event %d",
__func__, event);
diff --git a/system_bt_ext/bta/tws_plus/bta_tws_plus_act.cc b/system_bt_ext/bta/tws_plus/bta_tws_plus_act.cc
index f56ffd2..049cf15 100644
--- a/system_bt_ext/bta/tws_plus/bta_tws_plus_act.cc
+++ b/system_bt_ext/bta/tws_plus/bta_tws_plus_act.cc
@@ -319,17 +319,19 @@
******************************************************************************/
void bta_tws_plus_derive_linkkey(tBTA_TWS_PLUS_MSG* p_data) {
tBTA_TWS_PLUS_STATUS status = BTA_TWS_PLUS_FAILURE;
- int i = 0;
tBTA_TWS_PLUS result;
memset(&result, 0, sizeof(result));
APPL_TRACE_DEBUG("%s in, sdp_active:%d", __func__, bta_tws_plus_cb.sdp_active);
- if(SMP_DeriveBrEdrLinkKey(p_data->derive_lk.peer_eb_addr,
- ( uint8_t *) p_data->derive_lk.key,(uint8_t *) result.lk_derived.key)) {
- APPL_TRACE_DEBUG("%s link key for 2nd device derived", __func__);
- for(i = 0; i< 16 ; i++)
- APPL_TRACE_DEBUG("%s result.key [%d] is %d", __func__, i, result.lk_derived.key[i]);
- status = BTA_TWS_PLUS_SUCCESS;
- }
+
+ int i = 0;
+ result.lk_derived.key = SMP_DeriveBrEdrLinkKey(p_data->derive_lk.peer_eb_addr,
+ p_data->derive_lk.key);
+
+ APPL_TRACE_DEBUG("%s link key for 2nd device derived", __func__);
+ for(i = 0; i< 16 ; i++)
+ APPL_TRACE_DEBUG("%s result.key [%d] is %d", __func__, i, result.lk_derived.key[i]);
+ status = BTA_TWS_PLUS_SUCCESS;
+
if (bta_tws_plus_cb.p_dm_cback) {
result.lk_derived.peer_eb_addr = p_data->derive_lk.peer_eb_addr;
result.lk_derived.bd_addr = p_data->derive_lk.bd_addr;
diff --git a/system_bt_ext/bta/tws_plus/bta_tws_plus_api.cc b/system_bt_ext/bta/tws_plus/bta_tws_plus_api.cc
index b81c3e4..420b7fb 100644
--- a/system_bt_ext/bta/tws_plus/bta_tws_plus_api.cc
+++ b/system_bt_ext/bta/tws_plus/bta_tws_plus_api.cc
@@ -179,7 +179,7 @@
*
******************************************************************************/
tBTA_TWS_PLUS_STATUS BTA_TwsPlusDeriveLinkKey(RawAddress eb_addr,
- RawAddress peer_eb_addr, LINK_KEY key, uint8_t reason) {
+ RawAddress peer_eb_addr, LinkKey key, uint8_t reason) {
tBTA_TWS_PLUS_API_DERIVE_LINKKEY* p_msg =
(tBTA_TWS_PLUS_API_DERIVE_LINKKEY*)osi_malloc(sizeof(tBTA_TWS_PLUS_API_DERIVE_LINKKEY));
@@ -188,7 +188,7 @@
p_msg->hdr.event = BTA_TWS_PLUS_API_DERIVE_LINK_KEY_EVT;
p_msg->peer_eb_addr = peer_eb_addr;
p_msg->bd_addr = eb_addr;
- memcpy(p_msg->key, key, sizeof(LINK_KEY));
+ p_msg->key = key;
p_msg->reason = reason;
bta_sys_sendmsg(p_msg);
diff --git a/system_bt_ext/bta/tws_plus/bta_tws_plus_int.h b/system_bt_ext/bta/tws_plus/bta_tws_plus_int.h
index 7b8f533..1c317f2 100644
--- a/system_bt_ext/bta/tws_plus/bta_tws_plus_int.h
+++ b/system_bt_ext/bta/tws_plus/bta_tws_plus_int.h
@@ -103,7 +103,7 @@
BT_HDR hdr;
RawAddress bd_addr;
RawAddress peer_eb_addr; /* peer eb addr for which lk has to derived */
- LINK_KEY key; /* Link key associated with peer device. */
+ LinkKey key; /* Link key associated with peer device. */
uint8_t reason;
} tBTA_TWS_PLUS_API_DERIVE_LINKKEY;
diff --git a/system_bt_ext/btif/Android.bp b/system_bt_ext/btif/Android.bp
index 6047291..6089d0d 100644
--- a/system_bt_ext/btif/Android.bp
+++ b/system_bt_ext/btif/Android.bp
@@ -23,7 +23,6 @@
],
srcs: [
"src/btif_l2cap.cc",
- "src/btif_mcap.cc",
"src/btif_rfcomm.cc",
"src/btif_vendor.cc",
"src/btif_vendor_socket.cc",
@@ -33,6 +32,7 @@
"src/btif_tws_plus.cc",
"src/btif_ba.cc",
"src/btif_twsp_hf.cc",
+ "src/btif_iot_config.cc",
],
shared_libs: [
"libcutils",
diff --git a/system_bt_ext/btif/include/btif_tws_plus.h b/system_bt_ext/btif/include/btif_tws_plus.h
index c1b0bb6..9075e03 100644
--- a/system_bt_ext/btif/include/btif_tws_plus.h
+++ b/system_bt_ext/btif/include/btif_tws_plus.h
@@ -81,7 +81,7 @@
bool btif_is_tws_plus_device(const RawAddress *remote_bd_addr);
bool btif_tws_plus_derive_link_key ( RawAddress eb_addr, RawAddress peer_eb_addr,
- LINK_KEY src_key, tLK_DERIVATION_REASON reason);
+ LinkKey src_key, tLK_DERIVATION_REASON reason);
bool btif_tws_plus_process_eir(tBTA_DM_SEARCH *p_search_data,
RawAddress *peer_eb_bd_addr);
diff --git a/system_bt_ext/btif/src/btif_gatt_qual.cc b/system_bt_ext/btif/src/btif_gatt_qual.cc
index 217bfd8..8ddda44 100644
--- a/system_bt_ext/btif/src/btif_gatt_qual.cc
+++ b/system_bt_ext/btif/src/btif_gatt_qual.cc
@@ -104,10 +104,12 @@
return Ret;
}
- tGATT_STATUS Gatt_Discover (uint16_t conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_PARAM *p_param )
+ tGATT_STATUS Gatt_Discover(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
+ uint16_t start_handle, uint16_t end_handle,
+ const Uuid& uuid)
{
tGATT_STATUS Ret = 0;
- Ret = GATTC_Discover(conn_id, disc_type, p_param);
+ Ret = GATTC_Discover(conn_id, disc_type, start_handle, end_handle, uuid);
printf("%s::Ret=%d, conn_id=%d, disc_type=%d \n", __FUNCTION__, Ret, conn_id, disc_type);
return Ret;
}
diff --git a/system_bt_ext/btif/src/btif_iot_config.cc b/system_bt_ext/btif/src/btif_iot_config.cc
new file mode 100644
index 0000000..a4a0214
--- /dev/null
+++ b/system_bt_ext/btif/src/btif_iot_config.cc
@@ -0,0 +1,163 @@
+/******************************************************************************
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#if (BT_IOT_LOGGING_ENABLED == TRUE)
+
+#include "device_iot_config.h"
+#include "bta_api.h"
+#include "bt_target.h"
+#include "btif_storage.h"
+
+/*******************************************************************************
+ * Constants & Macros
+ ******************************************************************************/
+#define COD_UNCLASSIFIED ((0x1F) << 8)
+
+
+/*******************************************************************************
+*
+* Function btif_iot_save_pair_type
+*
+* Description Store remote pair type to iot conf file
+*
+* Returns void
+*
+*******************************************************************************/
+static void btif_iot_save_pair_type(const RawAddress& bdaddr, bool is_ble, bool is_ssp) {
+ if (is_ssp) {
+ if (!is_ble)
+ device_iot_config_addr_set_int(bdaddr,
+ IOT_CONF_KEY_PAIRTYPE, IOT_CONF_VAL_PAIR_TYPE_SSP);
+ else
+ device_iot_config_addr_set_int(bdaddr,
+ IOT_CONF_KEY_LE_PAIRTYPE, IOT_CONF_VAL_LE_PAIRTYPE_SECURE);
+ } else {
+ if (!is_ble)
+ device_iot_config_addr_set_int(bdaddr,
+ IOT_CONF_KEY_PAIRTYPE, IOT_CONF_VAL_PAIR_TYPE_LEGACY);
+ else
+ device_iot_config_addr_set_int(bdaddr,
+ IOT_CONF_KEY_LE_PAIRTYPE, IOT_CONF_VAL_LE_PAIRTYPE_LEGACY);
+ }
+}
+
+/*******************************************************************************
+*
+* Function btif_iot_update_remote_info
+*
+* Description Store remote dev info to iot conf file
+*
+* Returns void
+*
+*******************************************************************************/
+void btif_iot_update_remote_info(tBTA_DM_AUTH_CMPL* p_auth_cmpl, bool is_ble, bool is_ssp) {
+ int name_length = 0;
+ char value[1024];
+ BD_NAME bd_name;
+ int num_properties = 0;
+ bt_property_t properties[2];
+ uint32_t cod = 0;
+ uint8_t lmp_ver = 0;
+ uint16_t lmp_subver = 0;
+ uint16_t mfct_set = 0;
+ tBTM_STATUS btm_status;
+
+ //save remote name to iot conf file
+ if (strlen((const char *)p_auth_cmpl->bd_name))
+ {
+ name_length = strlen((char *)p_auth_cmpl->bd_name) > BTM_MAX_LOC_BD_NAME_LEN ?
+ BTM_MAX_LOC_BD_NAME_LEN : strlen((char *)p_auth_cmpl->bd_name) + 1;
+ strlcpy(value, (char*)p_auth_cmpl->bd_name, name_length);
+ device_iot_config_addr_set_str(p_auth_cmpl->bd_addr,
+ IOT_CONF_KEY_REMOTE_NAME, value);
+ } else {
+ if (BTM_GetRemoteDeviceName(p_auth_cmpl->bd_addr, bd_name))
+ {
+ device_iot_config_addr_set_str(p_auth_cmpl->bd_addr,
+ IOT_CONF_KEY_REMOTE_NAME, (char *)bd_name);
+ }
+ }
+
+ //save remote dev class to iot conf file
+ //Try to retrieve cod from storage
+ BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
+ BT_PROPERTY_CLASS_OF_DEVICE, sizeof(cod), &cod);
+ if (btif_storage_get_remote_device_property(&p_auth_cmpl->bd_addr, &properties[num_properties])
+ == BT_STATUS_SUCCESS)
+ BTIF_TRACE_DEBUG("%s cod retrieved from storage is 0x%06x", __func__, cod);
+ if (cod == 0) {
+ BTIF_TRACE_DEBUG("%s cod is 0, set as unclassified", __func__);
+ cod = COD_UNCLASSIFIED;
+ }
+ device_iot_config_addr_set_int(p_auth_cmpl->bd_addr,
+ IOT_CONF_KEY_DEVCLASS, (int)cod);
+ num_properties++;
+
+ //save remote dev type to iot conf file
+ bt_device_type_t dev_type;
+ uint8_t remote_dev_type;
+ BTIF_STORAGE_FILL_PROPERTY(&properties[num_properties],
+ BT_PROPERTY_TYPE_OF_DEVICE, sizeof(uint8_t), &remote_dev_type);
+ if (btif_storage_get_remote_device_property(&p_auth_cmpl->bd_addr, &properties[num_properties])
+ == BT_STATUS_SUCCESS) {
+ BTIF_TRACE_DEBUG("%s retrieve dev type from storage", __func__);
+ dev_type = (bt_device_type_t)(remote_dev_type | p_auth_cmpl->dev_type);
+ } else {
+ dev_type = (bt_device_type_t)(p_auth_cmpl->dev_type);
+ }
+ device_iot_config_addr_set_int(p_auth_cmpl->bd_addr,
+ IOT_CONF_KEY_DEVTYPE, (int)dev_type);
+
+ //save remote addr type to iot conf file
+ device_iot_config_addr_set_int(p_auth_cmpl->bd_addr,
+ IOT_CONF_KEY_ADDRTYPE, (int)p_auth_cmpl->addr_type);
+
+ //save remote versions to iot conf file
+ btm_status = BTM_ReadRemoteVersion(p_auth_cmpl->bd_addr, &lmp_ver,
+ &mfct_set, &lmp_subver);
+
+ if (btm_status == BTM_SUCCESS)
+ {
+ device_iot_config_addr_set_int(p_auth_cmpl->bd_addr,
+ IOT_CONF_KEY_MANUFACTURER, mfct_set);
+ device_iot_config_addr_set_int(p_auth_cmpl->bd_addr,
+ IOT_CONF_KEY_LMPVER, lmp_ver);
+ device_iot_config_addr_set_int(p_auth_cmpl->bd_addr,
+ IOT_CONF_KEY_LMPSUBVER, lmp_subver);
+ }
+
+ //save remote pair type to iot conf file
+ btif_iot_save_pair_type(p_auth_cmpl->bd_addr, is_ble, is_ssp);
+
+ device_iot_config_flush();
+}
+
+#endif
diff --git a/system_bt_ext/btif/src/btif_mcap.cc b/system_bt_ext/btif/src/btif_mcap.cc
deleted file mode 100644
index 2a37b35..0000000
--- a/system_bt_ext/btif/src/btif_mcap.cc
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- *Copyright (c) 2015, The Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the followin conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the followin disclaimer.
- * * Redistributions in binary form must reproduce the above copyriht
- * notice, this list of conditions and the followin disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of The Linux Foundation nor
- * the names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <hardware/bluetooth.h>
-
-
-#define LOG_NDDEBUG 0
-#define LOG_TAG "bluedroid"
-
-#include "btif_api.h"
-#include "bt_utils.h"
-#include "bt_testapp.h"
-#include "btm_api.h"
-#include "btu.h"
-#include "btm_api.h"
-#include "mca_api.h"
-
-#ifdef TEST_APP_INTERFACE
-
-static void McaInit(void)
-{
- MCA_Init();
-}
-
-static tMCA_HANDLE McaRegister(tMCA_REG *p_reg, tMCA_CTRL_CBACK *p_cback)
-{
- tMCA_HANDLE Ret = 0;
- BTM_SetConnectability (1, 0, 0);
- Ret = MCA_Register(p_reg, p_cback);
- ALOGI("McaRegister");
- return Ret;
-}
-
-static void Mca_Deregister(tMCA_HANDLE handle)
-{
- MCA_Deregister(handle);
- ALOGI("McaRegister");
-}
-
-static tMCA_RESULT Mca_CreateDep(tMCA_HANDLE handle, tMCA_DEP *p_dep, tMCA_CS *p_cs)
-{
- tMCA_RESULT Ret = 0;
- ALOGI("Mca_CreateDep Enter");
- Ret = MCA_CreateDep(handle, p_dep, p_cs);
- ALOGI("Mca_CreateDep Exit");
- return Ret;
-}
-
-static tMCA_RESULT Mca_DeleteDep(tMCA_HANDLE handle, tMCA_DEP dep)
-{
- tMCA_RESULT Ret = 0;
- Ret = MCA_DeleteDep(handle, dep);
- ALOGI("MCA_DeleteDep Exit");
- return Ret;
-}
-
-
-static tMCA_RESULT Mca_ConnectReq(tMCA_HANDLE handle, RawAddress bd_addr, uint16_t ctrl_psm, uint16_t sec_mask)
-{
- tMCA_RESULT Ret = 0;
- Ret = MCA_ConnectReq(handle, bd_addr, ctrl_psm, sec_mask);
- ALOGI("MCA_ConnectReq");
- return Ret;
-}
-
-static tMCA_RESULT Mca_DisconnectReq(tMCA_CL mcl)
-{
- tMCA_RESULT Ret = 0;
- Ret = MCA_DisconnectReq(mcl);
- ALOGI("Mca_DisconnectReq");
- return Ret;
-}
-
-
-static tMCA_RESULT Mca_CreateMdl(tMCA_CL mcl, tMCA_DEP dep, uint16_t data_psm,
- uint16_t mdl_id, uint8_t peer_dep_id,
- uint8_t cfg, const tMCA_CHNL_CFG *p_chnl_cfg)
-{
- tMCA_RESULT Ret = 0;
- Ret = MCA_CreateMdl(mcl, dep, data_psm, mdl_id, peer_dep_id, cfg, p_chnl_cfg);
- ALOGI("MCA_CreateMdl");
- return Ret;
-}
-
-
-static tMCA_RESULT Mca_CreateMdlRsp(tMCA_CL mcl, tMCA_DEP dep, uint16_t mdl_id, uint8_t cfg, uint8_t rsp_code, const tMCA_CHNL_CFG *p_chnl_cfg)
-{
- tMCA_RESULT Ret = 0;
- Ret = MCA_CreateMdlRsp(mcl, dep, mdl_id, cfg, rsp_code, p_chnl_cfg);
- ALOGI("Mca_CreateMdlRsp");
- return Ret;
-}
-
-
-static tMCA_RESULT Mca_CloseReq(tMCA_DL mdl)
-{
- tMCA_RESULT Ret = 0;
- Ret = MCA_CloseReq(mdl);
- ALOGI("Mca_CloseReq");
- return Ret;
-}
-
-static tMCA_RESULT Mca_ReconnectMdl(tMCA_CL mcl, tMCA_DEP dep, uint16_t data_psm, uint16_t mdl_id, const tMCA_CHNL_CFG *p_chnl_cfg)
-{
- tMCA_RESULT Ret = 0;
- Ret = MCA_ReconnectMdl(mcl, dep, data_psm, mdl_id, p_chnl_cfg);
- ALOGI("Mca_ReconnectMdl");
- return Ret;
-}
-
-static tMCA_RESULT Mca_ReconnectMdlRsp(tMCA_CL mcl, tMCA_DEP dep, uint16_t mdl_id, uint8_t rsp_code, const tMCA_CHNL_CFG *p_chnl_cfg)
-{
- tMCA_RESULT Ret = 0;
- Ret = MCA_ReconnectMdlRsp(mcl, dep, mdl_id, rsp_code, p_chnl_cfg);
- ALOGI("Mca_ReconnectMdl");
- return Ret;
-}
-
-static tMCA_RESULT Mca_DataChnlCfg(tMCA_CL mcl, const tMCA_CHNL_CFG *p_chnl_cfg)
-{
- tMCA_RESULT Ret = 0;
- Ret = MCA_DataChnlCfg(mcl, p_chnl_cfg);
- ALOGI("Mca_DataChnlCfg");
- return Ret;
-}
-
-static tMCA_RESULT Mca_Abort(tMCA_CL mcl)
-{
- tMCA_RESULT Ret = 0;
- Ret = MCA_Abort(mcl);
- ALOGI("MCA_Abort");
- return Ret;
-}
-
-
-static tMCA_RESULT Mca_Delete(tMCA_CL mcl, uint16_t mdl_id)
-{
- tMCA_RESULT Ret = 0;
- Ret = MCA_Delete(mcl, mdl_id);
- ALOGI("Mca_Delete");
- return Ret;
-}
-
-static tMCA_RESULT Mca_WriteReq(tMCA_DL mdl, BT_HDR *p_pkt)
-{
- tMCA_RESULT Ret = 0;
- Ret = MCA_WriteReq(mdl, p_pkt);
- ALOGI("Mca_Delete");
- return Ret;
-}
-
-static uint16_t Mca_GetL2CapChannel (tMCA_DL mdl)
-{
- uint16_t Ret = 0;
- Ret = MCA_GetL2CapChannel(mdl);
- ALOGI("Mca_GetL2CapChannel");
- return Ret;
-}
-
-static const btmcap_interface_t btmcaInterface = {
- sizeof(btmcap_interface_t),
- McaInit,
- McaRegister,
- Mca_Deregister,
- Mca_CreateDep,
- Mca_DeleteDep,
- Mca_ConnectReq,
- Mca_DisconnectReq,
- Mca_CreateMdl,
- Mca_CreateMdlRsp,
- Mca_CloseReq,
- Mca_ReconnectMdl,
- Mca_ReconnectMdlRsp,
- Mca_DataChnlCfg,
- Mca_Abort,
- Mca_Delete,
- Mca_WriteReq,
- Mca_GetL2CapChannel
-};
-
-
-const btmcap_interface_t *btif_mcap_get_interface(void)
-{
- //BTIF_TRACE_EVENT1("%s", __FUNCTION__);
- //printf("\n%s\n", __FUNCTION__);
- return &btmcaInterface;
-}
-
-
-#endif
diff --git a/system_bt_ext/btif/src/btif_smp.cc b/system_bt_ext/btif/src/btif_smp.cc
index f632d86..edb0366 100644
--- a/system_bt_ext/btif/src/btif_smp.cc
+++ b/system_bt_ext/btif/src/btif_smp.cc
@@ -40,6 +40,11 @@
#include "btif_api.h"
#include "bt_utils.h"
#include "smp_api.h"
+#include "stack/crypto_toolbox/crypto_toolbox.h"
+
+using crypto_toolbox::aes_128;
+
+
#ifdef TEST_APP_INTERFACE
#include <bt_testapp.h>
@@ -84,14 +89,12 @@
printf("%s:: executed \n", __FUNCTION__);
}
-static bool Encrypt(uint8_t *key, uint8_t key_len,
- uint8_t *plain_text, uint8_t pt_len,
- tSMP_ENC *p_out)
+static Octet16 Encrypt(Octet16 key, Octet16 message)
{
- bool Ret = 0;
- Ret = SMP_Encrypt(key, key_len, plain_text, pt_len, p_out);
- printf("%s:: Ret=%d\n", __FUNCTION__, Ret);
- return Ret;
+ Octet16 output;
+
+ output= aes_128(key, message);
+ return output;
}
static const btsmp_interface_t btsmpInterface = {
diff --git a/system_bt_ext/btif/src/btif_tws_plus.cc b/system_bt_ext/btif/src/btif_tws_plus.cc
index 320d6e4..b030604 100644
--- a/system_bt_ext/btif/src/btif_tws_plus.cc
+++ b/system_bt_ext/btif/src/btif_tws_plus.cc
@@ -82,10 +82,12 @@
bt_status_t btif_tws_plus_replace_earbud ( RawAddress *addr,
RawAddress* peer_bd_addr) {
bt_status_t status = BT_STATUS_FAIL;
- LINK_KEY link_key;
- size_t size = sizeof(link_key);
+
+ LinkKey link_key;
+ size_t size = OCTET16_LEN;
+ uint8_t *key = &link_key[0];
if (btif_config_get_bin(addr->ToString().c_str(), "LinkKey",
- link_key, &size)) {
+ key, &size)) {
if(btif_tws_plus_derive_link_key( *addr, *peer_bd_addr, link_key,
LK_DERIVATION_REASON_REPLACE_EB)) {
status = BT_STATUS_SUCCESS;
@@ -323,7 +325,7 @@
}
bool btif_tws_plus_derive_link_key ( RawAddress eb_addr, RawAddress peer_eb_addr,
- LINK_KEY src_key, tLK_DERIVATION_REASON reason) {
+ LinkKey src_key, tLK_DERIVATION_REASON reason) {
BTIF_TRACE_DEBUG("%s() Derive link for Bd addr %s ", __func__,
peer_eb_addr.ToString().c_str());
BTA_TwsPlusDeriveLinkKey( eb_addr, peer_eb_addr, src_key, reason);
@@ -332,8 +334,9 @@
static void btif_tws_plus_upstreams_evt(uint16_t event, char* p_param) {
tBTA_TWS_PLUS* p_data = (tBTA_TWS_PLUS*)p_param;
- LINK_KEY link_key;
- size_t size = sizeof(link_key);
+ LinkKey link_key;
+ uint8_t *key = &link_key[0];
+ size_t size = OCTET16_LEN;
BTIF_TRACE_EVENT("%s: event = %d", __func__, event);
switch (event) {
@@ -347,7 +350,7 @@
btif_tws_plus_set_peer_eb_addr(&p_data->sdp_search_comp.eb_addr,
&p_data->sdp_search_comp.peer_eb_addr);
if (btif_config_get_bin(p_data->sdp_search_comp.eb_addr.ToString().c_str(),
- "LinkKey", link_key, &size)) {
+ "LinkKey", key, &size)) {
btif_tws_plus_derive_link_key(p_data->sdp_search_comp.eb_addr,
p_data->sdp_search_comp.peer_eb_addr,
link_key, LK_DERIVATION_REASON_PAIR);
@@ -466,6 +469,7 @@
if (twsplus_enabled == true) {
if (b_enable) {
BTA_TwsPlusEnable(btif_tws_plus_callback);
+ btif_tws_plus_load_tws_devices();
} else {
BTA_TwsPlusDisable();
}
diff --git a/system_bt_ext/btif/src/btif_vendor.cc b/system_bt_ext/btif/src/btif_vendor.cc
index 446c812..9d1f7f1 100644
--- a/system_bt_ext/btif/src/btif_vendor.cc
+++ b/system_bt_ext/btif/src/btif_vendor.cc
@@ -78,6 +78,7 @@
#include "profile_config.h"
#include "btif_tws_plus.h"
#include "btif_api.h"
+#include "device/include/controller.h"
#if TEST_APP_INTERFACE == TRUE
#include <bt_testapp.h>
@@ -121,7 +122,6 @@
#if TEST_APP_INTERFACE == TRUE
extern const btl2cap_interface_t *btif_l2cap_get_interface(void);
extern const btrfcomm_interface_t *btif_rfcomm_get_interface(void);
-extern const btmcap_interface_t *btif_mcap_get_interface(void);
extern const btgatt_test_interface_t *btif_gatt_test_get_interface(void);
extern const btsmp_interface_t *btif_smp_get_interface(void);
extern const btgap_interface_t *btif_gap_get_interface(void);
@@ -146,7 +146,6 @@
broadcast_cb_timer = alarm_new("btif_vnd.cb_timer");
LOG_INFO(LOG_TAG,"init");
LOG_INFO(LOG_TAG,"init done");
- btif_enable_service(BTA_TWS_PLUS_SERVICE_ID);
return BT_STATUS_SUCCESS;
}
@@ -182,6 +181,27 @@
broadcast_cb_data.glitch_count);
}
+void btif_vendor_update_add_on_features() {
+ uint8_t add_on_features_len = 0;
+ bt_vendor_property_t vnd_prop;
+ char buf[8];
+ vnd_prop.len = 0;
+ const controller_t* controller = controller_get_interface();
+ if(controller) {
+ const bt_device_features_t* dev_features = controller->get_add_on_features(
+ &add_on_features_len);
+
+ vnd_prop.type = BT_VENDOR_PROPERTY_SOC_ADD_ON_FEATURES;
+ vnd_prop.val = (void*)buf;
+ if(dev_features && add_on_features_len > 0) {
+ vnd_prop.len = add_on_features_len;
+ memcpy(vnd_prop.val, dev_features, add_on_features_len);
+ }
+ HAL_CBACK(bt_vendor_callbacks, adapter_vendor_prop_cb,
+ BT_STATUS_SUCCESS, 1, &vnd_prop);
+ }
+}
+
void btif_broadcast_timer_cb(UNUSED_ATTR void *data) {
btif_transfer_context(btif_vendor_send_iot_info_cb, 1, NULL, 0, NULL);
}
@@ -290,6 +310,13 @@
NULL, 0, NULL);
}
+static void hciclose(void)
+{
+ LOG_INFO(LOG_TAG,"hciclose");
+ btif_hci_close();
+}
+
+
#if HCI_RAW_CMD_INCLUDED == TRUE
// Callback invoked on receiving HCI event
static void btif_vendor_hci_event_callback ( tBTM_RAW_CMPL *p)
@@ -404,8 +431,6 @@
return btif_l2cap_get_interface();
case TEST_APP_RFCOMM:
return btif_rfcomm_get_interface();
- case TEST_APP_MCAP:
- return btif_mcap_get_interface();
case TEST_APP_GATT:
return btif_gatt_test_get_interface();
case TEST_APP_SMP:
@@ -435,6 +460,7 @@
set_property_callouts,
cleanup,
voip_network_type_wifi,
+ hciclose,
};
/*******************************************************************************
diff --git a/system_bt_ext/conf/bt_profile.conf b/system_bt_ext/conf/bt_profile.conf
index 02404c4..ae9cdaf 100644
--- a/system_bt_ext/conf/bt_profile.conf
+++ b/system_bt_ext/conf/bt_profile.conf
@@ -29,4 +29,5 @@
# map_email_support default value true
[MAP]
map_email_support = true
+map_0104_support = true
diff --git a/system_bt_ext/conf/interop_database.conf b/system_bt_ext/conf/interop_database.conf
index fa948f6..774776d 100644
--- a/system_bt_ext/conf/interop_database.conf
+++ b/system_bt_ext/conf/interop_database.conf
@@ -391,6 +391,7 @@
00:09:93 = Address_Based
74:6f:f7 = Address_Based
A0:56:B2 = Address_Based
+00:54:AF = Address_Based
[INTEROP_DISABLE_CONNECTION_AFTER_COLLISION]
A0:14:3D
@@ -437,6 +438,7 @@
2c:dc:ad:08 = Address_Based
74:6f:f7 = Address_Based
90:03:b7 = Address_Based
+00:06:F5 = Address_Based
#Some remote devices don't support sniff mode when the SCO is connected.
#For such devices, disable sniff mode after SCO is connected and make
@@ -448,3 +450,7 @@
50:65:83 = Address_Based
28:3f:69 = Address_Based
AirPods = Name_Based
+
+#Enable power level 10 adaptive control in FW side for remote devices
+#in this whitelist item.
+[INTEROP_ENABLE_PL10_ADAPTIVE_CONTROL]
diff --git a/system_bt_ext/device/Android.bp b/system_bt_ext/device/Android.bp
index 1032e5f..44babef 100644
--- a/system_bt_ext/device/Android.bp
+++ b/system_bt_ext/device/Android.bp
@@ -13,10 +13,13 @@
"vendor/qcom/opensource/commonsys/system/bt/internal_include",
"vendor/qcom/opensource/commonsys/system/bt/stack/include",
"vendor/qcom/opensource/commonsys/bluetooth_ext/vhal/include",
+ "vendor/qcom/opensource/commonsys/system/bt/bta/include",
+ "vendor/qcom/opensource/commonsys/system/bt/utils/include/",
],
srcs: [
"src/interop.cc",
"src/profile_config.cc",
+ "src/device_iot_config.cc",
],
shared_libs: [
"liblog",
@@ -25,8 +28,4 @@
"libosi_qti",
"libbluetooth-types",
],
- cflags: [
- "-DHAS_NO_BDROID_BUILDCFG"
- ],
-
}
diff --git a/system_bt_ext/device/include/device_iot_conf_defs.h b/system_bt_ext/device/include/device_iot_conf_defs.h
new file mode 100644
index 0000000..12907a0
--- /dev/null
+++ b/system_bt_ext/device/include/device_iot_conf_defs.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#pragma once
+
+#define IOT_CONF_KEY_SECTION_ADAPTER "Adapter"
+#define IOT_CONF_KEY_ADDRESS "Address"
+#define IOT_CONF_KEY_BT_ONOFF_COUNT "BTOnOffCount"
+
+#define IOT_CONF_KEY_REMOTE_NAME "Name"
+#define IOT_CONF_KEY_DEVCLASS "DevClass"
+#define IOT_CONF_KEY_DEVTYPE "DevType"
+#define IOT_CONF_KEY_ADDRTYPE "AddrType"
+#define IOT_CONF_KEY_MANUFACTURER "Manufacturer"
+#define IOT_CONF_KEY_LMPVER "LmpVer"
+#define IOT_CONF_KEY_LMPSUBVER "LmpSubVer"
+#define IOT_CONF_KEY_PAIRTYPE "PairType"
+#define IOT_CONF_KEY_LE_PAIRTYPE "LE_PairType"
+#define IOT_CONF_KEY_RT_SUPP_FEATURES "RemoteSupportedFeatures"
+#define IOT_CONF_KEY_RT_EXT_FEATURES "RemoteExtendedFeatures"
+#define IOT_CONF_KEY_LE_RT_FEATURES "LE_RemoteSupportedFeatures"
+#define IOT_CONF_KEY_RECORDED "Recorded"
+
+#define IOT_CONF_KEY_GAP_CONN_COUNT "ProfileGap_ConnectCount"
+#define IOT_CONF_KEY_GAP_CONN_FAIL_COUNT "ProfileGap_ConnectFailCount"
+#define IOT_CONF_KEY_GAP_DISC_COUNT "ProfileGap_DiscCount"
+#define IOT_CONF_KEY_GAP_DISC_AUTHFAIL_COUNT "ProfileGap_DiscAuthFailCount"
+#define IOT_CONF_KEY_GAP_DISC_CONNTIMEOUT_COUNT "ProfileGap_DiscConnTimeoutCount"
+#define IOT_CONF_KEY_A2DP_ROLE "ProfileA2dp_Role"
+#define IOT_CONF_KEY_A2DP_VERSION "ProfileA2dp_Version"
+#define IOT_CONF_KEY_A2DP_CODECTYPE "ProfileA2dp_CodecType"
+#define IOT_CONF_KEY_A2DP_CONN_COUNT "ProfileA2dp_ConnectCount"
+#define IOT_CONF_KEY_A2DP_CONN_FAIL_COUNT "ProfileA2dp_ConnectFailCount"
+#define IOT_CONF_KEY_HFP_ROLE "ProfileHfp_Role"
+#define IOT_CONF_KEY_HFP_VERSION "ProfileHfp_Version"
+#define IOT_CONF_KEY_HFP_CODECTYPE "ProfileHfp_CodecType"
+#define IOT_CONF_KEY_HFP_SLC_CONN_COUNT "ProfileHfp_SlcConnectCount"
+#define IOT_CONF_KEY_HFP_SLC_CONN_FAIL_COUNT "ProfileHfp_SlcConnectFailCount"
+#define IOT_CONF_KEY_HFP_SCO_CONN_COUNT "ProfileHfp_ScoConnectCount"
+#define IOT_CONF_KEY_HFP_SCO_CONN_FAIL_COUNT "ProfileHfp_ScoConnectFailCount"
+#define IOT_CONF_KEY_HFP_FEATURES "ProfileHfp_Features"
+#define IOT_CONF_KEY_AVRCP_CTRL_VERSION "ProfileAvrcp_ControllerVersion"
+#define IOT_CONF_KEY_AVRCP_TG_VERSION "ProfileAvrcp_TargetVersion"
+#define IOT_CONF_KEY_AVRCP_CONN_COUNT "ProfileAvrcp_ConnectCount"
+#define IOT_CONF_KEY_AVRCP_CONN_FAIL_COUNT "ProfileAvrcp_ConnectFailCount"
+#define IOT_CONF_KEY_AVRCP_FEATURES "ProfileAvrcp_Features"
+#define IOT_CONF_KEY_HID_ROLE "ProfileHid_Role"
+#define IOT_CONF_KEY_HID_VERSION "ProfileHid_Version"
+#define IOT_CONF_KEY_HID_CONN_COUNT "ProfileHid_ConnectCount"
+#define IOT_CONF_KEY_HID_CONN_FAIL_COUNT "ProfileHid_ConnectFailCount"
+#define IOT_CONF_KEY_PBAP_ROLE "ProfilePbap_Role"
+#define IOT_CONF_KEY_PBAP_VERSION "ProfilePbap_Version"
+#define IOT_CONF_KEY_PBAP_CONN_COUNT "ProfilePbap_ConnectCount"
+#define IOT_CONF_KEY_PBAP_CONN_FAIL_COUNT "ProfilePbap_ConnectFailCount"
+#define IOT_CONF_KEY_MAP_ROLE "ProfileMap_Role"
+#define IOT_CONF_KEY_MAP_VERSION "ProfileMap_Version"
+#define IOT_CONF_KEY_MAP_CONN_COUNT "ProfileMap_ConnectCount"
+#define IOT_CONF_KEY_MAP_CONN_FAIL_COUNT "ProfileMap_ConnectFailCount"
+
+#define IOT_CONF_VAL_PAIR_TYPE_LEGACY 0
+#define IOT_CONF_VAL_PAIR_TYPE_SSP 1
+#define IOT_CONF_VAL_LE_PAIRTYPE_LEGACY 0
+#define IOT_CONF_VAL_LE_PAIRTYPE_SECURE 1
+#define IOT_CONF_VAL_RECORDED_DEFAULT 0
+
+#define IOT_CONF_VAL_A2DP_ROLE_SINK 0
+#define IOT_CONF_VAL_A2DP_ROLE_SOURCE 1
+#define IOT_CONF_VAL_A2DP_CODECTYPE_SBC 0x01
+#define IOT_CONF_VAL_A2DP_CODECTYPE_APTX 0x02
+#define IOT_CONF_VAL_A2DP_CODECTYPE_APTXHD 0x04
+#define IOT_CONF_VAL_A2DP_CODECTYPE_AAC 0x08
+#define IOT_CONF_VAL_A2DP_CODECTYPE_LDAC 0x10
+#define IOT_CONF_VAL_A2DP_CODECTYPE_APTXADAPTIVE 0x20
+#define IOT_CONF_VAL_A2DP_CODECTYPE_APTXTWS 0x40
+
+#define IOT_CONF_VAL_HFP_ROLE_CLIENT 0
+#define IOT_CONF_VAL_HFP_ROLE_AG 1
+#define IOT_CONF_VAL_HFP_CODECTYPE_CVSD 0x01
+#define IOT_CONF_VAL_HFP_CODECTYPE_CVSDMSBC 0x02
+
+#define IOT_CONF_VAL_HID_ROLE_HOST 0
+#define IOT_CONF_VAL_HID_ROLE_DEVICE 1
+
+#define IOT_CONF_VAL_PBAP_ROLE_CLIENT 0
+#define IOT_CONF_VAL_PBAP_ROLE_SERVER 1
+
+#define IOT_CONF_VAL_MAP_ROLE_CLIENT 0
+#define IOT_CONF_VAL_MAP_ROLE_SERVER 1
+
+#define IOT_CONF_BYTE_NUM_1 1
+#define IOT_CONF_BYTE_NUM_2 2
+#define IOT_CONF_BYTE_NUM_3 3
+#define IOT_CONF_BYTE_NUM_4 4
+
diff --git a/system_bt_ext/device/include/device_iot_config.h b/system_bt_ext/device/include/device_iot_config.h
new file mode 100644
index 0000000..a4ed0fb
--- /dev/null
+++ b/system_bt_ext/device/include/device_iot_config.h
@@ -0,0 +1,74 @@
+/******************************************************************************
+ * Copyright (C) 2018, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * 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 "bt_target.h"
+#if (BT_IOT_LOGGING_ENABLED == TRUE)
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#include "bt_types.h"
+#include "device_iot_conf_defs.h"
+#include "raw_address.h"
+
+static const char DEVICE_IOT_CONFIG_MODULE[] = "device_iot_config_module";
+
+typedef struct device_iot_config_section_iter_t device_iot_config_section_iter_t;
+
+bool device_iot_config_has_section(const char* section);
+bool device_iot_config_exist(const char* section, const char* key);
+bool device_iot_config_get_int(const char* section, const char* key, int* value);
+bool device_iot_config_addr_get_int(const RawAddress& peer_addr, const char* key, int* value);
+bool device_iot_config_set_int(const char* section, const char* key, int value);
+bool device_iot_config_addr_set_int(const RawAddress& peer_addr, const char* key, int value);
+bool device_iot_config_int_add_one(const char* section, const char* key);
+bool device_iot_config_addr_int_add_one(const RawAddress& peer_addr, const char* key);
+
+bool device_iot_config_get_hex(const char* section, const char* key, int* value);
+bool device_iot_config_addr_get_hex(const RawAddress& peer_addr, const char* key, int* value);
+bool device_iot_config_set_hex(const char* section, const char* key, int value, int byte_num);
+bool device_iot_config_addr_set_hex(const RawAddress& peer_addr, const char* key, int value, int byte_num);
+bool device_iot_config_addr_set_hex_if_greater(const RawAddress& peer_addr, const char* key, int value, int byte_num);
+bool device_iot_config_get_str(const char* section, const char* key, char* value, int* size_bytes);
+bool device_iot_config_set_str(const char* section, const char* key, const char* value);
+bool device_iot_config_addr_set_str(const RawAddress& peer_addr, const char* key, const char* value);
+bool device_iot_config_get_bin(const char* section, const char* key, uint8_t* value, size_t* length);
+bool device_iot_config_set_bin(const char* section, const char* key, const uint8_t* value, size_t length);
+bool device_iot_config_addr_set_bin(const RawAddress& peer_addr, const char* key, const uint8_t* value, size_t length);
+bool device_iot_config_remove(const char* section, const char* key);
+
+size_t device_iot_config_get_bin_length(const char* section, const char* key);
+
+const device_iot_config_section_iter_t* device_iot_config_section_begin(void);
+const device_iot_config_section_iter_t* device_iot_config_section_end(void);
+const device_iot_config_section_iter_t* device_iot_config_section_next(const device_iot_config_section_iter_t* section);
+const char* device_iot_config_section_name(const device_iot_config_section_iter_t* section);
+
+void device_iot_config_flush(void);
+bool device_iot_config_clear(void);
+
+void device_debug_iot_config_dump(int fd);
+
+#endif
diff --git a/system_bt_ext/device/src/device_iot_config.cc b/system_bt_ext/device/src/device_iot_config.cc
new file mode 100644
index 0000000..b5b3d18
--- /dev/null
+++ b/system_bt_ext/device/src/device_iot_config.cc
@@ -0,0 +1,822 @@
+/******************************************************************************
+ * Copyright (C) 2018, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution
+ *****************************************************************************/
+/******************************************************************************
+ *
+ * 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.
+ *
+ ******************************************************************************/
+#include "bt_target.h"
+#if (BT_IOT_LOGGING_ENABLED == TRUE)
+
+#define LOG_TAG "device_iot_config"
+//#undef LOG_NDEBUG
+//#define LOG_NDEBUG 0
+#include "device_iot_config.h"
+
+#include <base/logging.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <string>
+#include <mutex>
+
+#include "bt_types.h"
+#include "btcore/include/module.h"
+#include "btif/include/btif_api.h"
+#include "btif/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"
+
+#define BT_IOT_CONFIG_SOURCE_TAG_NUM 1010003
+
+#define INFO_SECTION "Info"
+#define VERSION_KEY "Version"
+#define FILE_CREATED_TIMESTAMP "TimeCreated"
+#define FILE_MODIFIED_TIMESTAMP "TimeModified"
+#define TIME_STRING_LENGTH sizeof("YYYY-MM-DD HH:MM:SS")
+static const char* TIME_STRING_FORMAT = "%Y-%m-%d %H:%M:%S";
+
+#ifndef DEVICES_MAX_NUM_IN_IOT_INFO_FILE
+#define DEVICES_MAX_NUM_IN_IOT_INFO_FILE 40
+#endif
+#define DEVICES_NUM_MARGIN 5
+
+#if (DEVICES_MAX_NUM_IN_IOT_INFO_FILE < DEVICES_NUM_MARGIN)
+#undef DEVICES_MAX_NUM_IN_IOT_INFO_FILE
+#define DEVICES_MAX_NUM_IN_IOT_INFO_FILE DEVICES_NUM_MARGIN
+#endif
+
+#define DEVICE_IOT_INFO_CURRENT_VERSION 1
+#define DEVICE_IOT_INFO_FIRST_VERSION 1
+
+#define IOT_CONFIG_FLUSH_EVT 0
+#define IOT_CONFIG_SAVE_TIMER_FIRED_EVT 1
+
+#if defined(OS_GENERIC)
+static const char* IOT_CONFIG_FILE_PATH = "bt_remote_dev_info.conf";
+static const char* IOT_CONFIG_BACKUP_PATH = "bt_remote_dev_info.bak";
+#else // !defined(OS_GENERIC)
+static const char* IOT_CONFIG_FILE_PATH = "/data/misc/bluedroid/bt_remote_dev_info.conf";
+static const char* IOT_CONFIG_BACKUP_PATH = "/data/misc/bluedroid/bt_remote_dev_info.bak";
+#endif // defined(OS_GENERIC)
+static const period_ms_t CONFIG_SETTLE_PERIOD_MS = 12000;
+
+static void timer_iot_config_save_cb(void* data);
+static void device_iot_config_write(uint16_t event, char* p_param);
+static config_t* device_iot_config_open(const char* filename);
+static int device_iot_config_get_device_num(config_t* config);
+static void device_iot_config_save(void);
+static bool is_factory_reset(void);
+static void delete_iot_config_files(void);
+
+static enum ConfigSource {
+ NOT_LOADED,
+ ORIGINAL,
+ BACKUP,
+ NEW_FILE,
+ RESET
+} device_iot_config_source = NOT_LOADED;
+
+static int device_iot_config_devices_loaded = -1;
+static char device_iot_config_time_created[TIME_STRING_LENGTH];
+
+static std::mutex config_lock; // protects operations on |config|.
+static config_t* config;
+static alarm_t* config_timer;
+static bool iot_logging_enabled = false;
+
+#define CHECK_LOGGING_ENABLED(return_value) do { if (!iot_logging_enabled) return (return_value); } while(0)
+
+// Module lifecycle functions
+static future_t* init(void) {
+ char enabled[PROPERTY_VALUE_MAX] = {0};
+
+ std::unique_lock<std::mutex> lock(config_lock);
+ osi_property_get("persist.vendor.service.bt.iot.enablelogging", enabled, "false");
+ iot_logging_enabled = strncmp(enabled, "true", 4) == 0;
+
+ if (!iot_logging_enabled) {
+ delete_iot_config_files();
+ return future_new_immediate(FUTURE_SUCCESS);
+ }
+
+ LOG_INFO(LOG_TAG, "%s", __func__);
+
+ if (is_factory_reset())
+ delete_iot_config_files();
+
+ config = device_iot_config_open(IOT_CONFIG_FILE_PATH);
+ device_iot_config_source = ORIGINAL;
+ if (!config) {
+ LOG_WARN(LOG_TAG, "%s unable to load config file: %s; using backup.",
+ __func__, IOT_CONFIG_FILE_PATH);
+ config = device_iot_config_open(IOT_CONFIG_BACKUP_PATH);
+ device_iot_config_source = BACKUP;
+ }
+
+ if (!config) {
+ LOG_ERROR(LOG_TAG, "%s unable to load bak file; creating empty config.", __func__);
+ config = config_new_empty();
+ device_iot_config_source = NEW_FILE;
+ }
+
+ if (!config) {
+ LOG_ERROR(LOG_TAG, "%s unable to allocate a config object.", __func__);
+ goto error;
+ }
+
+ int version;
+ if (device_iot_config_source == NEW_FILE) {
+ version = DEVICE_IOT_INFO_CURRENT_VERSION;
+ config_set_int(config, INFO_SECTION, VERSION_KEY, DEVICE_IOT_INFO_CURRENT_VERSION);
+ } else {
+ version = config_get_int(config, INFO_SECTION, VERSION_KEY, -1);
+ if (version == -1) {
+ version = DEVICE_IOT_INFO_FIRST_VERSION;
+ config_set_int(config, INFO_SECTION, VERSION_KEY, DEVICE_IOT_INFO_FIRST_VERSION);
+ }
+ }
+
+ if (version != DEVICE_IOT_INFO_CURRENT_VERSION) {
+ LOG_INFO(LOG_TAG, "%s: version in file is %d, CURRENT_VERSION is %d ", __func__,
+ version, DEVICE_IOT_INFO_CURRENT_VERSION);
+ remove(IOT_CONFIG_FILE_PATH);
+ remove(IOT_CONFIG_BACKUP_PATH);
+ config_free(config);
+ config = config_new_empty();
+ if (!config) {
+ LOG_ERROR(LOG_TAG, "%s unable to allocate a config object.", __func__);
+ goto error;
+ }
+ config_set_int(config, INFO_SECTION, VERSION_KEY, DEVICE_IOT_INFO_CURRENT_VERSION);
+ device_iot_config_source = NEW_FILE;
+ }
+
+ device_iot_config_devices_loaded = device_iot_config_get_device_num(config);
+
+ // Read or set config file creation timestamp
+ const char* time_str;
+ time_str = config_get_string(config, INFO_SECTION, FILE_CREATED_TIMESTAMP, NULL);
+ if (time_str != NULL) {
+ strlcpy(device_iot_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) {
+ strftime(device_iot_config_time_created, TIME_STRING_LENGTH,
+ TIME_STRING_FORMAT, time_created);
+ config_set_string(config, INFO_SECTION, FILE_CREATED_TIMESTAMP,
+ device_iot_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.iot.config");
+ if (!config_timer) {
+ LOG_ERROR(LOG_TAG, "%s unable to create alarm.", __func__);
+ goto error;
+ }
+
+ LOG_EVENT_INT(BT_IOT_CONFIG_SOURCE_TAG_NUM, device_iot_config_source);
+
+ return future_new_immediate(FUTURE_SUCCESS);
+
+error:
+ alarm_free(config_timer);
+ config_free(config);
+ config_timer = NULL;
+ config = NULL;
+ device_iot_config_source = NOT_LOADED;
+ return future_new_immediate(FUTURE_FAIL);
+}
+
+static config_t* device_iot_config_open(const char* filename) {
+ config_t* config = config_new(filename);
+ if (!config)
+ return NULL;
+
+ return config;
+}
+
+static future_t* start_up(void) {
+ CHECK_LOGGING_ENABLED(future_new_immediate(FUTURE_SUCCESS));
+
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ device_iot_config_int_add_one(IOT_CONF_KEY_SECTION_ADAPTER, IOT_CONF_KEY_BT_ONOFF_COUNT);
+ return future_new_immediate(FUTURE_SUCCESS);
+}
+
+static future_t* shut_down(void) {
+ CHECK_LOGGING_ENABLED(future_new_immediate(FUTURE_SUCCESS));
+
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ device_iot_config_flush();
+ return future_new_immediate(FUTURE_SUCCESS);
+}
+
+static future_t* clean_up(void) {
+ CHECK_LOGGING_ENABLED(future_new_immediate(FUTURE_SUCCESS));
+
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ if (config_timer != NULL && alarm_is_scheduled(config_timer))
+ device_iot_config_flush();
+
+ alarm_free(config_timer);
+ config_timer = NULL;
+
+ std::unique_lock<std::mutex> lock(config_lock);
+ config_free(config);
+ config = NULL;
+ return future_new_immediate(FUTURE_SUCCESS);
+}
+
+EXPORT_SYMBOL module_t device_iot_config_module = {
+ .name = DEVICE_IOT_CONFIG_MODULE,
+ .init = init,
+ .start_up = start_up,
+ .shut_down = shut_down,
+ .clean_up = clean_up
+};
+
+bool device_iot_config_has_section(const char* section) {
+ CHECK_LOGGING_ENABLED(false);
+
+ CHECK(config != NULL);
+ CHECK(section != NULL);
+
+ std::unique_lock<std::mutex> lock(config_lock);
+ return config_has_section(config, section);
+}
+
+bool device_iot_config_exist(const char* section, const char* key) {
+ CHECK_LOGGING_ENABLED(false);
+
+ CHECK(config != NULL);
+ CHECK(section != NULL);
+ CHECK(key != NULL);
+
+ std::unique_lock<std::mutex> lock(config_lock);
+ return config_has_key(config, section, key);
+}
+
+static bool device_iot_config_has_key_value(const char* section, const char* key, const char* value_str) {
+ CHECK(config != NULL);
+ CHECK(section != NULL);
+ CHECK(key != NULL);
+ CHECK(value_str != NULL);
+
+ const char* stored_value = config_get_string(config, section, key, NULL);
+
+ if (!stored_value || strcmp(value_str, stored_value) != 0)
+ return false;
+
+ return true;
+}
+
+bool device_iot_config_get_int(const char* section, const char* key, int* value) {
+ CHECK_LOGGING_ENABLED(false);
+
+ CHECK(config != NULL);
+ CHECK(section != NULL);
+ CHECK(key != NULL);
+ CHECK(value != NULL);
+
+ std::unique_lock<std::mutex> lock(config_lock);
+ bool ret = config_has_key(config, section, key);
+ if (ret)
+ *value = config_get_int(config, section, key, *value);
+
+ return ret;
+}
+
+bool device_iot_config_addr_get_int(const RawAddress& peer_addr, const char* key, int* value) {
+ CHECK_LOGGING_ENABLED(false);
+
+ std::string addrstr = peer_addr.ToString();
+ const char* bdstr = addrstr.c_str();
+ return device_iot_config_get_int(bdstr, key, value);
+}
+
+bool device_iot_config_set_int(const char* section, const char* key, int value) {
+ CHECK_LOGGING_ENABLED(false);
+
+ CHECK(config != NULL);
+ CHECK(section != NULL);
+ CHECK(key != NULL);
+
+ LOG_VERBOSE(LOG_TAG, "%s: sec=%s, key=%s, val=%d", __func__, section, key, value);
+ std::unique_lock<std::mutex> lock(config_lock);
+ char value_str[32] = {0};
+ snprintf(value_str, sizeof(value_str), "%d", value);
+ if (device_iot_config_has_key_value(section, key, value_str))
+ return true;
+
+ config_set_string(config, section, key, value_str);
+ device_iot_config_save();
+
+ return true;
+}
+
+bool device_iot_config_addr_set_int(const RawAddress& peer_addr, const char* key, int value) {
+ CHECK_LOGGING_ENABLED(false);
+
+ std::string addrstr = peer_addr.ToString();
+ const char* bdstr = addrstr.c_str();
+ return device_iot_config_set_int(bdstr, key, value);
+}
+
+bool device_iot_config_int_add_one(const char* section, const char* key) {
+ CHECK_LOGGING_ENABLED(false);
+
+ CHECK(config != NULL);
+ CHECK(section != NULL);
+ CHECK(key != NULL);
+
+ LOG_VERBOSE(LOG_TAG, "%s: sec=%s, key=%s", __func__, section, key);
+ int result = 0;
+ std::unique_lock<std::mutex> lock(config_lock);
+ result = config_get_int(config, section, key, result);
+ result += 1;
+ config_set_int(config, section, key, result);
+ device_iot_config_save();
+
+ return true;
+}
+
+bool device_iot_config_addr_int_add_one(const RawAddress& peer_addr, const char* key) {
+ CHECK_LOGGING_ENABLED(false);
+
+ std::string addrstr = peer_addr.ToString();
+ const char* bdstr = addrstr.c_str();
+ return device_iot_config_int_add_one(bdstr, key);
+}
+
+bool device_iot_config_get_hex(const char* section, const char* key, int* value) {
+ CHECK_LOGGING_ENABLED(false);
+
+ CHECK(config != NULL);
+ CHECK(section != NULL);
+ CHECK(key != NULL);
+ CHECK(value != NULL);
+
+ int sscanf_ret, result = 0;
+ std::unique_lock<std::mutex> lock(config_lock);
+ const char* stored_value = config_get_string(config, section, key, NULL);
+ if (!stored_value)
+ return false;
+
+ sscanf_ret = sscanf(stored_value, "%x", &result);
+ if (sscanf_ret != 1)
+ return false;
+
+ *value = result;
+ return true;
+}
+
+bool device_iot_config_addr_get_hex(const RawAddress& peer_addr, const char* key, int* value) {
+ CHECK_LOGGING_ENABLED(false);
+
+ std::string addrstr = peer_addr.ToString();
+ const char* bdstr = addrstr.c_str();
+ return device_iot_config_get_hex(bdstr, key, value);
+}
+
+bool device_iot_config_set_hex(const char* section, const char* key, int value, int byte_num) {
+ CHECK_LOGGING_ENABLED(false);
+
+ CHECK(config != NULL);
+ CHECK(section != NULL);
+ CHECK(key != NULL);
+
+ LOG_VERBOSE(LOG_TAG, "%s: sec=%s, key=%s, val=0x%x", __func__, section, key, value);
+ char value_str[32] = { 0 };
+ if (byte_num == 1)
+ snprintf(value_str, sizeof(value_str), "%02x", value);
+ else if (byte_num == 2)
+ snprintf(value_str, sizeof(value_str), "%04x", value);
+ else if (byte_num == 3)
+ snprintf(value_str, sizeof(value_str), "%06x", value);
+ else if (byte_num == 4)
+ snprintf(value_str, sizeof(value_str), "%08x", value);
+
+ std::unique_lock<std::mutex> lock(config_lock);
+ if (device_iot_config_has_key_value(section, key, value_str))
+ return true;
+
+ config_set_string(config, section, key, value_str);
+ device_iot_config_save();
+
+ return true;
+}
+
+bool device_iot_config_addr_set_hex(const RawAddress& peer_addr,
+ const char* key, int value, int byte_num) {
+ CHECK_LOGGING_ENABLED(false);
+
+ std::string addrstr = peer_addr.ToString();
+ const char* bdstr = addrstr.c_str();
+ return device_iot_config_set_hex(bdstr, key, value, byte_num);
+}
+
+bool device_iot_config_addr_set_hex_if_greater(const RawAddress& peer_addr,
+ const char* key, int value, int byte_num) {
+ CHECK_LOGGING_ENABLED(false);
+
+ int stored_value = 0;
+ bool ret = device_iot_config_addr_get_hex(peer_addr, key, &stored_value);
+ if (ret && stored_value >= value)
+ return true;
+
+ return device_iot_config_addr_set_hex(peer_addr, key, value, byte_num);
+}
+
+bool device_iot_config_get_str(const char* section, const char* key, char* value, int* size_bytes) {
+ CHECK_LOGGING_ENABLED(false);
+
+ CHECK(config != NULL);
+ CHECK(section != NULL);
+ CHECK(key != NULL);
+ CHECK(value != NULL);
+ CHECK(size_bytes != NULL);
+
+ std::unique_lock<std::mutex> lock(config_lock);
+ const char* stored_value = config_get_string(config, section, key, NULL);
+
+ if (!stored_value)
+ return false;
+
+ strlcpy(value, stored_value, *size_bytes);
+ *size_bytes = strlen(value) + 1;
+
+ return true;
+}
+
+bool device_iot_config_set_str(const char* section, const char* key, const char* value) {
+ CHECK_LOGGING_ENABLED(false);
+
+ CHECK(config != NULL);
+ CHECK(section != NULL);
+ CHECK(key != NULL);
+ CHECK(value != NULL);
+
+ LOG_VERBOSE(LOG_TAG, "%s: sec=%s, key=%s, val=%s", __func__, section, key, value);
+ std::unique_lock<std::mutex> lock(config_lock);
+ if (device_iot_config_has_key_value(section, key, value))
+ return true;
+
+ config_set_string(config, section, key, value);
+ device_iot_config_save();
+
+ return true;
+}
+
+bool device_iot_config_addr_set_str(const RawAddress& peer_addr,
+ const char* key, const char* value) {
+ CHECK_LOGGING_ENABLED(false);
+
+ std::string addrstr = peer_addr.ToString();
+ const char* bdstr = addrstr.c_str();
+ return device_iot_config_set_str(bdstr, key, value);
+}
+
+bool device_iot_config_get_bin(const char* section, const char* key,
+ uint8_t* value, size_t* length) {
+ CHECK_LOGGING_ENABLED(false);
+
+ CHECK(config != NULL);
+ CHECK(section != NULL);
+ CHECK(key != NULL);
+ CHECK(value != NULL);
+ CHECK(length != NULL);
+
+ std::unique_lock<std::mutex> lock(config_lock);
+ const char* value_str = config_get_string(config, section, key, NULL);
+
+ if (!value_str)
+ return false;
+
+ size_t value_len = strlen(value_str);
+ if ((value_len % 2) != 0 || *length < (value_len / 2))
+ return false;
+
+ for (size_t i = 0; i < value_len; ++i)
+ if (!isxdigit(value_str[i]))
+ return false;
+
+ for (*length = 0; *value_str; value_str += 2, *length += 1)
+ sscanf(value_str, "%02hhx", &value[*length]);
+
+ return true;
+}
+
+size_t device_iot_config_get_bin_length(const char* section, const char* key) {
+ CHECK_LOGGING_ENABLED(0);
+
+ CHECK(config != NULL);
+ CHECK(section != NULL);
+ CHECK(key != NULL);
+
+ std::unique_lock<std::mutex> lock(config_lock);
+ const char* value_str = config_get_string(config, section, key, NULL);
+
+ if (!value_str)
+ return 0;
+
+ size_t value_len = strlen(value_str);
+ return ((value_len % 2) != 0) ? 0 : (value_len / 2);
+}
+
+bool device_iot_config_set_bin(const char* section, const char* key,
+ const uint8_t* value, size_t length) {
+ CHECK_LOGGING_ENABLED(false);
+
+ const char* lookup = "0123456789abcdef";
+
+ CHECK(config != NULL);
+ CHECK(section != NULL);
+ CHECK(key != NULL);
+
+ LOG_VERBOSE(LOG_TAG, "%s: key = %s", __func__, key);
+ if (length > 0)
+ CHECK(value != NULL);
+
+ char* str = (char* )osi_calloc(length * 2 + 1);
+ if (str == NULL) {
+ LOG_ERROR(LOG_TAG, "%s unable to allocate a str.", __func__);
+ return false;
+ }
+
+ for (size_t i = 0; i < length; ++i) {
+ str[(i * 2) + 0] = lookup[(value[i] >> 4) & 0x0F];
+ str[(i * 2) + 1] = lookup[value[i] & 0x0F];
+ }
+
+ std::unique_lock<std::mutex> lock(config_lock);
+ if (device_iot_config_has_key_value(section, key, str))
+ return true;
+
+ config_set_string(config, section, key, str);
+ device_iot_config_save();
+
+ osi_free(str);
+ return true;
+}
+
+bool device_iot_config_addr_set_bin(const RawAddress& peer_addr,
+ const char* key, const uint8_t* value, size_t length) {
+ CHECK_LOGGING_ENABLED(false);
+
+ std::string addrstr = peer_addr.ToString();
+ const char* bdstr = addrstr.c_str();
+ return device_iot_config_set_bin(bdstr, key, value, length);
+}
+
+const device_iot_config_section_iter_t* device_iot_config_section_begin(void) {
+ CHECK_LOGGING_ENABLED(NULL);
+
+ CHECK(config != NULL);
+ return (const device_iot_config_section_iter_t* )config_section_begin(config);
+}
+
+const device_iot_config_section_iter_t* device_iot_config_section_end(void) {
+ CHECK_LOGGING_ENABLED(NULL);
+
+ CHECK(config != NULL);
+ return (const device_iot_config_section_iter_t* )config_section_end(config);
+}
+
+const device_iot_config_section_iter_t* device_iot_config_section_next(const
+ device_iot_config_section_iter_t* section) {
+ CHECK_LOGGING_ENABLED(NULL);
+
+ CHECK(config != NULL);
+ CHECK(section != NULL);
+ return (const device_iot_config_section_iter_t* )config_section_next((const
+ config_section_node_t* )section);
+}
+
+const char* device_iot_config_section_name(const device_iot_config_section_iter_t* section) {
+ CHECK_LOGGING_ENABLED(NULL);
+
+ CHECK(config != NULL);
+ CHECK(section != NULL);
+ return config_section_name((const config_section_node_t* )section);
+}
+
+bool device_iot_config_remove(const char* section, const char* key) {
+ CHECK_LOGGING_ENABLED(false);
+
+ CHECK(config != NULL);
+ CHECK(section != NULL);
+ CHECK(key != NULL);
+
+ std::unique_lock<std::mutex> lock(config_lock);
+ return config_remove_key(config, section, key);
+}
+
+static void device_iot_config_save(void) {
+ CHECK_LOGGING_ENABLED((void)0);
+
+ CHECK(config != NULL);
+ CHECK(config_timer != NULL);
+
+ LOG_VERBOSE(LOG_TAG, "%s", __func__);
+ alarm_set(config_timer, CONFIG_SETTLE_PERIOD_MS, timer_iot_config_save_cb, NULL);
+}
+
+void device_iot_config_flush(void) {
+ CHECK_LOGGING_ENABLED((void)0);
+
+ CHECK(config != NULL);
+ CHECK(config_timer != NULL);
+
+ int event = alarm_is_scheduled(config_timer) ? IOT_CONFIG_SAVE_TIMER_FIRED_EVT :
+ IOT_CONFIG_FLUSH_EVT;
+ LOG_VERBOSE(LOG_TAG, "%s: evt=%d", __func__, event);
+ alarm_cancel(config_timer);
+ device_iot_config_write(event, NULL);
+}
+
+bool device_iot_config_clear(void) {
+ CHECK_LOGGING_ENABLED(false);
+
+ CHECK(config != NULL);
+ CHECK(config_timer != NULL);
+
+ LOG_INFO(LOG_TAG, "%s", __func__);
+ alarm_cancel(config_timer);
+
+ std::unique_lock<std::mutex> lock(config_lock);
+ config_free(config);
+
+ config = config_new_empty();
+ if (config == NULL) {
+ return false;
+ }
+
+ bool ret = config_save(config, IOT_CONFIG_FILE_PATH);
+ device_iot_config_source = RESET;
+ return ret;
+}
+
+static void timer_iot_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.
+ LOG_VERBOSE(LOG_TAG, "%s", __func__);
+ btif_transfer_context(device_iot_config_write, IOT_CONFIG_SAVE_TIMER_FIRED_EVT, NULL, 0, NULL);
+}
+
+static void set_modified_time() {
+ time_t current_time = time(NULL);
+ struct tm* time_modified = localtime(¤t_time);
+ char device_iot_config_time_modified[TIME_STRING_LENGTH];
+ if (time_modified) {
+ strftime(device_iot_config_time_modified, TIME_STRING_LENGTH,
+ TIME_STRING_FORMAT, time_modified);
+ config_set_string(config, INFO_SECTION, FILE_MODIFIED_TIMESTAMP,
+ device_iot_config_time_modified);
+ }
+}
+
+static void restrict_device_num() {
+ CHECK(config != NULL);
+
+ int curr_num = device_iot_config_get_device_num(config);
+ int removed_devices = 0;
+ int need_remove_devices_num;
+
+ if (curr_num <= DEVICES_MAX_NUM_IN_IOT_INFO_FILE) {
+ return;
+ }
+
+ need_remove_devices_num = curr_num - DEVICES_MAX_NUM_IN_IOT_INFO_FILE + DEVICES_NUM_MARGIN;
+ LOG_INFO(LOG_TAG, "%s: curr_num=%d, need_remove_num=%d", __func__,
+ curr_num, need_remove_devices_num);
+
+ const config_section_node_t* snode = config_section_begin(config);
+ while (snode != config_section_end(config)) {
+ const char* section = config_section_name(snode);
+ if (RawAddress::IsValidAddress(section)) {
+ snode = config_section_next(snode);
+ config_remove_section(config, section);
+ if (++removed_devices >= need_remove_devices_num) {
+ break;
+ }
+ } else {
+ snode = config_section_next(snode);
+ }
+ }
+}
+
+static int compare_key(const char* first, const char* second) {
+ bool first_is_profile_key = strncasecmp(first, "Profile", 7) == 0;
+ bool second_is_profile_key = strncasecmp(second, "Profile", 7) == 0;
+ if (!first_is_profile_key && !second_is_profile_key) {
+ return 0;
+ } else if (first_is_profile_key && second_is_profile_key) {
+ return strcasecmp(first, second);
+ } else {
+ return first_is_profile_key ? 1 : -1;
+ }
+}
+
+static void device_iot_config_write(uint16_t event, UNUSED_ATTR char* p_param) {
+ CHECK_LOGGING_ENABLED((void)0);
+
+ CHECK(config != NULL);
+ CHECK(config_timer != NULL);
+
+ LOG_INFO(LOG_TAG, "%s: evt=%d", __func__, event);
+ std::unique_lock<std::mutex> lock(config_lock);
+ if (event == IOT_CONFIG_SAVE_TIMER_FIRED_EVT)
+ set_modified_time();
+
+ rename(IOT_CONFIG_FILE_PATH, IOT_CONFIG_BACKUP_PATH);
+ restrict_device_num();
+ config_sections_sort_by_entry_key(config, compare_key);
+ config_save(config, IOT_CONFIG_FILE_PATH);
+}
+
+static int device_iot_config_get_device_num(config_t* conf) {
+ CHECK_LOGGING_ENABLED(0);
+
+ CHECK(conf != NULL);
+ int devices = 0;
+
+ const config_section_node_t* snode = config_section_begin(conf);
+ while (snode != config_section_end(conf)) {
+ const char* section = config_section_name(snode);
+ if (RawAddress::IsValidAddress(section)) {
+ devices++;
+ }
+ snode = config_section_next(snode);
+ }
+ return devices;
+}
+
+void device_debug_iot_config_dump(int fd) {
+ CHECK_LOGGING_ENABLED((void)0);
+
+ dprintf(fd, "\nBluetooth Iot Config:\n");
+
+ dprintf(fd, " Config Source: ");
+ switch(device_iot_config_source) {
+ case NOT_LOADED:
+ dprintf(fd, "Not loaded\n");
+ break;
+ case ORIGINAL:
+ dprintf(fd, "Original file\n");
+ break;
+ case BACKUP:
+ dprintf(fd, "Backup file\n");
+ break;
+ case NEW_FILE:
+ dprintf(fd, "New file\n");
+ break;
+ case RESET:
+ dprintf(fd, "Reset file\n");
+ break;
+ }
+
+ dprintf(fd, " Devices loaded: %d\n", device_iot_config_devices_loaded);
+ dprintf(fd, " File created/tagged: %s\n", device_iot_config_time_created);
+}
+
+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_iot_config_files(void) {
+ remove(IOT_CONFIG_FILE_PATH);
+ remove(IOT_CONFIG_BACKUP_PATH);
+}
+
+#endif
diff --git a/system_bt_ext/device/src/interop.cc b/system_bt_ext/device/src/interop.cc
index 6e209c7..b29d1c9 100644
--- a/system_bt_ext/device/src/interop.cc
+++ b/system_bt_ext/device/src/interop.cc
@@ -241,6 +241,7 @@
CASE_RETURN_STR(INTEROP_ENABLE_AAC_CODEC)
CASE_RETURN_STR(INTEROP_DISABLE_CONNECTION_AFTER_COLLISION)
CASE_RETURN_STR(INTEROP_AVRCP_BROWSE_OPEN_CHANNEL_COLLISION)
+ CASE_RETURN_STR(INTEROP_ENABLE_PL10_ADAPTIVE_CONTROL)
CASE_RETURN_STR(END_OF_INTEROP_LIST)
CASE_RETURN_STR(INTEROP_ADV_PBAP_VER_1_2)
CASE_RETURN_STR(INTEROP_DISABLE_SNIFF_LINK_DURING_SCO)
diff --git a/system_bt_ext/device/src/profile_config.cc b/system_bt_ext/device/src/profile_config.cc
index 8446864..ed1b0d8 100644
--- a/system_bt_ext/device/src/profile_config.cc
+++ b/system_bt_ext/device/src/profile_config.cc
@@ -85,6 +85,7 @@
typedef struct {
char map_email_support[VALUE_MAX_LENGTH];
+ char map_0104_support[VALUE_MAX_LENGTH];
} map_feature_t;
typedef struct {
@@ -131,6 +132,7 @@
CASE_RETURN_STR(AVRCP_0103_SUPPORT)
CASE_RETURN_STR(USE_SIM_SUPPORT)
CASE_RETURN_STR(MAP_EMAIL_SUPPORT)
+ CASE_RETURN_STR(MAP_0104_SUPPORT)
CASE_RETURN_STR(PBAP_0102_SUPPORT)
CASE_RETURN_STR(END_OF_FEATURE_LIST)
}
@@ -347,6 +349,14 @@
LOG_WARN(LOG_TAG, "profile_feature_fetch:MAP_EMAIL_SUPPORT found %d" , feature_set);
}
break;
+ case MAP_0104_SUPPORT:
+ {
+ if (strncasecmp("true", db_entry->profile_feature_type.map_feature_entry.map_0104_support,
+ strlen("true")) == 0)
+ feature_set = true;
+ LOG_WARN(LOG_TAG, "profile_feature_fetch:MAP_0104_SUPPORT found %d" , feature_set);
+ }
+ break;
default:
{
LOG_WARN(LOG_TAG, "profile_feature_fetch:profile = %d , feature %d not found" , profile, feature_name);
@@ -451,6 +461,14 @@
memcpy(&entry->profile_feature_type.map_feature_entry.map_email_support, value, strlen(value));
}
break;
+ case MAP_0104_SUPPORT:
+ {
+ memset(&entry->profile_feature_type.map_feature_entry.map_0104_support,
+ '\0', VALUE_MAX_LENGTH);
+ memcpy(&entry->profile_feature_type.map_feature_entry.map_0104_support,
+ value, strlen(value));
+ }
+ break;
default:
{
LOG_WARN(LOG_TAG,"%s is invalid key %s", __func__, key);
diff --git a/system_bt_ext/include/bt_testapp.h b/system_bt_ext/include/bt_testapp.h
index a8681ed..486b9e1 100644
--- a/system_bt_ext/include/bt_testapp.h
+++ b/system_bt_ext/include/bt_testapp.h
@@ -50,7 +50,6 @@
#include "sdp_api.h"
#include "gatt_api.h"
#include "gap_api.h"
-#include "mca_api.h"
#include <hardware/hardware.h>
#include "btm_api.h"
#include "bt_types.h"
@@ -138,37 +137,6 @@
typedef struct
{
size_t size;
- void (*Init)(void);
- tMCA_HANDLE (*Register)(tMCA_REG *p_reg, tMCA_CTRL_CBACK *p_cback);
- void (*Deregister)(tMCA_HANDLE handle);
- tMCA_RESULT (*CreateDep)(tMCA_HANDLE handle, tMCA_DEP *p_dep, tMCA_CS *p_cs);
- tMCA_RESULT (*DeleteDep)(tMCA_HANDLE handle, tMCA_DEP dep);
- tMCA_RESULT (*ConnectReq)(tMCA_HANDLE handle, RawAddress bd_addr,
- uint16_t ctrl_psm,
- uint16_t sec_mask);
- tMCA_RESULT (*DisconnectReq)(tMCA_CL mcl);
- tMCA_RESULT (*CreateMdl)(tMCA_CL mcl, tMCA_DEP dep, uint16_t data_psm,
- uint16_t mdl_id, uint8_t peer_dep_id,
- uint8_t cfg, const tMCA_CHNL_CFG *p_chnl_cfg);
- tMCA_RESULT (*CreateMdlRsp)(tMCA_CL mcl, tMCA_DEP dep,
- uint16_t mdl_id, uint8_t cfg, uint8_t rsp_code,
- const tMCA_CHNL_CFG *p_chnl_cfg);
- tMCA_RESULT (*CloseReq)(tMCA_DL mdl);
- tMCA_RESULT (*ReconnectMdl)(tMCA_CL mcl, tMCA_DEP dep, uint16_t data_psm,
- uint16_t mdl_id, const tMCA_CHNL_CFG *p_chnl_cfg);
- tMCA_RESULT (*ReconnectMdlRsp)(tMCA_CL mcl, tMCA_DEP dep,
- uint16_t mdl_id, uint8_t rsp_code,
- const tMCA_CHNL_CFG *p_chnl_cfg);
- tMCA_RESULT (*DataChnlCfg)(tMCA_CL mcl, const tMCA_CHNL_CFG *p_chnl_cfg);
- tMCA_RESULT (*Abort)(tMCA_CL mcl);
- tMCA_RESULT (*Delete)(tMCA_CL mcl, uint16_t mdl_id);
- tMCA_RESULT (*WriteReq)(tMCA_DL mdl, BT_HDR *p_pkt);
- uint16_t (*GetL2CapChannel) (tMCA_DL mdl);
-}btmcap_interface_t;
-
-typedef struct
-{
- size_t size;
//GATT common APIs (Both client and server)
tGATT_IF (*Register) (bluetooth::Uuid& p_app_uuid128, tGATT_CBACK *p_cb_info);
void (*Deregister) (tGATT_IF gatt_if);
@@ -179,7 +147,9 @@
//GATT Client APIs
tGATT_STATUS (*cConfigureMTU) (uint16_t conn_id, uint16_t mtu);
- tGATT_STATUS (*cDiscover) (uint16_t conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_PARAM *p_param );
+ tGATT_STATUS (*cDiscover) (uint16_t conn_id, tGATT_DISC_TYPE disc_type,
+ uint16_t start_handle, uint16_t end_handle,
+ const bluetooth::Uuid& uuid);
tGATT_STATUS (*cRead) (uint16_t conn_id, tGATT_READ_TYPE type, tGATT_READ_PARAM *p_read);
tGATT_STATUS (*cWrite) (uint16_t conn_id, tGATT_WRITE_TYPE type, tGATT_VALUE *p_write);
tGATT_STATUS (*cExecuteWrite) (uint16_t conn_id, bool is_execute);
@@ -201,7 +171,7 @@
bool (*PairCancel) (RawAddress bd_addr);
void (*SecurityGrant)(RawAddress bd_addr, uint8_t res);
void (*PasskeyReply) (RawAddress bd_addr, uint8_t res, uint32_t passkey);
- bool (*Encrypt) (uint8_t *key, uint8_t key_len, uint8_t *plain_text, uint8_t pt_len, tSMP_ENC *p_out);
+ Octet16 (*Encrypt) (Octet16 key, Octet16 message);
}btsmp_interface_t;
typedef struct
{
diff --git a/system_bt_ext/stack/Android.bp b/system_bt_ext/stack/Android.bp
index 15bd5f0..c317860 100644
--- a/system_bt_ext/stack/Android.bp
+++ b/system_bt_ext/stack/Android.bp
@@ -21,10 +21,12 @@
"vendor/qcom/opensource/commonsys/system/bt/stack/include",
"vendor/qcom/opensource/commonsys/system/bt/stack/btm",
"vendor/qcom/opensource/commonsys/bluetooth_ext/system_bt_ext/bta/include/",
- "vendor/qcom/opensource/commonsys/bluetooth_ext/vhal/include"
+ "vendor/qcom/opensource/commonsys/bluetooth_ext/system_bt_ext/device/include/",
+ "vendor/qcom/opensource/commonsys/bluetooth_ext/vhal/include",
],
srcs: [
"btm/btm_csb.cc",
+ "btm/btm_iot_config.cc",
"hcic/hcivendorcmds.cc",
"a2dp/a2dp_vendor_aptx_tws_encoder.cc",
"a2dp/a2dp_vendor_aptx_tws.cc",
diff --git a/system_bt_ext/stack/btm/btm_iot_config.cc b/system_bt_ext/stack/btm/btm_iot_config.cc
new file mode 100644
index 0000000..75a6ae2
--- /dev/null
+++ b/system_bt_ext/stack/btm/btm_iot_config.cc
@@ -0,0 +1,125 @@
+/******************************************************************************
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#if (BT_IOT_LOGGING_ENABLED == TRUE)
+
+#include "device_iot_config.h"
+#include "btif/include/btif_storage.h"
+#include "btif/include/btif_util.h"
+#include "btm_int_types.h"
+#include "btm_ble_api.h"
+
+
+/*******************************************************************************
+*
+* Function btm_iot_save_remote_properties
+*
+* Description Store remote basic properties to iot conf file
+*
+* Returns void
+*
+*******************************************************************************/
+void btm_iot_save_remote_properties(tACL_CONN* p_acl_cb) {
+ int name_length = 0;
+ char value[1024];
+ BD_NAME bd_name;
+ bt_property_t prop_name;
+ uint32_t cod = 0;
+ tBT_DEVICE_TYPE dev_type;
+ tBLE_ADDR_TYPE addr_type;
+
+ //save remote name to iot conf file
+ if (strlen((const char *)p_acl_cb->remote_name))
+ {
+ name_length = strlen((char *)p_acl_cb->remote_name) > BTM_MAX_REM_BD_NAME_LEN ?
+ BTM_MAX_REM_BD_NAME_LEN : strlen((char *)p_acl_cb->remote_name) + 1;
+ strlcpy(value, (char*)p_acl_cb->remote_name, name_length);
+ device_iot_config_addr_set_str(p_acl_cb->remote_addr,
+ IOT_CONF_KEY_REMOTE_NAME, value);
+ } else {
+ if (BTM_GetRemoteDeviceName(p_acl_cb->remote_addr, bd_name))
+ {
+ device_iot_config_addr_set_str(p_acl_cb->remote_addr,
+ IOT_CONF_KEY_REMOTE_NAME, (char *)bd_name);
+ }
+ }
+
+ //save remote dev class to iot conf file
+ cod = devclass2uint(p_acl_cb->remote_dc);
+ if (cod == 0) {
+ /* Try to retrieve cod from storage */
+ BTIF_STORAGE_FILL_PROPERTY(&prop_name,
+ BT_PROPERTY_CLASS_OF_DEVICE, sizeof(cod), &cod);
+ if (btif_storage_get_remote_device_property(&p_acl_cb->remote_addr, &prop_name)
+ == BT_STATUS_SUCCESS)
+ BTIF_TRACE_DEBUG("%s cod retrieved from storage is 0x%06x", __func__, cod);
+ if (cod == 0) {
+ BTIF_TRACE_DEBUG("%s cod is 0, set as unclassified", __func__);
+ cod = (0x1F) << 8;
+ }
+ }
+ device_iot_config_addr_set_int(p_acl_cb->remote_addr,
+ IOT_CONF_KEY_DEVCLASS, (int)cod);
+
+ BTM_ReadDevInfo(p_acl_cb->remote_addr, &dev_type, &addr_type);
+
+ //save remote dev type to iot conf file
+ device_iot_config_addr_set_int(p_acl_cb->remote_addr,
+ IOT_CONF_KEY_DEVTYPE, (int)dev_type);
+
+ //save remote addr type to iot conf file
+ device_iot_config_addr_set_int(p_acl_cb->remote_addr,
+ IOT_CONF_KEY_ADDRTYPE, (int)addr_type);
+
+ //save default recorded value to iot conf file
+ device_iot_config_addr_set_int(p_acl_cb->remote_addr,
+ IOT_CONF_KEY_RECORDED, IOT_CONF_VAL_RECORDED_DEFAULT);
+}
+
+/*******************************************************************************
+*
+* Function btm_iot_save_remote_versions
+*
+* Description Store remote versions to iot conf file
+*
+* Returns void
+*
+*******************************************************************************/
+void btm_iot_save_remote_versions(tACL_CONN* p_acl_cb) {
+ device_iot_config_addr_set_int(p_acl_cb->remote_addr,
+ IOT_CONF_KEY_MANUFACTURER, p_acl_cb->manufacturer);
+ device_iot_config_addr_set_int(p_acl_cb->remote_addr,
+ IOT_CONF_KEY_LMPVER, p_acl_cb->lmp_version);
+ device_iot_config_addr_set_int(p_acl_cb->remote_addr,
+ IOT_CONF_KEY_LMPSUBVER, p_acl_cb->lmp_subversion);
+}
+
+#endif
diff --git a/vhal/include/hardware/bt_rc_ext.h b/vhal/include/hardware/bt_rc_ext.h
index 5a7f3fc..40e7862 100644
--- a/vhal/include/hardware/bt_rc_ext.h
+++ b/vhal/include/hardware/bt_rc_ext.h
@@ -500,7 +500,7 @@
/* Get folder item list response from TG to CT */
bt_status_t (*get_folder_items_list_rsp)(RawAddress *bd_addr, btrc_status_t rsp_status,
- uint16_t uid_counter, uint8_t num_items, btrc_folder_items_t *p_items);
+ uint16_t uid_counter, uint16_t num_items, btrc_folder_items_t *p_items);
/* Change path response from TG to CT */
bt_status_t (*change_path_rsp)(RawAddress *bd_addr, btrc_status_t rsp_status,
diff --git a/vhal/include/hardware/vendor.h b/vhal/include/hardware/vendor.h
index 00a532d..2b6be6f 100644
--- a/vhal/include/hardware/vendor.h
+++ b/vhal/include/hardware/vendor.h
@@ -75,6 +75,7 @@
USE_SIM_SUPPORT,
MAP_EMAIL_SUPPORT,
PBAP_0102_SUPPORT,
+ MAP_0104_SUPPORT,
END_OF_FEATURE_LIST
} profile_info_t;
@@ -88,6 +89,8 @@
BT_VENDOR_PROPERTY_TWS_PLUS_DEVICE_TYPE = 0x01,
BT_VENDOR_PROPERTY_TWS_PLUS_PEER_ADDR,
BT_VENDOR_PROPERTY_TWS_PLUS_AUTO_CONNECT,
+ BT_VENDOR_PROPERTY_HOST_ADD_ON_FEATURES,
+ BT_VENDOR_PROPERTY_SOC_ADD_ON_FEATURES
} bt_vendor_property_type_t;
typedef enum {
@@ -121,10 +124,19 @@
RawAddress *bd_addr, int num_properties,
bt_vendor_property_t *properties);
+/** Callback to handle SSR */
+typedef void (* ssr_vendor_callback)(void);
+
/** Bluetooth HCI event Callback */
/* Receive any HCI event from controller for raw commands */
typedef void (* hci_event_recv_callback)(uint8_t event_code, uint8_t *buf, uint8_t len);
+/** Callback to notify the remote device vendor properties.
+ */
+typedef void (* adapter_vendor_prop_callback)(bt_status_t status,
+ int num_properties,
+ bt_vendor_property_t *properties);
+
/** BT-Vendor callback structure. */
typedef struct {
/** set to sizeof(BtVendorCallbacks) */
@@ -133,6 +145,8 @@
btvendor_iot_device_broadcast_callback iot_device_broadcast_cb;
remote_dev_prop_callback rmt_dev_prop_cb;
hci_event_recv_callback hci_event_recv_cb;
+ adapter_vendor_prop_callback adapter_vendor_prop_cb;
+ ssr_vendor_callback ssr_vendor_cb;
} btvendor_callbacks_t;
typedef int (*property_set_callout)(const char* key, const char* value);
@@ -185,6 +199,8 @@
/** Sends connectivity network type used by Voip currently to stack */
bt_status_t (*voip_network_type_wifi) (bthf_voip_state_t is_voip_started,
bthf_voip_call_network_type_t is_network_wifi);
+ void (*hciclose)(void);
+
} btvendor_interface_t;