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