接该系列前文,本篇继续围绕高通定制usb架构,针对设备作为usb device模式下的相关逻辑梳理。
本篇先介绍usbgadget hal服务的代码实现,然后逆推native层的usbd,以及fw和settings usb模式切换的完整调用链。
一、USB Gadget HAL
UsbGadget.cpp实现了USB Gadget Hal服务的完整代码,他往往被上层进行调用,上层可以通过它来改变当期设备作为usb device模式下.
端口应该配置成什么?应该支持什么样的功能?是否可以使用adb的功能?是否可以使用diag的功能?或者是否可以进行音视频数据传输?
1、UsbGadget主函数

如上A14和A16的代码对比,可以看出来A16以及使用了AIDL接口,A14还是HIDL接口,其他基本上一致,都是启动一个HAL服务进程,他们的一些差别总结如下:
| 特性 | usb a14 | usb a16 |
|---|---|---|
| HAL 类型 | HIDL (Hardware Interface Definition Language) | AIDL (Android Interface Definition Language) |
| 接口版本 | android.hardware.usb.gadget@1.1 | aidl::android::hardware::usb::gadget |
| LOG_TAG | "android.hardware.usb.gadget@1.1-service-qti" | "android.hardware.usb.gadget-service.qti" |
2、UsbGadget向量表
接下来我们看看UsbGadget的初始化流程:

解析了conf配置表添加到向量表supported_compositions 中,这个很重要后续会使用到,就是https://blog.csdn.net/qq_27672101/article/details/156097668中介绍的usb device支持的模式:

如上配置会添加到向量表**supported_compositions中,**后续上层通过usb.config属性设置gadget模式的时候,就跟根据这个向量表去设置底层驱动VID和PID端口。
3、getCurrentUsbFunctions
UsbGadget对外提供的最核心的接口之一,该接口的作用就是查询当前已设置的 USB 功能状态,返回usb functions。

