Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cc1de48d authored by Mike Lockwood's avatar Mike Lockwood
Browse files

adb: Another attempted workaround for the adb disconnect problem.



For adb shell commands (as well as shell based commands like logcat and bugreport) we now
batch USB writes into 4K chunks instead of sending small packets of data as they come in.
A timeout prevents us from blocking for more than 100ms when our 4K buffer is partially full.

Signed-off-by: default avatarMike Lockwood <lockwood@android.com>
parent de6f62a6
Loading
Loading
Loading
Loading
+81 −11
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@
#    include <netinet/in.h>
#    include <netdb.h>
#  endif
#else
#include <sys/poll.h>
#endif

typedef struct stinfo stinfo;
@@ -196,12 +198,9 @@ static int create_service_thread(void (*func)(int, void *), void *cookie)
    return s[0];
}

#if !ADB_HOST
static int create_subprocess(const char *cmd, const char *arg0, const char *arg1)
{
#ifdef HAVE_WIN32_PROC
	fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
	return -1;
#else /* !HAVE_WIN32_PROC */
    char *devname;
    int ptm;
    pid_t pid;
@@ -244,7 +243,6 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1
                cmd, strerror(errno), errno);
        exit(-1);
    } else {
#if !ADB_HOST
        // set child's OOM adjustment to zero
        char text[64];
        snprintf(text, sizeof text, "/proc/%d/oom_adj", pid);
@@ -255,11 +253,11 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1
        } else {
           D("adb: unable to open %s\n", text);
        }
#endif

        return ptm;
    }
#endif /* !HAVE_WIN32_PROC */
}
#endif /* !ADB_HOST */

#if ADB_HOST
#define SHELL_COMMAND "/bin/sh"
@@ -267,6 +265,76 @@ static int create_subprocess(const char *cmd, const char *arg0, const char *arg1
#define SHELL_COMMAND "/system/bin/sh"
#endif

#if !ADB_HOST
static void shell_service(int s, void *command)
{
    char    buffer[MAX_PAYLOAD];
    char    buffer2[MAX_PAYLOAD];
    struct pollfd ufds[2];
    int     fd, ret = 0;
    unsigned count = 0;
    char** args = (char **)command;
    fd = create_subprocess(SHELL_COMMAND, args[0], args[1]);

    while (1) {
        while (count < sizeof(buffer)) {
            ufds[0].fd = fd;
            ufds[0].events = POLLIN | POLLHUP;
            ufds[0].revents = 0;
            ufds[1].fd = s;
            ufds[1].events = POLLIN | POLLHUP;
            ufds[1].revents = 0;
            // use a 100ms timeout so we don't block indefinitely with our
            // buffer partially filled.
            ret = poll(ufds, 2, 100);
            if (ret <= 0) {
                D("poll returned %d\n", ret);
                // file has closed or we timed out
                // set ret to 1 so we don't exit the outer loop
                ret = 1;
                break;
            }

            if (ufds[0].revents & POLLIN) {
                ret = adb_read(fd, buffer + count, sizeof(buffer) - count);
                D("read fd ret: %d, count: %d\n", ret, count);
                if (ret > 0)
                    count += ret;
                else
                    break;
            }
            if (ufds[1].revents & POLLIN) {
                ret = adb_read(s, buffer2, sizeof(buffer2));
                D("read s ret: %d\n", ret);
                if (ret > 0)
                    adb_write(fd, buffer2, ret);
                else
                    break;
            }

            if ((ufds[0].revents & POLLHUP) || (ufds[1].revents & POLLHUP)) {
                // set flag to exit after flushing the buffer
                ret = -1;
                break;
            }
        }

        D("writing: %d\n", count);
        if (count > 0) {
            adb_write(s, buffer, count);
            count = 0;
        }
        if (ret <= 0)
            break;
    }

    D("shell_service done\n");

    adb_close(fd);
    adb_close(s);
}
#endif // !ADB_HOST

int service_to_fd(const char *name)
{
    int ret = -1;
@@ -317,14 +385,16 @@ int service_to_fd(const char *name)
        ret = create_jdwp_connection_fd(atoi(name+5));
    } else if (!strncmp(name, "log:", 4)) {
        ret = create_service_thread(log_service, get_log_file_path(name + 4));
#endif
    } else if(!HOST && !strncmp(name, "shell:", 6)) {
        const char* args[2];
        if(name[6]) {
            ret = create_subprocess(SHELL_COMMAND, "-c", name + 6);
            args[0] = "-c";
            args[1] = name + 6;
        } else {
            ret = create_subprocess(SHELL_COMMAND, "-", 0);
            args[0] = "-";
            args[1] = 0;
        }
#if !ADB_HOST
        ret = create_service_thread(shell_service, (void *)args);
    } else if(!strncmp(name, "sync:", 5)) {
        ret = create_service_thread(file_sync_service, NULL);
    } else if(!strncmp(name, "remount:", 8)) {