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