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