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

Commit ea1103cb authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[adb] Fix incremental installation on Windows" into rvc-dev

parents 5a495bec c3ac339d
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -1423,13 +1423,13 @@ static bool _is_valid_ack_reply_fd(const int ack_reply_fd) {
#endif
}

static bool _is_valid_fd(int fd) {
static bool _is_valid_os_fd(int fd) {
    // Disallow invalid FDs and stdin/out/err as well.
    if (fd < 3) {
        return false;
    }
#ifdef _WIN32
    HANDLE handle = adb_get_os_handle(fd);
    auto handle = (HANDLE)fd;
    DWORD info = 0;
    if (GetHandleInformation(handle, &info) == 0) {
        return false;
@@ -2005,7 +2005,7 @@ int adb_commandline(int argc, const char** argv) {
#endif
        }
        int connection_fd = atoi(argv[1]);
        if (!_is_valid_fd(connection_fd)) {
        if (!_is_valid_os_fd(connection_fd)) {
            error_exit("Invalid connection_fd number given: %d", connection_fd);
        }

@@ -2013,7 +2013,7 @@ int adb_commandline(int argc, const char** argv) {
        close_on_exec(connection_fd);

        int output_fd = atoi(argv[2]);
        if (!_is_valid_fd(output_fd)) {
        if (!_is_valid_os_fd(output_fd)) {
            error_exit("Invalid output_fd number given: %d", output_fd);
        }
        output_fd = adb_register_socket(output_fd);
+6 −4
Original line number Diff line number Diff line
@@ -41,8 +41,7 @@ using Size = int64_t;

static inline int32_t read_int32(borrowed_fd fd) {
    int32_t result;
    ReadFully(fd, &result, sizeof(result));
    return result;
    return ReadFdExactly(fd, &result, sizeof(result)) ? result : -1;
}

static inline void append_int(borrowed_fd fd, std::vector<char>* bytes) {
@@ -54,11 +53,14 @@ static inline void append_int(borrowed_fd fd, std::vector<char>* bytes) {

static inline void append_bytes_with_size(borrowed_fd fd, std::vector<char>* bytes) {
    int32_t le_size = read_int32(fd);
    if (le_size < 0) {
        return;
    }
    int32_t size = int32_t(le32toh(le_size));
    auto old_size = bytes->size();
    bytes->resize(old_size + sizeof(le_size) + size);
    memcpy(bytes->data() + old_size, &le_size, sizeof(le_size));
    ReadFully(fd, bytes->data() + old_size + sizeof(le_size), size);
    ReadFdExactly(fd, bytes->data() + old_size + sizeof(le_size), size);
}

static inline std::pair<std::vector<char>, int32_t> read_id_sig_headers(borrowed_fd fd) {
@@ -200,7 +202,7 @@ std::optional<Process> install(std::vector<std::string> files) {
        return {};
    }
    auto [pipe_read_fd, pipe_write_fd] = print_fds;
    auto pipe_write_fd_param = std::to_string(pipe_write_fd);
    auto pipe_write_fd_param = std::to_string(intptr_t(adb_get_os_handle(pipe_write_fd)));
    close_on_exec(pipe_read_fd);

    std::vector<std::string> args(std::move(files));
+71 −5
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#include "incremental_utils.h"

#include <android-base/mapped_file.h>
#include <android-base/strings.h>
#include <ziparchive/zip_archive.h>
#include <ziparchive/zip_writer.h>
@@ -26,6 +27,7 @@
#include <numeric>
#include <unordered_set>

#include "adb_trace.h"
#include "sysdeps.h"

static constexpr int kBlockSize = 4096;
@@ -155,18 +157,81 @@ static std::vector<int32_t> ZipPriorityBlocks(off64_t signerBlockOffset, int64_t
    return zipPriorityBlocks;
}

// TODO(b/151676293): avoid using OpenArchiveFd that reads local file headers
[[maybe_unused]] static ZipArchiveHandle openZipArchiveFd(int fd) {
    bool transferFdOwnership = false;
#ifdef _WIN32
    //
    // Need to create a special CRT FD here as the current one is not compatible with
    // normal read()/write() calls that libziparchive uses.
    // To make this work we have to create a copy of the file handle, as CRT doesn't care
    // and closes it together with the new descriptor.
    //
    // Note: don't move this into a helper function, it's better to be hard to reuse because
    //       the code is ugly and won't work unless it's a last resort.
    //
    auto handle = adb_get_os_handle(fd);
    HANDLE dupedHandle;
    if (!::DuplicateHandle(::GetCurrentProcess(), handle, ::GetCurrentProcess(), &dupedHandle, 0,
                           false, DUPLICATE_SAME_ACCESS)) {
        D("%s failed at DuplicateHandle: %d", __func__, (int)::GetLastError());
        return {};
    }
    fd = _open_osfhandle((intptr_t)dupedHandle, _O_RDONLY | _O_BINARY);
    if (fd < 0) {
        D("%s failed at _open_osfhandle: %d", __func__, errno);
        ::CloseHandle(handle);
        return {};
    }
    transferFdOwnership = true;
#endif
    ZipArchiveHandle zip;
    if (OpenArchiveFd(fd, "apk_fd", &zip, transferFdOwnership) != 0) {
        D("%s failed at OpenArchiveFd: %d", __func__, errno);
#ifdef _WIN32
        // "_close()" is a secret WinCRT name for the regular close() function.
        _close(fd);
#endif
        return {};
    }
    return zip;
}

static std::pair<ZipArchiveHandle, std::unique_ptr<android::base::MappedFile>> openZipArchive(
        int fd, int64_t fileSize) {
#ifndef __LP64__
    if (fileSize >= INT_MAX) {
        return {openZipArchiveFd(fd), nullptr};
    }
#endif
    auto mapping =
            android::base::MappedFile::FromOsHandle(adb_get_os_handle(fd), 0, fileSize, PROT_READ);
    if (!mapping) {
        D("%s failed at FromOsHandle: %d", __func__, errno);
        return {};
    }
    ZipArchiveHandle zip;
    if (OpenArchiveFromMemory(mapping->data(), mapping->size(), "apk_mapping", &zip) != 0) {
        D("%s failed at OpenArchiveFromMemory: %d", __func__, errno);
        return {};
    }
    return {zip, std::move(mapping)};
}

// TODO(b/151676293): avoid using libziparchive as it reads local file headers
// which causes additional performance cost. Instead, only read from central directory.
static std::vector<int32_t> InstallationPriorityBlocks(int fd, int64_t fileSize) {
    std::vector<int32_t> installationPriorityBlocks;
    ZipArchiveHandle zip;
    if (OpenArchiveFd(fd, "", &zip, false) != 0) {
    auto [zip, _] = openZipArchive(fd, fileSize);
    if (!zip) {
        return {};
    }

    void* cookie = nullptr;
    if (StartIteration(zip, &cookie) != 0) {
        D("%s failed at StartIteration: %d", __func__, errno);
        return {};
    }

    std::vector<int32_t> installationPriorityBlocks;
    ZipEntry entry;
    std::string_view entryName;
    while (Next(cookie, &entry, &entryName) == 0) {
@@ -183,6 +248,7 @@ static std::vector<int32_t> InstallationPriorityBlocks(int fd, int64_t fileSize)
            int32_t endBlockIndex = offsetToBlockIndex(entryEndOffset);
            int32_t numNewBlocks = endBlockIndex - startBlockIndex + 1;
            appendBlocks(startBlockIndex, numNewBlocks, &installationPriorityBlocks);
            D("\tadding to priority blocks: '%.*s'", (int)entryName.size(), entryName.data());
        } else if (entryName == "classes.dex") {
            // Only the head is needed for installation
            int32_t startBlockIndex = offsetToBlockIndex(entry.offset);
+7 −0
Original line number Diff line number Diff line
@@ -276,6 +276,7 @@ inline void seekdir(DIR*, long) {
class Process {
  public:
    constexpr explicit Process(HANDLE h = nullptr) : h_(h) {}
    constexpr Process(Process&& other) : h_(std::exchange(other.h_, nullptr)) {}
    ~Process() { close(); }
    constexpr explicit operator bool() const { return h_ != nullptr; }

@@ -292,6 +293,8 @@ class Process {
    }

  private:
    DISALLOW_COPY_AND_ASSIGN(Process);

    void close() {
        if (*this) {
            ::CloseHandle(h_);
@@ -666,6 +669,8 @@ static __inline__ int adb_get_os_handle(borrowed_fd fd) {
class Process {
  public:
    constexpr explicit Process(pid_t pid) : pid_(pid) {}
    constexpr Process(Process&& other) : pid_(std::exchange(other.pid_, -1)) {}

    constexpr explicit operator bool() const { return pid_ >= 0; }

    void wait() {
@@ -682,6 +687,8 @@ class Process {
    }

  private:
    DISALLOW_COPY_AND_ASSIGN(Process);

    pid_t pid_;
};