Merge "DO NOT MERGE btif: check overflow on create_pbuf size" into security-aosp-mnc-mr1-release
diff --git a/btif/include/btif_api.h b/btif/include/btif_api.h
index 62687d3..6bb1d39 100644
--- a/btif/include/btif_api.h
+++ b/btif/include/btif_api.h
@@ -87,6 +87,23 @@
 
 /*******************************************************************************
 **
+** 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 7763d3a3..26384e1 100644
--- a/btif/include/btif_storage.h
+++ b/btif/include/btif_storage.h
@@ -309,6 +309,18 @@
 *******************************************************************************/
 BOOLEAN btif_storage_is_fixed_pin_zeros_keyboard(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 3213221..5ee48d3 100644
--- a/btif/src/bluetooth.c
+++ b/btif/src/bluetooth.c
@@ -55,6 +55,7 @@
 #include "osi/include/log.h"
 #include "stack_manager.h"
 #include "btif_config.h"
+#include "btif_storage.h"
 
 /************************************************************************************
 **  Constants & Macros
@@ -67,6 +68,7 @@
 ************************************************************************************/
 
 bt_callbacks_t *bt_hal_cbacks = NULL;
+bool restricted_mode = FALSE;
 
 /** Operating System specific callouts for resource management */
 bt_os_callouts_t *bt_os_callouts = NULL;
@@ -135,8 +137,10 @@
   return BT_STATUS_SUCCESS;
 }
 
-static int enable(void) {
-  LOG_INFO("%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;
@@ -157,6 +161,10 @@
   stack_manager_get_interface()->clean_up_stack_async();
 }
 
+bool is_restricted_mode() {
+  return restricted_mode;
+}
+
 static int get_adapter_properties(void)
 {
     /* sanity check */
@@ -267,6 +275,9 @@
 
 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 ad5b607..bae39d2 100644
--- a/btif/src/btif_config.c
+++ b/btif/src/btif_config.c
@@ -27,6 +27,7 @@
 #include "osi/include/alarm.h"
 #include "osi/include/allocator.h"
 #include "btcore/include/bdaddr.h"
+#include "btif_api.h"
 #include "btif_config.h"
 #include "btif_config_transcode.h"
 #include "btif_util.h"
@@ -45,6 +46,7 @@
 static void timer_config_save_cb(void *data);
 static void btif_config_write(void);
 static void btif_config_remove_unpaired(config_t *config);
+static void btif_config_remove_restricted(config_t *config);
 
 // TODO(zachoverflow): Move these two functions out, because they are too specific for this file
 // {grumpy-cat/no, monty-python/you-make-me-sad}
@@ -111,6 +113,10 @@
 
   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.
@@ -421,3 +427,19 @@
     snode = config_section_next(snode);
   }
 }
+
+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);
+}
diff --git a/btif/src/btif_storage.c b/btif/src/btif_storage.c
index 687af94d9..83a5c2e 100644
--- a/btif/src/btif_storage.c
+++ b/btif/src/btif_storage.c
@@ -806,6 +806,13 @@
     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;
@@ -1660,3 +1667,20 @@
 
 }
 
