Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d1bfc53d authored by Zhengping Jiang's avatar Zhengping Jiang
Browse files

floss: prevent device lost when toggle ll privacy

Control ll privacy and own address type with two sysprops. Do the best
effort to keep ll privacy and address policy consistent.

When setting ll privacy and address privacy, read devices in storage.
Only change address policy if there is no LE device connected. This is
to avoid losing previously paired device.

When switching accounts, it is possible to have ll privacy enabled with
own address type public, or ll privacy disabled with own address type
random.

Bug: 319713370
Bug: 338134627
Test: mma -j32
Test: pair le hid and toggle ll privacy in chrome://flags
Test: nearby share
Flag: floss_separate_host_privacy_and_llprivacy
Change-Id: I163ca07363376fbd265312eaa1903a7ff12b1888
parent bb44623e
Loading
Loading
Loading
Loading
+76 −6
Original line number Diff line number Diff line
@@ -4,6 +4,9 @@ use std::collections::HashMap;
use std::process::Command;
use std::sync::{Arc, Mutex};

use configparser::ini::Ini;
use glob::glob;

use crate::powerd_suspend_manager::SuspendManagerContext;

use crate::iface_bluetooth_experimental::IBluetoothExperimental;
@@ -215,6 +218,56 @@ impl IBluetoothManager for BluetoothManager {
    }
}

/// Helper function that check if there is at least one LE device in Floss config file.
fn config_with_le_device_entry(filename: &str) -> bool {
    let mut floss_conf = Ini::new_cs();
    let floss_map = match floss_conf.load(filename) {
        Ok(map) => map,
        Err(err) => {
            warn!("Error opening ini file while loading Floss devices for {}: {}", filename, err);
            return false;
        }
    };
    for (sec, props) in floss_map {
        // Skip all the non-device sections
        if !sec.contains(":") {
            continue;
        }
        // Invalid entries have no DevType
        if !props.contains_key("DevType") {
            continue;
        }
        for (k, v) in props {
            if k == "DevType" {
                let val = v.unwrap_or_default().to_string();
                // "1" BREDR, "2" LE, "3" DUAL
                if val != "1" {
                    return true;
                }
            }
        }
    }
    return false;
}

/// Check if there are any LE Floss devices in storage.
fn floss_have_le_devices() -> bool {
    let globbed = match glob(migrate::FLOSS_CONF_FILE) {
        Ok(v) => v,
        Err(_) => {
            warn!("Didn't find Floss conf file to search devices");
            return false;
        }
    };

    for entry in globbed {
        if config_with_le_device_entry(entry.unwrap_or_default().to_str().unwrap_or_default()) {
            return true;
        }
    }
    return false;
}

