/*******************************************************************************
**
+** 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
*******************************************************************************/
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,
#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"
************************************************************************************/
bt_callbacks_t *bt_hal_cbacks = NULL;
+bool restricted_mode = FALSE;
/************************************************************************************
** Externs
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;
stack_manager_get_interface()->clean_up_stack();
}
+bool is_restricted_mode() {
+ return restricted_mode;
+}
+
static int get_adapter_properties(void)
{
/* sanity check */
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;
#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"
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,
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.
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");
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;
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");
+}
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: "
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);
// 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.
}
void HandleEnable(IBluetooth* bt_iface, const vector<string>& 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<string>& args) {
} 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,
}
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;
}
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();
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;
// IBluetooth overrides:
bool IsEnabled() override;
int GetState() override;
- bool Enable() override;
+ bool Enable(bool start_restricted) override;
bool EnableNoAutoConnect() override;
bool Disable() override;
FakeBluetoothInterface::Manager g_hal_manager;
-int FakeHALEnable() {
+int FakeHALEnable(bool start_restricted) {
return g_hal_manager.enable_succeed ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
}
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() {
// IBluetooth overrides:
bool IsEnabled() override;
int GetState() override;
- bool Enable() override;
+ bool Enable(bool start_restricted) override;
bool EnableNoAutoConnect() override;
bool Disable() override;
android::sp<IBluetoothGattServer> GetGattServerInterface() override;
android::status_t dump(int fd, const android::Vector<android::String16>& args) override;
-
// bluetooth::Adapter::Observer overrides:
void OnAdapterStateChanged(bluetooth::Adapter* adapter,
bluetooth::AdapterState prev_state,
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());
// 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);
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) {
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&));
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.";
<< "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.";
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";
}
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";
}
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";
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.";
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);