A17 国内(cn) vs 国外(global) 蓝牙差异分析(底层视角)

面向:底层蓝牙适配工程师 + Settings 开发 分支dev_a17_0610,对比两个编译变体 xcd_cn_a17(国内)vs xcd_global_a17(国外) 产出:2026-07-24 | 方法 = flavor 源集对比 + 运行时判断 grep(非跨分支 diff) 配套:跨分支差异见 适配视角-dev-vs-a17蓝牙差异详解dev-vs-dev_a17_0610蓝牙差异报告


0. 结论先行(TL;DR)

A17 蓝牙国内外是同一套代码和同一套逻辑。 两个变体的蓝牙核心代码逐字节相同(共享 micarConnectionSettingsmain + f3dif 源集),差异极小,且全部性质是”海外合规补充”,不是功能分叉

蓝牙相关差异性质
APP 层global 多 1 个 BluetoothRequestPermissionActivity(AOSP 原生,为 Google GTS 认证海外合规
APP 层蓝牙 manifest 组件 / 权限 / 代码 / res / 运行时逻辑零差异
lib 层settingslib 蓝牙部分(f3dif 共享,src/global 无蓝牙文件)零差异

一句话:开发蓝牙功能时,cn/global 改一处两版本同步生效,无需为海外单独适配蓝牙逻辑;唯一要注意的是 BluetoothRequestPermissionActivity 只在 global 编译。


1. 怎么界定”差异”(方法论)

cn/global 是同一分支的两个 productFlavor,差异来自编译期选哪些源集(不是 git diff)。三处差异来源:

差异源cnglobal
app/.../src/region/region/cn/res(仅 1 个顶层菜单 xml)region/global/{java,res,AndroidManifest.xml}(location/privacy,无蓝牙
globalOnly 模块不依赖依赖xcd_global_a17Implementation project(":settingsPage:globalOnly")
src/global/ 源集不含settingslib 与 micarConnectionSettings 均声明含,但实际为空

关键查证手段(都做了实证):

  1. 编译期源集:git ls-tree -r dev_a17_0610 -- <src/global 路径> → 看有无蓝牙文件
  2. 运行时判断:git grep isGlobal/isCn/region → 看代码有无动态开关
  3. 包名预装:互联能力靠运行时查包,代码层不分 cn/global

第一部分:APP 层差异

2.1 APP 层差异总览

维度cn (xcd_cn_a17)global (xcd_global_a17)蓝牙相关?
蓝牙核心代码main + f3difmain + f3dif(+ 空的 src/global同一套,零差异
BluetoothRequestPermissionActivity❌ 无✅ 有(globalOnly 模块)是(唯一差异)
蓝牙 manifest 权限/组件共享 micarConnectionSettings/src/main/AndroidManifest.xml同左零差异
蓝牙/连接代码运行时 region 判断零差异
互联能力(CarPlay/CarLink 等)运行时查包名运行时查包名代码一致,差异在镜像预装
蓝牙 res/stringregion/cnsrc/global 均无蓝牙资源同左零差异
顶层菜单连接/蓝牙入口一致一致零差异

2.2 蓝牙代码:cn/global 完全同一套(实证)

蓝牙核心模块 settingsPage/micarConnectionSettings/ 的 flavor 源集绑定(build.gradle):

xcd_cn_a17:     java.srcDirs = ['src/main/java', 'src/f3dif/java']
xcd_global_a17: java.srcDirs = ['src/main/java', 'src/f3dif/java', 'src/global/java']
  • 两个 flavor 都包含 main + f3dif —— 蓝牙 14 个核心文件 + settingslib 蓝牙栈 cn/global 完全相同
  • global 多出的 src/global/javagit ls-tree 实测目录为空(0 文件)。
  • micarConnectionSettings/src/main/AndroidManifest.xml:两 flavor 的 manifest.srcFile 都指向它 → 蓝牙 manifest 组件零差异。

蓝牙核心逻辑、扫描/配对/连接状态机、UI Controller,cn/global 一套代码,不存在任何分支。

2.3 唯一蓝牙差异:BluetoothRequestPermissionActivity(global 独有)

文件settingsPage/globalOnly/src/main/java/com/android/car/settings/bluetooth/BluetoothRequestPermissionActivity.java 模块globalOnly(namespace com.android.car.settings.global,仅被 xcd_global_a17 依赖) 来源:AOSP 原生(版权 2019 The Android Open Source Project) 用途:处理系统标准蓝牙权限请求 intent

manifest 声明globalOnly/src/main/AndroidManifest.xml,注释明写用途):

<!--for google GTS-->
<activity android:name="com.android.car.settings.bluetooth.BluetoothRequestPermissionActivity"
    android:exported="true" android:launchMode="singleInstance">
    <intent-filter>
        <action android:name="android.bluetooth.adapter.action.REQUEST_DISCOVERABLE" />
        <action android:name="android.bluetooth.adapter.action.REQUEST_ENABLE" />
        <action android:name="android.bluetooth.adapter.action.REQUEST_DISABLE" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

关键代码(请求类型 + 状态机):

static final int REQUEST_ENABLE = 1;
static final int REQUEST_DISABLE = 2;
static final int REQUEST_ENABLE_DISCOVERABLE = 3;
static final int DISCOVERABLE_TIMEOUT_TWO_MINUTES = 120;
static final int DISCOVERABLE_TIMEOUT_ONE_HOUR = 3600;
 
// 用 settingslib 的 LocalBluetoothManager(注意:是 settingslib 包装类,非标准 BluetoothAdapter)
mLocalBluetoothManager = LocalBluetoothManager.getInstance(getApplicationContext(), null);
mLocalBluetoothAdapter = mLocalBluetoothManager.getBluetoothAdapter();
int btState = mLocalBluetoothAdapter.getState();
switch (mRequest) {
    case REQUEST_ENABLE:    // 弹"是否开启蓝牙"确认框 → 开启
    case REQUEST_DISABLE:   // 弹"是否关闭蓝牙"确认框 → 关闭
    case REQUEST_ENABLE_DISCOVERABLE:  // 设为可发现 N 秒(默认 120s,最大 1h)
}

为什么 global 才有

  • 海外版必须通过 Google GTS(Google Test Suite)认证,GTS 会发 android.bluetooth.adapter.action.REQUEST_ENABLE/REQUEST_DISCOVERABLE 等标准 intent,要求有 Activity 响应并征求用户同意
  • 国内版不走 Google 认证,蓝牙开关用 Settings 自有 UI(BluetoothMainEntrySettingsFragment),不响应这些标准 intent。
  • cn 编译产物实测不含此类app/src/main + micarConnectionSettings grep BluetoothRequestPermission = 空)。

对蓝牙同事的影响

  • 改此类只影响海外,不影响国内蓝牙功能。
  • 此类用 LocalBluetoothAdapter(settingslib 包装,getState()),与 a17 核心蓝牙模块用的标准 BluetoothAdapter(见 适配视角-dev-vs-a17蓝牙差异详解 第 1 节)API 风格不同——它是 AOSP 原样搬来的,没跟着核心模块一起升级到标准 API。
  • 若 GTS 测试报蓝牙权限请求相关问题,只排查 global 编译的这个 Activity。

2.4 蓝牙 manifest 组件:cn/global 零差异

micarConnectionSettings/src/main/AndroidManifest.xml(两 flavor 共享),蓝牙相关组件清单一致:

组件/权限说明
BLUETOOTH / BLUETOOTH_ADMIN / BLUETOOTH_PRIVILEGED / BLUETOOTH_CONNECT蓝牙权限,两 flavor 都有
BluetoothSettingsActivity蓝牙设置主页(响应 android.settings.BLUETOOTH_SETTINGS
MiBluetoothPairingDialogActivity配对对话框
MiCarplayConnectTypeChooseDialogActivityCarPlay 连接类型选择(注释「CarPlay蓝牙连接选择弹窗」)
MiBluetoothPickerDialogActivity蓝牙设备选择器(响应 com.android.micar.settings.BLUETOOTH_DEVICE_PICKER
MiBluetoothPairingRequest配对请求(响应 android.bluetooth.device.action.PAIRING_REQUEST
BluetoothDeviceService蓝牙设备服务

→ 国内外蓝牙 UI 入口、权限、后台组件完全相同。CarPlay 相关组件国内也存在(是否可用取决于包预装,见 2.5)。

2.5 互联能力:运行时包名判断(代码层不分 cn/global)

手车互联(CarPlay/CarLink/AndroidAuto/小米设备互联)能力判断在 ConnectionUtils.kt靠运行时查包是否预装,代码 cn/global 完全一致:

// ConnectionUtils.kt(f3dif,cn/global 共享)
isMiuiShareSupported()  → PackageUtils.isPkgInstalled("com.xiaomi.mitv.smartshare")
isCarPlaySupported()    → isPkgInstalled("com.mi.car.carplay") || isPkgInstalled("com.desaysv.carplay")
isCarLinkSupported()    → isPkgInstalled("com.mi.car.carlink")
isAndroidAutoSupported()→ isPkgInstalled("com.mi.car.androidauto")

国内外互联能力差异由系统镜像预装哪些包决定(国外镜像装 CarPlay/AndroidAuto,国内装 CarLink/MiuiShare),不在 Settings 代码里。要改国内外互联支持,改镜像预装包,而非改 Settings。

注:ConnectionUtils 全文 grep isGlobal/isCn/region = 空,证实无运行时 region 开关

2.6 非蓝牙的 app 层差异(避免混淆,顺带说明)

这些差异与蓝牙无关,列出来防止蓝牙同事误判:

差异cnglobal性质
双层氛围灯同步有(ATMOSPHERE_LIGHT_SYNCHRONIZE 权限 + Receiver)国内特色
强制发电弹窗有(EnergyModeForceChargeDialogActivity国内特色
辅助驾驶 FragmentAutopilotSettingsFragmentGlobalAutopilotSettingsFragment国内外方案不同
location/privacy 入口有(LocationSettingsFragment/PrivacySettingsFragment 等)海外隐私合规
Activity themeDarkFullscreenThemeDarkFullscreenThemeKeepStatusBartools:replace海外保留状态栏
app 主 manifest 文件src/main/AndroidManifest.xmlsrc/region/global/AndroidManifest.xml(独立)

第二部分:lib 层差异

3.1 settingslib flavor 绑定

base/settingsLibAndroid/build.gradle

xcd_cn_a17:     java.srcDirs = ['src/main/java', 'src/f3dif/java']
xcd_global_a17: java.srcDirs = ['src/main/java', 'src/f3dif/java', 'src/global/java']

3.2 src/global 蓝牙文件:零(6 个 lib 实证)

git ls-tree -r dev_a17_0610 -- base/<lib>/src/global 对全部 base 库统计蓝牙文件:

src/global 蓝牙文件数
settingsLibAndroid0
WifiTrackerLib0
settingsLibUtils0
settingsLibTile0
settingsLibAdaptiveIcon0
settingsLibDisplayUtils0

micarConnectionSettings/src/global 同样为空目录。

3.3 结论:lib 层蓝牙 cn/global 零差异

  • 蓝牙 profile 栈、事件总线、LocalBluetoothAdapter/CachedBluetoothDevice 等 settingslib 蓝牙类,cn/global 共享 f3dif 同一份。
  • global 的 src/global 源集里没有任何蓝牙文件(可能有 location/privacy 等非蓝牙内容)。
  • 底层蓝牙库,国内外零差异。

4. 对蓝牙/Settings 同事的评估要点

开发影响清单

场景cn/global 是否需分别处理说明
改蓝牙扫描/配对/连接逻辑❌ 不需要一套代码,改 main/f3dif 两版本同步
改蓝牙 UI(列表/详情/配对弹窗)❌ 不需要同上
改蓝牙 manifest 权限/组件❌ 不需要共享 micarConnectionSettings/src/main/AndroidManifest.xml
改互联能力(CarPlay 等)开关❌ 不需要(改代码无效)改系统镜像预装包
改 GTS 蓝牙权限请求流程✅ 只影响 globalBluetoothRequestPermissionActivity(globalOnly 模块)
加新的海外专属蓝牙功能✅ global 独占globalOnly 模块或 src/global

关键提醒

  1. BluetoothRequestPermissionActivity 是 global 唯一蓝牙独占代码,用 settingslib 的 LocalBluetoothAdapter(AOSP 原样,未跟随核心模块升级到标准 API)。若做 API 统一,此类是 global 侧的历史遗留点。
  2. 国内外蓝牙功能/逻辑/字段/UI 完全一致,差异仅”海外多了个 GTS Activity”。评估蓝牙功能开发工作量时,不需要乘以 2
  3. 互联能力差异不在代码层,别在 Settings 里找 CarPlay 国内/国外分支(没有)。

附录:复验命令

# micarConnectionSettings flavor 源集(确认 cn/global 共享 main+f3dif)
git show dev_a17_0610:settingsPage/micarConnectionSettings/build.gradle | sed -n '75,85p'
 
# global 独有蓝牙 Activity
git show dev_a17_0610:settingsPage/globalOnly/src/main/java/com/android/car/settings/bluetooth/BluetoothRequestPermissionActivity.java
 
# lib 层 src/global 蓝牙文件数(应为 0)
git ls-tree -r dev_a17_0610 -- base/settingsLibAndroid/src/global | grep -ic bluetooth
 
# 运行时 region 判断(应为空)
git grep -niE "isGlobal|isCn|region" dev_a17_0610 -- 'settingsPage/micarConnectionSettings/src/main/java/com/android/car/settings/miauto/bluetooth/**'