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

Commit 1b9a7f24 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 5348557 from c19e4191 to qt-release

Change-Id: Iaa067dff94fab42eddfa71ec43e58e6c04ce96e8
parents 5a87356c c19e4191
Loading
Loading
Loading
Loading
+39 −0
Original line number Original line Diff line number Diff line
@@ -17,6 +17,8 @@


import os
import os
import statistics
import statistics
import subprocess
import tempfile
import time
import time


import adb
import adb
@@ -56,6 +58,41 @@ def analyze(name, speeds):
    msg = "%s: %d runs: median %.2f MiB/s, mean %.2f MiB/s, stddev: %.2f MiB/s"
    msg = "%s: %d runs: median %.2f MiB/s, mean %.2f MiB/s, stddev: %.2f MiB/s"
    print(msg % (name, len(speeds), median, mean, stddev))
    print(msg % (name, len(speeds), median, mean, stddev))


def benchmark_sink(device=None, size_mb=100):
    if device == None:
        device = adb.get_device()

    speeds = list()
    cmd = device.adb_cmd + ["raw", "sink:%d" % (size_mb * 1024 * 1024)]

    with tempfile.TemporaryFile() as tmpfile:
        tmpfile.truncate(size_mb * 1024 * 1024)

        for _ in range(0, 10):
            tmpfile.seek(0)
            begin = time.time()
            subprocess.check_call(cmd, stdin=tmpfile)
            end = time.time()
            speeds.append(size_mb / float(end - begin))

    analyze("sink %dMiB" % size_mb, speeds)

def benchmark_source(device=None, size_mb=100):
    if device == None:
        device = adb.get_device()

    speeds = list()
    cmd = device.adb_cmd + ["raw", "source:%d" % (size_mb * 1024 * 1024)]

    with open(os.devnull, 'w') as devnull:
        for _ in range(0, 10):
            begin = time.time()
            subprocess.check_call(cmd, stdout=devnull)
            end = time.time()
            speeds.append(size_mb / float(end - begin))

    analyze("source %dMiB" % size_mb, speeds)

def benchmark_push(device=None, file_size_mb=100):
def benchmark_push(device=None, file_size_mb=100):
    if device == None:
    if device == None:
        device = adb.get_device()
        device = adb.get_device()
@@ -110,6 +147,8 @@ def benchmark_shell(device=None, file_size_mb=100):
def main():
def main():
    device = adb.get_device()
    device = adb.get_device()
    unlock(device)
    unlock(device)
    benchmark_sink(device)
    benchmark_source(device)
    benchmark_push(device)
    benchmark_push(device)
    benchmark_pull(device)
    benchmark_pull(device)


+67 −41
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@
#include <linux/usb/functionfs.h>
#include <linux/usb/functionfs.h>
#include <sys/eventfd.h>
#include <sys/eventfd.h>


#include <algorithm>
#include <array>
#include <array>
#include <future>
#include <future>
#include <memory>
#include <memory>
@@ -56,10 +57,11 @@ using android::base::StringPrintf;
// We can't find out whether we have support for AIO on ffs endpoints until we submit a read.
// We can't find out whether we have support for AIO on ffs endpoints until we submit a read.
static std::optional<bool> gFfsAioSupported;
static std::optional<bool> gFfsAioSupported;


static constexpr size_t kUsbReadQueueDepth = 16;
static constexpr size_t kUsbReadQueueDepth = 32;
static constexpr size_t kUsbReadSize = 16384;
static constexpr size_t kUsbReadSize = 8 * PAGE_SIZE;


static constexpr size_t kUsbWriteQueueDepth = 16;
static constexpr size_t kUsbWriteQueueDepth = 32;
static constexpr size_t kUsbWriteSize = 8 * PAGE_SIZE;


