android6.0 adbd深さ分析(一)adb駆動初期化、adbノードスレッド読み出し

15901 ワード

adbdは前に一度見たことがありますが、コードが複雑すぎると感じました.それから、adb client adb server adbdが織り交ぜて疲れているように見えます.最近、プロジェクトはそれを大体見終わって、整理して、adbdから多くのことを学ぶことができるような気がします.ここでまとめて、adbdのコードです.
私は分析しただけで分かったので,すべてがそろっているはずがない.また,主に通信面や命令処理などに重点を置いている.
一、adb主関数
まず、主関数を見てみましょう.
int main(int argc, char **argv) {
#if ADB_HOST
    // adb client/server
    adb_sysdeps_init();
    adb_trace_init();
    D("Handling commandline()
"); return adb_commandline(argc - 1, const_cast(argv + 1)); #else // adbd while (true) { static struct option opts[] = { {"root_seclabel", required_argument, nullptr, 's'}, {"device_banner", required_argument, nullptr, 'b'}, {"version", no_argument, nullptr, 'v'}, }; int option_index = 0; int c = getopt_long(argc, argv, "", opts, &option_index); if (c == -1) break; switch (c) { case 's': root_seclabel = optarg; break; case 'b': adb_device_banner = optarg; break; case 'v': printf("Android Debug Bridge Daemon version %d.%d.%d %s
", ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION, ADB_REVISION); return 0; default: break; } } close_stdin(); adb_trace_init(); /* If adbd runs inside the emulator this will enable adb tracing via * adb-debug qemud service in the emulator. */ adb_qemu_trace_init(); D("Handling main()
"); return adb_main(0, DEFAULT_ADB_PORT); #endif

ADB_HOSTマクロはPC上なのか携帯電話上なのかを直接区別するために使用され、pc上の直接はadb_を使用します.commandline関数は様々なコマンドを処理して、私たちは見ないで、私たちは主にadbdを分析します.
adbdは主にadb_を呼び出したmainメソッド
int adb_main(int is_daemon, int server_port)
{
#if !ADB_HOST
    int port;
    char value[PROPERTY_VALUE_MAX];

    umask(000);
#endif

    atexit(adb_cleanup);
#if defined(_WIN32)
    SetConsoleCtrlHandler( ctrlc_handler, TRUE );
#else
    // No SIGCHLD. Let the service subproc handle its children.
    signal(SIGPIPE, SIG_IGN);
#endif

    init_transport_registration();

#if ADB_HOST
    HOST = 1;

#ifdef WORKAROUND_BUG6558362
    if(is_daemon) adb_set_affinity();
#endif
    usb_init();
adbを見てmainコードinit_を見てみましょうtransport_registration関数
void init_transport_registration(void)
{
    int s[2];

    if(adb_socketpair(s)){//socketpair
        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);
}

SOcketpairが呼び出され、一端にデータがあるとtransportが呼び出されます.registration_func関数、transport_を見てみましょう.registration_recvはデータが来るのでtransportも見てみましょうregistration_sendはいつデータを送信しますか.
二、usb、adbの駆動初期化
次にadb駆動ノードの初期化を見てみましょう
上のadbを見続けますmainのusb_init関数:
void usb_init()
{
    if (access(USB_FFS_ADB_EP0, F_OK) == 0)
        usb_ffs_init();
    else
        usb_adb_init();
}

こちらで呼び出したのは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.
    int fd = unix_open("/dev/android_adb_enable", O_RDWR);//  android_adb_enable    enableadb usb  
    if (fd < 0) {
       D("failed to open /dev/android_adb_enable
"); } else { close_on_exec(fd); } D("[ usb_init - starting thread ]
"); adb_thread_t tid; if(adb_thread_create(&tid, usb_adb_open_thread, h)){ fatal_errno("cannot create usb thread"); } }

この関数でandroidを開きます.adb_enableノードはenableadb usbにすぎず、その後スレッドを開いて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 ]
"); 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); close_on_exec(fd); usb->fd = fd;// usb D("[ usb_thread - registering device ]
"); register_usb_transport(usb, 0, 0, 1); } // never gets here return 0; }

この関数では主にadbノードを開きregister_を呼び出すusb_Transport関数はusb転送を登録します.
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')
", t, usb, serial ? serial : ""); 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); }

この関数はinit_を先に呼び出しましたusb_Transport関数はatransportを初期化しusb_handleも与えましたregisterを見てみましょうTransport関数.
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
"); } }

この関数はatransportをカプセル化して伝わりましたtransport_を見てみましょうwrite_Action関数、最初のパラメータtransport_を見てみましょう.registration_sendは私たちの前のsockpairのsend端です
transport_write_Action関数はtransportをtransport_に送ることですregistration_recv端子.
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);
        if(r > 0) {
            len -= r;
            p   += r;
        } else {
            if((r < 0) && (errno == EINTR)) continue;
            D("transport_write_action: on fd %d, error %d: %s
", fd, errno, strerror(errno)); #if !ADB_HOST __android_log_print(ANDROID_LOG_INFO, __FUNCTION__, "transport_write_action: on fd %d, error %d: %s
", fd, errno, strerror(errno)); #endif return -1; } } return 0; }

これによりadb駆動ノードが読み出されると、駆動伝送されたtransportがtransport_に伝達されるregistration_recv端子、次にこのコードを見てみましょう.
三、オープンスレッドadbデータを受け入れる
前に分析した関数を覚えていますか?transport_registration_recvにデータがある場合はtransport_が呼び出されますregistration_func関数
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);
}
transportを見てみましょうregistration_funcという関数
static void transport_registration_func(int _fd, unsigned ev, void *data)
{
    tmsg m;
    adb_thread_t output_thread_ptr;
    adb_thread_t input_thread_ptr;
    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;

まずtransportを呼び出しましたread_アクションでtransport_を読み込むregistration_recvのデータ、つまり以前のtransport_registration_sendからのadb駆動ノードのデータ.そしてtという変数に保存します.
次にtransportを見てみましょうregistration_func関数の別のコード
    if (t->connection_state != CS_NOPERM) {
        /* initial references are the two threads */
        t->ref_count = 2;

        if(adb_socketpair(s)) {//    socketpair
            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    ,  transport_socket_events  
                        transport_socket_events,
                        t);

        fdevent_set(&(t->transport_fde), FDE_READ);

        if(adb_thread_create(&input_thread_ptr, input_thread, t)){
            fatal_errno("cannot create input thread");
        }

        if(adb_thread_create(&output_thread_ptr, output_thread, t)){
            fatal_errno("cannot create output thread");
        }
    }

上のコードはsocketpairのペアを確立し、2つのスレッドを開きました.この2つのスレッドを見てみましょう.
3.1 output_thread adbドライバデータの受信
まずアウトプットを見てみましょうthreadこのスレッド:
static void *output_thread(void *_t)
{
    atransport *t = reinterpret_cast(_t);
    apacket *p;

    D("%s: starting transport output thread on fd %d, SYNC online (%d)
", t->serial, t->fd, t->sync_token + 1); p = get_apacket(); p->msg.command = A_SYNC; p->msg.arg0 = 1; p->msg.arg1 = ++(t->sync_token); p->msg.magic = A_SYNC ^ 0xffffffff; if(write_packet(t->fd, t->serial, &p)) { put_apacket(p); D("%s: failed to write SYNC packet
", t->serial); goto oops; } D("%s: data pump started
", t->serial); for(;;) { p = get_apacket();// if(t->read_from_remote(p, t) == 0){// adb if(write_packet(t->fd, t->serial, &p)){// socketpair put_apacket(p); D("%s: failed to write apacket to transport
", t->serial); goto oops; } } else { D("%s: remote read failed for transport
", t->serial); put_apacket(p);// , , break; } } D("%s: SYNC offline for transport
", t->serial); p = get_apacket(); p->msg.command = A_SYNC;// adb p->msg.arg0 = 0; p->msg.arg1 = 0; p->msg.magic = A_SYNC ^ 0xffffffff; if(write_packet(t->fd, t->serial, &p)) { put_apacket(p); D("%s: failed to write SYNC apacket to transport", t->serial); } oops: D("%s: transport output thread is exiting
", t->serial); kick_transport(t); transport_unref(t); return 0; }

このスレッドは主にadb駆動からデータを読み出し、socketpairの一端にadb駆動から読み出したデータを書き込む.
まずreadを見てみましょうfrom_remoteという関数は、adb駆動からデータを読み出す方法について説明します.
前にregister_usb_Transportの時にinitを呼び出しましたusb_transportは、transportのいくつかの関数などを初期化します.
void init_usb_transport(atransport *t, usb_handle *h, int state)
{
    D("transport: usb
"); t->close = remote_close; t->kick = remote_kick; t->read_from_remote = remote_read; t->write_to_remote = remote_write; t->sync_token = 1; t->connection_state = state; t->type = kTransportUsb; t->usb = h; #if ADB_HOST HOST = 1; #else HOST = 0; #endif }
read_from_remote関数はremote_ですread関数:
static int remote_read(apacket *p, atransport *t)
{
    if(usb_read(t->usb, &p->msg, sizeof(amessage))){//     adb      
        D("remote usb: read terminated (message)
"); return -1; } if(check_header(p)) {// D("remote usb: check_header failed
"); return -1; } if(p->msg.data_length) { if(usb_read(t->usb, p->data, p->msg.data_length)){ D("remote usb: terminated (data)
"); return -1; } } if(check_data(p)) {// D("remote usb: check_data failed
"); return -1; } return 0; }

前に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;

したがって、最後にreadが呼び出されたのはusb_です.adb_read関数、すなわちadb駆動の内容を読む.
usb_adb_read関数はadb_を呼び出すことですreadはadb駆動データを読み出し、adb_readとは、h->fdからadb駆動データを読み出すことである.このh->fdは前のusb_ですadb_open_thread関数で/dev/android_を開くadb(adb駆動ノード).
static int usb_adb_read(usb_handle *h, void *data, int len)
{
    int n;

    D("about to read (fd=%d, len=%d)
", h->fd, len); n = adb_read(h->fd, data, len); if(n != len) { D("ERROR: fd = %d, n = %d, errno = %d (%s)
", h->fd, n, errno, strerror(errno)); for (int i = 0; i < n; i++) { char print = (char)*((char*)data + i); LOG("%x ", print); } return -1; } D("[ done fd=%d ]
", h->fd); return 0; }

3.2 output_threadデータ送信後、データ処理
output_threadでadb駆動のデータを読み込んだらwrite_を呼び出すpacket(t->fd,t->serial,&p)関数は、データネットワークsocketpairの片側を書きます.
これにより、socketpairの反対側にデータがあり、反対側にtransport_が呼び出されます.socket_events関数はデータを処理します
static void transport_socket_events(int fd, unsigned events, void *_t)
{
    atransport *t = reinterpret_cast(_t);
    D("transport_socket_events(fd=%d, events=%04x,...)
", fd, events); if(events & FDE_READ){ apacket *p = 0; if(read_packet(fd, t->serial, &p)){ D("%s: failed to read packet from transport socket on fd %d
", t->serial, fd); } else { handle_packet(p, (atransport *) _t); } } }

四、まとめ
主にadb駆動ノードの初期化を解析し,駆動ノードのオンに成功するとスレッドをオンにしてadb駆動ノードの内容を読み出す.
データの処理部分は次のブログで分析を続けます.