mCurrentUsbFunctions就是当前usb被启用的功能的掩码,被定义为 uint64_t类型,如下配置:
| 功能 | 枚举值 | 说明 | 示例值(二进制) |
|---|---|---|---|
| NONE | 0x0 | 无功能 | 0000 0000 |
| ADB | 0x1 | Android Debug Bridge | 0000 0001 |
| MTP | 0x2 | Media Transfer Protocol | 0000 0010 |
| PTP | 0x4 | Picture Transfer Protocol | 0000 0100 |
| RNDIS | 0x8 | USB 网络共享 | 0000 1000 |
| MIDI | 0x10 | MIDI 音频 | 0001 0000 |
| ACCESSORY | 0x20 | Android Accessory | 0010 0000 |
| AUDIO_SOURCE | 0x40 | 音频源 | 0100 0000 |
| NCM | 0x80 | Network Control Model | 1000 0000 |
| UVC | 0x100 | USB Video Class | 0001 0000 0000 |
4、AOSP标准功能 VS 高通特有功能
这里系统性的介绍一下usb作为device模式的时候,到底有哪些功能,为什么有的地方使用function来表达,但是又有地方使用字符串来表达。两者傻傻的分不清
1)AOSP标准功能
其实就是如上mCurrentUsbFunctions中定义的子网掩码,包括ADB、MTP等,这些功能都是AOSP原生定义的,即只要是android系统,都必须支持usb的这几种功能。
因此USB Gadget HAL对上层只提供了getCurrentUsbFunctions这样的接口,同样对外也只提供setCurrentUsbFunctions接口,目的就是为了和aosp fw进行匹配。
| functions 枚举 | 配置文件字符串 | 说明 |
|---|---|---|
| GadgetFunction::ADB | "adb" | Android Debug Bridge |
| GadgetFunction::MTP | "mtp" | Media Transfer Protocol |
| GadgetFunction::PTP | "ptp" | Picture Transfer Protocol |
| GadgetFunction::RNDIS | "rndis" | USB 网络共享 |
| GadgetFunction::NCM | "ncm" | Network Control Model |
| GadgetFunction::UVC | "uvc" | USB Video Class |
2)Qualcomm特有功能
这类功能属于高通特有,所以不可能存在于AOSP标准功能中,即不可能存在AOSP定义的GadgetFunction枚举中,那么高通如何兼容这些特有功能呢?高通对xxx.usb.config属性进行了扩展:
aosp标准的GadgetFunction::ADB对应属性值为adb,这个是aosp和高通都支持配置
高通特有的diag功能,就在该属性值上面进行扩展为"diag,adb"或者"diag"的ADB,因为这是高通自己加的,所以GadgetFunction里面是不可能存在的。高通的做法就是在UsbGadget HAL里面进行适配,那么如何适配的,请参考setCurrentUsbFunctions函数。
| 配置文件字符串 | 说明 | 是否在 functions 中 |
|---|---|---|
| "diag" | 诊断接口 | ❌ 不在 |
| "diag_mdm" | 调制解调器诊断 | ❌ 不在 |
| "qdss" | Qualcomm 调试子系统 | ❌ 不在 |
| "rmnet" | 远程网络接口 | ❌ 不在 |
| "serial_cdev" | 串口设备 | ❌ 不在 |
| "dpl" | 数据路径日志 | ❌ 不在 |
| "ccid" | 智能卡接口 | ❌ 不在 |
| "uac2" | USB 音频(Qualcomm 实现) | ❌ 不在 |
| "mass_storage" | U盘模式 | ❌ 不在 |
| "ipcr" | 处理器间通信 | ❌ 不在 |
PS:正式因为高通的这种骚操作,到时aosp usbd的代码无法适配,在高通项目上面出现了一类通用bug,详细参考案例分析。
5、setCurrentUsbFunctions
UsbGadget对外提供的最核心的接口之一,该接口的作用是设置启动usb一个或者多个功能,同上,该函数对外支持的接口也只针对AOSP标准功能,因此该函数参数也是一个uint64_t类型,也是通过mCurrentUsbFunctions变量来存储当前functions。
1)AOSP标准流程
cpp
//la.um/vendor/qcom/opensource/usb/hal/UsbGadget.cpp
//setCurrentUsbFunctions函数用于动态切换Android设备的USB功能模式(如ADB/MTP等)
//functions参数为USB功能模式,只能是AOSP标准功能如ADB MTP等,不可能传递高通特有的diag,serial_cdev等字符串
ScopedAStatus UsbGadget::setCurrentUsbFunctions(int64_t functions, const shared_ptr<IUsbGadgetCallback> &callback, int64_t timeout, int64_t in_transactionId) {
std::unique_lock<std::mutex> lk(mLockSetCurrentFunction);
mCurrentUsbFunctions = functions;
mCurrentUsbFunctionsApplied = false;
//流程1:卸载当前USB功能驱动(如断开ADB/MTP链接)Unlink the gadget and stop the monitor if running.
Status status = tearDownGadget();
if (status != Status::SUCCESS) goto error;
//流程2:等待主机(如PC)检测到USB断开,即延迟等待 Leave the gadget pulled down to give time for the host to sense disconnect.
usleep(kDisconnectWaitUs);
//流程3:如果要设置NONE,即卸载当前USB功能驱动,所以直接return即可
if (functions == static_cast<uint64_t>(GadgetFunction::NONE)) {
if (callback == nullptr)
return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(functions, Status::SUCCESS, in_transactionId); //回调给客户端
if (!ret.isOk()) ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.getDescription().c_str());
return ret;
}
//流程4:验证并设置VID/PID,根据功能配置验证并设置USB厂商/产品ID(如ADB和MTP的ID不同),例如高通的90DB等这些端口
status = validateAndSetVidPid(functions);
if (status != Status::SUCCESS) goto error;
//流程5:设置USB的功能,这个很重要
status = setupFunctions(functions, callback, timeout, in_transactionId);
if (status != Status::SUCCESS) goto error;
//流程6:整个流程成功,日志打印
ALOGI("Usb Gadget setcurrent functions called successfully");
return ScopedAStatus::ok();
//流程7:整个流程失败,错误处理
error:
ALOGI("Usb Gadget setcurrent functions failed");
if (callback == nullptr)
return ScopedAStatus::fromServiceSpecificErrorWithMessage(-1, "Usb Gadget setcurrent functions failed");
ScopedAStatus ret = callback->setCurrentUsbFunctionsCb(functions, status, in_transactionId);
if (!ret.isOk()) {
ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.getDescription().c_str());
return ret;
}
return ScopedAStatus::fromServiceSpecificErrorWithMessage(-1, "Usb Gadget setcurrent functions failed");
}
如上代码的核心流程还是参照aosp原生流程进行处理,在设置usb功能的时候,先卸载断开当前usb,然后验证VID/PID,然后通过setupFunctions来实现具体功能的启用。
2)高通定制setupFunctions
cpp
//la.um/vendor/qcom/opensource/usb/hal/UsbGadget.cpp
#define VENDOR_USB_PROP "vendor.usb.config"
#define PERSIST_VENDOR_USB_PROP "persist.vendor.usb.config"
#define PERSIST_VENDOR_USB_EXTRA_PROP "persist.vendor.usb.config.extra"
Status UsbGadget::setupFunctions( int64_t functions, const shared_ptr<IUsbGadgetCallback> &callback, int64_t timeout, int64_t in_transactionId) {
//functions参数为aosp标准功能,例如ADB MTP等,不可能是高通特有的diag等字符串
bool ffsEnabled = false;
int i = 0;
//核心流程1:获取属性vendor.usb.config和persist.vendor.usb.config的值
// 获取高通定制的功能,例如diag,adb将被获取出来
std::string gadgetName = GetProperty(USB_CONTROLLER_PROP, "");
std::string vendorProp = GetProperty(VENDOR_USB_PROP, GetProperty(PERSIST_VENDOR_USB_PROP, ""));
std::string vendorExtraProp = GetProperty(PERSIST_VENDOR_USB_EXTRA_PROP, "none");
//......
//核心分支A:如果设置AOSP标准RNDIS/NCM网络共享功能
// GadgetFunction::RNDIS和GadgetFunction::NCM是AOSP标准功能
if (((functions & GadgetFunction::RNDIS) != 0) || ((functions & GadgetFunction::NCM) != 0)) {
ALOGI("setCurrentUsbFunctions rndis");
std::string tetherComp = (functions & GadgetFunction::RNDIS) ? "rndis" : "ncm";
//如果persist.vendor.usb.config.extra属性有值,那么追加adb功能
if (vendorExtraProp != "none") tetherComp += "," + vendorExtraProp;
if (functions & GadgetFunction::ADB) tetherComp += ",adb";
//通过addFunctionsFromPropString去启用属性字符串的功能
if (addFunctionsFromPropString(tetherComp, ffsEnabled, i)) return Status::ERROR;
}
//核心分支B:如果设置AOSP标准ADB,且vendor.usb.config不等于adb
// 例如vendor.usb.config=diag.adb,这个时候上层应该传递GadgetFunction::ADB,但是还得添加高通定制的diag功能
else if (functions == static_cast<uint64_t>(GadgetFunction::ADB) && !vendorProp.empty() && vendorProp != "adb") {
if (vendorProp.find("adb") == std::string::npos) vendorProp += ",adb";
// 先打印vendor.usb.config值,即要设置的功能,其值可能包含多个功能
ALOGI("setting composition from %s: %s", VENDOR_USB_PROP, vendorProp.c_str());
// look up & parse prop string and link each function into the composition
//通过addFunctionsFromPropString去添加所有的高通指定的功能
if (addFunctionsFromPropString(vendorProp, ffsEnabled, i)) {
// if failed just fall back to adb-only
unlinkFunctions(CONFIG_PATH);
i = 0;
ffsEnabled = true;
if (addAdb(&mMonitorFfs, &i) != ::android::hardware::usb::gadget::V1_0::Status::SUCCESS)
return Status::ERROR;
}
} else {
//核心分支C:android标准功能添加,例如单纯的MTP或者PTP
WriteStringToFile("android", CONFIG_STRING);
if ((functions & GadgetFunction::UVC) == 0) {
if (addGenericAndroidFunctions(&mMonitorFfs, functions, &ffsEnabled, &i) != ::android::hardware::usb::gadget::V1_0::Status::SUCCESS)
return Status::ERROR;
} else {
ALOGI("setCurrentUsbFunctions uvc");
if (linkFunction("uvc.0", i++)) return Status::ERROR;
}
if ((functions & GadgetFunction::ADB) != 0) {
ffsEnabled = true;
if (addAdb(&mMonitorFfs, &i) != ::android::hardware::usb::gadget::V1_0::Status::SUCCESS)
return Status::ERROR;
}
}
//........
//ffs相关功能启用判断
ALOGI("Started monitor for FFS functions");
//........
return Status::SUCCESS;
}
如上代码核心逻辑,先获取了vendor.usb.config和persist.vendor.usb.config属性的值,然后进行了如下三条分支判断:
- function参数是RNDIS/NCM:表示启用aosp标准的网络共享功能,判断如果xxx.usb.config包含adb,那么通过addFunctionsFromPropString函数添加adb功能
- function参数是ADB:判断如果xxx.usb.config不等于adb,那么说明除了adb还有其他功能,例如高通特有功能,那么通过addFunctionsFromPropString函数添加字符串功能
- function参数是其他asop标准功能:走aosp标准流程
3)addFunctionsFromPropString

