1011 of search

本文介绍了一个简单的深度优先搜索算法,用于解决地质勘探中检测地下油田分布的问题。通过将土地划分为网格,并利用DFS算法来确定不同油田沉积物的数量。

Oil Deposits

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other)
Total Submission(s) : 68   Accepted Submission(s) : 31
Problem Description
The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSurvComp works with one large rectangular region of land at a time, and creates a grid that divides the land into numerous square plots. It then analyzes each plot separately, using sensing equipment to determine whether or not the plot contains oil. A plot containing oil is called a pocket. If two pockets are adjacent, then they are part of the same oil deposit. Oil deposits can be quite large and may contain numerous pockets. Your job is to determine how many different oil deposits are contained in a grid. <br>
 

Input
The input file contains one or more grids. Each grid begins with a line containing m and n, the number of rows and columns in the grid, separated by a single space. If m = 0 it signals the end of the input; otherwise 1 <= m <= 100 and 1 <= n <= 100. Following this are m lines of n characters each (not counting the end-of-line characters). Each character corresponds to one plot, and is either `*', representing the absence of oil, or `@', representing an oil pocket.<br>
 

Output
For each grid, output the number of distinct oil deposits. Two different pockets are part of the same oil deposit if they are adjacent horizontally, vertically, or diagonally. An oil deposit will not contain more than 100 pockets.<br>
 

Sample Input
1 1<br>*<br>3 5<br>*@*@*<br>**@**<br>*@*@*<br>1 8<br>@@****@*<br>5 5 <br>****@<br>*@@*@<br>*@**@<br>@@@*@<br>@@**@<br>0 0 <br>
 

Sample Output
0<br>1<br>2<br>2<br>
 

Source
Mid-Central USA 1997
 题目要求:求出油田@连成片组成的区域的个数。
思路:差不多是最简单的dfs了,只需要全部搜索一遍每次搜索过的进行标记即可。
注意事项:每次记得清零。
#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
int dir[9][3];int m,n,x,y,sum;
int J[101][101]={0};
char o[101][101];
void dfs(int a,int b)
{
    int i;
    for(i=1;i<=8;i++)
    {
        if(a<1||b<1||a>m||b>n)continue;
        if(J[a+dir[i][1]][b+dir[i][2]]==1)continue;
        if(o[a+dir[i][1]][b+dir[i][2]]=='*')continue;
        J[a+dir[i][1]][b+dir[i][2]]=1;
        dfs(a+dir[i][1],b+dir[i][2]);
    }
}
int main()
{
    dir[1][1]=-1;dir[1][2]=0;
dir[2][1]=-1;dir[1][2]=-1;
dir[3][1]=0;dir[3][2]=-1;
dir[4][1]=-1;dir[4][2]=1;
dir[5][1]=0;dir[5][2]=1;
dir[6][1]=1;dir[6][2]=1;
dir[7][1]=1;dir[7][2]=0;
dir[8][1]=1;dir[8][2]=-1;
    while(cin>>m>>n&&m)
    {
        memset(J,0,sizeof(J));
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
            cin>>o[i][j];
        sum=0;
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
            if(o[i][j]=='@'&&J[i][j]==0){J[i][j]=1;dfs(i,j);sum++;}
            cout<<sum<<endl;
    }
}

