main.cc revision 2e4341488064be7e8f4d575c8de0a1670ddc81a0
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 1362e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray private: 1372e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray DISALLOW_COPY_AND_ASSIGN(CLIBluetoothLowEnergyCallback); 1382e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray}; 1395192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray 140fcf2e0391950a8b140082fbe78688fa89471fbedArman Ugurayvoid PrintCommandStatus(bool status) { 141fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray cout << COLOR_BOLDWHITE "Command status: " COLOR_OFF 142fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray << (status ? (COLOR_GREEN "success") : (COLOR_RED "failure")) 143fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray << COLOR_OFF << endl << endl; 144fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray} 145fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray 1465192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid PrintFieldAndValue(const string& field, const string& value) { 1475192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray cout << COLOR_BOLDWHITE << field << ": " << COLOR_BOLDYELLOW << value 1485192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray << COLOR_OFF << endl; 1495192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray} 1505192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray 1515192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid PrintFieldAndBoolValue(const string& field, bool value) { 1525192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray PrintFieldAndValue(field, (value ? "true" : "false")); 1535192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray} 1545192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray 1555192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleDisable(IBluetooth* bt_iface, const vector<string>& args) { 1565192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray CHECK_NO_ARGS(args); 157fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray PrintCommandStatus(bt_iface->Disable()); 158fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray} 159fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray 1605192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleEnable(IBluetooth* bt_iface, const vector<string>& args) { 1615192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray CHECK_NO_ARGS(args); 162fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray PrintCommandStatus(bt_iface->Enable()); 163fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray} 164fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray 1655192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleGetState(IBluetooth* bt_iface, const vector<string>& args) { 1665192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray CHECK_NO_ARGS(args); 1672117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray bluetooth::AdapterState state = static_cast<bluetooth::AdapterState>( 1682117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray bt_iface->GetState()); 1695192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray PrintFieldAndValue("Adapter state", bluetooth::AdapterStateToString(state)); 170fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray} 171fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray 1725192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleIsEnabled(IBluetooth* bt_iface, const vector<string>& args) { 1735192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray CHECK_NO_ARGS(args); 174fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray bool enabled = bt_iface->IsEnabled(); 1755192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray PrintFieldAndBoolValue("Adapter enabled", enabled); 176fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray} 177fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray 1785192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleGetLocalAddress(IBluetooth* bt_iface, const vector<string>& args) { 1795192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray CHECK_NO_ARGS(args); 1805192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray string address = bt_iface->GetAddress(); 1815192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray PrintFieldAndValue("Adapter address", address); 1825192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray} 1835192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray 1845192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleSetLocalName(IBluetooth* bt_iface, const vector<string>& args) { 1855192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray CHECK_ARGS_COUNT(args, >=, 1, "No name was given"); 1865192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray 1875192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray std::string name; 1885192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray for (const auto& arg : args) 1895192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray name += arg + " "; 1905192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray 1915192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray base::TrimWhitespaceASCII(name, base::TRIM_TRAILING, &name); 1925192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray 1935192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray PrintCommandStatus(bt_iface->SetName(name)); 1945192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray} 1955192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray 1965192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleGetLocalName(IBluetooth* bt_iface, const vector<string>& args) { 1975192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray CHECK_NO_ARGS(args); 1985192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray string name = bt_iface->GetName(); 1995192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray PrintFieldAndValue("Adapter name", name); 2005192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray} 2015192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray 2025192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleAdapterInfo(IBluetooth* bt_iface, const vector<string>& args) { 2035192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray CHECK_NO_ARGS(args); 2045192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray 2055192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray cout << COLOR_BOLDWHITE "Adapter Properties: " COLOR_OFF << endl; 2065192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray 2075192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray PrintFieldAndValue("\tAddress", bt_iface->GetAddress()); 2085192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray PrintFieldAndValue("\tState", bluetooth::AdapterStateToString( 2095192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray static_cast<bluetooth::AdapterState>(bt_iface->GetState()))); 2105192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray PrintFieldAndValue("\tName", bt_iface->GetName()); 21110b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray PrintFieldAndBoolValue("\tMulti-Adv. supported", 21210b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray bt_iface->IsMultiAdvertisementSupported()); 21310b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray} 21410b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray 21510b54c4b7f1a863a27eca4158f256062ec9c3770Arman Ugurayvoid HandleSupportsMultiAdv(IBluetooth* bt_iface, const vector<string>& args) { 21610b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray CHECK_NO_ARGS(args); 21710b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray 21810b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray bool status = bt_iface->IsMultiAdvertisementSupported(); 21910b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray PrintFieldAndBoolValue("Multi-advertisement support", status); 2205192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray} 2215192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray 2222e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayvoid HandleRegisterBLE(IBluetooth* bt_iface, const vector<string>& args) { 2232e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray CHECK_NO_ARGS(args); 2242e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray 2252e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray if (ble_registering.load()) { 2262e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray PrintError("In progress"); 2272e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray return; 2282e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray } 2292e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray 2302e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray if (ble_client_if.load()) { 2312e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray PrintError("Already registered"); 2322e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray return; 2332e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray } 2342e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray 2352e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray sp<IBluetoothLowEnergy> ble_iface = bt_iface->GetLowEnergyInterface(); 2362e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray if (!ble_iface.get()) { 2372e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray PrintError("Failed to obtain handle to Bluetooth Low Energy interface"); 2382e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray return; 2392e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray } 2402e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray 2412e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray ble_iface->RegisterClient(new CLIBluetoothLowEnergyCallback()); 2422e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray ble_registering = true; 2432e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray PrintCommandStatus(true); 2442e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray} 2452e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray 2462e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayvoid HandleUnregisterBLE(IBluetooth* bt_iface, const vector<string>& args) { 2472e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray CHECK_NO_ARGS(args); 2482e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray 2492e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray if (!ble_client_if.load()) { 2502e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray PrintError("Not registered"); 2512e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray return; 2522e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray } 2532e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray 2542e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray sp<IBluetoothLowEnergy> ble_iface = bt_iface->GetLowEnergyInterface(); 2552e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray if (!ble_iface.get()) { 2562e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray PrintError("Failed to obtain handle to Bluetooth Low Energy interface"); 2572e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray return; 2582e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray } 2592e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray 2602e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray ble_iface->UnregisterClient(ble_client_if.load()); 2612e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray ble_client_if = 0; 2622e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray PrintCommandStatus(true); 2632e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray} 2642e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray 2652e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayvoid HandleUnregisterAllBLE(IBluetooth* bt_iface, const vector<string>& args) { 2662e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray CHECK_NO_ARGS(args); 2672e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray 2682e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray sp<IBluetoothLowEnergy> ble_iface = bt_iface->GetLowEnergyInterface(); 2692e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray if (!ble_iface.get()) { 2702e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray PrintError("Failed to obtain handle to Bluetooth Low Energy interface"); 2712e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray return; 2722e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray } 2732e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray 2742e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray ble_iface->UnregisterAll(); 2752e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray PrintCommandStatus(true); 2762e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray} 2772e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray 2785192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleHelp(IBluetooth* bt_iface, const vector<string>& args); 2792117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray 280fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguraystruct { 281fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray string command; 2825192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray void (*func)(IBluetooth*, const vector<string>& args); 2832117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray string help; 284fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray} kCommandMap[] = { 2855192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray { "help", HandleHelp, "\t\t\tDisplay this message" }, 2865192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray { "disable", HandleDisable, "\t\t\tDisable Bluetooth" }, 2875192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray { "enable", HandleEnable, "\t\t\tEnable Bluetooth" }, 2885192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray { "get-state", HandleGetState, "\t\tGet the current adapter state" }, 2895192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray { "is-enabled", HandleIsEnabled, "\t\tReturn if Bluetooth is enabled" }, 2905192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray { "get-local-address", HandleGetLocalAddress, 2915192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray "\tGet the local adapter address" }, 2925192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray { "set-local-name", HandleSetLocalName, "\t\tSet the local adapter name" }, 2935192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray { "get-local-name", HandleGetLocalName, "\t\tGet the local adapter name" }, 2945192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray { "adapter-info", HandleAdapterInfo, "\t\tPrint adapter properties" }, 29510b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray { "supports-multi-adv", HandleSupportsMultiAdv, 29610b54c4b7f1a863a27eca4158f256062ec9c3770Arman Uguray "\tWhether multi-advertisement is currently supported" }, 2972e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray { "register-ble", HandleRegisterBLE, 2982e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray "\t\tRegister with the Bluetooth Low Energy interface" }, 2992e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray { "unregister-ble", HandleUnregisterBLE, 3002e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray "\t\tUnregister from the Bluetooth Low Energy interface" }, 3012e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray { "unregister-all-ble", HandleUnregisterAllBLE, 3022e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray "\tUnregister all clients from the Bluetooth Low Energy interface" }, 303fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray {}, 304fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray}; 305f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray 3065192309af14408c3f170f15c1282ae5c1eb5abffArman Ugurayvoid HandleHelp(IBluetooth* /* bt_iface */, const vector<string>& /* args */) { 3072117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray cout << endl; 3082117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray for (int i = 0; kCommandMap[i].func; i++) 3092117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray cout << "\t" << kCommandMap[i].command << kCommandMap[i].help << endl; 3102117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray cout << endl; 3112117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray} 3122117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray 3132117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray} // namespace 3142117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray 3152e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Ugurayclass BluetoothDeathRecipient : public android::IBinder::DeathRecipient { 3162e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray public: 3172e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray BluetoothDeathRecipient() = default; 3182e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray ~BluetoothDeathRecipient() override = default; 3192e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray 3202e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray // android::IBinder::DeathRecipient override: 3212e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray void binderDied(const android::wp<android::IBinder>& /* who */) override { 3222e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray if (showing_prompt.load()) 3232e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray cout << endl; 3242e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray cout << COLOR_BOLDWHITE "The Bluetooth daemon has died" COLOR_OFF << endl; 3252e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray cout << "\nPress 'ENTER' to exit." << endl; 3262e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray if (showing_prompt.load()) 3272e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray PrintPrompt(); 3282e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray 3292e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray android::IPCThreadState::self()->stopProcess(); 3302e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray should_exit = true; 3312e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray } 3322e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray 3332e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray private: 3342e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray DISALLOW_COPY_AND_ASSIGN(BluetoothDeathRecipient); 3352e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray}; 3362e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray 337f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Ugurayint main() { 338f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray sp<IBluetooth> bt_iface = IBluetooth::getClientInterface(); 339f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray if (!bt_iface.get()) { 340f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray LOG(ERROR) << "Failed to obtain handle on IBluetooth"; 341f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray return EXIT_FAILURE; 342f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray } 343f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray 3442e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray sp<BluetoothDeathRecipient> dr(new BluetoothDeathRecipient()); 3452e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray if (android::IInterface::asBinder(bt_iface.get())->linkToDeath(dr) != 3462e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray android::NO_ERROR) { 3472e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray LOG(ERROR) << "Failed to register DeathRecipient for IBluetooth"; 3482e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray return EXIT_FAILURE; 3492e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray } 3502e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray 35139a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray // Initialize the Binder process thread pool. We have to set this up, 35239a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray // otherwise, incoming callbacks from IBluetoothCallback will block the main 35339a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray // thread (in other words, we have to do this as we are a "Binder server"). 35439a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray android::ProcessState::self()->startThreadPool(); 35539a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray 35639a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray // Register Adapter state-change callback 35739a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray sp<CLIBluetoothCallback> callback = new CLIBluetoothCallback(); 35839a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray bt_iface->RegisterCallback(callback); 35939a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray 360fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray cout << COLOR_BOLDWHITE << "Fluoride Command-Line Interface\n" << COLOR_OFF 3612117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray << endl 3622117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray << "Type \"help\" to see possible commands.\n" 363fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray << endl; 364fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray 365fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray while (true) { 366fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray string command; 3675192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray 36839a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray PrintPrompt(); 36939a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray 37039a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray showing_prompt = true; 371fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray getline(cin, command); 37239a66bed960d96eca900e7e002e0d7bef0e0e151Arman Uguray showing_prompt = false; 373fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray 3742e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray if (should_exit.load()) 3752e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray return EXIT_SUCCESS; 3762e4341488064be7e8f4d575c8de0a1670ddc81a0Arman Uguray 3775192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray vector<string> args; 3785192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray base::SplitString(command, ' ', &args); 3795192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray 3805192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray if (args.empty()) 3815192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray continue; 3825192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray 3835192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray // The first argument is the command while the remaning are what we pass to 3845192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray // the handler functions. 3855192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray command = args[0]; 3865192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray args.erase(args.begin()); 3875192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray 388fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray bool command_handled = false; 3892117e520c9f5b105ade7e92c4ab4928ea905f176Arman Uguray for (int i = 0; kCommandMap[i].func && !command_handled; i++) { 390fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray if (command == kCommandMap[i].command) { 3915192309af14408c3f170f15c1282ae5c1eb5abffArman Uguray kCommandMap[i].func(bt_iface.get(), args); 392fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray command_handled = true; 393fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray } 394fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray } 395fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray 396fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray if (!command_handled) 397fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray cout << "Unrecognized command: " << command << endl; 398fcf2e0391950a8b140082fbe78688fa89471fbedArman Uguray } 399f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray 400f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray return EXIT_SUCCESS; 401f52095257e36b887d7ddfd1f00871b9311dbfa1bArman Uguray} 402