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

Commit e2615416 authored by Josh Gao's avatar Josh Gao
Browse files

adb: switch daemon_service_to_fd to string_view.

Test: test_adb.py
Test: test_device.py
Test: $ANDROID_HOST_OUT/nativetest64/adb_test/adb_test
Test: adb shell /data/nativetest64/adbd_test/adbd_test
Change-Id: I298517b688650c9d94bf837284e0264ca0ac6702
parent 5021cfc1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -141,7 +141,7 @@ atransport* find_emulator_transport_by_console_port(int console_port);

int service_to_fd(const char* name, atransport* transport);
#if !ADB_HOST
unique_fd daemon_service_to_fd(const char* name, atransport* transport);
unique_fd daemon_service_to_fd(std::string_view name, atransport* transport);
#endif

#if ADB_HOST
+13 −0
Original line number Diff line number Diff line
@@ -94,3 +94,16 @@ class BlockingQueue {
};

std::string GetLogFilePath();

inline std::string_view StripTrailingNulls(std::string_view str) {
    size_t n = 0;
    for (auto it = str.rbegin(); it != str.rend(); ++it) {
        if (*it != '\0') {
            break;
        }
        ++n;
    }

    str.remove_suffix(n);
    return str;
}
+62 −40
Original line number Diff line number Diff line
@@ -151,14 +151,17 @@ void reconnect_service(unique_fd fd, atransport* t) {
    kick_transport(t);
}

