日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

adb android源码分析,Android Adb 源码解析(base on Android 9.0)

發布時間:2024/7/23 Android 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 adb android源码分析,Android Adb 源码解析(base on Android 9.0) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Adb 框架

Adb架構

Android Adb 一共分為三個部分:adb、adb server、adbd,源碼路徑:system?/?core?/?adb。

adb和adb server 是運行在PC端,adb就是大家所熟悉的控制臺命令adb,adb server是由adb fork出的一個常駐后臺的子進程大家再看到

* daemon not running. starting it now on port 5037 *

* daemon started successfully *

的時候就是adb在啟動 adb server,adb與adb server 通過local socket進行通信。

adbd運行在Android端,是在內核初始化完畢之后,init進程啟動

service adbd /sbin/adbd --root_seclabel=u:r:su:s0 --device_banner=recovery

disabled

socket adbd stream 660 system system

seclabel u:r:adbd:s0

adbd是一個linux程序,不依賴Android framework,通過tcp或者usb與PC端的adb server通信,調用logcat shell 等等程序實現各種功能。

1. 初始化

adbd main 入口在system?/?core?/?adb/daemon/main.cpp中,main函數獲取selinux標簽、banner名稱、版本信息參數以及設置一些調試信息后,調用adbd_main函數:

int adbd_main(int server_port) {

umask(0);

signal(SIGPIPE, SIG_IGN);

init_transport_registration();

// We need to call this even if auth isn't enabled because the file

// descriptor will always be open.

adbd_cloexec_auth_socket();

if (ALLOW_ADBD_NO_AUTH && !android::base::GetBoolProperty("ro.adb.secure", false)) {

auth_required = false;

}

adbd_auth_init();

// Our external storage path may be different than apps, since

// we aren't able to bind mount after dropping root.

const char* adb_external_storage = getenv("ADB_EXTERNAL_STORAGE");

if (adb_external_storage != nullptr) {

setenv("EXTERNAL_STORAGE", adb_external_storage, 1);

} else {

D("Warning: ADB_EXTERNAL_STORAGE is not set. Leaving EXTERNAL_STORAGE"

" unchanged.\n");

}

drop_privileges(server_port);

bool is_usb = false;

if (access(USB_FFS_ADB_EP0, F_OK) == 0) {

// Listen on USB.

usb_init();

is_usb = true;

}

// If one of these properties is set, also listen on that port.

// If one of the properties isn't set and we couldn't listen on usb, listen

// on the default port.

std::string prop_port = android::base::GetProperty("service.adb.tcp.port", "");

if (prop_port.empty()) {

prop_port = android::base::GetProperty("persist.adb.tcp.port", "");

}

int port;

if (sscanf(prop_port.c_str(), "%d", &port) == 1 && port > 0) {

D("using port=%d", port);

// Listen on TCP port specified by service.adb.tcp.port property.

setup_port(port);

} else if (!is_usb) {

// Listen on default port.

setup_port(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);

}

D("adbd_main(): pre init_jdwp()");

init_jdwp();

D("adbd_main(): post init_jdwp()");

D("Event loop starting");

fdevent_loop();

return 0;

}

init_transport_registration 函數完成adbd接受PC端adb server連接功能的初始化工作

adbd_auth_init 函數負責完成對連入的PC端身份驗證功能的初始化工作

drop_privileges 函數負責是否要去掉adbd的root權限,降級為shell權限

usb_init 如果可以usb調試,初始化usb,等待連接

setup_port 如果開啟了網絡調試,初始化端口,等待連接

init_jdwp 初始化 java 調試框架

fdevent_loop 對監聽的fd進行消息處理(死循環)

這里我們重點看一下 init_transport_registration 函數

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];

fdevent_install(&transport_registration_fde, transport_registration_recv,

transport_registration_func, 0);

fdevent_set(&transport_registration_fde, FDE_READ);

}

通過adb_socketpair 函數建立了一個管道,并且把管道的一頭放入fdevent中進行讀監聽,當有數據可讀時候調用transport_registration_func 函數