4)MTP场景
vendor.usb.config = adb 或者 vendor.usb.config = diag,adb
hal->setCurrentUsbFunctions(static_cast<uint64_t>(GadgetFunction::MTP), nullptr, 0);
因为hal调用传递的参数是MTP,所以直接走核心分支C,也不会添加高通特有功能diag
5)RNDIS场景 + adb
vendor.usb.config = rndis,adb
hal->setCurrentUsbFunctions(static_cast<uint64_t>(GadgetFunction::RNDIS), nullptr, 0);
因为hal调用传递的参数是RNDIS,所以直接走核心分支A,后判断xxx.usb.config包含adb,因此会通过addFunctionsFromPropString添加adb功能
6)ADB场景 + 高通字符串
vendor.usb.config = adb
hal->setCurrentUsbFunctions(static_cast<uint64_t>(GadgetFunction::ADB), nullptr, 0);
因为hal调用传递的参数是ADB,所以直接走核心分支B,但是判断没有高通特定的功能,所以也不会调用addFunctionsFromPropString
vendor.usb.config = diag,serial_cdev,rmnet,dpl,qdss,adb
hal->setCurrentUsbFunctions(static_cast<uint64_t>(GadgetFunction::ADB), nullptr, 0);
因为hal调用传递的参数是ADB,所以直接走核心分支B,判断xxx.usb.config不等于adb,所以会调用addFunctionsFromPropString依次遍历添加高通特有功能,如下日志:
bash
12-17 12:21:29.554 890 890 I servicemanager: Caller(pid=13885,uid=0,sid=u:r:usbd:s0) Found android.hardware.usb.gadget.IUsbGadget/default in device VINTF manifest.
12-17 12:21:29.672 1480 1480 I android.hardware.usb.gadget-service.qti: setting composition from vendor.usb.config: diag,serial_cdev,rmnet,dpl,qdss,adb
12-17 12:21:29.672 1480 1480 E android.hardware.usb.gadget-service.qti: vid 0x05C6 pid 0x90DB
12-17 12:21:29.673 1480 1480 I android.hardware.usb.gadget-service.qti: Adding diag
12-17 12:21:29.674 1480 1480 I android.hardware.usb.gadget-service.qti: Adding serial_cdev
12-17 12:21:29.675 1480 1480 I android.hardware.usb.gadget-service.qti: Adding rmnet
12-17 12:21:29.676 1480 1480 I android.hardware.usb.gadget-service.qti: Adding dpl
12-17 12:21:29.678 1480 1480 I android.hardware.usb.gadget-service.qti: Adding qdss
12-17 12:21:29.680 1480 1480 I android.hardware.usb.gadget-service.qti: Adding adb
12-17 12:21:29.686 1480 1480 I android.hardware.usb.gadget-service.qti: Started monitor for FFS functions
12-17 12:21:29.686 1480 1480 I android.hardware.usb.gadget-service.qti: Usb Gadget setcurrent functions called successfully
二、usbd进程
usbd属于native层的一个普通进程,被定义为usbd,被init启动,被定义为oneshot,即就启动一次。


