1 /*
2  * Copyright 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "bta/dm/bta_dm_gatt_client.h"
18 
19 #include <base/functional/bind.h>
20 #include <base/functional/callback.h>
21 #include <base/strings/stringprintf.h>
22 
23 #include <cstdint>
24 #include <string>
25 #include <vector>
26 
27 #include "bta/include/bta_gatt_api.h"
28 #include "common/strings.h"
29 #include "main/shim/dumpsys.h"
30 #include "stack/btm/btm_int_types.h"
31 #include "types/bluetooth/uuid.h"
32 #include "types/raw_address.h"
33 
34 // TODO(b/369381361) Enfore -Wmissing-prototypes
35 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
36 
37 namespace {
38 TimestampedStringCircularBuffer gatt_history_{50};
39 constexpr char kTimeFormatString[] = "%Y-%m-%d %H:%M:%S";
40 
41 constexpr unsigned MillisPerSecond = 1000;
EpochMillisToString(uint64_t time_ms)42 std::string EpochMillisToString(uint64_t time_ms) {
43   time_t time_sec = time_ms / MillisPerSecond;
44   struct tm tm;
45   localtime_r(&time_sec, &tm);
46   std::string s = bluetooth::common::StringFormatTime(kTimeFormatString, tm);
47   return base::StringPrintf("%s.%03u", s.c_str(),
48                             static_cast<unsigned int>(time_ms % MillisPerSecond));
49 }
50 }  // namespace
51 
52 gatt_interface_t default_gatt_interface = {
53         .BTA_GATTC_CancelOpen =
__anon43cdcbd20202() 54                 [](tGATT_IF client_if, const RawAddress& remote_bda, bool is_direct) {
55                   gatt_history_.Push(base::StringPrintf(
56                           "%-32s bd_addr:%s client_if:%hu is_direct:%c", "GATTC_CancelOpen",
57                           ADDRESS_TO_LOGGABLE_CSTR(remote_bda), static_cast<uint16_t>(client_if),
58                           (is_direct) ? 'T' : 'F'));
59                   BTA_GATTC_CancelOpen(client_if, remote_bda, is_direct);
60                 },
61         .BTA_GATTC_Refresh =
__anon43cdcbd20302() 62                 [](const RawAddress& remote_bda) {
63                   gatt_history_.Push(base::StringPrintf("%-32s bd_addr:%s", "GATTC_Refresh",
64                                                         ADDRESS_TO_LOGGABLE_CSTR(remote_bda)));
65                   BTA_GATTC_Refresh(remote_bda);
66                 },
67         .BTA_GATTC_GetGattDb =
68                 [](tCONN_ID conn_id, uint16_t start_handle, uint16_t end_handle,
__anon43cdcbd20402() 69                    btgatt_db_element_t** db, int* count) {
70                   gatt_history_.Push(base::StringPrintf(
71                           "%-32s conn_id:%hu start_handle:%hu end:handle:%hu", "GATTC_GetGattDb",
72                           static_cast<uint16_t>(conn_id), start_handle, end_handle));
73                   BTA_GATTC_GetGattDb(conn_id, start_handle, end_handle, db, count);
74                 },
75         .BTA_GATTC_AppRegister =
__anon43cdcbd20502() 76                 [](tBTA_GATTC_CBACK* p_client_cb, BtaAppRegisterCallback cb, bool eatt_support) {
77                   gatt_history_.Push(base::StringPrintf("%-32s eatt_support:%c",
78                                                         "GATTC_AppRegister",
79                                                         (eatt_support) ? 'T' : 'F'));
80                   BTA_GATTC_AppRegister(p_client_cb, cb, eatt_support);
81                 },
82         .BTA_GATTC_Close =
__anon43cdcbd20602() 83                 [](tCONN_ID conn_id) {
84                   gatt_history_.Push(base::StringPrintf("%-32s conn_id:%hu", "GATTC_Close",
85                                                         static_cast<uint16_t>(conn_id)));
86                   BTA_GATTC_Close(conn_id);
87                 },
88         .BTA_GATTC_ServiceSearchRequest =
__anon43cdcbd20702() 89                 [](tCONN_ID conn_id, const bluetooth::Uuid* p_srvc_uuid) {
90                   gatt_history_.Push(base::StringPrintf("%-32s conn_id:%hu",
91                                                         "GATTC_ServiceSearchRequest",
92                                                         static_cast<uint16_t>(conn_id)));
93                   if (p_srvc_uuid) {
94                     BTA_GATTC_ServiceSearchRequest(conn_id, *p_srvc_uuid);
95                   } else {
96                     BTA_GATTC_ServiceSearchAllRequest(conn_id);
97                   }
98                 },
99         .BTA_GATTC_Open =
100                 [](tGATT_IF client_if, const RawAddress& remote_bda,
__anon43cdcbd20802() 101                    tBTM_BLE_CONN_TYPE connection_type, bool opportunistic, uint16_t preferred_mtu) {
102                   gatt_history_.Push(base::StringPrintf(
103                           "%-32s bd_addr:%s client_if:%hu type:0x%x opportunistic:%c", "GATTC_Open",
104                           ADDRESS_TO_LOGGABLE_CSTR(remote_bda), static_cast<uint16_t>(client_if),
105                           connection_type, (opportunistic) ? 'T' : 'F'));
106                   BTA_GATTC_Open(client_if, remote_bda, BLE_ADDR_PUBLIC, connection_type,
107                                  BT_TRANSPORT_LE, opportunistic, LE_PHY_1M, preferred_mtu);
108                 },
109 };
110 
111 gatt_interface_t* gatt_interface = &default_gatt_interface;
112 
get_gatt_interface()113 gatt_interface_t& get_gatt_interface() { return *gatt_interface; }
114 
gatt_history_callback(const std::string & entry)115 void gatt_history_callback(const std::string& entry) { gatt_history_.Push(entry); }
116 
117 #define DUMPSYS_TAG "shim::legacy::bta::dm"
DumpsysBtaDmGattClient(int fd)118 void DumpsysBtaDmGattClient(int fd) {
119   auto gatt_history = gatt_history_.Pull();
120   LOG_DUMPSYS(fd, " last %zu gatt history entries", gatt_history.size());
121   for (const auto& it : gatt_history) {
122     LOG_DUMPSYS(fd, "   %s %s", EpochMillisToString(it.timestamp).c_str(), it.entry.c_str());
123   }
124 }
125 #undef DUMPSYS_TAG
126 
set_gatt_interface(const gatt_interface_t & interface)127 void bluetooth::testing::set_gatt_interface(const gatt_interface_t& interface) {
128   *gatt_interface = interface;
129 }
130 
131 namespace bluetooth {
132 namespace legacy {
133 namespace testing {
134 
PullCopyOfGattHistory()135 std::vector<bluetooth::common::TimestampedEntry<std::string>> PullCopyOfGattHistory() {
136   return gatt_history_.Pull();
137 }
138 
139 }  // namespace testing
140 }  // namespace legacy
141 }  // namespace bluetooth
142