static void transport_registration_func(int _fd, unsigned ev, void* data) {

tmsg m;

int s[2];

atransport* t;

if (!(ev & FDE_READ)) {

return;

}

if (transport_read_action(_fd, &m)) {

fatal_errno("cannot read transport registration socket");

}

t = m.transport;

if (m.action == 0) {

D("transport: %s removing and free'ing %d", t->serial, t->transport_socket);

/* IMPORTANT: the remove closes one half of the

** socket pair. The close closes the other half.

*/

fdevent_remove(&(t->transport_fde));

adb_close(t->fd);

{

std::lock_guard<:recursive_mutex> lock(transport_lock);

transport_list.remove(t);

}

if (t->product) free(t->product);

if (t->serial) free(t->serial);

if (t->model) free(t->model);

if (t->device) free(t->device);

if (t->devpath) free(t->devpath);

delete t;

update_transports();

return;

}

/* don't create transport threads for inaccessible devices */

if (t->GetConnectionState() != kCsNoPerm) {

/* initial references are the two threads */

t->ref_count = 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);

std::thread(write_transport_thread, t).detach();

std::thread(read_transport_thread, t).detach();

}

{

std::lock_guard<:recursive_mutex> lock(transport_lock);

pending_list.remove(t);

transport_list.push_front(t);

}

update_transports();

}

1.建立連接(adb connect ip舉例)

adb入口函數system?/?core?/?adb/client/main.cpp,在啟動時候會調用adb_commandline函數,如果命令能adb進程處理就直接處理返回,如果不能處理則嘗試連接adb server,adb server如果未啟動則fork出adb server

調用adb_server_main 完成各種初始化工作(類似adbd初始化),adb server啟動后發起命令"host:connect:"經過smart_socket_enqueue 最終調用

else if (!strncmp(name, "connect:", 8)) {

char* host = strdup(name + 8);

int fd = create_service_thread("connect", connect_service, host);

if (fd == -1) {

free(host);

}

return create_local_socket(fd);

}

調用

void connect_device(const std::string& address, std::string* response) {

if (address.empty()) {

*response = "empty address";

return;

}

std::string serial;

std::string host;

int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;

if (!android::base::ParseNetAddress(address, &host, &port, &serial, response)) {

return;

}

std::string error;

int fd = network_connect(host.c_str(), port, SOCK_STREAM, 10, &error);

if (fd == -1) {

*response = android::base::StringPrintf("unable to connect to %s: %s",

serial.c_str(), error.c_str());

return;

}

D("client: connected %s remote on fd %d", serial.c_str(), fd);

close_on_exec(fd);

disable_tcp_nagle(fd);

// Send a TCP keepalive ping to the device every second so we can detect disconnects.

if (!set_tcp_keepalive(fd, 1)) {

D("warning: failed to configure TCP keepalives (%s)", strerror(errno));

}

int ret = register_socket_transport(fd, serial.c_str(), port, 0);

if (ret < 0) {

adb_close(fd);

*response = android::base::StringPrintf("already connected to %s", serial.c_str());

} else {

*response = android::base::StringPrintf("connected to %s", serial.c_str());

}

}

至此通過network_connect發起tcp連接請求并返回fd通過register_socket_transport注冊到transport列表中。

而adbd端

static void server_socket_thread(int port) {

int serverfd, fd;

adb_thread_setname("server socket");

D("transport: server_socket_thread() starting");

serverfd = -1;

for(;;) {

if(serverfd == -1) {

std::string error;

serverfd = network_inaddr_any_server(port, SOCK_STREAM, &error);

if(serverfd < 0) {

D("server: cannot bind socket yet: %s", error.c_str());

std::this_thread::sleep_for(1s);

continue;

}

close_on_exec(serverfd);

}

D("server: trying to get new connection from %d", port);

fd = adb_socket_accept(serverfd, nullptr, nullptr);

if(fd >= 0) {

D("server: new connection on fd %d", fd);

close_on_exec(fd);

disable_tcp_nagle(fd);

std::string serial = android::base::StringPrintf("host-%d", fd);

if (register_socket_transport(fd, serial.c_str(), port, 1) != 0) {

adb_close(fd);

}

}

}

D("transport: server_socket_thread() exiting");

}

接收到TCP連接請求,調用register_transport函數

至此adb server和adbd物理連接建立完成

2. 消息流轉

當register_transport函數被調用,管道一端被寫入tmsg消息

static void register_transport(atransport* transport) {

tmsg m;

m.transport = transport;

m.action = 1;

D("transport: %s registered", transport->serial);

if (transport_write_action(transport_registration_send, &m)) {

fatal_errno("cannot write transport registration socket\n");

}

}