1)usbd主函数
usbd进程非常简单,就只有一个main函数,在main函数中主要逻辑就是根据persist.sys.usb.config属性的值去掉用usb hal层,设置对应的function。
cpp
//system/core/usbd/usbd.cpp
#define LOG_TAG "usbd"
int main(int /*argc*/, char** /*argv*/) {
//充电模式直接退出
if (GetProperty("ro.bootmode", "") == "charger") exit(0);
//native进程的binder线程池初始化
int operationId = sUsbOperationCount++;
ABinderProcess_setThreadPoolMaxThreadCount(1);
ABinderProcess_startThreadPool();
const std::string service_name = std::string(aidl::android::hardware::usb::gadget::IUsbGadget::descriptor).append("/default");
//获取系统属性persist.sys.usb.config,其值可能为adb,在init进程的update_sys_usb_config函数中初始化值,其逻辑动态设置adb或者none
std::string function = GetProperty("persist.sys.usb.config", "");
if (function == "adb") {
LOG(INFO) << "persistent prop is adb";
SetProperty("ctl.start", "adbd"); //启动adbd进程
}
//获取USB AIDL HAL,在A14之后google建议使用AIDL替代之前HIDL
if (AServiceManager_isDeclared(service_name.c_str())) {
shared_ptr<aidl::android::hardware::usb::gadget::IUsbGadget> gadget_aidl =
aidl::android::hardware::usb::gadget::IUsbGadget::fromBinder(ndk::SpAIBinder(AServiceManager_waitForService(service_name.c_str())));
ScopedAStatus ret;
if (gadget_aidl != nullptr) {
//找到usb hal
LOG(INFO) << "Usb AIDL HAL found.";
if (function == "adb") {
//如果function是adb,设置当前function为adb
ret = gadget_aidl->setCurrentUsbFunctions( static_cast<uint64_t>(GadgetFunction::ADB), nullptr, 0, operationId);
} else {
//如果function是mtp,设置当前function为mtp
LOG(INFO) << "Signal MTP to enable default functions";
ret = gadget_aidl->setCurrentUsbFunctions( static_cast<uint64_t>(GadgetFunction::MTP), nullptr, 0, operationId);
}
if (!ret.isOk()) LOG(ERROR) << "Error while invoking usb hal";
} else {
LOG(INFO) << "Usb AIDL HAL not found";
}
} else {
//获取USB HIDL HAL,兼容A14之前的版本
android::sp<android::hardware::usb::gadget::V1_0::IUsbGadget> gadget = android::hardware::usb::gadget::V1_0::IUsbGadget::getService();
Return<void> ret;
if (gadget != nullptr) {
LOG(INFO) << "Usb HAL found.";
if (function == "adb") {
ret = gadget->setCurrentUsbFunctions(static_cast<uint64_t>(GadgetFunction::ADB), nullptr, 0);
} else {
LOG(INFO) << "Signal MTP to enable default functions";
ret = gadget->setCurrentUsbFunctions(static_cast<uint64_t>(GadgetFunction::MTP), nullptr, 0);
}
if (!ret.isOk()) LOG(ERROR) << "Error while invoking usb hal";
} else {
LOG(INFO) << "Usb HAL not found";
}
}
exit(0);
}
usbd主函数的逻辑非常的简单,通过如上代码可以总结如下:
- 如果persist.sys.usb.config属性值为adb,那么就启动adbd守护进程
- 如果persist.sys.usb.config属性值为adb,那么就调用HAL设置usb功能GadgetFunction::ADB
- 如果persist.sys.usb.config属性值非adb,那么就调用HAL设置usb功能GadgetFunction::MTP
- A14包括之前使用的HIDL接口,A16使用的就是AIDL
- 注意:其实这里的判断会有bug,后文会详细介绍
2)A14 setCurrentUsbFunctions函数
接着上文native层的usbd进程直接调用usb hal的setCurrentUsbFunctions接口来设置usb的function,我们先看看改接口的定义,如下:

