【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

news2025/6/12 20:02:48

1. BluetoothProperties介绍

  • libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop

BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相关的系统属性(System Properties)。这些属性以结构化的方式定义,并由 sysprop 编译工具自动生成访问接口,供 Framework、HAL 或其他模块使用。

# 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 文件
// 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));
    }
}

如何使用:
// 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
// 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
// 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

如何使用:
// 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_nameprop_name、类型、以及对应的典型使用场景和说明:

属性 API 名称系统属性名类型使用场景描述
snoop_default_modepersist.bluetooth.btsnoopdefaultmodeEnum (empty/disabled/filtered/full)控制默认的 BT Snoop 日志记录模式(启动时默认设置)。用于决定是否及何种程度记录 Bluetooth HCI 日志,方便调试或抓包。
snoop_log_modepersist.bluetooth.btsnooplogmodeEnum (empty/disabled/filtered/full)实时控制当前的 BT Snoop 日志记录模式。可在运行时开启关闭日志,便于故障调试或日志采集。
factory_resetpersist.bluetooth.factoryresetBoolean用于触发 Bluetooth 模块的出厂重置行为。服务启动时检测该标志,进行清除配对记录或状态恢复。
isGapLePrivacyEnabledbluetooth.core.gap.le.privacy.enabledBoolean决定是否在 BLE GAP 中启用隐私功能(RPA),在 Bluetooth 初始化时从 vendor overlay 读取,用于控制设备地址随机与否。
getDefaultDeviceNamebluetooth.device.default_nameString指定设备默认蓝牙名称(如“Pixel 7”)。Bluetooth 初始化时使用,决定配对名称显示。
getClassOfDevicebluetooth.device.class_of_deviceUIntList指定蓝牙设备类型(如音频、输入设备等),初始化时使用设备类型分类,对其他设备展示能力信息。
getHardwareOperatingVoltageMvbluetooth.hardware.power.operating_voltage_mvInteger指定蓝牙芯片的电压参数,用于功耗计算,如动态电源模型,初始化时读取。
getHardwareIdleCurrentMabluetooth.hardware.power.idle_cur_maInteger指定空闲时的电流消耗,用于评估功耗性能指标。
getHardwareTxCurrentMabluetooth.hardware.power.tx_cur_maInteger指定发送时的电流消耗,用于功耗模型评估。
getHardwareRxCurrentMabluetooth.hardware.power.rx_cur_maInteger指定接收时的电流消耗,用于设备功耗分析。
isSupportPersistedStateEnabledbluetooth.framework.support_persisted_stateBoolean控制是否支持在重启后保持蓝牙配对状态、连接状态等。初始化时根据厂商覆盖设置行为。
isAdapterAddressValidationEnabledbluetooth.framework.adapter_address_validationBoolean控制是否校验底层蓝牙地址有效性,初始化时决定是否验证 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 中配置
# 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
# 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2407644.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…

ServerTrust 并非唯一

NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…