AnnotateLine# Scopes# Navigate#Raw Download current directory 1 /* 2 * Copyright 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "bt_bta_sd" 18 19 #include "bta/dm/bta_dm_device_search.h" 20 21 #include <base/functional/bind.h> 22 #include <base/strings/stringprintf.h> 23 #include <bluetooth/log.h> 24 #include <com_android_bluetooth_flags.h> 25 #include <stddef.h> 26 27 #include <cstdint> 28 #include <string> 29 #include <variant> 30 #include <vector> 31 32 #include "bta/dm/bta_dm_device_search_int.h" 33 #include "bta/dm/bta_dm_disc_legacy.h" 34 #include "bta/include/bta_gatt_api.h" 35 #include "bta/include/bta_sdp_api.h" 36 #include "btif/include/btif_config.h" 37 #include "com_android_bluetooth_flags.h" 38 #include "common/circular_buffer.h" 39 #include "common/init_flags.h" 40 #include "common/strings.h" 41 #include "device/include/interop.h" 42 #include "internal_include/bt_target.h" 43 #include "main/shim/dumpsys.h" 44 #include "os/logging/log_adapter.h" 45 #include "osi/include/allocator.h" 46 #include "stack/btm/btm_int_types.h" // TimestampedStringCircularBuffer 47 #include "stack/btm/neighbor_inquiry.h" 48 #include "stack/include/bt_dev_class.h" 49 #include "stack/include/bt_name.h" 50 #include "stack/include/bt_uuid16.h" 51 #include "stack/include/btm_client_interface.h" 52 #include "stack/include/btm_inq.h" 53 #include "stack/include/btm_log_history.h" 54 #include "stack/include/btm_sec_api.h" // BTM_IsRemoteNameKnown 55 #include "stack/include/gap_api.h" // GAP_BleReadPeerPrefConnParams 56 #include "stack/include/hidh_api.h" 57 #include "stack/include/main_thread.h" 58 #include "stack/include/sdp_status.h" 59 #include "stack/sdp/sdpint.h" // is_sdp_pbap_pce_disabled 60 #include "storage/config_keys.h" 61 #include "types/raw_address.h" 62 //#ifdef OPLUS_BUG_STABILITY 63 //Wanghuaiyin@Connectivity.BT.Basic.7911775, 2024/09/12 64 //Add for address mask output 65 #include "oplus_bt_util.h" 66 //#endif /* OPLUS_BUG_STABILITY */ 67 68 #ifdef OPLUS_FEATURE_BT_HS_INQUIRY 69 #include "btif/include/btif_dm.h" 70 //lvshengyi@CONNECTIVITY.BT.Basic.Inquiry.1678005, 2021/03/09 71 //add for fast inquiry 72 #include "oplus_bt_stack_scan_manager.h" 73 extern tBTM_CB btm_cb; 74 #endif 75 76 #ifdef OPLUS_FEATURE_BT_HS_SDP 77 //lvshengyi@CONNECTIVITY.BT.Basic.SDP.1710878, 2023/10/15 78 #include "oplus_bt_stack_sdp_manager.h" 79 #endif 80 81 //#ifdef OPLUS_BT_STACK_UNIFY 82 #include "oplus_btif_dm.h" 83 #include "oplus_btif_core.h" 84 //#endif /* OPLUS_BT_STACK_UNIFY */ 85 86 #include "common/include/hardware/oplus_vendor.h" /* OPLUS_BT_STACK_UNIFY */ 87 88 #ifdef OPLUS_FEATURE_BT_HS_INQUIRY 89 //zengqiu@CONNECTIVITY.BT.Basic.fast.inquiry 90 #include "oplus_btif_fast_inquiry.h" 91 #include "main/shim/le_scanning_manager.h" 92 93 #ifdef OPLUS_FEATURE_BT_LE_AUDIO 94 #include "oplus_bt_interop.h" 95 #include "btm_ble_adv_data_processor.h" 96 #endif /* OPLUS_FEATURE_BT_LE_AUDIO */ 97 #endif 98 99 using namespace bluetooth; 100 101 namespace { 102 constexpr char kBtmLogTag[] = "DEV_SEARCH"; 103 104 tBTA_DM_SEARCH_CB bta_dm_search_cb; 105 } // namespace 106 107 //#ifdef OPLUS_BUG_COMPATIBILITY 108 //queleiyu@CONNECTIVITY.BT.7544886, 2024/07/22 109 tBTA_DM_SEARCH_CB* bta_dm_get_search_cb() { 110 return &bta_dm_search_cb; 111 } 112 //#endif /* OPLUS_BUG_COMPATIBILITY */ 113 114 static void bta_dm_inq_results_cb(tBTM_INQ_RESULTS* p_inq, const uint8_t* p_eir, 115 uint16_t eir_len); 116 static void bta_dm_inq_cmpl(); 117 static void bta_dm_inq_cmpl_cb(void* p_result); 118 static void bta_dm_search_cmpl(); 119 static void bta_dm_discover_next_device(void); 120 static void bta_dm_remname_cback(const tBTM_REMOTE_DEV_NAME* p); 121 122 static bool bta_dm_read_remote_device_name(const RawAddress& bd_addr, 123 tBT_TRANSPORT transport); 124 static void bta_dm_discover_name(const RawAddress& remote_bd_addr); 125 static void bta_dm_execute_queued_search_request(); 126 static void bta_dm_search_cancel_notify(); 127 static void bta_dm_disable_search(); 128 129 static void bta_dm_search_sm_execute(tBTA_DM_DEV_SEARCH_EVT event, 130 std::unique_ptr<tBTA_DM_SEARCH_MSG> msg); 131 static void bta_dm_observe_results_cb(tBTM_INQ_RESULTS* p_inq, 132 const uint8_t* p_eir, uint16_t eir_len); 133 static void bta_dm_observe_cmpl_cb(void* p_result); 134 135 static void bta_dm_search_set_state(tBTA_DM_DEVICE_SEARCH_STATE state) { 136 bta_dm_search_cb.search_state = state; 137 } 138 static tBTA_DM_DEVICE_SEARCH_STATE bta_dm_search_get_state() { 139 return bta_dm_search_cb.search_state; 140 } 141 142 static void post_search_evt(tBTA_DM_DEV_SEARCH_EVT event, 143 std::unique_ptr<tBTA_DM_SEARCH_MSG> msg) { 144 if (do_in_main_thread(FROM_HERE, base::BindOnce(&bta_dm_search_sm_execute, 145 event, std::move(msg))) != 146 BT_STATUS_SUCCESS) { 147 log::error("post_search_evt failed"); 148 } 149 } 150 151 void bta_dm_disc_disable_search() { 152 if (!com::android::bluetooth::flags:: 153 separate_service_and_device_discovery()) { 154 log::info("no-op when flag is disabled"); 155 return; 156 } 157 bta_dm_disable_search(); 158 } 159 160 /******************************************************************************* 161 * 162 * Function bta_dm_search_start 163 * 164 * Description Starts an inquiry 165 * 166 * 167 * Returns void 168 * 169 ******************************************************************************/ 170 static void bta_dm_search_start(tBTA_DM_API_SEARCH& search) { 171 #ifdef OPLUS_FEATURE_BT_HS_INQUIRY 172 //zengqiu@CONNECTIVITY.BT.Basic.fast.inquiry 173 if(get_fast_act_interface()->enable_inquiry_optimize()) { 174 bluetooth::shim::initAddressCacheExt(); 175 } 176 #endif 177 178 #ifdef OPLUS_FEATURE_BT_HS_INQUIRY 179 //lvshengyi@CONNECTIVITY.BT.Basic.Inquiry.1653415, 2021/03/09 180 if (btm_cb.btm_inq_vars.inq_num == 0) { 181 get_btm_client_interface().db.BTM_ClearInqDb(nullptr); 182 } 183 #else /* OPLUS_FEATURE_BT_HS_INQUIRY */ 184 if (get_btm_client_interface().db.BTM_ClearInqDb(nullptr) != BTM_SUCCESS) { 185 log::warn("Unable to clear inquiry database for device discovery"); 186 } 187 #endif/*OPLUS_FEATURE_BT_HS_INQUIRY*/ 188 /* save search params */ 189 bta_dm_search_cb.p_device_search_cback = search.p_cback; 190 191 const tBTM_STATUS btm_status = 192 BTM_StartInquiry(bta_dm_inq_results_cb, bta_dm_inq_cmpl_cb); 193 switch (btm_status) { 194 case BTM_CMD_STARTED: 195 // Completion callback will be executed when controller inquiry 196 // timer pops or is cancelled by the user 197 break; 198 default: 199 log::warn("Unable to start device discovery search btm_status:{}", 200 btm_status_text(btm_status)); 201 // Not started so completion callback is executed now 202 bta_dm_inq_cmpl(); 203 break; 204 } 205 } 206 207 /******************************************************************************* 208 * 209 * Function bta_dm_search_cancel 210 * 211 * Description Cancels an ongoing search for devices 212 * 213 * 214 * Returns void 215 * 216 ******************************************************************************/ 217 static void bta_dm_search_cancel() { 218 if (BTM_IsInquiryActive()) { 219 BTM_CancelInquiry(); 220 bta_dm_search_cancel_notify(); 221 bta_dm_search_cmpl(); 222 } 223 /* If no Service Search going on then issue cancel remote name in case it is 224 active */ 225 else if (!bta_dm_search_cb.name_discover_done) { 226 if (get_btm_client_interface().peer.BTM_CancelRemoteDeviceName() != 227 BTM_CMD_STARTED) { 228 log::warn("Unable to cancel RNR"); 229 } 230 /* bta_dm_search_cmpl is called when receiving the remote name cancel evt */ 231 if (!com::android::bluetooth::flags:: 232 bta_dm_defer_device_discovery_state_change_until_rnr_complete()) { 233 bta_dm_search_cmpl(); 234 } 235 } else { 236 bta_dm_inq_cmpl(); 237 } 238 } 239 240 /******************************************************************************* 241 * 242 * Function bta_dm_inq_cmpl_cb 243 * 244 * Description Inquiry complete callback from BTM 245 * 246 * Returns void 247 * 248 ******************************************************************************/ 249 static void bta_dm_inq_cmpl_cb(void* /* p_result */) { 250 log::verbose(""); 251 252 bta_dm_inq_cmpl(); 253 } 254 255 /******************************************************************************* 256 * 257 * Function bta_dm_inq_results_cb 258 * 259 * Description Inquiry results callback from BTM 260 * 261 * Returns void 262 * 263 ******************************************************************************/ 264 static void bta_dm_inq_results_cb(tBTM_INQ_RESULTS* p_inq, const uint8_t* p_eir, 265 uint16_t eir_len) { 266 tBTA_DM_SEARCH result; 267 tBTM_INQ_INFO* p_inq_info; 268 uint16_t service_class; 269 270 result.inq_res.bd_addr = p_inq->remote_bd_addr; 271 272 // Pass the original address to GattService#onScanResult 273 result.inq_res.original_bda = p_inq->original_bda; 274 275 result.inq_res.dev_class = p_inq->dev_class; 276 BTM_COD_SERVICE_CLASS(service_class, p_inq->dev_class); 277 result.inq_res.is_limited = 278 (service_class & BTM_COD_SERVICE_LMTD_DISCOVER) ? true : false; 279 result.inq_res.rssi = p_inq->rssi; 280 281 result.inq_res.ble_addr_type = p_inq->ble_addr_type; 282 result.inq_res.inq_result_type = p_inq->inq_result_type; 283 result.inq_res.device_type = p_inq->device_type; 284 result.inq_res.flag = p_inq->flag; 285 result.inq_res.include_rsi = p_inq->include_rsi; 286 result.inq_res.clock_offset = p_inq->clock_offset; 287 288 /* application will parse EIR to find out remote device name */ 289 result.inq_res.p_eir = const_cast<uint8_t*>(p_eir); 290 result.inq_res.eir_len = eir_len; 291 292 result.inq_res.ble_evt_type = p_inq->ble_evt_type; 293 294 p_inq_info = 295 get_btm_client_interface().db.BTM_InqDbRead(p_inq->remote_bd_addr); 296 if (p_inq_info != NULL) { 297 /* initialize remt_name_not_required to false so that we get the name by 298 * default */ 299 result.inq_res.remt_name_not_required = false; 300 } 301 302 if (bta_dm_search_cb.p_device_search_cback) 303 bta_dm_search_cb.p_device_search_cback(BTA_DM_INQ_RES_EVT, &result); 304 305 if (p_inq_info) { 306 /* application indicates if it knows the remote name, inside the callback 307 copy that to the inquiry data base*/ 308 if (result.inq_res.remt_name_not_required) 309 p_inq_info->appl_knows_rem_name = true; 310 } 311 } 312 313 /******************************************************************************* 314 * 315 * Function bta_dm_remname_cback 316 * 317 * Description Remote name complete call back from BTM 318 * 319 * Returns void 320 * 321 ******************************************************************************/ 322 static void bta_dm_remname_cback(const tBTM_REMOTE_DEV_NAME* p_remote_name) { 323 log::assert_that(p_remote_name != nullptr, 324 "assert failed: p_remote_name != nullptr"); 325 326 log::info( 327 "Remote name request complete peer:{} btm_status:{} hci_status:{} " 328 "name[0]:{:c} length:{}", 329 p_remote_name->bd_addr, btm_status_text(p_remote_name->status), 330 hci_error_code_text(p_remote_name->hci_status), 331 p_remote_name->remote_bd_name[0], 332 strnlen((const char*)p_remote_name->remote_bd_name, BD_NAME_LEN)); 333 334 if (bta_dm_search_cb.peer_bdaddr != p_remote_name->bd_addr) { 335 // if we got a different response, maybe ignore it 336 // we will have made a request directly from BTM_ReadRemoteDeviceName so we 337 // expect a dedicated response for us 338 if (p_remote_name->hci_status == HCI_ERR_CONNECTION_EXISTS) { 339 log::info( 340 "Assume command failed due to disconnection hci_status:{} peer:{}", 341 hci_error_code_text(p_remote_name->hci_status), 342 p_remote_name->bd_addr); 343 } else { 344 log::info( 345 "Ignored remote name response for the wrong address exp:{} act:{}", 346 bta_dm_search_cb.peer_bdaddr, p_remote_name->bd_addr); 347 return; 348 } 349 } 350 351 /* remote name discovery is done but it could be failed */ 352 bta_dm_search_cb.name_discover_done = true; 353 bd_name_copy(bta_dm_search_cb.peer_name, p_remote_name->remote_bd_name); 354 355 auto msg = std::make_unique<tBTA_DM_SEARCH_MSG>(tBTA_DM_REMOTE_NAME{}); 356 auto& rmt_name_msg = std::get<tBTA_DM_REMOTE_NAME>(*msg); 357 rmt_name_msg.bd_addr = bta_dm_search_cb.peer_bdaddr; 358 rmt_name_msg.hci_status = p_remote_name->hci_status; 359 bd_name_copy(rmt_name_msg.bd_name, p_remote_name->remote_bd_name); 360 361 post_search_evt(BTA_DM_REMT_NAME_EVT, std::move(msg)); 362 } 363 364 /******************************************************************************* 365 * 366 * Function bta_dm_read_remote_device_name 367 * 368 * Description Initiate to get remote device name 369 * 370 * Returns true if started to get remote name 371 * 372 ******************************************************************************/ 373 static bool bta_dm_read_remote_device_name(const RawAddress& bd_addr, 374 tBT_TRANSPORT transport) { 375 tBTM_STATUS btm_status; 376 377 log::verbose(""); 378 379 bta_dm_search_cb.peer_bdaddr = bd_addr; 380 bta_dm_search_cb.peer_name[0] = 0; 381 382 btm_status = get_btm_client_interface().peer.BTM_ReadRemoteDeviceName( 383 bta_dm_search_cb.peer_bdaddr, bta_dm_remname_cback, transport); 384 385 if (btm_status == BTM_CMD_STARTED) { 386 log::verbose("BTM_ReadRemoteDeviceName is started"); 387 388 return (true); 389 } else if (btm_status == BTM_BUSY) { 390 log::verbose("BTM_ReadRemoteDeviceName is busy"); 391 392 return (true); 393 } else { 394 log::warn("BTM_ReadRemoteDeviceName returns 0x{:02X}", btm_status); 395 396 return (false); 397 } 398 } 399 400 /******************************************************************************* 401 * 402 * Function bta_dm_inq_cmpl 403 * 404 * Description Process the inquiry complete event from BTM 405 * 406 * Returns void 407 * 408 ******************************************************************************/ 409 static void bta_dm_inq_cmpl() { 410 if (bta_dm_search_get_state() == BTA_DM_SEARCH_CANCELLING) { 411 bta_dm_search_set_state(BTA_DM_SEARCH_IDLE); 412 bta_dm_execute_queued_search_request(); 413 return; 414 } 415 416 if (bta_dm_search_get_state() != BTA_DM_SEARCH_ACTIVE) { 417 return; 418 } 419 420 log::verbose("bta_dm_inq_cmpl"); 421 422 bta_dm_search_cb.p_btm_inq_info = 423 get_btm_client_interface().db.BTM_InqDbFirst(); 424 if (bta_dm_search_cb.p_btm_inq_info != NULL) { 425 /* start name discovery from the first device on inquiry result 426 */ 427 bta_dm_search_cb.name_discover_done = false; 428 bta_dm_search_cb.peer_name[0] = 0; 429 bta_dm_discover_name( 430 bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr); 431 } else { 432 bta_dm_search_cmpl(); 433 } 434 } 435 436 static void bta_dm_remote_name_cmpl( 437 const tBTA_DM_REMOTE_NAME& remote_name_msg) { 438 BTM_LogHistory(kBtmLogTag, remote_name_msg.bd_addr, "Remote name completed", 439 base::StringPrintf( 440 "status:%s state:%s name:\"%s\"", 441 hci_status_code_text(remote_name_msg.hci_status).c_str(), 442 bta_dm_state_text(bta_dm_search_get_state()).c_str(), 443 PRIVATE_NAME(remote_name_msg.bd_name))); 444 445 tBTM_INQ_INFO* p_btm_inq_info = 446 get_btm_client_interface().db.BTM_InqDbRead(remote_name_msg.bd_addr); 447 if (!bd_name_is_empty(remote_name_msg.bd_name) && p_btm_inq_info) { 448 #ifdef OPLUS_FEATURE_BT_HS_INQUIRY 449 //lvshengyi@CONNECTIVITY.BT.Basic.Inquiry.1653415, 2021/03/09 450 //If the Bluetooth device used as RNR has no name before, the address and name information of the device 451 //will be cached to the local file 452 std::string namestr((char*)remote_name_msg.bd_name); 453 log::debug("bta_dm_rmt_name: {},inq_num: {}", 454 obfuscate_name_string(namestr), 455 btm_cb.btm_inq_vars.inq_num); 456 oplus_save_rnr_info_to_file(remote_name_msg.bd_addr,(char*)remote_name_msg.bd_name, 457 bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name); 458 #endif/*OPLUS_FEATURE_BT_HS_INQUIRY*/ 459 p_btm_inq_info->appl_knows_rem_name = true; 460 } 461 462 // Callback with this property 463 if (bta_dm_search_cb.p_device_search_cback != nullptr) { 464 tBTA_DM_SEARCH search_data = { 465 .name_res = {.bd_addr = remote_name_msg.bd_addr, .bd_name = {}}, 466 }; 467 if (remote_name_msg.hci_status == HCI_SUCCESS) { 468 bd_name_copy(search_data.name_res.bd_name, remote_name_msg.bd_name); 469 } 470 bta_dm_search_cb.p_device_search_cback(BTA_DM_NAME_READ_EVT, &search_data); 471 } else { 472 log::warn("Received remote name complete without callback"); 473 } 474 475 switch (bta_dm_search_get_state()) { 476 case BTA_DM_SEARCH_ACTIVE: 477 bta_dm_discover_name(bta_dm_search_cb.peer_bdaddr); 478 break; 479 case BTA_DM_SEARCH_IDLE: 480 case BTA_DM_SEARCH_CANCELLING: 481 log::warn("Received remote name request in state:{}", 482 bta_dm_state_text(bta_dm_search_get_state())); 483 break; 484 } 485 } 486 487 static void bta_dm_search_cmpl() { 488 bta_dm_search_set_state(BTA_DM_SEARCH_IDLE); 489 490 if (bta_dm_search_cb.p_device_search_cback) { 491 bta_dm_search_cb.p_device_search_cback(BTA_DM_DISC_CMPL_EVT, nullptr); 492 } 493 494 bta_dm_execute_queued_search_request(); 495 } 496 497 static void bta_dm_execute_queued_search_request() { 498 if (!bta_dm_search_cb.p_pending_search) return; 499 500 log::info("Start pending search"); 501 post_search_evt(BTA_DM_API_SEARCH_EVT, 502 std::move(bta_dm_search_cb.p_pending_search)); 503 bta_dm_search_cb.p_pending_search.reset(); 504 } 505 506 /******************************************************************************* 507 * 508 * Function bta_dm_search_clear_queue 509 * 510 * Description Clears the queue if API search cancel is called 511 * 512 * Returns void 513 * 514 ******************************************************************************/ 515 static void bta_dm_search_clear_queue() { 516 bta_dm_search_cb.p_pending_search.reset(); 517 } 518 519 /******************************************************************************* 520 * 521 * Function bta_dm_search_cancel_notify 522 * 523 * Description Notify application that search has been cancelled 524 * 525 * Returns void 526 * 527 ******************************************************************************/ 528 static void bta_dm_search_cancel_notify() { 529 if (bta_dm_search_cb.p_device_search_cback) { 530 bta_dm_search_cb.p_device_search_cback(BTA_DM_SEARCH_CANCEL_CMPL_EVT, NULL); 531 } 532 switch (bta_dm_search_get_state()) { 533 case BTA_DM_SEARCH_ACTIVE: 534 case BTA_DM_SEARCH_CANCELLING: 535 if (!bta_dm_search_cb.name_discover_done) { 536 if (get_btm_client_interface().peer.BTM_CancelRemoteDeviceName() != 537 BTM_CMD_STARTED) { 538 log::warn("Unable to cancel RNR"); 539 } 540 } 541 break; 542 case BTA_DM_SEARCH_IDLE: 543 // Nothing to do 544 break; 545 } 546 } 547 548 /******************************************************************************* 549 * 550 * Function bta_dm_discover_next_device 551 * 552 * Description Starts discovery on the next device in Inquiry data base 553 * 554 * Returns void 555 * 556 ******************************************************************************/ 557 static void bta_dm_discover_next_device(void) { 558 log::verbose("bta_dm_discover_next_device"); 559 560 /* searching next device on inquiry result */ 561 bta_dm_search_cb.p_btm_inq_info = get_btm_client_interface().db.BTM_InqDbNext( 562 bta_dm_search_cb.p_btm_inq_info); 563 if (bta_dm_search_cb.p_btm_inq_info != NULL) { 564 bta_dm_search_cb.name_discover_done = false; 565 bta_dm_search_cb.peer_name[0] = 0; 566 bta_dm_discover_name( 567 bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr); 568 } else { 569 post_search_evt(BTA_DM_SEARCH_CMPL_EVT, nullptr); 570 } 571 } 572 573 /*TODO: this function is duplicated, make it common ?*/ 574 static tBT_TRANSPORT bta_dm_determine_discovery_transport( 575 const RawAddress& remote_bd_addr) { 576 tBT_DEVICE_TYPE dev_type; 577 tBLE_ADDR_TYPE addr_type; 578 579 get_btm_client_interface().peer.BTM_ReadDevInfo(remote_bd_addr, &dev_type, 580 &addr_type); 581 if (dev_type == BT_DEVICE_TYPE_BLE || addr_type == BLE_ADDR_RANDOM) { 582 return BT_TRANSPORT_LE; 583 } else if (dev_type == BT_DEVICE_TYPE_DUMO) { 584 if (get_btm_client_interface().peer.BTM_IsAclConnectionUp( 585 remote_bd_addr, BT_TRANSPORT_BR_EDR)) { 586 return BT_TRANSPORT_BR_EDR; 587 } else if (get_btm_client_interface().peer.BTM_IsAclConnectionUp( 588 remote_bd_addr, BT_TRANSPORT_LE)) { 589 return BT_TRANSPORT_LE; 590 } 591 } 592 return BT_TRANSPORT_BR_EDR; 593 } 594 595 static void bta_dm_discover_name(const RawAddress& remote_bd_addr) { 596 const tBT_TRANSPORT transport = 597 bta_dm_determine_discovery_transport(remote_bd_addr); 598 599 log::verbose("BDA: {}", remote_bd_addr); 600 601 bta_dm_search_cb.peer_bdaddr = remote_bd_addr; 602 603 log::verbose( 604 "name_discover_done = {} p_btm_inq_info 0x{} state = {}, transport={}", 605 bta_dm_search_cb.name_discover_done, 606 fmt::ptr(bta_dm_search_cb.p_btm_inq_info), bta_dm_search_get_state(), 607 transport); 608 609 if (bta_dm_search_cb.p_btm_inq_info) { 610 log::verbose("appl_knows_rem_name {}", 611 bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name); 612 } 613 /** M: Avoid initiate RNR to LE transport. @{ */ 614 if (((bta_dm_search_cb.p_btm_inq_info) && 615 (bta_dm_search_cb.p_btm_inq_info->results.device_type == 616 BT_DEVICE_TYPE_BLE) && 617 #ifndef OPLUS_FEATURE_BT_LE_AUDIO 618 (bta_dm_search_get_state() == BTA_DM_SEARCH_ACTIVE)) || 619 transport == BT_TRANSPORT_LE && 620 interop_match_addr(INTEROP_DISABLE_NAME_REQUEST, 621 &bta_dm_search_cb.peer_bdaddr))) { 622 #else 623 (bta_dm_search_get_state() == BTA_DM_SEARCH_ACTIVE)) || 624 (transport == BT_TRANSPORT_LE && (!is_device_le_audio_capable(remote_bd_addr)))) { 625 #endif /* OPLUS_FEATURE_BT_LE_AUDIO */ 626 /** @} */ 627 /* Do not perform RNR for LE devices at inquiry complete*/ 628 bta_dm_search_cb.name_discover_done = true; 629 } 630 631 #ifdef OPLUS_FEATURE_BT_HS_INQUIRY 632 //lvshengyi@CONNECTIVITY.BT.Basic.Inquiry.1653415, 2021/03/09 633 if(bta_dm_search_cb.p_btm_inq_info) { 634 bta_dm_search_cb.name_discover_done = oplus_check_remote_device_not_need_rnr( 635 //#ifdef OPLUS_FEATURE_BT_LE_AUDIO 636 //wangli@CONNECTIVITY.BT.Basic.FEATURE.5308163, add acl exist, if exist to read remote name for BLE 637 remote_bd_addr, btm_cb.btm_inq_vars.inq_num, bta_dm_search_cb.p_btm_inq_info->results.rssi); 638 //#endif /*OPLUS_FEATURE_BT_LE_AUDIO*/ 639 if(!bta_dm_search_cb.name_discover_done) { 640 LOG_VERBOSE("%s rssi: %d ,inq_num: %d", __func__, 641 bta_dm_search_cb.p_btm_inq_info->results.rssi, 642 btm_cb.btm_inq_vars.inq_num); 643 } 644 } 645 #endif /*OPLUS_FEATURE_BT_HS_INQUIRY*/ 646 647 // If we already have the name we can skip getting the name 648 if (BTM_IsRemoteNameKnown(remote_bd_addr, transport) && 649 bluetooth::common::init_flags::sdp_skip_rnr_if_known_is_enabled()) { 650 log::debug( 651 "Security record already known skipping read remote name peer:{}", 652 remote_bd_addr); 653 bta_dm_search_cb.name_discover_done = true; 654 } 655 656 /* if name discovery is not done and application needs remote name */ 657 if ((!bta_dm_search_cb.name_discover_done) && 658 ((bta_dm_search_cb.p_btm_inq_info == NULL) || 659 (bta_dm_search_cb.p_btm_inq_info && 660 (!bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name)))) { 661 if (bta_dm_read_remote_device_name(bta_dm_search_cb.peer_bdaddr, 662 transport)) { 663 BTM_LogHistory(kBtmLogTag, bta_dm_search_cb.peer_bdaddr, 664 "Read remote name", 665 base::StringPrintf("Transport:%s", 666 bt_transport_text(transport).c_str())); 667 return; 668 } else { 669 log::error("Unable to start read remote device name"); 670 } 671 672 /* starting name discovery failed */ 673 bta_dm_search_cb.name_discover_done = true; 674 } 675 676 /* name discovery is done for this device */ 677 if (bta_dm_search_get_state() == BTA_DM_SEARCH_ACTIVE) { 678 // if p_btm_inq_info is nullptr, there is no more inquiry results to 679 // discover name for 680 if (bta_dm_search_cb.p_btm_inq_info) { 681 bta_dm_discover_next_device(); 682 } else { 683 log::info("end of parsing inquiry result"); 684 } 685 } else { 686 log::info("name discovery finished in bad state: {}", 687 bta_dm_state_text(bta_dm_search_get_state())); 688 } 689 } 690 691 /******************************************************************************* 692 * 693 * Function bta_dm_is_search_request_queued 694 * 695 * Description Checks if there is a queued search request 696 * 697 * Returns bool 698 * 699 ******************************************************************************/ 700 bool bta_dm_is_search_request_queued() { 701 if (!com::android::bluetooth::flags:: 702 separate_service_and_device_discovery()) { 703 return bta_dm_disc_legacy::bta_dm_is_search_request_queued(); 704 } 705 return bta_dm_search_cb.p_pending_search != NULL; 706 } 707 708 /******************************************************************************* 709 * 710 * Function bta_dm_queue_search 711 * 712 * Description Queues search command 713 * 714 * Returns void 715 * 716 ******************************************************************************/ 717 static void bta_dm_queue_search(tBTA_DM_API_SEARCH& search) { 718 if (bta_dm_search_cb.p_pending_search) { 719 log::warn("Overwrote previous device discovery inquiry scan request"); 720 } 721 bta_dm_search_cb.p_pending_search.reset(new tBTA_DM_SEARCH_MSG(search)); 722 log::info("Queued device discovery inquiry scan request"); 723 } 724 725 /******************************************************************************* 726 * 727 * Function bta_dm_observe_results_cb 728 * 729 * Description Callback for BLE Observe result 730 * 731 * 732 * Returns void 733 * 734 ******************************************************************************/ 735 static void bta_dm_observe_results_cb(tBTM_INQ_RESULTS* p_inq, 736 const uint8_t* p_eir, uint16_t eir_len) { 737 tBTA_DM_SEARCH result; 738 tBTM_INQ_INFO* p_inq_info; 739 log::verbose("bta_dm_observe_results_cb"); 740 741 result.inq_res.bd_addr = p_inq->remote_bd_addr; 742 result.inq_res.original_bda = p_inq->original_bda; 743 result.inq_res.rssi = p_inq->rssi; 744 result.inq_res.ble_addr_type = p_inq->ble_addr_type; 745 result.inq_res.inq_result_type = p_inq->inq_result_type; 746 result.inq_res.device_type = p_inq->device_type; 747 result.inq_res.flag = p_inq->flag; 748 result.inq_res.ble_evt_type = p_inq->ble_evt_type; 749 result.inq_res.ble_primary_phy = p_inq->ble_primary_phy; 750 result.inq_res.ble_secondary_phy = p_inq->ble_secondary_phy; 751 result.inq_res.ble_advertising_sid = p_inq->ble_advertising_sid; 752 result.inq_res.ble_tx_power = p_inq->ble_tx_power; 753 result.inq_res.ble_periodic_adv_int = p_inq->ble_periodic_adv_int; 754 755 /* application will parse EIR to find out remote device name */ 756 result.inq_res.p_eir = const_cast<uint8_t*>(p_eir); 757 result.inq_res.eir_len = eir_len; 758 759 p_inq_info = 760 get_btm_client_interface().db.BTM_InqDbRead(p_inq->remote_bd_addr); 761 if (p_inq_info != NULL) { 762 /* initialize remt_name_not_required to false so that we get the name by 763 * default */ 764 result.inq_res.remt_name_not_required = false; 765 } 766 767 if (p_inq_info) { 768 /* application indicates if it knows the remote name, inside the callback 769 copy that to the inquiry data base*/ 770 if (result.inq_res.remt_name_not_required) 771 p_inq_info->appl_knows_rem_name = true; 772 } 773 } 774 775 /******************************************************************************* 776 * 777 * Function bta_dm_opportunistic_observe_results_cb 778 * 779 * Description Callback for BLE Observe result 780 * 781 * 782 * Returns void 783 * 784 ******************************************************************************/ 785 static void bta_dm_opportunistic_observe_results_cb(tBTM_INQ_RESULTS* p_inq, 786 const uint8_t* p_eir, 787 uint16_t eir_len) { 788 tBTA_DM_SEARCH result; 789 tBTM_INQ_INFO* p_inq_info; 790 791 result.inq_res.bd_addr = p_inq->remote_bd_addr; 792 result.inq_res.rssi = p_inq->rssi; 793 result.inq_res.ble_addr_type = p_inq->ble_addr_type; 794 result.inq_res.inq_result_type = p_inq->inq_result_type; 795 result.inq_res.device_type = p_inq->device_type; 796 result.inq_res.flag = p_inq->flag; 797 result.inq_res.ble_evt_type = p_inq->ble_evt_type; 798 result.inq_res.ble_primary_phy = p_inq->ble_primary_phy; 799 result.inq_res.ble_secondary_phy = p_inq->ble_secondary_phy; 800 result.inq_res.ble_advertising_sid = p_inq->ble_advertising_sid; 801 result.inq_res.ble_tx_power = p_inq->ble_tx_power; 802 result.inq_res.ble_periodic_adv_int = p_inq->ble_periodic_adv_int; 803 804 /* application will parse EIR to find out remote device name */ 805 result.inq_res.p_eir = const_cast<uint8_t*>(p_eir); 806 result.inq_res.eir_len = eir_len; 807 808 p_inq_info = 809 get_btm_client_interface().db.BTM_InqDbRead(p_inq->remote_bd_addr); 810 if (p_inq_info != NULL) { 811 /* initialize remt_name_not_required to false so that we get the name by 812 * default */ 813 result.inq_res.remt_name_not_required = false; 814 } 815 816 if (bta_dm_search_cb.p_csis_scan_cback) 817 bta_dm_search_cb.p_csis_scan_cback(BTA_DM_INQ_RES_EVT, &result); 818 819 if (p_inq_info) { 820 /* application indicates if it knows the remote name, inside the callback 821 copy that to the inquiry data base*/ 822 if (result.inq_res.remt_name_not_required) 823 p_inq_info->appl_knows_rem_name = true; 824 } 825 } 826 827 /******************************************************************************* 828 * 829 * Function bta_dm_observe_cmpl_cb 830 * 831 * Description Callback for BLE Observe complete 832 * 833 * 834 * Returns void 835 * 836 ******************************************************************************/ 837 static void bta_dm_observe_cmpl_cb(void* p_result) { 838 log::verbose("bta_dm_observe_cmpl_cb"); 839 840 if (bta_dm_search_cb.p_csis_scan_cback) { 841 auto num_resps = ((tBTM_INQUIRY_CMPL*)p_result)->num_resp; 842 tBTA_DM_SEARCH data{.observe_cmpl{.num_resps = num_resps}}; 843 bta_dm_search_cb.p_csis_scan_cback(BTA_DM_OBSERVE_CMPL_EVT, &data); 844 } 845 } 846 847 static void bta_dm_start_scan(uint8_t duration_sec, 848 bool low_latency_scan = false) { 849 tBTM_STATUS status = get_btm_client_interface().ble.BTM_BleObserve( 850 true, duration_sec, bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb, 851 low_latency_scan); 852 853 if (status != BTM_CMD_STARTED) { 854 log::warn("BTM_BleObserve failed. status {}", status); 855 if (bta_dm_search_cb.p_csis_scan_cback) { 856 tBTA_DM_SEARCH data{.observe_cmpl = {.num_resps = 0}}; 857 bta_dm_search_cb.p_csis_scan_cback(BTA_DM_OBSERVE_CMPL_EVT, &data); 858 } 859 } 860 } 861 862 void bta_dm_ble_scan(bool start, uint8_t duration_sec, 863 bool low_latency_scan = false) { 864 if (!start) { 865 if (get_btm_client_interface().ble.BTM_BleObserve( 866 false, 0, NULL, NULL, false) != BTM_CMD_STARTED) { 867 log::warn("Unable to start ble observe"); 868 } 869 return; 870 } 871 872 bta_dm_start_scan(duration_sec, low_latency_scan); 873 } 874 875 void bta_dm_ble_csis_observe(bool observe, tBTA_DM_SEARCH_CBACK* p_cback) { 876 if (!observe) { 877 bta_dm_search_cb.p_csis_scan_cback = NULL; 878 BTM_BleOpportunisticObserve(false, NULL); 879 return; 880 } 881 882 /* Save the callback to be called when a scan results are available */ 883 bta_dm_search_cb.p_csis_scan_cback = p_cback; 884 BTM_BleOpportunisticObserve(true, bta_dm_opportunistic_observe_results_cb); 885 } 886 887 namespace bluetooth { 888 namespace legacy { 889 namespace testing { 890 891 void bta_dm_remname_cback(const tBTM_REMOTE_DEV_NAME* p) { 892 ::bta_dm_remname_cback(p); 893 } 894 895 void bta_dm_remote_name_cmpl(const tBTA_DM_REMOTE_NAME& remote_name_msg) { 896 ::bta_dm_remote_name_cmpl(remote_name_msg); 897 } 898 899 } // namespace testing 900 } // namespace legacy 901 } // namespace bluetooth 902 903 namespace { 904 constexpr size_t kSearchStateHistorySize = 50; 905 constexpr char kTimeFormatString[] = "%Y-%m-%d %H:%M:%S"; 906 907 constexpr unsigned MillisPerSecond = 1000; 908 std::string EpochMillisToString(long long time_ms) { 909 time_t time_sec = time_ms / MillisPerSecond; 910 struct tm tm; 911 localtime_r(&time_sec, &tm); 912 std::string s = bluetooth::common::StringFormatTime(kTimeFormatString, tm); 913 return base::StringPrintf( 914 "%s.%03u", s.c_str(), 915 static_cast<unsigned int>(time_ms % MillisPerSecond)); 916 } 917 918 } // namespace 919 920 struct tSEARCH_STATE_HISTORY { 921 const tBTA_DM_DEVICE_SEARCH_STATE state; 922 const tBTA_DM_DEV_SEARCH_EVT event; 923 std::string ToString() const { 924 return base::StringPrintf("state:%25s event:%s", 925 bta_dm_state_text(state).c_str(), 926 bta_dm_event_text(event).c_str()); 927 } 928 }; 929 930 bluetooth::common::TimestampedCircularBuffer<tSEARCH_STATE_HISTORY> 931 search_state_history_(kSearchStateHistorySize); 932 933 /******************************************************************************* 934 * 935 * Function bta_dm_search_sm_execute 936 * 937 * Description State machine event handling function for DM 938 * 939 * 940 * Returns void 941 * 942 ******************************************************************************/ 943 static void bta_dm_search_sm_execute(tBTA_DM_DEV_SEARCH_EVT event, 944 std::unique_ptr<tBTA_DM_SEARCH_MSG> msg) { 945 log::info("state:{}, event:{}[0x{:x}]", 946 bta_dm_state_text(bta_dm_search_get_state()), 947 bta_dm_event_text(event), event); 948 search_state_history_.Push({ 949 .state = bta_dm_search_get_state(), 950 .event = event, 951 }); 952 953 switch (bta_dm_search_get_state()) { 954 case BTA_DM_SEARCH_IDLE: 955 switch (event) { 956 case BTA_DM_API_SEARCH_EVT: 957 bta_dm_search_set_state(BTA_DM_SEARCH_ACTIVE); 958 log::assert_that(std::holds_alternative<tBTA_DM_API_SEARCH>(*msg), 959 "bad message type: {}", msg->index()); 960 961 bta_dm_search_start(std::get<tBTA_DM_API_SEARCH>(*msg)); 962 break; 963 case BTA_DM_API_SEARCH_CANCEL_EVT: 964 bta_dm_search_clear_queue(); 965 bta_dm_search_cancel_notify(); 966 break; 967 default: 968 log::info("Received unexpected event {}[0x{:x}] in state {}", 969 bta_dm_event_text(event), event, 970 bta_dm_state_text(bta_dm_search_get_state())); 971 } 972 break; 973 case BTA_DM_SEARCH_ACTIVE: 974 switch (event) { 975 case BTA_DM_REMT_NAME_EVT: 976 log::assert_that(std::holds_alternative<tBTA_DM_REMOTE_NAME>(*msg), 977 "bad message type: {}", msg->index()); 978 979 bta_dm_remote_name_cmpl(std::get<tBTA_DM_REMOTE_NAME>(*msg)); 980 break; 981 case BTA_DM_SEARCH_CMPL_EVT: 982 bta_dm_search_cmpl(); 983 break; 984 case BTA_DM_API_SEARCH_CANCEL_EVT: 985 bta_dm_search_clear_queue(); 986 bta_dm_search_set_state(BTA_DM_SEARCH_CANCELLING); 987 bta_dm_search_cancel(); 988 break; 989 default: 990 log::info("Received unexpected event {}[0x{:x}] in state {}", 991 bta_dm_event_text(event), event, 992 bta_dm_state_text(bta_dm_search_get_state())); 993 } 994 break; 995 case BTA_DM_SEARCH_CANCELLING: 996 switch (event) { 997 case BTA_DM_API_SEARCH_EVT: 998 log::assert_that(std::holds_alternative<tBTA_DM_API_SEARCH>(*msg), 999 "bad message type: {}", msg->index()); 1000 1001 bta_dm_queue_search(std::get<tBTA_DM_API_SEARCH>(*msg)); 1002 break; 1003 case BTA_DM_API_SEARCH_CANCEL_EVT: 1004 bta_dm_search_clear_queue(); 1005 bta_dm_search_cancel_notify(); 1006 break; 1007 case BTA_DM_REMT_NAME_EVT: 1008 case BTA_DM_SEARCH_CMPL_EVT: 1009 bta_dm_search_set_state(BTA_DM_SEARCH_IDLE); 1010 bta_dm_search_cancel_notify(); 1011 bta_dm_execute_queued_search_request(); 1012 break; 1013 default: 1014 log::info("Received unexpected event {}[0x{:x}] in state {}", 1015 bta_dm_event_text(event), event, 1016 bta_dm_state_text(bta_dm_search_get_state())); 1017 } 1018 break; 1019 } 1020 } 1021 1022 static void bta_dm_disable_search(void) { 1023 switch (bta_dm_search_get_state()) { 1024 case BTA_DM_SEARCH_IDLE: 1025 break; 1026 case BTA_DM_SEARCH_ACTIVE: 1027 case BTA_DM_SEARCH_CANCELLING: 1028 default: 1029 log::debug( 1030 "Search state machine is not idle so issuing search cancel current " 1031 "state:{}", 1032 bta_dm_state_text(bta_dm_search_get_state())); 1033 bta_dm_search_cancel(); 1034 } 1035 } 1036 1037 void bta_dm_disc_start_device_discovery(tBTA_DM_SEARCH_CBACK* p_cback) { 1038 if (!com::android::bluetooth::flags:: 1039 separate_service_and_device_discovery()) { 1040 bta_dm_disc_legacy::bta_dm_disc_start_device_discovery(p_cback); 1041 return; 1042 } 1043 bta_dm_search_sm_execute(BTA_DM_API_SEARCH_EVT, 1044 std::make_unique<tBTA_DM_SEARCH_MSG>( 1045 tBTA_DM_API_SEARCH{.p_cback = p_cback})); 1046 } 分析一下这段代码的逻辑
09-02
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值