setCurrentUsbFunctions函数的实现如下:
cpp
//hardware/interfaces/usb/gadget/1.1/default/UsbGadget.cpp
//setCurrentUsbFunctions函数用于动态切换Android设备的USB功能模式(如ADB/MTP等)
//functions参数为USB功能模式,可能值diag,serial_cdev,rmnet,dpl,qdss,adb或者none
Return<void> UsbGadget::setCurrentUsbFunctions(uint64_t functions, const sp<V1_0::IUsbGadgetCallback>& callback, uint64_t timeout) {
std::unique_lock<std::mutex> lk(mLockSetCurrentFunction);
mCurrentUsbFunctions = functions;
mCurrentUsbFunctionsApplied = false;
//流程1:卸载当前USB功能驱动(如断开ADB/MTP链接)Unlink the gadget and stop the monitor if running.
V1_0::Status status = tearDownGadget();
if (status != V1_0::Status::SUCCESS) {
goto error;
}
ALOGI("Returned from tearDown gadget");
//流程2:等待主机(如PC)检测到USB断开,即延迟等待 Leave the gadget pulled down to give time for the host to sense disconnect.
usleep(kDisconnectWaitUs);
//流程3:如果要设置NONE,即卸载当前USB功能驱动,所以直接return即可
if (functions == static_cast<uint64_t>(V1_0::GadgetFunction::NONE)) {
if (callback == NULL) return Void();
Return<void> ret = callback->setCurrentUsbFunctionsCb(functions, V1_0::Status::SUCCESS);//回调给客户端
if (!ret.isOk())
ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.description().c_str());
return Void();
}
//流程4:验证并设置VID/PID,根据功能配置验证并设置USB厂商/产品ID(如ADB和MTP的ID不同),例如高通的90DB等这些端口
status = validateAndSetVidPid(functions);
if (status != V1_0::Status::SUCCESS) {
goto error;
}
//流程5:设置USB的功能,例如adb,diag等,加载对应内核模块(如ffs.adb或ffs.mtp)并激活功能
status = setupFunctions(functions, callback, timeout);
if (status != V1_0::Status::SUCCESS) {
goto error;
}
//流程6:整个流程成功,日志打印
ALOGI("Usb Gadget setcurrent functions called successfully");
return Void();
//流程7:整个流程失败,错误处理
error:
ALOGI("Usb Gadget setcurrent functions failed");
if (callback == NULL) return Void();
Return<void> ret = callback->setCurrentUsbFunctionsCb(functions, status);
if (!ret.isOk())
ALOGE("Error while calling setCurrentUsbFunctionsCb %s", ret.description().c_str());
return Void();
}
总计如下几个流程:
- 流程1:tearDownGadget函数卸载当前USB功能驱动(如断开ADB/MTP链接)
- 流程2:如果functions是none,那么函数直接退出
- 流程3:validateAndSetVidPid校验设置VID和PID
- 流程4:setupFunctions设置functions
重点在看看setupFunctions是如何设置function的呢?如下代码,重点是根据vendor的几个属性来获取:
cpp
//vendor/qcom/opensource/usb/hal/UsbGadget.cpp
#define VENDOR_USB_PROP "vendor.usb.config"
#define PERSIST_VENDOR_USB_PROP "persist.vendor.usb.config"
#define PERSIST_VENDOR_USB_EXTRA_PROP "persist.vendor.usb.config.extra"