觸發transport_registration_func 函數從管道另一端讀取tmsg消息同時再建立了一條管道和兩個線程并把tmsg中的atransport記錄到傳輸隊列中,atransport記錄了三個文件描述符 sfd、fd、transport_socket,他們的關系如圖

adbd 消息流

圖中的apacket為各種消息載體。

struct amessage {

uint32_t command; /* command identifier constant */

uint32_t arg0; /* first argument */

uint32_t arg1; /* second argument */

uint32_t data_length; /* length of payload (0 is allowed) */

uint32_t data_check; /* checksum of data payload */

uint32_t magic; /* command ^ 0xffffffff */

};

struct apacket {

amessage msg;

std::string payload;

};

3. 消息處理

重點看handle_packet 函數

void handle_packet(apacket *p, atransport *t)

{

D("handle_packet() %c%c%c%c", ((char*) (&(p->msg.command)))[0],

((char*) (&(p->msg.command)))[1],

((char*) (&(p->msg.command)))[2],

((char*) (&(p->msg.command)))[3]);

print_packet("recv", p);

CHECK_EQ(p->payload.size(), p->msg.data_length);

switch(p->msg.command){

case A_SYNC:

if (p->msg.arg0){

send_packet(p, t);

#if ADB_HOST

send_connect(t);

#endif

} else {

t->SetConnectionState(kCsOffline);

handle_offline(t);

send_packet(p, t);

}

return;

case A_CNXN: // CONNECT(version, maxdata, "system-id-string")

handle_new_connection(t, p);

break;

case A_AUTH:

switch (p->msg.arg0) {

#if ADB_HOST

case ADB_AUTH_TOKEN:

if (t->GetConnectionState() == kCsOffline) {

t->SetConnectionState(kCsUnauthorized);

}

send_auth_response(p->payload.data(), p->msg.data_length, t);

break;

#else

case ADB_AUTH_SIGNATURE:

if (adbd_auth_verify(t->token, sizeof(t->token), p->payload)) {

adbd_auth_verified(t);

t->failed_auth_attempts = 0;

} else {

if (t->failed_auth_attempts++ > 256) std::this_thread::sleep_for(1s);

send_auth_request(t);

}

break;

case ADB_AUTH_RSAPUBLICKEY:

adbd_auth_confirm_key(p->payload.data(), p->msg.data_length, t);

break;

#endif

default:

t->SetConnectionState(kCsOffline);

handle_offline(t);

break;

}

break;

case A_OPEN: /* OPEN(local-id, 0, "destination") */

if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {

asocket* s = create_local_service_socket(p->payload.c_str(), t);

if (s == nullptr) {

send_close(0, p->msg.arg0, t);

} else {

s->peer = create_remote_socket(p->msg.arg0, t);

s->peer->peer = s;

send_ready(s->id, s->peer->id, t);

s->ready(s);

}

}

break;

case A_OKAY: /* READY(local-id, remote-id, "") */

if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {

asocket* s = find_local_socket(p->msg.arg1, 0);

if (s) {

if(s->peer == 0) {

/* On first READY message, create the connection. */

s->peer = create_remote_socket(p->msg.arg0, t);

s->peer->peer = s;

s->ready(s);

} else if (s->peer->id == p->msg.arg0) {

/* Other READY messages must use the same local-id */

s->ready(s);

} else {

D("Invalid A_OKAY(%d,%d), expected A_OKAY(%d,%d) on transport %s",

p->msg.arg0, p->msg.arg1, s->peer->id, p->msg.arg1, t->serial);

}

} else {

// When receiving A_OKAY from device for A_OPEN request, the host server may

// have closed the local socket because of client disconnection. Then we need

// to send A_CLSE back to device to close the service on device.

send_close(p->msg.arg1, p->msg.arg0, t);

}

}

break;

case A_CLSE: /* CLOSE(local-id, remote-id, "") or CLOSE(0, remote-id, "") */

if (t->online && p->msg.arg1 != 0) {

asocket* s = find_local_socket(p->msg.arg1, p->msg.arg0);

if (s) {

/* According to protocol.txt, p->msg.arg0 might be 0 to indicate

* a failed OPEN only. However, due to a bug in previous ADB

* versions, CLOSE(0, remote-id, "") was also used for normal

* CLOSE() operations.

*

* This is bad because it means a compromised adbd could

* send packets to close connections between the host and

* other devices. To avoid this, only allow this if the local

* socket has a peer on the same transport.

*/

if (p->msg.arg0 == 0 && s->peer && s->peer->transport != t) {

D("Invalid A_CLSE(0, %u) from transport %s, expected transport %s",

p->msg.arg1, t->serial, s->peer->transport->serial);

} else {

s->close(s);

}

}

}

break;

case A_WRTE: /* WRITE(local-id, remote-id, ) */

if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {

asocket* s = find_local_socket(p->msg.arg1, p->msg.arg0);

if (s) {

unsigned rid = p->msg.arg0;

if (s->enqueue(s, std::move(p->payload)) == 0) {

D("Enqueue the socket");

send_ready(s->id, rid, t);

}

}

}

break;

default:

printf("handle_packet: what is %08x?!\n", p->msg.command);

}

put_apacket(p);

}

