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

Commit 82834f12 authored by Songchun Fan's avatar Songchun Fan Committed by Gerrit Code Review
Browse files

Merge "[adb] Speed up the streaming install"

parents 6c4cfd6a 6eca0e69
Loading
Loading
Loading
Loading
+48 −26
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#include "adb_install.h"

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -40,18 +41,31 @@
static constexpr int kFastDeployMinApi = 24;
#endif

namespace {

enum InstallMode {
    INSTALL_DEFAULT,
    INSTALL_PUSH,
    INSTALL_STREAM,
};

}

static bool can_use_feature(const char* feature) {
    FeatureSet features;
    std::string error;
    if (!adb_get_feature_set(&features, &error)) {
        fprintf(stderr, "error: %s\n", error.c_str());
        return true;
        return false;
    }
    return CanUseFeature(features, feature);
}

static bool use_legacy_install() {
    return !can_use_feature(kFeatureCmd);
static InstallMode best_install_mode() {
    if (can_use_feature(kFeatureCmd)) {
        return INSTALL_STREAM;
    }
    return INSTALL_PUSH;
}

static bool is_apex_supported() {
@@ -112,7 +126,7 @@ static int uninstall_app_legacy(int argc, const char** argv) {
}

int uninstall_app(int argc, const char** argv) {
    if (use_legacy_install()) {
    if (best_install_mode() == INSTALL_PUSH) {
        return uninstall_app_legacy(argc, argv);
    }
    return uninstall_app_streamed(argc, argv);
@@ -200,32 +214,49 @@ static int install_app_streamed(int argc, const char** argv, bool use_fastdeploy
            return 1;
        }

#ifdef __linux__
        posix_fadvise(local_fd.get(), 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
#endif

        const bool use_abb = can_use_feature(kFeatureAbb);
        std::string error;
        std::string cmd = "exec:cmd package";
        std::vector<std::string> cmd_args = {use_abb ? "package" : "exec:cmd package"};
        cmd_args.reserve(argc + 3);

        // don't copy the APK name, but, copy the rest of the arguments as-is
        while (argc-- > 1) {
            cmd += " " + escape_arg(std::string(*argv++));
            if (use_abb) {
                cmd_args.push_back(*argv++);
            } else {
                cmd_args.push_back(escape_arg(*argv++));
            }
        }

        // add size parameter [required for streaming installs]
        // do last to override any user specified value
        cmd += " " + android::base::StringPrintf("-S %" PRIu64, static_cast<uint64_t>(sb.st_size));
        cmd_args.push_back("-S");
        cmd_args.push_back(
                android::base::StringPrintf("%" PRIu64, static_cast<uint64_t>(sb.st_size)));

        if (is_apex) {
            cmd += " --apex";
            cmd_args.push_back("--apex");
        }

        unique_fd remote_fd(adb_connect(cmd, &error));
        unique_fd remote_fd;
        if (use_abb) {
            remote_fd = send_abb_exec_command(cmd_args, &error);
        } else {
            remote_fd.reset(adb_connect(android::base::Join(cmd_args, " "), &error));
        }
        if (remote_fd < 0) {
            fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
            return 1;
        }

        char buf[BUFSIZ];
        copy_to_file(local_fd.get(), remote_fd.get());
        read_status_line(remote_fd.get(), buf, sizeof(buf));

        char buf[BUFSIZ];
        read_status_line(remote_fd.get(), buf, sizeof(buf));
        if (!strncmp("Success", buf, 7)) {
            fputs(buf, stdout);
            return 0;
@@ -256,8 +287,7 @@ static int install_app_legacy(int argc, const char** argv, bool use_fastdeploy,

    int result = -1;
    std::vector<const char*> apk_file = {argv[last_apk]};
    std::string apk_dest =
            "/data/local/tmp/" + android::base::Basename(argv[last_apk]);
    std::string apk_dest = "/data/local/tmp/" + android::base::Basename(argv[last_apk]);

    if (use_fastdeploy == true) {
#if defined(ENABLE_FASTDEPLOY)
@@ -292,11 +322,7 @@ cleanup_apk:

int install_app(int argc, const char** argv) {
    std::vector<int> processedArgIndicies;
    enum installMode {
        INSTALL_DEFAULT,
        INSTALL_PUSH,
        INSTALL_STREAM
    } installMode = INSTALL_DEFAULT;
    InstallMode installMode = INSTALL_DEFAULT;
    bool use_fastdeploy = false;
    bool is_reinstall = false;
    bool use_localagent = false;
@@ -337,14 +363,10 @@ int install_app(int argc, const char** argv) {
    }

    if (installMode == INSTALL_DEFAULT) {
        if (use_legacy_install()) {
            installMode = INSTALL_PUSH;
        } else {
            installMode = INSTALL_STREAM;
        }
        installMode = best_install_mode();
    }

    if (installMode == INSTALL_STREAM && use_legacy_install() == true) {
    if (installMode == INSTALL_STREAM && best_install_mode() == INSTALL_PUSH) {
        error_exit("Attempting to use streaming install on unsupported device");
    }

@@ -420,7 +442,7 @@ int install_multiple_app(int argc, const char** argv) {
    if (first_apk == -1) error_exit("need APK file on command line");

    std::string install_cmd;
    if (use_legacy_install()) {
    if (best_install_mode() == INSTALL_PUSH) {
        install_cmd = "exec:pm";
    } else {
        install_cmd = "exec:cmd package";
@@ -545,7 +567,7 @@ int install_multi_package(int argc, const char** argv) {

    if (first_package == -1) error_exit("need APK or APEX files on command line");

    if (use_legacy_install()) {
    if (best_install_mode() == INSTALL_PUSH) {
        fprintf(stderr, "adb: multi-package install is not supported on this device\n");
        return EXIT_FAILURE;
    }
+1 −1
Original line number Diff line number Diff line
@@ -357,7 +357,7 @@ static void stdinout_raw_epilogue(int inFd, int outFd, int old_stdin_mode, int o
}

void copy_to_file(int inFd, int outFd) {
    std::vector<char> buf(32 * 1024);
    std::vector<char> buf(64 * 1024);
    int len;
    long total = 0;
    int old_stdin_mode = -1;
+17 −0
Original line number Diff line number Diff line
@@ -17,7 +17,11 @@
#ifndef COMMANDLINE_H
#define COMMANDLINE_H

#include <android-base/strings.h>

#include "adb.h"
#include "adb_client.h"
#include "adb_unique_fd.h"

// Callback used to handle the standard streams (stdout and stderr) sent by the
// device's upon receiving a command.
@@ -105,4 +109,17 @@ int send_shell_command(
        const std::string& command, bool disable_shell_protocol = false,
        StandardStreamsCallbackInterface* callback = &DEFAULT_STANDARD_STREAMS_CALLBACK);

// Connects to the device "abb" service with |command| and returns the fd.
template <typename ContainerT>
unique_fd send_abb_exec_command(const ContainerT& command_args, std::string* error) {
    std::string service_string = "abb_exec:" + android::base::Join(command_args, ABB_ARG_DELIMETER);

    unique_fd fd(adb_connect(service_string, error));
    if (fd < 0) {
        fprintf(stderr, "adb: failed to run abb_exec. Error: %s\n", error->c_str());
        return unique_fd{};
    }
    return fd;
}

#endif  // COMMANDLINE_H
+8 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include "adb_io.h"
#include "adb_utils.h"
#include "shell_service.h"
#include "sysdeps.h"

namespace {

@@ -69,6 +70,11 @@ std::vector<std::string_view> parseCmdArgs(std::string_view args) {
}  // namespace

static int execCmd(std::string_view args, borrowed_fd in, borrowed_fd out, borrowed_fd err) {
    int max_buf = LINUX_MAX_SOCKET_SIZE;
    adb_setsockopt(in, SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(max_buf));
    adb_setsockopt(out, SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(max_buf));
    adb_setsockopt(err, SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(max_buf));

    AdbFdTextOutput oin(out);
    AdbFdTextOutput oerr(err);
    return cmdMain(parseCmdArgs(args), oin, oerr, in.get(), out.get(), err.get(),
@@ -98,6 +104,8 @@ int main(int argc, char* const argv[]) {
        }

        unique_fd result = StartCommandInProcess(std::string(name), &execCmd, protocol);
        int max_buf = LINUX_MAX_SOCKET_SIZE;
        adb_setsockopt(result, SOL_SOCKET, SO_SNDBUF, &max_buf, sizeof(max_buf));
        if (android::base::SendFileDescriptors(fd, "", 1, result.get()) != 1) {
            PLOG(ERROR) << "Failed to send an inprocess fd for command: " << data;
            break;
+1 −2
Original line number Diff line number Diff line
@@ -53,14 +53,13 @@ unique_fd AbbProcess::sendCommand(std::string_view command) {
            return error_fd;
        }

        if (!SendProtocolString(socket_fd_, std::string(command))) {
        if (!SendProtocolString(socket_fd_, command)) {
            PLOG(ERROR) << "failed to send command to abb";
            socket_fd_.reset();
            continue;
        }

        unique_fd fd;
        std::string error;
        char buf;
        if (android::base::ReceiveFileDescriptors(socket_fd_, &buf, 1, &fd) != 1) {
            PLOG(ERROR) << "failed to receive FD from abb";