2、usb.config属性的配置
由此可见,usbd进程到usb hal之间协同作用,设置usb的工作模式,这个过程中不仅仅关联了如下几个属性,有persist.sys. 还有persist.vendor. 等,感觉非常的乱。
这里依次对她们进行一个整理。总共相关联的如下几个,在不同的平台和不同的android版本可能不一致:
-
persist.sys.usb.config\]: \[adb
-
persist.vendor.usb.config\]: \[diag,serial_cdev,rmnet,dpl,qdss,adb
-
persist.vendor.usb.config.extra\]: \[none
-
sys.usb.config\]: \[diag,serial_cdev,rmnet,dpl,qdss,adb
-
sys.usb.configfs\]: \[2
-
vendor.usb.config\]: \[diag,serial_cdev,rmnet,dpl,qdss,adb
-
vendor.usb.configfs\]: \[1
1)persist.sys.usb.config属性的初始化

这段代码是在init进程初始化系统属性的时候,通过PropertyLoadBootDefaults函数去加载默认属性的时候调用,梳理如下逻辑:
- 如果persist.sys.usb.config属性为空,如果debug版本,设置改属性为adb,用来支持开发者调试
- 如果persist.sys.usb.config属性为空,如果非debug版本,设置改属性为none,默认不允许调试
- 如果persist.sys.usb.config属性有值,如果debug版本,并且属性值没有adb,那么加上adb用来支持开发者调试。
- 在usbd进程启动过程中,会根据persist.sys.usb.config的值去对HAL层设置function功能,这里只看到了adb和mtp两种功function。
2)persist.vendor.usb.config属性的初始化
此属性在MTK平台不存在,主要是在高通平台上面,高通平台通过一个sh脚本主动去设置初始值,如果是debug版本就主动设置为diag,diag_mdm,qdss,qdss_mdm,serial_cdev,dpl,rmnet,adb,后续根据高通不同平台去设置不同的值,可能高通不同芯片架构支持的能力不一样。

