1f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//
25b790feeeb211c42bf78ca3ae9c26aa30e516765Jakub Pawlowski//  Copyright 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
20ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray#include <base/at_exit.h>
21ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray#include <base/command_line.h>
22f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray#include <base/logging.h>
2339a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray#include <base/macros.h>
24ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski#include <base/strings/string_number_conversions.h>
255192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray#include <base/strings/string_split.h>
265192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray#include <base/strings/string_util.h>
272e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray#include <binder/IPCThreadState.h>
28a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#include <binder/IServiceManager.h>
2939a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray#include <binder/ProcessState.h>
30f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
31a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#include <android/bluetooth/BnBluetoothCallback.h>
32a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#include <android/bluetooth/BnBluetoothGattClientCallback.h>
3367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski#include <android/bluetooth/BnBluetoothLeAdvertiserCallback.h>
34c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski#include <android/bluetooth/BnBluetoothLeScannerCallback.h>
35911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include <android/bluetooth/BnBluetoothLowEnergyCallback.h>
36a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#include <android/bluetooth/IBluetooth.h>
37a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#include <android/bluetooth/IBluetoothGattClient.h>
3867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski#include <android/bluetooth/IBluetoothLeAdvertiser.h>
39c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski#include <android/bluetooth/IBluetoothLeScanner.h>
40a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#include <android/bluetooth/IBluetoothLowEnergy.h>
41911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson#include <bluetooth/adapter_state.h>
42234138e2606dd7a54fbcc540643511abc0a3598dArman Uguray#include <bluetooth/low_energy_constants.h>
43ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski#include <bluetooth/scan_filter.h>
44ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski#include <bluetooth/scan_settings.h>
4587222e0e826216c69f6a9a5bfe77689561067474Arman Uguray#include <bluetooth/uuid.h>
46f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
47fcf2e0391950a8b140082fbe78688fa89471fbedArman Ugurayusing namespace std;
48fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
49f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Ugurayusing android::sp;
50a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskiusing android::String8;
51a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskiusing android::String16;
52a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskiusing android::binder::Status;
53a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskiusing android::OK;
54a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskiusing android::getService;
55f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
56a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskiusing android::bluetooth::IBluetooth;
57a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskiusing android::bluetooth::IBluetoothGattClient;
5867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskiusing android::bluetooth::IBluetoothLeAdvertiser;
59c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowskiusing android::bluetooth::IBluetoothLeScanner;
60a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskiusing android::bluetooth::IBluetoothLowEnergy;
61f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
622117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguraynamespace {
632117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray
64a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define COLOR_OFF "\x1B[0m"
65a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define COLOR_RED "\x1B[0;91m"
66a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define COLOR_GREEN "\x1B[0;92m"
67a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define COLOR_YELLOW "\x1B[0;93m"
68a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define COLOR_BLUE "\x1B[0;94m"
69a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define COLOR_MAGENTA "\x1B[0;95m"
70a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define COLOR_BOLDGRAY "\x1B[1;30m"
71a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define COLOR_BOLDWHITE "\x1B[1;37m"
72a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define COLOR_BOLDYELLOW "\x1B[1;93m"
73a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski#define CLEAR_LINE "\x1B[2K"
74fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
755192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray#define CHECK_ARGS_COUNT(args, op, num, msg) \
7663b0519c3f0d1c0cc523e0e9553c60fc68651accChih-Hung Hsieh  if (!((args).size() op num)) {             \
77a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    PrintError(msg);                         \
78a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    return;                                  \
795192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  }
805192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray#define CHECK_NO_ARGS(args) \
815192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_ARGS_COUNT(args, ==, 0, "Expected no arguments")
825192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
8339a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray// TODO(armansito): Clean up this code. Right now everything is in this
8439a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray// monolithic file. We should organize this into different classes for command
8539a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray// handling, console output/printing, callback handling, etc.
8639a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray// (See http://b/23387611)
8739a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
8839a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray// Used to synchronize the printing of the command-line prompt and incoming
8939a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray// Binder callbacks.
9039a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguraystd::atomic_bool showing_prompt(false);
9139a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
922e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray// The registered IBluetoothLowEnergy client handle. If |ble_registering| is
932e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray// true then an operation to register the client is in progress.
942e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguraystd::atomic_bool ble_registering(false);
954fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguraystd::atomic_int ble_client_id(0);
964fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
979ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson// The registered IBluetoothLeAdvertiser handle. If |ble_advertiser_registering|
989ca07091a1f07ea201cee0504dab6a1d7073d429Myles Watson// is true then an operation to register the advertiser is in progress.
99daa8a99913a211a30dda08bd731e44ad49a6a4e8Jakub Pawlowskiconst int invalid_advertiser_id = -1;
10067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskistd::atomic_bool ble_advertiser_registering(false);
101daa8a99913a211a30dda08bd731e44ad49a6a4e8Jakub Pawlowskistd::atomic_int ble_advertiser_id(invalid_advertiser_id);
10267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
103c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski// The registered IBluetoothLeScanner handle. If |ble_scanner_registering| is
104c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski// true then an operation to register the scanner is in progress.
105c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowskistd::atomic_bool ble_scanner_registering(false);
106c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowskistd::atomic_int ble_scanner_id(0);
107c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski
1084fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray// The registered IBluetoothGattClient client handle. If |gatt_registering| is
1094fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray// true then an operation to register the client is in progress.
1104fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguraystd::atomic_bool gatt_registering(false);
1114fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguraystd::atomic_int gatt_client_id(0);
1122e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
113ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski// True if we should dump the scan record bytes for incoming scan results.
114ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowskistd::atomic_bool dump_scan_record(false);
115ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
1162e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray// True if the remote process has died and we should exit.
1172e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguraystd::atomic_bool should_exit(false);
1182e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
119a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskistd::string kServiceName = "bluetooth-service";
120a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski
121a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskivoid PrintPrompt() { cout << COLOR_BLUE "[FCLI] " COLOR_OFF << flush; }
12239a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
1232e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayvoid PrintError(const string& message) {
1242e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  cout << COLOR_RED << message << COLOR_OFF << endl;
1252e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray}
1262e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
127d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Ugurayvoid PrintOpStatus(const std::string& op, bool status) {
128d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  cout << COLOR_BOLDWHITE << op << " status: " COLOR_OFF
129d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray       << (status ? (COLOR_GREEN "success") : (COLOR_RED "failure"))
13064401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski       << COLOR_OFF << endl;
13164401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski}
13264401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski
13364401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowskiinline void BeginAsyncOut() {
134a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  if (showing_prompt.load()) cout << CLEAR_LINE << "\r";
13564401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski}
13664401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski
13764401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowskiinline void EndAsyncOut() {
13864401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski  std::flush(cout);
13964401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski  if (showing_prompt.load())
140a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    PrintPrompt();
14164401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski  else
14264401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    cout << endl;
143d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray}
144d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
145a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskiclass CLIBluetoothCallback : public android::bluetooth::BnBluetoothCallback {
14639a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray public:
14739a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  CLIBluetoothCallback() = default;
14839a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  ~CLIBluetoothCallback() override = default;
14939a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
1502e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  // IBluetoothCallback overrides:
151a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  Status OnBluetoothStateChange(int32_t prev_state,
152a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski                                int32_t new_state) override {
15364401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    BeginAsyncOut();
154a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    cout << COLOR_BOLDWHITE "Adapter state changed: " COLOR_OFF << COLOR_MAGENTA
155a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski         << AdapterStateToString(bluetooth::AdapterState(prev_state))
156a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski         << COLOR_OFF << COLOR_BOLDWHITE " -> " COLOR_OFF << COLOR_BOLDYELLOW
157a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski         << AdapterStateToString(bluetooth::AdapterState(new_state))
158a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski         << COLOR_OFF;
15964401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    EndAsyncOut();
160a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski
161a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    return Status::ok();
162a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  }
16339a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
16439a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray private:
16539a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  DISALLOW_COPY_AND_ASSIGN(CLIBluetoothCallback);
16639a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray};
16739a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
1682e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayclass CLIBluetoothLowEnergyCallback
169a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    : public android::bluetooth::BnBluetoothLowEnergyCallback {
1702e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray public:
1712e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  CLIBluetoothLowEnergyCallback() = default;
1724fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  ~CLIBluetoothLowEnergyCallback() override = default;
1732e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
1742e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  // IBluetoothLowEnergyCallback overrides:
175a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  Status OnClientRegistered(int status, int client_id) override {
17664401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    BeginAsyncOut();
1772e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    if (status != bluetooth::BLE_STATUS_SUCCESS) {
1782e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray      PrintError("Failed to register BLE client");
1792e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    } else {
1804fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray      ble_client_id = client_id;
1812e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray      cout << COLOR_BOLDWHITE "Registered BLE client with ID: " COLOR_OFF
18264401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski           << COLOR_GREEN << client_id << COLOR_OFF;
1832e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    }
18464401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    EndAsyncOut();
1852e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
1862e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    ble_registering = false;
187a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    return Status::ok();
1882e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
1892e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
190a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  Status OnConnectionState(int status, int client_id, const String16& address,
191a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski                           bool connected) override {
19264401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    BeginAsyncOut();
193a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    cout << COLOR_BOLDWHITE "Connection state: " << COLOR_BOLDYELLOW "["
194a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski         << address << " connected: " << (connected ? "true" : "false") << " ] "
195608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski         << COLOR_BOLDWHITE "- status: " << status
196608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski         << COLOR_BOLDWHITE " - client_id: " << client_id << COLOR_OFF;
19764401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    EndAsyncOut();
198a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    return Status::ok();
199455dc8f535a719af6a65a7512d90f9db878f5a58Jakub Pawlowski  }
200455dc8f535a719af6a65a7512d90f9db878f5a58Jakub Pawlowski
201a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  Status OnMtuChanged(int status, const String16& address, int mtu) override {
20264401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    BeginAsyncOut();
203a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    cout << COLOR_BOLDWHITE "MTU changed: " << COLOR_BOLDYELLOW "[" << address
204a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski         << " ] " << COLOR_BOLDWHITE " - status: " << status
205a6551079fe71b1c76505ada0e4f758f6faf651e0Jakub Pawlowski         << COLOR_BOLDWHITE " - mtu: " << mtu << COLOR_OFF;
20664401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    EndAsyncOut();
207a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    return Status::ok();
208a6551079fe71b1c76505ada0e4f758f6faf651e0Jakub Pawlowski  }
209a6551079fe71b1c76505ada0e4f758f6faf651e0Jakub Pawlowski
21067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski private:
21167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLowEnergyCallback);
21267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski};
21367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
21467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowskiclass CLIBluetoothLeAdvertiserCallback
21567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    : public android::bluetooth::BnBluetoothLeAdvertiserCallback {
21667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski public:
21767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  CLIBluetoothLeAdvertiserCallback() = default;
21867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  ~CLIBluetoothLeAdvertiserCallback() override = default;
21967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
22067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  // IBluetoothLowEnergyCallback overrides:
22167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  Status OnAdvertiserRegistered(int status, int advertiser_id) override {
22267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    BeginAsyncOut();
22367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    if (status != bluetooth::BLE_STATUS_SUCCESS) {
22467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski      PrintError("Failed to register BLE advertiser");
22567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    } else {
22667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski      ble_advertiser_id = advertiser_id;
22767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski      cout << COLOR_BOLDWHITE "Registered BLE advertiser with ID: " COLOR_OFF
22867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski           << COLOR_GREEN << advertiser_id << COLOR_OFF;
22967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    }
23067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    EndAsyncOut();
23167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
23267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    ble_advertiser_registering = false;
23367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    return Status::ok();
23467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  }
23567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
236a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  Status OnMultiAdvertiseCallback(
23752bfc6060cec652a67c8989e0548225af0008be1Arman Uguray      int status, bool is_start,
238a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski      const android::bluetooth::AdvertiseSettings& /* settings */) {
23964401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    BeginAsyncOut();
240d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    std::string op = is_start ? "start" : "stop";
241d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
242d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    PrintOpStatus("Advertising " + op, status == bluetooth::BLE_STATUS_SUCCESS);
24364401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    EndAsyncOut();
244a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    return Status::ok();
24552bfc6060cec652a67c8989e0548225af0008be1Arman Uguray  }
24652bfc6060cec652a67c8989e0548225af0008be1Arman Uguray
2472e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray private:
24867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLeAdvertiserCallback);
2492e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray};
2505192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
251c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowskiclass CLIBluetoothLeScannerCallback
252c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    : public android::bluetooth::BnBluetoothLeScannerCallback {
253c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski public:
254c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  CLIBluetoothLeScannerCallback() = default;
255c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  ~CLIBluetoothLeScannerCallback() override = default;
256c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski
257c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  // IBluetoothLowEnergyCallback overrides:
258c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  Status OnScannerRegistered(int status, int scanner_id) override {
259c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    BeginAsyncOut();
260c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    if (status != bluetooth::BLE_STATUS_SUCCESS) {
261c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski      PrintError("Failed to register BLE client");
262c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    } else {
263c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski      ble_scanner_id = scanner_id;
264c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski      cout << COLOR_BOLDWHITE "Registered BLE client with ID: " COLOR_OFF
265c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski           << COLOR_GREEN << scanner_id << COLOR_OFF;
266c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    }
267c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    EndAsyncOut();
268c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski
269c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    ble_scanner_registering = false;
270c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    return Status::ok();
271c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  }
272c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski
273c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  Status OnScanResult(
274c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski      const android::bluetooth::ScanResult& scan_result) override {
275c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    BeginAsyncOut();
276c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    cout << COLOR_BOLDWHITE "Scan result: " << COLOR_BOLDYELLOW "["
277c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski         << scan_result.device_address() << "] "
278c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski         << COLOR_BOLDWHITE "- RSSI: " << scan_result.rssi() << COLOR_OFF;
279c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski
280c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    if (dump_scan_record) {
281c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski      cout << " - Record: "
282c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski           << base::HexEncode(scan_result.scan_record().data(),
283c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski                              scan_result.scan_record().size());
284c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    }
285c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    EndAsyncOut();
286c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    return Status::ok();
287c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  }
288c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski
289c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski private:
290c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLeScannerCallback);
291c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski};
292c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski
2934fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Ugurayclass CLIGattClientCallback
294a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    : public android::bluetooth::BnBluetoothGattClientCallback {
2954fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray public:
2964fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  CLIGattClientCallback() = default;
2974fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  ~CLIGattClientCallback() override = default;
2984fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
2994fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  // IBluetoothGattClientCallback overrides:
300a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  Status OnClientRegistered(int status, int client_id) override {
30164401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    BeginAsyncOut();
3024fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    if (status != bluetooth::BLE_STATUS_SUCCESS) {
3034fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray      PrintError("Failed to register GATT client");
3044fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    } else {
3054fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray      gatt_client_id = client_id;
3064fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray      cout << COLOR_BOLDWHITE "Registered GATT client with ID: " COLOR_OFF
30764401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski           << COLOR_GREEN << client_id << COLOR_OFF;
3084fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    }
30964401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    EndAsyncOut();
3104fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
3114fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    gatt_registering = false;
312a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    return Status::ok();
3134fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  }
3144fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
3154fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray private:
3164fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  DISALLOW_COPY_AND_ASSIGN(CLIGattClientCallback);
3174fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray};
3184fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
319a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowskivoid PrintCommandStatus(bool status) { PrintOpStatus("Command", status); }
320fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
3215192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid PrintFieldAndValue(const string& field, const string& value) {
3225192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  cout << COLOR_BOLDWHITE << field << ": " << COLOR_BOLDYELLOW << value
3235192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray       << COLOR_OFF << endl;
3245192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray}
3255192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
3265192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid PrintFieldAndBoolValue(const string& field, bool value) {
3275192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  PrintFieldAndValue(field, (value ? "true" : "false"));
3285192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray}
3295192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
3305192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleDisable(IBluetooth* bt_iface, const vector<string>& args) {
3315192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
332a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
333a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->Disable(&status);
334a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintCommandStatus(status);
335fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray}
336fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
3375192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleEnable(IBluetooth* bt_iface, const vector<string>& args) {
3387b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker  bool is_restricted_mode = false;
3397b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker
3407b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker  for (auto iter : args) {
3417b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker    const std::string& arg = iter;
3427b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker    if (arg == "-h") {
3437b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker      static const char kUsage[] =
3447b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker          "Usage: start-adv [flags]\n"
3457b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker          "\n"
3467b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker          "Flags:\n"
3477b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker          "\t--restricted|-r\tStart in restricted mode\n";
3487b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker      cout << kUsage << endl;
3497b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker      return;
3507b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker    } else if (arg == "--restricted" || arg == "-r") {
3517b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker      is_restricted_mode = true;
3527b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker    }
3537b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker  }
3547b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker
355a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
3567b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker  bt_iface->Enable(is_restricted_mode, &status);
357a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintCommandStatus(status);
358fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray}
359fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
3605192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleGetState(IBluetooth* bt_iface, const vector<string>& args) {
3615192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
362a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski
363a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  int32_t st;
364a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetState(&st);
365a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bluetooth::AdapterState state = static_cast<bluetooth::AdapterState>(st);
3665192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  PrintFieldAndValue("Adapter state", bluetooth::AdapterStateToString(state));
367fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray}
368fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
3695192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleIsEnabled(IBluetooth* bt_iface, const vector<string>& args) {
3705192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
371a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool enabled;
372a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->IsEnabled(&enabled);
3735192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  PrintFieldAndBoolValue("Adapter enabled", enabled);
374fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray}
375fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
3765192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleGetLocalAddress(IBluetooth* bt_iface, const vector<string>& args) {
3775192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
378a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  String16 address;
379a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetAddress(&address);
380a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintFieldAndValue("Adapter address", std::string(String8(address).string()));
3815192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray}
3825192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
3835192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleSetLocalName(IBluetooth* bt_iface, const vector<string>& args) {
3845192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_ARGS_COUNT(args, >=, 1, "No name was given");
3855192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
3865192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  std::string name;
387a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  for (const auto& arg : args) name += arg + " ";
3885192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
3895192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  base::TrimWhitespaceASCII(name, base::TRIM_TRAILING, &name);
3905192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
391a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
392a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->SetName(String16(String8(name.c_str())), &status);
393a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintCommandStatus(status);
3945192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray}
3955192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
3965192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleGetLocalName(IBluetooth* bt_iface, const vector<string>& args) {
3975192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
398a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  String16 name;
399a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetName(&name);
400a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintFieldAndValue("Adapter name", std::string(String8(name).string()));
4015192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray}
4025192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
4035192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleAdapterInfo(IBluetooth* bt_iface, const vector<string>& args) {
4045192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
4055192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
4065192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  cout << COLOR_BOLDWHITE "Adapter Properties: " COLOR_OFF << endl;
4075192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
408a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  String16 address;
409a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetAddress(&address);
410a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintFieldAndValue("\tAddress", std::string(String8(address).string()));
411a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski
412a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  int adapter_state;
413a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetState(&adapter_state);
414a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintFieldAndValue("\tState",
415a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski                     bluetooth::AdapterStateToString(
416a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski                         static_cast<bluetooth::AdapterState>(adapter_state)));
417a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski
418a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  String16 name;
419a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetName(&name);
420a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintFieldAndValue("\tName", std::string(String8(name).string()));
421a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski
422a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool multi_adv;
423a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->IsMultiAdvertisementSupported(&multi_adv);
424a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintFieldAndBoolValue("\tMulti-Adv. supported", multi_adv);
42510b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray}
42610b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray
42710b54c4b7f1a863a27eca4158f256062ec9c3770Arman Ugurayvoid HandleSupportsMultiAdv(IBluetooth* bt_iface, const vector<string>& args) {
42810b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray  CHECK_NO_ARGS(args);
42910b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray
430a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool multi_adv;
431a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->IsMultiAdvertisementSupported(&multi_adv);
432a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  PrintFieldAndBoolValue("Multi-advertisement support", multi_adv);
4335192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray}
4345192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
435911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid HandleRegisterBLEAdvertiser(IBluetooth* bt_iface,
436911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                 const vector<string>& args) {
43767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  CHECK_NO_ARGS(args);
43867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
43967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  if (ble_advertiser_registering.load()) {
44067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    PrintError("In progress");
44167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    return;
44267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  }
44367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
444daa8a99913a211a30dda08bd731e44ad49a6a4e8Jakub Pawlowski  if (ble_advertiser_id.load() != invalid_advertiser_id) {
44567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    PrintError("Already registered");
44667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    return;
44767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  }
44867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
44967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  sp<IBluetoothLeAdvertiser> ble_advertiser_iface;
45067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  bt_iface->GetLeAdvertiserInterface(&ble_advertiser_iface);
45167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  if (!ble_advertiser_iface.get()) {
45267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    PrintError("Failed to obtain handle to Bluetooth Le Advertiser interface");
45367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    return;
45467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  }
45567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
45667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  bool status;
457911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  ble_advertiser_iface->RegisterAdvertiser(
458911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      new CLIBluetoothLeAdvertiserCallback(), &status);
45967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  ble_advertiser_registering = status;
46067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  PrintCommandStatus(status);
46167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski}
46267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
463911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid HandleUnregisterBLEAdvertiser(IBluetooth* bt_iface,
464911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                   const vector<string>& args) {
46567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  CHECK_NO_ARGS(args);
46667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
467daa8a99913a211a30dda08bd731e44ad49a6a4e8Jakub Pawlowski  if (ble_advertiser_id.load() == invalid_advertiser_id) {
46867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    PrintError("Not registered");
46967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    return;
47067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  }
47167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
47267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  sp<IBluetoothLeAdvertiser> ble_advertiser_iface;
47367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  bt_iface->GetLeAdvertiserInterface(&ble_advertiser_iface);
47467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  if (!ble_advertiser_iface.get()) {
47567d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
47667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    return;
47767d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  }
47867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
47967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  ble_advertiser_iface->UnregisterAdvertiser(ble_advertiser_id.load());
480daa8a99913a211a30dda08bd731e44ad49a6a4e8Jakub Pawlowski  ble_advertiser_id = invalid_advertiser_id;
48167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  PrintCommandStatus(true);
48267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski}
48367d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski
4842e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayvoid HandleRegisterBLE(IBluetooth* bt_iface, const vector<string>& args) {
4852e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  CHECK_NO_ARGS(args);
4862e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
4872e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  if (ble_registering.load()) {
4882e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    PrintError("In progress");
4892e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return;
4902e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
4912e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
4924fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  if (ble_client_id.load()) {
4932e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    PrintError("Already registered");
4942e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return;
4952e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
4962e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
497a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetoothLowEnergy> ble_iface;
498a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetLowEnergyInterface(&ble_iface);
4992e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  if (!ble_iface.get()) {
5002e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
5012e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return;
5022e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
5032e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
504a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
505a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  ble_iface->RegisterClient(new CLIBluetoothLowEnergyCallback(), &status);
506ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray  ble_registering = status;
507ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray  PrintCommandStatus(status);
5082e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray}
5092e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
5102e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayvoid HandleUnregisterBLE(IBluetooth* bt_iface, const vector<string>& args) {
5112e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  CHECK_NO_ARGS(args);
5122e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
5134fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  if (!ble_client_id.load()) {
5142e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    PrintError("Not registered");
5152e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return;
5162e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
5172e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
518a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetoothLowEnergy> ble_iface;
519a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetLowEnergyInterface(&ble_iface);
5202e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  if (!ble_iface.get()) {
5212e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
5222e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return;
5232e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
5242e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
5254fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  ble_iface->UnregisterClient(ble_client_id.load());
5264fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  ble_client_id = 0;
5272e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  PrintCommandStatus(true);
5282e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray}
5292e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
5302e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayvoid HandleUnregisterAllBLE(IBluetooth* bt_iface, const vector<string>& args) {
5312e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  CHECK_NO_ARGS(args);
5322e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
533a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetoothLowEnergy> ble_iface;
534a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetLowEnergyInterface(&ble_iface);
5352e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  if (!ble_iface.get()) {
5362e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
5372e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return;
5382e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
5392e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
5402e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  ble_iface->UnregisterAll();
5412e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  PrintCommandStatus(true);
5422e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray}
5432e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
5444fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Ugurayvoid HandleRegisterGATT(IBluetooth* bt_iface, const vector<string>& args) {
5454fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  CHECK_NO_ARGS(args);
5464fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
5474fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  if (gatt_registering.load()) {
5484fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    PrintError("In progress");
5494fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    return;
5504fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  }
5514fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
5524fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  if (gatt_client_id.load()) {
5534fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    PrintError("Already registered");
5544fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    return;
5554fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  }
5564fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
557a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetoothGattClient> gatt_iface;
558a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetGattClientInterface(&gatt_iface);
5594fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  if (!gatt_iface.get()) {
5604fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    PrintError("Failed to obtain handle to Bluetooth GATT Client interface");
5614fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    return;
5624fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  }
5634fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
564a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
565a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  gatt_iface->RegisterClient(new CLIGattClientCallback(), &status);
5664fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  gatt_registering = status;
5674fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  PrintCommandStatus(status);
5684fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray}
5694fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
5704fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Ugurayvoid HandleUnregisterGATT(IBluetooth* bt_iface, const vector<string>& args) {
5714fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  CHECK_NO_ARGS(args);
5724fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
5734fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  if (!gatt_client_id.load()) {
5744fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    PrintError("Not registered");
5754fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    return;
5764fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  }
5774fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
578a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetoothGattClient> gatt_iface;
579a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetGattClientInterface(&gatt_iface);
5804fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  if (!gatt_iface.get()) {
5814fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    PrintError("Failed to obtain handle to Bluetooth GATT Client interface");
5824fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray    return;
5834fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  }
5844fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
5854fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  gatt_iface->UnregisterClient(gatt_client_id.load());
5864fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  gatt_client_id = 0;
5874fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray  PrintCommandStatus(true);
5884fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray}
5894fbbf6047f182b9dfbf11d5d8da7281845fce99eArman Uguray
590d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Ugurayvoid HandleStartAdv(IBluetooth* bt_iface, const vector<string>& args) {
591d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  bool include_name = false;
592d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  bool include_tx_power = false;
593d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  bool connectable = false;
594d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  bool set_manufacturer_data = false;
59587222e0e826216c69f6a9a5bfe77689561067474Arman Uguray  bool set_uuid = false;
596819e2ecb84a22d6e03ec9ed67b3260c0dd7e8abaJakub Pawlowski  bluetooth::Uuid uuid;
597d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
59887222e0e826216c69f6a9a5bfe77689561067474Arman Uguray  for (auto iter = args.begin(); iter != args.end(); ++iter) {
59987222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    const std::string& arg = *iter;
600d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    if (arg == "-n")
601d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray      include_name = true;
602d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    else if (arg == "-t")
603d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray      include_tx_power = true;
604d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    else if (arg == "-c")
605d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray      connectable = true;
606d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    else if (arg == "-m")
607d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray      set_manufacturer_data = true;
60887222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    else if (arg == "-u") {
60987222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      // This flag has a single argument.
61087222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      ++iter;
61187222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      if (iter == args.end()) {
612819e2ecb84a22d6e03ec9ed67b3260c0dd7e8abaJakub Pawlowski        PrintError("Expected a Uuid after -u");
61387222e0e826216c69f6a9a5bfe77689561067474Arman Uguray        return;
61487222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      }
61587222e0e826216c69f6a9a5bfe77689561067474Arman Uguray
61687222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      std::string uuid_str = *iter;
617819e2ecb84a22d6e03ec9ed67b3260c0dd7e8abaJakub Pawlowski      bool is_valid = false;
618819e2ecb84a22d6e03ec9ed67b3260c0dd7e8abaJakub Pawlowski      uuid = bluetooth::Uuid::FromString(uuid_str, &is_valid);
619819e2ecb84a22d6e03ec9ed67b3260c0dd7e8abaJakub Pawlowski      if (!is_valid) {
620819e2ecb84a22d6e03ec9ed67b3260c0dd7e8abaJakub Pawlowski        PrintError("Invalid Uuid: " + uuid_str);
62187222e0e826216c69f6a9a5bfe77689561067474Arman Uguray        return;
62287222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      }
62387222e0e826216c69f6a9a5bfe77689561067474Arman Uguray
62487222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      set_uuid = true;
625a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    } else if (arg == "-h") {
626ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski      static const char kUsage[] =
627d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray          "Usage: start-adv [flags]\n"
628d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray          "\n"
629ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski          "Flags:\n"
630d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray          "\t-n\tInclude device name\n"
631d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray          "\t-t\tInclude TX power\n"
632d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray          "\t-c\tSend connectable adv. packets (default is non-connectable)\n"
633d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray          "\t-m\tInclude random manufacturer data\n"
634d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray          "\t-h\tShow this help message\n";
635d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray      cout << kUsage << endl;
636d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray      return;
637a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    } else {
638d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray      PrintError("Unrecognized option: " + arg);
639d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray      return;
640d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    }
641d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  }
642d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
643daa8a99913a211a30dda08bd731e44ad49a6a4e8Jakub Pawlowski  if (ble_advertiser_id.load() == invalid_advertiser_id) {
64467d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    PrintError("BLE advertiser not registered");
645d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    return;
646d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  }
647d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
64867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  sp<IBluetoothLeAdvertiser> ble_advertiser_iface;
64967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  bt_iface->GetLeAdvertiserInterface(&ble_advertiser_iface);
65067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  if (!ble_advertiser_iface.get()) {
65167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    PrintError("Failed to obtain handle to Bluetooth Le Advertiser interface");
652d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    return;
653d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  }
654d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
655d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  std::vector<uint8_t> data;
656d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  if (set_manufacturer_data) {
657a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    data = {{0x07, bluetooth::kEIRTypeManufacturerSpecificData, 0xe0, 0x00, 'T',
658a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski             'e', 's', 't'}};
659d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  }
660d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
66187222e0e826216c69f6a9a5bfe77689561067474Arman Uguray  if (set_uuid) {
66287222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    // Determine the type and length bytes.
66387222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    int uuid_size = uuid.GetShortestRepresentationSize();
66487222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    uint8_t type;
665819e2ecb84a22d6e03ec9ed67b3260c0dd7e8abaJakub Pawlowski    if (uuid_size == bluetooth::Uuid::kNumBytes128)
666819e2ecb84a22d6e03ec9ed67b3260c0dd7e8abaJakub Pawlowski      type = bluetooth::kEIRTypeComplete128BitUuids;
667819e2ecb84a22d6e03ec9ed67b3260c0dd7e8abaJakub Pawlowski    else if (uuid_size == bluetooth::Uuid::kNumBytes32)
668819e2ecb84a22d6e03ec9ed67b3260c0dd7e8abaJakub Pawlowski      type = bluetooth::kEIRTypeComplete32BitUuids;
669819e2ecb84a22d6e03ec9ed67b3260c0dd7e8abaJakub Pawlowski    else if (uuid_size == bluetooth::Uuid::kNumBytes16)
670819e2ecb84a22d6e03ec9ed67b3260c0dd7e8abaJakub Pawlowski      type = bluetooth::kEIRTypeComplete16BitUuids;
67187222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    else
67287222e0e826216c69f6a9a5bfe77689561067474Arman Uguray      NOTREACHED() << "Unexpected size: " << uuid_size;
67387222e0e826216c69f6a9a5bfe77689561067474Arman Uguray
67487222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    data.push_back(uuid_size + 1);
67587222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    data.push_back(type);
67687222e0e826216c69f6a9a5bfe77689561067474Arman Uguray
677819e2ecb84a22d6e03ec9ed67b3260c0dd7e8abaJakub Pawlowski    auto uuid_bytes = uuid.To128BitLE();
67887222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    int index = (uuid_size == 16) ? 0 : 12;
67987222e0e826216c69f6a9a5bfe77689561067474Arman Uguray    data.insert(data.end(), uuid_bytes.data() + index,
68087222e0e826216c69f6a9a5bfe77689561067474Arman Uguray                uuid_bytes.data() + index + uuid_size);
68187222e0e826216c69f6a9a5bfe77689561067474Arman Uguray  }
68287222e0e826216c69f6a9a5bfe77689561067474Arman Uguray
683d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  base::TimeDelta timeout;
684d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
685d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  bluetooth::AdvertiseSettings settings(
686a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski      bluetooth::AdvertiseSettings::MODE_LOW_POWER, timeout,
687a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski      bluetooth::AdvertiseSettings::TX_POWER_LEVEL_MEDIUM, connectable);
688d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
6890ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski  if (include_tx_power) {
6900ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski    data.push_back(0x02);
6910ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski    data.push_back(bluetooth::kEIRTypeTxPower);
6920ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski    data.push_back(0x00);
6930ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski  }
6940ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski
695d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  bluetooth::AdvertiseData adv_data(data);
6960ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski
6970ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski  if (include_name) {
6980ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski    String16 name_param;
6990ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski    bt_iface->GetName(&name_param);
7000ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski    std::string name(String8(name_param).string());
7010ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski    data.push_back(name.length() + 1);
7020ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski    data.push_back(bluetooth::kEIRTypeCompleteLocalName);
7030ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski    data.insert(data.begin(), name.c_str(), name.c_str() + name.length());
7040ecddf398c92324e15a53c9d410646fd7a494b96Jakub Pawlowski  }
705d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
706d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  bluetooth::AdvertiseData scan_rsp;
707d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
708a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
709911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  ble_advertiser_iface->StartMultiAdvertising(
710911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      ble_advertiser_id.load(), adv_data, scan_rsp, settings, &status);
711ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray  PrintCommandStatus(status);
712d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray}
713d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
714d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Ugurayvoid HandleStopAdv(IBluetooth* bt_iface, const vector<string>& args) {
715daa8a99913a211a30dda08bd731e44ad49a6a4e8Jakub Pawlowski  if (ble_advertiser_id.load() == invalid_advertiser_id) {
71667d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    PrintError("BLE advertiser not registered");
717d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    return;
718d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  }
719d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
72067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  sp<IBluetoothLeAdvertiser> ble_advertiser_iface;
72167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  bt_iface->GetLeAdvertiserInterface(&ble_advertiser_iface);
72267d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  if (!ble_advertiser_iface.get()) {
723d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
724d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray    return;
725d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray  }
726d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
727a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
72867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski  ble_advertiser_iface->StopMultiAdvertising(ble_advertiser_id.load(), &status);
729ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray  PrintCommandStatus(status);
730d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray}
731d19bc0457a9b6519acd6a79c3ac7de653894f5ecArman Uguray
732608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowskivoid HandleConnect(IBluetooth* bt_iface, const vector<string>& args) {
733608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  string address;
734608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
735608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  if (args.size() != 1) {
736608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    PrintError("Expected MAC address as only argument");
737608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    return;
738608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  }
739608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
740608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  address = args[0];
741608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
742608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  if (!ble_client_id.load()) {
743608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    PrintError("BLE not registered");
744608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    return;
745608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  }
746608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
747a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetoothLowEnergy> ble_iface;
748a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetLowEnergyInterface(&ble_iface);
749608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  if (!ble_iface.get()) {
750608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
751608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    return;
752608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  }
753608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
754a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
755a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  ble_iface->Connect(ble_client_id.load(),
756a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski                     String16(address.c_str(), address.length()),
757a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski                     false /*  is_direct */, &status);
758608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
759608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  PrintCommandStatus(status);
760608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski}
761608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
762608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowskivoid HandleDisconnect(IBluetooth* bt_iface, const vector<string>& args) {
763608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  string address;
764608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
765608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  if (args.size() != 1) {
766608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    PrintError("Expected MAC address as only argument");
767608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    return;
768608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  }
769608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
770608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  address = args[0];
771608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
772608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  if (!ble_client_id.load()) {
773608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    PrintError("BLE not registered");
774608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    return;
775608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  }
776608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
777a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetoothLowEnergy> ble_iface;
778a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetLowEnergyInterface(&ble_iface);
779608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  if (!ble_iface.get()) {
780608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
781608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski    return;
782608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  }
783608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
784a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
785a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  ble_iface->Disconnect(ble_client_id.load(),
786a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski                        String16(address.c_str(), address.length()), &status);
787608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski  PrintCommandStatus(status);
788608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski}
789608762d5769b948387c8d76e7f1d5a60db1850aeJakub Pawlowski
790756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowskivoid HandleSetMtu(IBluetooth* bt_iface, const vector<string>& args) {
791756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  string address;
792756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  int mtu;
793756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski
794756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  if (args.size() != 2) {
795756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski    PrintError("Usage: set-mtu [address] [mtu]");
796756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski    return;
797756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  }
798756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski
799756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  address = args[0];
800756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  mtu = std::stoi(args[1]);
801756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski
802756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  if (mtu < 23) {
803756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski    PrintError("MTU must be 23 or larger");
804756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski    return;
805756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  }
806756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski
807756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  if (!ble_client_id.load()) {
808756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski    PrintError("BLE not registered");
809756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski    return;
810756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  }
811756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski
812a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetoothLowEnergy> ble_iface;
813a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bt_iface->GetLowEnergyInterface(&ble_iface);
814756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  if (!ble_iface.get()) {
815756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
816756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski    return;
817756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  }
818756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski
819a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
820a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  ble_iface->SetMtu(ble_client_id.load(),
821a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski                    String16(address.c_str(), address.length()), mtu, &status);
822756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski  PrintCommandStatus(status);
823756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski}
824756cc4bdedca24e4ba157902a3d0b411cfa109beJakub Pawlowski
825911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid HandleRegisterBLEScanner(IBluetooth* bt_iface,
826911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                              const vector<string>& args) {
827c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  CHECK_NO_ARGS(args);
828c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski
829c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  if (ble_scanner_registering.load()) {
830c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    PrintError("In progress");
831c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    return;
832c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  }
833c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski
834c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  if (ble_scanner_id.load()) {
835c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    PrintError("Already registered");
836c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    return;
837c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  }
838c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski
839c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  sp<IBluetoothLeScanner> ble_scanner_iface;
840c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  bt_iface->GetLeScannerInterface(&ble_scanner_iface);
841c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  if (!ble_scanner_iface.get()) {
842c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    PrintError("Failed to obtain handle to Bluetooth LE Scanner interface");
843c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    return;
844c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  }
845c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski
846c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  bool status;
847911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  ble_scanner_iface->RegisterScanner(new CLIBluetoothLeScannerCallback(),
848911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                     &status);
849c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  ble_scanner_registering = status;
850c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  PrintCommandStatus(status);
851c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski}
852c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski
853911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonvoid HandleUnregisterBLEScanner(IBluetooth* bt_iface,
854911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                const vector<string>& args) {
855c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  CHECK_NO_ARGS(args);
856c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski
857c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  if (!ble_scanner_id.load()) {
858c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    PrintError("Not registered");
859c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    return;
860c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  }
861c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski
862c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  sp<IBluetoothLeScanner> ble_scanner_iface;
863c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  bt_iface->GetLeScannerInterface(&ble_scanner_iface);
864c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  if (!ble_scanner_iface.get()) {
865c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    PrintError("Failed to obtain handle to Bluetooth LE scanner interface");
866c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    return;
867c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  }
868c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski
869c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  ble_scanner_iface->UnregisterScanner(ble_scanner_id.load());
870c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  ble_scanner_id = 0;
871c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  PrintCommandStatus(true);
872c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski}
873c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski
874ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowskivoid HandleStartLeScan(IBluetooth* bt_iface, const vector<string>& args) {
875ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  if (!ble_client_id.load()) {
876ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    PrintError("BLE not registered");
877ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    return;
878ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  }
879ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
8805dc0d15e7865104d13be75c06de4b9158ce7dff4Chih-Hung Hsieh  for (const auto& arg : args) {
881ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    if (arg == "-d") {
882ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski      dump_scan_record = true;
883ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    } else if (arg == "-h") {
884ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski      static const char kUsage[] =
885ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski          "Usage: start-le-scan [flags]\n"
886ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski          "\n"
887ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski          "Flags:\n"
888ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski          "\t-d\tDump scan record\n"
889ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski          "\t-h\tShow this help message\n";
890ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski      cout << kUsage << endl;
891ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski      return;
892ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    }
893ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  }
894ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
895c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  sp<IBluetoothLeScanner> ble_scanner_iface;
896c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  bt_iface->GetLeScannerInterface(&ble_scanner_iface);
897c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  if (!ble_scanner_iface.get()) {
898c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    PrintError("Failed to obtain handle to Bluetooth LE scanner interface");
899ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    return;
900ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  }
901ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
902ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  bluetooth::ScanSettings settings;
903a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  std::vector<android::bluetooth::ScanFilter> filters;
904ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
905a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
906911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  ble_scanner_iface->StartScan(ble_scanner_id.load(), settings, filters,
907911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                               &status);
908ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  PrintCommandStatus(status);
909ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski}
910ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
911ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowskivoid HandleStopLeScan(IBluetooth* bt_iface, const vector<string>& args) {
912ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  if (!ble_client_id.load()) {
913ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    PrintError("BLE not registered");
914ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    return;
915ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  }
916ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
917c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  sp<IBluetoothLeScanner> ble_scanner_iface;
918c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  bt_iface->GetLeScannerInterface(&ble_scanner_iface);
919c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  if (!ble_scanner_iface.get()) {
920c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    PrintError("Failed to obtain handle to Bluetooth LE scanner interface");
921ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski    return;
922ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  }
923ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
924a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  bool status;
925c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski  ble_scanner_iface->StopScan(ble_scanner_id.load(), &status);
926ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski  PrintCommandStatus(status);
927ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski}
928ba197a21d810b0ef814ed9c23dd3b290613751c7Jakub Pawlowski
9295192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleHelp(IBluetooth* bt_iface, const vector<string>& args);
9302117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray
931fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguraystruct {
932fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray  string command;
9335192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  void (*func)(IBluetooth*, const vector<string>& args);
9342117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray  string help;
935fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray} kCommandMap[] = {
936a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"help", HandleHelp, "\t\t\tDisplay this message"},
937a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"disable", HandleDisable, "\t\t\tDisable Bluetooth"},
9387b266be449e4f915c419199c2312eb31f70e63bcAjay Panicker    {"enable", HandleEnable, "\t\t\tEnable Bluetooth (-h for options)"},
939a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"get-state", HandleGetState, "\t\tGet the current adapter state"},
940a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"is-enabled", HandleIsEnabled, "\t\tReturn if Bluetooth is enabled"},
941a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"get-local-address", HandleGetLocalAddress,
942a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski     "\tGet the local adapter address"},
943a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"set-local-name", HandleSetLocalName, "\t\tSet the local adapter name"},
944a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"get-local-name", HandleGetLocalName, "\t\tGet the local adapter name"},
945a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"adapter-info", HandleAdapterInfo, "\t\tPrint adapter properties"},
946a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"supports-multi-adv", HandleSupportsMultiAdv,
947a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski     "\tWhether multi-advertisement is currently supported"},
94867d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    {"register-le-advertiser", HandleRegisterBLEAdvertiser,
94967d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski     "\t\tRegister with the Bluetooth Low Energy Advertiser interface"},
95067d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski    {"unregister-le-advertiser", HandleUnregisterBLEAdvertiser,
95167d5a2523314d9757b2472c3e828dbc1015df4feJakub Pawlowski     "\t\tUnregister from the Bluetooth LE Advertiser interface"},
952a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"register-ble", HandleRegisterBLE,
953a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski     "\t\tRegister with the Bluetooth Low Energy interface"},
954a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"unregister-ble", HandleUnregisterBLE,
955a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski     "\t\tUnregister from the Bluetooth Low Energy interface"},
956a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"unregister-all-ble", HandleUnregisterAllBLE,
957a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski     "\tUnregister all clients from the Bluetooth Low Energy interface"},
958a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"register-gatt", HandleRegisterGATT,
959a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski     "\t\tRegister with the Bluetooth GATT Client interface"},
960a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"unregister-gatt", HandleUnregisterGATT,
961a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski     "\t\tUnregister from the Bluetooth GATT Client interface"},
962a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"connect-le", HandleConnect, "\t\tConnect to LE device (-h for options)"},
963a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"disconnect-le", HandleDisconnect,
964a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski     "\t\tDisconnect LE device (-h for options)"},
965a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"set-mtu", HandleSetMtu, "\t\tSet MTU (-h for options)"},
966a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"start-adv", HandleStartAdv, "\t\tStart advertising (-h for options)"},
967a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"stop-adv", HandleStopAdv, "\t\tStop advertising"},
968c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    {"register-le-scanner", HandleRegisterBLEScanner,
969c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski     "\t\tRegister with the Bluetooth Low Energy scanner interface"},
970c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski    {"unregister-le-scanner", HandleUnregisterBLEScanner,
971c3f6a51615c4f26bce0b8b6e16757610dbd0b45bJakub Pawlowski     "\t\tUnregister from the Bluetooth LE scanner interface"},
972a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"start-le-scan", HandleStartLeScan,
973a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski     "\t\tStart LE device scan (-h for options)"},
974a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {"stop-le-scan", HandleStopLeScan, "\t\tStop LE device scan"},
975a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    {},
976fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray};
977f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
9785192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleHelp(IBluetooth* /* bt_iface */, const vector<string>& /* args */) {
9792117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray  cout << endl;
9802117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray  for (int i = 0; kCommandMap[i].func; i++)
9812117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray    cout << "\t" << kCommandMap[i].command << kCommandMap[i].help << endl;
9822117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray  cout << endl;
9832117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray}
9842117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray
9855d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssenconst char kExecuteLong[] = "exec";
9865d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssenconst char kExecuteShort[] = "e";
9875d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
988911d1ae03efec2d54c3b1b605589d790d1745488Myles Watsonbool ExecuteCommand(const sp<IBluetooth>& bt_iface, std::string& command) {
989911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  vector<string> args = base::SplitString(command, " ", base::TRIM_WHITESPACE,
990911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson                                          base::SPLIT_WANT_ALL);
9915d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
992911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson  if (args.empty()) return true;
9935d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
9945d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  // The first argument is the command while the remaining are what we pass to
9955d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  // the handler functions.
9965d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  command = args[0];
9975d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  args.erase(args.begin());
9985d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
9995d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  for (int i = 0; kCommandMap[i].func; i++) {
10005d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen    if (command == kCommandMap[i].command) {
10015d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen      kCommandMap[i].func(bt_iface.get(), args);
10025d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen      return true;
10035d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen    }
10045d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  }
10055d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
10065d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  cout << "Unrecognized command: " << command << endl;
10075d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  return false;
10085d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen}
10095d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
10102117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray}  // namespace
10112117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray
10122e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayclass BluetoothDeathRecipient : public android::IBinder::DeathRecipient {
10132e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray public:
10142e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  BluetoothDeathRecipient() = default;
10152e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  ~BluetoothDeathRecipient() override = default;
10162e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
10172e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  // android::IBinder::DeathRecipient override:
10182e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  void binderDied(const android::wp<android::IBinder>& /* who */) override {
101964401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    BeginAsyncOut();
10202e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    cout << COLOR_BOLDWHITE "The Bluetooth daemon has died" COLOR_OFF << endl;
102164401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    cout << "\nPress 'ENTER' to exit.";
102264401bf539bdef652ddcfc25138ad5e353aea1c3Jakub Pawlowski    EndAsyncOut();
10232e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
10242e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    android::IPCThreadState::self()->stopProcess();
10252e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    should_exit = true;
10262e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
10272e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
10282e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray private:
10292e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  DISALLOW_COPY_AND_ASSIGN(BluetoothDeathRecipient);
10302e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray};
10312e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
1032ae43de627b9c91e54215d439149c0e01599249c0Arman Ugurayint main(int argc, char* argv[]) {
1033ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray  base::AtExitManager exit_manager;
1034ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray  base::CommandLine::Init(argc, argv);
1035ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray  logging::LoggingSettings log_settings;
1036ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray
1037ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray  if (!logging::InitLogging(log_settings)) {
1038ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray    LOG(ERROR) << "Failed to set up logging";
1039ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray    return EXIT_FAILURE;
1040ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray  }
1041ae43de627b9c91e54215d439149c0e01599249c0Arman Uguray
1042a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  sp<IBluetooth> bt_iface;
1043a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  status_t status = getService(String16(kServiceName.c_str()), &bt_iface);
1044a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  if (status != OK) {
1045a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski    LOG(ERROR) << "Failed to get service binder: '" << kServiceName
1046a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski               << "' status=" << status;
1047f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray    return EXIT_FAILURE;
1048f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray  }
1049f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
10502e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  sp<BluetoothDeathRecipient> dr(new BluetoothDeathRecipient());
10512e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  if (android::IInterface::asBinder(bt_iface.get())->linkToDeath(dr) !=
10522e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray      android::NO_ERROR) {
10532e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    LOG(ERROR) << "Failed to register DeathRecipient for IBluetooth";
10542e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return EXIT_FAILURE;
10552e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
10562e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
105739a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  // Initialize the Binder process thread pool. We have to set this up,
105839a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  // otherwise, incoming callbacks from IBluetoothCallback will block the main
105939a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  // thread (in other words, we have to do this as we are a "Binder server").
106039a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  android::ProcessState::self()->startThreadPool();
106139a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
106239a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  // Register Adapter state-change callback
106339a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  sp<CLIBluetoothCallback> callback = new CLIBluetoothCallback();
106439a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  bt_iface->RegisterCallback(callback);
106539a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
1066a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski  cout << COLOR_BOLDWHITE << "Fluoride Command-Line Interface\n"
1067a4bd0d2370bd469942e92e724cfc9c7c01d3da74Jakub Pawlowski       << COLOR_OFF << endl
10682117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray       << "Type \"help\" to see possible commands.\n"
1069fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray       << endl;
1070fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
10715d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  string command;
10725d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
10735d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  // Add commands from the command line, if they exist.
10745d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  auto command_line = base::CommandLine::ForCurrentProcess();
10755d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  if (command_line->HasSwitch(kExecuteLong)) {
10765d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen    command += command_line->GetSwitchValueASCII(kExecuteLong);
10775d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  }
10785d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
10795d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  if (command_line->HasSwitch(kExecuteShort)) {
1080911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    if (!command.empty()) command += " ; ";
10815d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen    command += command_line->GetSwitchValueASCII(kExecuteShort);
10825d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen  }
10835d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
1084fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray  while (true) {
1085911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson    vector<string> commands = base::SplitString(
1086911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson        command, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
10875d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen    for (string command : commands) {
1088911d1ae03efec2d54c3b1b605589d790d1745488Myles Watson      if (!ExecuteCommand(bt_iface, command)) break;
10895d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen    }
10905d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen
10915d80cb938d7fb3312870a047749cc839ba5bafcaMarie Janssen    commands.clear();
10925192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
109339a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray    PrintPrompt();
109439a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
109539a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray    showing_prompt = true;
109691c59c9febbf4a49664b8a06620d4a4882605131Arman Uguray    auto& istream = getline(cin, command);
109739a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray    showing_prompt = false;
1098fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
109991c59c9febbf4a49664b8a06620d4a4882605131Arman Uguray    if (istream.eof() || should_exit.load()) {
110091c59c9febbf4a49664b8a06620d4a4882605131Arman Uguray      cout << "\nExiting" << endl;
11012e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray      return EXIT_SUCCESS;
110291c59c9febbf4a49664b8a06620d4a4882605131Arman Uguray    }
110391c59c9febbf4a49664b8a06620d4a4882605131Arman Uguray
110491c59c9febbf4a49664b8a06620d4a4882605131Arman Uguray    if (!istream.good()) {
110591c59c9febbf4a49664b8a06620d4a4882605131Arman Uguray      LOG(ERROR) << "An error occured while reading input";
110691c59c9febbf4a49664b8a06620d4a4882605131Arman Uguray      return EXIT_FAILURE;
110791c59c9febbf4a49664b8a06620d4a4882605131Arman Uguray    }
1108fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray  }
1109f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
1110f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray  return EXIT_SUCCESS;
1111f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray}
1112