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