/*
* Copyright 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bta/dm/bta_dm_gatt_client.h"
#include
#include
#include
#include
#include
#include "bta/include/bta_gatt_api.h"
#include "common/strings.h"
#include "main/shim/dumpsys.h"
#include "stack/btm/btm_int_types.h"
#include "types/bluetooth/uuid.h"
#include "types/raw_address.h"
namespace {
TimestampedStringCircularBuffer gatt_history_{50};
constexpr char kTimeFormatString[] = "%Y-%m-%d %H:%M:%S";
constexpr unsigned MillisPerSecond = 1000;
std::string EpochMillisToString(uint64_t time_ms) {
time_t time_sec = time_ms / MillisPerSecond;
struct tm tm;
localtime_r(&time_sec, &tm);
std::string s = bluetooth::common::StringFormatTime(kTimeFormatString, tm);
return std::format("{}.{:03}", s, time_ms % MillisPerSecond);
}
} // namespace
gatt_interface_t default_gatt_interface = {
.BTA_GATTC_CancelOpen =
[](tGATT_IF client_if, const RawAddress& remote_bda, bool is_direct) {
gatt_history_.Push(std::format("{:<32s} bd_addr:{} client_if:{} is_direct:{:c}",
"GATTC_CancelOpen", remote_bda, client_if,
is_direct ? 'T' : 'F'));
BTA_GATTC_CancelOpen(client_if, remote_bda, is_direct);
},
.BTA_GATTC_Refresh =
[](const RawAddress& remote_bda) {
gatt_history_.Push(
std::format("{:<32s} bd_addr:{}", "GATTC_Refresh", remote_bda));
BTA_GATTC_Refresh(remote_bda);
},
.BTA_GATTC_GetGattDb =
[](tCONN_ID conn_id, uint16_t start_handle, uint16_t end_handle,
btgatt_db_element_t** db, int* count) {
gatt_history_.Push(std::format("{:<32s} conn_id:{} start_handle:{} end:handle:{}",
"GATTC_GetGattDb", conn_id, start_handle,
end_handle));
BTA_GATTC_GetGattDb(conn_id, start_handle, end_handle, db, count);
},
.BTA_GATTC_AppRegister =
[](const std::string& name, tBTA_GATTC_CBACK* p_client_cb,
BtaAppRegisterCallback cb, bool eatt_support) {
gatt_history_.Push(std::format("{:<32s} eatt_support:{:c}", "GATTC_AppRegister",
eatt_support ? 'T' : 'F'));
BTA_GATTC_AppRegister(name, p_client_cb, cb, eatt_support);
},
.BTA_GATTC_Close =
[](tCONN_ID conn_id) {
gatt_history_.Push(std::format("{:<32s} conn_id:{}", "GATTC_Close", conn_id));
BTA_GATTC_Close(conn_id);
},
.BTA_GATTC_ServiceSearchRequest =
[](tCONN_ID conn_id, const bluetooth::Uuid* p_srvc_uuid) {
gatt_history_.Push(
std::format("{:<32s} conn_id:{}", "GATTC_ServiceSearchRequest", conn_id));
if (p_srvc_uuid) {
BTA_GATTC_ServiceSearchRequest(conn_id, *p_srvc_uuid);
} else {
BTA_GATTC_ServiceSearchAllRequest(conn_id);
}
},
.BTA_GATTC_Open =
[](tGATT_IF client_if, const RawAddress& remote_bda,
tBTM_BLE_CONN_TYPE connection_type, bool opportunistic, uint16_t preferred_mtu) {
gatt_history_.Push(std::format(
"{:<32s} bd_addr:{} client_if:{} type:0x{:x} opportunistic:{:c}",
"GATTC_Open", remote_bda, client_if, connection_type,
opportunistic ? 'T' : 'F'));
BTA_GATTC_Open(client_if, remote_bda, BLE_ADDR_PUBLIC, connection_type,
BT_TRANSPORT_LE, opportunistic, LE_PHY_1M, preferred_mtu);
},
};
gatt_interface_t* gatt_interface = &default_gatt_interface;
gatt_interface_t& get_gatt_interface() { return *gatt_interface; }
void gatt_history_callback(const std::string& entry) { gatt_history_.Push(entry); }
#define DUMPSYS_TAG "shim::legacy::bta::dm"
void DumpsysBtaDmGattClient(int fd) {
auto gatt_history = gatt_history_.Pull();
LOG_DUMPSYS(fd, " last %zu gatt history entries", gatt_history.size());
for (const auto& it : gatt_history) {
LOG_DUMPSYS(fd, " %s %s", EpochMillisToString(it.timestamp).c_str(), it.entry.c_str());
}
}
#undef DUMPSYS_TAG
namespace bluetooth::testing {
std::vector> PullCopyOfGattHistory() {
return gatt_history_.Pull();
}
} // namespace bluetooth::testing