ADB summary of Android
The contents of this paper are as follows:
1. makefile analysis and summary
2. Introduction to adb framework
3. adbd source code analysis
3.1} adbd initialization process analysis
3.2 # adb # shell process analysis
3.3 # adb # root process analysis
4. adb common commands
1, makefile analysis and summary
// The following is an excerpt from android/ system/core/adb/Android.mk # Copyright 2005 The Android Open Source Project # # Android.mk for adb # LOCAL_PATH:= $(call my-dir) // Using HOST_OS macro is compatible with different PC operating systems, such as windows, linux, mac, etc. 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 // Compile and generate libadbd static library for use by adbd deamon process 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) // Compile and generate libadb dynamic library for pc adb executable 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 // Compile the test program to generate 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) // Compile the test program to generate 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) // Compile and generate ADB_ device_ Test program of tracker service 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 \ // Compile and generate the adb executable file on the PC side, which is located in the SDK / platform tools / adb directory 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 \ // AUTH certification is not required in engineer mode 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 // Compile and generate the adbd daemon process on the device side or simulator side 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)
Summary of key points:
be-all adb Procedure( PC End and device end) share a set of codes, only with the help of HOST_OS This macro is isolated, and two executable files will be generated during compilation: 1.adb/adb.exe: Run on PC end(include Windows,Linux,MacOS And other operating systems),be located platform/tools/adb Directory, through adb Commands can evoke. 2.adbd: Run on Android On the device, it starts automatically when it is turned on. Accordingly, the source code will also be ADB_HOST Macros are used to distinguish local hosts(adb)And target machine(adbd). Engineer Defined in mode ALLOW_ADBD_NO_AUTH,It will be used in the source code.
2, Introduction to adb framework
ADB It is the abbreviation of "Android Debug Bridge", which is essentially a command line tool based on "C/S" architecture. The whole ADB module consists of the following parts (see system / core / ADB / overviews.txt and transports.txt for details):
- The # ADB # server(adb): a background application running on the PC side, which is used to detect the connection or removal of Android # devices, and then maintain the device status list. In addition, ADB # Server will also be responsible for coordinating the data transmission between Client, Services and Android # devices.
- The # ADB # daemon (adbd): a background daemon running on Android # Devices or Emulator. This process is mainly used to connect to ADB} Server and provide some services for ADB} clients through USB (or TCP).
- The ADB command line client: the terminal that executes the ADB command. Specifically, it will connect to the ADB server and send a request command to the ADB server. If it is found that the ADB server is not started, it will automatically wake up the ADB server
- Services: some of The capabilities of ADB can be abstracted into services for The # ADB # command line # client to access. It can be divided into Host services and Local services, which are briefly described as follows:
a) Host Services: Run on ADB Server,No and devices Data exchange. Typical is execution adb devices Command, just adb server The client returns the current adb devices The status of. b)Local Services: Run on adbd Daemons, ADB Server Responsible for establishing adb clients and Local Services And transparently transmit data.
Note: This article only analyzes the implementation of ADBD.
3, adbd source code analysis
- adbd initialization process analysis
ADB is divided into two modes: USB ADB and wifi ADB. They are mutually exclusive. USB ADB is used by default If you want to start wifi # ADB by default, you need to set the property service adb. tcp. The port value is 55555, and then restart adbd. ADB daemon(usb adb.) The main steps of program startup are shown in the figure below.
The description is as follows:
- DEFAULT_ADB_PORT is the port number of adb} server. It is defined as follows. The general value is 5037. Sometimes the ADB on the PC cannot be used, which may be because the port has been occupied by mobile assistants such as Tencent.
#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
- 1.1.1-init_ transport_ The analysis of registration() is as follows:
void init_transport_registration( void) { int s[ 2]; // Create two-way communication pipeline, full duplex if( adb_socketpair(s)){ fatal_errno( "cannot open transport registration socketpair"); } D( "socketpair: (%d,%d)", s[ 0], s[ 1]); transport_registration_send = s[ 0]; // send data transport_registration_recv = s[ 1]; // receive data // transport_ registration_ After recv receives data, it will trigger transport_registration_func execution fdevent_install(&transport_registration_fde, transport_registration_recv, transport_registration_func, // This function is very heavy!! 0); fdevent_set(&transport_registration_fde, FDE_READ); }
Therefore, we need to analyze transport next_ registration_ Recv will receive data, i.e. transport_ registration_ When will send send data.
- 1.1.2-adbd_cloexec_auth_socket() is analyzed as follows:
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); }
- 1.1.3-should_drop_privileges() is analyzed as follows:
// adbd defaults to root permission, that is, the highest permission. This is for security needs. Consider whether to downgrade, that is, reduce permissions. static bool should_drop_privileges() { #if defined(ALLOW_ADBD_ROOT) char value[PROPERTY_VALUE_MAX]; // The simulator is not degraded // 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); // The default debug mode will not be degraded, that is, adb has root permission // ...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 */ }
- 1.1.4-usb_init() analysis is as follows:
void usb_init() { if (access(USB_FFS_ADB_EP0, F_OK) == 0) usb_ffs_init(); else usb_adb_init(); //Take this case, and then analyze this function } continue usb_adb_init()analysis... static void usb_adb_init() { usb_handle* h = reinterpret_cast<usb_handle*>(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. // Open android_adb_enable node, i.e. 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)){ //Next, analyze this function fatal_errno( "cannot create usb thread"); } } continue usb_adb_open_thread()analysis... 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); //Open adb node 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; //Assign the adb node to USB - > FD, which is important! D( "[ usb_thread - registering device ]\n"); register_usb_transport(usb, 0, 0, 1); //Next, analyze this function } // never gets here return 0; } continue register_usb_transport()analysis... //transport.cpp void register_usb_transport(usb_handle *usb, const char *serial, const char *devpath, unsigned writeable) { atransport *t = reinterpret_cast<atransport*>(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 : ""); // Initialize atlansport 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); //Next, analyze this function } continue register_transport(t)analysis... /* 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); //See this socket fd: transport_registration_send, we thought of 1.1.1 - init_ transport_ Problems left in registration(). Let's continue... if(transport_write_action(transport_registration_send, &m)) { fatal_errno( "cannot write transport registration socket\n"); } } continue transport_write_action(transport_registration_send, &m)analysis... 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); // Here is to transport_registration_send write data!!!! 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; }
- Transport will then be called_ registration_ func(int _fd, unsigned ev, void *data)
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); //important fdevent_set(&(t->transport_fde), FDE_READ); // From the perspective of adb driver, create adb input channel if(adb_thread_create(&input_thread_ptr, input_thread, t)){ fatal_errno( "cannot create input thread"); } // From the perspective of adb driver, create adb output channel if(adb_thread_create(&output_thread_ptr, output_thread, t)){ fatal_errno( "cannot create output thread"); } ...... }
The follow-up process is as follows:
So far, the main initialization process of adbd has been analyzed. The key is to initialize the adb driver node and then create the output_thread constantly reads the changes of node content
2. adb} shell process analysis
According to Section 3.1, output_thread reads the data from the adb driver node and calls write_. Packet (T - > FD, T - > serial, & P)) triggers the call to transport_ socket_ The events () function performs data processing.
3. adb# root process analysis
4, adb common commands
The general format of adb command is: adb [- e | - d | - s < device serial number >] < subcommand >
- adb} version to view the adb version
- ADB # tcpip # 5555, set the attribute ersist adb. tcp. Port = 5555, restart adbd and enter ADB # wifi mode.
- adb devices to get the device list and device status
a.device: The equipment is connected normally b.offline: The connection is abnormal and the device is not responding c.unknown: No device connected
- adb # get state: get the status of the device. The status of the device includes # 3 # minutes, device, offline and unknown
- adb kill-server , adb start-server
end adb Service, start adb Service, usually two commands are used together. Generally, when an exception occurs in the connection, use adb devices The equipment is not listed normally, and it is used when the equipment status is abnormal kill- server,Then run start- server Restart service
- adb # logcat, print the system log of # Android #
- adb bugreport
Print dumpsys,dumpstate,logcat The output of is also used to analyze errors There is a lot of output. It is recommended to redirect to a file adb bugreport > d:\bugreport. log
- adb install
Install the application, overwrite the installation is to use -r option
- adb uninstall
Uninstall the application. The following parameter is the package name of the application. Please distinguish it from apk file name '-k' means keep the data and cache directories , -k Option to save data and cache directory when uninstalling
- adb # pull to copy the files or folders on the # Android # device to the local
- adb # push, push local files to # Android # devices
- adb , root, adb , remount, obtain , root , permission and mount the system file system in the read-write state
- adb # reboot, restart # Android # device
- adb # reboot # loader, restart the device and enter # fastboot # mode, the same as the # adb # reboot bootloader # command
- adb # reboot # recovery, restart the device and enter # recovery # mode
- adb connect <device-ip-address>/adb disconnect <device-ip-address>
The above commands are built-in commands of the adb program and have nothing to do with Android. The commands of the Android system are implemented in system/bin (pm, am, screenrecord, getprop, input, ime, wm, settings, monkey, dumpsys, logcat, log, uiautomator, etc.). In addition, it is the command that comes with linux. Check it yourself.
Postscript: due to the actual development needs of adb, I studied the adb source code. The above is a summary. In the spirit of open source, we will make progress together!
Reference article:
https://blog.csdn.net/wlwl0071986/article/details/50935496