static const char* to_string(enum usb_functionfs_event_type type) {
static const char* to_string(enum usb_functionfs_event_type type) {
    switch (type) {
    switch (type) {
@@ -115,7 +117,7 @@ struct TransferId {
struct IoBlock {
struct IoBlock {
    bool pending;
    bool pending;
    struct iocb control;
    struct iocb control;
    Block payload;
    std::shared_ptr<Block> payload;


    TransferId id() const { return TransferId::from_value(control.aio_data); }
    TransferId id() const { return TransferId::from_value(control.aio_data); }
};
};
@@ -207,8 +209,20 @@ struct UsbFfsConnection : public Connection {
        std::lock_guard<std::mutex> lock(write_mutex_);
        std::lock_guard<std::mutex> lock(write_mutex_);
        write_requests_.push_back(CreateWriteBlock(std::move(header), next_write_id_++));
        write_requests_.push_back(CreateWriteBlock(std::move(header), next_write_id_++));
        if (!packet->payload.empty()) {
        if (!packet->payload.empty()) {
            // The kernel attempts to allocate a contiguous block of memory for each write,
            // which can fail if the write is large and the kernel heap is fragmented.
            // Split large writes into smaller chunks to avoid this.
            std::shared_ptr<Block> payload = std::make_shared<Block>(std::move(packet->payload));
            size_t offset = 0;
            size_t len = payload->size();

            while (len > 0) {
                size_t write_size = std::min(kUsbWriteSize, len);
                write_requests_.push_back(
                write_requests_.push_back(
                    CreateWriteBlock(std::move(packet->payload), next_write_id_++));
                        CreateWriteBlock(payload, offset, write_size, next_write_id_++));
                len -= write_size;
                offset += write_size;
            }
        }
        }
        SubmitWrites();
        SubmitWrites();
        return true;
        return true;
@@ -246,7 +260,6 @@ struct UsbFfsConnection : public Connection {
        // until it dies, and then report failure to the transport via HandleError, which will
        // until it dies, and then report failure to the transport via HandleError, which will
        // eventually result in the transport being destroyed, which will result in UsbFfsConnection
        // eventually result in the transport being destroyed, which will result in UsbFfsConnection
        // being destroyed, which unblocks the open thread and restarts this entire process.
        // being destroyed, which unblocks the open thread and restarts this entire process.
        static constexpr int kInterruptionSignal = SIGUSR1;
        static std::once_flag handler_once;
        static std::once_flag handler_once;
        std::call_once(handler_once, []() { signal(kInterruptionSignal, [](int) {}); });
        std::call_once(handler_once, []() { signal(kInterruptionSignal, [](int) {}); });


@@ -272,6 +285,7 @@ struct UsbFfsConnection : public Connection {
                } else if (rc == 0) {
                } else if (rc == 0) {
                    // Something in the kernel presumably went wrong.
                    // Something in the kernel presumably went wrong.
                    // Close our endpoints, wait for a bit, and then try again.
                    // Close our endpoints, wait for a bit, and then try again.
                    StopWorker();
                    aio_context_.reset();
                    aio_context_.reset();
                    read_fd_.reset();
                    read_fd_.reset();
                    write_fd_.reset();
                    write_fd_.reset();
@@ -297,7 +311,7 @@ struct UsbFfsConnection : public Connection {


                switch (event.type) {
                switch (event.type) {
                    case FUNCTIONFS_BIND:
                    case FUNCTIONFS_BIND:
                        CHECK(!started) << "received FUNCTIONFS_ENABLE while already bound?";
                        CHECK(!bound) << "received FUNCTIONFS_BIND while already bound?";
                        bound = true;
                        bound = true;
                        break;
                        break;


@@ -313,28 +327,7 @@ struct UsbFfsConnection : public Connection {
                }
                }
            }
            }


            pthread_t worker_thread_handle = worker_thread_.native_handle();
            StopWorker();
            while (true) {
                int rc = pthread_kill(worker_thread_handle, kInterruptionSignal);
                if (rc != 0) {
                    LOG(ERROR) << "failed to send interruption signal to worker: " << strerror(rc);
                    break;
                }

                std::this_thread::sleep_for(100ms);

                rc = pthread_kill(worker_thread_handle, 0);
                if (rc == 0) {
                    continue;
                } else if (rc == ESRCH) {
                    break;
                } else {
                    LOG(ERROR) << "failed to send interruption signal to worker: " << strerror(rc);
                }
            }

            worker_thread_.join();

            aio_context_.reset();
            aio_context_.reset();
            read_fd_.reset();
            read_fd_.reset();
            write_fd_.reset();
            write_fd_.reset();
@@ -365,12 +358,36 @@ struct UsbFfsConnection : public Connection {
        });
        });
    }
    }


    void StopWorker() {
        pthread_t worker_thread_handle = worker_thread_.native_handle();
        while (true) {
            int rc = pthread_kill(worker_thread_handle, kInterruptionSignal);
            if (rc != 0) {
                LOG(ERROR) << "failed to send interruption signal to worker: " << strerror(rc);
                break;
            }

            std::this_thread::sleep_for(100ms);

            rc = pthread_kill(worker_thread_handle, 0);
            if (rc == 0) {
                continue;
            } else if (rc == ESRCH) {
                break;
            } else {
                LOG(ERROR) << "failed to send interruption signal to worker: " << strerror(rc);
            }
        }

        worker_thread_.join();
    }

    void PrepareReadBlock(IoBlock* block, uint64_t id) {
    void PrepareReadBlock(IoBlock* block, uint64_t id) {
        block->pending = false;
        block->pending = false;
        block->payload.resize(kUsbReadSize);
        block->payload = std::make_shared<Block>(kUsbReadSize);
        block->control.aio_data = static_cast<uint64_t>(TransferId::read(id));
        block->control.aio_data = static_cast<uint64_t>(TransferId::read(id));
        block->control.aio_buf = reinterpret_cast<uintptr_t>(block->payload.data());
        block->control.aio_buf = reinterpret_cast<uintptr_t>(block->payload->data());
        block->control.aio_nbytes = block->payload.size();
        block->control.aio_nbytes = block->payload->size();
    }
    }


    IoBlock CreateReadBlock(uint64_t id) {
    IoBlock CreateReadBlock(uint64_t id) {
@@ -421,7 +438,7 @@ struct UsbFfsConnection : public Connection {
        uint64_t read_idx = id.id % kUsbReadQueueDepth;
        uint64_t read_idx = id.id % kUsbReadQueueDepth;
        IoBlock* block = &read_requests_[read_idx];
        IoBlock* block = &read_requests_[read_idx];
        block->pending = false;
        block->pending = false;
        block->payload.resize(size);
        block->payload->resize(size);


        // Notification for completed reads can be received out of order.
        // Notification for completed reads can be received out of order.
        if (block->id().id != needed_read_id_) {
        if (block->id().id != needed_read_id_) {
@@ -442,16 +459,16 @@ struct UsbFfsConnection : public Connection {
    }
    }


    void ProcessRead(IoBlock* block) {
    void ProcessRead(IoBlock* block) {
        if (!block->payload.empty()) {
        if (!block->payload->empty()) {
            if (!incoming_header_.has_value()) {
            if (!incoming_header_.has_value()) {
                CHECK_EQ(sizeof(amessage), block->payload.size());
                CHECK_EQ(sizeof(amessage), block->payload->size());
                amessage msg;
                amessage msg;
                memcpy(&msg, block->payload.data(), sizeof(amessage));
                memcpy(&msg, block->payload->data(), sizeof(amessage));
                LOG(DEBUG) << "USB read:" << dump_header(&msg);
                LOG(DEBUG) << "USB read:" << dump_header(&msg);
                incoming_header_ = msg;
                incoming_header_ = msg;
            } else {
            } else {
                size_t bytes_left = incoming_header_->data_length - incoming_payload_.size();
                size_t bytes_left = incoming_header_->data_length - incoming_payload_.size();
                Block payload = std::move(block->payload);
                Block payload = std::move(*block->payload);
                CHECK_LE(payload.size(), bytes_left);
                CHECK_LE(payload.size(), bytes_left);
                incoming_payload_.append(std::make_unique<Block>(std::move(payload)));
                incoming_payload_.append(std::make_unique<Block>(std::move(payload)));
            }
            }
@@ -506,7 +523,8 @@ struct UsbFfsConnection : public Connection {
        SubmitWrites();
        SubmitWrites();
    }
    }


    std::unique_ptr<IoBlock> CreateWriteBlock(Block payload, uint64_t id) {
    std::unique_ptr<IoBlock> CreateWriteBlock(std::shared_ptr<Block> payload, size_t offset,
                                              size_t len, uint64_t id) {
        auto block = std::make_unique<IoBlock>();
        auto block = std::make_unique<IoBlock>();
        block->payload = std::move(payload);
        block->payload = std::move(payload);
        block->control.aio_data = static_cast<uint64_t>(TransferId::write(id));
        block->control.aio_data = static_cast<uint64_t>(TransferId::write(id));
@@ -514,14 +532,20 @@ struct UsbFfsConnection : public Connection {
        block->control.aio_lio_opcode = IOCB_CMD_PWRITE;
        block->control.aio_lio_opcode = IOCB_CMD_PWRITE;
        block->control.aio_reqprio = 0;
        block->control.aio_reqprio = 0;
        block->control.aio_fildes = write_fd_.get();
        block->control.aio_fildes = write_fd_.get();
        block->control.aio_buf = reinterpret_cast<uintptr_t>(block->payload.data());
        block->control.aio_buf = reinterpret_cast<uintptr_t>(block->payload->data() + offset);
        block->control.aio_nbytes = block->payload.size();
        block->control.aio_nbytes = len;
        block->control.aio_offset = 0;
        block->control.aio_offset = 0;
        block->control.aio_flags = IOCB_FLAG_RESFD;
        block->control.aio_flags = IOCB_FLAG_RESFD;
        block->control.aio_resfd = worker_event_fd_.get();
        block->control.aio_resfd = worker_event_fd_.get();
        return block;
        return block;
    }
    }


    std::unique_ptr<IoBlock> CreateWriteBlock(Block payload, uint64_t id) {
        std::shared_ptr<Block> block = std::make_shared<Block>(std::move(payload));
        size_t len = block->size();
        return CreateWriteBlock(std::move(block), 0, len, id);
    }

    void SubmitWrites() REQUIRES(write_mutex_) {
    void SubmitWrites() REQUIRES(write_mutex_) {
        if (writes_submitted_ == kUsbWriteQueueDepth) {
        if (writes_submitted_ == kUsbWriteQueueDepth) {
            return;
            return;
@@ -594,6 +618,8 @@ struct UsbFfsConnection : public Connection {
    std::deque<std::unique_ptr<IoBlock>> write_requests_ GUARDED_BY(write_mutex_);
    std::deque<std::unique_ptr<IoBlock>> write_requests_ GUARDED_BY(write_mutex_);
    size_t next_write_id_ GUARDED_BY(write_mutex_) = 0;
    size_t next_write_id_ GUARDED_BY(write_mutex_) = 0;
    size_t writes_submitted_ GUARDED_BY(write_mutex_) = 0;
    size_t writes_submitted_ GUARDED_BY(write_mutex_) = 0;

    static constexpr int kInterruptionSignal = SIGUSR1;
};
};


void usb_init_legacy();
void usb_init_legacy();
+1 −0
Original line number Original line Diff line number Diff line
jhawkins@google.com
jhawkins@google.com
salyzyn@google.com
+7 −2
Original line number Original line Diff line number Diff line
@@ -403,7 +403,7 @@ RetCode FastBootDriver::DownloadCommand(uint32_t size, std::string* response,
RetCode FastBootDriver::HandleResponse(std::string* response, std::vector<std::string>* info,
RetCode FastBootDriver::HandleResponse(std::string* response, std::vector<std::string>* info,
                                       int* dsize) {
                                       int* dsize) {
    char status[FB_RESPONSE_SZ + 1];
    char status[FB_RESPONSE_SZ + 1];
    auto start = std::chrono::system_clock::now();
    auto start = std::chrono::steady_clock::now();


    auto set_response = [response](std::string s) {
    auto set_response = [response](std::string s) {
        if (response) *response = std::move(s);
        if (response) *response = std::move(s);
@@ -414,7 +414,7 @@ RetCode FastBootDriver::HandleResponse(std::string* response, std::vector<std::s


    // erase response
    // erase response
    set_response("");
    set_response("");
    while ((std::chrono::system_clock::now() - start) < std::chrono::seconds(RESP_TIMEOUT)) {
    while ((std::chrono::steady_clock::now() - start) < std::chrono::seconds(RESP_TIMEOUT)) {
        int r = transport_->Read(status, FB_RESPONSE_SZ);
        int r = transport_->Read(status, FB_RESPONSE_SZ);
        if (r < 0) {
        if (r < 0) {
            error_ = ErrnoStr("Status read failed");
            error_ = ErrnoStr("Status read failed");
@@ -427,6 +427,11 @@ RetCode FastBootDriver::HandleResponse(std::string* response, std::vector<std::s
            std::string tmp = input.substr(strlen("INFO"));
            std::string tmp = input.substr(strlen("INFO"));
            info_(tmp);
            info_(tmp);
            add_info(std::move(tmp));
            add_info(std::move(tmp));
            // We may receive one or more INFO packets during long operations,
            // e.g. flash/erase if they are back by slow media like NAND/NOR
            // flash. In that case, reset the timer since it's not a real
            // timeout.
            start = std::chrono::steady_clock::now();
        } else if (android::base::StartsWith(input, "OKAY")) {
        } else if (android::base::StartsWith(input, "OKAY")) {
            set_response(input.substr(strlen("OKAY")));
            set_response(input.substr(strlen("OKAY")));
            return SUCCESS;
            return SUCCESS;
+2 −2
Original line number Original line Diff line number Diff line
@@ -307,6 +307,8 @@ void ParseFsMgrFlags(const std::string& flags, FstabEntry* entry) {
            } else {
            } else {
                entry->logical_blk_size = val;
                entry->logical_blk_size = val;
            }
            }
        } else if (StartsWith(flag, "avb_keys=")) {  // must before the following "avb"
            entry->avb_keys = arg;
        } else if (StartsWith(flag, "avb")) {
        } else if (StartsWith(flag, "avb")) {
            entry->fs_mgr_flags.avb = true;
            entry->fs_mgr_flags.avb = true;
            entry->vbmeta_partition = arg;
            entry->vbmeta_partition = arg;
@@ -325,8 +327,6 @@ void ParseFsMgrFlags(const std::string& flags, FstabEntry* entry) {
            }
            }
        } else if (StartsWith(flag, "zram_backing_dev_path=")) {
        } else if (StartsWith(flag, "zram_backing_dev_path=")) {
            entry->zram_backing_dev_path = arg;
            entry->zram_backing_dev_path = arg;
        } else if (StartsWith(flag, "avb_keys=")) {
            entry->avb_keys = arg;
        } else {
        } else {
            LWARNING << "Warning: unknown flag: " << flag;
            LWARNING << "Warning: unknown flag: " << flag;
        }
        }
Loading