main.cc revision 0ecddf398c92324e15a53c9d410646fd7a494b96
1f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//
2f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  Copyright (C) 2015 Google, Inc.
3f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//
4f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  Licensed under the Apache License, Version 2.0 (the "License");
5f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  you may not use this file except in compliance with the License.
6f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  You may obtain a copy of the License at:
7f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//
8f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  http://www.apache.org/licenses/LICENSE-2.0
9f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//
10f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  Unless required by applicable law or agreed to in writing, software
11f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  distributed under the License is distributed on an "AS IS" BASIS,
12f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  See the License for the specific language governing permissions and
14f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  limitations under the License.
15f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//
16f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
17fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray#include <iostream>
18fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray#include <string>
19fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
201377f938abf30ab3104571fb8372c657e65237d0Pavlin Radoslavov#ifdef BT_LIBCHROME_NDEBUG
211377f938abf30ab3104571fb8372c657e65237d0Pavlin Radoslavov#define NDEBUG 1
221377f938abf30ab3104571fb8372c657e65237d0Pavlin Radoslavov#endif
231377f938abf30ab3104571fb8372c657e65237d0Pavlin Radoslavov
24ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray#include <base/at_exit.h>
25ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray#include <base/command_line.h>
26f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray#include <base/logging.h>
2739a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray#include <base/macros.h>
28ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski#include <base/strings/string_number_conversions.h>
295192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray#include <base/strings/string_split.h>
305192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray#include <base/strings/string_util.h>
312e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray#include <binder/IPCThreadState.h>
32a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#include <binder/IServiceManager.h>
3339a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray#include <binder/ProcessState.h>
34f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
35234138e2606dd7a54fbcc540643511abc0a3598dArman Uguray#include <bluetooth/adapter_state.h>
36a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#include <android/bluetooth/BnBluetoothCallback.h>
37a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#include <android/bluetooth/BnBluetoothGattClientCallback.h>
38a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#include <android/bluetooth/BnBluetoothLowEnergyCallback.h>
3967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski#include <android/bluetooth/BnBluetoothLeAdvertiserCallback.h>
40a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#include <android/bluetooth/IBluetooth.h>
41a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#include <android/bluetooth/IBluetoothGattClient.h>
4267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski#include <android/bluetooth/IBluetoothLeAdvertiser.h>
43a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#include <android/bluetooth/IBluetoothLowEnergy.h>
44234138e2606dd7a54fbcc540643511abc0a3598dArman Uguray#include <bluetooth/low_energy_constants.h>
45ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski#include <bluetooth/scan_filter.h>
46ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski#include <bluetooth/scan_settings.h>
4787222e0e826216c69f6a9a5bfe77689561067474Arman Uguray#include <bluetooth/uuid.h>
48f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
49fcf2e0391950a8b140082fbe78688fa89471fbedArman Ugurayusing namespace std;
50fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
51f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Ugurayusing android::sp;
52a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskiusing android::String8;
53a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskiusing android::String16;
54a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskiusing android::binder::Status;
55a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskiusing android::OK;
56a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskiusing android::getService;
57f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
58a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskiusing android::bluetooth::IBluetooth;
59a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskiusing android::bluetooth::IBluetoothGattClient;
6067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskiusing android::bluetooth::IBluetoothLeAdvertiser;
61a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskiusing android::bluetooth::IBluetoothLowEnergy;
62f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
632117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguraynamespace {
642117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray
65a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define COLOR_OFF "\x1B[0m"
66a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define COLOR_RED "\x1B[0;91m"
67a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define COLOR_GREEN "\x1B[0;92m"
68a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define COLOR_YELLOW "\x1B[0;93m"
69a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define COLOR_BLUE "\x1B[0;94m"
70a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define COLOR_MAGENTA "\x1B[0;95m"
71a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define COLOR_BOLDGRAY "\x1B[1;30m"
72a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define COLOR_BOLDWHITE "\x1B[1;37m"
73a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define COLOR_BOLDYELLOW "\x1B[1;93m"
74a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define CLEAR_LINE "\x1B[2K"
75fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
765192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray#define CHECK_ARGS_COUNT(args, op, num, msg) \
7763b0519c3f0d1c0cc523e0e9553c60fc68651accChih-Hung Hsieh  if (!((args).size() op num)) {             \
78a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    PrintError(msg);                         \
79a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    return;                                  \
805192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  }
815192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray#define CHECK_NO_ARGS(args) \
825192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_ARGS_COUNT(args, ==, 0, "Expected no arguments")
835192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
8439a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray// TODO(armansito): Clean up this code. Right now everything is in this
8539a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray// monolithic file. We should organize this into different classes for command
8639a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray// handling, console output/printing, callback handling, etc.
8739a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray// (See http://b/23387611)
8839a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
8939a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray// Used to synchronize the printing of the command-line prompt and incoming
9039a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray// Binder callbacks.
9139a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguraystd::atomic_bool showing_prompt(false);
9239a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
932e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray// The registered IBluetoothLowEnergy client handle. If |ble_registering| is
942e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray// true then an operation to register the client is in progress.
952e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguraystd::atomic_bool ble_registering(false);
964fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguraystd::atomic_int ble_client_id(0);
974fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
9867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// The registered IBluetoothLeAdvertiser handle. If |ble_advertiser_registering| is
9967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski// true then an operation to register the advertiser is in progress.
10067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskistd::atomic_bool ble_advertiser_registering(false);
10167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskistd::atomic_int ble_advertiser_id(0);
10267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
1034fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray// The registered IBluetoothGattClient client handle. If |gatt_registering| is
1044fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray// true then an operation to register the client is in progress.
1054fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguraystd::atomic_bool gatt_registering(false);
1064fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguraystd::atomic_int gatt_client_id(0);
1072e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
108ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski// True if we should dump the scan record bytes for incoming scan results.
109ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowskistd::atomic_bool dump_scan_record(false);
110ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
1112e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray// True if the remote process has died and we should exit.
1122e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguraystd::atomic_bool should_exit(false);
1132e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
114a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskistd::string kServiceName = "bluetooth-service";
115a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski
116a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskivoid PrintPrompt() { cout << COLOR_BLUE "[FCLI] " COLOR_OFF << flush; }
11739a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
1182e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayvoid PrintError(const string& message) {
1192e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  cout << COLOR_RED << message << COLOR_OFF << endl;
1202e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray}
1212e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
122d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Ugurayvoid PrintOpStatus(const std::string& op, bool status) {
123d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  cout << COLOR_BOLDWHITE << op << " status: " COLOR_OFF
124d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray       << (status ? (COLOR_GREEN "success") : (COLOR_RED "failure"))
12564401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski       << COLOR_OFF << endl;
12664401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski}
12764401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski
12864401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowskiinline void BeginAsyncOut() {
129a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  if (showing_prompt.load()) cout << CLEAR_LINE << "\r";
13064401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski}
13164401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski
13264401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowskiinline void EndAsyncOut() {
13364401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski  std::flush(cout);
13464401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski  if (showing_prompt.load())
135a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    PrintPrompt();
13664401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski  else
13764401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    cout << endl;
138d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray}
139d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
140a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskiclass CLIBluetoothCallback : public android::bluetooth::BnBluetoothCallback {
14139a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray public:
14239a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  CLIBluetoothCallback() = default;
14339a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  ~CLIBluetoothCallback() override = default;
14439a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
1452e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  // IBluetoothCallback overrides:
146a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  Status OnBluetoothStateChange(int32_t prev_state,
147a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski                                int32_t new_state) override {
14864401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    BeginAsyncOut();
149a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    cout << COLOR_BOLDWHITE "Adapter state changed: " COLOR_OFF << COLOR_MAGENTA
150a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski         << AdapterStateToString(bluetooth::AdapterState(prev_state))
151a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski         << COLOR_OFF << COLOR_BOLDWHITE " -> " COLOR_OFF << COLOR_BOLDYELLOW
152a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski         << AdapterStateToString(bluetooth::AdapterState(new_state))
153a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski         << COLOR_OFF;
15464401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    EndAsyncOut();
155a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski
156a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    return Status::ok();
157a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  }
15839a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
15939a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray private:
16039a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  DISALLOW_COPY_AND_ASSIGN(CLIBluetoothCallback);
16139a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray};
16239a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
1632e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayclass CLIBluetoothLowEnergyCallback
164a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    : public android::bluetooth::BnBluetoothLowEnergyCallback {
1652e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray public:
1662e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  CLIBluetoothLowEnergyCallback() = default;
1674fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  ~CLIBluetoothLowEnergyCallback() override = default;
1682e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
1692e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  // IBluetoothLowEnergyCallback overrides:
170a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  Status OnClientRegistered(int status, int client_id) override {
17164401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    BeginAsyncOut();
1722e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    if (status != bluetooth::BLE_STATUS_SUCCESS) {
1732e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray      PrintError("Failed to register BLE client");
1742e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    } else {
1754fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray      ble_client_id = client_id;
1762e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray      cout << COLOR_BOLDWHITE "Registered BLE client with ID: " COLOR_OFF
17764401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski           << COLOR_GREEN << client_id << COLOR_OFF;
1782e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    }
17964401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    EndAsyncOut();
1802e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
1812e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    ble_registering = false;
182a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    return Status::ok();
1832e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
1842e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
185a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  Status OnConnectionState(int status, int client_id, const String16& address,
186a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski                           bool connected) override {
18764401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    BeginAsyncOut();
188a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    cout << COLOR_BOLDWHITE "Connection state: " << COLOR_BOLDYELLOW "["
189a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski         << address << " connected: " << (connected ? "true" : "false") << " ] "
190608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski         << COLOR_BOLDWHITE "- status: " << status
191608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski         << COLOR_BOLDWHITE " - client_id: " << client_id << COLOR_OFF;
19264401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    EndAsyncOut();
193a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    return Status::ok();
194455dc8f535a719af6a65a7512d90f9db878f5a58Jakub Pawlowski  }
195455dc8f535a719af6a65a7512d90f9db878f5a58Jakub Pawlowski
196a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  Status OnMtuChanged(int status, const String16& address, int mtu) override {
19764401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    BeginAsyncOut();
198a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    cout << COLOR_BOLDWHITE "MTU changed: " << COLOR_BOLDYELLOW "[" << address
199a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski         << " ] " << COLOR_BOLDWHITE " - status: " << status
200a6551079fe71b1c76505ada0e4f758f6faf651e0Jakub Pawlowski         << COLOR_BOLDWHITE " - mtu: " << mtu << COLOR_OFF;
20164401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    EndAsyncOut();
202a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    return Status::ok();
203a6551079fe71b1c76505ada0e4f758f6faf651e0Jakub Pawlowski  }
204a6551079fe71b1c76505ada0e4f758f6faf651e0Jakub Pawlowski
205a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  Status OnScanResult(
206a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski      const android::bluetooth::ScanResult& scan_result) override {
20764401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    BeginAsyncOut();
208a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    cout << COLOR_BOLDWHITE "Scan result: " << COLOR_BOLDYELLOW "["
209a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski         << scan_result.device_address() << "] "
210ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski         << COLOR_BOLDWHITE "- RSSI: " << scan_result.rssi() << COLOR_OFF;
211ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
212ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    if (dump_scan_record) {
213ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski      cout << " - Record: "
214ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski           << base::HexEncode(scan_result.scan_record().data(),
215ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski                              scan_result.scan_record().size());
216ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    }
21764401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    EndAsyncOut();
218a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    return Status::ok();
219ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  }
220ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
22167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski private:
22267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLowEnergyCallback);
22367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski};
22467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
22567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskiclass CLIBluetoothLeAdvertiserCallback
22667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    : public android::bluetooth::BnBluetoothLeAdvertiserCallback {
22767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski public:
22867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  CLIBluetoothLeAdvertiserCallback() = default;
22967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  ~CLIBluetoothLeAdvertiserCallback() override = default;
23067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
23167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  // IBluetoothLowEnergyCallback overrides:
23267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  Status OnAdvertiserRegistered(int status, int advertiser_id) override {
23367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    BeginAsyncOut();
23467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    if (status != bluetooth::BLE_STATUS_SUCCESS) {
23567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski      PrintError("Failed to register BLE advertiser");
23667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    } else {
23767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski      ble_advertiser_id = advertiser_id;
23867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski      cout << COLOR_BOLDWHITE "Registered BLE advertiser with ID: " COLOR_OFF
23967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski           << COLOR_GREEN << advertiser_id << COLOR_OFF;
24067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    }
24167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    EndAsyncOut();
24267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
24367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    ble_advertiser_registering = false;
24467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    return Status::ok();
24567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  }
24667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
247a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  Status OnMultiAdvertiseCallback(
24852bfc6060cec652a67c8989e0548225af0008be1Arman Uguray      int status, bool is_start,
249a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski      const android::bluetooth::AdvertiseSettings& /* settings */) {
25064401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    BeginAsyncOut();
251d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    std::string op = is_start ? "start" : "stop";
252d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
253d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    PrintOpStatus("Advertising " + op, status == bluetooth::BLE_STATUS_SUCCESS);
25464401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    EndAsyncOut();
255a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    return Status::ok();
25652bfc6060cec652a67c8989e0548225af0008be1Arman Uguray  }
25752bfc6060cec652a67c8989e0548225af0008be1Arman Uguray
2582e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray private:
25967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLeAdvertiserCallback);
2602e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray};
2615192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
2624fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Ugurayclass CLIGattClientCallback
263a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    : public android::bluetooth::BnBluetoothGattClientCallback {
2644fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray public:
2654fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  CLIGattClientCallback() = default;
2664fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  ~CLIGattClientCallback() override = default;
2674fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
2684fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  // IBluetoothGattClientCallback overrides:
269a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  Status OnClientRegistered(int status, int client_id) override {
27064401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    BeginAsyncOut();
2714fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    if (status != bluetooth::BLE_STATUS_SUCCESS) {
2724fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray      PrintError("Failed to register GATT client");
2734fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    } else {
2744fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray      gatt_client_id = client_id;
2754fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray      cout << COLOR_BOLDWHITE "Registered GATT client with ID: " COLOR_OFF
27664401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski           << COLOR_GREEN << client_id << COLOR_OFF;
2774fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    }
27864401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    EndAsyncOut();
2794fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
2804fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    gatt_registering = false;
281a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    return Status::ok();
2824fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  }
2834fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
2844fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray private:
2854fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  DISALLOW_COPY_AND_ASSIGN(CLIGattClientCallback);
2864fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray};
2874fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
288a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskivoid PrintCommandStatus(bool status) { PrintOpStatus("Command", status); }
289fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
2905192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid PrintFieldAndValue(const string& field, const string& value) {
2915192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  cout << COLOR_BOLDWHITE << field << ": " << COLOR_BOLDYELLOW << value
2925192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray       << COLOR_OFF << endl;
2935192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray}
2945192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
2955192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid PrintFieldAndBoolValue(const string& field, bool value) {
2965192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  PrintFieldAndValue(field, (value ? "true" : "false"));
2975192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray}
2985192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
2995192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleDisable(IBluetooth* bt_iface, const vector<string>& args) {
3005192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
301a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
302a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->Disable(&status);
303a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintCommandStatus(status);
304fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray}
305fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
3065192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleEnable(IBluetooth* bt_iface, const vector<string>& args) {
3077b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker  bool is_restricted_mode = false;
3087b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker
3097b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker  for (auto iter : args) {
3107b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker    const std::string& arg = iter;
3117b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker    if (arg == "-h") {
3127b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker      static const char kUsage[] =
3137b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker          "Usage: start-adv [flags]\n"
3147b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker          "\n"
3157b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker          "Flags:\n"
3167b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker          "\t--restricted|-r\tStart in restricted mode\n";
3177b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker      cout << kUsage << endl;
3187b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker      return;
3197b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker    } else if (arg == "--restricted" || arg == "-r") {
3207b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker      is_restricted_mode = true;
3217b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker    }
3227b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker  }
3237b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker
324a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
3257b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker  bt_iface->Enable(is_restricted_mode, &status);
326a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintCommandStatus(status);
327fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray}
328fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
3295192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleGetState(IBluetooth* bt_iface, const vector<string>& args) {
3305192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
331a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski
332a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  int32_t st;
333a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetState(&st);
334a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bluetooth::AdapterState state = static_cast<bluetooth::AdapterState>(st);
3355192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  PrintFieldAndValue("Adapter state", bluetooth::AdapterStateToString(state));
336fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray}
337fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
3385192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleIsEnabled(IBluetooth* bt_iface, const vector<string>& args) {
3395192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
340a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool enabled;
341a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->IsEnabled(&enabled);
3425192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  PrintFieldAndBoolValue("Adapter enabled", enabled);
343fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray}
344fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
3455192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleGetLocalAddress(IBluetooth* bt_iface, const vector<string>& args) {
3465192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
347a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  String16 address;
348a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetAddress(&address);
349a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintFieldAndValue("Adapter address", std::string(String8(address).string()));
3505192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray}
3515192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
3525192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleSetLocalName(IBluetooth* bt_iface, const vector<string>& args) {
3535192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_ARGS_COUNT(args, >=, 1, "No name was given");
3545192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
3555192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  std::string name;
356a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  for (const auto& arg : args) name += arg + " ";
3575192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
3585192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  base::TrimWhitespaceASCII(name, base::TRIM_TRAILING, &name);
3595192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
360a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
361a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->SetName(String16(String8(name.c_str())), &status);
362a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintCommandStatus(status);
3635192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray}
3645192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
3655192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleGetLocalName(IBluetooth* bt_iface, const vector<string>& args) {
3665192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
367a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  String16 name;
368a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetName(&name);
369a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintFieldAndValue("Adapter name", std::string(String8(name).string()));
3705192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray}
3715192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
3725192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleAdapterInfo(IBluetooth* bt_iface, const vector<string>& args) {
3735192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
3745192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
3755192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  cout << COLOR_BOLDWHITE "Adapter Properties: " COLOR_OFF << endl;
3765192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
377a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  String16 address;
378a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetAddress(&address);
379a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintFieldAndValue("\tAddress", std::string(String8(address).string()));
380a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski
381a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  int adapter_state;
382a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetState(&adapter_state);
383a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintFieldAndValue("\tState",
384a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski                     bluetooth::AdapterStateToString(
385a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski                         static_cast<bluetooth::AdapterState>(adapter_state)));
386a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski
387a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  String16 name;
388a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetName(&name);
389a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintFieldAndValue("\tName", std::string(String8(name).string()));
390a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski
391a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool multi_adv;
392a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->IsMultiAdvertisementSupported(&multi_adv);
393a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintFieldAndBoolValue("\tMulti-Adv. supported", multi_adv);
39410b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray}
39510b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray
39610b54c4b7f1a863a27eca4158f256062ec9c3770Arman Ugurayvoid HandleSupportsMultiAdv(IBluetooth* bt_iface, const vector<string>& args) {
39710b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray  CHECK_NO_ARGS(args);
39810b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray
399a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool multi_adv;
400a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->IsMultiAdvertisementSupported(&multi_adv);
401a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintFieldAndBoolValue("Multi-advertisement support", multi_adv);
4025192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray}
4035192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
40467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskivoid HandleRegisterBLEAdvertiser(IBluetooth* bt_iface, const vector<string>& args) {
40567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  CHECK_NO_ARGS(args);
40667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
40767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  if (ble_advertiser_registering.load()) {
40867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    PrintError("In progress");
40967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    return;
41067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  }
41167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
41267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  if (ble_advertiser_id.load()) {
41367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    PrintError("Already registered");
41467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    return;
41567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  }
41667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
41767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  sp<IBluetoothLeAdvertiser> ble_advertiser_iface;
41867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  bt_iface->GetLeAdvertiserInterface(&ble_advertiser_iface);
41967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  if (!ble_advertiser_iface.get()) {
42067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    PrintError("Failed to obtain handle to Bluetooth Le Advertiser interface");
42167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    return;
42267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  }
42367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
42467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  bool status;
42567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  ble_advertiser_iface->RegisterAdvertiser(new CLIBluetoothLeAdvertiserCallback(), &status);
42667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  ble_advertiser_registering = status;
42767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  PrintCommandStatus(status);
42867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski}
42967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
43067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskivoid HandleUnregisterBLEAdvertiser(IBluetooth* bt_iface, const vector<string>& args) {
43167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  CHECK_NO_ARGS(args);
43267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
43367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  if (!ble_advertiser_id.load()) {
43467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    PrintError("Not registered");
43567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    return;
43667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  }
43767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
43867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  sp<IBluetoothLeAdvertiser> ble_advertiser_iface;
43967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  bt_iface->GetLeAdvertiserInterface(&ble_advertiser_iface);
44067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  if (!ble_advertiser_iface.get()) {
44167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
44267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    return;
44367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  }
44467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
44567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  ble_advertiser_iface->UnregisterAdvertiser(ble_advertiser_id.load());
44667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  ble_advertiser_id = 0;
44767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  PrintCommandStatus(true);
44867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski}
44967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
4502e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayvoid HandleRegisterBLE(IBluetooth* bt_iface, const vector<string>& args) {
4512e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  CHECK_NO_ARGS(args);
4522e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
4532e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  if (ble_registering.load()) {
4542e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    PrintError("In progress");
4552e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return;
4562e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
4572e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
4584fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  if (ble_client_id.load()) {
4592e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    PrintError("Already registered");
4602e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return;
4612e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
4622e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
463a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetoothLowEnergy> ble_iface;
464a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetLowEnergyInterface(&ble_iface);
4652e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  if (!ble_iface.get()) {
4662e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
4672e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return;
4682e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
4692e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
470a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
471a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  ble_iface->RegisterClient(new CLIBluetoothLowEnergyCallback(), &status);
472ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray  ble_registering = status;
473ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray  PrintCommandStatus(status);
4742e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray}
4752e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
4762e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayvoid HandleUnregisterBLE(IBluetooth* bt_iface, const vector<string>& args) {
4772e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  CHECK_NO_ARGS(args);
4782e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
4794fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  if (!ble_client_id.load()) {
4802e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    PrintError("Not registered");
4812e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return;
4822e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
4832e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
484a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetoothLowEnergy> ble_iface;
485a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetLowEnergyInterface(&ble_iface);
4862e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  if (!ble_iface.get()) {
4872e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
4882e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return;
4892e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
4902e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
4914fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  ble_iface->UnregisterClient(ble_client_id.load());
4924fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  ble_client_id = 0;
4932e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  PrintCommandStatus(true);
4942e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray}
4952e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
4962e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayvoid HandleUnregisterAllBLE(IBluetooth* bt_iface, const vector<string>& args) {
4972e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  CHECK_NO_ARGS(args);
4982e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
499a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetoothLowEnergy> ble_iface;
500a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetLowEnergyInterface(&ble_iface);
5012e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  if (!ble_iface.get()) {
5022e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
5032e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return;
5042e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
5052e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
5062e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  ble_iface->UnregisterAll();
5072e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  PrintCommandStatus(true);
5082e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray}
5092e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
5104fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Ugurayvoid HandleRegisterGATT(IBluetooth* bt_iface, const vector<string>& args) {
5114fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  CHECK_NO_ARGS(args);
5124fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
5134fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  if (gatt_registering.load()) {
5144fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    PrintError("In progress");
5154fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    return;
5164fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  }
5174fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
5184fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  if (gatt_client_id.load()) {
5194fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    PrintError("Already registered");
5204fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    return;
5214fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  }
5224fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
523a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetoothGattClient> gatt_iface;
524a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetGattClientInterface(&gatt_iface);
5254fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  if (!gatt_iface.get()) {
5264fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    PrintError("Failed to obtain handle to Bluetooth GATT Client interface");
5274fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    return;
5284fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  }
5294fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
530a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
531a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  gatt_iface->RegisterClient(new CLIGattClientCallback(), &status);
5324fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  gatt_registering = status;
5334fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  PrintCommandStatus(status);
5344fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray}
5354fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
5364fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Ugurayvoid HandleUnregisterGATT(IBluetooth* bt_iface, const vector<string>& args) {
5374fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  CHECK_NO_ARGS(args);
5384fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
5394fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  if (!gatt_client_id.load()) {
5404fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    PrintError("Not registered");
5414fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    return;
5424fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  }
5434fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
544a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetoothGattClient> gatt_iface;
545a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetGattClientInterface(&gatt_iface);
5464fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  if (!gatt_iface.get()) {
5474fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    PrintError("Failed to obtain handle to Bluetooth GATT Client interface");
5484fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    return;
5494fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  }
5504fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
5514fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  gatt_iface->UnregisterClient(gatt_client_id.load());
5524fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  gatt_client_id = 0;
5534fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  PrintCommandStatus(true);
5544fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray}
5554fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
556d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Ugurayvoid HandleStartAdv(IBluetooth* bt_iface, const vector<string>& args) {
557d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  bool include_name = false;
558d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  bool include_tx_power = false;
559d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  bool connectable = false;
560d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  bool set_manufacturer_data = false;
56187222e0e826216c69f6a9a5bfe77689561067474Arman Uguray  bool set_uuid = false;
56287222e0e826216c69f6a9a5bfe77689561067474Arman Uguray  bluetooth::UUID uuid;
563d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
56487222e0e826216c69f6a9a5bfe77689561067474Arman Uguray  for (auto iter = args.begin(); iter != args.end(); ++iter) {
56587222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    const std::string& arg = *iter;
566d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    if (arg == "-n")
567d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray      include_name = true;
568d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    else if (arg == "-t")
569d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray      include_tx_power = true;
570d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    else if (arg == "-c")
571d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray      connectable = true;
572d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    else if (arg == "-m")
573d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray      set_manufacturer_data = true;
57487222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    else if (arg == "-u") {
57587222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      // This flag has a single argument.
57687222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      ++iter;
57787222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      if (iter == args.end()) {
57887222e0e826216c69f6a9a5bfe77689561067474Arman Uguray        PrintError("Expected a UUID after -u");
57987222e0e826216c69f6a9a5bfe77689561067474Arman Uguray        return;
58087222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      }
58187222e0e826216c69f6a9a5bfe77689561067474Arman Uguray
58287222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      std::string uuid_str = *iter;
58387222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      uuid = bluetooth::UUID(uuid_str);
58487222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      if (!uuid.is_valid()) {
58587222e0e826216c69f6a9a5bfe77689561067474Arman Uguray        PrintError("Invalid UUID: " + uuid_str);
58687222e0e826216c69f6a9a5bfe77689561067474Arman Uguray        return;
58787222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      }
58887222e0e826216c69f6a9a5bfe77689561067474Arman Uguray
58987222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      set_uuid = true;
590a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    } else if (arg == "-h") {
591ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski      static const char kUsage[] =
592d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray          "Usage: start-adv [flags]\n"
593d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray          "\n"
594ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski          "Flags:\n"
595d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray          "\t-n\tInclude device name\n"
596d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray          "\t-t\tInclude TX power\n"
597d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray          "\t-c\tSend connectable adv. packets (default is non-connectable)\n"
598d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray          "\t-m\tInclude random manufacturer data\n"
599d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray          "\t-h\tShow this help message\n";
600d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray      cout << kUsage << endl;
601d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray      return;
602a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    } else {
603d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray      PrintError("Unrecognized option: " + arg);
604d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray      return;
605d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    }
606d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  }
607d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
60867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  if (!ble_advertiser_id.load()) {
60967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    PrintError("BLE advertiser not registered");
610d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    return;
611d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  }
612d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
61367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  sp<IBluetoothLeAdvertiser> ble_advertiser_iface;
61467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  bt_iface->GetLeAdvertiserInterface(&ble_advertiser_iface);
61567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  if (!ble_advertiser_iface.get()) {
61667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    PrintError("Failed to obtain handle to Bluetooth Le Advertiser interface");
617d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    return;
618d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  }
619d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
620d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  std::vector<uint8_t> data;
621d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  if (set_manufacturer_data) {
622a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    data = {{0x07, bluetooth::kEIRTypeManufacturerSpecificData, 0xe0, 0x00, 'T',
623a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski             'e', 's', 't'}};
624d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  }
625d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
62687222e0e826216c69f6a9a5bfe77689561067474Arman Uguray  if (set_uuid) {
62787222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    // Determine the type and length bytes.
62887222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    int uuid_size = uuid.GetShortestRepresentationSize();
62987222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    uint8_t type;
63087222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    if (uuid_size == bluetooth::UUID::kNumBytes128)
63187222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      type = bluetooth::kEIRTypeComplete128BitUUIDs;
63287222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    else if (uuid_size == bluetooth::UUID::kNumBytes32)
63387222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      type = bluetooth::kEIRTypeComplete32BitUUIDs;
63487222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    else if (uuid_size == bluetooth::UUID::kNumBytes16)
63587222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      type = bluetooth::kEIRTypeComplete16BitUUIDs;
63687222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    else
63787222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      NOTREACHED() << "Unexpected size: " << uuid_size;
63887222e0e826216c69f6a9a5bfe77689561067474Arman Uguray
63987222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    data.push_back(uuid_size + 1);
64087222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    data.push_back(type);
64187222e0e826216c69f6a9a5bfe77689561067474Arman Uguray
64287222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    auto uuid_bytes = uuid.GetFullLittleEndian();
64387222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    int index = (uuid_size == 16) ? 0 : 12;
64487222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    data.insert(data.end(), uuid_bytes.data() + index,
64587222e0e826216c69f6a9a5bfe77689561067474Arman Uguray                uuid_bytes.data() + index + uuid_size);
64687222e0e826216c69f6a9a5bfe77689561067474Arman Uguray  }
64787222e0e826216c69f6a9a5bfe77689561067474Arman Uguray
648d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  base::TimeDelta timeout;
649d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
650d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  bluetooth::AdvertiseSettings settings(
651a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski      bluetooth::AdvertiseSettings::MODE_LOW_POWER, timeout,
652a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski      bluetooth::AdvertiseSettings::TX_POWER_LEVEL_MEDIUM, connectable);
653d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
6540ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski  if (include_tx_power) {
6550ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski    data.push_back(0x02);
6560ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski    data.push_back(bluetooth::kEIRTypeTxPower);
6570ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski    data.push_back(0x00);
6580ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski  }
6590ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski
660d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  bluetooth::AdvertiseData adv_data(data);
6610ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski
6620ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski  if (include_name) {
6630ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski    String16 name_param;
6640ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski    bt_iface->GetName(&name_param);
6650ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski    std::string name(String8(name_param).string());
6660ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski    data.push_back(name.length() + 1);
6670ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski    data.push_back(bluetooth::kEIRTypeCompleteLocalName);
6680ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski    data.insert(data.begin(), name.c_str(), name.c_str() + name.length());
6690ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski  }
670d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
671d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  bluetooth::AdvertiseData scan_rsp;
672d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
673a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
67467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  ble_advertiser_iface->StartMultiAdvertising(ble_advertiser_id.load(), adv_data, scan_rsp,
675a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski                                   settings, &status);
676ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray  PrintCommandStatus(status);
677d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray}
678d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
679d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Ugurayvoid HandleStopAdv(IBluetooth* bt_iface, const vector<string>& args) {
68067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  if (!ble_advertiser_id.load()) {
68167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    PrintError("BLE advertiser not registered");
682d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    return;
683d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  }
684d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
68567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  sp<IBluetoothLeAdvertiser> ble_advertiser_iface;
68667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  bt_iface->GetLeAdvertiserInterface(&ble_advertiser_iface);
68767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  if (!ble_advertiser_iface.get()) {
688d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
689d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    return;
690d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  }
691d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
692a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
69367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  ble_advertiser_iface->StopMultiAdvertising(ble_advertiser_id.load(), &status);
694ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray  PrintCommandStatus(status);
695d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray}
696d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
697608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowskivoid HandleConnect(IBluetooth* bt_iface, const vector<string>& args) {
698608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  string address;
699608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
700608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  if (args.size() != 1) {
701608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    PrintError("Expected MAC address as only argument");
702608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    return;
703608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  }
704608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
705608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  address = args[0];
706608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
707608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  if (!ble_client_id.load()) {
708608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    PrintError("BLE not registered");
709608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    return;
710608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  }
711608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
712a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetoothLowEnergy> ble_iface;
713a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetLowEnergyInterface(&ble_iface);
714608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  if (!ble_iface.get()) {
715608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
716608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    return;
717608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  }
718608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
719a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
720a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  ble_iface->Connect(ble_client_id.load(),
721a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski                     String16(address.c_str(), address.length()),
722a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski                     false /*  is_direct */, &status);
723608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
724608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  PrintCommandStatus(status);
725608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski}
726608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
727608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowskivoid HandleDisconnect(IBluetooth* bt_iface, const vector<string>& args) {
728608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  string address;
729608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
730608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  if (args.size() != 1) {
731608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    PrintError("Expected MAC address as only argument");
732608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    return;
733608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  }
734608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
735608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  address = args[0];
736608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
737608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  if (!ble_client_id.load()) {
738608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    PrintError("BLE not registered");
739608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    return;
740608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  }
741608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
742a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetoothLowEnergy> ble_iface;
743a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetLowEnergyInterface(&ble_iface);
744608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  if (!ble_iface.get()) {
745608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
746608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    return;
747608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  }
748608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
749a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
750a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  ble_iface->Disconnect(ble_client_id.load(),
751a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski                        String16(address.c_str(), address.length()), &status);
752608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  PrintCommandStatus(status);
753608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski}
754608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
755756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowskivoid HandleSetMtu(IBluetooth* bt_iface, const vector<string>& args) {
756756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  string address;
757756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  int mtu;
758756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski
759756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  if (args.size() != 2) {
760756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski    PrintError("Usage: set-mtu [address] [mtu]");
761756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski    return;
762756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  }
763756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski
764756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  address = args[0];
765756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  mtu = std::stoi(args[1]);
766756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski
767756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  if (mtu < 23) {
768756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski    PrintError("MTU must be 23 or larger");
769756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski    return;
770756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  }
771756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski
772756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  if (!ble_client_id.load()) {
773756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski    PrintError("BLE not registered");
774756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski    return;
775756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  }
776756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski
777a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetoothLowEnergy> ble_iface;
778a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetLowEnergyInterface(&ble_iface);
779756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  if (!ble_iface.get()) {
780756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
781756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski    return;
782756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  }
783756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski
784a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
785a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  ble_iface->SetMtu(ble_client_id.load(),
786a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski                    String16(address.c_str(), address.length()), mtu, &status);
787756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  PrintCommandStatus(status);
788756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski}
789756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski
790ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowskivoid HandleStartLeScan(IBluetooth* bt_iface, const vector<string>& args) {
791ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  if (!ble_client_id.load()) {
792ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    PrintError("BLE not registered");
793ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    return;
794ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  }
795ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
7965dc0d15e7865104d13be75c06de4b9158ce7dff4Chih-Hung Hsieh  for (const auto& arg : args) {
797ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    if (arg == "-d") {
798ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski      dump_scan_record = true;
799ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    } else if (arg == "-h") {
800ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski      static const char kUsage[] =
801ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski          "Usage: start-le-scan [flags]\n"
802ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski          "\n"
803ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski          "Flags:\n"
804ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski          "\t-d\tDump scan record\n"
805ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski          "\t-h\tShow this help message\n";
806ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski      cout << kUsage << endl;
807ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski      return;
808ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    }
809ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  }
810ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
811a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetoothLowEnergy> ble_iface;
812a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetLowEnergyInterface(&ble_iface);
813ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  if (!ble_iface.get()) {
814ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
815ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    return;
816ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  }
817ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
818ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  bluetooth::ScanSettings settings;
819a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  std::vector<android::bluetooth::ScanFilter> filters;
820ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
821a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
822a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  ble_iface->StartScan(ble_client_id.load(), settings, filters, &status);
823ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  PrintCommandStatus(status);
824ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski}
825ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
826ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowskivoid HandleStopLeScan(IBluetooth* bt_iface, const vector<string>& args) {
827ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  if (!ble_client_id.load()) {
828ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    PrintError("BLE not registered");
829ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    return;
830ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  }
831ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
832a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetoothLowEnergy> ble_iface;
833a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetLowEnergyInterface(&ble_iface);
834ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  if (!ble_iface.get()) {
835ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
836ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    return;
837ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  }
838ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
839a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
840a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  ble_iface->StopScan(ble_client_id.load(), &status);
841ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  PrintCommandStatus(status);
842ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski}
843ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
8445192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleHelp(IBluetooth* bt_iface, const vector<string>& args);
8452117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray
846fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguraystruct {
847fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray  string command;
8485192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  void (*func)(IBluetooth*, const vector<string>& args);
8492117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray  string help;
850fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray} kCommandMap[] = {
851a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"help", HandleHelp, "\t\t\tDisplay this message"},
852a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"disable", HandleDisable, "\t\t\tDisable Bluetooth"},
8537b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker    {"enable", HandleEnable, "\t\t\tEnable Bluetooth (-h for options)"},
854a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"get-state", HandleGetState, "\t\tGet the current adapter state"},
855a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"is-enabled", HandleIsEnabled, "\t\tReturn if Bluetooth is enabled"},
856a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"get-local-address", HandleGetLocalAddress,
857a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski     "\tGet the local adapter address"},
858a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"set-local-name", HandleSetLocalName, "\t\tSet the local adapter name"},
859a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"get-local-name", HandleGetLocalName, "\t\tGet the local adapter name"},
860a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"adapter-info", HandleAdapterInfo, "\t\tPrint adapter properties"},
861a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"supports-multi-adv", HandleSupportsMultiAdv,
862a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski     "\tWhether multi-advertisement is currently supported"},
86367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    {"register-le-advertiser", HandleRegisterBLEAdvertiser,
86467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski     "\t\tRegister with the Bluetooth Low Energy Advertiser interface"},
86567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    {"unregister-le-advertiser", HandleUnregisterBLEAdvertiser,
86667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski     "\t\tUnregister from the Bluetooth LE Advertiser interface"},
867a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"register-ble", HandleRegisterBLE,
868a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski     "\t\tRegister with the Bluetooth Low Energy interface"},
869a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"unregister-ble", HandleUnregisterBLE,
870a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski     "\t\tUnregister from the Bluetooth Low Energy interface"},
871a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"unregister-all-ble", HandleUnregisterAllBLE,
872a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski     "\tUnregister all clients from the Bluetooth Low Energy interface"},
873a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"register-gatt", HandleRegisterGATT,
874a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski     "\t\tRegister with the Bluetooth GATT Client interface"},
875a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"unregister-gatt", HandleUnregisterGATT,
876a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski     "\t\tUnregister from the Bluetooth GATT Client interface"},
877a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"connect-le", HandleConnect, "\t\tConnect to LE device (-h for options)"},
878a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"disconnect-le", HandleDisconnect,
879a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski     "\t\tDisconnect LE device (-h for options)"},
880a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"set-mtu", HandleSetMtu, "\t\tSet MTU (-h for options)"},
881a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"start-adv", HandleStartAdv, "\t\tStart advertising (-h for options)"},
882a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"stop-adv", HandleStopAdv, "\t\tStop advertising"},
883a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"start-le-scan", HandleStartLeScan,
884a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski     "\t\tStart LE device scan (-h for options)"},
885a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"stop-le-scan", HandleStopLeScan, "\t\tStop LE device scan"},
886a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {},
887fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray};
888f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
8895192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleHelp(IBluetooth* /* bt_iface */, const vector<string>& /* args */) {
8902117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray  cout << endl;
8912117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray  for (int i = 0; kCommandMap[i].func; i++)
8922117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray    cout << "\t" << kCommandMap[i].command << kCommandMap[i].help << endl;
8932117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray  cout << endl;
8942117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray}
8952117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray
8965d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssenconst char kExecuteLong[] = "exec";
8975d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssenconst char kExecuteShort[] = "e";
8985d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
8995dc0d15e7865104d13be75c06de4b9158ce7dff4Chih-Hung Hsiehbool ExecuteCommand(const sp<IBluetooth>& bt_iface, std::string &command) {
9005d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  vector<string> args =
9015d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen      base::SplitString(command, " ", base::TRIM_WHITESPACE,
9025d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen                        base::SPLIT_WANT_ALL);
9035d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
9045d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  if (args.empty())
9055d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen    return true;
9065d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
9075d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  // The first argument is the command while the remaining are what we pass to
9085d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  // the handler functions.
9095d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  command = args[0];
9105d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  args.erase(args.begin());
9115d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
9125d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  for (int i = 0; kCommandMap[i].func; i++) {
9135d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen    if (command == kCommandMap[i].command) {
9145d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen      kCommandMap[i].func(bt_iface.get(), args);
9155d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen      return true;
9165d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen    }
9175d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  }
9185d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
9195d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  cout << "Unrecognized command: " << command << endl;
9205d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  return false;
9215d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen}
9225d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
9232117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray}  // namespace
9242117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray
9252e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayclass BluetoothDeathRecipient : public android::IBinder::DeathRecipient {
9262e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray public:
9272e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  BluetoothDeathRecipient() = default;
9282e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  ~BluetoothDeathRecipient() override = default;
9292e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
9302e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  // android::IBinder::DeathRecipient override:
9312e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  void binderDied(const android::wp<android::IBinder>& /* who */) override {
93264401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    BeginAsyncOut();
9332e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    cout << COLOR_BOLDWHITE "The Bluetooth daemon has died" COLOR_OFF << endl;
93464401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    cout << "\nPress 'ENTER' to exit.";
93564401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    EndAsyncOut();
9362e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
9372e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    android::IPCThreadState::self()->stopProcess();
9382e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    should_exit = true;
9392e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
9402e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
9412e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray private:
9422e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  DISALLOW_COPY_AND_ASSIGN(BluetoothDeathRecipient);
9432e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray};
9442e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
9455d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
946ae43de627b9c91e54215d439149c0e01599249c0Arman Ugurayint main(int argc, char* argv[]) {
947ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray  base::AtExitManager exit_manager;
948ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray  base::CommandLine::Init(argc, argv);
949ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray  logging::LoggingSettings log_settings;
950ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray
951ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray  if (!logging::InitLogging(log_settings)) {
952ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray    LOG(ERROR) << "Failed to set up logging";
953ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray    return EXIT_FAILURE;
954ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray  }
955ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray
956a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetooth> bt_iface;
957a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  status_t status = getService(String16(kServiceName.c_str()), &bt_iface);
958a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  if (status != OK) {
959a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    LOG(ERROR) << "Failed to get service binder: '" << kServiceName
960a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski               << "' status=" << status;
961f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray    return EXIT_FAILURE;
962f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray  }
963f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
9642e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  sp<BluetoothDeathRecipient> dr(new BluetoothDeathRecipient());
9652e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  if (android::IInterface::asBinder(bt_iface.get())->linkToDeath(dr) !=
9662e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray      android::NO_ERROR) {
9672e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    LOG(ERROR) << "Failed to register DeathRecipient for IBluetooth";
9682e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return EXIT_FAILURE;
9692e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
9702e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
97139a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  // Initialize the Binder process thread pool. We have to set this up,
97239a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  // otherwise, incoming callbacks from IBluetoothCallback will block the main
97339a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  // thread (in other words, we have to do this as we are a "Binder server").
97439a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  android::ProcessState::self()->startThreadPool();
97539a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
97639a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  // Register Adapter state-change callback
97739a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  sp<CLIBluetoothCallback> callback = new CLIBluetoothCallback();
97839a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  bt_iface->RegisterCallback(callback);
97939a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
980a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  cout << COLOR_BOLDWHITE << "Fluoride Command-Line Interface\n"
981a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski       << COLOR_OFF << endl
9822117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray       << "Type \"help\" to see possible commands.\n"
983fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray       << endl;
984fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
9855d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  string command;
9865d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
9875d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  // Add commands from the command line, if they exist.
9885d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  auto command_line = base::CommandLine::ForCurrentProcess();
9895d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  if (command_line->HasSwitch(kExecuteLong)) {
9905d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen    command += command_line->GetSwitchValueASCII(kExecuteLong);
9915d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  }
9925d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
9935d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  if (command_line->HasSwitch(kExecuteShort)) {
9945d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen    if (!command.empty())
9955d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen      command += " ; ";
9965d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen    command += command_line->GetSwitchValueASCII(kExecuteShort);
9975d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  }
9985d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
999fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray  while (true) {
10005d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen    vector<string> commands = base::SplitString(command, ";",
10015d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen                                                base::TRIM_WHITESPACE,
10025d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen                                                base::SPLIT_WANT_ALL);
10035d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen    for (string command : commands) {
10045d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen      if (!ExecuteCommand(bt_iface, command))
10055d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen        break;
10065d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen    }
10075d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
10085d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen    commands.clear();
10095192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
101039a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray    PrintPrompt();
101139a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
101239a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray    showing_prompt = true;
101391c59c9febbf4a49664b8a06620d4a4882605131Arman Uguray    auto& istream = getline(cin, command);
101439a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray    showing_prompt = false;
1015fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
101691c59c9febbf4a49664b8a06620d4a4882605131Arman Uguray    if (istream.eof() || should_exit.load()) {
101791c59c9febbf4a49664b8a06620d4a4882605131Arman Uguray      cout << "\nExiting" << endl;
10182e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray      return EXIT_SUCCESS;
101991c59c9febbf4a49664b8a06620d4a4882605131Arman Uguray    }
102091c59c9febbf4a49664b8a06620d4a4882605131Arman Uguray
102191c59c9febbf4a49664b8a06620d4a4882605131Arman Uguray    if (!istream.good()) {
102291c59c9febbf4a49664b8a06620d4a4882605131Arman Uguray      LOG(ERROR) << "An error occured while reading input";
102391c59c9febbf4a49664b8a06620d4a4882605131Arman Uguray      return EXIT_FAILURE;
102491c59c9febbf4a49664b8a06620d4a4882605131Arman Uguray    }
1025fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray  }
1026f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
1027f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray  return EXIT_SUCCESS;
1028f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray}
1029