unique_fd reverse_service(const char* command, atransport* transport) {
unique_fd reverse_service(std::string_view command, atransport* transport) {
    // TODO: Switch handle_forward_request to std::string_view.
    std::string str(command);

    int s[2];
    if (adb_socketpair(s)) {
        PLOG(ERROR) << "cannot create service socket pair.";
        return unique_fd{};
    }
    VLOG(SERVICES) << "service socketpair: " << s[0] << ", " << s[1];
    if (!handle_forward_request(command, transport, s[1])) {
    if (!handle_forward_request(str.c_str(), transport, s[1])) {
        SendFail(s[1], "not a reverse forwarding command");
    }
    adb_close(s[1]);
@@ -167,15 +170,16 @@ unique_fd reverse_service(const char* command, atransport* transport) {

// Shell service string can look like:
//   shell[,arg1,arg2,...]:[command]
unique_fd ShellService(const std::string& args, const atransport* transport) {
unique_fd ShellService(std::string_view args, const atransport* transport) {
    size_t delimiter_index = args.find(':');
    if (delimiter_index == std::string::npos) {
        LOG(ERROR) << "No ':' found in shell service arguments: " << args;
        return unique_fd{};
    }

    const std::string service_args = args.substr(0, delimiter_index);
    const std::string command = args.substr(delimiter_index + 1);
    // TODO: android::base::Split(const std::string_view&, ...)
    std::string service_args(args.substr(0, delimiter_index));
    std::string command(args.substr(delimiter_index + 1));

    // Defaults:
    //   PTY for interactive, raw for non-interactive.
@@ -192,15 +196,15 @@ unique_fd ShellService(const std::string& args, const atransport* transport) {
            type = SubprocessType::kPty;
        } else if (arg == kShellServiceArgShellProtocol) {
            protocol = SubprocessProtocol::kShell;
        } else if (android::base::StartsWith(arg, "TERM=")) {
            terminal_type = arg.substr(5);
        } else if (arg.starts_with("TERM=")) {
            terminal_type = arg.substr(strlen("TERM="));
        } else if (!arg.empty()) {
            // This is not an error to allow for future expansion.
            LOG(WARNING) << "Ignoring unknown shell service argument: " << arg;
        }
    }

    return StartSubprocess(command.c_str(), terminal_type.c_str(), type, protocol);
    return StartSubprocess(command, terminal_type.c_str(), type, protocol);
}

static void spin_service(unique_fd fd) {
@@ -323,59 +327,77 @@ asocket* daemon_service_to_socket(std::string_view name) {
    return nullptr;
}

unique_fd daemon_service_to_fd(const char* name, atransport* transport) {
    if (!strncmp("dev:", name, 4)) {
        return unique_fd{unix_open(name + 4, O_RDWR | O_CLOEXEC)};
    } else if (!strncmp(name, "framebuffer:", 12)) {
unique_fd daemon_service_to_fd(std::string_view name, atransport* transport) {
    // Historically, we received service names as a char*, and stopped at the first NUL byte.
    // The client unintentionally sent strings with embedded NULs, which post-string_view, start
    // being interpreted as part of the string, unless we explicitly strip them.
    // Notably, shell checks that the part after "shell:" is empty to determine whether the session
    // is interactive, and {'\0'} is non-empty.
    name = StripTrailingNulls(name);

    if (name.starts_with("dev:")) {
        name.remove_prefix(strlen("dev:"));
        return unique_fd{unix_open(name, O_RDWR | O_CLOEXEC)};
    } else if (name.starts_with("framebuffer:")) {
        return create_service_thread("fb", framebuffer_service);
    } else if (!strncmp(name, "jdwp:", 5)) {
        return create_jdwp_connection_fd(atoi(name + 5));
    } else if (!strncmp(name, "shell", 5)) {
        return ShellService(name + 5, transport);
    } else if (!strncmp(name, "exec:", 5)) {
        return StartSubprocess(name + 5, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
    } else if (!strncmp(name, "sync:", 5)) {
    } else if (name.starts_with("jdwp:")) {
        name.remove_prefix(strlen("jdwp:"));
        std::string str(name);
        return create_jdwp_connection_fd(atoi(str.c_str()));
    } else if (name.starts_with("shell")) {
        name.remove_prefix(strlen("shell"));
        return ShellService(name, transport);
    } else if (name.starts_with("exec:")) {
        name.remove_prefix(strlen("exec:"));
        return StartSubprocess(std::string(name), nullptr, SubprocessType::kRaw,
                               SubprocessProtocol::kNone);
    } else if (name.starts_with("sync:")) {
        return create_service_thread("sync", file_sync_service);
    } else if (!strncmp(name, "remount:", 8)) {
        std::string options(name + strlen("remount:"));
    } else if (name.starts_with("remount:")) {
        std::string arg(name.begin() + strlen("remount:"), name.end());
        return create_service_thread("remount",
                                     std::bind(remount_service, std::placeholders::_1, options));
    } else if (!strncmp(name, "reboot:", 7)) {
        std::string arg(name + strlen("reboot:"));
                                     std::bind(remount_service, std::placeholders::_1, arg));
    } else if (name.starts_with("reboot:")) {
        std::string arg(name.begin() + strlen("reboot:"), name.end());
        return create_service_thread("reboot",
                                     std::bind(reboot_service, std::placeholders::_1, arg));
    } else if (!strncmp(name, "root:", 5)) {
    } else if (name.starts_with("root:")) {
        return create_service_thread("root", restart_root_service);
    } else if (!strncmp(name, "unroot:", 7)) {
    } else if (name.starts_with("unroot:")) {
        return create_service_thread("unroot", restart_unroot_service);
    } else if (!strncmp(name, "backup:", 7)) {
        return StartSubprocess(
                android::base::StringPrintf("/system/bin/bu backup %s", (name + 7)).c_str(),
                nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
    } else if (!strncmp(name, "restore:", 8)) {
    } else if (name.starts_with("backup:")) {
        name.remove_prefix(strlen("backup:"));
        std::string cmd = "/system/bin/bu backup ";
        cmd += name;
        return StartSubprocess(cmd, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
    } else if (name.starts_with("restore:")) {
        return StartSubprocess("/system/bin/bu restore", nullptr, SubprocessType::kRaw,
                               SubprocessProtocol::kNone);
    } else if (!strncmp(name, "tcpip:", 6)) {
    } else if (name.starts_with("tcpip:")) {
        name.remove_prefix(strlen("tcpip:"));
        std::string str(name);

        int port;
        if (sscanf(name + 6, "%d", &port) != 1) {
        if (sscanf(str.c_str(), "%d", &port) != 1) {
            return unique_fd{};
        }
        return create_service_thread("tcp",
                                     std::bind(restart_tcp_service, std::placeholders::_1, port));
    } else if (!strncmp(name, "usb:", 4)) {
    } else if (name.starts_with("usb:")) {
        return create_service_thread("usb", restart_usb_service);
    } else if (!strncmp(name, "reverse:", 8)) {
        return reverse_service(name + 8, transport);
    } else if (!strncmp(name, "disable-verity:", 15)) {
    } else if (name.starts_with("reverse:")) {
        name.remove_prefix(strlen("reverse:"));
        return reverse_service(name, transport);
    } else if (name.starts_with("disable-verity:")) {
        return create_service_thread("verity-on", std::bind(set_verity_enabled_state_service,
                                                            std::placeholders::_1, false));
    } else if (!strncmp(name, "enable-verity:", 15)) {
    } else if (name.starts_with("enable-verity:")) {
        return create_service_thread("verity-off", std::bind(set_verity_enabled_state_service,
                                                             std::placeholders::_1, true));
    } else if (!strcmp(name, "reconnect")) {
    } else if (name == "reconnect") {
        return create_service_thread(
                "reconnect", std::bind(reconnect_service, std::placeholders::_1, transport));
    } else if (!strcmp(name, "spin")) {
    } else if (name == "spin") {
        return create_service_thread("spin", spin_service);
    }

+8 −9
Original line number Diff line number Diff line
@@ -140,8 +140,8 @@ bool CreateSocketpair(unique_fd* fd1, unique_fd* fd2) {

class Subprocess {
  public:
    Subprocess(const std::string& command, const char* terminal_type,
               SubprocessType type, SubprocessProtocol protocol);
    Subprocess(std::string command, const char* terminal_type, SubprocessType type,
               SubprocessProtocol protocol);
    ~Subprocess();

    const std::string& command() const { return command_; }
@@ -191,9 +191,9 @@ class Subprocess {
    DISALLOW_COPY_AND_ASSIGN(Subprocess);
};

Subprocess::Subprocess(const std::string& command, const char* terminal_type,
                       SubprocessType type, SubprocessProtocol protocol)
    : command_(command),
Subprocess::Subprocess(std::string command, const char* terminal_type, SubprocessType type,
                       SubprocessProtocol protocol)
    : command_(std::move(command)),
      terminal_type_(terminal_type ? terminal_type : ""),
      type_(type),
      protocol_(protocol) {
@@ -745,14 +745,13 @@ static unique_fd ReportError(SubprocessProtocol protocol, const std::string& mes
    return read;
}

unique_fd StartSubprocess(const char* name, const char* terminal_type, SubprocessType type,
unique_fd StartSubprocess(std::string name, const char* terminal_type, SubprocessType type,
                          SubprocessProtocol protocol) {
    D("starting %s subprocess (protocol=%s, TERM=%s): '%s'",
      type == SubprocessType::kRaw ? "raw" : "PTY",
      protocol == SubprocessProtocol::kNone ? "none" : "shell",
      terminal_type, name);
      protocol == SubprocessProtocol::kNone ? "none" : "shell", terminal_type, name.c_str());

    auto subprocess = std::make_unique<Subprocess>(name, terminal_type, type, protocol);
    auto subprocess = std::make_unique<Subprocess>(std::move(name), terminal_type, type, protocol);
    if (!subprocess) {
        LOG(ERROR) << "failed to allocate new subprocess";
        return ReportError(protocol, "failed to allocate new subprocess");
+3 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

#pragma once

#include <string>

#include "adb_unique_fd.h"

enum class SubprocessType {
@@ -32,5 +34,5 @@ enum class SubprocessProtocol {
// shell is started, otherwise |name| is executed non-interactively.
//
// Returns an open FD connected to the subprocess or -1 on failure.
unique_fd StartSubprocess(const char* name, const char* terminal_type, SubprocessType type,
unique_fd StartSubprocess(std::string name, const char* terminal_type, SubprocessType type,
                          SubprocessProtocol protocol);