blob: 6458b2da5cabb39c83aa5b41f9de27f3416227f9 [file] [log] [blame]
Arman Ugurayf5209522015-08-05 21:22:39 -07001//
Jakub Pawlowski5b790fe2017-09-18 09:00:20 -07002// Copyright 2015 Google, Inc.
Arman Ugurayf5209522015-08-05 21:22:39 -07003//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
Arman Ugurayfcf2e032015-08-13 17:05:03 -070017#include <iostream>
18#include <string>
19
Arman Ugurayae43de62015-09-24 15:05:21 -070020#include <base/at_exit.h>
21#include <base/command_line.h>
Arman Ugurayf5209522015-08-05 21:22:39 -070022#include <base/logging.h>
Arman Uguray39a66be2015-08-20 12:47:55 -070023#include <base/macros.h>
Jakub Pawlowskiba197a22016-01-13 11:28:08 -080024#include <base/strings/string_number_conversions.h>
Arman Uguray51923092015-08-17 17:25:04 -070025#include <base/strings/string_split.h>
26#include <base/strings/string_util.h>
Arman Uguray2e434142015-09-04 13:17:39 -070027#include <binder/IPCThreadState.h>
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -080028#include <binder/IServiceManager.h>
Arman Uguray39a66be2015-08-20 12:47:55 -070029#include <binder/ProcessState.h>
Arman Ugurayf5209522015-08-05 21:22:39 -070030
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -080031#include <android/bluetooth/BnBluetoothCallback.h>
32#include <android/bluetooth/BnBluetoothGattClientCallback.h>
Jakub Pawlowski67d5a252016-07-13 11:55:16 -070033#include <android/bluetooth/BnBluetoothLeAdvertiserCallback.h>
Jakub Pawlowskic3f6a512016-10-27 11:49:40 -070034#include <android/bluetooth/BnBluetoothLeScannerCallback.h>
Myles Watson911d1ae2016-11-28 16:44:40 -080035#include <android/bluetooth/BnBluetoothLowEnergyCallback.h>
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -080036#include <android/bluetooth/IBluetooth.h>
37#include <android/bluetooth/IBluetoothGattClient.h>
Jakub Pawlowski67d5a252016-07-13 11:55:16 -070038#include <android/bluetooth/IBluetoothLeAdvertiser.h>
Jakub Pawlowskic3f6a512016-10-27 11:49:40 -070039#include <android/bluetooth/IBluetoothLeScanner.h>
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -080040#include <android/bluetooth/IBluetoothLowEnergy.h>
Myles Watson911d1ae2016-11-28 16:44:40 -080041#include <bluetooth/adapter_state.h>
Arman Uguray234138e2015-10-06 15:56:36 -070042#include <bluetooth/low_energy_constants.h>
Jakub Pawlowskiba197a22016-01-13 11:28:08 -080043#include <bluetooth/scan_filter.h>
44#include <bluetooth/scan_settings.h>
Arman Uguray87222e02015-10-09 12:32:55 -070045#include <bluetooth/uuid.h>
Arman Ugurayf5209522015-08-05 21:22:39 -070046
Arman Ugurayfcf2e032015-08-13 17:05:03 -070047using namespace std;
48
Arman Ugurayf5209522015-08-05 21:22:39 -070049using android::sp;
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -080050using android::String8;
51using android::String16;
52using android::binder::Status;
53using android::OK;
54using android::getService;
Arman Ugurayf5209522015-08-05 21:22:39 -070055
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -080056using android::bluetooth::IBluetooth;
57using android::bluetooth::IBluetoothGattClient;
Jakub Pawlowski67d5a252016-07-13 11:55:16 -070058using android::bluetooth::IBluetoothLeAdvertiser;
Jakub Pawlowskic3f6a512016-10-27 11:49:40 -070059using android::bluetooth::IBluetoothLeScanner;
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -080060using android::bluetooth::IBluetoothLowEnergy;
Arman Ugurayf5209522015-08-05 21:22:39 -070061
Arman Uguray2117e522015-08-14 17:23:47 -070062namespace {
63
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -080064#define COLOR_OFF "\x1B[0m"
65#define COLOR_RED "\x1B[0;91m"
66#define COLOR_GREEN "\x1B[0;92m"
67#define COLOR_YELLOW "\x1B[0;93m"
68#define COLOR_BLUE "\x1B[0;94m"
69#define COLOR_MAGENTA "\x1B[0;95m"
70#define COLOR_BOLDGRAY "\x1B[1;30m"
71#define COLOR_BOLDWHITE "\x1B[1;37m"
72#define COLOR_BOLDYELLOW "\x1B[1;93m"
73#define CLEAR_LINE "\x1B[2K"
Arman Ugurayfcf2e032015-08-13 17:05:03 -070074
Arman Uguray51923092015-08-17 17:25:04 -070075#define CHECK_ARGS_COUNT(args, op, num, msg) \
Chih-Hung Hsieh63b05192016-05-20 10:29:31 -070076 if (!((args).size() op num)) { \
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -080077 PrintError(msg); \
78 return; \
Arman Uguray51923092015-08-17 17:25:04 -070079 }
80#define CHECK_NO_ARGS(args) \
81 CHECK_ARGS_COUNT(args, ==, 0, "Expected no arguments")
82
Arman Uguray39a66be2015-08-20 12:47:55 -070083// TODO(armansito): Clean up this code. Right now everything is in this
84// monolithic file. We should organize this into different classes for command
85// handling, console output/printing, callback handling, etc.
86// (See http://b/23387611)
87
88// Used to synchronize the printing of the command-line prompt and incoming
89// Binder callbacks.
90std::atomic_bool showing_prompt(false);
91
Arman Uguray2e434142015-09-04 13:17:39 -070092// The registered IBluetoothLowEnergy client handle. If |ble_registering| is
93// true then an operation to register the client is in progress.
94std::atomic_bool ble_registering(false);
Arman Uguray4fbbf602015-11-10 18:05:33 -080095std::atomic_int ble_client_id(0);
96
Myles Watson9ca07092016-11-28 16:41:53 -080097// The registered IBluetoothLeAdvertiser handle. If |ble_advertiser_registering|
98// is true then an operation to register the advertiser is in progress.
Jakub Pawlowskidaa8a992017-01-09 06:53:36 -080099const int invalid_advertiser_id = -1;
Jakub Pawlowski67d5a252016-07-13 11:55:16 -0700100std::atomic_bool ble_advertiser_registering(false);
Jakub Pawlowskidaa8a992017-01-09 06:53:36 -0800101std::atomic_int ble_advertiser_id(invalid_advertiser_id);
Jakub Pawlowski67d5a252016-07-13 11:55:16 -0700102
Jakub Pawlowskic3f6a512016-10-27 11:49:40 -0700103// The registered IBluetoothLeScanner handle. If |ble_scanner_registering| is
104// true then an operation to register the scanner is in progress.
105std::atomic_bool ble_scanner_registering(false);
106std::atomic_int ble_scanner_id(0);
107
Arman Uguray4fbbf602015-11-10 18:05:33 -0800108// The registered IBluetoothGattClient client handle. If |gatt_registering| is
109// true then an operation to register the client is in progress.
110std::atomic_bool gatt_registering(false);
111std::atomic_int gatt_client_id(0);
Arman Uguray2e434142015-09-04 13:17:39 -0700112
Jakub Pawlowskiba197a22016-01-13 11:28:08 -0800113// True if we should dump the scan record bytes for incoming scan results.
114std::atomic_bool dump_scan_record(false);
115
Arman Uguray2e434142015-09-04 13:17:39 -0700116// True if the remote process has died and we should exit.
117std::atomic_bool should_exit(false);
118
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800119std::string kServiceName = "bluetooth-service";
120
121void PrintPrompt() { cout << COLOR_BLUE "[FCLI] " COLOR_OFF << flush; }
Arman Uguray39a66be2015-08-20 12:47:55 -0700122
Arman Uguray2e434142015-09-04 13:17:39 -0700123void PrintError(const string& message) {
124 cout << COLOR_RED << message << COLOR_OFF << endl;
125}
126
Arman Ugurayd19bc042015-09-16 18:04:32 -0700127void PrintOpStatus(const std::string& op, bool status) {
128 cout << COLOR_BOLDWHITE << op << " status: " COLOR_OFF
129 << (status ? (COLOR_GREEN "success") : (COLOR_RED "failure"))
Jakub Pawlowski64401bf2016-01-28 23:57:17 -0800130 << COLOR_OFF << endl;
131}
132
133inline void BeginAsyncOut() {
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800134 if (showing_prompt.load()) cout << CLEAR_LINE << "\r";
Jakub Pawlowski64401bf2016-01-28 23:57:17 -0800135}
136
137inline void EndAsyncOut() {
138 std::flush(cout);
139 if (showing_prompt.load())
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800140 PrintPrompt();
Jakub Pawlowski64401bf2016-01-28 23:57:17 -0800141 else
142 cout << endl;
Arman Ugurayd19bc042015-09-16 18:04:32 -0700143}
144
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800145class CLIBluetoothCallback : public android::bluetooth::BnBluetoothCallback {
Arman Uguray39a66be2015-08-20 12:47:55 -0700146 public:
147 CLIBluetoothCallback() = default;
148 ~CLIBluetoothCallback() override = default;
149
Arman Uguray2e434142015-09-04 13:17:39 -0700150 // IBluetoothCallback overrides:
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800151 Status OnBluetoothStateChange(int32_t prev_state,
152 int32_t new_state) override {
Jakub Pawlowski64401bf2016-01-28 23:57:17 -0800153 BeginAsyncOut();
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800154 cout << COLOR_BOLDWHITE "Adapter state changed: " COLOR_OFF << COLOR_MAGENTA
155 << AdapterStateToString(bluetooth::AdapterState(prev_state))
156 << COLOR_OFF << COLOR_BOLDWHITE " -> " COLOR_OFF << COLOR_BOLDYELLOW
157 << AdapterStateToString(bluetooth::AdapterState(new_state))
158 << COLOR_OFF;
Jakub Pawlowski64401bf2016-01-28 23:57:17 -0800159 EndAsyncOut();
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800160
161 return Status::ok();
162 }
Arman Uguray39a66be2015-08-20 12:47:55 -0700163
Bailey Forrest62aa15f2017-01-30 17:38:58 -0800164 Status OnSspRequest(const String16& device_address,
165 const String16& device_name, int32_t cod,
166 int32_t pairing_variant, int32_t pass_key) override {
167 // no-op
168 return Status::ok();
169 }
170
171 Status OnGetBondedDevices(
172 int32_t status,
173 const ::std::vector<String16>& device_addresses) override {
174 BeginAsyncOut();
175 std::cout << "Bonded devices:\n";
176 for (const auto& device_address : device_addresses) {
177 std::cout << " " << device_address << "\n";
178 }
179 EndAsyncOut();
180 return Status::ok();
181 }
182
183 Status OnBondStateChanged(int32_t status, const String16& device_address,
184 int32_t state) override {
185 BeginAsyncOut();
186 std::cout << COLOR_BOLDWHITE "Device address: " << COLOR_BOLDYELLOW "["
187 << device_address << " bond state: " << state << " ] "
188 << COLOR_BOLDWHITE "- status: "
189 << (status == 0 ? "SUCCESS" : "FAIL") << COLOR_OFF;
190 EndAsyncOut();
191 return Status::ok();
192 }
193
194 Status OnGetRemoteDeviceProperties(
195 int32_t status, const String16& device_address,
196 const android::bluetooth::BluetoothRemoteDeviceProps& props) override {
197 // no-op
198 return Status::ok();
199 }
200
201 Status OnDeviceFound(
202 const android::bluetooth::BluetoothRemoteDeviceProps& props) override {
203 // no-op
204 return Status::ok();
205 }
206
207 Status OnDeviceConnectionStateChanged(const String16& device_address,
208 bool connected) override {
209 // no-op
210 return Status::ok();
211 }
212
213 Status OnScanEnableChanged(bool scan_enabled) override {
214 // no-op
215 return Status::ok();
216 }
217
Arman Uguray39a66be2015-08-20 12:47:55 -0700218 private:
219 DISALLOW_COPY_AND_ASSIGN(CLIBluetoothCallback);
220};
221
Arman Uguray2e434142015-09-04 13:17:39 -0700222class CLIBluetoothLowEnergyCallback
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800223 : public android::bluetooth::BnBluetoothLowEnergyCallback {
Arman Uguray2e434142015-09-04 13:17:39 -0700224 public:
225 CLIBluetoothLowEnergyCallback() = default;
Arman Uguray4fbbf602015-11-10 18:05:33 -0800226 ~CLIBluetoothLowEnergyCallback() override = default;
Arman Uguray2e434142015-09-04 13:17:39 -0700227
228 // IBluetoothLowEnergyCallback overrides:
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800229 Status OnClientRegistered(int status, int client_id) override {
Jakub Pawlowski64401bf2016-01-28 23:57:17 -0800230 BeginAsyncOut();
Arman Uguray2e434142015-09-04 13:17:39 -0700231 if (status != bluetooth::BLE_STATUS_SUCCESS) {
232 PrintError("Failed to register BLE client");
233 } else {
Arman Uguray4fbbf602015-11-10 18:05:33 -0800234 ble_client_id = client_id;
Arman Uguray2e434142015-09-04 13:17:39 -0700235 cout << COLOR_BOLDWHITE "Registered BLE client with ID: " COLOR_OFF
Jakub Pawlowski64401bf2016-01-28 23:57:17 -0800236 << COLOR_GREEN << client_id << COLOR_OFF;
Arman Uguray2e434142015-09-04 13:17:39 -0700237 }
Jakub Pawlowski64401bf2016-01-28 23:57:17 -0800238 EndAsyncOut();
Arman Uguray2e434142015-09-04 13:17:39 -0700239
240 ble_registering = false;
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800241 return Status::ok();
Arman Uguray2e434142015-09-04 13:17:39 -0700242 }
243
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800244 Status OnConnectionState(int status, int client_id, const String16& address,
245 bool connected) override {
Jakub Pawlowski64401bf2016-01-28 23:57:17 -0800246 BeginAsyncOut();
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800247 cout << COLOR_BOLDWHITE "Connection state: " << COLOR_BOLDYELLOW "["
248 << address << " connected: " << (connected ? "true" : "false") << " ] "
Jakub Pawlowski608762d2016-01-19 17:07:53 -0800249 << COLOR_BOLDWHITE "- status: " << status
250 << COLOR_BOLDWHITE " - client_id: " << client_id << COLOR_OFF;
Jakub Pawlowski64401bf2016-01-28 23:57:17 -0800251 EndAsyncOut();
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800252 return Status::ok();
Jakub Pawlowski455dc8f2016-01-19 17:00:16 -0800253 }
254
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800255 Status OnMtuChanged(int status, const String16& address, int mtu) override {
Jakub Pawlowski64401bf2016-01-28 23:57:17 -0800256 BeginAsyncOut();
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800257 cout << COLOR_BOLDWHITE "MTU changed: " << COLOR_BOLDYELLOW "[" << address
258 << " ] " << COLOR_BOLDWHITE " - status: " << status
Jakub Pawlowskia6551072016-01-26 12:58:47 -0800259 << COLOR_BOLDWHITE " - mtu: " << mtu << COLOR_OFF;
Jakub Pawlowski64401bf2016-01-28 23:57:17 -0800260 EndAsyncOut();
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800261 return Status::ok();
Jakub Pawlowskia6551072016-01-26 12:58:47 -0800262 }
263
Jakub Pawlowski67d5a252016-07-13 11:55:16 -0700264 private:
265 DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLowEnergyCallback);
266};
267
268class CLIBluetoothLeAdvertiserCallback
269 : public android::bluetooth::BnBluetoothLeAdvertiserCallback {
270 public:
271 CLIBluetoothLeAdvertiserCallback() = default;
272 ~CLIBluetoothLeAdvertiserCallback() override = default;
273
274 // IBluetoothLowEnergyCallback overrides:
275 Status OnAdvertiserRegistered(int status, int advertiser_id) override {
276 BeginAsyncOut();
277 if (status != bluetooth::BLE_STATUS_SUCCESS) {
278 PrintError("Failed to register BLE advertiser");
279 } else {
280 ble_advertiser_id = advertiser_id;
281 cout << COLOR_BOLDWHITE "Registered BLE advertiser with ID: " COLOR_OFF
282 << COLOR_GREEN << advertiser_id << COLOR_OFF;
283 }
284 EndAsyncOut();
285
286 ble_advertiser_registering = false;
287 return Status::ok();
288 }
289
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800290 Status OnMultiAdvertiseCallback(
Arman Uguray52bfc602015-09-10 14:28:54 -0700291 int status, bool is_start,
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800292 const android::bluetooth::AdvertiseSettings& /* settings */) {
Jakub Pawlowski64401bf2016-01-28 23:57:17 -0800293 BeginAsyncOut();
Arman Ugurayd19bc042015-09-16 18:04:32 -0700294 std::string op = is_start ? "start" : "stop";
295
296 PrintOpStatus("Advertising " + op, status == bluetooth::BLE_STATUS_SUCCESS);
Jakub Pawlowski64401bf2016-01-28 23:57:17 -0800297 EndAsyncOut();
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800298 return Status::ok();
Arman Uguray52bfc602015-09-10 14:28:54 -0700299 }
300
Arman Uguray2e434142015-09-04 13:17:39 -0700301 private:
Jakub Pawlowski67d5a252016-07-13 11:55:16 -0700302 DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLeAdvertiserCallback);
Arman Uguray2e434142015-09-04 13:17:39 -0700303};
Arman Uguray51923092015-08-17 17:25:04 -0700304
Jakub Pawlowskic3f6a512016-10-27 11:49:40 -0700305class CLIBluetoothLeScannerCallback
306 : public android::bluetooth::BnBluetoothLeScannerCallback {
307 public:
308 CLIBluetoothLeScannerCallback() = default;
309 ~CLIBluetoothLeScannerCallback() override = default;
310
311 // IBluetoothLowEnergyCallback overrides:
312 Status OnScannerRegistered(int status, int scanner_id) override {
313 BeginAsyncOut();
314 if (status != bluetooth::BLE_STATUS_SUCCESS) {
315 PrintError("Failed to register BLE client");
316 } else {
317 ble_scanner_id = scanner_id;
318 cout << COLOR_BOLDWHITE "Registered BLE client with ID: " COLOR_OFF
319 << COLOR_GREEN << scanner_id << COLOR_OFF;
320 }
321 EndAsyncOut();
322
323 ble_scanner_registering = false;
324 return Status::ok();
325 }
326
327 Status OnScanResult(
328 const android::bluetooth::ScanResult& scan_result) override {
329 BeginAsyncOut();
330 cout << COLOR_BOLDWHITE "Scan result: " << COLOR_BOLDYELLOW "["
331 << scan_result.device_address() << "] "
332 << COLOR_BOLDWHITE "- RSSI: " << scan_result.rssi() << COLOR_OFF;
333
334 if (dump_scan_record) {
335 cout << " - Record: "
336 << base::HexEncode(scan_result.scan_record().data(),
337 scan_result.scan_record().size());
338 }
339 EndAsyncOut();
340 return Status::ok();
341 }
342
343 private:
344 DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLeScannerCallback);
345};
346
Arman Uguray4fbbf602015-11-10 18:05:33 -0800347class CLIGattClientCallback
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800348 : public android::bluetooth::BnBluetoothGattClientCallback {
Arman Uguray4fbbf602015-11-10 18:05:33 -0800349 public:
350 CLIGattClientCallback() = default;
351 ~CLIGattClientCallback() override = default;
352
353 // IBluetoothGattClientCallback overrides:
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800354 Status OnClientRegistered(int status, int client_id) override {
Jakub Pawlowski64401bf2016-01-28 23:57:17 -0800355 BeginAsyncOut();
Arman Uguray4fbbf602015-11-10 18:05:33 -0800356 if (status != bluetooth::BLE_STATUS_SUCCESS) {
357 PrintError("Failed to register GATT client");
358 } else {
359 gatt_client_id = client_id;
360 cout << COLOR_BOLDWHITE "Registered GATT client with ID: " COLOR_OFF
Jakub Pawlowski64401bf2016-01-28 23:57:17 -0800361 << COLOR_GREEN << client_id << COLOR_OFF;
Arman Uguray4fbbf602015-11-10 18:05:33 -0800362 }
Jakub Pawlowski64401bf2016-01-28 23:57:17 -0800363 EndAsyncOut();
Arman Uguray4fbbf602015-11-10 18:05:33 -0800364
365 gatt_registering = false;
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800366 return Status::ok();
Arman Uguray4fbbf602015-11-10 18:05:33 -0800367 }
368
369 private:
370 DISALLOW_COPY_AND_ASSIGN(CLIGattClientCallback);
371};
372
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800373void PrintCommandStatus(bool status) { PrintOpStatus("Command", status); }
Arman Ugurayfcf2e032015-08-13 17:05:03 -0700374
Arman Uguray51923092015-08-17 17:25:04 -0700375void PrintFieldAndValue(const string& field, const string& value) {
376 cout << COLOR_BOLDWHITE << field << ": " << COLOR_BOLDYELLOW << value
377 << COLOR_OFF << endl;
378}
379
380void PrintFieldAndBoolValue(const string& field, bool value) {
381 PrintFieldAndValue(field, (value ? "true" : "false"));
382}
383
384void HandleDisable(IBluetooth* bt_iface, const vector<string>& args) {
385 CHECK_NO_ARGS(args);
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800386 bool status;
387 bt_iface->Disable(&status);
388 PrintCommandStatus(status);
Arman Ugurayfcf2e032015-08-13 17:05:03 -0700389}
390
Arman Uguray51923092015-08-17 17:25:04 -0700391void HandleEnable(IBluetooth* bt_iface, const vector<string>& args) {
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800392 bool status;
Martin Brabham1a88ace2019-05-10 12:42:15 -0700393 bt_iface->Enable(&status);
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800394 PrintCommandStatus(status);
Arman Ugurayfcf2e032015-08-13 17:05:03 -0700395}
396
Arman Uguray51923092015-08-17 17:25:04 -0700397void HandleGetState(IBluetooth* bt_iface, const vector<string>& args) {
398 CHECK_NO_ARGS(args);
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800399
400 int32_t st;
401 bt_iface->GetState(&st);
402 bluetooth::AdapterState state = static_cast<bluetooth::AdapterState>(st);
Arman Uguray51923092015-08-17 17:25:04 -0700403 PrintFieldAndValue("Adapter state", bluetooth::AdapterStateToString(state));
Arman Ugurayfcf2e032015-08-13 17:05:03 -0700404}
405
Arman Uguray51923092015-08-17 17:25:04 -0700406void HandleIsEnabled(IBluetooth* bt_iface, const vector<string>& args) {
407 CHECK_NO_ARGS(args);
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800408 bool enabled;
409 bt_iface->IsEnabled(&enabled);
Arman Uguray51923092015-08-17 17:25:04 -0700410 PrintFieldAndBoolValue("Adapter enabled", enabled);
Arman Ugurayfcf2e032015-08-13 17:05:03 -0700411}
412
Arman Uguray51923092015-08-17 17:25:04 -0700413void HandleGetLocalAddress(IBluetooth* bt_iface, const vector<string>& args) {
414 CHECK_NO_ARGS(args);
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800415 String16 address;
416 bt_iface->GetAddress(&address);
417 PrintFieldAndValue("Adapter address", std::string(String8(address).string()));
Arman Uguray51923092015-08-17 17:25:04 -0700418}
419
420void HandleSetLocalName(IBluetooth* bt_iface, const vector<string>& args) {
421 CHECK_ARGS_COUNT(args, >=, 1, "No name was given");
422
423 std::string name;
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800424 for (const auto& arg : args) name += arg + " ";
Arman Uguray51923092015-08-17 17:25:04 -0700425
426 base::TrimWhitespaceASCII(name, base::TRIM_TRAILING, &name);
427
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800428 bool status;
429 bt_iface->SetName(String16(String8(name.c_str())), &status);
430 PrintCommandStatus(status);
Arman Uguray51923092015-08-17 17:25:04 -0700431}
432
433void HandleGetLocalName(IBluetooth* bt_iface, const vector<string>& args) {
434 CHECK_NO_ARGS(args);
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800435 String16 name;
436 bt_iface->GetName(&name);
437 PrintFieldAndValue("Adapter name", std::string(String8(name).string()));
Arman Uguray51923092015-08-17 17:25:04 -0700438}
439
440void HandleAdapterInfo(IBluetooth* bt_iface, const vector<string>& args) {
441 CHECK_NO_ARGS(args);
442
443 cout << COLOR_BOLDWHITE "Adapter Properties: " COLOR_OFF << endl;
444
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800445 String16 address;
446 bt_iface->GetAddress(&address);
447 PrintFieldAndValue("\tAddress", std::string(String8(address).string()));
448
449 int adapter_state;
450 bt_iface->GetState(&adapter_state);
451 PrintFieldAndValue("\tState",
452 bluetooth::AdapterStateToString(
453 static_cast<bluetooth::AdapterState>(adapter_state)));
454
455 String16 name;
456 bt_iface->GetName(&name);
457 PrintFieldAndValue("\tName", std::string(String8(name).string()));
458
459 bool multi_adv;
460 bt_iface->IsMultiAdvertisementSupported(&multi_adv);
461 PrintFieldAndBoolValue("\tMulti-Adv. supported", multi_adv);
Arman Uguray10b54c42015-08-21 14:59:57 -0700462}
463
464void HandleSupportsMultiAdv(IBluetooth* bt_iface, const vector<string>& args) {
465 CHECK_NO_ARGS(args);
466
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800467 bool multi_adv;
468 bt_iface->IsMultiAdvertisementSupported(&multi_adv);
469 PrintFieldAndBoolValue("Multi-advertisement support", multi_adv);
Arman Uguray51923092015-08-17 17:25:04 -0700470}
471
Myles Watson911d1ae2016-11-28 16:44:40 -0800472void HandleRegisterBLEAdvertiser(IBluetooth* bt_iface,
473 const vector<string>& args) {
Jakub Pawlowski67d5a252016-07-13 11:55:16 -0700474 CHECK_NO_ARGS(args);
475
476 if (ble_advertiser_registering.load()) {
477 PrintError("In progress");
478 return;
479 }
480
Jakub Pawlowskidaa8a992017-01-09 06:53:36 -0800481 if (ble_advertiser_id.load() != invalid_advertiser_id) {
Jakub Pawlowski67d5a252016-07-13 11:55:16 -0700482 PrintError("Already registered");
483 return;
484 }
485
486 sp<IBluetoothLeAdvertiser> ble_advertiser_iface;
487 bt_iface->GetLeAdvertiserInterface(&ble_advertiser_iface);
488 if (!ble_advertiser_iface.get()) {
489 PrintError("Failed to obtain handle to Bluetooth Le Advertiser interface");
490 return;
491 }
492
493 bool status;
Myles Watson911d1ae2016-11-28 16:44:40 -0800494 ble_advertiser_iface->RegisterAdvertiser(
495 new CLIBluetoothLeAdvertiserCallback(), &status);
Jakub Pawlowski67d5a252016-07-13 11:55:16 -0700496 ble_advertiser_registering = status;
497 PrintCommandStatus(status);
498}
499
Myles Watson911d1ae2016-11-28 16:44:40 -0800500void HandleUnregisterBLEAdvertiser(IBluetooth* bt_iface,
501 const vector<string>& args) {
Jakub Pawlowski67d5a252016-07-13 11:55:16 -0700502 CHECK_NO_ARGS(args);
503
Jakub Pawlowskidaa8a992017-01-09 06:53:36 -0800504 if (ble_advertiser_id.load() == invalid_advertiser_id) {
Jakub Pawlowski67d5a252016-07-13 11:55:16 -0700505 PrintError("Not registered");
506 return;
507 }
508
509 sp<IBluetoothLeAdvertiser> ble_advertiser_iface;
510 bt_iface->GetLeAdvertiserInterface(&ble_advertiser_iface);
511 if (!ble_advertiser_iface.get()) {
512 PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
513 return;
514 }
515
516 ble_advertiser_iface->UnregisterAdvertiser(ble_advertiser_id.load());
Jakub Pawlowskidaa8a992017-01-09 06:53:36 -0800517 ble_advertiser_id = invalid_advertiser_id;
Jakub Pawlowski67d5a252016-07-13 11:55:16 -0700518 PrintCommandStatus(true);
519}
520
Arman Uguray2e434142015-09-04 13:17:39 -0700521void HandleRegisterBLE(IBluetooth* bt_iface, const vector<string>& args) {
522 CHECK_NO_ARGS(args);
523
524 if (ble_registering.load()) {
525 PrintError("In progress");
526 return;
527 }
528
Arman Uguray4fbbf602015-11-10 18:05:33 -0800529 if (ble_client_id.load()) {
Arman Uguray2e434142015-09-04 13:17:39 -0700530 PrintError("Already registered");
531 return;
532 }
533
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800534 sp<IBluetoothLowEnergy> ble_iface;
535 bt_iface->GetLowEnergyInterface(&ble_iface);
Arman Uguray2e434142015-09-04 13:17:39 -0700536 if (!ble_iface.get()) {
537 PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
538 return;
539 }
540
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800541 bool status;
542 ble_iface->RegisterClient(new CLIBluetoothLowEnergyCallback(), &status);
Arman Ugurayae43de62015-09-24 15:05:21 -0700543 ble_registering = status;
544 PrintCommandStatus(status);
Arman Uguray2e434142015-09-04 13:17:39 -0700545}
546
547void HandleUnregisterBLE(IBluetooth* bt_iface, const vector<string>& args) {
548 CHECK_NO_ARGS(args);
549
Arman Uguray4fbbf602015-11-10 18:05:33 -0800550 if (!ble_client_id.load()) {
Arman Uguray2e434142015-09-04 13:17:39 -0700551 PrintError("Not registered");
552 return;
553 }
554
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800555 sp<IBluetoothLowEnergy> ble_iface;
556 bt_iface->GetLowEnergyInterface(&ble_iface);
Arman Uguray2e434142015-09-04 13:17:39 -0700557 if (!ble_iface.get()) {
558 PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
559 return;
560 }
561
Arman Uguray4fbbf602015-11-10 18:05:33 -0800562 ble_iface->UnregisterClient(ble_client_id.load());
563 ble_client_id = 0;
Arman Uguray2e434142015-09-04 13:17:39 -0700564 PrintCommandStatus(true);
565}
566
567void HandleUnregisterAllBLE(IBluetooth* bt_iface, const vector<string>& args) {
568 CHECK_NO_ARGS(args);
569
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800570 sp<IBluetoothLowEnergy> ble_iface;
571 bt_iface->GetLowEnergyInterface(&ble_iface);
Arman Uguray2e434142015-09-04 13:17:39 -0700572 if (!ble_iface.get()) {
573 PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
574 return;
575 }
576
577 ble_iface->UnregisterAll();
578 PrintCommandStatus(true);
579}
580
Arman Uguray4fbbf602015-11-10 18:05:33 -0800581void HandleRegisterGATT(IBluetooth* bt_iface, const vector<string>& args) {
582 CHECK_NO_ARGS(args);
583
584 if (gatt_registering.load()) {
585 PrintError("In progress");
586 return;
587 }
588
589 if (gatt_client_id.load()) {
590 PrintError("Already registered");
591 return;
592 }
593
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800594 sp<IBluetoothGattClient> gatt_iface;
595 bt_iface->GetGattClientInterface(&gatt_iface);
Arman Uguray4fbbf602015-11-10 18:05:33 -0800596 if (!gatt_iface.get()) {
597 PrintError("Failed to obtain handle to Bluetooth GATT Client interface");
598 return;
599 }
600
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800601 bool status;
602 gatt_iface->RegisterClient(new CLIGattClientCallback(), &status);
Arman Uguray4fbbf602015-11-10 18:05:33 -0800603 gatt_registering = status;
604 PrintCommandStatus(status);
605}
606
607void HandleUnregisterGATT(IBluetooth* bt_iface, const vector<string>& args) {
608 CHECK_NO_ARGS(args);
609
610 if (!gatt_client_id.load()) {
611 PrintError("Not registered");
612 return;
613 }
614
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800615 sp<IBluetoothGattClient> gatt_iface;
616 bt_iface->GetGattClientInterface(&gatt_iface);
Arman Uguray4fbbf602015-11-10 18:05:33 -0800617 if (!gatt_iface.get()) {
618 PrintError("Failed to obtain handle to Bluetooth GATT Client interface");
619 return;
620 }
621
622 gatt_iface->UnregisterClient(gatt_client_id.load());
623 gatt_client_id = 0;
624 PrintCommandStatus(true);
625}
626
Arman Ugurayd19bc042015-09-16 18:04:32 -0700627void HandleStartAdv(IBluetooth* bt_iface, const vector<string>& args) {
628 bool include_name = false;
629 bool include_tx_power = false;
630 bool connectable = false;
631 bool set_manufacturer_data = false;
Arman Uguray87222e02015-10-09 12:32:55 -0700632 bool set_uuid = false;
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700633 bluetooth::Uuid uuid;
Arman Ugurayd19bc042015-09-16 18:04:32 -0700634
Arman Uguray87222e02015-10-09 12:32:55 -0700635 for (auto iter = args.begin(); iter != args.end(); ++iter) {
636 const std::string& arg = *iter;
Arman Ugurayd19bc042015-09-16 18:04:32 -0700637 if (arg == "-n")
638 include_name = true;
639 else if (arg == "-t")
640 include_tx_power = true;
641 else if (arg == "-c")
642 connectable = true;
643 else if (arg == "-m")
644 set_manufacturer_data = true;
Arman Uguray87222e02015-10-09 12:32:55 -0700645 else if (arg == "-u") {
646 // This flag has a single argument.
647 ++iter;
648 if (iter == args.end()) {
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700649 PrintError("Expected a Uuid after -u");
Arman Uguray87222e02015-10-09 12:32:55 -0700650 return;
651 }
652
653 std::string uuid_str = *iter;
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700654 bool is_valid = false;
655 uuid = bluetooth::Uuid::FromString(uuid_str, &is_valid);
656 if (!is_valid) {
657 PrintError("Invalid Uuid: " + uuid_str);
Arman Uguray87222e02015-10-09 12:32:55 -0700658 return;
659 }
660
661 set_uuid = true;
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800662 } else if (arg == "-h") {
Jakub Pawlowskiba197a22016-01-13 11:28:08 -0800663 static const char kUsage[] =
Arman Ugurayd19bc042015-09-16 18:04:32 -0700664 "Usage: start-adv [flags]\n"
665 "\n"
Jakub Pawlowskiba197a22016-01-13 11:28:08 -0800666 "Flags:\n"
Arman Ugurayd19bc042015-09-16 18:04:32 -0700667 "\t-n\tInclude device name\n"
668 "\t-t\tInclude TX power\n"
669 "\t-c\tSend connectable adv. packets (default is non-connectable)\n"
670 "\t-m\tInclude random manufacturer data\n"
671 "\t-h\tShow this help message\n";
672 cout << kUsage << endl;
673 return;
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800674 } else {
Arman Ugurayd19bc042015-09-16 18:04:32 -0700675 PrintError("Unrecognized option: " + arg);
676 return;
677 }
678 }
679
Jakub Pawlowskidaa8a992017-01-09 06:53:36 -0800680 if (ble_advertiser_id.load() == invalid_advertiser_id) {
Jakub Pawlowski67d5a252016-07-13 11:55:16 -0700681 PrintError("BLE advertiser not registered");
Arman Ugurayd19bc042015-09-16 18:04:32 -0700682 return;
683 }
684
Jakub Pawlowski67d5a252016-07-13 11:55:16 -0700685 sp<IBluetoothLeAdvertiser> ble_advertiser_iface;
686 bt_iface->GetLeAdvertiserInterface(&ble_advertiser_iface);
687 if (!ble_advertiser_iface.get()) {
688 PrintError("Failed to obtain handle to Bluetooth Le Advertiser interface");
Arman Ugurayd19bc042015-09-16 18:04:32 -0700689 return;
690 }
691
692 std::vector<uint8_t> data;
693 if (set_manufacturer_data) {
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800694 data = {{0x07, bluetooth::kEIRTypeManufacturerSpecificData, 0xe0, 0x00, 'T',
695 'e', 's', 't'}};
Arman Ugurayd19bc042015-09-16 18:04:32 -0700696 }
697
Arman Uguray87222e02015-10-09 12:32:55 -0700698 if (set_uuid) {
699 // Determine the type and length bytes.
700 int uuid_size = uuid.GetShortestRepresentationSize();
701 uint8_t type;
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700702 if (uuid_size == bluetooth::Uuid::kNumBytes128)
703 type = bluetooth::kEIRTypeComplete128BitUuids;
704 else if (uuid_size == bluetooth::Uuid::kNumBytes32)
705 type = bluetooth::kEIRTypeComplete32BitUuids;
706 else if (uuid_size == bluetooth::Uuid::kNumBytes16)
707 type = bluetooth::kEIRTypeComplete16BitUuids;
Arman Uguray87222e02015-10-09 12:32:55 -0700708 else
709 NOTREACHED() << "Unexpected size: " << uuid_size;
710
711 data.push_back(uuid_size + 1);
712 data.push_back(type);
713
Jakub Pawlowski819e2ec2017-07-10 09:56:09 -0700714 auto uuid_bytes = uuid.To128BitLE();
Arman Uguray87222e02015-10-09 12:32:55 -0700715 int index = (uuid_size == 16) ? 0 : 12;
716 data.insert(data.end(), uuid_bytes.data() + index,
717 uuid_bytes.data() + index + uuid_size);
718 }
719
Arman Ugurayd19bc042015-09-16 18:04:32 -0700720 base::TimeDelta timeout;
721
722 bluetooth::AdvertiseSettings settings(
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800723 bluetooth::AdvertiseSettings::MODE_LOW_POWER, timeout,
724 bluetooth::AdvertiseSettings::TX_POWER_LEVEL_MEDIUM, connectable);
Arman Ugurayd19bc042015-09-16 18:04:32 -0700725
Jakub Pawlowski0ecddf32016-10-19 14:46:09 -0700726 if (include_tx_power) {
727 data.push_back(0x02);
728 data.push_back(bluetooth::kEIRTypeTxPower);
729 data.push_back(0x00);
730 }
731
Arman Ugurayd19bc042015-09-16 18:04:32 -0700732 bluetooth::AdvertiseData adv_data(data);
Jakub Pawlowski0ecddf32016-10-19 14:46:09 -0700733
734 if (include_name) {
735 String16 name_param;
736 bt_iface->GetName(&name_param);
737 std::string name(String8(name_param).string());
738 data.push_back(name.length() + 1);
739 data.push_back(bluetooth::kEIRTypeCompleteLocalName);
740 data.insert(data.begin(), name.c_str(), name.c_str() + name.length());
741 }
Arman Ugurayd19bc042015-09-16 18:04:32 -0700742
743 bluetooth::AdvertiseData scan_rsp;
744
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800745 bool status;
Myles Watson911d1ae2016-11-28 16:44:40 -0800746 ble_advertiser_iface->StartMultiAdvertising(
747 ble_advertiser_id.load(), adv_data, scan_rsp, settings, &status);
Arman Ugurayae43de62015-09-24 15:05:21 -0700748 PrintCommandStatus(status);
Arman Ugurayd19bc042015-09-16 18:04:32 -0700749}
750
751void HandleStopAdv(IBluetooth* bt_iface, const vector<string>& args) {
Jakub Pawlowskidaa8a992017-01-09 06:53:36 -0800752 if (ble_advertiser_id.load() == invalid_advertiser_id) {
Jakub Pawlowski67d5a252016-07-13 11:55:16 -0700753 PrintError("BLE advertiser not registered");
Arman Ugurayd19bc042015-09-16 18:04:32 -0700754 return;
755 }
756
Jakub Pawlowski67d5a252016-07-13 11:55:16 -0700757 sp<IBluetoothLeAdvertiser> ble_advertiser_iface;
758 bt_iface->GetLeAdvertiserInterface(&ble_advertiser_iface);
759 if (!ble_advertiser_iface.get()) {
Arman Ugurayd19bc042015-09-16 18:04:32 -0700760 PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
761 return;
762 }
763
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800764 bool status;
Jakub Pawlowski67d5a252016-07-13 11:55:16 -0700765 ble_advertiser_iface->StopMultiAdvertising(ble_advertiser_id.load(), &status);
Arman Ugurayae43de62015-09-24 15:05:21 -0700766 PrintCommandStatus(status);
Arman Ugurayd19bc042015-09-16 18:04:32 -0700767}
768
Jakub Pawlowski608762d2016-01-19 17:07:53 -0800769void HandleConnect(IBluetooth* bt_iface, const vector<string>& args) {
770 string address;
771
772 if (args.size() != 1) {
773 PrintError("Expected MAC address as only argument");
774 return;
775 }
776
777 address = args[0];
778
779 if (!ble_client_id.load()) {
780 PrintError("BLE not registered");
781 return;
782 }
783
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800784 sp<IBluetoothLowEnergy> ble_iface;
785 bt_iface->GetLowEnergyInterface(&ble_iface);
Jakub Pawlowski608762d2016-01-19 17:07:53 -0800786 if (!ble_iface.get()) {
787 PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
788 return;
789 }
790
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800791 bool status;
792 ble_iface->Connect(ble_client_id.load(),
793 String16(address.c_str(), address.length()),
794 false /* is_direct */, &status);
Jakub Pawlowski608762d2016-01-19 17:07:53 -0800795
796 PrintCommandStatus(status);
797}
798
799void HandleDisconnect(IBluetooth* bt_iface, const vector<string>& args) {
800 string address;
801
802 if (args.size() != 1) {
803 PrintError("Expected MAC address as only argument");
804 return;
805 }
806
807 address = args[0];
808
809 if (!ble_client_id.load()) {
810 PrintError("BLE not registered");
811 return;
812 }
813
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800814 sp<IBluetoothLowEnergy> ble_iface;
815 bt_iface->GetLowEnergyInterface(&ble_iface);
Jakub Pawlowski608762d2016-01-19 17:07:53 -0800816 if (!ble_iface.get()) {
817 PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
818 return;
819 }
820
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800821 bool status;
822 ble_iface->Disconnect(ble_client_id.load(),
823 String16(address.c_str(), address.length()), &status);
Jakub Pawlowski608762d2016-01-19 17:07:53 -0800824 PrintCommandStatus(status);
825}
826
Jakub Pawlowski756cc4b2016-01-26 14:56:21 -0800827void HandleSetMtu(IBluetooth* bt_iface, const vector<string>& args) {
828 string address;
829 int mtu;
830
831 if (args.size() != 2) {
832 PrintError("Usage: set-mtu [address] [mtu]");
833 return;
834 }
835
836 address = args[0];
837 mtu = std::stoi(args[1]);
838
839 if (mtu < 23) {
840 PrintError("MTU must be 23 or larger");
841 return;
842 }
843
844 if (!ble_client_id.load()) {
845 PrintError("BLE not registered");
846 return;
847 }
848
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800849 sp<IBluetoothLowEnergy> ble_iface;
850 bt_iface->GetLowEnergyInterface(&ble_iface);
Jakub Pawlowski756cc4b2016-01-26 14:56:21 -0800851 if (!ble_iface.get()) {
852 PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
853 return;
854 }
855
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800856 bool status;
857 ble_iface->SetMtu(ble_client_id.load(),
858 String16(address.c_str(), address.length()), mtu, &status);
Jakub Pawlowski756cc4b2016-01-26 14:56:21 -0800859 PrintCommandStatus(status);
860}
861
Myles Watson911d1ae2016-11-28 16:44:40 -0800862void HandleRegisterBLEScanner(IBluetooth* bt_iface,
863 const vector<string>& args) {
Jakub Pawlowskic3f6a512016-10-27 11:49:40 -0700864 CHECK_NO_ARGS(args);
865
866 if (ble_scanner_registering.load()) {
867 PrintError("In progress");
868 return;
869 }
870
871 if (ble_scanner_id.load()) {
872 PrintError("Already registered");
873 return;
874 }
875
876 sp<IBluetoothLeScanner> ble_scanner_iface;
877 bt_iface->GetLeScannerInterface(&ble_scanner_iface);
878 if (!ble_scanner_iface.get()) {
879 PrintError("Failed to obtain handle to Bluetooth LE Scanner interface");
880 return;
881 }
882
883 bool status;
Myles Watson911d1ae2016-11-28 16:44:40 -0800884 ble_scanner_iface->RegisterScanner(new CLIBluetoothLeScannerCallback(),
885 &status);
Jakub Pawlowskic3f6a512016-10-27 11:49:40 -0700886 ble_scanner_registering = status;
887 PrintCommandStatus(status);
888}
889
Myles Watson911d1ae2016-11-28 16:44:40 -0800890void HandleUnregisterBLEScanner(IBluetooth* bt_iface,
891 const vector<string>& args) {
Jakub Pawlowskic3f6a512016-10-27 11:49:40 -0700892 CHECK_NO_ARGS(args);
893
894 if (!ble_scanner_id.load()) {
895 PrintError("Not registered");
896 return;
897 }
898
899 sp<IBluetoothLeScanner> ble_scanner_iface;
900 bt_iface->GetLeScannerInterface(&ble_scanner_iface);
901 if (!ble_scanner_iface.get()) {
902 PrintError("Failed to obtain handle to Bluetooth LE scanner interface");
903 return;
904 }
905
906 ble_scanner_iface->UnregisterScanner(ble_scanner_id.load());
907 ble_scanner_id = 0;
908 PrintCommandStatus(true);
909}
910
Jakub Pawlowskiba197a22016-01-13 11:28:08 -0800911void HandleStartLeScan(IBluetooth* bt_iface, const vector<string>& args) {
912 if (!ble_client_id.load()) {
913 PrintError("BLE not registered");
914 return;
915 }
916
Chih-Hung Hsieh5dc0d152016-08-17 14:12:51 -0700917 for (const auto& arg : args) {
Jakub Pawlowskiba197a22016-01-13 11:28:08 -0800918 if (arg == "-d") {
919 dump_scan_record = true;
920 } else if (arg == "-h") {
921 static const char kUsage[] =
922 "Usage: start-le-scan [flags]\n"
923 "\n"
924 "Flags:\n"
925 "\t-d\tDump scan record\n"
926 "\t-h\tShow this help message\n";
927 cout << kUsage << endl;
928 return;
929 }
930 }
931
Jakub Pawlowskic3f6a512016-10-27 11:49:40 -0700932 sp<IBluetoothLeScanner> ble_scanner_iface;
933 bt_iface->GetLeScannerInterface(&ble_scanner_iface);
934 if (!ble_scanner_iface.get()) {
935 PrintError("Failed to obtain handle to Bluetooth LE scanner interface");
Jakub Pawlowskiba197a22016-01-13 11:28:08 -0800936 return;
937 }
938
939 bluetooth::ScanSettings settings;
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800940 std::vector<android::bluetooth::ScanFilter> filters;
Jakub Pawlowskiba197a22016-01-13 11:28:08 -0800941
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800942 bool status;
Myles Watson911d1ae2016-11-28 16:44:40 -0800943 ble_scanner_iface->StartScan(ble_scanner_id.load(), settings, filters,
944 &status);
Jakub Pawlowskiba197a22016-01-13 11:28:08 -0800945 PrintCommandStatus(status);
946}
947
948void HandleStopLeScan(IBluetooth* bt_iface, const vector<string>& args) {
949 if (!ble_client_id.load()) {
950 PrintError("BLE not registered");
951 return;
952 }
953
Jakub Pawlowskic3f6a512016-10-27 11:49:40 -0700954 sp<IBluetoothLeScanner> ble_scanner_iface;
955 bt_iface->GetLeScannerInterface(&ble_scanner_iface);
956 if (!ble_scanner_iface.get()) {
957 PrintError("Failed to obtain handle to Bluetooth LE scanner interface");
Jakub Pawlowskiba197a22016-01-13 11:28:08 -0800958 return;
959 }
960
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800961 bool status;
Jakub Pawlowskic3f6a512016-10-27 11:49:40 -0700962 ble_scanner_iface->StopScan(ble_scanner_id.load(), &status);
Jakub Pawlowskiba197a22016-01-13 11:28:08 -0800963 PrintCommandStatus(status);
964}
965
Arman Uguray51923092015-08-17 17:25:04 -0700966void HandleHelp(IBluetooth* bt_iface, const vector<string>& args);
Arman Uguray2117e522015-08-14 17:23:47 -0700967
Arman Ugurayfcf2e032015-08-13 17:05:03 -0700968struct {
969 string command;
Arman Uguray51923092015-08-17 17:25:04 -0700970 void (*func)(IBluetooth*, const vector<string>& args);
Arman Uguray2117e522015-08-14 17:23:47 -0700971 string help;
Arman Ugurayfcf2e032015-08-13 17:05:03 -0700972} kCommandMap[] = {
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800973 {"help", HandleHelp, "\t\t\tDisplay this message"},
974 {"disable", HandleDisable, "\t\t\tDisable Bluetooth"},
Ajay Panicker7b266be2016-03-17 17:09:24 -0700975 {"enable", HandleEnable, "\t\t\tEnable Bluetooth (-h for options)"},
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800976 {"get-state", HandleGetState, "\t\tGet the current adapter state"},
977 {"is-enabled", HandleIsEnabled, "\t\tReturn if Bluetooth is enabled"},
978 {"get-local-address", HandleGetLocalAddress,
979 "\tGet the local adapter address"},
980 {"set-local-name", HandleSetLocalName, "\t\tSet the local adapter name"},
981 {"get-local-name", HandleGetLocalName, "\t\tGet the local adapter name"},
982 {"adapter-info", HandleAdapterInfo, "\t\tPrint adapter properties"},
983 {"supports-multi-adv", HandleSupportsMultiAdv,
984 "\tWhether multi-advertisement is currently supported"},
Jakub Pawlowski67d5a252016-07-13 11:55:16 -0700985 {"register-le-advertiser", HandleRegisterBLEAdvertiser,
986 "\t\tRegister with the Bluetooth Low Energy Advertiser interface"},
987 {"unregister-le-advertiser", HandleUnregisterBLEAdvertiser,
988 "\t\tUnregister from the Bluetooth LE Advertiser interface"},
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -0800989 {"register-ble", HandleRegisterBLE,
990 "\t\tRegister with the Bluetooth Low Energy interface"},
991 {"unregister-ble", HandleUnregisterBLE,
992 "\t\tUnregister from the Bluetooth Low Energy interface"},
993 {"unregister-all-ble", HandleUnregisterAllBLE,
994 "\tUnregister all clients from the Bluetooth Low Energy interface"},
995 {"register-gatt", HandleRegisterGATT,
996 "\t\tRegister with the Bluetooth GATT Client interface"},
997 {"unregister-gatt", HandleUnregisterGATT,
998 "\t\tUnregister from the Bluetooth GATT Client interface"},
999 {"connect-le", HandleConnect, "\t\tConnect to LE device (-h for options)"},
1000 {"disconnect-le", HandleDisconnect,
1001 "\t\tDisconnect LE device (-h for options)"},
1002 {"set-mtu", HandleSetMtu, "\t\tSet MTU (-h for options)"},
1003 {"start-adv", HandleStartAdv, "\t\tStart advertising (-h for options)"},
1004 {"stop-adv", HandleStopAdv, "\t\tStop advertising"},
Jakub Pawlowskic3f6a512016-10-27 11:49:40 -07001005 {"register-le-scanner", HandleRegisterBLEScanner,
1006 "\t\tRegister with the Bluetooth Low Energy scanner interface"},
1007 {"unregister-le-scanner", HandleUnregisterBLEScanner,
1008 "\t\tUnregister from the Bluetooth LE scanner interface"},
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -08001009 {"start-le-scan", HandleStartLeScan,
1010 "\t\tStart LE device scan (-h for options)"},
1011 {"stop-le-scan", HandleStopLeScan, "\t\tStop LE device scan"},
1012 {},
Arman Ugurayfcf2e032015-08-13 17:05:03 -07001013};
Arman Ugurayf5209522015-08-05 21:22:39 -07001014
Arman Uguray51923092015-08-17 17:25:04 -07001015void HandleHelp(IBluetooth* /* bt_iface */, const vector<string>& /* args */) {
Arman Uguray2117e522015-08-14 17:23:47 -07001016 cout << endl;
1017 for (int i = 0; kCommandMap[i].func; i++)
1018 cout << "\t" << kCommandMap[i].command << kCommandMap[i].help << endl;
1019 cout << endl;
1020}
1021
Marie Janssen5d80cb92016-01-21 18:45:53 -08001022const char kExecuteLong[] = "exec";
1023const char kExecuteShort[] = "e";
1024
Myles Watson911d1ae2016-11-28 16:44:40 -08001025bool ExecuteCommand(const sp<IBluetooth>& bt_iface, std::string& command) {
1026 vector<string> args = base::SplitString(command, " ", base::TRIM_WHITESPACE,
1027 base::SPLIT_WANT_ALL);
Marie Janssen5d80cb92016-01-21 18:45:53 -08001028
Myles Watson911d1ae2016-11-28 16:44:40 -08001029 if (args.empty()) return true;
Marie Janssen5d80cb92016-01-21 18:45:53 -08001030
1031 // The first argument is the command while the remaining are what we pass to
1032 // the handler functions.
1033 command = args[0];
1034 args.erase(args.begin());
1035
1036 for (int i = 0; kCommandMap[i].func; i++) {
1037 if (command == kCommandMap[i].command) {
1038 kCommandMap[i].func(bt_iface.get(), args);
1039 return true;
1040 }
1041 }
1042
1043 cout << "Unrecognized command: " << command << endl;
1044 return false;
1045}
1046
Arman Uguray2117e522015-08-14 17:23:47 -07001047} // namespace
1048
Arman Uguray2e434142015-09-04 13:17:39 -07001049class BluetoothDeathRecipient : public android::IBinder::DeathRecipient {
1050 public:
1051 BluetoothDeathRecipient() = default;
1052 ~BluetoothDeathRecipient() override = default;
1053
1054 // android::IBinder::DeathRecipient override:
1055 void binderDied(const android::wp<android::IBinder>& /* who */) override {
Jakub Pawlowski64401bf2016-01-28 23:57:17 -08001056 BeginAsyncOut();
Arman Uguray2e434142015-09-04 13:17:39 -07001057 cout << COLOR_BOLDWHITE "The Bluetooth daemon has died" COLOR_OFF << endl;
Jakub Pawlowski64401bf2016-01-28 23:57:17 -08001058 cout << "\nPress 'ENTER' to exit.";
1059 EndAsyncOut();
Arman Uguray2e434142015-09-04 13:17:39 -07001060
1061 android::IPCThreadState::self()->stopProcess();
1062 should_exit = true;
1063 }
1064
1065 private:
1066 DISALLOW_COPY_AND_ASSIGN(BluetoothDeathRecipient);
1067};
1068
Arman Ugurayae43de62015-09-24 15:05:21 -07001069int main(int argc, char* argv[]) {
1070 base::AtExitManager exit_manager;
1071 base::CommandLine::Init(argc, argv);
1072 logging::LoggingSettings log_settings;
1073
1074 if (!logging::InitLogging(log_settings)) {
1075 LOG(ERROR) << "Failed to set up logging";
1076 return EXIT_FAILURE;
1077 }
1078
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -08001079 sp<IBluetooth> bt_iface;
1080 status_t status = getService(String16(kServiceName.c_str()), &bt_iface);
1081 if (status != OK) {
1082 LOG(ERROR) << "Failed to get service binder: '" << kServiceName
1083 << "' status=" << status;
Arman Ugurayf5209522015-08-05 21:22:39 -07001084 return EXIT_FAILURE;
1085 }
1086
Arman Uguray2e434142015-09-04 13:17:39 -07001087 sp<BluetoothDeathRecipient> dr(new BluetoothDeathRecipient());
1088 if (android::IInterface::asBinder(bt_iface.get())->linkToDeath(dr) !=
1089 android::NO_ERROR) {
1090 LOG(ERROR) << "Failed to register DeathRecipient for IBluetooth";
1091 return EXIT_FAILURE;
1092 }
1093
Arman Uguray39a66be2015-08-20 12:47:55 -07001094 // Initialize the Binder process thread pool. We have to set this up,
1095 // otherwise, incoming callbacks from IBluetoothCallback will block the main
1096 // thread (in other words, we have to do this as we are a "Binder server").
1097 android::ProcessState::self()->startThreadPool();
1098
1099 // Register Adapter state-change callback
1100 sp<CLIBluetoothCallback> callback = new CLIBluetoothCallback();
1101 bt_iface->RegisterCallback(callback);
1102
Jakub Pawlowskia4bd0d22016-02-16 11:53:14 -08001103 cout << COLOR_BOLDWHITE << "Fluoride Command-Line Interface\n"
1104 << COLOR_OFF << endl
Arman Uguray2117e522015-08-14 17:23:47 -07001105 << "Type \"help\" to see possible commands.\n"
Arman Ugurayfcf2e032015-08-13 17:05:03 -07001106 << endl;
1107
Marie Janssen5d80cb92016-01-21 18:45:53 -08001108 string command;
1109
1110 // Add commands from the command line, if they exist.
1111 auto command_line = base::CommandLine::ForCurrentProcess();
1112 if (command_line->HasSwitch(kExecuteLong)) {
1113 command += command_line->GetSwitchValueASCII(kExecuteLong);
1114 }
1115
1116 if (command_line->HasSwitch(kExecuteShort)) {
Myles Watson911d1ae2016-11-28 16:44:40 -08001117 if (!command.empty()) command += " ; ";
Marie Janssen5d80cb92016-01-21 18:45:53 -08001118 command += command_line->GetSwitchValueASCII(kExecuteShort);
1119 }
1120
Arman Ugurayfcf2e032015-08-13 17:05:03 -07001121 while (true) {
Myles Watson911d1ae2016-11-28 16:44:40 -08001122 vector<string> commands = base::SplitString(
1123 command, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
Marie Janssen5d80cb92016-01-21 18:45:53 -08001124 for (string command : commands) {
Myles Watson911d1ae2016-11-28 16:44:40 -08001125 if (!ExecuteCommand(bt_iface, command)) break;
Marie Janssen5d80cb92016-01-21 18:45:53 -08001126 }
1127
1128 commands.clear();
Arman Uguray51923092015-08-17 17:25:04 -07001129
Arman Uguray39a66be2015-08-20 12:47:55 -07001130 PrintPrompt();
1131
1132 showing_prompt = true;
Arman Uguray91c59c92015-10-13 08:06:46 -07001133 auto& istream = getline(cin, command);
Arman Uguray39a66be2015-08-20 12:47:55 -07001134 showing_prompt = false;
Arman Ugurayfcf2e032015-08-13 17:05:03 -07001135
Arman Uguray91c59c92015-10-13 08:06:46 -07001136 if (istream.eof() || should_exit.load()) {
1137 cout << "\nExiting" << endl;
Arman Uguray2e434142015-09-04 13:17:39 -07001138 return EXIT_SUCCESS;
Arman Uguray91c59c92015-10-13 08:06:46 -07001139 }
1140
1141 if (!istream.good()) {
1142 LOG(ERROR) << "An error occured while reading input";
1143 return EXIT_FAILURE;
1144 }
Arman Ugurayfcf2e032015-08-13 17:05:03 -07001145 }
Arman Ugurayf5209522015-08-05 21:22:39 -07001146
1147 return EXIT_SUCCESS;
1148}