1 /******************************************************************************
2  *
3  *  Copyright 2008-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /******************************************************************************
20  *
21  *  this file contains the main GATT server attributes access request
22  *  handling functions.
23  *
24  ******************************************************************************/
25 
26 #include <bluetooth/log.h>
27 
28 #include <deque>
29 #include <map>
30 
31 #include "base/functional/callback.h"
32 #include "btif/include/btif_storage.h"
33 #include "eatt/eatt.h"
34 #include "gatt_api.h"
35 #include "gatt_int.h"
36 #include "internal_include/bt_target.h"
37 #include "stack/include/bt_types.h"
38 #include "stack/include/bt_uuid16.h"
39 #include "stack/include/btm_sec_api.h"
40 #include "types/bluetooth/uuid.h"
41 #include "types/raw_address.h"
42 
43 using base::StringPrintf;
44 using bluetooth::Uuid;
45 using namespace bluetooth;
46 
47 #define BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK 0x01
48 
49 #define BLE_GATT_CL_SUP_FEAT_CACHING_BITMASK 0x01
50 #define BLE_GATT_CL_SUP_FEAT_EATT_BITMASK 0x02
51 #define BLE_GATT_CL_SUP_FEAT_MULTI_NOTIF_BITMASK 0x04
52 
53 #define BLE_GATT_CL_ANDROID_SUP_FEAT \
54   (BLE_GATT_CL_SUP_FEAT_EATT_BITMASK | BLE_GATT_CL_SUP_FEAT_MULTI_NOTIF_BITMASK)
55 
56 using gatt_sr_supported_feat_cb =
57     base::OnceCallback<void(const RawAddress&, uint8_t)>;
58 using gatt_sirk_cb = base::OnceCallback<void(
59     tGATT_STATUS status, const RawAddress&, uint8_t sirk_type, Octet16& sirk)>;
60 
61 typedef struct {
62   uint16_t op_uuid;
63   gatt_sr_supported_feat_cb cb;
64   gatt_sirk_cb sirk_cb;
65 } gatt_op_cb_data;
66 
67 static std::map<uint16_t, std::deque<gatt_op_cb_data>> OngoingOps;
68 
69 static void gatt_request_cback(uint16_t conn_id, uint32_t trans_id,
70                                uint8_t op_code, tGATTS_DATA* p_data);
71 static void gatt_connect_cback(tGATT_IF /* gatt_if */, const RawAddress& bda,
72                                uint16_t conn_id, bool connected,
73                                tGATT_DISCONN_REASON reason,
74                                tBT_TRANSPORT transport);
75 static void gatt_disc_res_cback(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
76                                 tGATT_DISC_RES* p_data);
77 static void gatt_disc_cmpl_cback(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
78                                  tGATT_STATUS status);
79 static void gatt_cl_op_cmpl_cback(uint16_t conn_id, tGATTC_OPTYPE op,
80                                   tGATT_STATUS status,
81                                   tGATT_CL_COMPLETE* p_data);
82 
83 static void gatt_cl_start_config_ccc(tGATT_PROFILE_CLCB* p_clcb);
84 
85 static bool gatt_sr_is_robust_caching_enabled();
86 
87 static bool read_sr_supported_feat_req(
88     uint16_t conn_id, base::OnceCallback<void(const RawAddress&, uint8_t)> cb);
89 static bool read_sr_sirk_req(
90     uint16_t conn_id,
91     base::OnceCallback<void(tGATT_STATUS status, const RawAddress&,
92                             uint8_t sirk_type, Octet16& sirk)>
93         cb);
94 
95 static tGATT_STATUS gatt_sr_read_db_hash(uint16_t conn_id,
96                                          tGATT_VALUE* p_value);
97 static tGATT_STATUS gatt_sr_read_cl_supp_feat(uint16_t conn_id,
98                                               tGATT_VALUE* p_value);
99 static tGATT_STATUS gatt_sr_write_cl_supp_feat(uint16_t conn_id,
100                                                tGATT_WRITE_REQ* p_data);
101 
102 static tGATT_CBACK gatt_profile_cback = {
103     .p_conn_cb = gatt_connect_cback,
104     .p_cmpl_cb = gatt_cl_op_cmpl_cback,
105     .p_disc_res_cb = gatt_disc_res_cback,
106     .p_disc_cmpl_cb = gatt_disc_cmpl_cback,
107     .p_req_cb = gatt_request_cback,
108     .p_enc_cmpl_cb = nullptr,
109     .p_congestion_cb = nullptr,
110     .p_phy_update_cb = nullptr,
111     .p_conn_update_cb = nullptr,
112     .p_subrate_chg_cb = nullptr,
113 };
114 
115 /*******************************************************************************
116  *
117  * Function         gatt_profile_find_conn_id_by_bd_addr
118  *
119  * Description      Find the connection ID by remote address
120  *
121  * Returns          Connection ID
122  *
123  ******************************************************************************/
gatt_profile_find_conn_id_by_bd_addr(const RawAddress & remote_bda)124 uint16_t gatt_profile_find_conn_id_by_bd_addr(const RawAddress& remote_bda) {
125   uint16_t conn_id = GATT_INVALID_CONN_ID;
126   if (!GATT_GetConnIdIfConnected(gatt_cb.gatt_if, remote_bda, &conn_id,
127                                  BT_TRANSPORT_LE)) {
128     log::warn(
129         "Unable to get GATT connection id if connected peer:{} gatt_if:{} "
130         "transport:{}",
131         remote_bda, gatt_cb.gatt_if, bt_transport_text(BT_TRANSPORT_LE));
132   }
133   if (conn_id == GATT_INVALID_CONN_ID) {
134     if (!GATT_GetConnIdIfConnected(gatt_cb.gatt_if, remote_bda, &conn_id,
135                                    BT_TRANSPORT_BR_EDR)) {
136       log::warn(
137           "Unable to get GATT connection id if connected peer:{} gatt_if:{} "
138           "transport:{}",
139           remote_bda, gatt_cb.gatt_if, bt_transport_text(BT_TRANSPORT_BR_EDR));
140     }
141   }
142   return conn_id;
143 }
144 
145 /*******************************************************************************
146  *
147  * Function         gatt_profile_find_clcb_by_conn_id
148  *
149  * Description      find clcb by Connection ID
150  *
151  * Returns          Pointer to the found link conenction control block.
152  *
153  ******************************************************************************/
gatt_profile_find_clcb_by_conn_id(uint16_t conn_id)154 static tGATT_PROFILE_CLCB* gatt_profile_find_clcb_by_conn_id(uint16_t conn_id) {
155   uint8_t i_clcb;
156   tGATT_PROFILE_CLCB* p_clcb = NULL;
157 
158   for (i_clcb = 0, p_clcb = gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS;
159        i_clcb++, p_clcb++) {
160     if (p_clcb->in_use && p_clcb->conn_id == conn_id) return p_clcb;
161   }
162 
163   return NULL;
164 }
165 
166 /*******************************************************************************
167  *
168  * Function         gatt_profile_find_clcb_by_bd_addr
169  *
170  * Description      The function searches all LCBs with macthing bd address.
171  *
172  * Returns          Pointer to the found link conenction control block.
173  *
174  ******************************************************************************/
gatt_profile_find_clcb_by_bd_addr(const RawAddress & bda,tBT_TRANSPORT transport)175 static tGATT_PROFILE_CLCB* gatt_profile_find_clcb_by_bd_addr(
176     const RawAddress& bda, tBT_TRANSPORT transport) {
177   uint8_t i_clcb;
178   tGATT_PROFILE_CLCB* p_clcb = NULL;
179 
180   for (i_clcb = 0, p_clcb = gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS;
181        i_clcb++, p_clcb++) {
182     if (p_clcb->in_use && p_clcb->transport == transport && p_clcb->connected &&
183         p_clcb->bda == bda)
184       return p_clcb;
185   }
186 
187   return NULL;
188 }
189 
190 /*******************************************************************************
191  *
192  * Function         gatt_profile_clcb_alloc
193  *
194  * Description      The function allocates a GATT profile connection link
195  *                  control block
196  *
197  * Returns          NULL if not found. Otherwise pointer to the connection link
198  *                  block.
199  *
200  ******************************************************************************/
gatt_profile_clcb_alloc(uint16_t conn_id,const RawAddress & bda,tBT_TRANSPORT tranport)201 tGATT_PROFILE_CLCB* gatt_profile_clcb_alloc(uint16_t conn_id,
202                                             const RawAddress& bda,
203                                             tBT_TRANSPORT tranport) {
204   uint8_t i_clcb = 0;
205   tGATT_PROFILE_CLCB* p_clcb = NULL;
206 
207   for (i_clcb = 0, p_clcb = gatt_cb.profile_clcb; i_clcb < GATT_MAX_APPS;
208        i_clcb++, p_clcb++) {
209     if (!p_clcb->in_use) {
210       p_clcb->in_use = true;
211       p_clcb->conn_id = conn_id;
212       p_clcb->connected = true;
213       p_clcb->transport = tranport;
214       p_clcb->bda = bda;
215       break;
216     }
217   }
218   if (i_clcb < GATT_MAX_APPS) return p_clcb;
219 
220   return NULL;
221 }
222 
223 /*******************************************************************************
224  *
225  * Function         gatt_profile_clcb_dealloc
226  *
227  * Description      The function deallocates a GATT profile connection link
228  *                  control block
229  *
230  * Returns          void
231  *
232  ******************************************************************************/
gatt_profile_clcb_dealloc(tGATT_PROFILE_CLCB * p_clcb)233 void gatt_profile_clcb_dealloc(tGATT_PROFILE_CLCB* p_clcb) {
234   memset(p_clcb, 0, sizeof(tGATT_PROFILE_CLCB));
235 }
236 
237 /** GAP Attributes Database Request callback */
read_attr_value(uint16_t conn_id,uint16_t handle,tGATT_VALUE * p_value,bool is_long)238 tGATT_STATUS read_attr_value(uint16_t conn_id, uint16_t handle,
239                              tGATT_VALUE* p_value, bool is_long) {
240   uint8_t* p = p_value->value;
241 
242   if (handle == gatt_cb.handle_sr_supported_feat) {
243     /* GATT_UUID_SERVER_SUP_FEAT*/
244     if (is_long) return GATT_NOT_LONG;
245 
246     UINT8_TO_STREAM(p, gatt_cb.gatt_svr_supported_feat_mask);
247     p_value->len = sizeof(gatt_cb.gatt_svr_supported_feat_mask);
248     return GATT_SUCCESS;
249   }
250 
251   if (handle == gatt_cb.handle_cl_supported_feat) {
252     /*GATT_UUID_CLIENT_SUP_FEAT */
253     if (is_long) return GATT_NOT_LONG;
254 
255     return gatt_sr_read_cl_supp_feat(conn_id, p_value);
256   }
257 
258   if (handle == gatt_cb.handle_of_database_hash) {
259     /* GATT_UUID_DATABASE_HASH */
260     if (is_long) return GATT_NOT_LONG;
261 
262     return gatt_sr_read_db_hash(conn_id, p_value);
263   }
264 
265   if (handle == gatt_cb.handle_of_h_r) {
266     /* GATT_UUID_GATT_SRV_CHGD */
267     return GATT_READ_NOT_PERMIT;
268   }
269 
270   return GATT_NOT_FOUND;
271 }
272 
273 /** GAP Attributes Database Read/Read Blob Request process */
proc_read_req(uint16_t conn_id,tGATTS_REQ_TYPE,tGATT_READ_REQ * p_data,tGATTS_RSP * p_rsp)274 tGATT_STATUS proc_read_req(uint16_t conn_id, tGATTS_REQ_TYPE,
275                            tGATT_READ_REQ* p_data, tGATTS_RSP* p_rsp) {
276   if (p_data->is_long) p_rsp->attr_value.offset = p_data->offset;
277 
278   p_rsp->attr_value.handle = p_data->handle;
279 
280   return read_attr_value(conn_id, p_data->handle, &p_rsp->attr_value,
281                          p_data->is_long);
282 }
283 
284 /** GAP ATT server process a write request */
proc_write_req(uint16_t conn_id,tGATTS_REQ_TYPE,tGATT_WRITE_REQ * p_data)285 tGATT_STATUS proc_write_req(uint16_t conn_id, tGATTS_REQ_TYPE,
286                             tGATT_WRITE_REQ* p_data) {
287   uint16_t handle = p_data->handle;
288 
289   /* GATT_UUID_SERVER_SUP_FEAT*/
290   if (handle == gatt_cb.handle_sr_supported_feat) return GATT_WRITE_NOT_PERMIT;
291 
292   /* GATT_UUID_CLIENT_SUP_FEAT*/
293   if (handle == gatt_cb.handle_cl_supported_feat)
294     return gatt_sr_write_cl_supp_feat(conn_id, p_data);
295 
296   /* GATT_UUID_DATABASE_HASH */
297   if (handle == gatt_cb.handle_of_database_hash) return GATT_WRITE_NOT_PERMIT;
298 
299   /* GATT_UUID_GATT_SRV_CHGD */
300   if (handle == gatt_cb.handle_of_h_r) return GATT_WRITE_NOT_PERMIT;
301 
302   return GATT_NOT_FOUND;
303 }
304 
305 /*******************************************************************************
306  *
307  * Function         gatt_request_cback
308  *
309  * Description      GATT profile attribute access request callback.
310  *
311  * Returns          void.
312  *
313  ******************************************************************************/
gatt_request_cback(uint16_t conn_id,uint32_t trans_id,tGATTS_REQ_TYPE type,tGATTS_DATA * p_data)314 static void gatt_request_cback(uint16_t conn_id, uint32_t trans_id,
315                                tGATTS_REQ_TYPE type, tGATTS_DATA* p_data) {
316   tGATT_STATUS status = GATT_INVALID_PDU;
317   tGATTS_RSP rsp_msg;
318   bool rsp_needed = true;
319 
320   memset(&rsp_msg, 0, sizeof(tGATTS_RSP));
321 
322   switch (type) {
323     case GATTS_REQ_TYPE_READ_CHARACTERISTIC:
324     case GATTS_REQ_TYPE_READ_DESCRIPTOR:
325       status = proc_read_req(conn_id, type, &p_data->read_req, &rsp_msg);
326       break;
327 
328     case GATTS_REQ_TYPE_WRITE_CHARACTERISTIC:
329     case GATTS_REQ_TYPE_WRITE_DESCRIPTOR:
330     case GATTS_REQ_TYPE_WRITE_EXEC:
331     case GATT_CMD_WRITE:
332       if (!p_data->write_req.need_rsp) rsp_needed = false;
333 
334       status = proc_write_req(conn_id, type, &p_data->write_req);
335       break;
336 
337     case GATTS_REQ_TYPE_MTU:
338       log::verbose("Get MTU exchange new mtu size: {}", p_data->mtu);
339       rsp_needed = false;
340       break;
341 
342     default:
343       log::verbose("Unknown/unexpected LE GAP ATT request: 0x{:x}", type);
344       break;
345   }
346 
347   if (rsp_needed) {
348     if (GATTS_SendRsp(conn_id, trans_id, status, &rsp_msg) != GATT_SUCCESS) {
349       log::warn("Unable to send GATT server response conn_id:{}", conn_id);
350     }
351   }
352 }
353 
354 /*******************************************************************************
355  *
356  * Function         gatt_connect_cback
357  *
358  * Description      Gatt profile connection callback.
359  *
360  * Returns          void
361  *
362  ******************************************************************************/
gatt_connect_cback(tGATT_IF,const RawAddress & bda,uint16_t conn_id,bool connected,tGATT_DISCONN_REASON,tBT_TRANSPORT transport)363 static void gatt_connect_cback(tGATT_IF /* gatt_if */, const RawAddress& bda,
364                                uint16_t conn_id, bool connected,
365                                tGATT_DISCONN_REASON /* reason */,
366                                tBT_TRANSPORT transport) {
367   log::verbose("from {} connected: {}, conn_id: 0x{:x}", bda, connected,
368                conn_id);
369 
370   // if the device is not trusted, remove data when the link is disconnected
371   if (!connected && !btm_sec_is_a_bonded_dev(bda)) {
372     log::info("remove untrusted client status, bda={}", bda);
373     btif_storage_remove_gatt_cl_supp_feat(bda);
374     btif_storage_remove_gatt_cl_db_hash(bda);
375   }
376 
377   tGATT_PROFILE_CLCB* p_clcb =
378       gatt_profile_find_clcb_by_bd_addr(bda, transport);
379   if (p_clcb == NULL) return;
380 
381   if (connected) {
382     p_clcb->conn_id = conn_id;
383     p_clcb->connected = true;
384 
385     if (p_clcb->ccc_stage == GATT_SVC_CHANGED_CONNECTING) {
386       p_clcb->ccc_stage++;
387       gatt_cl_start_config_ccc(p_clcb);
388     }
389   } else {
390     gatt_profile_clcb_dealloc(p_clcb);
391   }
392 }
393 
394 /*******************************************************************************
395  *
396  * Function         gatt_profile_db_init
397  *
398  * Description      Initializa the GATT profile attribute database.
399  *
400  ******************************************************************************/
gatt_profile_db_init(void)401 void gatt_profile_db_init(void) {
402   /* Fill our internal UUID with a fixed pattern 0x81 */
403   std::array<uint8_t, Uuid::kNumBytes128> tmp;
404   tmp.fill(0x81);
405 
406   OngoingOps.clear();
407 
408   /* Create a GATT profile service */
409   gatt_cb.gatt_if = GATT_Register(Uuid::From128BitBE(tmp), "GattProfileDb",
410                                   &gatt_profile_cback, false);
411   GATT_StartIf(gatt_cb.gatt_if);
412 
413   Uuid service_uuid = Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER);
414 
415   Uuid srv_changed_char_uuid = Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD);
416   Uuid svr_sup_feat_uuid = Uuid::From16Bit(GATT_UUID_SERVER_SUP_FEAT);
417   Uuid cl_sup_feat_uuid = Uuid::From16Bit(GATT_UUID_CLIENT_SUP_FEAT);
418   Uuid database_hash_uuid = Uuid::From16Bit(GATT_UUID_DATABASE_HASH);
419 
420   btgatt_db_element_t service[] = {
421       {
422           .uuid = service_uuid,
423           .type = BTGATT_DB_PRIMARY_SERVICE,
424       },
425       {
426           .uuid = srv_changed_char_uuid,
427           .type = BTGATT_DB_CHARACTERISTIC,
428           .properties = GATT_CHAR_PROP_BIT_INDICATE,
429           .permissions = 0,
430       },
431       {
432           .uuid = svr_sup_feat_uuid,
433           .type = BTGATT_DB_CHARACTERISTIC,
434           .properties = GATT_CHAR_PROP_BIT_READ,
435           .permissions = GATT_PERM_READ,
436       },
437       {
438           .uuid = cl_sup_feat_uuid,
439           .type = BTGATT_DB_CHARACTERISTIC,
440           .properties = GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_WRITE,
441           .permissions = GATT_PERM_READ | GATT_PERM_WRITE,
442       },
443       {
444           .uuid = database_hash_uuid,
445           .type = BTGATT_DB_CHARACTERISTIC,
446           .properties = GATT_CHAR_PROP_BIT_READ,
447           .permissions = GATT_PERM_READ,
448       }};
449 
450   if (GATTS_AddService(gatt_cb.gatt_if, service,
451                        sizeof(service) / sizeof(btgatt_db_element_t)) !=
452       GATT_SERVICE_STARTED) {
453     log::warn("Unable to add GATT server service gatt_if:{}", gatt_cb.gatt_if);
454   }
455 
456   gatt_cb.handle_of_h_r = service[1].attribute_handle;
457   gatt_cb.handle_sr_supported_feat = service[2].attribute_handle;
458   gatt_cb.handle_cl_supported_feat = service[3].attribute_handle;
459   gatt_cb.handle_of_database_hash = service[4].attribute_handle;
460 
461   gatt_cb.gatt_svr_supported_feat_mask |= BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK;
462   gatt_cb.gatt_cl_supported_feat_mask |= BLE_GATT_CL_ANDROID_SUP_FEAT;
463   gatt_cb.gatt_cl_supported_feat_mask |= BLE_GATT_CL_SUP_FEAT_CACHING_BITMASK;
464 
465   log::verbose("gatt_if={} EATT supported", gatt_cb.gatt_if);
466 }
467 
468 /*******************************************************************************
469  *
470  * Function         gatt_disc_res_cback
471  *
472  * Description      Gatt profile discovery result callback
473  *
474  * Returns          void
475  *
476  ******************************************************************************/
gatt_disc_res_cback(uint16_t conn_id,tGATT_DISC_TYPE disc_type,tGATT_DISC_RES * p_data)477 static void gatt_disc_res_cback(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
478                                 tGATT_DISC_RES* p_data) {
479   tGATT_PROFILE_CLCB* p_clcb = gatt_profile_find_clcb_by_conn_id(conn_id);
480 
481   if (p_clcb == NULL) return;
482 
483   switch (disc_type) {
484     case GATT_DISC_SRVC_BY_UUID: /* stage 1 */
485       p_clcb->e_handle = p_data->value.group_value.e_handle;
486       p_clcb->ccc_result++;
487       break;
488 
489     case GATT_DISC_CHAR: /* stage 2 */
490       p_clcb->s_handle = p_data->value.dclr_value.val_handle;
491       p_clcb->ccc_result++;
492       break;
493 
494     case GATT_DISC_CHAR_DSCPT: /* stage 3 */
495       if (p_data->type == Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG)) {
496         p_clcb->s_handle = p_data->handle;
497         p_clcb->ccc_result++;
498       }
499       break;
500 
501     case GATT_DISC_SRVC_ALL:
502     case GATT_DISC_INC_SRVC:
503     case GATT_DISC_MAX:
504       log::error("Illegal discovery item handled");
505       break;
506   }
507 }
508 
509 /*******************************************************************************
510  *
511  * Function         gatt_disc_cmpl_cback
512  *
513  * Description      Gatt profile discovery complete callback
514  *
515  * Returns          void
516  *
517  ******************************************************************************/
gatt_disc_cmpl_cback(uint16_t conn_id,tGATT_DISC_TYPE,tGATT_STATUS status)518 static void gatt_disc_cmpl_cback(uint16_t conn_id,
519                                  tGATT_DISC_TYPE /* disc_type */,
520                                  tGATT_STATUS status) {
521   tGATT_PROFILE_CLCB* p_clcb = gatt_profile_find_clcb_by_conn_id(conn_id);
522   if (p_clcb == NULL) {
523     log::warn("Unable to find gatt profile after discovery complete");
524     return;
525   }
526 
527   if (status != GATT_SUCCESS) {
528     log::warn("Gatt discovery completed with errors status:{}", status);
529     return;
530   }
531   if (p_clcb->ccc_result == 0) {
532     log::warn("Gatt discovery completed but connection was idle id:{}",
533               conn_id);
534     return;
535   }
536 
537   p_clcb->ccc_result = 0;
538   p_clcb->ccc_stage++;
539   gatt_cl_start_config_ccc(p_clcb);
540 }
541 
gatt_svc_read_cl_supp_feat_req(uint16_t conn_id)542 static bool gatt_svc_read_cl_supp_feat_req(uint16_t conn_id) {
543   tGATT_READ_PARAM param;
544 
545   memset(&param, 0, sizeof(tGATT_READ_PARAM));
546 
547   param.service.s_handle = 1;
548   param.service.e_handle = 0xFFFF;
549   param.service.auth_req = 0;
550 
551   param.service.uuid = bluetooth::Uuid::From16Bit(GATT_UUID_CLIENT_SUP_FEAT);
552 
553   tGATT_STATUS status = GATTC_Read(conn_id, GATT_READ_BY_TYPE, &param);
554   if (status != GATT_SUCCESS) {
555     log::error("Read failed. Status: 0x{:x}", static_cast<uint8_t>(status));
556     return false;
557   }
558 
559   gatt_op_cb_data cb_data;
560 
561   cb_data.cb = base::BindOnce(
562       [](const RawAddress& /* bdaddr */, uint8_t /* support */) { return; });
563   cb_data.op_uuid = GATT_UUID_CLIENT_SUP_FEAT;
564   OngoingOps[conn_id].emplace_back(std::move(cb_data));
565 
566   return true;
567 }
568 
gatt_att_write_cl_supp_feat(uint16_t conn_id,uint16_t handle)569 static bool gatt_att_write_cl_supp_feat(uint16_t conn_id, uint16_t handle) {
570   tGATT_VALUE attr;
571 
572   memset(&attr, 0, sizeof(tGATT_VALUE));
573 
574   attr.conn_id = conn_id;
575   attr.handle = handle;
576   attr.len = 1;
577   attr.value[0] = gatt_cb.gatt_cl_supported_feat_mask;
578 
579   tGATT_STATUS status = GATTC_Write(conn_id, GATT_WRITE, &attr);
580   if (status != GATT_SUCCESS) {
581     log::error("Write failed. Status: 0x{:x}", static_cast<uint8_t>(status));
582     return false;
583   }
584 
585   return true;
586 }
587 
588 /*******************************************************************************
589  *
590  * Function         gatt_cl_op_cmpl_cback
591  *
592  * Description      Gatt profile client operation complete callback
593  *
594  * Returns          void
595  *
596  ******************************************************************************/
gatt_cl_op_cmpl_cback(uint16_t conn_id,tGATTC_OPTYPE op,tGATT_STATUS status,tGATT_CL_COMPLETE * p_data)597 static void gatt_cl_op_cmpl_cback(uint16_t conn_id, tGATTC_OPTYPE op,
598                                   tGATT_STATUS status,
599                                   tGATT_CL_COMPLETE* p_data) {
600   auto iter = OngoingOps.find(conn_id);
601 
602   log::verbose("opcode: 0x{:x} status: {} conn id: 0x{:x}",
603                static_cast<uint8_t>(op), status, static_cast<uint8_t>(conn_id));
604 
605   if (op != GATTC_OPTYPE_READ && op != GATTC_OPTYPE_WRITE) {
606     log::verbose("Not interested in opcode {}", op);
607     return;
608   }
609 
610   if (iter == OngoingOps.end() || (iter->second.size() == 0)) {
611     /* If OngoingOps is empty it means we are not interested in the result here.
612      */
613     log::debug("Unexpected read complete");
614     return;
615   }
616 
617   uint16_t cl_op_uuid = iter->second.front().op_uuid;
618 
619   if (op == GATTC_OPTYPE_WRITE) {
620     if (cl_op_uuid == GATT_UUID_GATT_SRV_CHGD) {
621       log::debug("Write response from Service Changed CCC");
622       iter->second.pop_front();
623       /* Read server supported features here supported */
624       read_sr_supported_feat_req(
625           conn_id, base::BindOnce([](const RawAddress& /* bdaddr */,
626                                      uint8_t /* support */) { return; }));
627     } else {
628       log::debug("Not interested in that write response");
629     }
630     return;
631   }
632 
633   /* Handle Read operations */
634   uint8_t* pp = p_data->att_value.value;
635 
636   log::verbose("cl_op_uuid 0x{:x}", cl_op_uuid);
637 
638   switch (cl_op_uuid) {
639     case GATT_UUID_SERVER_SUP_FEAT: {
640       uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
641       tGATT_TCB& tcb = gatt_cb.tcb[tcb_idx];
642 
643       auto operation_callback_data = std::move(iter->second.front());
644       iter->second.pop_front();
645 
646       /* Check if EATT is supported */
647       if (status == GATT_SUCCESS) {
648         STREAM_TO_UINT8(tcb.sr_supp_feat, pp);
649         btif_storage_set_gatt_sr_supp_feat(tcb.peer_bda, tcb.sr_supp_feat);
650       }
651 
652       /* Notify user about the supported features */
653       std::move(operation_callback_data.cb).Run(tcb.peer_bda, tcb.sr_supp_feat);
654 
655       /* If server supports EATT lets try to find handle for the
656        * client supported features characteristic, where we could write
657        * our supported features as a client.
658        */
659       if (tcb.sr_supp_feat & BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK) {
660         gatt_svc_read_cl_supp_feat_req(conn_id);
661       }
662 
663       break;
664     }
665     case GATT_UUID_CSIS_SIRK: {
666       uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
667       tGATT_TCB& tcb = gatt_cb.tcb[tcb_idx];
668 
669       auto operation_callback_data = std::move(iter->second.front());
670       iter->second.pop_front();
671       tcb.gatt_status = status;
672 
673       if (status == GATT_SUCCESS) {
674         STREAM_TO_UINT8(tcb.sirk_type, pp);
675         STREAM_TO_ARRAY(tcb.sirk.data(), pp, 16);
676       }
677 
678       std::move(operation_callback_data.sirk_cb)
679           .Run(tcb.gatt_status, tcb.peer_bda, tcb.sirk_type, tcb.sirk);
680 
681       break;
682     }
683     case GATT_UUID_CLIENT_SUP_FEAT:
684       /*We don't need callback data anymore */
685       iter->second.pop_front();
686 
687       if (status != GATT_SUCCESS) {
688         log::info("Client supported features charcteristic not found");
689         return;
690       }
691 
692       /* Write our client supported features to the remote device */
693       gatt_att_write_cl_supp_feat(conn_id, p_data->att_value.handle);
694       break;
695   }
696 }
697 
698 /*******************************************************************************
699  *
700  * Function         gatt_cl_start_config_ccc
701  *
702  * Description      Gatt profile start configure service change CCC
703  *
704  * Returns          void
705  *
706  ******************************************************************************/
gatt_cl_start_config_ccc(tGATT_PROFILE_CLCB * p_clcb)707 static void gatt_cl_start_config_ccc(tGATT_PROFILE_CLCB* p_clcb) {
708   log::verbose("stage: {}", p_clcb->ccc_stage);
709 
710   switch (p_clcb->ccc_stage) {
711     case GATT_SVC_CHANGED_SERVICE: /* discover GATT service */
712       if (GATTC_Discover(p_clcb->conn_id, GATT_DISC_SRVC_BY_UUID, 0x0001,
713                          0xffff, Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER)) !=
714           GATT_SUCCESS) {
715         log::warn("Unable to discovery GATT client conn_id:{}",
716                   p_clcb->conn_id);
717       }
718       break;
719 
720     case GATT_SVC_CHANGED_CHARACTERISTIC: /* discover service change char */
721       if (GATTC_Discover(
722               p_clcb->conn_id, GATT_DISC_CHAR, 0x0001, p_clcb->e_handle,
723               Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD)) != GATT_SUCCESS) {
724         log::warn("Unable to discovery GATT client conn_id:{}",
725                   p_clcb->conn_id);
726       }
727       break;
728 
729     case GATT_SVC_CHANGED_DESCRIPTOR: /* discover service change ccc */
730       if (GATTC_Discover(p_clcb->conn_id, GATT_DISC_CHAR_DSCPT,
731                          p_clcb->s_handle, p_clcb->e_handle) != GATT_SUCCESS) {
732         log::warn("Unable to discovery GATT client conn_id:{}",
733                   p_clcb->conn_id);
734       }
735       break;
736 
737     case GATT_SVC_CHANGED_CONFIGURE_CCCD: /* write ccc */
738     {
739       tGATT_VALUE ccc_value;
740       memset(&ccc_value, 0, sizeof(tGATT_VALUE));
741       ccc_value.handle = p_clcb->s_handle;
742       ccc_value.len = 2;
743       ccc_value.value[0] = GATT_CLT_CONFIG_INDICATION;
744       if (GATTC_Write(p_clcb->conn_id, GATT_WRITE, &ccc_value) !=
745           GATT_SUCCESS) {
746         log::warn("Unable to write GATT client data conn_id:{}",
747                   p_clcb->conn_id);
748       }
749 
750       gatt_op_cb_data cb_data;
751       cb_data.cb = base::BindOnce([](const RawAddress& /* bdaddr */,
752                                      uint8_t /* support */) { return; });
753       cb_data.op_uuid = GATT_UUID_GATT_SRV_CHGD;
754       OngoingOps[p_clcb->conn_id].emplace_back(std::move(cb_data));
755 
756       break;
757     }
758   }
759 }
760 
761 /*******************************************************************************
762  *
763  * Function         GATT_ConfigServiceChangeCCC
764  *
765  * Description      Configure service change indication on remote device
766  *
767  * Returns          none
768  *
769  ******************************************************************************/
GATT_ConfigServiceChangeCCC(const RawAddress & remote_bda,bool,tBT_TRANSPORT transport)770 void GATT_ConfigServiceChangeCCC(const RawAddress& remote_bda,
771                                  bool /* enable */, tBT_TRANSPORT transport) {
772   tGATT_PROFILE_CLCB* p_clcb =
773       gatt_profile_find_clcb_by_bd_addr(remote_bda, transport);
774 
775   if (p_clcb == NULL)
776     p_clcb = gatt_profile_clcb_alloc(0, remote_bda, transport);
777 
778   if (p_clcb == NULL) return;
779 
780   if (GATT_GetConnIdIfConnected(gatt_cb.gatt_if, remote_bda, &p_clcb->conn_id,
781                                 transport)) {
782     p_clcb->connected = true;
783   } else {
784     log::warn(
785         "Unable to get GATT connection id if connected peer:{} gatt_if:{} "
786         "transport:{}",
787         remote_bda, gatt_cb.gatt_if, bt_transport_text(BT_TRANSPORT_LE));
788   }
789 
790   /* hold the link here */
791   if (!GATT_Connect(gatt_cb.gatt_if, remote_bda, BTM_BLE_DIRECT_CONNECTION,
792                     transport, true)) {
793     log::warn(
794         "Unable to connect GATT client gatt_if:{} peer:{} transport:{} "
795         "connection_tyoe:{} opporunistic:{}",
796         gatt_cb.gatt_if, remote_bda, bt_transport_text(transport),
797         "BTM_BLE_DIRECT_CONNECTION", true);
798   }
799   p_clcb->ccc_stage = GATT_SVC_CHANGED_CONNECTING;
800 
801   if (!p_clcb->connected) {
802     /* wait for connection */
803     return;
804   }
805 
806   p_clcb->ccc_stage++;
807   gatt_cl_start_config_ccc(p_clcb);
808 }
809 
810 /*******************************************************************************
811  *
812  * Function         gatt_cl_init_sr_status
813  *
814  * Description      Restore status for trusted GATT Server device
815  *
816  * Returns          none
817  *
818  ******************************************************************************/
gatt_cl_init_sr_status(tGATT_TCB & tcb)819 void gatt_cl_init_sr_status(tGATT_TCB& tcb) {
820   tcb.sr_supp_feat = btif_storage_get_sr_supp_feat(tcb.peer_bda);
821 
822   if (tcb.sr_supp_feat & BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK)
823     bluetooth::eatt::EattExtension::AddFromStorage(tcb.peer_bda);
824 }
825 
read_sr_supported_feat_req(uint16_t conn_id,base::OnceCallback<void (const RawAddress &,uint8_t)> cb)826 static bool read_sr_supported_feat_req(
827     uint16_t conn_id, base::OnceCallback<void(const RawAddress&, uint8_t)> cb) {
828   tGATT_READ_PARAM param = {};
829 
830   param.service.s_handle = 1;
831   param.service.e_handle = 0xFFFF;
832   param.service.auth_req = 0;
833 
834   param.service.uuid = bluetooth::Uuid::From16Bit(GATT_UUID_SERVER_SUP_FEAT);
835 
836   if (GATTC_Read(conn_id, GATT_READ_BY_TYPE, &param) != GATT_SUCCESS) {
837     log::error("Read GATT Support features GATT_Read Failed");
838     return false;
839   }
840 
841   gatt_op_cb_data cb_data;
842 
843   cb_data.cb = std::move(cb);
844   cb_data.op_uuid = GATT_UUID_SERVER_SUP_FEAT;
845   OngoingOps[conn_id].emplace_back(std::move(cb_data));
846 
847   return true;
848 }
849 
read_sr_sirk_req(uint16_t conn_id,base::OnceCallback<void (tGATT_STATUS status,const RawAddress &,uint8_t sirk_type,Octet16 & sirk)> cb)850 static bool read_sr_sirk_req(
851     uint16_t conn_id,
852     base::OnceCallback<void(tGATT_STATUS status, const RawAddress&,
853                             uint8_t sirk_type, Octet16& sirk)>
854         cb) {
855   tGATT_READ_PARAM param = {};
856 
857   param.service.s_handle = 1;
858   param.service.e_handle = 0xFFFF;
859   param.service.auth_req = 0;
860 
861   param.service.uuid = bluetooth::Uuid::From16Bit(GATT_UUID_CSIS_SIRK);
862 
863   if (GATTC_Read(conn_id, GATT_READ_BY_TYPE, &param) != GATT_SUCCESS) {
864     log::error("Read GATT Support features GATT_Read Failed, conn_id: {}",
865                static_cast<int>(conn_id));
866     return false;
867   }
868 
869   gatt_op_cb_data cb_data;
870 
871   cb_data.sirk_cb = std::move(cb);
872   cb_data.op_uuid = GATT_UUID_CSIS_SIRK;
873   OngoingOps[conn_id].emplace_back(std::move(cb_data));
874 
875   return true;
876 }
877 
878 /*******************************************************************************
879  *
880  * Function         gatt_cl_read_sr_supp_feat_req
881  *
882  * Description      Read remote device supported GATT feature mask.
883  *
884  * Returns          bool
885  *
886  ******************************************************************************/
gatt_cl_read_sr_supp_feat_req(const RawAddress & peer_bda,base::OnceCallback<void (const RawAddress &,uint8_t)> cb)887 bool gatt_cl_read_sr_supp_feat_req(
888     const RawAddress& peer_bda,
889     base::OnceCallback<void(const RawAddress&, uint8_t)> cb) {
890   tGATT_PROFILE_CLCB* p_clcb;
891   uint16_t conn_id;
892 
893   if (!cb) return false;
894 
895   log::verbose("BDA: {} read gatt supported features", peer_bda);
896 
897   if (!GATT_GetConnIdIfConnected(gatt_cb.gatt_if, peer_bda, &conn_id,
898                                  BT_TRANSPORT_LE)) {
899     log::warn(
900         "Unable to get GATT connection id if connected peer:{} gatt_if:{} "
901         "transport:{}",
902         peer_bda, gatt_cb.gatt_if, bt_transport_text(BT_TRANSPORT_LE));
903   }
904 
905   if (conn_id == GATT_INVALID_CONN_ID) return false;
906 
907   p_clcb = gatt_profile_find_clcb_by_conn_id(conn_id);
908   if (!p_clcb) {
909     p_clcb = gatt_profile_clcb_alloc(conn_id, peer_bda, BT_TRANSPORT_LE);
910   }
911 
912   if (!p_clcb) {
913     log::verbose("p_clcb is NULL 0x{:x}", conn_id);
914     return false;
915   }
916 
917   auto it = OngoingOps.find(conn_id);
918   if (it == OngoingOps.end()) {
919     OngoingOps[conn_id] = std::deque<gatt_op_cb_data>();
920   }
921 
922   return read_sr_supported_feat_req(conn_id, std::move(cb));
923 }
924 
925 /*******************************************************************************
926  *
927  * Function         gatt_cl_read_sirk_req
928  *
929  * Description      Read remote SIRK if it's a set member device.
930  *
931  * Returns          bool
932  *
933  ******************************************************************************/
gatt_cl_read_sirk_req(const RawAddress & peer_bda,base::OnceCallback<void (tGATT_STATUS status,const RawAddress &,uint8_t sirk_type,Octet16 & sirk)> cb)934 bool gatt_cl_read_sirk_req(
935     const RawAddress& peer_bda,
936     base::OnceCallback<void(tGATT_STATUS status, const RawAddress&,
937                             uint8_t sirk_type, Octet16& sirk)>
938         cb) {
939   tGATT_PROFILE_CLCB* p_clcb;
940   uint16_t conn_id;
941 
942   if (!cb) return false;
943 
944   log::debug("BDA: {}, read SIRK", peer_bda);
945 
946   if (!GATT_GetConnIdIfConnected(gatt_cb.gatt_if, peer_bda, &conn_id,
947                                  BT_TRANSPORT_LE)) {
948     log::warn(
949         "Unable to get GATT connection id if connected peer:{} gatt_if:{} "
950         "transport:{}",
951         peer_bda, gatt_cb.gatt_if, bt_transport_text(BT_TRANSPORT_LE));
952   }
953   if (conn_id == GATT_INVALID_CONN_ID) return false;
954 
955   p_clcb = gatt_profile_find_clcb_by_conn_id(conn_id);
956   if (!p_clcb) {
957     p_clcb = gatt_profile_clcb_alloc(conn_id, peer_bda, BT_TRANSPORT_LE);
958   }
959 
960   if (!p_clcb) {
961     log::verbose("p_clcb is NULL, conn_id: {:04x}", conn_id);
962     return false;
963   }
964 
965   auto it = OngoingOps.find(conn_id);
966 
967   if (it == OngoingOps.end()) {
968     OngoingOps[conn_id] = std::deque<gatt_op_cb_data>();
969   }
970 
971   return read_sr_sirk_req(conn_id, std::move(cb));
972 }
973 
974 /*******************************************************************************
975  *
976  * Function         gatt_profile_get_eatt_support
977  *
978  * Description      Check if EATT is supported with remote device.
979  *
980  * Returns          if EATT is supported.
981  *
982  ******************************************************************************/
gatt_profile_get_eatt_support(const RawAddress & remote_bda)983 bool gatt_profile_get_eatt_support(const RawAddress& remote_bda) {
984   uint16_t conn_id;
985 
986   log::verbose("BDA: {} read GATT support", remote_bda);
987 
988   if (!GATT_GetConnIdIfConnected(gatt_cb.gatt_if, remote_bda, &conn_id,
989                                  BT_TRANSPORT_LE)) {
990     log::warn(
991         "Unable to get GATT connection id if connected peer:{} gatt_if:{} "
992         "transport:{}",
993         remote_bda, gatt_cb.gatt_if, bt_transport_text(BT_TRANSPORT_LE));
994   }
995 
996   /* This read is important only when connected */
997   if (conn_id == GATT_INVALID_CONN_ID) return false;
998 
999   /* Get tcb info */
1000   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
1001   tGATT_TCB& tcb = gatt_cb.tcb[tcb_idx];
1002   return tcb.sr_supp_feat & BLE_GATT_SVR_SUP_FEAT_EATT_BITMASK;
1003 }
1004 
1005 /*******************************************************************************
1006  *
1007  * Function         gatt_sr_is_robust_caching_enabled
1008  *
1009  * Description      Check if Robust Caching is enabled on server side.
1010  *
1011  * Returns          true if enabled in gd flag, otherwise false
1012  *
1013  ******************************************************************************/
gatt_sr_is_robust_caching_enabled()1014 static bool gatt_sr_is_robust_caching_enabled() {
1015   return bluetooth::common::init_flags::gatt_robust_caching_server_is_enabled();
1016 }
1017 
1018 /*******************************************************************************
1019  *
1020  * Function         gatt_sr_is_cl_robust_caching_supported
1021  *
1022  * Description      Check if Robust Caching is supported for the connection
1023  *
1024  * Returns          true if enabled by client side, otherwise false
1025  *
1026  ******************************************************************************/
gatt_sr_is_cl_robust_caching_supported(tGATT_TCB & tcb)1027 static bool gatt_sr_is_cl_robust_caching_supported(tGATT_TCB& tcb) {
1028   // if robust caching is not enabled, should always return false
1029   if (!gatt_sr_is_robust_caching_enabled()) return false;
1030   return (tcb.cl_supp_feat & BLE_GATT_CL_SUP_FEAT_CACHING_BITMASK);
1031 }
1032 
1033 /*******************************************************************************
1034  *
1035  * Function         gatt_sr_is_cl_multi_variable_len_notif_supported
1036  *
1037  * Description      Check if Multiple Variable Length Notifications
1038  *                  supported for the connection
1039  *
1040  * Returns          true if enabled by client side, otherwise false
1041  *
1042  ******************************************************************************/
gatt_sr_is_cl_multi_variable_len_notif_supported(tGATT_TCB & tcb)1043 bool gatt_sr_is_cl_multi_variable_len_notif_supported(tGATT_TCB& tcb) {
1044   return (tcb.cl_supp_feat & BLE_GATT_CL_SUP_FEAT_MULTI_NOTIF_BITMASK);
1045 }
1046 
1047 /*******************************************************************************
1048  *
1049  * Function         gatt_sr_is_cl_change_aware
1050  *
1051  * Description      Check if the connection is change-aware
1052  *
1053  * Returns          true if change aware, otherwise false
1054  *
1055  ******************************************************************************/
gatt_sr_is_cl_change_aware(tGATT_TCB & tcb)1056 bool gatt_sr_is_cl_change_aware(tGATT_TCB& tcb) {
1057   // if robust caching is not supported, should always return true by default
1058   if (!gatt_sr_is_cl_robust_caching_supported(tcb)) return true;
1059   return tcb.is_robust_cache_change_aware;
1060 }
1061 
1062 /*******************************************************************************
1063  *
1064  * Function         gatt_sr_init_cl_status
1065  *
1066  * Description      Restore status for trusted device
1067  *
1068  * Returns          none
1069  *
1070  ******************************************************************************/
gatt_sr_init_cl_status(tGATT_TCB & tcb)1071 void gatt_sr_init_cl_status(tGATT_TCB& tcb) {
1072   tcb.cl_supp_feat = btif_storage_get_gatt_cl_supp_feat(tcb.peer_bda);
1073   // This is used to reset bit when robust caching is disabled
1074   if (!gatt_sr_is_robust_caching_enabled()) {
1075     tcb.cl_supp_feat &= ~BLE_GATT_CL_SUP_FEAT_CACHING_BITMASK;
1076   }
1077 
1078   if (gatt_sr_is_cl_robust_caching_supported(tcb)) {
1079     Octet16 stored_hash = btif_storage_get_gatt_cl_db_hash(tcb.peer_bda);
1080     tcb.is_robust_cache_change_aware = (stored_hash == gatt_cb.database_hash);
1081   } else {
1082     // set default value for untrusted device
1083     tcb.is_robust_cache_change_aware = true;
1084   }
1085 
1086   log::info("bda={}, cl_supp_feat=0x{:x}, aware={}", tcb.peer_bda,
1087             tcb.cl_supp_feat, tcb.is_robust_cache_change_aware);
1088 }
1089 
1090 /*******************************************************************************
1091  *
1092  * Function         gatt_sr_update_cl_status
1093  *
1094  * Description      Update change-aware status for the remote device
1095  *
1096  * Returns          none
1097  *
1098  ******************************************************************************/
gatt_sr_update_cl_status(tGATT_TCB & tcb,bool chg_aware)1099 void gatt_sr_update_cl_status(tGATT_TCB& tcb, bool chg_aware) {
1100   // if robust caching is not supported, do nothing
1101   if (!gatt_sr_is_cl_robust_caching_supported(tcb)) return;
1102 
1103   // only when client status is changed from change-unaware to change-aware, we
1104   // can then store database hash into btif_storage
1105   if (!tcb.is_robust_cache_change_aware && chg_aware) {
1106     btif_storage_set_gatt_cl_db_hash(tcb.peer_bda, gatt_cb.database_hash);
1107   }
1108 
1109   // only when the status is changed, print the log
1110   if (tcb.is_robust_cache_change_aware != chg_aware) {
1111     log::info("bda={}, chg_aware={}", tcb.peer_bda, chg_aware);
1112   }
1113 
1114   tcb.is_robust_cache_change_aware = chg_aware;
1115 }
1116 
1117 /* handle request for reading database hash */
gatt_sr_read_db_hash(uint16_t conn_id,tGATT_VALUE * p_value)1118 static tGATT_STATUS gatt_sr_read_db_hash(uint16_t conn_id,
1119                                          tGATT_VALUE* p_value) {
1120   log::info("conn_id=0x{:x}", conn_id);
1121 
1122   uint8_t* p = p_value->value;
1123   Octet16& db_hash = gatt_cb.database_hash;
1124   ARRAY_TO_STREAM(p, db_hash.data(), (uint16_t)db_hash.size());
1125   p_value->len = (uint16_t)db_hash.size();
1126 
1127   // Every time when database hash is requested, reset flag.
1128   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
1129   gatt_sr_update_cl_status(gatt_cb.tcb[tcb_idx], /* chg_aware= */ true);
1130   return GATT_SUCCESS;
1131 }
1132 
1133 /* handle request for reading client supported features */
gatt_sr_read_cl_supp_feat(uint16_t conn_id,tGATT_VALUE * p_value)1134 static tGATT_STATUS gatt_sr_read_cl_supp_feat(uint16_t conn_id,
1135                                               tGATT_VALUE* p_value) {
1136   // Get tcb info
1137   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
1138   tGATT_TCB& tcb = gatt_cb.tcb[tcb_idx];
1139 
1140   uint8_t* p = p_value->value;
1141   UINT8_TO_STREAM(p, tcb.cl_supp_feat);
1142   p_value->len = 1;
1143 
1144   return GATT_SUCCESS;
1145 }
1146 
1147 /* handle request for writing client supported features */
gatt_sr_write_cl_supp_feat(uint16_t conn_id,tGATT_WRITE_REQ * p_data)1148 static tGATT_STATUS gatt_sr_write_cl_supp_feat(uint16_t conn_id,
1149                                                tGATT_WRITE_REQ* p_data) {
1150   std::list<uint8_t> tmp;
1151   uint16_t len = p_data->len;
1152   uint8_t value, *p = p_data->value;
1153   // Read all octets into list
1154   while (len > 0) {
1155     STREAM_TO_UINT8(value, p);
1156     tmp.push_back(value);
1157     len--;
1158   }
1159   // Remove trailing zero octets
1160   while (!tmp.empty()) {
1161     if (tmp.back() != 0x00) break;
1162     tmp.pop_back();
1163   }
1164 
1165   // Get tcb info
1166   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
1167   tGATT_TCB& tcb = gatt_cb.tcb[tcb_idx];
1168 
1169   std::list<uint8_t> feature_list;
1170   feature_list.push_back(tcb.cl_supp_feat);
1171 
1172   // If input length is zero, return value_not_allowed
1173   if (tmp.empty()) {
1174     log::info("zero length, conn_id=0x{:x}, bda={}", conn_id, tcb.peer_bda);
1175     return GATT_VALUE_NOT_ALLOWED;
1176   }
1177   // if original length is longer than new one, it must be the bit reset case.
1178   if (feature_list.size() > tmp.size()) {
1179     log::info("shorter length, conn_id=0x{:x}, bda={}", conn_id, tcb.peer_bda);
1180     return GATT_VALUE_NOT_ALLOWED;
1181   }
1182   // new length is longer or equals to the original, need to check bits
1183   // one by one. Here we use bit-wise operation.
1184   // 1. Use XOR to locate the change bit, val_xor is the change bit mask
1185   // 2. Use AND for val_xor and *it_new to get val_and
1186   // 3. If val_and != val_xor, it means the change is from 1 to 0
1187   auto it_old = feature_list.cbegin();
1188   auto it_new = tmp.cbegin();
1189   for (; it_old != feature_list.cend(); it_old++, it_new++) {
1190     uint8_t val_xor = *it_old ^ *it_new;
1191     uint8_t val_and = val_xor & *it_new;
1192     if (val_and != val_xor) {
1193       log::info("bit cannot be reset, conn_id=0x{:x}, bda={}", conn_id,
1194                 tcb.peer_bda);
1195       return GATT_VALUE_NOT_ALLOWED;
1196     }
1197   }
1198 
1199   // get current robust caching status before setting new one
1200   bool curr_caching_state = gatt_sr_is_cl_robust_caching_supported(tcb);
1201 
1202   tcb.cl_supp_feat = tmp.front();
1203   if (!gatt_sr_is_robust_caching_enabled()) {
1204     // remove robust caching bit
1205     tcb.cl_supp_feat &= ~BLE_GATT_CL_SUP_FEAT_CACHING_BITMASK;
1206     log::info("reset robust caching bit, conn_id=0x{:x}, bda={}", conn_id,
1207               tcb.peer_bda);
1208   }
1209   // TODO(hylo): save data as byte array
1210   btif_storage_set_gatt_cl_supp_feat(tcb.peer_bda, tcb.cl_supp_feat);
1211 
1212   // get new robust caching status after setting new one
1213   bool new_caching_state = gatt_sr_is_cl_robust_caching_supported(tcb);
1214   // only when the first time robust caching request, print the log
1215   if (!curr_caching_state && new_caching_state) {
1216     log::info("robust caching enabled by client, conn_id=0x{:x}", conn_id);
1217   }
1218 
1219   return GATT_SUCCESS;
1220 }
1221