From c7087d2466a291185853a6b2a16f789233e3420f Mon Sep 17 00:00:00 2001 From: Ajay Panicker Date: Thu, 17 Mar 2016 17:09:24 -0700 Subject: [PATCH] Add guest mode functionality (2/5) Add a flag to enable() to start Bluetooth in restricted mode. In restricted mode, all devices that are paired during restricted mode are deleted upon leaving restricted mode. Right now restricted mode is only entered while a guest user is active. Bug: 27410683 Change-Id: I8f23d28ef0aa3a8df13d469c73005c8e1b894d19 --- btif/include/btif_api.h | 17 +++++++++++++++++ btif/include/btif_storage.h | 12 ++++++++++++ btif/src/bluetooth.c | 15 +++++++++++++-- btif/src/btif_config.c | 22 ++++++++++++++++++++++ btif/src/btif_storage.c | 24 ++++++++++++++++++++++++ service/adapter.cpp | 4 ++-- service/adapter.h | 5 ++++- service/client/main.cpp | 22 +++++++++++++++++++--- service/common/bluetooth/binder/IBluetooth.cpp | 6 ++++-- service/common/bluetooth/binder/IBluetooth.h | 4 ++-- service/hal/fake_bluetooth_interface.cpp | 2 +- service/ipc/binder/bluetooth_binder_server.cpp | 4 ++-- service/ipc/binder/bluetooth_binder_server.h | 3 +-- service/test/adapter_unittest.cpp | 8 ++++---- service/test/mock_adapter.h | 2 +- test/suite/adapter/adapter_unittest.cpp | 12 ++++++------ test/suite/gatt/gatt_test.cpp | 2 +- 17 files changed, 135 insertions(+), 29 deletions(-) diff --git a/btif/include/btif_api.h b/btif/include/btif_api.h index dcaecfc6c..ed67b9ea5 100644 --- a/btif/include/btif_api.h +++ b/btif/include/btif_api.h @@ -89,6 +89,23 @@ bt_status_t btif_shutdown_bluetooth(void); /******************************************************************************* ** +** Function is_restricted_mode +** +** Description Checks if BT was enabled in restriced mode. In restricted +** mode, bonds that are created are marked as temporary. +** These bonds persist until we leave restricted mode, at +** which point they will be deleted from the config. Also +** while in restricted mode, the user can access devices +** that are already paired before entering restricted mode, +** but they cannot remove any of these devices. +** +** Returns bool +** +*******************************************************************************/ +bool is_restricted_mode(void); + +/******************************************************************************* +** ** Function btif_get_adapter_properties ** ** Description Fetches all local adapter properties diff --git a/btif/include/btif_storage.h b/btif/include/btif_storage.h index 03debef12..bc1060c26 100644 --- a/btif/include/btif_storage.h +++ b/btif/include/btif_storage.h @@ -262,6 +262,18 @@ bt_status_t btif_storage_load_bonded_hid_info(void); *******************************************************************************/ bt_status_t btif_storage_remove_hid_info(bt_bdaddr_t *remote_bd_addr); +/******************************************************************************* +** +** Function btif_storage_is_retricted_device +** +** Description BTIF storage API - checks if this device is a restricted device +** +** Returns TRUE if the device is labled as restricted +** FALSE otherwise +** +*******************************************************************************/ +BOOLEAN btif_storage_is_restricted_device(const bt_bdaddr_t *remote_bd_addr); + #if (BLE_INCLUDED == TRUE) bt_status_t btif_storage_add_ble_bonding_key( bt_bdaddr_t *remote_bd_addr, char *key, diff --git a/btif/src/bluetooth.c b/btif/src/bluetooth.c index e0399ab97..14141389a 100644 --- a/btif/src/bluetooth.c +++ b/btif/src/bluetooth.c @@ -59,6 +59,7 @@ #include "osi/include/wakelock.h" #include "stack_manager.h" #include "btif_config.h" +#include "btif_storage.h" #include "btif/include/btif_debug_btsnoop.h" #include "btif/include/btif_debug_conn.h" #include "btif/include/btif_media.h" @@ -68,6 +69,7 @@ ************************************************************************************/ bt_callbacks_t *bt_hal_cbacks = NULL; +bool restricted_mode = FALSE; /************************************************************************************ ** Externs @@ -139,8 +141,10 @@ static int init(bt_callbacks_t *callbacks) { return BT_STATUS_SUCCESS; } -static int enable(void) { - LOG_INFO(LOG_TAG, "%s", __func__); +static int enable(bool start_restricted) { + LOG_INFO(LOG_TAG, "%s: start restricted = %d", __func__, start_restricted); + + restricted_mode = start_restricted; if (!interface_ready()) return BT_STATUS_NOT_READY; @@ -161,6 +165,10 @@ static void cleanup(void) { stack_manager_get_interface()->clean_up_stack(); } +bool is_restricted_mode() { + return restricted_mode; +} + static int get_adapter_properties(void) { /* sanity check */ @@ -281,6 +289,9 @@ static int cancel_bond(const bt_bdaddr_t *bd_addr) static int remove_bond(const bt_bdaddr_t *bd_addr) { + if (is_restricted_mode() && !btif_storage_is_restricted_device(bd_addr)) + return BT_STATUS_SUCCESS; + /* sanity check */ if (interface_ready() == FALSE) return BT_STATUS_NOT_READY; diff --git a/btif/src/btif_config.c b/btif/src/btif_config.c index 64b5818df..fd5ee6973 100644 --- a/btif/src/btif_config.c +++ b/btif/src/btif_config.c @@ -30,6 +30,7 @@ #include "bt_types.h" #include "btcore/include/bdaddr.h" #include "btcore/include/module.h" +#include "btif_api.h" #include "btif_common.h" #include "btif_config.h" #include "btif_config_transcode.h" @@ -67,6 +68,7 @@ static void btif_config_write(UINT16 event, char *p_param); static bool is_factory_reset(void); static void delete_config_files(void); static void btif_config_remove_unpaired(config_t *config); +static void btif_config_remove_restricted(config_t *config); static enum ConfigSource { NOT_LOADED, @@ -153,6 +155,10 @@ static future_t *init(void) { btif_config_remove_unpaired(config); + // Cleanup temporary pairings if we have left guest mode + if (!is_restricted_mode()) + btif_config_remove_restricted(config); + // TODO(sharvil): use a non-wake alarm for this once we have // API support for it. There's no need to wake the system to // write back to disk. @@ -499,6 +505,22 @@ void btif_debug_config_dump(int fd) { pthread_mutex_unlock(&lock); } +static void btif_config_remove_restricted(config_t* config) { + assert(config != NULL); + + pthread_mutex_lock(&lock); + const config_section_node_t *snode = config_section_begin(config); + while (snode != config_section_end(config)) { + const char *section = config_section_name(snode); + if (string_is_bdaddr(section) && config_has_key(config, section, "Restricted")) { + BTIF_TRACE_DEBUG("%s: Removing restricted device %s", __func__, section); + config_remove_section(config, section); + } + snode = config_section_next(snode); + } + pthread_mutex_unlock(&lock); +} + static bool is_factory_reset(void) { char factory_reset[PROPERTY_VALUE_MAX] = {0}; property_get("persist.bluetooth.factoryreset", factory_reset, "false"); diff --git a/btif/src/btif_storage.c b/btif/src/btif_storage.c index e058a14d6..791203f14 100644 --- a/btif/src/btif_storage.c +++ b/btif/src/btif_storage.c @@ -793,6 +793,13 @@ bt_status_t btif_storage_add_bonded_device(bt_bdaddr_t *remote_bd_addr, int ret = btif_config_set_int(bdstr, "LinkKeyType", (int)key_type); ret &= btif_config_set_int(bdstr, "PinLength", (int)pin_length); ret &= btif_config_set_bin(bdstr, "LinkKey", link_key, sizeof(LINK_KEY)); + + if (is_restricted_mode()) { + BTIF_TRACE_WARNING("%s: '%s' pairing will be removed if unrestricted", + __func__, bdstr); + btif_config_set_int(bdstr, "Restricted", 1); + } + /* write bonded info immediately */ btif_config_flush(); return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; @@ -1474,3 +1481,20 @@ bt_status_t btif_storage_read_hl_apps_cb(char *value, int value_size) return bt_status; } +/******************************************************************************* +** +** Function btif_storage_is_restricted_device +** +** Description BTIF storage API - checks if this device is a restricted device +** +** Returns TRUE if the device is labeled as restricted +** FALSE otherwise +** +*******************************************************************************/ +BOOLEAN btif_storage_is_restricted_device(const bt_bdaddr_t *remote_bd_addr) +{ + bdstr_t bdstr; + bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr)); + + return btif_config_exist(bdstr, "Restricted"); +} diff --git a/service/adapter.cpp b/service/adapter.cpp index 891bc089a..45826b287 100644 --- a/service/adapter.cpp +++ b/service/adapter.cpp @@ -105,7 +105,7 @@ class AdapterImpl : public Adapter, return state_.load() == ADAPTER_STATE_ON; } - bool Enable() override { + bool Enable(bool start_restricted) override { AdapterState current_state = GetState(); if (current_state != ADAPTER_STATE_OFF) { LOG(INFO) << "Adapter not disabled - state: " @@ -118,7 +118,7 @@ class AdapterImpl : public Adapter, state_ = ADAPTER_STATE_TURNING_ON; NotifyAdapterStateChanged(current_state, state_); - int status = hal::BluetoothInterface::Get()->GetHALInterface()->enable(); + int status = hal::BluetoothInterface::Get()->GetHALInterface()->enable(start_restricted); if (status != BT_STATUS_SUCCESS) { LOG(ERROR) << "Failed to enable Bluetooth - status: " << BtStatusText((const bt_status_t)status); diff --git a/service/adapter.h b/service/adapter.h index 8594f203f..11226ced8 100644 --- a/service/adapter.h +++ b/service/adapter.h @@ -82,7 +82,10 @@ class Adapter { // to the controller, otherwise returns false. A successful call to this // method only means that the enable request has been sent to the Bluetooth // controller and does not imply that the operation itself succeeded. - virtual bool Enable() = 0; + // The |start_restricted| flag enables the adapter in restricted mode. In + // restricted mode, bonds that are created are marked as restricted in the + // config file. These devices are deleted upon leaving restricted mode. + virtual bool Enable(bool start_restricted) = 0; // Powers off the Bluetooth radio. Returns true, if the disable request was // successfully sent to the Bluetooth controller. diff --git a/service/client/main.cpp b/service/client/main.cpp index 078e1ffed..87fdaf59b 100644 --- a/service/client/main.cpp +++ b/service/client/main.cpp @@ -259,8 +259,24 @@ void HandleDisable(IBluetooth* bt_iface, const vector& args) { } void HandleEnable(IBluetooth* bt_iface, const vector& args) { - CHECK_NO_ARGS(args); - PrintCommandStatus(bt_iface->Enable()); + bool is_restricted_mode = false; + + for (auto iter : args) { + const std::string& arg = iter; + if (arg == "-h") { + static const char kUsage[] = + "Usage: start-adv [flags]\n" + "\n" + "Flags:\n" + "\t--restricted|-r\tStart in restricted mode\n"; + cout << kUsage << endl; + return; + } else if (arg == "--restricted" || arg == "-r") { + is_restricted_mode = true; + } + } + + PrintCommandStatus(bt_iface->Enable(is_restricted_mode)); } void HandleGetState(IBluetooth* bt_iface, const vector& args) { @@ -697,7 +713,7 @@ struct { } kCommandMap[] = { { "help", HandleHelp, "\t\t\tDisplay this message" }, { "disable", HandleDisable, "\t\t\tDisable Bluetooth" }, - { "enable", HandleEnable, "\t\t\tEnable Bluetooth" }, + { "enable", HandleEnable, "\t\t\tEnable Bluetooth (-h for options)" }, { "get-state", HandleGetState, "\t\tGet the current adapter state" }, { "is-enabled", HandleIsEnabled, "\t\tReturn if Bluetooth is enabled" }, { "get-local-address", HandleGetLocalAddress, diff --git a/service/common/bluetooth/binder/IBluetooth.cpp b/service/common/bluetooth/binder/IBluetooth.cpp index 65d130786..3fb091604 100644 --- a/service/common/bluetooth/binder/IBluetooth.cpp +++ b/service/common/bluetooth/binder/IBluetooth.cpp @@ -81,7 +81,8 @@ status_t BnBluetooth::onTransact( } case ENABLE_TRANSACTION: { CHECK_INTERFACE(IBluetooth, data, reply); - bool result = Enable(); + bool start_restricted = data.readBool(); + bool result = Enable(start_restricted); reply->writeInt32(result); return android::NO_ERROR; } @@ -182,10 +183,11 @@ int BpBluetooth::GetState() { return reply.readInt32(); } -bool BpBluetooth::Enable() { +bool BpBluetooth::Enable(bool start_restricted) { Parcel data, reply; data.writeInterfaceToken(IBluetooth::getInterfaceDescriptor()); + data.writeBool(start_restricted); remote()->transact(IBluetooth::ENABLE_TRANSACTION, data, &reply); return reply.readInt32(); diff --git a/service/common/bluetooth/binder/IBluetooth.h b/service/common/bluetooth/binder/IBluetooth.h index 54e0b19d7..ad1d33c2c 100644 --- a/service/common/bluetooth/binder/IBluetooth.h +++ b/service/common/bluetooth/binder/IBluetooth.h @@ -134,7 +134,7 @@ class IBluetooth : public android::IInterface { virtual bool IsEnabled() = 0; virtual int GetState() = 0; - virtual bool Enable() = 0; + virtual bool Enable(bool start_restricted) = 0; virtual bool EnableNoAutoConnect() = 0; virtual bool Disable() = 0; @@ -184,7 +184,7 @@ class BpBluetooth : public android::BpInterface { // IBluetooth overrides: bool IsEnabled() override; int GetState() override; - bool Enable() override; + bool Enable(bool start_restricted) override; bool EnableNoAutoConnect() override; bool Disable() override; diff --git a/service/hal/fake_bluetooth_interface.cpp b/service/hal/fake_bluetooth_interface.cpp index a0b4eaad2..5036c63c5 100644 --- a/service/hal/fake_bluetooth_interface.cpp +++ b/service/hal/fake_bluetooth_interface.cpp @@ -23,7 +23,7 @@ namespace { FakeBluetoothInterface::Manager g_hal_manager; -int FakeHALEnable() { +int FakeHALEnable(bool start_restricted) { return g_hal_manager.enable_succeed ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; } diff --git a/service/ipc/binder/bluetooth_binder_server.cpp b/service/ipc/binder/bluetooth_binder_server.cpp index 7b216ca44..198ccf6e4 100644 --- a/service/ipc/binder/bluetooth_binder_server.cpp +++ b/service/ipc/binder/bluetooth_binder_server.cpp @@ -50,9 +50,9 @@ int BluetoothBinderServer::GetState() { return adapter_->GetState(); } -bool BluetoothBinderServer::Enable() { +bool BluetoothBinderServer::Enable(bool start_restricted) { VLOG(2) << __func__; - return adapter_->Enable(); + return adapter_->Enable(start_restricted); } bool BluetoothBinderServer::EnableNoAutoConnect() { diff --git a/service/ipc/binder/bluetooth_binder_server.h b/service/ipc/binder/bluetooth_binder_server.h index 4c85a2d27..351a8584c 100644 --- a/service/ipc/binder/bluetooth_binder_server.h +++ b/service/ipc/binder/bluetooth_binder_server.h @@ -45,7 +45,7 @@ class BluetoothBinderServer : public BnBluetooth, // IBluetooth overrides: bool IsEnabled() override; int GetState() override; - bool Enable() override; + bool Enable(bool start_restricted) override; bool EnableNoAutoConnect() override; bool Disable() override; @@ -65,7 +65,6 @@ class BluetoothBinderServer : public BnBluetooth, android::sp GetGattServerInterface() override; android::status_t dump(int fd, const android::Vector& args) override; - // bluetooth::Adapter::Observer overrides: void OnAdapterStateChanged(bluetooth::Adapter* adapter, bluetooth::AdapterState prev_state, diff --git a/service/test/adapter_unittest.cpp b/service/test/adapter_unittest.cpp index 1c2df52f4..1d094a4a8 100644 --- a/service/test/adapter_unittest.cpp +++ b/service/test/adapter_unittest.cpp @@ -127,12 +127,12 @@ TEST_F(AdapterTest, Enable) { EXPECT_EQ(bluetooth::ADAPTER_STATE_OFF, adapter_->GetState()); // Enable fails at HAL level - EXPECT_FALSE(adapter_->Enable()); + EXPECT_FALSE(adapter_->Enable(false)); EXPECT_EQ(bluetooth::ADAPTER_STATE_OFF, adapter_->GetState()); // Enable success fake_hal_manager_->enable_succeed = true; - EXPECT_TRUE(adapter_->Enable()); + EXPECT_TRUE(adapter_->Enable(false)); // Should have received a state update. EXPECT_EQ(bluetooth::ADAPTER_STATE_OFF, observer.prev_state()); @@ -140,7 +140,7 @@ TEST_F(AdapterTest, Enable) { // Enable fails because not disabled EXPECT_EQ(bluetooth::ADAPTER_STATE_TURNING_ON, adapter_->GetState()); - EXPECT_FALSE(adapter_->Enable()); + EXPECT_FALSE(adapter_->Enable(false)); // Adapter state updates properly fake_hal_iface_->NotifyAdapterStateChanged(BT_STATE_ON); @@ -151,7 +151,7 @@ TEST_F(AdapterTest, Enable) { EXPECT_EQ(bluetooth::ADAPTER_STATE_ON, observer.cur_state()); // Enable fails because already enabled - EXPECT_FALSE(adapter_->Enable()); + EXPECT_FALSE(adapter_->Enable(false)); } TEST_F(AdapterTest, Disable) { diff --git a/service/test/mock_adapter.h b/service/test/mock_adapter.h index d46ea0330..b56192611 100644 --- a/service/test/mock_adapter.h +++ b/service/test/mock_adapter.h @@ -32,7 +32,7 @@ class MockAdapter : public Adapter { MOCK_METHOD1(RemoveObserver, void(Observer*)); MOCK_CONST_METHOD0(GetState, AdapterState()); MOCK_CONST_METHOD0(IsEnabled, bool()); - MOCK_METHOD0(Enable, bool()); + MOCK_METHOD1(Enable, bool(bool)); MOCK_METHOD0(Disable, bool()); MOCK_CONST_METHOD0(GetName, std::string()); MOCK_METHOD1(SetName, bool(const std::string&)); diff --git a/test/suite/adapter/adapter_unittest.cpp b/test/suite/adapter/adapter_unittest.cpp index d2bf0faea..1f78b210b 100644 --- a/test/suite/adapter/adapter_unittest.cpp +++ b/test/suite/adapter/adapter_unittest.cpp @@ -38,7 +38,7 @@ TEST_F(BluetoothTest, AdapterEnableDisable) { EXPECT_EQ(GetState(), BT_STATE_OFF) << "Test should be run with Adapter disabled"; - EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS); + EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS); semaphore_wait(adapter_state_changed_callback_sem_); EXPECT_EQ(GetState(), BT_STATE_ON) << "Adapter did not turn on."; @@ -52,7 +52,7 @@ TEST_F(BluetoothTest, AdapterRepeatedEnableDisable) { << "Test should be run with Adapter disabled"; for (int i = 0; i < kTestRepeatCount; ++i) { - EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS); + EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS); semaphore_wait(adapter_state_changed_callback_sem_); EXPECT_EQ(GetState(), BT_STATE_ON) << "Adapter did not turn on."; @@ -65,7 +65,7 @@ TEST_F(BluetoothTest, AdapterRepeatedEnableDisable) { TEST_F(BluetoothTest, AdapterSetGetName) { bt_property_t *new_name = property_new_name("BluetoothTestName1"); - EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS); + EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS); semaphore_wait(adapter_state_changed_callback_sem_); EXPECT_EQ(GetState(), BT_STATE_ON) << "Test should be run with Adapter enabled"; @@ -115,7 +115,7 @@ TEST_F(BluetoothTest, AdapterSetGetName) { } TEST_F(BluetoothTest, AdapterStartDiscovery) { - EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS); + EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS); semaphore_wait(adapter_state_changed_callback_sem_); EXPECT_EQ(GetState(), BT_STATE_ON) << "Test should be run with Adapter enabled"; @@ -131,7 +131,7 @@ TEST_F(BluetoothTest, AdapterStartDiscovery) { } TEST_F(BluetoothTest, AdapterCancelDiscovery) { - EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS); + EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS); semaphore_wait(adapter_state_changed_callback_sem_); EXPECT_EQ(GetState(), BT_STATE_ON) << "Test should be run with Adapter enabled"; @@ -156,7 +156,7 @@ TEST_F(BluetoothTest, AdapterDisableDuringBonding) { bt_bdaddr_t bdaddr = { { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 } }; for (int i = 0; i < kTestRepeatCount; ++i) { - EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS); + EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS); semaphore_wait(adapter_state_changed_callback_sem_); EXPECT_EQ(GetState(), BT_STATE_ON) << "Adapter did not turn on."; diff --git a/test/suite/gatt/gatt_test.cpp b/test/suite/gatt/gatt_test.cpp index 150624739..a7912bbdd 100644 --- a/test/suite/gatt/gatt_test.cpp +++ b/test/suite/gatt/gatt_test.cpp @@ -37,7 +37,7 @@ void GattTest::SetUp() { status_ = 0; BluetoothTest::SetUp(); - ASSERT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS); + ASSERT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS); semaphore_wait(adapter_state_changed_callback_sem_); EXPECT_TRUE(GetState() == BT_STATE_ON); -- 2.11.0