1. BluetoothProperties介绍
- libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop
BluetoothProperties.sysprop
是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File) ,用于声明和管理 Bluetooth 模块相关的系统属性(System Properties) 。这些属性以结构化的方式定义,并由 sysprop
编译工具自动生成访问接口,供 Framework、HAL 或其他模块使用。
c
# Copyright (C) 2021 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
module: "android.sysprop.BluetoothProperties"
owner: Platform
prop {
api_name: "snoop_default_mode"
type: Enum
scope: Public
access: ReadWrite
enum_values: "empty|disabled|filtered|full"
prop_name: "persist.bluetooth.btsnoopdefaultmode"
}
prop {
api_name: "snoop_log_mode"
type: Enum
scope: Public
access: ReadWrite
enum_values: "empty|disabled|filtered|full"
prop_name: "persist.bluetooth.btsnooplogmode"
}
prop {
api_name: "factory_reset"
type: Boolean
scope: Public
access: ReadWrite
prop_name: "persist.bluetooth.factoryreset"
}
######## Bluetooth configurations
# Whether GAP BLE Privacy (RPA) is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isGapLePrivacyEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.core.gap.le.privacy.enabled"
}
# The default name of the device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "getDefaultDeviceName"
type: String
scope: Public
access: Readonly
prop_name: "bluetooth.device.default_name"
}
# The default class of device of the device, represented as a list of exactly 3 unsigned integers.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "getClassOfDevice"
type: UIntList
scope: Public
access: Readonly
prop_name: "bluetooth.device.class_of_device"
}
# Bluetooth operating voltage in millivolts available for vendors overlay.
# Used to calculate Bluetooth power consumption for a specific hardware.
prop {
api_name: "getHardwareOperatingVoltageMv"
type: Integer
scope: Public
access: Readonly
prop_name: "bluetooth.hardware.power.operating_voltage_mv"
}
# Bluetooth idle current in milliamps available for vendors overlay.
# Used to calculate Bluetooth power consumption for a specific hardware.
prop {
api_name: "getHardwareIdleCurrentMa"
type: Integer
scope: Public
access: Readonly
prop_name: "bluetooth.hardware.power.idle_cur_ma"
}
# Bluetooth transmit current in milliamps available for vendors overlay.
# Used to calculate Bluetooth power consumption for a specific hardware.
prop {
api_name: "getHardwareTxCurrentMa"
type: Integer
scope: Public
access: Readonly
prop_name: "bluetooth.hardware.power.tx_cur_ma"
}
# Bluetooth receive current in milliamps available for vendors overlay.
# Used to calculate Bluetooth power consumption for a specific hardware.
prop {
api_name: "getHardwareRxCurrentMa"
type: Integer
scope: Public
access: Readonly
prop_name: "bluetooth.hardware.power.rx_cur_ma"
}
# Whether Bluetooth should keep its state after reboot.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isSupportPersistedStateEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.framework.support_persisted_state"
}
# Whether Bluetooth should keep its state after reboot.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isAdapterAddressValidationEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.framework.adapter_address_validation"
}
# Whether the Advanced Audio Distribution Profile (A2DP) Sink role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileA2dpSinkEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.a2dp.sink.enabled"
}
# Whether the Advanced Audio Distribution Profile (A2DP) Source role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileA2dpSourceEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.a2dp.source.enabled"
}
# Whether the Android defined Audio Support for Hearing Aids (ASHA) central role over is enabled on
# this device. Set by vendors overlay, read at Bluetooth initialization.
prop {
api_name: "isProfileAshaCentralEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.asha.central.enabled"
}
# Whether the Audio/Video Remote Control Profile (AVRCP) Controller role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileAvrcpControllerEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.avrcp.controller.enabled"
}
# Whether the Audio/Video Remote Control Profile (AVRCP) Target role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileAvrcpTargetEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.avrcp.target.enabled"
}
# Whether the Basic Audio Profile (BAP) broadcast assist role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileBapBroadcastAssistEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.bap.broadcast.assist.enabled"
}
# Whether the Basic Audio Profile (BAP) broadcast source role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileBapBroadcastSourceEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.bap.broadcast.source.enabled"
}
# Whether the Basic Audio Profile (BAP) unicast client role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileBapUnicastClientEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.bap.unicast.client.enabled"
}
# Whether the Battery Service profile (BAS) client role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileBasClientEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.bas.client.enabled"
}
# Whether the Broadcast Audio Scan Service profile (BASS) client role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileBassClientEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.bass.client.enabled"
}
# Whether the Coordinated Set Indentification Profile (CSIP) set coordinator role is enabled on this
# device. Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileCsipSetCoordinatorEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.csip.set_coordinator.enabled"
}
# Whether the Generic Attribute Profile (GATT) is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileGattEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.gatt.enabled"
}
# Whether the Hearing Aid Profile (HAP) client role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileHapClientEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.hap.client.enabled"
}
# Whether the Hands-Free Profile (HFP) Audio Gateway role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileHfpAgEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.hfp.ag.enabled"
}
# Whether the Hands-Free Profile (HFP) Hands-free role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileHfpHfEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.hfp.hf.enabled"
}
# Whether the Human Interface Device Profile (HID) device role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileHidDeviceEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.hid.device.enabled"
}
# Whether the Human Interface Device Profile (HID) host role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileHidHostEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.hid.host.enabled"
}
# Whether the Message Access Profile (MAP) Client role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileMapClientEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.map.client.enabled"
}
# Whether the Message Access Profile (MAP) Server role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileMapServerEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.map.server.enabled"
}
# Whether the Media Control Profile (MCP) server role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileMcpServerEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.mcp.server.enabled"
}
# Whether the Object Push Profile (OPP) is enabled on this device. The implementation of OPP
# supports both client and server roles. Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileOppEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.opp.enabled"
}
# Whether the Personal Area Networking Profile (PAN) NAP role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfilePanNapEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.pan.nap.enabled"
}
# Whether the Personal Area Networking Profile (PAN) PANU role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfilePanPanuEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.pan.panu.enabled"
}
# Whether the Phonebook Access Profile (PBAP) client role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfilePbapClientEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.pbap.client.enabled"
}
# Whether the Phonebook Access Profile (PBAP) server role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfilePbapServerEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.pbap.server.enabled"
}
# Whether the SIM Access Profile (SAP) server is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileSapServerEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.sap.server.enabled"
}
# Whether the Call Control Profile (CCP) server role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileCcpServerEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.ccp.server.enabled"
}
# Whether the Volume Control Profile (VCP) controller role is enabled on this device.
# Set by vendors overlay, read at Bluetooth initialization
prop {
api_name: "isProfileVcpControllerEnabled"
type: Boolean
scope: Public
access: Readonly
prop_name: "bluetooth.profile.vcp.controller.enabled"
}
1. 编译后的产物
1. java
BluetoothProperties.sysprop
文件在 aosp 中会自动编译生成对应的 *.jar 和 .h
- ./out/soong/.intermediates/system/libsysprop/srcs/PlatformProperties_java_gen/gen/sysprop/system/libsysprop/srcs/android/sysprop/BluetoothProperties.srcjar
- 当前的 jar 中会存在 BluetoothProperties.java 文件
java
// Generated by the sysprop generator. DO NOT EDIT!
package android.sysprop;
import android.os.SystemProperties;
import android.util.Log;
import java.lang.StringBuilder;
import java.util.ArrayList;
import java.util.function.Function;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.StringJoiner;
import java.util.stream.Collectors;
public final class BluetoothProperties {
private BluetoothProperties () {}
private static Boolean tryParseBoolean(String str) {
switch (str.toLowerCase(Locale.US)) {
case "1":
case "true":
return Boolean.TRUE;
case "0":
case "false":
return Boolean.FALSE;
default:
return null;
}
}
private static Integer tryParseInteger(String str) {
try {
return Integer.valueOf(str);
} catch (NumberFormatException e) {
return null;
}
}
private static Integer tryParseUInt(String str) {
try {
return Integer.parseUnsignedInt(str);
} catch (NumberFormatException e) {
return null;
}
}
private static Long tryParseLong(String str) {
try {
return Long.valueOf(str);
} catch (NumberFormatException e) {
return null;
}
}
private static Long tryParseULong(String str) {
try {
return Long.parseUnsignedLong(str);
} catch (NumberFormatException e) {
return null;
}
}
private static Double tryParseDouble(String str) {
try {
return Double.valueOf(str);
} catch (NumberFormatException e) {
return null;
}
}
private static String tryParseString(String str) {
return "".equals(str) ? null : str;
}
private static <T extends Enum<T>> T tryParseEnum(Class<T> enumType, String str) {
try {
return Enum.valueOf(enumType, str.toUpperCase(Locale.US));
} catch (IllegalArgumentException e) {
return null;
}
}
private static <T> List<T> tryParseList(Function<String, T> elementParser, String str) {
if ("".equals(str)) return new ArrayList<>();
List<T> ret = new ArrayList<>();
int p = 0;
for (;;) {
StringBuilder sb = new StringBuilder();
while (p < str.length() && str.charAt(p) != ',') {
if (str.charAt(p) == '\\') ++p;
if (p == str.length()) break;
sb.append(str.charAt(p++));
}
ret.add(elementParser.apply(sb.toString()));
if (p == str.length()) break;
++p;
}
return ret;
}
private static <T extends Enum<T>> List<T> tryParseEnumList(Class<T> enumType, String str) {
if ("".equals(str)) return new ArrayList<>();
List<T> ret = new ArrayList<>();
for (String element : str.split(",")) {
ret.add(tryParseEnum(enumType, element));
}
return ret;
}
private static String escape(String str) {
return str.replaceAll("([\\\\,])", "\\\\$1");
}
private static <T> String formatList(List<T> list) {
StringJoiner joiner = new StringJoiner(",");
for (T element : list) {
joiner.add(element == null ? "" : escape(element.toString()));
}
return joiner.toString();
}
private static String formatUIntList(List<Integer> list) {
StringJoiner joiner = new StringJoiner(",");
for (Integer element : list) {
joiner.add(element == null ? "" : escape(Integer.toUnsignedString(element)));
}
return joiner.toString();
}
private static String formatULongList(List<Long> list) {
StringJoiner joiner = new StringJoiner(",");
for (Long element : list) {
joiner.add(element == null ? "" : escape(Long.toUnsignedString(element)));
}
return joiner.toString();
}
private static <T extends Enum<T>> String formatEnumList(List<T> list, Function<T, String> elementFormatter) {
StringJoiner joiner = new StringJoiner(",");
for (T element : list) {
joiner.add(element == null ? "" : elementFormatter.apply(element));
}
return joiner.toString();
}
public static enum snoop_default_mode_values {
EMPTY("empty"),
DISABLED("disabled"),
FILTERED("filtered"),
FULL("full");
private final String propValue;
private snoop_default_mode_values(String propValue) {
this.propValue = propValue;
}
public String getPropValue() {
return propValue;
}
}
public static Optional<snoop_default_mode_values> snoop_default_mode() {
String value = SystemProperties.get("persist.bluetooth.btsnoopdefaultmode");
return Optional.ofNullable(tryParseEnum(snoop_default_mode_values.class, value));
}
public static void snoop_default_mode(snoop_default_mode_values value) {
SystemProperties.set("persist.bluetooth.btsnoopdefaultmode", value == null ? "" : value.getPropValue());
}
public static enum snoop_log_mode_values {
EMPTY("empty"),
DISABLED("disabled"),
FILTERED("filtered"),
FULL("full");
private final String propValue;
private snoop_log_mode_values(String propValue) {
this.propValue = propValue;
}
public String getPropValue() {
return propValue;
}
}
public static Optional<snoop_log_mode_values> snoop_log_mode() {
String value = SystemProperties.get("persist.bluetooth.btsnooplogmode");
return Optional.ofNullable(tryParseEnum(snoop_log_mode_values.class, value));
}
public static void snoop_log_mode(snoop_log_mode_values value) {
SystemProperties.set("persist.bluetooth.btsnooplogmode", value == null ? "" : value.getPropValue());
}
public static Optional<Boolean> factory_reset() {
String value = SystemProperties.get("persist.bluetooth.factoryreset");
return Optional.ofNullable(tryParseBoolean(value));
}
public static void factory_reset(Boolean value) {
SystemProperties.set("persist.bluetooth.factoryreset", value == null ? "" : value.toString());
}
public static Optional<Boolean> isGapLePrivacyEnabled() {
String value = SystemProperties.get("bluetooth.core.gap.le.privacy.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<String> getDefaultDeviceName() {
String value = SystemProperties.get("bluetooth.device.default_name");
return Optional.ofNullable(tryParseString(value));
}
public static List<Integer> getClassOfDevice() {
String value = SystemProperties.get("bluetooth.device.class_of_device");
return tryParseList(v -> tryParseUInt(v), value);
}
public static Optional<Integer> getHardwareOperatingVoltageMv() {
String value = SystemProperties.get("bluetooth.hardware.power.operating_voltage_mv");
return Optional.ofNullable(tryParseInteger(value));
}
public static Optional<Integer> getHardwareIdleCurrentMa() {
String value = SystemProperties.get("bluetooth.hardware.power.idle_cur_ma");
return Optional.ofNullable(tryParseInteger(value));
}
public static Optional<Integer> getHardwareTxCurrentMa() {
String value = SystemProperties.get("bluetooth.hardware.power.tx_cur_ma");
return Optional.ofNullable(tryParseInteger(value));
}
public static Optional<Integer> getHardwareRxCurrentMa() {
String value = SystemProperties.get("bluetooth.hardware.power.rx_cur_ma");
return Optional.ofNullable(tryParseInteger(value));
}
public static Optional<Boolean> isSupportPersistedStateEnabled() {
String value = SystemProperties.get("bluetooth.framework.support_persisted_state");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isAdapterAddressValidationEnabled() {
String value = SystemProperties.get("bluetooth.framework.adapter_address_validation");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileA2dpSinkEnabled() {
String value = SystemProperties.get("bluetooth.profile.a2dp.sink.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileA2dpSourceEnabled() {
String value = SystemProperties.get("bluetooth.profile.a2dp.source.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileAshaCentralEnabled() {
String value = SystemProperties.get("bluetooth.profile.asha.central.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileAvrcpControllerEnabled() {
String value = SystemProperties.get("bluetooth.profile.avrcp.controller.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileAvrcpTargetEnabled() {
String value = SystemProperties.get("bluetooth.profile.avrcp.target.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileBapBroadcastAssistEnabled() {
String value = SystemProperties.get("bluetooth.profile.bap.broadcast.assist.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileBapBroadcastSourceEnabled() {
String value = SystemProperties.get("bluetooth.profile.bap.broadcast.source.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileBapUnicastClientEnabled() {
String value = SystemProperties.get("bluetooth.profile.bap.unicast.client.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileBasClientEnabled() {
String value = SystemProperties.get("bluetooth.profile.bas.client.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileBassClientEnabled() {
String value = SystemProperties.get("bluetooth.profile.bass.client.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileCsipSetCoordinatorEnabled() {
String value = SystemProperties.get("bluetooth.profile.csip.set_coordinator.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileGattEnabled() {
String value = SystemProperties.get("bluetooth.profile.gatt.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileHapClientEnabled() {
String value = SystemProperties.get("bluetooth.profile.hap.client.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileHfpAgEnabled() {
String value = SystemProperties.get("bluetooth.profile.hfp.ag.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileHfpHfEnabled() {
String value = SystemProperties.get("bluetooth.profile.hfp.hf.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileHidDeviceEnabled() {
String value = SystemProperties.get("bluetooth.profile.hid.device.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileHidHostEnabled() {
String value = SystemProperties.get("bluetooth.profile.hid.host.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileMapClientEnabled() {
String value = SystemProperties.get("bluetooth.profile.map.client.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileMapServerEnabled() {
String value = SystemProperties.get("bluetooth.profile.map.server.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileMcpServerEnabled() {
String value = SystemProperties.get("bluetooth.profile.mcp.server.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileOppEnabled() {
String value = SystemProperties.get("bluetooth.profile.opp.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfilePanNapEnabled() {
String value = SystemProperties.get("bluetooth.profile.pan.nap.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfilePanPanuEnabled() {
String value = SystemProperties.get("bluetooth.profile.pan.panu.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfilePbapClientEnabled() {
String value = SystemProperties.get("bluetooth.profile.pbap.client.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfilePbapServerEnabled() {
String value = SystemProperties.get("bluetooth.profile.pbap.server.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileSapServerEnabled() {
String value = SystemProperties.get("bluetooth.profile.sap.server.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileCcpServerEnabled() {
String value = SystemProperties.get("bluetooth.profile.ccp.server.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
public static Optional<Boolean> isProfileVcpControllerEnabled() {
String value = SystemProperties.get("bluetooth.profile.vcp.controller.enabled");
return Optional.ofNullable(tryParseBoolean(value));
}
}
如何使用:
c
// android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java
import android.sysprop.BluetoothProperties;
public static boolean isEnabled() {
return BluetoothProperties.isProfileAvrcpTargetEnabled().orElse(false);
}
2. native 层
aosp 编译系统会帮我们自动生成:
- ./out/soong/.intermediates/system/libsysprop/srcs/libPlatformProperties/android_arm64_armv8-a-branchprot_static_hwasan/gen/sysprop/android/sysprop/BluetoothProperties.sysprop.cpp
- ./out/soong/.intermediates/system/libsysprop/srcs/libPlatformProperties/android_arm64_armv8-a-branchprot_static_hwasan/gen/sysprop/public/include/android/sysprop/BluetoothProperties.sysprop.h
c
// Generated by the sysprop generator. DO NOT EDIT!
#include <android/sysprop/BluetoothProperties.sysprop.h>
#include <cctype>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <limits>
#include <utility>
#include <strings.h>
#ifdef __BIONIC__
#include <sys/system_properties.h>
[[maybe_unused]] static bool SetProp(const char* key, const char* value) {
return __system_property_set(key, value) == 0;
}
#else
#include <android-base/properties.h>
[[maybe_unused]] static bool SetProp(const char* key, const char* value) {
android::base::SetProperty(key, value);
return true;
}
#endif
#include <android-base/parseint.h>
#include <log/log.h>
namespace {
using namespace android::sysprop::BluetoothProperties;
template <typename T> T DoParse(const char* str);
constexpr const std::pair<const char*, snoop_default_mode_values> snoop_default_mode_list[] = {
{"empty", snoop_default_mode_values::EMPTY},
{"disabled", snoop_default_mode_values::DISABLED},
{"filtered", snoop_default_mode_values::FILTERED},
{"full", snoop_default_mode_values::FULL},
};
template <>
std::optional<snoop_default_mode_values> DoParse(const char* str) {
for (auto [name, val] : snoop_default_mode_list) {
if (strcmp(str, name) == 0) {
return val;
}
}
return std::nullopt;
}
std::string FormatValue(std::optional<snoop_default_mode_values> value) {
if (!value) return "";
for (auto [name, val] : snoop_default_mode_list) {
if (val == *value) {
return name;
}
}
LOG_ALWAYS_FATAL("Invalid value %d for property persist.bluetooth.btsnoopdefaultmode", static_cast<std::int32_t>(*value));
__builtin_unreachable();
}
constexpr const std::pair<const char*, snoop_log_mode_values> snoop_log_mode_list[] = {
{"empty", snoop_log_mode_values::EMPTY},
{"disabled", snoop_log_mode_values::DISABLED},
{"filtered", snoop_log_mode_values::FILTERED},
{"full", snoop_log_mode_values::FULL},
};
template <>
std::optional<snoop_log_mode_values> DoParse(const char* str) {
for (auto [name, val] : snoop_log_mode_list) {
if (strcmp(str, name) == 0) {
return val;
}
}
return std::nullopt;
}
std::string FormatValue(std::optional<snoop_log_mode_values> value) {
if (!value) return "";
for (auto [name, val] : snoop_log_mode_list) {
if (val == *value) {
return name;
}
}
LOG_ALWAYS_FATAL("Invalid value %d for property persist.bluetooth.btsnooplogmode", static_cast<std::int32_t>(*value));
__builtin_unreachable();
}
template <typename T> constexpr bool is_vector = false;
template <typename T> constexpr bool is_vector<std::vector<T>> = true;
template <> [[maybe_unused]] std::optional<bool> DoParse(const char* str) {
static constexpr const char* kYes[] = {"1", "true"};
static constexpr const char* kNo[] = {"0", "false"};
for (const char* yes : kYes) {
if (strcasecmp(yes, str) == 0) return std::make_optional(true);
}
for (const char* no : kNo) {
if (strcasecmp(no, str) == 0) return std::make_optional(false);
}
return std::nullopt;
}
template <> [[maybe_unused]] std::optional<std::int32_t> DoParse(const char* str) {
std::int32_t ret;
return android::base::ParseInt(str, &ret) ? std::make_optional(ret) : std::nullopt;
}
template <> [[maybe_unused]] std::optional<std::uint32_t> DoParse(const char* str) {
std::uint32_t ret;
return android::base::ParseUint(str, &ret) ? std::make_optional(ret) : std::nullopt;
}
template <> [[maybe_unused]] std::optional<std::int64_t> DoParse(const char* str) {
std::int64_t ret;
return android::base::ParseInt(str, &ret) ? std::make_optional(ret) : std::nullopt;
}
template <> [[maybe_unused]] std::optional<std::uint64_t> DoParse(const char* str) {
std::uint64_t ret;
return android::base::ParseUint(str, &ret) ? std::make_optional(ret) : std::nullopt;
}
template <> [[maybe_unused]] std::optional<double> DoParse(const char* str) {
int old_errno = errno;
errno = 0;
char* end;
double ret = std::strtod(str, &end);
if (errno != 0) {
return std::nullopt;
}
if (str == end || *end != '\0') {
errno = EINVAL;
return std::nullopt;
}
errno = old_errno;
return std::make_optional(ret);
}
template <> [[maybe_unused]] std::optional<std::string> DoParse(const char* str) {
return *str == '\0' ? std::nullopt : std::make_optional(str);
}
template <typename Vec> [[maybe_unused]] Vec DoParseList(const char* str) {
Vec ret;
if (*str == '\0') return ret;
const char* p = str;
for (;;) {
const char* r = p;
std::string value;
while (*r != ',') {
if (*r == '\\') ++r;
if (*r == '\0') break;
value += *r++;
}
ret.emplace_back(DoParse<typename Vec::value_type>(value.c_str()));
if (*r == '\0') break;
p = r + 1;
}
return ret;
}
template <typename T> inline T TryParse(const char* str) {
if constexpr(is_vector<T>) {
return DoParseList<T>(str);
} else {
return DoParse<T>(str);
}
}
[[maybe_unused]] std::string FormatValue(const std::optional<std::int32_t>& value) {
return value ? std::to_string(*value) : "";
}
[[maybe_unused]] std::string FormatValue(const std::optional<std::uint32_t>& value) {
return value ? std::to_string(*value) : "";
}
[[maybe_unused]] std::string FormatValue(const std::optional<std::int64_t>& value) {
return value ? std::to_string(*value) : "";
}
[[maybe_unused]] std::string FormatValue(const std::optional<std::uint64_t>& value) {
return value ? std::to_string(*value) : "";
}
[[maybe_unused]] std::string FormatValue(const std::optional<double>& value) {
if (!value) return "";
char buf[1024];
std::sprintf(buf, "%.*g", std::numeric_limits<double>::max_digits10, *value);
return buf;
}
[[maybe_unused]] std::string FormatValue(const std::optional<bool>& value) {
return value ? (*value ? "true" : "false") : "";
}
template <typename T>
[[maybe_unused]] std::string FormatValue(const std::vector<T>& value) {
if (value.empty()) return "";
std::string ret;
bool first = true;
for (auto&& element : value) {
if (!first) ret += ',';
else first = false;
if constexpr(std::is_same_v<T, std::optional<std::string>>) {
if (element) {
for (char c : *element) {
if (c == '\\' || c == ',') ret += '\\';
ret += c;
}
}
} else {
ret += FormatValue(element);
}
}
return ret;
}
template <typename T>
T GetProp(const char* key, const char* legacy = nullptr) {
std::string value;
#ifdef __BIONIC__
auto pi = __system_property_find(key);
if (pi != nullptr) {
__system_property_read_callback(pi, [](void* cookie, const char*, const char* value, std::uint32_t) {
*static_cast<std::string*>(cookie) = value;
}, &value);
}
#else
value = android::base::GetProperty(key, "");
#endif
if (value.empty() && legacy) {
ALOGV("prop %s doesn't exist; fallback to legacy prop %s", key, legacy);
return GetProp<T>(legacy);
}
return TryParse<T>(value.c_str());
}
} // namespace
namespace android::sysprop::BluetoothProperties {
std::optional<snoop_default_mode_values> snoop_default_mode() {
return GetProp<std::optional<snoop_default_mode_values>>("persist.bluetooth.btsnoopdefaultmode");
}
bool snoop_default_mode(const std::optional<snoop_default_mode_values>& value) {
return SetProp("persist.bluetooth.btsnoopdefaultmode", FormatValue(value).c_str());
}
std::optional<snoop_log_mode_values> snoop_log_mode() {
return GetProp<std::optional<snoop_log_mode_values>>("persist.bluetooth.btsnooplogmode");
}
bool snoop_log_mode(const std::optional<snoop_log_mode_values>& value) {
return SetProp("persist.bluetooth.btsnooplogmode", FormatValue(value).c_str());
}
std::optional<bool> factory_reset() {
return GetProp<std::optional<bool>>("persist.bluetooth.factoryreset");
}
bool factory_reset(const std::optional<bool>& value) {
return SetProp("persist.bluetooth.factoryreset", FormatValue(value).c_str());
}
std::optional<bool> isGapLePrivacyEnabled() {
return GetProp<std::optional<bool>>("bluetooth.core.gap.le.privacy.enabled");
}
std::optional<std::string> getDefaultDeviceName() {
return GetProp<std::optional<std::string>>("bluetooth.device.default_name");
}
std::vector<std::optional<std::uint32_t>> getClassOfDevice() {
return GetProp<std::vector<std::optional<std::uint32_t>>>("bluetooth.device.class_of_device");
}
std::optional<std::int32_t> getHardwareOperatingVoltageMv() {
return GetProp<std::optional<std::int32_t>>("bluetooth.hardware.power.operating_voltage_mv");
}
std::optional<std::int32_t> getHardwareIdleCurrentMa() {
return GetProp<std::optional<std::int32_t>>("bluetooth.hardware.power.idle_cur_ma");
}
std::optional<std::int32_t> getHardwareTxCurrentMa() {
return GetProp<std::optional<std::int32_t>>("bluetooth.hardware.power.tx_cur_ma");
}
std::optional<std::int32_t> getHardwareRxCurrentMa() {
return GetProp<std::optional<std::int32_t>>("bluetooth.hardware.power.rx_cur_ma");
}
std::optional<bool> isSupportPersistedStateEnabled() {
return GetProp<std::optional<bool>>("bluetooth.framework.support_persisted_state");
}
std::optional<bool> isAdapterAddressValidationEnabled() {
return GetProp<std::optional<bool>>("bluetooth.framework.adapter_address_validation");
}
std::optional<bool> isProfileA2dpSinkEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.a2dp.sink.enabled");
}
std::optional<bool> isProfileA2dpSourceEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.a2dp.source.enabled");
}
std::optional<bool> isProfileAshaCentralEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.asha.central.enabled");
}
std::optional<bool> isProfileAvrcpControllerEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.avrcp.controller.enabled");
}
std::optional<bool> isProfileAvrcpTargetEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.avrcp.target.enabled");
}
std::optional<bool> isProfileBapBroadcastAssistEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.bap.broadcast.assist.enabled");
}
std::optional<bool> isProfileBapBroadcastSourceEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.bap.broadcast.source.enabled");
}
std::optional<bool> isProfileBapUnicastClientEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.bap.unicast.client.enabled");
}
std::optional<bool> isProfileBasClientEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.bas.client.enabled");
}
std::optional<bool> isProfileBassClientEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.bass.client.enabled");
}
std::optional<bool> isProfileCsipSetCoordinatorEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.csip.set_coordinator.enabled");
}
std::optional<bool> isProfileGattEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.gatt.enabled");
}
std::optional<bool> isProfileHapClientEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.hap.client.enabled");
}
std::optional<bool> isProfileHfpAgEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.hfp.ag.enabled");
}
std::optional<bool> isProfileHfpHfEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.hfp.hf.enabled");
}
std::optional<bool> isProfileHidDeviceEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.hid.device.enabled");
}
std::optional<bool> isProfileHidHostEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.hid.host.enabled");
}
std::optional<bool> isProfileMapClientEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.map.client.enabled");
}
std::optional<bool> isProfileMapServerEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.map.server.enabled");
}
std::optional<bool> isProfileMcpServerEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.mcp.server.enabled");
}
std::optional<bool> isProfileOppEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.opp.enabled");
}
std::optional<bool> isProfilePanNapEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.pan.nap.enabled");
}
std::optional<bool> isProfilePanPanuEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.pan.panu.enabled");
}
std::optional<bool> isProfilePbapClientEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.pbap.client.enabled");
}
std::optional<bool> isProfilePbapServerEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.pbap.server.enabled");
}
std::optional<bool> isProfileSapServerEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.sap.server.enabled");
}
std::optional<bool> isProfileCcpServerEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.ccp.server.enabled");
}
std::optional<bool> isProfileVcpControllerEnabled() {
return GetProp<std::optional<bool>>("bluetooth.profile.vcp.controller.enabled");
}
} // namespace android::sysprop::BluetoothProperties
c
// Generated by the sysprop generator. DO NOT EDIT!
#pragma once
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
namespace android::sysprop::BluetoothProperties {
enum class snoop_default_mode_values {
EMPTY,
DISABLED,
FILTERED,
FULL,
};
std::optional<snoop_default_mode_values> snoop_default_mode();
bool snoop_default_mode(const std::optional<snoop_default_mode_values>& value);
enum class snoop_log_mode_values {
EMPTY,
DISABLED,
FILTERED,
FULL,
};
std::optional<snoop_log_mode_values> snoop_log_mode();
bool snoop_log_mode(const std::optional<snoop_log_mode_values>& value);
std::optional<bool> factory_reset();
bool factory_reset(const std::optional<bool>& value);
std::optional<bool> isGapLePrivacyEnabled();
std::optional<std::string> getDefaultDeviceName();
std::vector<std::optional<std::uint32_t>> getClassOfDevice();
std::optional<std::int32_t> getHardwareOperatingVoltageMv();
std::optional<std::int32_t> getHardwareIdleCurrentMa();
std::optional<std::int32_t> getHardwareTxCurrentMa();
std::optional<std::int32_t> getHardwareRxCurrentMa();
std::optional<bool> isSupportPersistedStateEnabled();
std::optional<bool> isAdapterAddressValidationEnabled();
std::optional<bool> isProfileA2dpSinkEnabled();
std::optional<bool> isProfileA2dpSourceEnabled();
std::optional<bool> isProfileAshaCentralEnabled();
std::optional<bool> isProfileAvrcpControllerEnabled();
std::optional<bool> isProfileAvrcpTargetEnabled();
std::optional<bool> isProfileBapBroadcastAssistEnabled();
std::optional<bool> isProfileBapBroadcastSourceEnabled();
std::optional<bool> isProfileBapUnicastClientEnabled();
std::optional<bool> isProfileBasClientEnabled();
std::optional<bool> isProfileBassClientEnabled();
std::optional<bool> isProfileCsipSetCoordinatorEnabled();
std::optional<bool> isProfileGattEnabled();
std::optional<bool> isProfileHapClientEnabled();
std::optional<bool> isProfileHfpAgEnabled();
std::optional<bool> isProfileHfpHfEnabled();
std::optional<bool> isProfileHidDeviceEnabled();
std::optional<bool> isProfileHidHostEnabled();
std::optional<bool> isProfileMapClientEnabled();
std::optional<bool> isProfileMapServerEnabled();
std::optional<bool> isProfileMcpServerEnabled();
std::optional<bool> isProfileOppEnabled();
std::optional<bool> isProfilePanNapEnabled();
std::optional<bool> isProfilePanPanuEnabled();
std::optional<bool> isProfilePbapClientEnabled();
std::optional<bool> isProfilePbapServerEnabled();
std::optional<bool> isProfileSapServerEnabled();
std::optional<bool> isProfileCcpServerEnabled();
std::optional<bool> isProfileVcpControllerEnabled();
} // namespace android::sysprop::BluetoothProperties
如何使用:
c
// system/btif/src/btif_dm.cc
#include <android/sysprop/BluetoothProperties.sysprop.h>
static const char* btif_get_default_local_name() {
...
std::optional<std::string> default_local_name =
android::sysprop::BluetoothProperties::getDefaultDeviceName();
...
}
3. 各个属性使用场景介绍
列出了每个属性的 api_name
、prop_name
、类型、以及对应的典型使用场景和说明:
属性 API 名称 | 系统属性名 | 类型 | 使用场景描述 |
---|---|---|---|
snoop_default_mode | persist.bluetooth.btsnoopdefaultmode | Enum (empty/disabled/filtered/full) | 控制默认的 BT Snoop 日志记录模式(启动时默认设置)。用于决定是否及何种程度记录 Bluetooth HCI 日志,方便调试或抓包。 |
snoop_log_mode | persist.bluetooth.btsnooplogmode | Enum (empty/disabled/filtered/full) | 实时控制当前的 BT Snoop 日志记录模式。可在运行时开启关闭日志,便于故障调试或日志采集。 |
factory_reset | persist.bluetooth.factoryreset | Boolean | 用于触发 Bluetooth 模块的出厂重置行为。服务启动时检测该标志,进行清除配对记录或状态恢复。 |
isGapLePrivacyEnabled | bluetooth.core.gap.le.privacy.enabled | Boolean | 决定是否在 BLE GAP 中启用隐私功能(RPA),在 Bluetooth 初始化时从 vendor overlay 读取,用于控制设备地址随机与否。 |
getDefaultDeviceName | bluetooth.device.default_name | String | 指定设备默认蓝牙名称(如"Pixel 7")。Bluetooth 初始化时使用,决定配对名称显示。 |
getClassOfDevice | bluetooth.device.class_of_device | UIntList | 指定蓝牙设备类型(如音频、输入设备等),初始化时使用设备类型分类,对其他设备展示能力信息。 |
getHardwareOperatingVoltageMv | bluetooth.hardware.power.operating_voltage_mv | Integer | 指定蓝牙芯片的电压参数,用于功耗计算,如动态电源模型,初始化时读取。 |
getHardwareIdleCurrentMa | bluetooth.hardware.power.idle_cur_ma | Integer | 指定空闲时的电流消耗,用于评估功耗性能指标。 |
getHardwareTxCurrentMa | bluetooth.hardware.power.tx_cur_ma | Integer | 指定发送时的电流消耗,用于功耗模型评估。 |
getHardwareRxCurrentMa | bluetooth.hardware.power.rx_cur_ma | Integer | 指定接收时的电流消耗,用于设备功耗分析。 |
isSupportPersistedStateEnabled | bluetooth.framework.support_persisted_state | Boolean | 控制是否支持在重启后保持蓝牙配对状态、连接状态等。初始化时根据厂商覆盖设置行为。 |
isAdapterAddressValidationEnabled | bluetooth.framework.adapter_address_validation | Boolean | 控制是否校验底层蓝牙地址有效性,初始化时决定是否验证 BLE/MAC 地址合法。 |
---所有 isProfile...Enabled 属性--- |
e.g. bluetooth.profile.a2dp.sink.enabled / .source / .gatt.enabled etc. | Boolean | 每个 Profile(A2DP、HFP、GATT、PBAP、AVRCP、HID、PAN 等)的开关:初始化时根据 overlay 配置决定 Framework 是否启用相应 Profile。用于裁剪系统功能和减小体积。 |
2. 我们该如何默认去配置呢:
上面这些 系统属性都是帮助我们来配置协议栈的, 我们可以在编译时对这些值进行默认的配置。
- 最对应的 device.mk 中配置
shell
# disable avdtp delay report
PRODUCT_PRODUCT_PROPERTIES += \
persist.bluetooth.disabledelayreports=true
# enable dual bluetooth
PRODUCT_PRODUCT_PROPERTIES += \
persist.bluetooth.dual_adapter_mode=false
PRODUCT_PRODUCT_PROPERTIES += \
bluetooth.profile.a2dp.source.enabled=true \
bluetooth.profile.avrcp.target.enabled=true \
bluetooth.profile.map.client.enabled=false \
bluetooth.profile.pan.nap.enabled=false \
bluetooth.profile.pan.panu.enabled=false \
bluetooth.profile.hid.host.enabled=true \
bluetooth.profile.hid.device.enabled=true \
ro.bluetooth.av_role_switch.supported=true
- packages/services/Car/car_product/properties/bluetooth.prop
c
# The default Bluetooth Class of Device
# Service Field: 0x26 -> 38
# - Bit 17: Networking
# - Bit 18: Rendering
# - Bit 21: Audio
# Major Class: 0x04 -> 4 (Audio / Video)
# Minor Class: 0x08 -> 8 (Car Audio)
bluetooth.device.class_of_device=38,4,8
# The Bluetooth profiles that cars expect to have enabled. All other profiles
# are disabled by default.
bluetooth.profile.a2dp.sink.enabled=true
bluetooth.profile.avrcp.controller.enabled=true
bluetooth.profile.gatt.enabled=true
bluetooth.profile.hfp.hf.enabled=true
bluetooth.profile.map.client.enabled=true
bluetooth.profile.pan.nap.enabled=true
bluetooth.profile.pan.panu.enabled=true
bluetooth.profile.pbap.client.enabled=true