+/*******************************************************************************
+**
+** 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/test/bluedroidtest/bluedroidtest.c b/test/bluedroidtest/bluedroidtest.c
index ac727d8..022738a 100644
--- a/test/bluedroidtest/bluedroidtest.c
+++ b/test/bluedroidtest/bluedroidtest.c
@@ -560,7 +560,7 @@
         bdt_log("Bluetooth is already enabled");
         return;
     }
-    status = sBtInterface->enable();
+    status = sBtInterface->enable(false);
 
     check_return_status(status);
 }
diff --git a/test/suite/cases/adapter.c b/test/suite/cases/adapter.c
index 280cfc6..4fcf6b9 100644
--- a/test/suite/cases/adapter.c
+++ b/test/suite/cases/adapter.c
@@ -24,7 +24,7 @@
 bool adapter_enable_disable() {
   int error;
 
-  CALL_AND_WAIT(error = bt_interface->enable(), adapter_state_changed);
+  CALL_AND_WAIT(error = bt_interface->enable(false), adapter_state_changed);
   TASSERT(error == BT_STATUS_SUCCESS, "Error enabling Bluetooth: %d", error);
   TASSERT(adapter_get_state() == BT_STATE_ON, "Adapter did not turn on.");
 
diff --git a/test/suite/main.c b/test/suite/main.c
index 24cb862..4f4ad1e 100644
--- a/test/suite/main.c
+++ b/test/suite/main.c
@@ -228,7 +228,7 @@
   for (size_t i = 0; i < test_suite_size; ++i) {
     if (!test_name || !strcmp(test_name, test_suite[i].function_name)) {
       callbacks_init();
-      CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
+      CALL_AND_WAIT(bt_interface->enable(false), adapter_state_changed);
       if (test_suite[i].function()) {
         printf("[%4d] %-64s [%sPASS%s]\n", ++case_num, test_suite[i].function_name, GREEN, DEFAULT);
         ++pass;
diff --git a/tools/bdtool/bdtool.c b/tools/bdtool/bdtool.c
index d0d0cc7..81c05c4 100644
--- a/tools/bdtool/bdtool.c
+++ b/tools/bdtool/bdtool.c
@@ -99,7 +99,7 @@
   }
 
   if (discover) {
-    CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
+    CALL_AND_WAIT(bt_interface->enable(false), adapter_state_changed);
     fprintf(stdout, "BT adapter is up\n");
 
     fprintf(stdout, "Starting to start discovery\n");
@@ -114,7 +114,7 @@
   }
 
   if (discoverable) {
-    CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
+    CALL_AND_WAIT(bt_interface->enable(false), adapter_state_changed);
     fprintf(stdout, "BT adapter is up\n");
 
     bt_property_t *property = property_new_scan_mode(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
@@ -133,7 +133,7 @@
       exit(1);
     }
 
-    CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
+    CALL_AND_WAIT(bt_interface->enable(false), adapter_state_changed);
     fprintf(stdout, "BT adapter is up\n");
 
     int rc = bt_interface->create_bond(&bt_remote_bdaddr, 0 /* UNKNOWN; Currently not documented :( */);
@@ -143,7 +143,7 @@
   }
 
   if (up) {
-    CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
+    CALL_AND_WAIT(bt_interface->enable(false), adapter_state_changed);
     fprintf(stdout, "BT adapter is up\n");
 
     fprintf(stdout, "Waiting for %d seconds\n", timeout_in_sec);
@@ -151,7 +151,7 @@
   }
 
   if (get_name) {
-    CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
+    CALL_AND_WAIT(bt_interface->enable(false), adapter_state_changed);
     fprintf(stdout, "BT adapter is up\n");
     int error;
     CALL_AND_WAIT(error = bt_interface->get_adapter_property(BT_PROPERTY_BDNAME), adapter_properties);
@@ -168,7 +168,7 @@
   }
 
   if (set_name) {
-    CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
+    CALL_AND_WAIT(bt_interface->enable(false), adapter_state_changed);
     fprintf(stdout, "BT adapter is up\n");
 
     bt_property_t *property = property_new_name(bd_name);
@@ -189,7 +189,7 @@
   }
 
   if (sco_listen) {
-    CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
+    CALL_AND_WAIT(bt_interface->enable(false), adapter_state_changed);
     fprintf(stdout, "BT adapter is up\n");
 
     bt_property_t *property = property_new_scan_mode(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
@@ -221,7 +221,7 @@
       exit(1);
     }
 
-    CALL_AND_WAIT(bt_interface->enable(), adapter_state_changed);
+    CALL_AND_WAIT(bt_interface->enable(false), adapter_state_changed);
     fprintf(stdout, "BT adapter is up\n");
 
     const btsock_interface_t *sock = bt_interface->get_profile_interface(BT_PROFILE_SOCKETS_ID);