十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

UsbDeviceResolver 设备解析器深度解析:Open Headunit 白名单过滤机制全指南

UsbDeviceResolver 设备解析器深度解析:Open Headunit 白名单过滤机制全指南 UsbDeviceResolver 设备解析器深度解析Open Headunit 白名单过滤机制全指南【免费下载链接】open-headunitHeadunit App for displaying Android Auto项目地址: https://gitcode.com/GitHub_Trending/he/open-headunitOpen Headunit是一款将 Android 平板或手机变身 Android Auto 车机头的开源应用。本文带你深入理解其核心的UsbDeviceResolver 设备解析器设计——它如何通过三层过滤器系统描述符白名单 → 设备身份策略 → 用户黑白名单精准识别 USB 设备避免应用被 U 盘、蓝牙适配器、USB 网卡等无关设备误唤醒。即使你是零基础新手也能轻松读懂这套优雅的设备识别架构 一、先搞懂问题为什么需要设备解析器当任何 USB 设备插入车机头时Android 系统会询问用哪个应用处理它。如果 Open Headunit 的声明过于宽泛那么插上 U 盘、蓝牙音频 dongle、USB 网卡都会弹出连接提示——体验灾难。Open Headunit 的解决方案是层层过滤USB 设备插入 │ ▼ ┌─────────────────────────────┐ │ 第1层系统描述符过滤器 │ usb_device_filter.xml在系统弹窗之前运行 └─────────────┬───────────────┘ ▼ ┌─────────────────────────────┐ │ 第2层设备身份策略 │ UsbDeviceIdentityPolicy判断是否像手机 └─────────────┬───────────────┘ ▼ ┌─────────────────────────────┐ │ 第3层用户黑白名单 │ allow-devices / blacklist用户自定义 └─────────────┬───────────────┘ ▼ 启动 AAP 传输连接 Android Auto 二、第一层系统描述符过滤器USB 白名单的入口关卡这一层位于 usb_device_filter.xml它是唯一在系统弹窗之前运行的过滤器。文件中有一段非常精炼的注释道出了设计权衡这里曾经是usb-device /无过滤导致系统为每一个插入的设备都提议 Open Headunit——U 盘和蓝牙 dongle 都会弹窗。当前白名单包含这些条目条目含义0x18D1:0x2D00/0x18D1:0x2D01已处于 accessory 模式的 Google 设备即手机/AA dongle 已切换成功class255 subclass255Vendor class 接口——手机在充电模式、文件传输模式下都长这样class255 subclass66ADB 接口class6PTP照片传输class224RNDIS 网络共享class239IAD 接口关联描述符这里有个经典设计取舍过滤太宽→ OS 启动应用后应用又拒绝它太窄→ 本该接受的手机永远无法自动启动。文件注释明确指出不匹配白名单的设备仍可通过应用内的USB 按钮手动枚举该功能自行扫描整个 USB 总线因此白名单只负责自动启动场景。 三、第二层设备身份策略判断它是不是手机真正核心的逻辑在 UsbDeviceIdentityPolicy.kt。它接受纯描述符数据而非活的UsbDevice对象这样任何一台设备在车上的异常行为都能从日志行复现——这是可测试性的关键设计。3.1 快速排除规则策略按顺序执行尽早剪枝Apple VID0x05AC→ 直接拒绝苹果设备不支持 Android Auto已处于 accessory 模式 → 直接接受Google VID 4 个 accessory PID 之一0x2D00/2D01/2D04/2D05设备类排除集音频(0x01)、打印机(0x07)、大容量存储(0x08)、Hub(0x09)、视频(0x0E)、Billboard(0x11每个 USB-C 扩展坞里都有)3.2 无歧义接口匹配先扫描所有接口命中这些铁证立即接受ADB、RNDIS 网络共享、PTP、IAD、MTP。注意顺序有讲究——RNDIS 必须排在 Vendor class 规则之前因为网络共享模式的手机同时也带着会被 Vendor 规则误判为网卡的 CDC 数据接口。3.3 最棘手的难题FF/FF/00 Vendor Class 接口手机在文件传输模式下的 MTP 接口和USB 网卡的控制接口报告的是完全相同的三元组class0xFF, subclass0xFF, protocol0加同一对 bulk 端点。策略用三个决定性证据区分接口名Android Accessory Interface→ 真 accessoryMTP→ 真手机网卡则叫自己的名字设备类 0xFFAndroid gadget 上报 class 0 并委托给接口而厂商声明整个设备为专有 class——这是网卡独有的特征CDC 兄弟接口带 ECM/NCM/MBIM 控制子类0x06/0x0D/0x0E说明这是网络适配器Verdict { accepted, reason } ← 每次判定都带人类可读的理由每个判定结果Verdict都携带reason字符串例如accepted: ADB或rejected: CDC network adapter直接喂给诊断导出功能——用户报找不到设备时维护者一眼就能区分设备不存在和设备被规则拒绝。⚖️ 四、第三层用户黑白名单白名单过滤的终极裁决通过前两层的设备还要过用户设置这道关。核心决策逻辑在 UsbAttachPolicy.ktfun shouldAttemptAoaSwitch( isGoogleVendor: Boolean, // VID 是 0x18D1Pixel 或 AA dongle autoStartOnUsb: Boolean, // 用户开启了任意 USB 接入即启动 allowListConfigured: Boolean, // 用户标记过至少一个允许的设备 deviceAllowed: Boolean, // 本设备在白名单里 ): Boolean when { isGoogleVendor - true // Google 设备几乎必然是 AA 手机/dongle autoStartOnUsb - true !allowListConfigured - true // 空白名单 从未配置而非禁止一切 else - deviceAllowed }这里藏着一个重要的 bug 修复语义空白名单意味着用户还没配置过而不是什么都被禁止。旧代码只看 vendor id非 Google 设备全部被拒——现在任何 Android 设备都有机会完成 AOA 切换不是 AA 设备的握手会自然失败无副作用。白名单本身存储在 Settings.kt 的allow-devices键中以厂商名 产品名 (VID:xxxx PID:xxxx)格式的 uniqueName 作为条目——同名不同硬件如车机内置多媒体模块 vs 外插手机因此可以区分。黑名单则由 UsbBlacklistPolicy.kt 管理用厂商产品字符串而非 VID:PID 作为键因为**手机切换 USB 模式时 VID:PID 会变字符串不变**——按数字键控的话被拉黑的手机换个模式就大摇大摆溜回来了。 五、设备解析的优先级UsbAttachedActivity 如何选设备当系统把 attach 事件交给 UsbAttachedActivity.kt 时resolveDevice方法为可测试性从 Activity 中抽出的纯函数按如下优先级裁决优先级条件结果1️⃣Intent 携带明确设备FROM_INTENT直接采用2️⃣Intent 无设备但总线上恰好只有 1 台Android 设备FROM_FALLBACK回退到该设备3️⃣多台候选或零候选AMBIGUOUS交给服务层决定不瞎猜这套三态判定被单元测试 UsbDeviceResolverTest.kt 完整覆盖4 个用例分别验证了意图优先、单设备回退、多候选歧义、全空歧义——没有 Android 上下文也能跑测试这正是策略与 UI 分离架构的价值。拒绝路径也值得一提白名单之外的设备不会简单finish()吞掉那是这条 plug-in 路径的终点系统不会再通知任何人而是移交给 AapService继续判断——见 UsbAttachedActivity.kt 的handOffToService()。✅ 六、总结这套设计的可借鉴之处Open Headunit 的 UsbDeviceResolver 体系给出了教科书级的设备识别设计过滤器各司其职XML 白名单管系统弹窗身份策略管是不是手机用户名单管是否允许——三层解耦各自独立演进纯数据驱动的策略对象UsbDeviceIdentityPolicy只吃描述符数据可单测、可复现、可审计判定必带理由Verdict(accepted, reason)让为什么没连接从玄学变成日志里的一行字空配置 ≠ 禁止配置空白名单的语义设计修复了非 Google 手机全被误拒的经典 bug宽进严出系统层宁可多弹一次窗也不放过真正的手动可达设备USB 按钮兜底想深入阅读推荐按此顺序usb_device_filter.xml注释写得极好→ UsbDeviceIdentityPolicy.kt → UsbAttachPolicy.kt → UsbAttachedActivity.kt【免费下载链接】open-headunitHeadunit App for displaying Android Auto项目地址: https://gitcode.com/GitHub_Trending/he/open-headunit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表