Android14 USB子系统的启动以及动态切换相关的init.usb.rc详解
init.usb.rc的作用是在Android系统启动和运行时,通过监听属性(sys.usb.config和sys.usb.configfs, sys.usb.typec.mode)变化动态,通过写入内核接口 /sys/class/android_usb/ 来配置USB模式。
1 USB子系统的启动
1.1 on init阶段的配置
在on init阶段设置sys.usb.configfs属性,该属性时USB配置方式开关,用来选择使用哪种内核机制来配置USB,0-表示传统模式,1-表示现代configfs模式。
on initsetprop sys.usb.configfs 0
✅ 两种模式对比
特性 | sys.usb.configfs=0 (传统模式) | sys.usb.configfs=1 (现代模式) |
---|---|---|
技术名称 | android_usb / gadgetfs | configfs USB Gadget |
出现时间 | Android 早期 | Android 6.0+ 逐渐引入 |
配置方式 | 写 /sys/class/android_usb/ | 使用 configfs 虚拟文件系统 |
灵活性 | 较低 | 极高(支持复合设备、自定义描述符) |
性能 | 一般 | 更好 |
常见设备 | 老设备、AOSP 默认 | Pixel、三星、华为等新设备 |
✅ 两种属性对比
- sys.usb.configfs是怎么做,即怎么选择哪种方式配置USB。
- sys.usb.config是做什么,即配置成哪种USB模式:mtp,adb,rndis,accessory等。
- 总结
特性 sys.usb.config
sys.usb.configfs
类型 功能列表(字符串) 模式开关(0/1) 作用 “要什么功能” “用什么方式配置” 影响范围 用户可见的 USB 模式 底层实现机制 可变性 频繁变化(用户切换模式) 启动时确定,很少变化 持久化 persist.sys.usb.config
通常硬编码或由内核决定
1.2 on post-fs-data阶段配置
在/data分区挂载后,设置USB功能所需的文件权限和目录结构。防止普通应用随意修改USB行为。
on post-fs-datachown system system /sys/class/android_usb/android0/f_mass_storage/lun/filechmod 0660 /sys/class/android_usb/android0/f_mass_storage/lun/filechown system system /sys/class/android_usb/android0/f_rndis/ethaddrchmod 0660 /sys/class/android_usb/android0/f_rndis/ethaddrmkdir /data/misc/adb 02750 system shellmkdir /data/adb 0700 root root encryption=Require
f_mass_storage/lun/file
:U盘模式下要暴露的镜像文件(通常是/dev/null
或某个映像)f_rndis/ethaddr
:RNDIS 网络共享时的 MAC 地址配置- 创建
/data/misc/adb
:存放 ADB 调试相关密钥(adb_keys
)- 创建
/data/adb
:高权限 ADB 目录(某些定制 ROM 使用)
2. 定义adbd的守护服务
service adbd /system/bin/adbd --root_seclabel=u:r:su:s0class coresocket adbd seqpacket 660 system systemdisabledupdatableseclabel u:r:adbd:s0
adbd服务默认不启动,由init.<platform>.usb.rc中通过start adbd启动。这里以高通平台为例,在init.qcom.usb.rc中会启动该adb的守护进程,eg:
on property:sys.usb.config=diag,diag_mdm,qdss,qdss_mdm,serial_cdev,serial_cdev_mdm,dpl,rmnet,adb && property:sys.usb.configfs=1start adbd
3. 同步厂商的USB属性到系统属性
on property:vendor.sys.usb.adb.disabled=*setprop sys.usb.adb.disabled ${vendor.sys.usb.adb.disabled}
只要
vendor.sys.usb.adb.disabled属性变化,就更新系统属性
sys.usb.adb.disabled的值。其中“*”表示任何值变化都触发。
4. USB配置属性变化时,则修改内核对应的USB配置
init.usb.rc中配置了传统的USB配置,是为了适配老机型。不同的平台或者厂商可以实现configfs架构来动态配置USB,例如高通平台中就是在
init.qcom.usb.rc中配置新的USB属性。
4.1 传统的USB动态配置
sys.usb.config的取值由none(关闭USB), adb(ADB调试模式),accessory(当前设备作为配件,连接主机(例如汽车)),audio_source(当前设备作为音频源输出),以及几种的组合。
当sys.usb.config变化时,同时还要满足property:sys.usb.configfs=0时才会修改内核的USB配置。
例如:
# audio accessory configuration, with adb
on property:sys.usb.config=audio_source,adb && property:sys.usb.configfs=0write /sys/class/android_usb/android0/enable 0write /sys/class/android_usb/android0/idVendor 18d1write /sys/class/android_usb/android0/idProduct 2d03write /sys/class/android_usb/android0/functions ${sys.usb.config}write /sys/class/android_usb/android0/enable 1start adbdsetprop sys.usb.state ${sys.usb.config}
- android_usb是内核包括给用户空间的USB驱动接口,android0表示是该启动的第一个实例,大多设备只有一个USB实例。
- enable 0表示安全关闭当前USB,设置新的配置之前先关闭,然后在修改VID和PID以及功能。
- idVendor表示厂商表示,即Vendo ID,
18d1
是 Google 的官方 VID(十六进制)。- idProduct表示产品型号标识,即Product ID,
2d03
(十六进制)是 AOSP 中“音频源 + ADB”模式的专用 PID。PID取值还有:
PID (hex) 模式 2d00
accessory(配件模式) 2d01
accessory + adb 2d02
audio_source(音频源) 2d03
audio_source + adb ✅ 2d04
accessory + audio_source 2d05
accessory + audio_source + adb - functions决定启用哪些USB功能,取值是${sys.usb.config}
- enable 1表示激活新的USB配置,内核会根据前面设置的
idVendor
、idProduct
、functions
创建一个新的 USB 设备,电脑端会“重新识别设备”(就像拔掉再插上)。
# Used to disable USB when switching states
on property:sys.usb.config=none && property:sys.usb.configfs=0stop adbdwrite /sys/class/android_usb/android0/enable 0write /sys/class/android_usb/android0/bDeviceClass 0setprop sys.usb.state ${sys.usb.config}
✅总结
配置项 | 取值 | 含义 / 用途 | 典型场景 |
---|---|---|---|
sys.usb.configfs | 0 | 使用传统 android_usb 驱动(旧方式) | AOSP、老设备 |
1 | 使用现代 configfs USB Gadget(新方式) | Pixel、三星、华为新机 | |
sys.usb.config | none | 仅充电,无数据功能 | 用户选择“仅充电” |
adb | 仅 ADB 调试 | 开发者模式调试 | |
accessory | Android Open Accessory 模式,当前设备作为配件,连接主机 | 连接 Arduino、汽车主机 | |
audio_source | 音频源输出(手机→外部设备) | 连车载音响播放音乐 | |
accessory, adb | 即支持配件模式,也支持adb | 手机共享网络给电脑 | |
audio_source,adb | 音源输出+adb | 连车载音响播放音乐、设备调试 | |
accessory,audio_source | 即支持Android Open Accessory 模式,当前设备作为配件,连接主机; 也作为音源输出 | 连接汽车主机,并作为音源输出 | |
accessory,audio_source,adb | Accessory + 调试 | 开发调试配件 |
4.2 使用configs动态配置USB
该章节以高通平台为例,请参考下一个。
5 USB Type-c的模式/角色/充电控制
5.1 USB Type-C模式控制
当属性sys.usb.typec.mode发生变化时,则写入内核dual_role_usb接口让内核切换角色。
- dfp(Downstream Facing Port):主机模式(Host),支持OTG(on the go)功能
ufp
(Upstream Facing Port):设备模式(Device)场景 手机角色 对方设备角色 手机连电脑传照片 UFP(设备) 电脑是 DFP(主机) 手机接 OTG + U盘 DFP(主机) U盘是 UFP(设备) 手机给另一台手机充电 DFP(电源/主机) 对方是 UFP(受电/设备 # USB mode changes on property:sys.usb.typec.mode=dfpwrite /sys/class/dual_role_usb/otg_default/mode ${sys.usb.typec.mode}setprop sys.usb.typec.state ${sys.usb.typec.mode}on property:sys.usb.typec.mode=ufpwrite /sys/class/dual_role_usb/otg_default/mode ${sys.usb.typec.mode}setprop sys.usb.typec.state ${sys.usb.typec.mode}
5.2 USB Type-C角色控制
当属性sys.usb.typec.data_role变化时,取值device和host,通过dual_role_usb修改设备的充当的角色,并更新sys.usb.typec.state的属性值。
- 取值device时,告诉内核要作为USB设备,即UFP模式。
- 取值host时,告诉内核要作为USB主机,即DFP模式。
# USB data role changes
on property:sys.usb.typec.data_role=devicewrite /sys/class/dual_role_usb/otg_default/data_role ${sys.usb.typec.data_role}setprop sys.usb.typec.state ${sys.usb.typec.data_role}on property:sys.usb.typec.data_role=hostwrite /sys/class/dual_role_usb/otg_default/data_role ${sys.usb.typec.data_role}setprop sys.usb.typec.state ${sys.usb.typec.data_role}
5.3 TypeC mode和 TypeC role的对比
这两个属性是Android采用“策略与机制分离”的设计原则,role是请求,mode是执行。
概念 | typec.data_role | typec.mode |
---|---|---|
层级 | 系统/策略层 | 硬件/内核层 |
作用 | 表达系统意图(我要当主机) | 直接控制硬件角色(变成主机) |
类比 | “我要加速”,是“请求” | “踩油门”,是“执行” |
是否可被覆盖 | 是(可被电源管理等策略干预) | 否 |
谁设置它 | 系统服务(如 UsbDeviceManager) | int /HAL/ 内核 |
设计目的 | 策略(policy) | 机制(mechanism) |
5.4 USB type-c充电角色控制
当属性sys.usb.typec.power_role变化时,取值source和sink,通过dual_role_usb控制谁给谁充电,实现反向充电和被充电,并更新sys.usb.typec.state的属性值。
- source: 我是电源,可以给其他设备充电
- sink:我是负载,需要被充电
# USB power role changes
on property:sys.usb.typec.power_role=sourcewrite /sys/class/dual_role_usb/otg_default/power_role ${sys.usb.typec.power_role}setprop sys.usb.typec.state ${sys.usb.typec.power_role}on property:sys.usb.typec.power_role=sinkwrite /sys/class/dual_role_usb/otg_default/power_role ${sys.usb.typec.power_role}setprop sys.usb.typec.state ${sys.usb.typec.power_role}
注意:power_role和data_role是相互独立,前者控制电源角色,后者控制数据角色。