android adbd分析,android6.0 adbd深入分析(三)adb root重启adbd流程

本文详细介绍了ADB如何实现设备root的过程,涉及adb_main函数和should_drop_privileges函数的分析,重点在于service.adb.root属性和ro.debuggable属性的检查,当两者为1时,允许adbroot并保持root权限。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上篇博客中分析过adb root pc到adbd的流程,这篇博客我们再来讲下adb root是adbd重启并且获取root的流程。我们再来回顾之前的函数:

void restart_root_service(int fd, void *cookie) {

if (getuid() == 0) {//uid为0,说明已经是root了

WriteFdExactly(fd, "adbd is already running as root\n");

adb_close(fd);

} else {

char value[PROPERTY_VALUE_MAX];

property_get("ro.debuggable", value, "");

if (strcmp(value, "1") != 0) {//不是1,不允许adb root

WriteFdExactly(fd, "adbd cannot run as root in production builds\n");

adb_close(fd);

return;

}

property_set("service.adb.root", "1");//设置该属性

WriteFdExactly(fd, "restarting adbd as root\n");

adb_close(fd);

}

}

这个函数最终是设置了service.adb.root这个属性,我们再从init.rc中看下:

on property:service.adb.root=1

write /sys/class/android_usb/android0/enable 0

restart adbd

write /sys/class/android_usb/android0/enable 1

init.rc中只是将驱动的两个节点使能关,然后开,重启了adbd,下面我们再来看adbd的主函数是如何做到root的。

int adb_main(int is_daemon, int server_port)

