Home | History | Annotate | Download | only in sdp
      1 /******************************************************************************
      2  *
      3  *  Copyright 1999-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 SDP discovery functions
     22  *
     23  ******************************************************************************/
     24 
     25 #include <stdio.h>
     26 #include <stdlib.h>
     27 #include <string.h>
     28 
     29 #include "bt_common.h"
     30 #include "bt_target.h"
     31 #include "btm_api.h"
     32 #include "btu.h"
     33 #include "hcidefs.h"
     34 #include "hcimsgs.h"
     35 #include "l2cdefs.h"
     36 #include "log/log.h"
     37 #include "sdp_api.h"
     38 #include "sdpint.h"
     39 
     40 using bluetooth::Uuid;
     41 
     42 #ifndef SDP_DEBUG_RAW
     43 #define SDP_DEBUG_RAW false
     44 #endif
     45 
     46 /******************************************************************************/
     47 /*            L O C A L    F U N C T I O N     P R O T O T Y P E S            */
     48 /******************************************************************************/
     49 static void process_service_search_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
     50                                        uint8_t* p_reply_end);
     51 static void process_service_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
     52                                      uint8_t* p_reply_end);
     53 static void process_service_search_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
     54                                             uint8_t* p_reply_end);
     55 static uint8_t* save_attr_seq(tCONN_CB* p_ccb, uint8_t* p, uint8_t* p_msg_end);
     56 static tSDP_DISC_REC* add_record(tSDP_DISCOVERY_DB* p_db,
     57                                  const RawAddress& p_bda);
     58 static uint8_t* add_attr(uint8_t* p, tSDP_DISCOVERY_DB* p_db,
     59                          tSDP_DISC_REC* p_rec, uint16_t attr_id,
     60                          tSDP_DISC_ATTR* p_parent_attr, uint8_t nest_level);
     61 
     62 /* Safety check in case we go crazy */
     63 #define MAX_NEST_LEVELS 5
     64 
     65 /*******************************************************************************
     66  *
     67  * Function         sdpu_build_uuid_seq
     68  *
     69  * Description      This function builds a UUID sequence from the list of
     70  *                  passed UUIDs. It is also passed the address of the output
     71  *                  buffer.
     72  *
     73  * Returns          Pointer to next byte in the output buffer.
     74  *
     75  ******************************************************************************/
     76 static uint8_t* sdpu_build_uuid_seq(uint8_t* p_out, uint16_t num_uuids,
     77                                     Uuid* p_uuid_list) {
     78   uint16_t xx;
     79   uint8_t* p_len;
     80 
     81   /* First thing is the data element header */
     82   UINT8_TO_BE_STREAM(p_out, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
     83 
     84   /* Remember where the length goes. Leave space for it. */
     85   p_len = p_out;
     86   p_out += 1;
     87 
     88   /* Now, loop through and put in all the UUID(s) */
     89   for (xx = 0; xx < num_uuids; xx++, p_uuid_list++) {
     90     int len = p_uuid_list->GetShortestRepresentationSize();
     91     if (len == Uuid::kNumBytes16) {
     92       UINT8_TO_BE_STREAM(p_out, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES);
     93       UINT16_TO_BE_STREAM(p_out, p_uuid_list->As16Bit());
     94     } else if (len == Uuid::kNumBytes32) {
     95       UINT8_TO_BE_STREAM(p_out, (UUID_DESC_TYPE << 3) | SIZE_FOUR_BYTES);
     96       UINT32_TO_BE_STREAM(p_out, p_uuid_list->As32Bit());
     97     } else if (len == Uuid::kNumBytes128) {
     98       UINT8_TO_BE_STREAM(p_out, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES);
     99       ARRAY_TO_BE_STREAM(p_out, p_uuid_list->To128BitBE(),
    100                          (int)Uuid::kNumBytes128);
    101     } else {
    102       DCHECK(0) << "SDP: Passed UUID has invalid length " << len;
    103     }
    104   }
    105 
    106   /* Now, put in the length */
    107   xx = (uint16_t)(p_out - p_len - 1);
    108   UINT8_TO_BE_STREAM(p_len, xx);
    109 
    110   return (p_out);
    111 }
    112 
    113 /*******************************************************************************
    114  *
    115  * Function         sdp_snd_service_search_req
    116  *
    117  * Description      Send a service search request to the SDP server.
    118  *
    119  * Returns          void
    120  *
    121  ******************************************************************************/
    122 static void sdp_snd_service_search_req(tCONN_CB* p_ccb, uint8_t cont_len,
    123                                        uint8_t* p_cont) {
    124   uint8_t *p, *p_start, *p_param_len;
    125   BT_HDR* p_cmd = (BT_HDR*)osi_malloc(SDP_DATA_BUF_SIZE);
    126   uint16_t param_len;
    127 
    128   /* Prepare the buffer for sending the packet to L2CAP */
    129   p_cmd->offset = L2CAP_MIN_OFFSET;
    130   p = p_start = (uint8_t*)(p_cmd + 1) + L2CAP_MIN_OFFSET;
    131 
    132   /* Build a service search request packet */
    133   UINT8_TO_BE_STREAM(p, SDP_PDU_SERVICE_SEARCH_REQ);
    134   UINT16_TO_BE_STREAM(p, p_ccb->transaction_id);
    135   p_ccb->transaction_id++;
    136 
    137   /* Skip the length, we need to add it at the end */
    138   p_param_len = p;
    139   p += 2;
    140 
    141 /* Build the UID sequence. */
    142 #if (SDP_BROWSE_PLUS == TRUE)
    143   p = sdpu_build_uuid_seq(p, 1,
    144                           &p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx]);
    145 #else
    146   p = sdpu_build_uuid_seq(p, p_ccb->p_db->num_uuid_filters,
    147                           p_ccb->p_db->uuid_filters);
    148 #endif
    149 
    150   /* Set max service record count */
    151   UINT16_TO_BE_STREAM(p, sdp_cb.max_recs_per_search);
    152 
    153   /* Set continuation state */
    154   UINT8_TO_BE_STREAM(p, cont_len);
    155 
    156   /* if this is not the first request */
    157   if (cont_len && p_cont) {
    158     memcpy(p, p_cont, cont_len);
    159     p += cont_len;
    160   }
    161 
    162   /* Go back and put the parameter length into the buffer */
    163   param_len = (uint16_t)(p - p_param_len - 2);
    164   UINT16_TO_BE_STREAM(p_param_len, param_len);
    165 
    166   p_ccb->disc_state = SDP_DISC_WAIT_HANDLES;
    167 
    168   /* Set the length of the SDP data in the buffer */
    169   p_cmd->len = (uint16_t)(p - p_start);
    170 
    171 #if (SDP_DEBUG_RAW == TRUE)
    172   SDP_TRACE_WARNING("sdp_snd_service_search_req cont_len :%d disc_state:%d",
    173                     cont_len, p_ccb->disc_state);
    174 #endif
    175 
    176   L2CA_DataWrite(p_ccb->connection_id, p_cmd);
    177 
    178   /* Start inactivity timer */
    179   alarm_set_on_mloop(p_ccb->sdp_conn_timer, SDP_INACT_TIMEOUT_MS,
    180                      sdp_conn_timer_timeout, p_ccb);
    181 }
    182 
    183 /*******************************************************************************
    184  *
    185  * Function         sdp_disc_connected
    186  *
    187  * Description      This function is called when an SDP discovery attempt is
    188  *                  connected.
    189  *
    190  * Returns          void
    191  *
    192  ******************************************************************************/
    193 void sdp_disc_connected(tCONN_CB* p_ccb) {
    194   if (p_ccb->is_attr_search) {
    195     p_ccb->disc_state = SDP_DISC_WAIT_SEARCH_ATTR;
    196 
    197     process_service_search_attr_rsp(p_ccb, NULL, NULL);
    198   } else {
    199     /* First step is to get a list of the handles from the server. */
    200     /* We are not searching for a specific attribute, so we will   */
    201     /* first search for the service, then get all attributes of it */
    202 
    203     p_ccb->num_handles = 0;
    204     sdp_snd_service_search_req(p_ccb, 0, NULL);
    205   }
    206 }
    207 
    208 /*******************************************************************************
    209  *
    210  * Function         sdp_disc_server_rsp
    211  *
    212  * Description      This function is called when there is a response from
    213  *                  the server.
    214  *
    215  * Returns          void
    216  *
    217  ******************************************************************************/
    218 void sdp_disc_server_rsp(tCONN_CB* p_ccb, BT_HDR* p_msg) {
    219   uint8_t *p, rsp_pdu;
    220   bool invalid_pdu = true;
    221 
    222 #if (SDP_DEBUG_RAW == TRUE)
    223   SDP_TRACE_WARNING("sdp_disc_server_rsp disc_state:%d", p_ccb->disc_state);
    224 #endif
    225 
    226   /* stop inactivity timer when we receive a response */
    227   alarm_cancel(p_ccb->sdp_conn_timer);
    228 
    229   /* Got a reply!! Check what we got back */
    230   p = (uint8_t*)(p_msg + 1) + p_msg->offset;
    231   uint8_t* p_end = p + p_msg->len;
    232 
    233   BE_STREAM_TO_UINT8(rsp_pdu, p);
    234 
    235   p_msg->len--;
    236 
    237   switch (rsp_pdu) {
    238     case SDP_PDU_SERVICE_SEARCH_RSP:
    239       if (p_ccb->disc_state == SDP_DISC_WAIT_HANDLES) {
    240         process_service_search_rsp(p_ccb, p, p_end);
    241         invalid_pdu = false;
    242       }
    243       break;
    244 
    245     case SDP_PDU_SERVICE_ATTR_RSP:
    246       if (p_ccb->disc_state == SDP_DISC_WAIT_ATTR) {
    247         process_service_attr_rsp(p_ccb, p, p_end);
    248         invalid_pdu = false;
    249       }
    250       break;
    251 
    252     case SDP_PDU_SERVICE_SEARCH_ATTR_RSP:
    253       if (p_ccb->disc_state == SDP_DISC_WAIT_SEARCH_ATTR) {
    254         process_service_search_attr_rsp(p_ccb, p, p_end);
    255         invalid_pdu = false;
    256       }
    257       break;
    258   }
    259 
    260   if (invalid_pdu) {
    261     SDP_TRACE_WARNING("SDP - Unexp. PDU: %d in state: %d", rsp_pdu,
    262                       p_ccb->disc_state);
    263     sdp_disconnect(p_ccb, SDP_GENERIC_ERROR);
    264   }
    265 }
    266 
    267 /******************************************************************************
    268  *
    269  * Function         process_service_search_rsp
    270  *
    271  * Description      This function is called when there is a search response from
    272  *                  the server.
    273  *
    274  * Returns          void
    275  *
    276  ******************************************************************************/
    277 static void process_service_search_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
    278                                        uint8_t* p_reply_end) {
    279   uint16_t xx;
    280   uint16_t total, cur_handles, orig;
    281   uint8_t cont_len;
    282 
    283   /* Skip transaction, and param len */
    284   p_reply += 4;
    285   BE_STREAM_TO_UINT16(total, p_reply);
    286   BE_STREAM_TO_UINT16(cur_handles, p_reply);
    287 
    288   orig = p_ccb->num_handles;
    289   p_ccb->num_handles += cur_handles;
    290   if (p_ccb->num_handles == 0) {
    291     SDP_TRACE_WARNING("SDP - Rcvd ServiceSearchRsp, no matches");
    292     sdp_disconnect(p_ccb, SDP_NO_RECS_MATCH);
    293     return;
    294   }
    295 
    296   /* Save the handles that match. We will can only process a certain number. */
    297   if (total > sdp_cb.max_recs_per_search) total = sdp_cb.max_recs_per_search;
    298   if (p_ccb->num_handles > sdp_cb.max_recs_per_search)
    299     p_ccb->num_handles = sdp_cb.max_recs_per_search;
    300 
    301   for (xx = orig; xx < p_ccb->num_handles; xx++)
    302     BE_STREAM_TO_UINT32(p_ccb->handles[xx], p_reply);
    303 
    304   BE_STREAM_TO_UINT8(cont_len, p_reply);
    305   if (cont_len != 0) {
    306     if (cont_len > SDP_MAX_CONTINUATION_LEN) {
    307       sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
    308       return;
    309     }
    310     if (p_reply + cont_len > p_reply_end) {
    311       android_errorWriteLog(0x534e4554, "68161546");
    312       sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
    313       return;
    314     }
    315     /* stay in the same state */
    316     sdp_snd_service_search_req(p_ccb, cont_len, p_reply);
    317   } else {
    318     /* change state */
    319     p_ccb->disc_state = SDP_DISC_WAIT_ATTR;
    320 
    321     /* Kick off the first attribute request */
    322     process_service_attr_rsp(p_ccb, NULL, NULL);
    323   }
    324 }
    325 
    326 /*******************************************************************************
    327  *
    328  * Function         sdp_copy_raw_data
    329  *
    330  * Description      copy the raw data
    331  *
    332  *
    333  * Returns          void
    334  *
    335  ******************************************************************************/
    336 #if (SDP_RAW_DATA_INCLUDED == TRUE)
    337 static void sdp_copy_raw_data(tCONN_CB* p_ccb, bool offset) {
    338   unsigned int cpy_len, rem_len;
    339   uint32_t list_len;
    340   uint8_t* p;
    341   uint8_t type;
    342 
    343 #if (SDP_DEBUG_RAW == TRUE)
    344   uint8_t num_array[SDP_MAX_LIST_BYTE_COUNT];
    345   uint32_t i;
    346 
    347   for (i = 0; i < p_ccb->list_len; i++) {
    348     snprintf((char*)&num_array[i * 2], sizeof(num_array) - i * 2, "%02X",
    349              (uint8_t)(p_ccb->rsp_list[i]));
    350   }
    351   SDP_TRACE_WARNING("result :%s", num_array);
    352 #endif
    353 
    354   if (p_ccb->p_db->raw_data) {
    355     cpy_len = p_ccb->p_db->raw_size - p_ccb->p_db->raw_used;
    356     list_len = p_ccb->list_len;
    357     p = &p_ccb->rsp_list[0];
    358 
    359     if (offset) {
    360       type = *p++;
    361       p = sdpu_get_len_from_type(p, type, &list_len);
    362     }
    363     if (list_len < cpy_len) {
    364       cpy_len = list_len;
    365     }
    366     rem_len = SDP_MAX_LIST_BYTE_COUNT - (unsigned int)(p - &p_ccb->rsp_list[0]);
    367     if (cpy_len > rem_len) {
    368       SDP_TRACE_WARNING("rem_len :%d less than cpy_len:%d", rem_len, cpy_len);
    369       cpy_len = rem_len;
    370     }
    371     SDP_TRACE_WARNING(
    372         "%s: list_len:%d cpy_len:%d p:%p p_ccb:%p p_db:%p raw_size:%d "
    373         "raw_used:%d raw_data:%p",
    374         __func__, list_len, cpy_len, p, p_ccb, p_ccb->p_db,
    375         p_ccb->p_db->raw_size, p_ccb->p_db->raw_used, p_ccb->p_db->raw_data);
    376     memcpy(&p_ccb->p_db->raw_data[p_ccb->p_db->raw_used], p, cpy_len);
    377     p_ccb->p_db->raw_used += cpy_len;
    378   }
    379 }
    380 #endif
    381 
    382 /*******************************************************************************
    383  *
    384  * Function         process_service_attr_rsp
    385  *
    386  * Description      This function is called when there is a attribute response
    387  *                  from the server.
    388  *
    389  * Returns          void
    390  *
    391  ******************************************************************************/
    392 static void process_service_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
    393                                      uint8_t* p_reply_end) {
    394   uint8_t *p_start, *p_param_len;
    395   uint16_t param_len, list_byte_count;
    396   bool cont_request_needed = false;
    397 
    398 #if (SDP_DEBUG_RAW == TRUE)
    399   SDP_TRACE_WARNING("process_service_attr_rsp raw inc:%d",
    400                     SDP_RAW_DATA_INCLUDED);
    401 #endif
    402   /* If p_reply is NULL, we were called after the records handles were read */
    403   if (p_reply) {
    404 #if (SDP_DEBUG_RAW == TRUE)
    405     SDP_TRACE_WARNING("ID & len: 0x%02x-%02x-%02x-%02x", p_reply[0], p_reply[1],
    406                       p_reply[2], p_reply[3]);
    407 #endif
    408     /* Skip transaction ID and length */
    409     p_reply += 4;
    410 
    411     BE_STREAM_TO_UINT16(list_byte_count, p_reply);
    412 #if (SDP_DEBUG_RAW == TRUE)
    413     SDP_TRACE_WARNING("list_byte_count:%d", list_byte_count);
    414 #endif
    415 
    416     /* Copy the response to the scratchpad. First, a safety check on the length
    417      */
    418     if ((p_ccb->list_len + list_byte_count) > SDP_MAX_LIST_BYTE_COUNT) {
    419       sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE);
    420       return;
    421     }
    422 
    423 #if (SDP_DEBUG_RAW == TRUE)
    424     SDP_TRACE_WARNING("list_len: %d, list_byte_count: %d", p_ccb->list_len,
    425                       list_byte_count);
    426 #endif
    427     if (p_ccb->rsp_list == NULL)
    428       p_ccb->rsp_list = (uint8_t*)osi_malloc(SDP_MAX_LIST_BYTE_COUNT);
    429     memcpy(&p_ccb->rsp_list[p_ccb->list_len], p_reply, list_byte_count);
    430     p_ccb->list_len += list_byte_count;
    431     p_reply += list_byte_count;
    432 #if (SDP_DEBUG_RAW == TRUE)
    433     SDP_TRACE_WARNING("list_len: %d(attr_rsp)", p_ccb->list_len);
    434 
    435     /* Check if we need to request a continuation */
    436     SDP_TRACE_WARNING("*p_reply:%d(%d)", *p_reply, SDP_MAX_CONTINUATION_LEN);
    437 #endif
    438     if (*p_reply) {
    439       if (*p_reply > SDP_MAX_CONTINUATION_LEN) {
    440         sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
    441         return;
    442       }
    443       cont_request_needed = true;
    444     } else {
    445 #if (SDP_RAW_DATA_INCLUDED == TRUE)
    446       SDP_TRACE_WARNING("process_service_attr_rsp");
    447       sdp_copy_raw_data(p_ccb, false);
    448 #endif
    449 
    450       /* Save the response in the database. Stop on any error */
    451       if (!save_attr_seq(p_ccb, &p_ccb->rsp_list[0],
    452                          &p_ccb->rsp_list[p_ccb->list_len])) {
    453         sdp_disconnect(p_ccb, SDP_DB_FULL);
    454         return;
    455       }
    456       p_ccb->list_len = 0;
    457       p_ccb->cur_handle++;
    458     }
    459   }
    460 
    461   /* Now, ask for the next handle. Re-use the buffer we just got. */
    462   if (p_ccb->cur_handle < p_ccb->num_handles) {
    463     BT_HDR* p_msg = (BT_HDR*)osi_malloc(SDP_DATA_BUF_SIZE);
    464     uint8_t* p;
    465 
    466     p_msg->offset = L2CAP_MIN_OFFSET;
    467     p = p_start = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET;
    468 
    469     /* Get all the attributes from the server */
    470     UINT8_TO_BE_STREAM(p, SDP_PDU_SERVICE_ATTR_REQ);
    471     UINT16_TO_BE_STREAM(p, p_ccb->transaction_id);
    472     p_ccb->transaction_id++;
    473 
    474     /* Skip the length, we need to add it at the end */
    475     p_param_len = p;
    476     p += 2;
    477 
    478     UINT32_TO_BE_STREAM(p, p_ccb->handles[p_ccb->cur_handle]);
    479 
    480     /* Max attribute byte count */
    481     UINT16_TO_BE_STREAM(p, sdp_cb.max_attr_list_size);
    482 
    483     /* If no attribute filters, build a wildcard attribute sequence */
    484     if (p_ccb->p_db->num_attr_filters)
    485       p = sdpu_build_attrib_seq(p, p_ccb->p_db->attr_filters,
    486                                 p_ccb->p_db->num_attr_filters);
    487     else
    488       p = sdpu_build_attrib_seq(p, NULL, 0);
    489 
    490     /* Was this a continuation request ? */
    491     if (cont_request_needed) {
    492       if ((p_reply + *p_reply + 1) <= p_reply_end) {
    493         memcpy(p, p_reply, *p_reply + 1);
    494         p += *p_reply + 1;
    495       } else {
    496         android_errorWriteLog(0x534e4554, "68161546");
    497       }
    498     } else
    499       UINT8_TO_BE_STREAM(p, 0);
    500 
    501     /* Go back and put the parameter length into the buffer */
    502     param_len = (uint16_t)(p - p_param_len - 2);
    503     UINT16_TO_BE_STREAM(p_param_len, param_len);
    504 
    505     /* Set the length of the SDP data in the buffer */
    506     p_msg->len = (uint16_t)(p - p_start);
    507 
    508     L2CA_DataWrite(p_ccb->connection_id, p_msg);
    509 
    510     /* Start inactivity timer */
    511     alarm_set_on_mloop(p_ccb->sdp_conn_timer, SDP_INACT_TIMEOUT_MS,
    512                        sdp_conn_timer_timeout, p_ccb);
    513   } else {
    514     sdp_disconnect(p_ccb, SDP_SUCCESS);
    515     return;
    516   }
    517 }
    518 
    519 /*******************************************************************************
    520  *
    521  * Function         process_service_search_attr_rsp
    522  *
    523  * Description      This function is called when there is a search attribute
    524  *                  response from the server.
    525  *
    526  * Returns          void
    527  *
    528  ******************************************************************************/
    529 static void process_service_search_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply,
    530                                             uint8_t* p_reply_end) {
    531   uint8_t *p, *p_start, *p_end, *p_param_len;
    532   uint8_t type;
    533   uint32_t seq_len;
    534   uint16_t param_len, lists_byte_count = 0;
    535   bool cont_request_needed = false;
    536 
    537 #if (SDP_DEBUG_RAW == TRUE)
    538   SDP_TRACE_WARNING("process_service_search_attr_rsp");
    539 #endif
    540   /* If p_reply is NULL, we were called for the initial read */
    541   if (p_reply) {
    542     if (p_reply + 4 /* transaction ID and length */ + sizeof(lists_byte_count) >
    543         p_reply_end) {
    544       android_errorWriteLog(0x534e4554, "79884292");
    545       sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE);
    546       return;
    547     }
    548 
    549 #if (SDP_DEBUG_RAW == TRUE)
    550     SDP_TRACE_WARNING("ID & len: 0x%02x-%02x-%02x-%02x", p_reply[0], p_reply[1],
    551                       p_reply[2], p_reply[3]);
    552 #endif
    553     /* Skip transaction ID and length */
    554     p_reply += 4;
    555 
    556     BE_STREAM_TO_UINT16(lists_byte_count, p_reply);
    557 #if (SDP_DEBUG_RAW == TRUE)
    558     SDP_TRACE_WARNING("lists_byte_count:%d", lists_byte_count);
    559 #endif
    560 
    561     /* Copy the response to the scratchpad. First, a safety check on the length
    562      */
    563     if ((p_ccb->list_len + lists_byte_count) > SDP_MAX_LIST_BYTE_COUNT) {
    564       sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE);
    565       return;
    566     }
    567 
    568 #if (SDP_DEBUG_RAW == TRUE)
    569     SDP_TRACE_WARNING("list_len: %d, list_byte_count: %d", p_ccb->list_len,
    570                       lists_byte_count);
    571 #endif
    572 
    573     if (p_reply + lists_byte_count + 1 /* continuation */ > p_reply_end) {
    574       android_errorWriteLog(0x534e4554, "79884292");
    575       sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE);
    576       return;
    577     }
    578 
    579     if (p_ccb->rsp_list == NULL)
    580       p_ccb->rsp_list = (uint8_t*)osi_malloc(SDP_MAX_LIST_BYTE_COUNT);
    581     memcpy(&p_ccb->rsp_list[p_ccb->list_len], p_reply, lists_byte_count);
    582     p_ccb->list_len += lists_byte_count;
    583     p_reply += lists_byte_count;
    584 #if (SDP_DEBUG_RAW == TRUE)
    585     SDP_TRACE_WARNING("list_len: %d(search_attr_rsp)", p_ccb->list_len);
    586 
    587     /* Check if we need to request a continuation */
    588     SDP_TRACE_WARNING("*p_reply:%d(%d)", *p_reply, SDP_MAX_CONTINUATION_LEN);
    589 #endif
    590     if (*p_reply) {
    591       if (*p_reply > SDP_MAX_CONTINUATION_LEN) {
    592         sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
    593         return;
    594       }
    595 
    596       cont_request_needed = true;
    597     }
    598   }
    599 
    600 #if (SDP_DEBUG_RAW == TRUE)
    601   SDP_TRACE_WARNING("cont_request_needed:%d", cont_request_needed);
    602 #endif
    603   /* If continuation request (or first time request) */
    604   if ((cont_request_needed) || (!p_reply)) {
    605     BT_HDR* p_msg = (BT_HDR*)osi_malloc(SDP_DATA_BUF_SIZE);
    606     uint8_t* p;
    607 
    608     p_msg->offset = L2CAP_MIN_OFFSET;
    609     p = p_start = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET;
    610 
    611     /* Build a service search request packet */
    612     UINT8_TO_BE_STREAM(p, SDP_PDU_SERVICE_SEARCH_ATTR_REQ);
    613     UINT16_TO_BE_STREAM(p, p_ccb->transaction_id);
    614     p_ccb->transaction_id++;
    615 
    616     /* Skip the length, we need to add it at the end */
    617     p_param_len = p;
    618     p += 2;
    619 
    620 /* Build the UID sequence. */
    621 #if (SDP_BROWSE_PLUS == TRUE)
    622     p = sdpu_build_uuid_seq(p, 1,
    623                             &p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx]);
    624 #else
    625     p = sdpu_build_uuid_seq(p, p_ccb->p_db->num_uuid_filters,
    626                             p_ccb->p_db->uuid_filters);
    627 #endif
    628 
    629     /* Max attribute byte count */
    630     UINT16_TO_BE_STREAM(p, sdp_cb.max_attr_list_size);
    631 
    632     /* If no attribute filters, build a wildcard attribute sequence */
    633     if (p_ccb->p_db->num_attr_filters)
    634       p = sdpu_build_attrib_seq(p, p_ccb->p_db->attr_filters,
    635                                 p_ccb->p_db->num_attr_filters);
    636     else
    637       p = sdpu_build_attrib_seq(p, NULL, 0);
    638 
    639     /* No continuation for first request */
    640     if (p_reply) {
    641       if ((p_reply + *p_reply + 1) <= p_reply_end) {
    642         memcpy(p, p_reply, *p_reply + 1);
    643         p += *p_reply + 1;
    644       } else {
    645         android_errorWriteLog(0x534e4554, "68161546");
    646       }
    647     } else
    648       UINT8_TO_BE_STREAM(p, 0);
    649 
    650     /* Go back and put the parameter length into the buffer */
    651     param_len = p - p_param_len - 2;
    652     UINT16_TO_BE_STREAM(p_param_len, param_len);
    653 
    654     /* Set the length of the SDP data in the buffer */
    655     p_msg->len = p - p_start;
    656 
    657     L2CA_DataWrite(p_ccb->connection_id, p_msg);
    658 
    659     /* Start inactivity timer */
    660     alarm_set_on_mloop(p_ccb->sdp_conn_timer, SDP_INACT_TIMEOUT_MS,
    661                        sdp_conn_timer_timeout, p_ccb);
    662 
    663     return;
    664   }
    665 
    666 /*******************************************************************/
    667 /* We now have the full response, which is a sequence of sequences */
    668 /*******************************************************************/
    669 
    670 #if (SDP_RAW_DATA_INCLUDED == TRUE)
    671   SDP_TRACE_WARNING("process_service_search_attr_rsp");
    672   sdp_copy_raw_data(p_ccb, true);
    673 #endif
    674 
    675   p = &p_ccb->rsp_list[0];
    676 
    677   /* The contents is a sequence of attribute sequences */
    678   type = *p++;
    679 
    680   if ((type >> 3) != DATA_ELE_SEQ_DESC_TYPE) {
    681     SDP_TRACE_WARNING("SDP - Wrong type: 0x%02x in attr_rsp", type);
    682     return;
    683   }
    684   p = sdpu_get_len_from_type(p, type, &seq_len);
    685 
    686   p_end = &p_ccb->rsp_list[p_ccb->list_len];
    687 
    688   if ((p + seq_len) != p_end) {
    689     sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
    690     return;
    691   }
    692 
    693   while (p < p_end) {
    694     p = save_attr_seq(p_ccb, p, &p_ccb->rsp_list[p_ccb->list_len]);
    695     if (!p) {
    696       sdp_disconnect(p_ccb, SDP_DB_FULL);
    697       return;
    698     }
    699   }
    700 
    701   /* Since we got everything we need, disconnect the call */
    702   sdp_disconnect(p_ccb, SDP_SUCCESS);
    703 }
    704 
    705 /*******************************************************************************
    706  *
    707  * Function         save_attr_seq
    708  *
    709  * Description      This function is called when there is a response from
    710  *                  the server.
    711  *
    712  * Returns          pointer to next byte or NULL if error
    713  *
    714  ******************************************************************************/
    715 static uint8_t* save_attr_seq(tCONN_CB* p_ccb, uint8_t* p, uint8_t* p_msg_end) {
    716   uint32_t seq_len, attr_len;
    717   uint16_t attr_id;
    718   uint8_t type, *p_seq_end;
    719   tSDP_DISC_REC* p_rec;
    720 
    721   type = *p++;
    722 
    723   if ((type >> 3) != DATA_ELE_SEQ_DESC_TYPE) {
    724     SDP_TRACE_WARNING("SDP - Wrong type: 0x%02x in attr_rsp", type);
    725     return (NULL);
    726   }
    727 
    728   p = sdpu_get_len_from_type(p, type, &seq_len);
    729   if ((p + seq_len) > p_msg_end) {
    730     SDP_TRACE_WARNING("SDP - Bad len in attr_rsp %d", seq_len);
    731     return (NULL);
    732   }
    733 
    734   /* Create a record */
    735   p_rec = add_record(p_ccb->p_db, p_ccb->device_address);
    736   if (!p_rec) {
    737     SDP_TRACE_WARNING("SDP - DB full add_record");
    738     return (NULL);
    739   }
    740 
    741   p_seq_end = p + seq_len;
    742 
    743   while (p < p_seq_end) {
    744     /* First get the attribute ID */
    745     type = *p++;
    746     p = sdpu_get_len_from_type(p, type, &attr_len);
    747     if (((type >> 3) != UINT_DESC_TYPE) || (attr_len != 2)) {
    748       SDP_TRACE_WARNING("SDP - Bad type: 0x%02x or len: %d in attr_rsp", type,
    749                         attr_len);
    750       return (NULL);
    751     }
    752     BE_STREAM_TO_UINT16(attr_id, p);
    753 
    754     /* Now, add the attribute value */
    755     p = add_attr(p, p_ccb->p_db, p_rec, attr_id, NULL, 0);
    756 
    757     if (!p) {
    758       SDP_TRACE_WARNING("SDP - DB full add_attr");
    759       return (NULL);
    760     }
    761   }
    762 
    763   return (p);
    764 }
    765 
    766 /*******************************************************************************
    767  *
    768  * Function         add_record
    769  *
    770  * Description      This function allocates space for a record from the DB.
    771  *
    772  * Returns          pointer to next byte in data stream
    773  *
    774  ******************************************************************************/
    775 tSDP_DISC_REC* add_record(tSDP_DISCOVERY_DB* p_db, const RawAddress& p_bda) {
    776   tSDP_DISC_REC* p_rec;
    777 
    778   /* See if there is enough space in the database */
    779   if (p_db->mem_free < sizeof(tSDP_DISC_REC)) return (NULL);
    780 
    781   p_rec = (tSDP_DISC_REC*)p_db->p_free_mem;
    782   p_db->p_free_mem += sizeof(tSDP_DISC_REC);
    783   p_db->mem_free -= sizeof(tSDP_DISC_REC);
    784 
    785   p_rec->p_first_attr = NULL;
    786   p_rec->p_next_rec = NULL;
    787 
    788   p_rec->remote_bd_addr = p_bda;
    789 
    790   /* Add the record to the end of chain */
    791   if (!p_db->p_first_rec)
    792     p_db->p_first_rec = p_rec;
    793   else {
    794     tSDP_DISC_REC* p_rec1 = p_db->p_first_rec;
    795 
    796     while (p_rec1->p_next_rec) p_rec1 = p_rec1->p_next_rec;
    797 
    798     p_rec1->p_next_rec = p_rec;
    799   }
    800 
    801   return (p_rec);
    802 }
    803 
    804 #define SDP_ADDITIONAL_LIST_MASK 0x80
    805 /*******************************************************************************
    806  *
    807  * Function         add_attr
    808  *
    809  * Description      This function allocates space for an attribute from the DB
    810  *                  and copies the data into it.
    811  *
    812  * Returns          pointer to next byte in data stream
    813  *
    814  ******************************************************************************/
    815 static uint8_t* add_attr(uint8_t* p, tSDP_DISCOVERY_DB* p_db,
    816                          tSDP_DISC_REC* p_rec, uint16_t attr_id,
    817                          tSDP_DISC_ATTR* p_parent_attr, uint8_t nest_level) {
    818   tSDP_DISC_ATTR* p_attr;
    819   uint32_t attr_len;
    820   uint32_t total_len;
    821   uint16_t attr_type;
    822   uint16_t id;
    823   uint8_t type;
    824   uint8_t* p_end;
    825   uint8_t is_additional_list = nest_level & SDP_ADDITIONAL_LIST_MASK;
    826 
    827   nest_level &= ~(SDP_ADDITIONAL_LIST_MASK);
    828 
    829   type = *p++;
    830   p = sdpu_get_len_from_type(p, type, &attr_len);
    831 
    832   attr_len &= SDP_DISC_ATTR_LEN_MASK;
    833   attr_type = (type >> 3) & 0x0f;
    834 
    835   /* See if there is enough space in the database */
    836   if (attr_len > 4)
    837     total_len = attr_len - 4 + (uint16_t)sizeof(tSDP_DISC_ATTR);
    838   else
    839     total_len = sizeof(tSDP_DISC_ATTR);
    840 
    841   /* Ensure it is a multiple of 4 */
    842   total_len = (total_len + 3) & ~3;
    843 
    844   /* See if there is enough space in the database */
    845   if (p_db->mem_free < total_len) return (NULL);
    846 
    847   p_attr = (tSDP_DISC_ATTR*)p_db->p_free_mem;
    848   p_attr->attr_id = attr_id;
    849   p_attr->attr_len_type = (uint16_t)attr_len | (attr_type << 12);
    850   p_attr->p_next_attr = NULL;
    851 
    852   /* Store the attribute value */
    853   switch (attr_type) {
    854     case UINT_DESC_TYPE:
    855       if ((is_additional_list != 0) && (attr_len == 2)) {
    856         BE_STREAM_TO_UINT16(id, p);
    857         if (id != ATTR_ID_PROTOCOL_DESC_LIST)
    858           p -= 2;
    859         else {
    860           /* Reserve the memory for the attribute now, as we need to add
    861            * sub-attributes */
    862           p_db->p_free_mem += sizeof(tSDP_DISC_ATTR);
    863           p_db->mem_free -= sizeof(tSDP_DISC_ATTR);
    864           p_end = p + attr_len;
    865           total_len = 0;
    866 
    867           /* SDP_TRACE_DEBUG ("SDP - attr nest level:%d(list)", nest_level); */
    868           if (nest_level >= MAX_NEST_LEVELS) {
    869             SDP_TRACE_ERROR("SDP - attr nesting too deep");
    870             return (p_end);
    871           }
    872 
    873           /* Now, add the list entry */
    874           p = add_attr(p, p_db, p_rec, ATTR_ID_PROTOCOL_DESC_LIST, p_attr,
    875                        (uint8_t)(nest_level + 1));
    876 
    877           break;
    878         }
    879       }
    880     /* Case falls through */
    881 
    882     case TWO_COMP_INT_DESC_TYPE:
    883       switch (attr_len) {
    884         case 1:
    885           p_attr->attr_value.v.u8 = *p++;
    886           break;
    887         case 2:
    888           BE_STREAM_TO_UINT16(p_attr->attr_value.v.u16, p);
    889           break;
    890         case 4:
    891           BE_STREAM_TO_UINT32(p_attr->attr_value.v.u32, p);
    892           break;
    893         default:
    894           BE_STREAM_TO_ARRAY(p, p_attr->attr_value.v.array, (int32_t)attr_len);
    895           break;
    896       }
    897       break;
    898 
    899     case UUID_DESC_TYPE:
    900       switch (attr_len) {
    901         case 2:
    902           BE_STREAM_TO_UINT16(p_attr->attr_value.v.u16, p);
    903           break;
    904         case 4:
    905           BE_STREAM_TO_UINT32(p_attr->attr_value.v.u32, p);
    906           if (p_attr->attr_value.v.u32 < 0x10000) {
    907             attr_len = 2;
    908             p_attr->attr_len_type = (uint16_t)attr_len | (attr_type << 12);
    909             p_attr->attr_value.v.u16 = (uint16_t)p_attr->attr_value.v.u32;
    910           }
    911           break;
    912         case 16:
    913           /* See if we can compress his UUID down to 16 or 32bit UUIDs */
    914           if (sdpu_is_base_uuid(p)) {
    915             if ((p[0] == 0) && (p[1] == 0)) {
    916               p_attr->attr_len_type =
    917                   (p_attr->attr_len_type & ~SDP_DISC_ATTR_LEN_MASK) | 2;
    918               p += 2;
    919               BE_STREAM_TO_UINT16(p_attr->attr_value.v.u16, p);
    920               p += Uuid::kNumBytes128 - 4;
    921             } else {
    922               p_attr->attr_len_type =
    923                   (p_attr->attr_len_type & ~SDP_DISC_ATTR_LEN_MASK) | 4;
    924               BE_STREAM_TO_UINT32(p_attr->attr_value.v.u32, p);
    925               p += Uuid::kNumBytes128 - 4;
    926             }
    927           } else {
    928             BE_STREAM_TO_ARRAY(p, p_attr->attr_value.v.array,
    929                                (int32_t)attr_len);
    930           }
    931           break;
    932         default:
    933           SDP_TRACE_WARNING("SDP - bad len in UUID attr: %d", attr_len);
    934           return (p + attr_len);
    935       }
    936       break;
    937 
    938     case DATA_ELE_SEQ_DESC_TYPE:
    939     case DATA_ELE_ALT_DESC_TYPE:
    940       /* Reserve the memory for the attribute now, as we need to add
    941        * sub-attributes */
    942       p_db->p_free_mem += sizeof(tSDP_DISC_ATTR);
    943       p_db->mem_free -= sizeof(tSDP_DISC_ATTR);
    944       p_end = p + attr_len;
    945       total_len = 0;
    946 
    947       /* SDP_TRACE_DEBUG ("SDP - attr nest level:%d", nest_level); */
    948       if (nest_level >= MAX_NEST_LEVELS) {
    949         SDP_TRACE_ERROR("SDP - attr nesting too deep");
    950         return (p_end);
    951       }
    952       if (is_additional_list != 0 ||
    953           attr_id == ATTR_ID_ADDITION_PROTO_DESC_LISTS)
    954         nest_level |= SDP_ADDITIONAL_LIST_MASK;
    955       /* SDP_TRACE_DEBUG ("SDP - attr nest level:0x%x(finish)", nest_level); */
    956 
    957       while (p < p_end) {
    958         /* Now, add the list entry */
    959         p = add_attr(p, p_db, p_rec, 0, p_attr, (uint8_t)(nest_level + 1));
    960 
    961         if (!p) return (NULL);
    962       }
    963       break;
    964 
    965     case TEXT_STR_DESC_TYPE:
    966     case URL_DESC_TYPE:
    967       BE_STREAM_TO_ARRAY(p, p_attr->attr_value.v.array, (int32_t)attr_len);
    968       break;
    969 
    970     case BOOLEAN_DESC_TYPE:
    971       switch (attr_len) {
    972         case 1:
    973           p_attr->attr_value.v.u8 = *p++;
    974           break;
    975         default:
    976           SDP_TRACE_WARNING("SDP - bad len in boolean attr: %d", attr_len);
    977           return (p + attr_len);
    978       }
    979       break;
    980 
    981     default: /* switch (attr_type) */
    982       break;
    983   }
    984 
    985   p_db->p_free_mem += total_len;
    986   p_db->mem_free -= total_len;
    987 
    988   /* Add the attribute to the end of the chain */
    989   if (!p_parent_attr) {
    990     if (!p_rec->p_first_attr)
    991       p_rec->p_first_attr = p_attr;
    992     else {
    993       tSDP_DISC_ATTR* p_attr1 = p_rec->p_first_attr;
    994 
    995       while (p_attr1->p_next_attr) p_attr1 = p_attr1->p_next_attr;
    996 
    997       p_attr1->p_next_attr = p_attr;
    998     }
    999   } else {
   1000     if (!p_parent_attr->attr_value.v.p_sub_attr) {
   1001       p_parent_attr->attr_value.v.p_sub_attr = p_attr;
   1002       /* SDP_TRACE_DEBUG ("parent:0x%x(id:%d), ch:0x%x(id:%d)",
   1003           p_parent_attr, p_parent_attr->attr_id, p_attr, p_attr->attr_id); */
   1004     } else {
   1005       tSDP_DISC_ATTR* p_attr1 = p_parent_attr->attr_value.v.p_sub_attr;
   1006       /* SDP_TRACE_DEBUG ("parent:0x%x(id:%d), ch1:0x%x(id:%d)",
   1007           p_parent_attr, p_parent_attr->attr_id, p_attr1, p_attr1->attr_id); */
   1008 
   1009       while (p_attr1->p_next_attr) p_attr1 = p_attr1->p_next_attr;
   1010 
   1011       p_attr1->p_next_attr = p_attr;
   1012       /* SDP_TRACE_DEBUG ("new ch:0x%x(id:%d)", p_attr, p_attr->attr_id); */
   1013     }
   1014   }
   1015 
   1016   return (p);
   1017 }
   1018