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