1 // 2 // Copyright (C) 2015 Google, Inc. 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at: 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include <iostream> 18 #include <string> 19 20 #ifdef BT_LIBCHROME_NDEBUG 21 #define NDEBUG 1 22 #endif 23 24 #include <base/at_exit.h> 25 #include <base/command_line.h> 26 #include <base/logging.h> 27 #include <base/macros.h> 28 #include <base/strings/string_number_conversions.h> 29 #include <base/strings/string_split.h> 30 #include <base/strings/string_util.h> 31 #include <binder/IPCThreadState.h> 32 #include <binder/ProcessState.h> 33 34 #include <bluetooth/adapter_state.h> 35 #include <bluetooth/binder/IBluetooth.h> 36 #include <bluetooth/binder/IBluetoothCallback.h> 37 #include <bluetooth/binder/IBluetoothGattClient.h> 38 #include <bluetooth/binder/IBluetoothGattClientCallback.h> 39 #include <bluetooth/binder/IBluetoothLowEnergy.h> 40 #include <bluetooth/binder/IBluetoothLowEnergyCallback.h> 41 #include <bluetooth/low_energy_constants.h> 42 #include <bluetooth/scan_filter.h> 43 #include <bluetooth/scan_settings.h> 44 #include <bluetooth/uuid.h> 45 46 using namespace std; 47 48 using android::sp; 49 50 using ipc::binder::IBluetooth; 51 using ipc::binder::IBluetoothGattClient; 52 using ipc::binder::IBluetoothLowEnergy; 53 54 namespace { 55 56 #define COLOR_OFF "\x1B[0m" 57 #define COLOR_RED "\x1B[0;91m" 58 #define COLOR_GREEN "\x1B[0;92m" 59 #define COLOR_YELLOW "\x1B[0;93m" 60 #define COLOR_BLUE "\x1B[0;94m" 61 #define COLOR_MAGENTA "\x1B[0;95m" 62 #define COLOR_BOLDGRAY "\x1B[1;30m" 63 #define COLOR_BOLDWHITE "\x1B[1;37m" 64 #define COLOR_BOLDYELLOW "\x1B[1;93m" 65 #define CLEAR_LINE "\x1B[2K" 66 67 #define CHECK_ARGS_COUNT(args, op, num, msg) \ 68 if (!(args.size() op num)) { \ 69 PrintError(msg); \ 70 return; \ 71 } 72 #define CHECK_NO_ARGS(args) \ 73 CHECK_ARGS_COUNT(args, ==, 0, "Expected no arguments") 74 75 // TODO(armansito): Clean up this code. Right now everything is in this 76 // monolithic file. We should organize this into different classes for command 77 // handling, console output/printing, callback handling, etc. 78 // (See http://b/23387611) 79 80 // Used to synchronize the printing of the command-line prompt and incoming 81 // Binder callbacks. 82 std::atomic_bool showing_prompt(false); 83 84 // The registered IBluetoothLowEnergy client handle. If |ble_registering| is 85 // true then an operation to register the client is in progress. 86 std::atomic_bool ble_registering(false); 87 std::atomic_int ble_client_id(0); 88 89 // The registered IBluetoothGattClient client handle. If |gatt_registering| is 90 // true then an operation to register the client is in progress. 91 std::atomic_bool gatt_registering(false); 92 std::atomic_int gatt_client_id(0); 93 94 // True if we should dump the scan record bytes for incoming scan results. 95 std::atomic_bool dump_scan_record(false); 96 97 // True if the remote process has died and we should exit. 98 std::atomic_bool should_exit(false); 99 100 void PrintPrompt() { 101 cout << COLOR_BLUE "[FCLI] " COLOR_OFF << flush; 102 } 103 104 void PrintError(const string& message) { 105 cout << COLOR_RED << message << COLOR_OFF << endl; 106 } 107 108 void PrintOpStatus(const std::string& op, bool status) { 109 cout << COLOR_BOLDWHITE << op << " status: " COLOR_OFF 110 << (status ? (COLOR_GREEN "success") : (COLOR_RED "failure")) 111 << COLOR_OFF << endl; 112 } 113 114 inline void BeginAsyncOut() { 115 if (showing_prompt.load()) 116 cout << CLEAR_LINE << "\r"; 117 } 118 119 inline void EndAsyncOut() { 120 std::flush(cout); 121 if (showing_prompt.load()) 122 PrintPrompt(); 123 else 124 cout << endl; 125 } 126 127 class CLIBluetoothCallback : public ipc::binder::BnBluetoothCallback { 128 public: 129 CLIBluetoothCallback() = default; 130 ~CLIBluetoothCallback() override = default; 131 132 // IBluetoothCallback overrides: 133 void OnBluetoothStateChange( 134 bluetooth::AdapterState prev_state, 135 bluetooth::AdapterState new_state) override { 136 137 BeginAsyncOut(); 138 cout << COLOR_BOLDWHITE "Adapter state changed: " COLOR_OFF 139 << COLOR_MAGENTA << AdapterStateToString(prev_state) << COLOR_OFF 140 << COLOR_BOLDWHITE " -> " COLOR_OFF 141 << COLOR_BOLDYELLOW << AdapterStateToString(new_state) << COLOR_OFF; 142 EndAsyncOut(); 143 } 144 145 private: 146 DISALLOW_COPY_AND_ASSIGN(CLIBluetoothCallback); 147 }; 148 149 class CLIBluetoothLowEnergyCallback 150 : public ipc::binder::BnBluetoothLowEnergyCallback { 151 public: 152 CLIBluetoothLowEnergyCallback() = default; 153 ~CLIBluetoothLowEnergyCallback() override = default; 154 155 // IBluetoothLowEnergyCallback overrides: 156 void OnClientRegistered(int status, int client_id) override { 157 BeginAsyncOut(); 158 if (status != bluetooth::BLE_STATUS_SUCCESS) { 159 PrintError("Failed to register BLE client"); 160 } else { 161 ble_client_id = client_id; 162 cout << COLOR_BOLDWHITE "Registered BLE client with ID: " COLOR_OFF 163 << COLOR_GREEN << client_id << COLOR_OFF; 164 } 165 EndAsyncOut(); 166 167 ble_registering = false; 168 } 169 170 void OnConnectionState(int status, int client_id, const char* address, 171 bool connected) override { 172 BeginAsyncOut(); 173 cout << COLOR_BOLDWHITE "Connection state: " 174 << COLOR_BOLDYELLOW "[" << address 175 << " connected: " << (connected ? "true" : "false") << " ] " 176 << COLOR_BOLDWHITE "- status: " << status 177 << COLOR_BOLDWHITE " - client_id: " << client_id << COLOR_OFF; 178 EndAsyncOut(); 179 } 180 181 void OnMtuChanged(int status, const char *address, int mtu) override { 182 BeginAsyncOut(); 183 cout << COLOR_BOLDWHITE "MTU changed: " 184 << COLOR_BOLDYELLOW "[" << address << " ] " 185 << COLOR_BOLDWHITE " - status: " << status 186 << COLOR_BOLDWHITE " - mtu: " << mtu << COLOR_OFF; 187 EndAsyncOut(); 188 } 189 190 void OnScanResult(const bluetooth::ScanResult& scan_result) override { 191 BeginAsyncOut(); 192 cout << COLOR_BOLDWHITE "Scan result: " 193 << COLOR_BOLDYELLOW "[" << scan_result.device_address() << "] " 194 << COLOR_BOLDWHITE "- RSSI: " << scan_result.rssi() << COLOR_OFF; 195 196 if (dump_scan_record) { 197 cout << " - Record: " 198 << base::HexEncode(scan_result.scan_record().data(), 199 scan_result.scan_record().size()); 200 } 201 EndAsyncOut(); 202 } 203 204 void OnMultiAdvertiseCallback( 205 int status, bool is_start, 206 const bluetooth::AdvertiseSettings& /* settings */) { 207 BeginAsyncOut(); 208 std::string op = is_start ? "start" : "stop"; 209 210 PrintOpStatus("Advertising " + op, status == bluetooth::BLE_STATUS_SUCCESS); 211 EndAsyncOut(); 212 } 213 214 private: 215 DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLowEnergyCallback); 216 }; 217 218 class CLIGattClientCallback 219 : public ipc::binder::BnBluetoothGattClientCallback { 220 public: 221 CLIGattClientCallback() = default; 222 ~CLIGattClientCallback() override = default; 223 224 // IBluetoothGattClientCallback overrides: 225 void OnClientRegistered(int status, int client_id) override { 226 BeginAsyncOut(); 227 if (status != bluetooth::BLE_STATUS_SUCCESS) { 228 PrintError("Failed to register GATT client"); 229 } else { 230 gatt_client_id = client_id; 231 cout << COLOR_BOLDWHITE "Registered GATT client with ID: " COLOR_OFF 232 << COLOR_GREEN << client_id << COLOR_OFF; 233 } 234 EndAsyncOut(); 235 236 gatt_registering = false; 237 } 238 239 private: 240 DISALLOW_COPY_AND_ASSIGN(CLIGattClientCallback); 241 }; 242 243 void PrintCommandStatus(bool status) { 244 PrintOpStatus("Command", status); 245 } 246 247 void PrintFieldAndValue(const string& field, const string& value) { 248 cout << COLOR_BOLDWHITE << field << ": " << COLOR_BOLDYELLOW << value 249 << COLOR_OFF << endl; 250 } 251 252 void PrintFieldAndBoolValue(const string& field, bool value) { 253 PrintFieldAndValue(field, (value ? "true" : "false")); 254 } 255 256 void HandleDisable(IBluetooth* bt_iface, const vector<string>& args) { 257 CHECK_NO_ARGS(args); 258 PrintCommandStatus(bt_iface->Disable()); 259 } 260 261 void HandleEnable(IBluetooth* bt_iface, const vector<string>& args) { 262 bool is_restricted_mode = false; 263 264 for (auto iter : args) { 265 const std::string& arg = iter; 266 if (arg == "-h") { 267 static const char kUsage[] = 268 "Usage: start-adv [flags]\n" 269 "\n" 270 "Flags:\n" 271 "\t--restricted|-r\tStart in restricted mode\n"; 272 cout << kUsage << endl; 273 return; 274 } else if (arg == "--restricted" || arg == "-r") { 275 is_restricted_mode = true; 276 } 277 } 278 279 PrintCommandStatus(bt_iface->Enable(is_restricted_mode)); 280 } 281 282 void HandleGetState(IBluetooth* bt_iface, const vector<string>& args) { 283 CHECK_NO_ARGS(args); 284 bluetooth::AdapterState state = static_cast<bluetooth::AdapterState>( 285 bt_iface->GetState()); 286 PrintFieldAndValue("Adapter state", bluetooth::AdapterStateToString(state)); 287 } 288 289 void HandleIsEnabled(IBluetooth* bt_iface, const vector<string>& args) { 290 CHECK_NO_ARGS(args); 291 bool enabled = bt_iface->IsEnabled(); 292 PrintFieldAndBoolValue("Adapter enabled", enabled); 293 } 294 295 void HandleGetLocalAddress(IBluetooth* bt_iface, const vector<string>& args) { 296 CHECK_NO_ARGS(args); 297 string address = bt_iface->GetAddress(); 298 PrintFieldAndValue("Adapter address", address); 299 } 300 301 void HandleSetLocalName(IBluetooth* bt_iface, const vector<string>& args) { 302 CHECK_ARGS_COUNT(args, >=, 1, "No name was given"); 303 304 std::string name; 305 for (const auto& arg : args) 306 name += arg + " "; 307 308 base::TrimWhitespaceASCII(name, base::TRIM_TRAILING, &name); 309 310 PrintCommandStatus(bt_iface->SetName(name)); 311 } 312 313 void HandleGetLocalName(IBluetooth* bt_iface, const vector<string>& args) { 314 CHECK_NO_ARGS(args); 315 string name = bt_iface->GetName(); 316 PrintFieldAndValue("Adapter name", name); 317 } 318 319 void HandleAdapterInfo(IBluetooth* bt_iface, const vector<string>& args) { 320 CHECK_NO_ARGS(args); 321 322 cout << COLOR_BOLDWHITE "Adapter Properties: " COLOR_OFF << endl; 323 324 PrintFieldAndValue("\tAddress", bt_iface->GetAddress()); 325 PrintFieldAndValue("\tState", bluetooth::AdapterStateToString( 326 static_cast<bluetooth::AdapterState>(bt_iface->GetState()))); 327 PrintFieldAndValue("\tName", bt_iface->GetName()); 328 PrintFieldAndBoolValue("\tMulti-Adv. supported", 329 bt_iface->IsMultiAdvertisementSupported()); 330 } 331 332 void HandleSupportsMultiAdv(IBluetooth* bt_iface, const vector<string>& args) { 333 CHECK_NO_ARGS(args); 334 335 bool status = bt_iface->IsMultiAdvertisementSupported(); 336 PrintFieldAndBoolValue("Multi-advertisement support", status); 337 } 338 339 void HandleRegisterBLE(IBluetooth* bt_iface, const vector<string>& args) { 340 CHECK_NO_ARGS(args); 341 342 if (ble_registering.load()) { 343 PrintError("In progress"); 344 return; 345 } 346 347 if (ble_client_id.load()) { 348 PrintError("Already registered"); 349 return; 350 } 351 352 sp<IBluetoothLowEnergy> ble_iface = bt_iface->GetLowEnergyInterface(); 353 if (!ble_iface.get()) { 354 PrintError("Failed to obtain handle to Bluetooth Low Energy interface"); 355 return; 356 } 357 358 bool status = ble_iface->RegisterClient(new CLIBluetoothLowEnergyCallback()); 359 ble_registering = status; 360 PrintCommandStatus(status); 361 } 362 363 void HandleUnregisterBLE(IBluetooth* bt_iface, const vector<string>& args) { 364 CHECK_NO_ARGS(args); 365 366 if (!ble_client_id.load()) { 367 PrintError("Not registered"); 368 return; 369 } 370 371 sp<IBluetoothLowEnergy> ble_iface = bt_iface->GetLowEnergyInterface(); 372 if (!ble_iface.get()) { 373 PrintError("Failed to obtain handle to Bluetooth Low Energy interface"); 374 return; 375 } 376 377 ble_iface->UnregisterClient(ble_client_id.load()); 378 ble_client_id = 0; 379 PrintCommandStatus(true); 380 } 381 382 void HandleUnregisterAllBLE(IBluetooth* bt_iface, const vector<string>& args) { 383 CHECK_NO_ARGS(args); 384 385 sp<IBluetoothLowEnergy> ble_iface = bt_iface->GetLowEnergyInterface(); 386 if (!ble_iface.get()) { 387 PrintError("Failed to obtain handle to Bluetooth Low Energy interface"); 388 return; 389 } 390 391 ble_iface->UnregisterAll(); 392 PrintCommandStatus(true); 393 } 394 395 void HandleRegisterGATT(IBluetooth* bt_iface, const vector<string>& args) { 396 CHECK_NO_ARGS(args); 397 398 if (gatt_registering.load()) { 399 PrintError("In progress"); 400 return; 401 } 402 403 if (gatt_client_id.load()) { 404 PrintError("Already registered"); 405 return; 406 } 407 408 sp<IBluetoothGattClient> gatt_iface = bt_iface->GetGattClientInterface(); 409 if (!gatt_iface.get()) { 410 PrintError("Failed to obtain handle to Bluetooth GATT Client interface"); 411 return; 412 } 413 414 bool status = gatt_iface->RegisterClient(new CLIGattClientCallback()); 415 gatt_registering = status; 416 PrintCommandStatus(status); 417 } 418 419 void HandleUnregisterGATT(IBluetooth* bt_iface, const vector<string>& args) { 420 CHECK_NO_ARGS(args); 421 422 if (!gatt_client_id.load()) { 423 PrintError("Not registered"); 424 return; 425 } 426 427 sp<IBluetoothGattClient> gatt_iface = bt_iface->GetGattClientInterface(); 428 if (!gatt_iface.get()) { 429 PrintError("Failed to obtain handle to Bluetooth GATT Client interface"); 430 return; 431 } 432 433 gatt_iface->UnregisterClient(gatt_client_id.load()); 434 gatt_client_id = 0; 435 PrintCommandStatus(true); 436 } 437 438 void HandleStartAdv(IBluetooth* bt_iface, const vector<string>& args) { 439 bool include_name = false; 440 bool include_tx_power = false; 441 bool connectable = false; 442 bool set_manufacturer_data = false; 443 bool set_uuid = false; 444 bluetooth::UUID uuid; 445 446 for (auto iter = args.begin(); iter != args.end(); ++iter) { 447 const std::string& arg = *iter; 448 if (arg == "-n") 449 include_name = true; 450 else if (arg == "-t") 451 include_tx_power = true; 452 else if (arg == "-c") 453 connectable = true; 454 else if (arg == "-m") 455 set_manufacturer_data = true; 456 else if (arg == "-u") { 457 // This flag has a single argument. 458 ++iter; 459 if (iter == args.end()) { 460 PrintError("Expected a UUID after -u"); 461 return; 462 } 463 464 std::string uuid_str = *iter; 465 uuid = bluetooth::UUID(uuid_str); 466 if (!uuid.is_valid()) { 467 PrintError("Invalid UUID: " + uuid_str); 468 return; 469 } 470 471 set_uuid = true; 472 } 473 else if (arg == "-h") { 474 static const char kUsage[] = 475 "Usage: start-adv [flags]\n" 476 "\n" 477 "Flags:\n" 478 "\t-n\tInclude device name\n" 479 "\t-t\tInclude TX power\n" 480 "\t-c\tSend connectable adv. packets (default is non-connectable)\n" 481 "\t-m\tInclude random manufacturer data\n" 482 "\t-h\tShow this help message\n"; 483 cout << kUsage << endl; 484 return; 485 } 486 else { 487 PrintError("Unrecognized option: " + arg); 488 return; 489 } 490 } 491 492 if (!ble_client_id.load()) { 493 PrintError("BLE not registered"); 494 return; 495 } 496 497 sp<IBluetoothLowEnergy> ble_iface = bt_iface->GetLowEnergyInterface(); 498 if (!ble_iface.get()) { 499 PrintError("Failed to obtain handle to Bluetooth Low Energy interface"); 500 return; 501 } 502 503 std::vector<uint8_t> data; 504 if (set_manufacturer_data) { 505 data = {{ 506 0x07, bluetooth::kEIRTypeManufacturerSpecificData, 507 0xe0, 0x00, 508 'T', 'e', 's', 't' 509 }}; 510 } 511 512 if (set_uuid) { 513 // Determine the type and length bytes. 514 int uuid_size = uuid.GetShortestRepresentationSize(); 515 uint8_t type; 516 if (uuid_size == bluetooth::UUID::kNumBytes128) 517 type = bluetooth::kEIRTypeComplete128BitUUIDs; 518 else if (uuid_size == bluetooth::UUID::kNumBytes32) 519 type = bluetooth::kEIRTypeComplete32BitUUIDs; 520 else if (uuid_size == bluetooth::UUID::kNumBytes16) 521 type = bluetooth::kEIRTypeComplete16BitUUIDs; 522 else 523 NOTREACHED() << "Unexpected size: " << uuid_size; 524 525 data.push_back(uuid_size + 1); 526 data.push_back(type); 527 528 auto uuid_bytes = uuid.GetFullLittleEndian(); 529 int index = (uuid_size == 16) ? 0 : 12; 530 data.insert(data.end(), uuid_bytes.data() + index, 531 uuid_bytes.data() + index + uuid_size); 532 } 533 534 base::TimeDelta timeout; 535 536 bluetooth::AdvertiseSettings settings( 537 bluetooth::AdvertiseSettings::MODE_LOW_POWER, 538 timeout, 539 bluetooth::AdvertiseSettings::TX_POWER_LEVEL_MEDIUM, 540 connectable); 541 542 bluetooth::AdvertiseData adv_data(data); 543 adv_data.set_include_device_name(include_name); 544 adv_data.set_include_tx_power_level(include_tx_power); 545 546 bluetooth::AdvertiseData scan_rsp; 547 548 bool status = ble_iface->StartMultiAdvertising(ble_client_id.load(), 549 adv_data, scan_rsp, settings); 550 PrintCommandStatus(status); 551 } 552 553 void HandleStopAdv(IBluetooth* bt_iface, const vector<string>& args) { 554 if (!ble_client_id.load()) { 555 PrintError("BLE not registered"); 556 return; 557 } 558 559 sp<IBluetoothLowEnergy> ble_iface = bt_iface->GetLowEnergyInterface(); 560 if (!ble_iface.get()) { 561 PrintError("Failed to obtain handle to Bluetooth Low Energy interface"); 562 return; 563 } 564 565 bool status = ble_iface->StopMultiAdvertising(ble_client_id.load()); 566 PrintCommandStatus(status); 567 } 568 569 void HandleConnect(IBluetooth* bt_iface, const vector<string>& args) { 570 string address; 571 572 if (args.size() != 1) { 573 PrintError("Expected MAC address as only argument"); 574 return; 575 } 576 577 address = args[0]; 578 579 if (!ble_client_id.load()) { 580 PrintError("BLE not registered"); 581 return; 582 } 583 584 sp<IBluetoothLowEnergy> ble_iface = bt_iface->GetLowEnergyInterface(); 585 if (!ble_iface.get()) { 586 PrintError("Failed to obtain handle to Bluetooth Low Energy interface"); 587 return; 588 } 589 590 bool status = ble_iface->Connect(ble_client_id.load(), address.c_str(), 591 false /* is_direct */); 592 593 PrintCommandStatus(status); 594 } 595 596 void HandleDisconnect(IBluetooth* bt_iface, const vector<string>& args) { 597 string address; 598 599 if (args.size() != 1) { 600 PrintError("Expected MAC address as only argument"); 601 return; 602 } 603 604 address = args[0]; 605 606 if (!ble_client_id.load()) { 607 PrintError("BLE not registered"); 608 return; 609 } 610 611 sp<IBluetoothLowEnergy> ble_iface = bt_iface->GetLowEnergyInterface(); 612 if (!ble_iface.get()) { 613 PrintError("Failed to obtain handle to Bluetooth Low Energy interface"); 614 return; 615 } 616 617 bool status = ble_iface->Disconnect(ble_client_id.load(), address.c_str()); 618 619 PrintCommandStatus(status); 620 } 621 622 void HandleSetMtu(IBluetooth* bt_iface, const vector<string>& args) { 623 string address; 624 int mtu; 625 626 if (args.size() != 2) { 627 PrintError("Usage: set-mtu [address] [mtu]"); 628 return; 629 } 630 631 address = args[0]; 632 mtu = std::stoi(args[1]); 633 634 if (mtu < 23) { 635 PrintError("MTU must be 23 or larger"); 636 return; 637 } 638 639 if (!ble_client_id.load()) { 640 PrintError("BLE not registered"); 641 return; 642 } 643 644 sp<IBluetoothLowEnergy> ble_iface = bt_iface->GetLowEnergyInterface(); 645 if (!ble_iface.get()) { 646 PrintError("Failed to obtain handle to Bluetooth Low Energy interface"); 647 return; 648 } 649 650 bool status = ble_iface->SetMtu(ble_client_id.load(), address.c_str(), mtu); 651 PrintCommandStatus(status); 652 } 653 654 void HandleStartLeScan(IBluetooth* bt_iface, const vector<string>& args) { 655 if (!ble_client_id.load()) { 656 PrintError("BLE not registered"); 657 return; 658 } 659 660 for (auto arg : args) { 661 if (arg == "-d") { 662 dump_scan_record = true; 663 } else if (arg == "-h") { 664 static const char kUsage[] = 665 "Usage: start-le-scan [flags]\n" 666 "\n" 667 "Flags:\n" 668 "\t-d\tDump scan record\n" 669 "\t-h\tShow this help message\n"; 670 cout << kUsage << endl; 671 return; 672 } 673 } 674 675 sp<IBluetoothLowEnergy> ble_iface = bt_iface->GetLowEnergyInterface(); 676 if (!ble_iface.get()) { 677 PrintError("Failed to obtain handle to Bluetooth Low Energy interface"); 678 return; 679 } 680 681 bluetooth::ScanSettings settings; 682 std::vector<bluetooth::ScanFilter> filters; 683 684 bool status = ble_iface->StartScan(ble_client_id.load(), settings, filters); 685 PrintCommandStatus(status); 686 } 687 688 void HandleStopLeScan(IBluetooth* bt_iface, const vector<string>& args) { 689 if (!ble_client_id.load()) { 690 PrintError("BLE not registered"); 691 return; 692 } 693 694 sp<IBluetoothLowEnergy> ble_iface = bt_iface->GetLowEnergyInterface(); 695 if (!ble_iface.get()) { 696 PrintError("Failed to obtain handle to Bluetooth Low Energy interface"); 697 return; 698 } 699 700 bluetooth::ScanSettings settings; 701 std::vector<bluetooth::ScanFilter> filters; 702 703 bool status = ble_iface->StopScan(ble_client_id.load()); 704 PrintCommandStatus(status); 705 } 706 707 void HandleHelp(IBluetooth* bt_iface, const vector<string>& args); 708 709 struct { 710 string command; 711 void (*func)(IBluetooth*, const vector<string>& args); 712 string help; 713 } kCommandMap[] = { 714 { "help", HandleHelp, "\t\t\tDisplay this message" }, 715 { "disable", HandleDisable, "\t\t\tDisable Bluetooth" }, 716 { "enable", HandleEnable, "\t\t\tEnable Bluetooth (-h for options)" }, 717 { "get-state", HandleGetState, "\t\tGet the current adapter state" }, 718 { "is-enabled", HandleIsEnabled, "\t\tReturn if Bluetooth is enabled" }, 719 { "get-local-address", HandleGetLocalAddress, 720 "\tGet the local adapter address" }, 721 { "set-local-name", HandleSetLocalName, "\t\tSet the local adapter name" }, 722 { "get-local-name", HandleGetLocalName, "\t\tGet the local adapter name" }, 723 { "adapter-info", HandleAdapterInfo, "\t\tPrint adapter properties" }, 724 { "supports-multi-adv", HandleSupportsMultiAdv, 725 "\tWhether multi-advertisement is currently supported" }, 726 { "register-ble", HandleRegisterBLE, 727 "\t\tRegister with the Bluetooth Low Energy interface" }, 728 { "unregister-ble", HandleUnregisterBLE, 729 "\t\tUnregister from the Bluetooth Low Energy interface" }, 730 { "unregister-all-ble", HandleUnregisterAllBLE, 731 "\tUnregister all clients from the Bluetooth Low Energy interface" }, 732 { "register-gatt", HandleRegisterGATT, 733 "\t\tRegister with the Bluetooth GATT Client interface" }, 734 { "unregister-gatt", HandleUnregisterGATT, 735 "\t\tUnregister from the Bluetooth GATT Client interface" }, 736 { "connect-le", HandleConnect, "\t\tConnect to LE device (-h for options)"}, 737 { "disconnect-le", HandleDisconnect, 738 "\t\tDisconnect LE device (-h for options)"}, 739 { "set-mtu", HandleSetMtu, "\t\tSet MTU (-h for options)"}, 740 { "start-adv", HandleStartAdv, "\t\tStart advertising (-h for options)" }, 741 { "stop-adv", HandleStopAdv, "\t\tStop advertising" }, 742 { "start-le-scan", HandleStartLeScan, 743 "\t\tStart LE device scan (-h for options)" }, 744 { "stop-le-scan", HandleStopLeScan, "\t\tStop LE device scan" }, 745 {}, 746 }; 747 748 void HandleHelp(IBluetooth* /* bt_iface */, const vector<string>& /* args */) { 749 cout << endl; 750 for (int i = 0; kCommandMap[i].func; i++) 751 cout << "\t" << kCommandMap[i].command << kCommandMap[i].help << endl; 752 cout << endl; 753 } 754 755 const char kExecuteLong[] = "exec"; 756 const char kExecuteShort[] = "e"; 757 758 bool ExecuteCommand(sp<IBluetooth> bt_iface, std::string &command) { 759 vector<string> args = 760 base::SplitString(command, " ", base::TRIM_WHITESPACE, 761 base::SPLIT_WANT_ALL); 762 763 if (args.empty()) 764 return true; 765 766 // The first argument is the command while the remaining are what we pass to 767 // the handler functions. 768 command = args[0]; 769 args.erase(args.begin()); 770 771 for (int i = 0; kCommandMap[i].func; i++) { 772 if (command == kCommandMap[i].command) { 773 kCommandMap[i].func(bt_iface.get(), args); 774 return true; 775 } 776 } 777 778 cout << "Unrecognized command: " << command << endl; 779 return false; 780 } 781 782 } // namespace 783 784 class BluetoothDeathRecipient : public android::IBinder::DeathRecipient { 785 public: 786 BluetoothDeathRecipient() = default; 787 ~BluetoothDeathRecipient() override = default; 788 789 // android::IBinder::DeathRecipient override: 790 void binderDied(const android::wp<android::IBinder>& /* who */) override { 791 BeginAsyncOut(); 792 cout << COLOR_BOLDWHITE "The Bluetooth daemon has died" COLOR_OFF << endl; 793 cout << "\nPress 'ENTER' to exit."; 794 EndAsyncOut(); 795 796 android::IPCThreadState::self()->stopProcess(); 797 should_exit = true; 798 } 799 800 private: 801 DISALLOW_COPY_AND_ASSIGN(BluetoothDeathRecipient); 802 }; 803 804 805 int main(int argc, char* argv[]) { 806 base::AtExitManager exit_manager; 807 base::CommandLine::Init(argc, argv); 808 logging::LoggingSettings log_settings; 809 810 if (!logging::InitLogging(log_settings)) { 811 LOG(ERROR) << "Failed to set up logging"; 812 return EXIT_FAILURE; 813 } 814 815 sp<IBluetooth> bt_iface = IBluetooth::getClientInterface(); 816 if (!bt_iface.get()) { 817 LOG(ERROR) << "Failed to obtain handle on IBluetooth"; 818 return EXIT_FAILURE; 819 } 820 821 sp<BluetoothDeathRecipient> dr(new BluetoothDeathRecipient()); 822 if (android::IInterface::asBinder(bt_iface.get())->linkToDeath(dr) != 823 android::NO_ERROR) { 824 LOG(ERROR) << "Failed to register DeathRecipient for IBluetooth"; 825 return EXIT_FAILURE; 826 } 827 828 // Initialize the Binder process thread pool. We have to set this up, 829 // otherwise, incoming callbacks from IBluetoothCallback will block the main 830 // thread (in other words, we have to do this as we are a "Binder server"). 831 android::ProcessState::self()->startThreadPool(); 832 833 // Register Adapter state-change callback 834 sp<CLIBluetoothCallback> callback = new CLIBluetoothCallback(); 835 bt_iface->RegisterCallback(callback); 836 837 cout << COLOR_BOLDWHITE << "Fluoride Command-Line Interface\n" << COLOR_OFF 838 << endl 839 << "Type \"help\" to see possible commands.\n" 840 << endl; 841 842 string command; 843 844 // Add commands from the command line, if they exist. 845 auto command_line = base::CommandLine::ForCurrentProcess(); 846 if (command_line->HasSwitch(kExecuteLong)) { 847 command += command_line->GetSwitchValueASCII(kExecuteLong); 848 } 849 850 if (command_line->HasSwitch(kExecuteShort)) { 851 if (!command.empty()) 852 command += " ; "; 853 command += command_line->GetSwitchValueASCII(kExecuteShort); 854 } 855 856 while (true) { 857 vector<string> commands = base::SplitString(command, ";", 858 base::TRIM_WHITESPACE, 859 base::SPLIT_WANT_ALL); 860 for (string command : commands) { 861 if (!ExecuteCommand(bt_iface, command)) 862 break; 863 } 864 865 commands.clear(); 866 867 PrintPrompt(); 868 869 showing_prompt = true; 870 auto& istream = getline(cin, command); 871 showing_prompt = false; 872 873 if (istream.eof() || should_exit.load()) { 874 cout << "\nExiting" << endl; 875 return EXIT_SUCCESS; 876 } 877 878 if (!istream.good()) { 879 LOG(ERROR) << "An error occured while reading input"; 880 return EXIT_FAILURE; 881 } 882 883 } 884 885 return EXIT_SUCCESS; 886 } 887