本文内容如下:
1. makefile分析及总结
2. adb框架介绍
3. adbd源码分析
3.1 adbd初始化流程分析
3.2 adb shell流程分析
3.3 adb root流程分析
4. adb常用命令
一、makefile分析及总结
-
// 以下内容摘录自android/
system/core/adb/Android.mk
-
-
# Copyright 2005 The Android Open Source Project
-
#
-
# Android.mk for adb
-
#
-
-
LOCAL_PATH:= $(call
my-dir)
-
-
// 使用HOST_OS这个宏兼容不同的PC操作系统,比如windows,linux,mac等。
-
ife
q ($(HOST_OS),windows)
-
adb_host_clang := false
# libc++ for mingw not ready yet.
-
else
-
adb_host_clang := true
-
endif
-
-
adb_version := $(shell git -C $(LOCAL_PATH) rev-parse --short=
12 HEAD
2>
/dev/null)-android
-
-
ADB_COMMON_CFLAGS := \
-
-Wall -Werror \
-
-Wno-unused-parameter \
-
-DADB_REVISION=
'"$(adb_version)"' \
-
-
# libadb
-
# =========================================================
-
-
# Much of adb is duplicated in bootable/recovery/minadb and fastboot. Changes
-
# made to adb rarely get ported to the other two, so the trees have diverged a
-
# bit. We'd like to stop this because it is a maintenance nightmare, but the
-
# divergence makes this difficult to do all at once. For now, we will start
-
# small by moving common files into a static library. Hopefully some day we can
-
# get enough of adb in here that we no longer need minadb. https://b/17626262
-
LIBADB_SRC_FILES := \
-
adb.cpp \
-
adb_auth.cpp \
-
adb_io.cpp \
-
adb_listeners.cpp \
-
adb_utils.cpp \
-
sockets.cpp \
-
transport.cpp \
-
transport_local.cpp \
-
transport_usb.cpp \
-
-
LIBADB_TEST_SRCS := \
-
adb_io_test.cpp \
-
adb_utils_test.cpp \
-
transport_test.cpp \
-
-
LIBADB_CFLAGS := \
-
$(ADB_COMMON_CFLAGS) \
-
-Wno-missing-field-initializers \
-
-fvisibility=hidden \
-
-
LIBADB_darwin_SRC_FILES := \
-
fdevent.cpp \
-
get_my_path_darwin.cpp \
-
usb_osx.cpp \
-
-
LIBADB_linux_SRC_FILES := \
-
fdevent.cpp \
-
get_my_path_linux.cpp \
-
usb_linux.cpp \
-
-
LIBADB_windows_SRC_FILES := \
-
get_my_path_windows.cpp \
-
sysdeps_win32.cpp \
-
usb_windows.cpp \
-
-
include $(CLEAR_VARS)
-
LOCAL_CLANG := true
-
// 编译生成libadbd静态库,供adbd deamon进程使用
-
LOCAL_MODULE := libadbd
-
LOCAL_CFLAGS := $(LIBADB_CFLAGS) -DADB_HOST=
0
-
LOCAL_SRC_FILES := \
-
$(LIBADB_SRC_FILES) \
-
adb_auth_client.cpp \
-
fdevent.cpp \
-
jdwp_service.cpp \
-
qemu_tracing.cpp \
-
usb_linux_client.cpp \
-
-
LOCAL_SHARED_LIBRARIES := libbase
-
-
include $(BUILD_STATIC_LIBRARY)
-
-
include $(CLEAR_VARS)
-
LOCAL_CLANG := $(adb_host_clang)
-
// 编译生成libadb动态库,供pc端adb可执行文件使用
-
LOCAL_MODULE := libadb
-
LOCAL_CFLAGS := $(LIBADB_CFLAGS) -DADB_HOST=
1
-
LOCAL_SRC_FILES := \
-
$(LIBADB_SRC_FILES) \
-
$(LIBADB
_$(HOST_OS)_SRC_FILES) \
-
adb_auth_host.cpp \
-
-
LOCAL_SHARED_LIBRARIES := libbase
-
-
# Even though we're building a static library (and thus there's no link step for
-
# this to take effect), this adds the SSL includes to our path.
-
LOCAL_STATIC_LIBRARIES := libcrypto_static
-
-
ife
q ($(HOST_OS),windows)
-
LOCAL_C_INCLUDES += development/host/windows/usb/api/
-
endif
-
-
include $(BUILD_HOST_STATIC_LIBRARY)
-
-
include $(CLEAR_VARS)
-
LOCAL_CLANG := true
-
// 编译生成adbd的测试程序
-
LOCAL_MODULE := adbd_test
-
LOCAL_CFLAGS := -DADB_HOST=
0 $(LIBADB_CFLAGS)
-
LOCAL_SRC_FILES := $(LIBADB_TEST_SRCS)
-
LOCAL_STATIC_LIBRARIES := libadbd
-
LOCAL_SHARED_LIBRARIES := liblog libbase libcutils
-
include $(BUILD_NATIVE_TEST)
-
-
include $(CLEAR_VARS)
-
LOCAL_CLANG := $(adb_host_clang)
-
// 编译生成adb的测试程序
-
LOCAL_MODULE := adb_test
-
LOCAL_CFLAGS := -DADB_HOST=
1 $(LIBADB_CFLAGS)
-
LOCAL_SRC_FILES := $(LIBADB_TEST_SRCS) services.cpp
-
LOCAL_SHARED_LIBRARIES := liblog libbase
-
LOCAL_STATIC_LIBRARIES := \
-
libadb \
-
libcrypto_static \
-
libcutils \
-
-
ife
q ($(HOST_OS),linux)
-
LOCAL_LDLIBS += -lrt -ldl -lpthread
-
endif
-
-
ife
q ($(HOST_OS),darwin)
-
LOCAL_LDLIBS += -framework CoreFoundation -framework IOKit
-
endif
-
-
include $(BUILD_HOST_NATIVE_TEST)
-
-
# adb device tracker (used by ddms) test tool
-
# =========================================================
-
-
ife
q ($(HOST_OS),linux)
-
include $(CLEAR_VARS)
-
LOCAL_CLANG := $(adb_host_clang)
-
// 编译生成adb_device_tracker服务的测试程序
-
LOCAL_MODULE := adb_device_tracker_test
-
LOCAL_CFLAGS := -DADB_HOST=
1 $(LIBADB_CFLAGS)
-
LOCAL_SRC_FILES := test_track_devices.cpp
-
LOCAL_SHARED_LIBRARIES := liblog libbase
-
LOCAL_STATIC_LIBRARIES := libadb libcrypto_static libcutils
-
LOCAL_LDLIBS += -lrt -ldl -lpthread
-
include $(BUILD_HOST_EXECUTABLE)
-
endif
-
-
# adb host tool
-
# =========================================================
-
include $(CLEAR_VARS)
-
-
ife
q ($(HOST_OS),linux)
-
LOCAL_LDLIBS += -lrt -ldl -lpthread
-
LOCAL_CFLAGS += -DWORKAROUND_BUG6558362
-
endif
-
-
ife
q ($(HOST_OS),darwin)
-
LOCAL_LDLIBS += -lpthread -framework CoreFoundation -framework IOKit -framework Carbon
-
LOCAL_CFLAGS += -Wno-sizeof-pointer-memaccess -Wno-unused-parameter
-
endif
-
-
ife
q ($(HOST_OS),windows)
-
LOCAL_LDLIBS += -lws2_32 -lgdi32
-
EXTRA_STATIC_LIBS := AdbWinApi
-
endif
-
-
LOCAL_CLANG := $(adb_host_clang)
-
-
LOCAL_SRC_FILES := \
-
adb_main.cpp \
-
console.cpp \
-
commandline.cpp \
-
adb_client.cpp \
-
services.cpp \
-
file_sync_client.cpp \
-
-
LOCAL_CFLAGS += \
-
$(ADB_COMMON_CFLAGS) \
-
-D_GNU_SOURCE \
-
-DADB_HOST=
1 \
-
-
// 编译生成PC端的adb可执行文件,位于sdk/platform-tools/adb目录下
-
LOCAL_MODULE := adb
-
LOCAL_MODULE_TAGS := debug
-
-
LOCAL_STATIC_LIBRARIES := \
-
libadb \
-
libbase \
-
libcrypto_static \
-
libcutils \
-
liblog \
-
$(EXTRA_STATIC_LIBS) \
-
-
# libc++ not available on windows yet
-
ifne
q ($(HOST_OS),windows)
-
LOCAL_CXX_STL := libc++_static
-
endif
-
-
# Don't add anything here, we don't want additional shared dependencies
-
# on the host adb tool, and shared libraries that link against libc++
-
# will violate ODR
-
LOCAL_SHARED_LIBRARIES :=
-
-
include $(BUILD_HOST_EXECUTABLE)
-
-
$(call dist-
for-goals,dist_files sdk,$(LOCAL_BUILT_MODULE))
-
-
ife
q ($(HOST_OS),windows)
-
$(LOCAL_INSTALLED_MODULE): \
-
$(HOST_OUT_EXECUTABLES)/AdbWinApi.dll \
-
$(HOST_OUT_EXECUTABLES)/AdbWinUsbApi.dll
-
endif
-
-
# adbd device daemon
-
# =========================================================
-
-
include $(CLEAR_VARS)
-
-
LOCAL_CLANG := true
-
-
LOCAL_SRC_FILES := \
-
adb_main.cpp \
-
services.cpp \
-
file_sync_service.cpp \
-
framebuffer_service.cpp \
-
remount_service.cpp \
-
set_verity_enable_state_service.cpp \
-
-
LOCAL_CFLAGS := \
-
$(ADB_COMMON_CFLAGS) \
-
-DADB_HOST=
0 \
-
-D_GNU_SOURCE \
-
-Wno-deprecated-declarations \
-
-
// engineer模式下无需AUTH认证
-
LOCAL_CFLAGS += -DALLOW_ADBD_NO_AUTH=$(
if $(filter userdebug eng,$(TARGET_BUILD_VARIANT)),
1,
0)
-
-
ifne
q (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
-
LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=
1
-
LOCAL_CFLAGS += -DALLOW_ADBD_ROOT=
1
-
endif
-
// 编译生成设备端或模拟器端的adbd deamon进程
-
LOCAL_MODULE := adbd
-
-
LOCAL_FORCE_STATIC_EXECUTABLE := true
-
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
-
LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
-
LOCAL_C_INCLUDES +=
system/extras/ext4_utils
-
-
LOCAL_STATIC_LIBRARIES := \
-
libadbd \
-
libbase \
-
libfs_mgr \
-
liblog \
-
libcutils \
-
libc \
-
libmincrypt \
-
libselinux \
-
libext4_utils_static \
-
-
include $(BUILD_EXECUTABLE)
关键点总结:
所有的adb程序(PC端和设备端)共用一套代码,只是借助于HOST_OS这个宏进行隔离,编译时会生成两个可执行文件: 1.adb/adb.exe:运行于PC端(包括Windows、Linux、MacOS等操作系统之上),位于platform/tools/adb目录下,透过adb命令可以唤起。 2.adbd:运行于Android设备上,开机时自动启动。 相应的,源码中也会由ADB_HOST宏用来区分本地主机(adb)和目标机(adbd)。 Engineer模式下会定义ALLOW_ADBD_NO_AUTH,源码中会使用到。
二、adb框架介绍
ADB为 Android Debug Bridge(调试桥)的缩写,本质上是一个 C/S 架构的命令行工具。整个ADB模块由如下几部分组成(详细参见system/core/adb/OVERVIEW.txt和transports.txt):
-
a) Host Services: 运行于ADB
Server,不需要和devices进行数据交换。典型的就是执行adb devices命令时,只需要adb
server端返回当前的adb devices的状态即可。
-
-
b)Local Services: 运行于adbd守护进程,ADB
Server负责建立adb clients和Local Services之间的连接,并透传数据。
注:本篇文章只分析ADBD的实现。
三、adbd源码分析
ADB分为usb adb和wifi adb两种方式,两者互斥存在,默认使用的是usb adb. 如果想默认启动wifi adb,需设置属性service.adb.tcp.port值为55555,然后重启adbd即可。ADB daemon(usb adb.)程序开机启动主要步骤如下图所示。
说明如下:
-
#if ADB_HOST_ON_TARGET
-
/* adb and adbd are coexisting on the target, so use 5038 for adb
-
* to avoid conflicting with adbd's usage of 5037
-
*/
-
# define DEFAULT_ADB_PORT 5038
-
#else
-
# define DEFAULT_ADB_PORT 5037
-
#endif
-
void
init_transport_registration(
void)
-
{
-
int s[
2];
-
-
// 创建双向通信的管道,全双工
-
if(
adb_socketpair(s)){
-
fatal_errno(
"cannot open transport registration socketpair");
-
}
-
D(
"socketpair: (%d,%d)", s[
0], s[
1]);
-
-
transport_registration_send = s[
0];
// 发送数据
-
transport_registration_recv = s[
1];
// 接收数据
-
-
// transport_registration_recv有数据接收到后,会触发transport_registration_func执行
-
fdevent_install(&transport_registration_fde,
-
transport_registration_recv,
-
transport_registration_func,
// 这个函数很重!!
-
0);
-
-
fdevent_set(&transport_registration_fde,
FDE_READ);
-
}
因此,接下来需要分析transport_registration_recv会接收数据,即transport_registration_send何时会发送数据。
-
void adbd_cloexec_auth_socket() {
-
int fd = android_get_control_socket(
"adbd");
-
if (fd ==
-1) {
-
D(
"Failed to get adbd socket\n");
-
return;
-
}
-
fcntl(fd, F_SETFD, FD_CLOEXEC);
-
}
-
// adbd 默认是root权限,即最高权限。此处是为了安全需要,考虑是否要降级,即降低权限。
-
static bool should_drop_privileges() {
-
#if defined(ALLOW_ADBD_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,
"");
-
bool adb_root = (
strcmp(value,
"1") ==
0);
-
bool adb_unroot = (
strcmp(value,
"0") ==
0);
-
// 默认debug模式不会降级,即adb有root权限
-
// ...except "adb root" lets you keep privileges in a debuggable build.
-
if (ro_debuggable && 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 */
-
}
-
void usb_init()
-
{
-
if (access(USB_FFS_ADB_EP0, F_OK) ==
0)
-
usb_ffs_init();
-
else
-
usb_adb_init();
//走此case,接下来分析此函数
-
}
-
-
继续usb_adb_init()分析...
-
-
static void usb_adb_init()
-
{
-
usb_handle* h = reinterpret_cast
(calloc(
1,
sizeof(usb_handle)));
-
if (h == nullptr) fatal(
"couldn't allocate usb_handle");
-
-
h->write = usb_adb_write;
-
h->read = usb_adb_read;
-
h->kick = usb_adb_kick;
-
h->fd =
-1;
-
-
adb_cond_init(&h->notify,
0);
-
adb_mutex_init(&h->
lock,
0);
-
-
// Open the file /dev/android_adb_enable to trigger
-
// the enabling of the adb USB function in the kernel.
-
// We never touch this file again - just leave it open
-
// indefinitely so the kernel will know when we are running
-
// and when we are not.
-
// 打开android_adb_enable节点,即enable adb usb
-
int fd = unix_open(
"/dev/android_adb_enable", O_RDWR);
-
if (fd <
0) {
-
D(
"failed to open /dev/android_adb_enable\n");
-
}
else {
-
close_on_exec(fd);
-
}
-
-
D(
"[ usb_init - starting thread ]\n");
-
adb_thread_t tid;
-
if(adb_thread_create(&tid, usb_adb_open_thread, h)){
//接下来分析此函数
-
fatal_errno(
"cannot create usb thread");
-
}
-
}
-
-
继续usb_adb_open_thread()分析...
-
-
static
void *usb_adb_open_thread(
void *x)
-
{
-
struct usb_handle *usb = (
struct usb_handle *)x;
-
int fd;
-
-
while (
true) {
-
// wait until the USB device needs opening
-
adb_mutex_lock(&usb->
lock);
-
while (usb->fd !=
-1)
-
adb_cond_wait(&usb->notify, &usb->
lock);
-
adb_mutex_unlock(&usb->
lock);
-
-
D(
"[ usb_thread - opening device ]\n");
-
do {
-
/* XXX use inotify? */
-
fd = unix_open(
"/dev/android_adb", O_RDWR);
//打开adb节点
-
if (fd <
0) {
-
// to support older kernels
-
fd = unix_open(
"/dev/android", O_RDWR);
-
}
-
if (fd <
0) {
-
adb_sleep_ms(
1000);
-
}
-
}
while (fd <
0);
-
D(
"[ opening device succeeded ]\n");
-
-
close_on_exec(fd);
-
usb->fd = fd;
//将adb节点赋值给usb->fd,重要!
-
-
D(
"[ usb_thread - registering device ]\n");
-
register_usb_transport(usb,
0,
0,
1);
//接下来分析此函数
-
}
-
-
// never gets here
-
return
0;
-
}
-
-
继续register_usb_transport()分析...
-
-
//transport.cpp
-
void register_usb_transport(usb_handle *usb, const char *serial, const char *devpath, unsigned writeable)
-
{
-
atransport *t = reinterpret_cast
(calloc(
1,
sizeof(atransport)));
-
if (t == nullptr) fatal(
"cannot allocate USB atransport");
-
D(
"transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb, serial ? serial :
"");
-
// 初始化atransport
-
init_usb_transport(t, usb, (writeable ? CS_OFFLINE : CS_NOPERM));
-
if(serial) {
-
t->serial = strdup(serial);
-
}
-
if(devpath) {
-
t->devpath = strdup(devpath);
-
}
-
-
adb_mutex_lock(&transport_lock);
-
t->next = &pending_list;
-
t->prev = pending_list.prev;
-
t->next->prev = t;
-
t->prev->next = t;
-
adb_mutex_unlock(&transport_lock);
-
-
register_transport(t);
//接下来分析此函数
-
}
-
-
继续register_transport(t)分析...
-
-
/* the fdevent select pump is single threaded */
-
static void register_transport(atransport *transport)
-
{
-
tmsg m;
-
m.transport = transport;
-
m.action =
1;
-
D(
"transport: %s registered\n", transport->serial);
-
//看到这个socket fd: transport_registration_send, 我们想到了1.1.1- init_transport_registration()中遗留的问题。让我们继续。。。
-
if(transport_write_action(transport_registration_send, &m)) {
-
fatal_errno(
"cannot write transport registration socket\n");
-
}
-
}
-
-
继续transport_write_action(transport_registration_send, &m)分析...
-
-
static int
-
transport_write_action(
int fd, struct tmsg* m)
-
{
-
char *p = (
char*)m;
-
int len =
sizeof(*m);
-
int r;
-
-
while(len >
0) {
-
r = adb_write(fd, p, len);
// 此处即为向transport_registration_send写数据!!!!
-
if(r >
0) {
-
len -= r;
-
p += r;
-
}
else {
-
if((r <
0) && (errno == EINTR))
continue;
-
D(
"transport_write_action: on fd %d, error %d: %s\n",
-
fd, errno, strerror(errno));
-
return
-1;
-
}
-
}
-
return
0;
-
}
-
static
void transport_registration_func(
int _fd, unsigned ev,
void *data)
-
{
-
int s[
2];
-
......
-
if(adb_socketpair(s)) {
-
fatal_errno(
"cannot open transport socketpair");
-
}
-
D(
"transport: %s socketpair: (%d,%d) starting", t->serial, s[
0], s[
1]);
-
-
t->transport_socket = s[
0];
-
t->fd = s[
1];
-
-
fdevent_install(&(t->transport_fde), t->transport_socket,transport_socket_events,t);
//重要
-
-
fdevent_set(&(t->transport_fde), FDE_READ);
-
-
// 从adb驱动的角度来看,创建adb输入通道
-
if(adb_thread_create(&input_thread_ptr, input_thread, t)){
-
fatal_errno(
"cannot create input thread");
-
}
-
-
// 从adb驱动的角度来看,创建adb输出通道
-
if(adb_thread_create(&output_thread_ptr, output_thread, t)){
-
fatal_errno(
"cannot create output thread");
-
}
-
......
-
}
后续大概流程为:
至此,adbd的主要初始化过程已分析完毕。其中最为关键的是初始化了adb驱动节点,然后创建output_thread不断的读取节点内容变化
2. adb shell流程分析
由3.1节知,output_thread从adb驱动节点读取数据后,调用write_packet(t->fd, t->serial, &p))会触发调用transport_socket_events()函数进行数据处理。
3. adb root流程分析
四、adb常用命令
adb 命令一般格式为:adb [-e | -d | -s <设备序列号>] <子命令>
-
a.device:设备正常连接
-
b.offline:连接出现异常,设备无响应
-
c.unknown:没有连接设备
-
结束 adb 服务, 启动 adb 服务,通常两个命令一起用。
-
一般在连接出现异常,使用 adb devices 未正常列出设备, 设备状态异常时使用 kill-
server,然后运行 start-
server 进行重启服务
-
打印dumpsys、dumpstate、logcat的输出,也是用于分析错误
-
输出比较多,建议重定向到一个文件中
-
adb bugreport > d:\bugreport.
log
安装应用,覆盖安装是使用 -r 选项
-
卸载应用,后面跟的参数是应用的包名,请区别于 apk 文件名
-
'-k' means keep the data and cache directories , -k 选项,卸载时保存数据和缓存目录
上述为adb程序自带的命令,与android无关,而Android系统自身的命令,实现位于system/bin(pm,am,screenrecord,getprop,input,ime,wm,settings,monkey,dumpsys,logcat,log,uiautomator等)。除此之外,就是linux自带的命令,自行查阅。
后记:因adb实际开发需要,研究了下adb源码,上述算是一个总结。本着开源的精神,大家共同进步!
参考文章:
https://blog.csdn.net/wlwl0071986/article/details/50935496
https://blog.csdn.net/qq_35970872/article/details/78912611
https://www.cnblogs.com/zzb-Dream-90Time/p/8166223.html