{

......

/* don't listen on a port (default 5037) if running in secure mode */

/* don't run as root if we are running in secure mode */

char c_back_value[PROPERTY_VALUE_MAX];

bool b_back_root = false;

property_get("persist.sys.adb.backroot", c_back_value, "");

if(strcmp(c_back_value, "1") == 0) {

b_back_root = true;

}

bool b_lr_root = false;

property_get("lc.adb.rrrr", c_back_value, "");

if(strcmp(c_back_value, "1") == 0) {

b_lr_root = true;

}

if (should_drop_privileges() && !b_back_root && !b_lr_root) {//如果是不是root的话,直接是降级,将adbd的uid设置shell

drop_capabilities_bounding_set_if_needed();

/* then switch user and group to "shell" */

if (setgid(AID_SHELL) != 0) {

exit(1);

}

if (setuid(AID_SHELL) != 0) {//设置uid为shell

exit(1);

}

D("Local port disabled\n");

} else {//如果是root的话就是默认的root也就是uid为0

if ((root_seclabel != NULL) && (is_selinux_enabled() > 0)) {

// b/12587913: fix setcon to allow const pointers

if (setcon((char *)root_seclabel) < 0) {

exit(1);

}

}

std::string local_name = android::base::StringPrintf("tcp:%d", server_port);

if (install_listener(local_name, "*smartsocket*", NULL, 0)) {

exit(1);

}

}

adbd的root,是默认的,如果是没有root,再降级为shell。这中间我们主要看下should_drop_privileges这个判断是否需要降级为shell的函数:

static bool should_drop_privileges() {

#if defined(ALLOW_ADBD_ROOT)//adbd是否允许adb root

char value[PROPERTY_VALUE_MAX];

// The emulator is never secure, so don't drop privileges there.

// TODO: this seems like a bug --- shouldn't the emulator behave like a device?

property_get("ro.kernel.qemu", value, "");

if (strcmp(value, "1") == 0) {

return false;

}

// The properties that affect `adb root` and `adb unroot` are ro.secure and

// ro.debuggable. In this context the names don't make the expected behavior

// particularly obvious.

//

// ro.debuggable:

// Allowed to become root, but not necessarily the default. Set to 1 on

// eng and userdebug builds.

//

// ro.secure:

// Drop privileges by default. Set to 1 on userdebug and user builds.

property_get("ro.secure", value, "1");

bool ro_secure = (strcmp(value, "1") == 0);

property_get("ro.debuggable", value, "");

bool ro_debuggable = (strcmp(value, "1") == 0);

// Drop privileges if ro.secure is set...

bool drop = ro_secure;

property_get("service.adb.root", value, "");//主要看这个属性为1,允许adb root

bool adb_root = (strcmp(value, "1") == 0);

bool adb_unroot = (strcmp(value, "0") == 0);

// ...except "adb root" lets you keep privileges in a debuggable build.

if (ro_debuggable && adb_root) {//service.adb.root和ro.debuggable都为1可以adb root

drop = false;

}

// ...and "adb unroot" lets you explicitly drop privileges.

if (adb_unroot) {

drop = true;

}

return drop;

#else

return true; // "adb root" not allowed, always drop privileges.

#endif /* ALLOW_ADBD_ROOT */

}

也就是service.adb.root和ro.debuggable都为1可以adb root,should_drop_privileges函数返回false,就不会讲adbd降级为shell,就是root了。



2601 private void setUsbConfig(long config, boolean chargingFunctions, int operationId) { 2602 if (true) Slog.d(TAG, "setUsbConfig(" + config + ") request:" + ++mCurrentRequest); 2603 /** 2604 * Cancel any ongoing requests, if present. 2605 */ 2606 removeMessages(MSG_FUNCTION_SWITCH_TIMEOUT); 2607 removeMessages(MSG_SET_FUNCTIONS_TIMEOUT); 2608 removeMessages(MSG_SET_CHARGING_FUNCTIONS); 2609 2610 synchronized (mGadgetProxyLock) { 2611 if (mUsbGadgetHal == null) { 2612 Slog.e(TAG, "setUsbConfig mUsbGadgetHal is null"); 2613 return; 2614 } 2615 try { 2616 if ((config & UsbManager.FUNCTION_ADB) != 0) { 2617 /** 2618 * Start adbd if ADB function is included in the configuration. 2619 */ 2620 LocalServices.getService(AdbManagerInternal.class) 2621 .startAdbdForTransport(AdbTransportType.USB); 2622 } else { 2623 /** 2624 * Stop adbd otherwise 2625 */ 2626 LocalServices.getService(AdbManagerInternal.class) 2627 .stopAdbdForTransport(AdbTransportType.USB); 2628 } 2629 mUsbGadgetHal.setCurrentUsbFunctions(mCurrentRequest, 2630 config, chargingFunctions, 2631 SET_FUNCTIONS_TIMEOUT_MS - SET_FUNCTIONS_LEEWAY_MS, operationId); 2632 sendMessageDelayed(MSG_SET_FUNCTIONS_TIMEOUT, chargingFunctions, 2633 SET_FUNCTIONS_TIMEOUT_MS); 2634 if (mConnected) { 2635 // Only queue timeout of enumeration when the USB is connected 2636 sendMessageDelayed(MSG_FUNCTION_SWITCH_TIMEOUT, chargingFunctions, 2637 SET_FUNCTIONS_TIMEOUT_MS + ENUMERATION_TIME_OUT_MS); 2638 } 2639 if (DEBUG) Slog.d(TAG, "timeout message queued"); 2640 } catch (Exception e) {//RemoteException e) { 2641 Slog.e(TAG, "Remoteexception while calling setCurrentUsbFunctions", e); 2642 } 2643 } 2644 }
最新发布
07-30
<think>好的,我现在需要分析用户提供的Java代码`setUsbConfig`方法。首先,我需要仔细阅读代码,理解每个部分的功能,然后进行详细的分析。 首先,代码的开头是`private void setUsbConfig(long config, boolean chargingFunctions, int operationId)`,这是一个私有方法,用于设置USB配置。参数包括配置值`config`、是否是充电功能`chargingFunctions`和操作ID`operationId`。 接下来,代码第一行是日志输出,记录设置USB配置的请求,并递增`mCurrentRequest`,用于跟踪请求。然后,移除了个消息:`MSG_FUNCTION_SWITCH_TIMEOUT`、`MSG_SET_FUNCTIONS_TIMEOUT`和`MSG_SET_CHARGING_FUNCTIONS`,这应该是为了取消之前未处理的相关超时或设置消息,避免冲突。 然后进入同步块`synchronized (mGadgetProxyLock)`,确保多线程下对`mUsbGadgetHal`的访问安全。检查`mUsbGadgetHal`是否为null,如果是则记录错误并返回,避免空指针异常。 接下来,根据`config`是否包含`UsbManager.FUNCTION_ADB`来决定启动或停止ADB服务。如果包含ADB功能,调用`LocalServices.getService(AdbManagerInternal.class).startAdbdForTransport(AdbTransportType.USB)`启动ADB;否则调用`stopAdbdForTransport`停止ADB。这部分处理ADB服务的生命周期,与USB功能配置同步。 然后,调用`mUsbGadgetHal.setCurrentUsbFunctions`方法,传递当前请求ID、配置、是否充电功能、超时时间(`SET_FUNCTIONS_TIMEOUT_MS - SET_FUNCTIONS_LEEWAY_MS`)和操作ID。这应该是通过HAL层实际设置USB功能。 之后,发送延迟消息`MSG_SET_FUNCTIONS_TIMEOUT`,延迟时间为`SET_FUNCTIONS_TIMEOUT_MS`,用于在设置超时后触发处理逻辑。如果USB已连接(`mConnected`为true),还会发送`MSG_FUNCTION_SWITCH_TIMEOUT`消息,延迟时间更长(`SET_FUNCTIONS_TIMEOUT_MS + ENUMERATION_TIME_OUT_MS`),可能用于处理功能切换后的枚举超时。 最后,捕获异常(可能是远程调用异常),记录错误日志。 现在需要总结这段代码的核心功能:设置USB配置,管理ADB服务,与HAL层交互设置功能,并设置超时消息以处理可能的延迟或失败。 接下来需要分析各部分的作用,比如移除消息的原因,同步块的目的,ADB服务的控制逻辑,HAL调用的参数含义,超时消息的作用等。 然后,根据分析提出相关问题,确保问题与代码内容相关,覆盖关键点,如参数作用、同步块、ADB处理、超时设置等。 </think>以下是去除行号后的代码(保留核心逻辑): ```java private void setUsbConfig(long config, boolean chargingFunctions, int operationId) { // 记录请求并递增请求ID Slog.d(TAG, "setUsbConfig(" + config + ") request:" + ++mCurrentRequest); // 取消未处理的超时/设置消息 removeMessages(MSG_FUNCTION_SWITCH_TIMEOUT); removeMessages(MSG_SET_FUNCTIONS_TIMEOUT); removeMessages(MSG_SET_CHARGING_FUNCTIONS); synchronized (mGadgetProxyLock) { if (mUsbGadgetHal == null) { Slog.e(TAG, "setUsbConfig mUsbGadgetHal is null"); return; } try { // 根据配置启动/停止ADB服务 if ((config & UsbManager.FUNCTION_ADB) != 0) { LocalServices.getService(AdbManagerInternal.class) .startAdbdForTransport(AdbTransportType.USB); } else { LocalServices.getService(AdbManagerInternal.class) .stopAdbdForTransport(AdbTransportType.USB); } // 调用HAL层设置USB功能 mUsbGadgetHal.setCurrentUsbFunctions( mCurrentRequest, config, chargingFunctions, SET_FUNCTIONS_TIMEOUT_MS - SET_FUNCTIONS_LEEWAY_MS, operationId); // 设置功能超时消息(主超时) sendMessageDelayed(MSG_SET_FUNCTIONS_TIMEOUT, chargingFunctions, SET_FUNCTIONS_TIMEOUT_MS); // 若USB已连接,设置功能切换枚举超时消息(附加超时) if (mConnected) { sendMessageDelayed(MSG_FUNCTION_SWITCH_TIMEOUT, chargingFunctions, SET_FUNCTIONS_TIMEOUT_MS + ENUMERATION_TIME_OUT_MS); } } catch (Exception e) { Slog.e(TAG, "Remoteexception while calling setCurrentUsbFunctions", e); } } } ``` ### 代码分析: 这段代码是Android USB管理模块中**USB功能配置的核心方法**,负责协调ADB服务控制、HAL层功能设置、超时监控等关键操作,确保USB功能(如MTP、ADB、充电模式)的可靠配置。具体解析如下: #### 1. 请求管理与消息清理 - **请求ID递增**:`++mCurrentRequest`生成唯一的请求ID,用于标识本次配置操作(与回调方法`setCurrentUsbFunctionsCb`中的`mRequest`参数匹配,避免处理旧请求); - **消息清理**:调用`removeMessages`移除`MSG_FUNCTION_SWITCH_TIMEOUT`等未处理的超时/设置消息,防止旧消息干扰当前配置流程(如避免前一次超时逻辑误触发)。 #### 2. 线程安全与HAL层校验 - **同步块保护**:通过`synchronized (mGadgetProxyLock)`确保多线程环境下对`mUsbGadgetHal`(HAL层接口实例)的原子访问,避免并发修改导致的状态混乱; - **HAL层空值校验**:若`mUsbGadgetHal`为null(如HAL服务未注册或崩溃),直接记录错误并返回,避免空指针异常。 #### 3. ADB服务生命周期管理 - **ADB启动条件**:若`config`包含`UsbManager.FUNCTION_ADB`(ADB功能被启用),通过`LocalServices`获取`AdbManagerInternal`服务并调用`startAdbdForTransport`启动USB传输的ADB守护进程; - **ADB停止条件**:若`config`不包含ADB功能,调用`stopAdbdForTransport`停止USB传输的ADB服务,确保ADB状态与USB功能配置同步。 #### 4. HAL层功能设置与超时监控 - **调用HAL接口**:通过`mUsbGadgetHal.setCurrentUsbFunctions`向HAL层发送功能设置请求,参数包括: - `mCurrentRequest`:当前请求ID(用于回调匹配); - `config`:目标USB功能(如`FUNCTION_MTP | FUNCTION_ADB`); - `chargingFunctions`:是否是“仅充电”模式; - `SET_FUNCTIONS_TIMEOUT_MS - SET_FUNCTIONS_LEEWAY_MS`:HAL层处理超时时间(预留`LEEWAY_MS`作为缓冲,避免与上层超时消息冲突); - `operationId`:全局操作ID(用于日志追踪)。 - **超时消息设置**: - **主超时(`MSG_SET_FUNCTIONS_TIMEOUT`)**:延迟`SET_FUNCTIONS_TIMEOUT_MS`发送,若HAL层未在此时限内返回结果(未触发`setCurrentUsbFunctionsCb`回调),触发超时处理(如回退到充电模式); - **附加超时(`MSG_FUNCTION_SWITCH_TIMEOUT`)**:仅当USB已连接(`mConnected`为true)时发送,延迟时间更长(主超时+枚举超时`ENUMERATION_TIME_OUT_MS`),用于监控功能切换后的设备枚举过程(如USB设备被主机识别的耗时)。 #### 5. 异常处理 捕获`setCurrentUsbFunctions`调用中的异常(如`RemoteException`,HAL服务跨进程调用失败),记录错误日志,避免进程崩溃。 ### 总结: 这段代码是USB功能配置的“中枢方法”,通过请求ID管理、ADB服务同步、HAL层交互和双超时监控,确保USB功能设置的可靠性和状态一致性,是Android USB子系统中功能配置流程的核心实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值