這部分代碼是adb server和adbd共用的,通過ADB_HOST宏來控制是否編譯,我們先看apacket命令種類

A_SYNC 握手命令,當PC開始連接建立時交換SYNC字段,其意義類似于TCP協議的握手

A_CNXN adb server握手完成后直接發送A_CNXN 協商版本、最大負載等信息,adbd收到A_CNXN后還會判斷是夠要對adb server進行認證,認證通過之后才會發送A_CNXN 協商版本、最大負載等信息

A_AUTH adbd對adb server進行驗證

以上均完成之后,adb連接完全建立,PC端查看adb devices命令devices顯示device

A_OPEN 當需要流完成的命令(例如:logat)需要通知接收方建立一個套接字,local-id用來標識套接字

A_OKAY 通知發送方已經準備好了接收流

A_CLSE 通知接收方關閉套接字

A_WRTE 發送的流消息

再重點看一下A_OPEN流程,在接收到A_OPEN后,先創建一個本地的套接字(create_local_service_socket),成功后再創建一個遠程套接字(create_remote_socket),并關聯兩個

套接字互為peer,完成后通知遠端A_OKAY。

遠端收到A_OKAY后同時也會關聯對方的套接字。

大家可能已經看出來了,這里所謂的本地套接字遠程套接字并非真的套接字,而是通過local-id字段在邏輯上建立相關聯的一個結構(peer),具體參見sockets.cpp。

至此針對不同服務(logcat、shell等)的鏈接就建立完成了。

在services.cpp文件中

int service_to_fd(const char* name, atransport* transport) {

int ret = -1;

if (is_socket_spec(name)) {

std::string error;

ret = socket_spec_connect(name, &error);

if (ret < 0) {

LOG(ERROR) << "failed to connect to socket '" << name << "': " << error;

}

#if !ADB_HOST

} else if(!strncmp("dev:", name, 4)) {

ret = unix_open(name + 4, O_RDWR | O_CLOEXEC);

} else if(!strncmp(name, "framebuffer:", 12)) {

ret = create_service_thread("fb", framebuffer_service, nullptr);

} else if (!strncmp(name, "jdwp:", 5)) {

ret = create_jdwp_connection_fd(atoi(name+5));

} else if(!strncmp(name, "shell", 5)) {

ret = ShellService(name + 5, transport);

} else if(!strncmp(name, "exec:", 5)) {

ret = StartSubprocess(name + 5, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);

} else if(!strncmp(name, "sync:", 5)) {

ret = create_service_thread("sync", file_sync_service, nullptr);

} else if(!strncmp(name, "remount:", 8)) {

ret = create_service_thread("remount", remount_service, nullptr);

} else if(!strncmp(name, "reboot:", 7)) {

void* arg = strdup(name + 7);

if (arg == NULL) return -1;

ret = create_service_thread("reboot", reboot_service, arg);

if (ret < 0) free(arg);

} else if(!strncmp(name, "root:", 5)) {

ret = create_service_thread("root", restart_root_service, nullptr);

} else if(!strncmp(name, "unroot:", 7)) {

ret = create_service_thread("unroot", restart_unroot_service, nullptr);

} else if(!strncmp(name, "backup:", 7)) {

ret = StartSubprocess(android::base::StringPrintf("/system/bin/bu backup %s",

(name + 7)).c_str(),

nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);

} else if(!strncmp(name, "restore:", 8)) {

ret = StartSubprocess("/system/bin/bu restore", nullptr, SubprocessType::kRaw,

SubprocessProtocol::kNone);

} else if(!strncmp(name, "tcpip:", 6)) {

int port;

if (sscanf(name + 6, "%d", &port) != 1) {

return -1;

}

ret = create_service_thread("tcp", restart_tcp_service, reinterpret_cast(port));

} else if(!strncmp(name, "usb:", 4)) {

ret = create_service_thread("usb", restart_usb_service, nullptr);

} else if (!strncmp(name, "reverse:", 8)) {

ret = reverse_service(name + 8, transport);

} else if(!strncmp(name, "disable-verity:", 15)) {

ret = create_service_thread("verity-on", set_verity_enabled_state_service,

reinterpret_cast(0));

} else if(!strncmp(name, "enable-verity:", 15)) {

ret = create_service_thread("verity-off", set_verity_enabled_state_service,

reinterpret_cast(1));

} else if (!strcmp(name, "reconnect")) {

ret = create_service_thread("reconnect", reconnect_service, transport);

#endif

}

if (ret >= 0) {

close_on_exec(ret);

}

return ret;

}

