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