/// Implementation of IBluetoothExperimental
impl IBluetoothExperimental for BluetoothManager {
    fn set_ll_privacy(&mut self, enabled: bool) -> bool {
@@ -223,17 +276,34 @@ impl IBluetoothExperimental for BluetoothManager {
            Ok(true) => true,
            _ => false,
        };
        let current_address_status = match config_util::read_floss_address_privacy_enabled() {
            Ok(true) => true,
            _ => false,
        };

        if current_status == enabled {
            return true;
        }
        let mut need_restart = current_status != enabled;

        if current_status != enabled {
            if let Err(e) = config_util::write_floss_ll_privacy_enabled(enabled) {
                error!("Failed to write ll privacy status: {}", e);
                return false;
            }
        }

        // Make change only when LL privacy status is not consistent with address policy and
        // there is no LE devices in storage.
        if current_address_status != enabled && !floss_have_le_devices() {
            // Keep address policy aligned with LL privacy status.
            if let Err(e) = config_util::write_floss_address_privacy_enabled(enabled) {
                error!("Failed to write address privacy status {}: {}", enabled, e);
            } else {
                need_restart = true;
            }
        }

        if need_restart {
            self.restart_adapters();
        }

        return true;
    }
+30 −0
Original line number Diff line number Diff line
@@ -222,6 +222,36 @@ pub fn write_floss_ll_privacy_enabled(enabled: bool) -> std::io::Result<()> {
    std::fs::write(format!("{}/{}", FLOSS_SYSPROPS_OVERRIDE_DIR, "privacy_override.conf"), data)
}

pub fn read_floss_address_privacy_enabled() -> std::io::Result<bool> {
    let parent = Path::new(FLOSS_SYSPROPS_OVERRIDE_DIR);
    if !parent.is_dir() {
        return Ok(false);
    }

    let data = std::fs::read_to_string(format!(
        "{}/{}",
        FLOSS_SYSPROPS_OVERRIDE_DIR, "privacy_address_override.conf"
    ))?;

    Ok(data == "[Sysprops]\nbluetooth.core.gap.le.privacy.own_address_type.enabled=true\n")
}

pub fn write_floss_address_privacy_enabled(enabled: bool) -> std::io::Result<()> {
    let parent = Path::new(FLOSS_SYSPROPS_OVERRIDE_DIR);

    std::fs::create_dir_all(parent)?;

    let data = format!(
        "[Sysprops]\nbluetooth.core.gap.le.privacy.own_address_type.enabled={}",
        if enabled { "true\n" } else { "false\n" }
    );

    std::fs::write(
        format!("{}/{}", FLOSS_SYSPROPS_OVERRIDE_DIR, "privacy_address_override.conf"),
        data,
    )
}

pub fn set_adapter_coredump_state(enabled: bool) -> std::io::Result<()> {
    let data = format!("{}\n", !enabled as i32);

+1 −1
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ use glob::glob;
use log::{debug, error, info, warn};

const BT_LIBDIR: &str = "/var/lib/bluetooth";
const FLOSS_CONF_FILE: &str = "/var/lib/bluetooth/bt_config.conf";
pub const FLOSS_CONF_FILE: &str = "/var/lib/bluetooth/bt_config.conf";

const ADAPTER_SECTION_NAME: &str = "Adapter";
const GENERAL_SECTION_NAME: &str = "General";
+1 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ void SyspropsModule::parse_config(std::string file_path) {
      "bluetooth.btm.sec.delay_auth_ms.value",
      "bluetooth.device.default_name",
      "bluetooth.core.gap.le.privacy.enabled",
      "bluetooth.core.gap.le.privacy.own_address_type.enabled",
      "bluetooth.core.gap.le.conn.only_init_1m_phy.enabled",
      "bluetooth.device.class_of_device",
      "bluetooth.device_id.product_id",
+18 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#include <android_bluetooth_sysprop.h>
#include <base/location.h>
#include <com_android_bluetooth_flags.h>

#include <cstdint>
#include <future>
@@ -30,6 +31,7 @@
#include "main/shim/helpers.h"
#include "main/shim/stack.h"
#include "osi/include/allocator.h"
#include "osi/include/properties.h"
#include "stack/btm/btm_sec.h"
#include "stack/btm/security_device_record.h"
#include "stack/include/bt_hdr.h"
@@ -37,6 +39,10 @@
#include "stack/include/main_thread.h"
#include "types/ble_address_with_type.h"
#include "types/raw_address.h"
#ifndef PROPERTY_BLE_PRIVACY_OWN_ADDRESS_ENABLED
#define PROPERTY_BLE_PRIVACY_OWN_ADDRESS_ENABLED \
  "bluetooth.core.gap.le.privacy.own_address_type.enabled"
#endif

void bluetooth::shim::ACL_CreateClassicConnection(
    const RawAddress& raw_address) {
@@ -102,6 +108,18 @@ void bluetooth::shim::ACL_ConfigureLePrivacy(bool is_le_privacy_enabled) {
      is_le_privacy_enabled
          ? hci::LeAddressManager::AddressPolicy::USE_RESOLVABLE_ADDRESS
          : hci::LeAddressManager::AddressPolicy::USE_PUBLIC_ADDRESS;
  /* This is a Floss only flag. Android determines address policy according to
   * privacy mode, hence it is not necessary to enable resolvable address with
   * another sysprop */
  if (com::android::bluetooth::flags::
          floss_separate_host_privacy_and_llprivacy()) {
    address_policy = hci::LeAddressManager::AddressPolicy::USE_PUBLIC_ADDRESS;
    if (osi_property_get_bool(PROPERTY_BLE_PRIVACY_OWN_ADDRESS_ENABLED,
                              is_le_privacy_enabled))
      address_policy =
          hci::LeAddressManager::AddressPolicy::USE_RESOLVABLE_ADDRESS;
  }

  hci::AddressWithType empty_address_with_type(
      hci::Address{}, hci::AddressType::RANDOM_DEVICE_ADDRESS);

Loading