可以看到各種各樣的命令是如何執行的,這里命令分為兩類,一類是adbd本身可以處理的,例如adb reboot 、adb remount、adb root等等;一類是adbd不能處理的,需要通過調用StartSubprocess函數來執行其他二進制程序或者腳本來完成,例如adb logcat 、adb shell等。

總結

以上是生活随笔為你收集整理的adb android源码分析,Android Adb 源码解析(base on Android 9.0)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产成人免费 | 国产精品69久久久久孕妇欧美 | 亚洲色图p| 1000部多毛熟女毛茸茸 | 精品久久久久久一区二区里番 | 国产精品一二三区在线观看 | 亲嘴扒胸摸屁股免费视频日本网站 | 青娱乐在线视频观看 | 国产一区二区精品 | 国产精品一级二级三级 | 在线观看高h | 99cao| 亚洲欧美中文字幕 | www.com污| 看日本毛片| 国产日韩欧美在线播放 | 日韩欧美国产中文字幕 | 中国少妇做爰全过程毛片 | 欧美日韩在线中文字幕 | 美日韩免费视频 | 国产午夜片 | 巨乳动漫美女 | 亚洲精品视频专区 | 日日夜操| 97影院手机版 | 在线免费三级 | 动漫大乳美女 | 诱惑av | 男人捅爽女人 | 精品无码成人久久久久久免费 | 激情久久网 | 白洁av | av一区三区 | 午夜伦伦电影理论片费看 | 久久福利影院 | 久久精品—区二区三区舞蹈 | 亚洲精品粉嫩小泬20p | 999久久久精品视频 亚洲视频精品在线 | 实拍女处破www免费看 | 日日干夜 | 国产一区av在线 | 美日韩免费 | 极品少妇xxxx精品少妇偷拍 | 国产精品白嫩白嫩大学美女 | 亚洲国产理论 | 欧美一级色片 | 亚洲综合丁香 | 久久久国产片 | 大尺度av在线 | 一卡二卡三卡在线观看 | 丰满少妇av| 草草影院发布页 | 国内视频一区二区三区 | 逼特逼在线视频 | 成人国产精品一区 | 中文字幕黄色av | 福利小视频在线 | 激情小说五月天 | 国产一级在线 | 亚洲美免无码中文字幕在线 | 午夜在线观看av | 欧美一区免费 | 黄色网一级片 | 九九色九九 | 国产二区在线播放 | 亚洲天堂成人在线观看 | 国产九色91 | 桃色一区 | 中文字幕一区二区三区四区欧美 | 日本三级456 | 久久人妻少妇嫩草av蜜桃 | 欧美tv| 美女av网站 | 久一在线视频 | 精品欧美一区二区三区在线观看 | 五月天综合激情 | 国产99久久久国产精品成人免费 | 91视频免费观看 | 天天综合天天做天天综合 | 梦梦电影免费高清在线观看 | 午夜一区二区三区在线观看 | 亚洲色图27p | 色哟哟在线视频 | 成人1区 | 中文字幕亚洲在线观看 | 国产探花视频在线观看 | 黄色网页观看 | 毛片麻豆 | 国产小视频网址 | 性高潮视频在线观看 | 亚洲精品一二三四区 | www.天天射| 永久免费在线 | 污在线观看 | 国产肥白大熟妇bbbb视频 | 国产成人无码www免费视频播放 | 国产精品自拍偷拍视频 | 亚洲精品久久久久中文字幕二区 | 日韩在线一区二区三区四区 |