main.cc revision 52bfc6060cec652a67c8989e0548225af0008be1
1f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//
2f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  Copyright (C) 2015 Google, Inc.
3f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//
4f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  Licensed under the Apache License, Version 2.0 (the "License");
5f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  you may not use this file except in compliance with the License.
6f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  You may obtain a copy of the License at:
7f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//
8f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  http://www.apache.org/licenses/LICENSE-2.0
9f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//
10f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  Unless required by applicable law or agreed to in writing, software
11f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  distributed under the License is distributed on an "AS IS" BASIS,
12f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  See the License for the specific language governing permissions and
14f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//  limitations under the License.
15f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray//
16f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
17fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray#include <iostream>
18fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray#include <string>
19fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
20f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray#include <base/logging.h>
2139a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray#include <base/macros.h>
225192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray#include <base/strings/string_split.h>
235192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray#include <base/strings/string_util.h>
242e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray#include <binder/IPCThreadState.h>
2539a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray#include <binder/ProcessState.h>
26f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
272117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray#include "service/adapter_state.h"
28f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray#include "service/ipc/binder/IBluetooth.h"
2939a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray#include "service/ipc/binder/IBluetoothCallback.h"
302e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray#include "service/low_energy_constants.h"
31f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
32fcf2e0391950a8b140082fbe78688fa89471fbedArman Ugurayusing namespace std;
33fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
34f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Ugurayusing android::sp;
35f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
36f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Ugurayusing ipc::binder::IBluetooth;
372e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayusing ipc::binder::IBluetoothLowEnergy;
38f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
392117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguraynamespace {
402117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray
412117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray#define COLOR_OFF         "\x1B[0m"
422117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray#define COLOR_RED         "\x1B[0;91m"
432117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray#define COLOR_GREEN       "\x1B[0;92m"
442117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray#define COLOR_YELLOW      "\x1B[0;93m"
452117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray#define COLOR_BLUE        "\x1B[0;94m"
462117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray#define COLOR_MAGENTA     "\x1B[0;95m"
472117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray#define COLOR_BOLDGRAY    "\x1B[1;30m"
482117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray#define COLOR_BOLDWHITE   "\x1B[1;37m"
492117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray#define COLOR_BOLDYELLOW  "\x1B[1;93m"
50fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
51fcf2e0391950a8b140082fbe78688fa89471fbedArman Ugurayconst char kCommandDisable[] = "disable";
52fcf2e0391950a8b140082fbe78688fa89471fbedArman Ugurayconst char kCommandEnable[] = "enable";
53fcf2e0391950a8b140082fbe78688fa89471fbedArman Ugurayconst char kCommandGetState[] = "get-state";
54fcf2e0391950a8b140082fbe78688fa89471fbedArman Ugurayconst char kCommandIsEnabled[] = "is-enabled";
55fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
565192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray#define CHECK_ARGS_COUNT(args, op, num, msg) \
575192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  if (!(args.size() op num)) { \
585192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray    PrintError(msg); \
595192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray    return; \
605192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  }
615192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray#define CHECK_NO_ARGS(args) \
625192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_ARGS_COUNT(args, ==, 0, "Expected no arguments")
635192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
6439a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray// TODO(armansito): Clean up this code. Right now everything is in this
6539a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray// monolithic file. We should organize this into different classes for command
6639a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray// handling, console output/printing, callback handling, etc.
6739a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray// (See http://b/23387611)
6839a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
6939a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray// Used to synchronize the printing of the command-line prompt and incoming
7039a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray// Binder callbacks.
7139a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguraystd::atomic_bool showing_prompt(false);
7239a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
732e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray// The registered IBluetoothLowEnergy client handle. If |ble_registering| is
742e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray// true then an operation to register the client is in progress.
752e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguraystd::atomic_bool ble_registering(false);
762e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguraystd::atomic_int ble_client_if(0);
772e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
782e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray// True if the remote process has died and we should exit.
792e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguraystd::atomic_bool should_exit(false);
802e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
8139a66bed960d96eca900e7e002e0d7bef0e0e151Arman Ugurayvoid PrintPrompt() {
8239a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  cout << COLOR_BLUE "[FCLI] " COLOR_OFF << flush;
8339a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray}
8439a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
852e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayvoid PrintError(const string& message) {
862e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  cout << COLOR_RED << message << COLOR_OFF << endl;
872e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray}
882e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
8939a66bed960d96eca900e7e002e0d7bef0e0e151Arman Ugurayclass CLIBluetoothCallback : public ipc::binder::BnBluetoothCallback {
9039a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray public:
9139a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  CLIBluetoothCallback() = default;
9239a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  ~CLIBluetoothCallback() override = default;
9339a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
942e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  // IBluetoothCallback overrides:
9539a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  void OnBluetoothStateChange(
9639a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray      bluetooth::AdapterState prev_state,
9739a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray      bluetooth::AdapterState new_state) override {
9839a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray    if (showing_prompt.load())
9939a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray      cout << endl;
10039a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray    cout << COLOR_BOLDWHITE "Adapter state changed: " COLOR_OFF
10139a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray         << COLOR_MAGENTA << AdapterStateToString(prev_state) << COLOR_OFF
10239a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray         << COLOR_BOLDWHITE " -> " COLOR_OFF
10339a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray         << COLOR_BOLDYELLOW << AdapterStateToString(new_state) << COLOR_OFF
10439a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray         << endl << endl;
10539a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray    if (showing_prompt.load())
10639a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray      PrintPrompt();
10739a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  }
10839a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
10939a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray private:
11039a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  DISALLOW_COPY_AND_ASSIGN(CLIBluetoothCallback);
11139a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray};
11239a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
1132e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayclass CLIBluetoothLowEnergyCallback
1142e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    : public ipc::binder::BnBluetoothLowEnergyCallback {
1152e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray public:
1162e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  CLIBluetoothLowEnergyCallback() = default;
1172e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  ~CLIBluetoothLowEnergyCallback() = default;
1182e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
1192e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  // IBluetoothLowEnergyCallback overrides:
1202e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  void OnClientRegistered(int status, int client_if) override {
1212e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    if (showing_prompt.load())
1222e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray      cout << endl;
1232e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    if (status != bluetooth::BLE_STATUS_SUCCESS) {
1242e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray      PrintError("Failed to register BLE client");
1252e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    } else {
1262e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray      ble_client_if = client_if;
1272e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray      cout << COLOR_BOLDWHITE "Registered BLE client with ID: " COLOR_OFF
1282e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray           << COLOR_GREEN << client_if << COLOR_OFF << endl << endl;
1292e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    }
1302e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    if (showing_prompt.load())
1312e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray      PrintPrompt();
1322e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
1332e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    ble_registering = false;
1342e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
1352e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
13652bfc6060cec652a67c8989e0548225af0008be1Arman Uguray  void OnMultiAdvertiseCallback(
13752bfc6060cec652a67c8989e0548225af0008be1Arman Uguray      int status, bool is_start,
13852bfc6060cec652a67c8989e0548225af0008be1Arman Uguray      const bluetooth::AdvertiseSettings& settings) {
13952bfc6060cec652a67c8989e0548225af0008be1Arman Uguray    // TODO(armansito): Implement once there are commands to start and stop
14052bfc6060cec652a67c8989e0548225af0008be1Arman Uguray    // advertising.
14152bfc6060cec652a67c8989e0548225af0008be1Arman Uguray  }
14252bfc6060cec652a67c8989e0548225af0008be1Arman Uguray
1432e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray private:
1442e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLowEnergyCallback);
1452e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray};
1465192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
147fcf2e0391950a8b140082fbe78688fa89471fbedArman Ugurayvoid PrintCommandStatus(bool status) {
148fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray  cout << COLOR_BOLDWHITE "Command status: " COLOR_OFF
149fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray       << (status ? (COLOR_GREEN "success") : (COLOR_RED "failure"))
150fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray       << COLOR_OFF << endl << endl;
151fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray}
152fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
1535192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid PrintFieldAndValue(const string& field, const string& value) {
1545192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  cout << COLOR_BOLDWHITE << field << ": " << COLOR_BOLDYELLOW << value
1555192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray       << COLOR_OFF << endl;
1565192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray}
1575192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
1585192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid PrintFieldAndBoolValue(const string& field, bool value) {
1595192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  PrintFieldAndValue(field, (value ? "true" : "false"));
1605192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray}
1615192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
1625192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleDisable(IBluetooth* bt_iface, const vector<string>& args) {
1635192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
164fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray  PrintCommandStatus(bt_iface->Disable());
165fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray}
166fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
1675192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleEnable(IBluetooth* bt_iface, const vector<string>& args) {
1685192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
169fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray  PrintCommandStatus(bt_iface->Enable());
170fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray}
171fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
1725192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleGetState(IBluetooth* bt_iface, const vector<string>& args) {
1735192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
1742117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray  bluetooth::AdapterState state = static_cast<bluetooth::AdapterState>(
1752117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray      bt_iface->GetState());
1765192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  PrintFieldAndValue("Adapter state", bluetooth::AdapterStateToString(state));
177fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray}
178fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
1795192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleIsEnabled(IBluetooth* bt_iface, const vector<string>& args) {
1805192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
181fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray  bool enabled = bt_iface->IsEnabled();
1825192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  PrintFieldAndBoolValue("Adapter enabled", enabled);
183fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray}
184fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
1855192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleGetLocalAddress(IBluetooth* bt_iface, const vector<string>& args) {
1865192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
1875192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  string address = bt_iface->GetAddress();
1885192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  PrintFieldAndValue("Adapter address", address);
1895192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray}
1905192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
1915192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleSetLocalName(IBluetooth* bt_iface, const vector<string>& args) {
1925192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_ARGS_COUNT(args, >=, 1, "No name was given");
1935192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
1945192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  std::string name;
1955192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  for (const auto& arg : args)
1965192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray    name += arg + " ";
1975192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
1985192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  base::TrimWhitespaceASCII(name, base::TRIM_TRAILING, &name);
1995192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
2005192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  PrintCommandStatus(bt_iface->SetName(name));
2015192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray}
2025192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
2035192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleGetLocalName(IBluetooth* bt_iface, const vector<string>& args) {
2045192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
2055192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  string name = bt_iface->GetName();
2065192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  PrintFieldAndValue("Adapter name", name);
2075192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray}
2085192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
2095192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleAdapterInfo(IBluetooth* bt_iface, const vector<string>& args) {
2105192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  CHECK_NO_ARGS(args);
2115192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
2125192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  cout << COLOR_BOLDWHITE "Adapter Properties: " COLOR_OFF << endl;
2135192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
2145192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  PrintFieldAndValue("\tAddress", bt_iface->GetAddress());
2155192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  PrintFieldAndValue("\tState", bluetooth::AdapterStateToString(
2165192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray      static_cast<bluetooth::AdapterState>(bt_iface->GetState())));
2175192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  PrintFieldAndValue("\tName", bt_iface->GetName());
21810b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray  PrintFieldAndBoolValue("\tMulti-Adv. supported",
21910b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray                         bt_iface->IsMultiAdvertisementSupported());
22010b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray}
22110b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray
22210b54c4b7f1a863a27eca4158f256062ec9c3770Arman Ugurayvoid HandleSupportsMultiAdv(IBluetooth* bt_iface, const vector<string>& args) {
22310b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray  CHECK_NO_ARGS(args);
22410b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray
22510b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray  bool status = bt_iface->IsMultiAdvertisementSupported();
22610b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray  PrintFieldAndBoolValue("Multi-advertisement support", status);
2275192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray}
2285192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
2292e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayvoid HandleRegisterBLE(IBluetooth* bt_iface, const vector<string>& args) {
2302e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  CHECK_NO_ARGS(args);
2312e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
2322e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  if (ble_registering.load()) {
2332e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    PrintError("In progress");
2342e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return;
2352e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
2362e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
2372e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  if (ble_client_if.load()) {
2382e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    PrintError("Already registered");
2392e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return;
2402e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
2412e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
2422e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  sp<IBluetoothLowEnergy> ble_iface = bt_iface->GetLowEnergyInterface();
2432e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  if (!ble_iface.get()) {
2442e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
2452e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return;
2462e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
2472e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
2482e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  ble_iface->RegisterClient(new CLIBluetoothLowEnergyCallback());
2492e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  ble_registering = true;
2502e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  PrintCommandStatus(true);
2512e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray}
2522e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
2532e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayvoid HandleUnregisterBLE(IBluetooth* bt_iface, const vector<string>& args) {
2542e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  CHECK_NO_ARGS(args);
2552e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
2562e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  if (!ble_client_if.load()) {
2572e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    PrintError("Not registered");
2582e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return;
2592e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
2602e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
2612e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  sp<IBluetoothLowEnergy> ble_iface = bt_iface->GetLowEnergyInterface();
2622e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  if (!ble_iface.get()) {
2632e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
2642e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return;
2652e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
2662e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
2672e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  ble_iface->UnregisterClient(ble_client_if.load());
2682e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  ble_client_if = 0;
2692e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  PrintCommandStatus(true);
2702e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray}
2712e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
2722e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayvoid HandleUnregisterAllBLE(IBluetooth* bt_iface, const vector<string>& args) {
2732e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  CHECK_NO_ARGS(args);
2742e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
2752e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  sp<IBluetoothLowEnergy> ble_iface = bt_iface->GetLowEnergyInterface();
2762e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  if (!ble_iface.get()) {
2772e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    PrintError("Failed to obtain handle to Bluetooth Low Energy interface");
2782e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return;
2792e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
2802e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
2812e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  ble_iface->UnregisterAll();
2822e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  PrintCommandStatus(true);
2832e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray}
2842e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
2855192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleHelp(IBluetooth* bt_iface, const vector<string>& args);
2862117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray
287fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguraystruct {
288fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray  string command;
2895192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  void (*func)(IBluetooth*, const vector<string>& args);
2902117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray  string help;
291fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray} kCommandMap[] = {
2925192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  { "help", HandleHelp, "\t\t\tDisplay this message" },
2935192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  { "disable", HandleDisable, "\t\t\tDisable Bluetooth" },
2945192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  { "enable", HandleEnable, "\t\t\tEnable Bluetooth" },
2955192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  { "get-state", HandleGetState, "\t\tGet the current adapter state" },
2965192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  { "is-enabled", HandleIsEnabled, "\t\tReturn if Bluetooth is enabled" },
2975192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  { "get-local-address", HandleGetLocalAddress,
2985192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray    "\tGet the local adapter address" },
2995192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  { "set-local-name", HandleSetLocalName, "\t\tSet the local adapter name" },
3005192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  { "get-local-name", HandleGetLocalName, "\t\tGet the local adapter name" },
3015192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray  { "adapter-info", HandleAdapterInfo, "\t\tPrint adapter properties" },
30210b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray  { "supports-multi-adv", HandleSupportsMultiAdv,
30310b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray    "\tWhether multi-advertisement is currently supported" },
3042e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  { "register-ble", HandleRegisterBLE,
3052e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    "\t\tRegister with the Bluetooth Low Energy interface" },
3062e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  { "unregister-ble", HandleUnregisterBLE,
3072e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    "\t\tUnregister from the Bluetooth Low Energy interface" },
3082e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  { "unregister-all-ble", HandleUnregisterAllBLE,
3092e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    "\tUnregister all clients from the Bluetooth Low Energy interface" },
310fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray  {},
311fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray};
312f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
3135192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleHelp(IBluetooth* /* bt_iface */, const vector<string>& /* args */) {
3142117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray  cout << endl;
3152117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray  for (int i = 0; kCommandMap[i].func; i++)
3162117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray    cout << "\t" << kCommandMap[i].command << kCommandMap[i].help << endl;
3172117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray  cout << endl;
3182117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray}
3192117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray
3202117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray}  // namespace
3212117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray
3222e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayclass BluetoothDeathRecipient : public android::IBinder::DeathRecipient {
3232e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray public:
3242e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  BluetoothDeathRecipient() = default;
3252e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  ~BluetoothDeathRecipient() override = default;
3262e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
3272e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  // android::IBinder::DeathRecipient override:
3282e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  void binderDied(const android::wp<android::IBinder>& /* who */) override {
3292e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    if (showing_prompt.load())
3302e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray      cout << endl;
3312e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    cout << COLOR_BOLDWHITE "The Bluetooth daemon has died" COLOR_OFF << endl;
3322e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    cout << "\nPress 'ENTER' to exit." << endl;
3332e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    if (showing_prompt.load())
3342e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray      PrintPrompt();
3352e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
3362e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    android::IPCThreadState::self()->stopProcess();
3372e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    should_exit = true;
3382e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
3392e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
3402e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray private:
3412e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  DISALLOW_COPY_AND_ASSIGN(BluetoothDeathRecipient);
3422e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray};
3432e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
344f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Ugurayint main() {
345f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray  sp<IBluetooth> bt_iface = IBluetooth::getClientInterface();
346f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray  if (!bt_iface.get()) {
347f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray    LOG(ERROR) << "Failed to obtain handle on IBluetooth";
348f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray    return EXIT_FAILURE;
349f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray  }
350f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
3512e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  sp<BluetoothDeathRecipient> dr(new BluetoothDeathRecipient());
3522e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  if (android::IInterface::asBinder(bt_iface.get())->linkToDeath(dr) !=
3532e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray      android::NO_ERROR) {
3542e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    LOG(ERROR) << "Failed to register DeathRecipient for IBluetooth";
3552e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    return EXIT_FAILURE;
3562e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray  }
3572e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
35839a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  // Initialize the Binder process thread pool. We have to set this up,
35939a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  // otherwise, incoming callbacks from IBluetoothCallback will block the main
36039a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  // thread (in other words, we have to do this as we are a "Binder server").
36139a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  android::ProcessState::self()->startThreadPool();
36239a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
36339a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  // Register Adapter state-change callback
36439a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  sp<CLIBluetoothCallback> callback = new CLIBluetoothCallback();
36539a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray  bt_iface->RegisterCallback(callback);
36639a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
367fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray  cout << COLOR_BOLDWHITE << "Fluoride Command-Line Interface\n" << COLOR_OFF
3682117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray       << endl
3692117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray       << "Type \"help\" to see possible commands.\n"
370fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray       << endl;
371fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
372fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray  while (true) {
373fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray    string command;
3745192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
37539a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray    PrintPrompt();
37639a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray
37739a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray    showing_prompt = true;
378fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray    getline(cin, command);
37939a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray    showing_prompt = false;
380fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
3812e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray    if (should_exit.load())
3822e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray      return EXIT_SUCCESS;
3832e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray
3845192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray    vector<string> args;
3855192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray    base::SplitString(command, ' ', &args);
3865192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
3875192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray    if (args.empty())
3885192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray      continue;
3895192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
3905192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray    // The first argument is the command while the remaning are what we pass to
3915192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray    // the handler functions.
3925192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray    command = args[0];
3935192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray    args.erase(args.begin());
3945192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray
395fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray    bool command_handled = false;
3962117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray    for (int i = 0; kCommandMap[i].func && !command_handled; i++) {
397fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray      if (command == kCommandMap[i].command) {
3985192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray        kCommandMap[i].func(bt_iface.get(), args);
399fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray        command_handled = true;
400fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray      }
401fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray    }
402fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray
403fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray    if (!command_handled)
404fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray      cout << "Unrecognized command: " << command << endl;
405fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray  }
406f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray
407f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray  return EXIT_SUCCESS;
408f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray}
409