Search code examples
androidtcpadb

“error: closed” displayed when trying to connect to Android device via adb through TCP


I'm building up Android system on a ARMv7 dev-board. For some reason I would like to use "adb shell" to manipulate the system from my PC. The dev-board and the PC are connected via Ethernet since the Android system use NFS sever as its root file system. Here's what I've tried (I have root access on the Android device):

On the Android device (accessed via serial port with putty):

android@ubuntu:~$ setprop service.adb.tcp.port 5555
android@ubuntu:~$ stop adbd
android@ubuntu:~$ start adbd

On the Ubuntu host:

android@ubuntu:~$ adb connect 192.168.0.85:5555
connected to 192.168.0.85:5555
android@ubuntu:~$ adb shell
error: closed
android@ubuntu:~$ adb devices
List of devices attached
192.168.0.85:5555       device

As the message shows, the connection via adb seems successful (connected to ...), however I can't "adb shell" to it. The most weird is that I can still see the device attached via "adb devices".

I tried to kill adb server and restart it, but it doesn't work either.


Solution

  • I studied the source code of adb, debugged with gdb and finally found the root cause.

    Basically, in order to respond to the host command adb shell, adbd (the daemon running on Android device) should open a pseudo terminal, and fork another child process for running shell. These are implemented in create_subproc_pty function in system/core/adb/services.c:

    static int create_subproc_pty(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
    {
        ....
    
        int ptm;
    
        ptm = unix_open("/dev/ptmx", O_RDWR | O_CLOEXEC); // | O_NOCTTY);
        if(ptm < 0){
            printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
            return -1;
        }
    
        ....
    
        *pid = fork();
        if(*pid < 0) {
            printf("- fork failed: %s -\n", strerror(errno));
            adb_close(ptm);
            return -1;
        }
    
        ....
    }
    

    And I found on my dev-board, the unix_open function failed. That's because PTY driver was not built into kernel, so the device /dev/ptmx is not found on the system.

    To solve this, just select Character Devices - Unix98 PTY driver and rebuild kernel, then adb shell will work.