这个脚本什么时候启动呢?是init进程运行过程中启动:


3)sys.usb.config和vendor.usb.config
persist.sy.usb.config和persist.vendor.usb.config的值分别会影响sys.usb.config和vendor.usb.config,但是他们的相互影响比较混乱,详细的可以参考init.qcom.usb.rc
这里整理一下大致的如下:
bash
#on boot的时候触发,把persist.vendor.usb.config的值赋值给sys.usb.config
on boot
setprop sys.usb.config ${persist.vendor.usb.config}
on boot && property:vendor.usb.use_gadget_hal=1
setprop sys.usb.configfs 2
#如果sys.usb.configfs强化模式支持,把sys.usb.config的值赋值给vendor.usb.config
on property:sys.usb.config=* && property:sys.usb.configfs=2
setprop vendor.usb.config ${sys.usb.config}
#如果sys.usb.configfs强化模式支持,usb.config属性变动启动usbd进程
on property:vendor.usb.config=* && property:sys.usb.configfs=2
start usbd
on property:vendor.usb.controller=* && property:vendor.usb.use_gadget_hal=0
setprop sys.usb.controller ${vendor.usb.controller}
setprop sys.usb.configfs 1
#如果vendor.usb.use_gadget_hal=0,把persist.vendor.usb.config赋值给persist.sys.usb.config
on property:persist.vendor.usb.config=* && property:vendor.usb.use_gadget_hal=0
setprop persist.sys.usb.config ${persist.vendor.usb.config}
on boot && property:ro.boot.usbconfigfs=true
setprop sys.usb.configfs 1
#如果sys.usb.configfs=1普通模式支持,后续通过rc来触发sys.usb.config属性的所有动作
on property:sys.usb.config=none && property:sys.usb.configfs=1
on property:sys.usb.config=* && property:sys.usb.configfs=1
rm /config/usb_gadget/g1/os_desc/b.1
on property:sys.usb.config=none && property:sys.usb.configfs=1
rm /config/usb_gadget/g1/configs/b.1/f1
rm /config/usb_gadget/g1/configs/b.1/f2
rm /config/usb_gadget/g1/configs/b.1/f3
rm /config/usb_gadget/g1/configs/b.1/f4
rm /config/usb_gadget/g1/configs/b.1/f5
rm /config/usb_gadget/g1/configs/b.1/f6
rm /config/usb_gadget/g1/configs/b.1/f7
rm /config/usb_gadget/g1/configs/b.1/f8
rm /config/usb_gadget/g1/configs/b.1/f9
rm /config/usb_gadget/g1/configs/b.1/f10
rm /config/usb_gadget/g1/configs/b.1/f11
rm /config/usb_gadget/g1/configs/b.1/f12
rm /config/usb_gadget/g1/configs/b.1/f13
rm /config/usb_gadget/g1/configs/b.1/f14
on property:sys.usb.config=mass_storage && property:sys.usb.configfs=1
#....省略...
这段rc配置把几个属性完全耦合,我们只需要明白
sys.usb.configfs属性的值为1的时候,不会赋值到vendor.usb.config,我在此值为1的手上调试发现基本上不会存在vendor.usb.config,即sys.ubs.config在rc文件中执行响应控制usb相关节点sys.usb.configfs属性的值为2的时候,直接赋值到vendor.usb.config,并通过启动usbd进程去响应,usbd进程里面获取persist.sys.usb.config,还会启动usb hal,在usb hal中会参考persist.vendor.usb.config去影响vendor.usb.config默认值,但是最终还是由vendor.usb.config来决定当前如何控制usb
3、sys.usb.configfs模式配置
sys.usb.configfs 是 Android 系统中用于控制 USB 配置方式的核心属性,该属性决定使用哪种内核机制来配置 USB 功能:
0:表示传统模式(基于android_usb.ko驱动),该方式在A12之后已经被弃用,此处不作任何介绍1:表示现代ConfigFS模式(基于/config/usb_gadget动态配置),即可以通过init.qcom.usb.rc文件配置的sys.usb.config属性动态配置生效- 2:最新usb hal采用usb_compositions.conf的配置来实现
4、高通A14项目的日志跟踪
1)高通A14 userdebug版本
这次使用的版本是高通a14 debug版本,因此属性如下:
- persist.sys.usb.config默认没有配置,因为是debug版本,所以在init进程update_sys_usb_config函数中被默认设置为adb
- persist.vendor.usb.config默认在init进程的on-post-fs-data阶段启动init.qcom.usb.sh脚本设置为diag,serial_cdev,rmnet,dpl,qdss,adb
bash
C:\Users\pengcheng.ding>adb shell getprop | findstr "usb.config"
[persist.sys.usb.config]: [adb]
[persist.vendor.usb.config]: [diag,serial_cdev,rmnet,dpl,qdss,adb]
[persist.vendor.usb.config.extra]: [none]
[sys.usb.config]: [diag,serial_cdev,rmnet,dpl,qdss,adb]
[sys.usb.configfs]: [2]
[vendor.usb.config]: [diag,serial_cdev,rmnet,dpl,qdss,adb]
[vendor.usb.configfs]: [1]
2)高通A14 user 定制版本:persist.vendor.usb.config
这次使用的是高通A14 user版本,定制了在update_sys_usb_config的时候强制如下属性:persist.sys.usb.config]: [diag,serial_cdev,rmnet,dpl,qdss,adb]
- 因为persist.sys.usb.config非adb,所以在原生的usbd代码中直接进入mtp流程
- 因为user版本,所以persist.vendor.usb.config在init.qcom.usb.sh脚本中根本不会设置
bash
C:\Users\pengcheng.ding>adb shell getprop | findstr "usb.config"
[persist.sys.usb.config]: [diag,serial_cdev,rmnet,dpl,qdss,adb]
[persist.vendor.usb.config.extra]: [none]
[sys.usb.config]: [diag,serial_cdev,rmnet,dpl,qdss,adb]
[sys.usb.configfs]: [2]
[vendor.usb.config]: [diag,serial_cdev,rmnet,dpl,qdss,adb]
[vendor.usb.configfs]: [1]
针对如上属性组合,开机流程会经过如下两个阶段:
- 大约开机动画显示的时候:此时init进程系统属性服务启动的时候,去设置persist.sys.usb.config会直接导致usbd启动,并进行匹配非adb,因此进入MTP模式,在usb hal里面切换为None和MTP,这个时候adb是断开的
- 在开机完成进入lancher的时候:会响应on boot把persist.sys.usb.config的值赋值到vendor.usb.config,这个时候居然去启动了adbd和usb hal,在hal中判断vendor.usb.config的值包含adb,因此添加了所有的功能
3)高通A14 user定制版本:usbd
针对如上情况,persist.vendor.usb.config定制为diag,serial_cdev,rmnet,dpl,qdss,adb,但是在开机动画阶段确没有adb,这个情况感觉个人觉得不是很合理,明明包含adb,为什么usbd判断出来非adb呢?因此针对usbd进程做了如下的修改:
此时在开机动画阶段,usbd进程启动的时候就不会进入mtp流程,而是直接切换为adb功能,adbd就不会在开机动画过程中中断,如下日志: