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

Commit 3f6419d0 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Make Mtp FFS allocations per session rather than per file"

parents f41c781c cc9d0fdd
Loading
Loading
Loading
Loading
+51 −75
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@

#include "AsyncIO.h"
#include "MtpFfsHandle.h"
#include "mtp.h"

#define cpu_to_le16(x)  htole16(x)
#define cpu_to_le32(x)  htole32(x)
@@ -58,8 +59,8 @@ constexpr int MAX_FILE_CHUNK_SIZE = 3145728;
// To get good performance, override these with
// higher values per device using the properties
// sys.usb.ffs.max_read and sys.usb.ffs.max_write
constexpr int USB_FFS_MAX_WRITE = 32768;
constexpr int USB_FFS_MAX_READ = 32768;
constexpr int USB_FFS_MAX_WRITE = MTP_BUFFER_SIZE;
constexpr int USB_FFS_MAX_READ = MTP_BUFFER_SIZE;

constexpr unsigned int MAX_MTP_FILE_SIZE = 0xFFFFFFFF;

@@ -344,28 +345,9 @@ bool MtpFfsHandle::initFunctionfs() {
    if (mBulkIn > -1 || mBulkOut > -1 || mIntr > -1)
        LOG(WARNING) << "Endpoints were not closed before configure!";

    mBulkIn.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_IN, O_RDWR)));
    if (mBulkIn < 0) {
        PLOG(ERROR) << FFS_MTP_EP_IN << ": cannot open bulk in ep";
        goto err;
    }

    mBulkOut.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_OUT, O_RDWR)));
    if (mBulkOut < 0) {
        PLOG(ERROR) << FFS_MTP_EP_OUT << ": cannot open bulk out ep";
        goto err;
    }

    mIntr.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_INTR, O_RDWR)));
    if (mIntr < 0) {
        PLOG(ERROR) << FFS_MTP_EP0 << ": cannot open intr ep";
        goto err;
    }

    return true;

err:
    closeEndpoints();
    closeConfig();
    return false;
}
@@ -447,8 +429,50 @@ int MtpFfsHandle::write(const void* data, int len) {

int MtpFfsHandle::start() {
    mLock.lock();

    mBulkIn.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_IN, O_RDWR)));
    if (mBulkIn < 0) {
        PLOG(ERROR) << FFS_MTP_EP_IN << ": cannot open bulk in ep";
        return -1;
    }

    mBulkOut.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_OUT, O_RDWR)));
    if (mBulkOut < 0) {
        PLOG(ERROR) << FFS_MTP_EP_OUT << ": cannot open bulk out ep";
        return -1;
    }

    mIntr.reset(TEMP_FAILURE_RETRY(open(FFS_MTP_EP_INTR, O_RDWR)));
    if (mIntr < 0) {
        PLOG(ERROR) << FFS_MTP_EP0 << ": cannot open intr ep";
        return -1;
    }

    mBuffer1.resize(MAX_FILE_CHUNK_SIZE);
    mBuffer2.resize(MAX_FILE_CHUNK_SIZE);
    posix_madvise(mBuffer1.data(), MAX_FILE_CHUNK_SIZE,
            POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED);
    posix_madvise(mBuffer2.data(), MAX_FILE_CHUNK_SIZE,
            POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED);

    // Get device specific r/w size
    mMaxWrite = android::base::GetIntProperty("sys.usb.ffs.max_write", USB_FFS_MAX_WRITE);
    mMaxRead = android::base::GetIntProperty("sys.usb.ffs.max_read", USB_FFS_MAX_READ);

    while (mMaxWrite > USB_FFS_MAX_WRITE && mMaxRead > USB_FFS_MAX_READ) {
        // If larger contiguous chunks of memory aren't available, attempt to try
        // smaller allocations.
        if (ioctl(mBulkIn, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(mMaxWrite)) ||
            ioctl(mBulkOut, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(mMaxRead))) {
            mMaxWrite /= 2;
            mMaxRead /=2;
        } else {
            return 0;
        }
    }
    PLOG(ERROR) << "Functionfs could not allocate any memory!";
    return -1;
}

int MtpFfsHandle::configure(bool usePtp) {
    // Wait till previous server invocation has closed
@@ -465,13 +489,6 @@ int MtpFfsHandle::configure(bool usePtp) {
        return -1;
    }

    // Get device specific r/w size
    mMaxWrite = android::base::GetIntProperty("sys.usb.ffs.max_write", 0);
    mMaxRead = android::base::GetIntProperty("sys.usb.ffs.max_read", 0);
    if (!mMaxWrite)
        mMaxWrite = USB_FFS_MAX_WRITE;
    if (!mMaxRead)
        mMaxRead = USB_FFS_MAX_READ;
    return 0;
}

@@ -480,26 +497,6 @@ void MtpFfsHandle::close() {
    mLock.unlock();
}

class ScopedEndpointBufferAlloc {
private:
    const int mFd;
    const unsigned int mAllocSize;
public:
    ScopedEndpointBufferAlloc(int fd, unsigned alloc_size) :
        mFd(fd),
        mAllocSize(alloc_size) {
        if (ioctl(mFd, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(mAllocSize)))
            PLOG(ERROR) << "FFS endpoint alloc failed!";
    }

    ~ScopedEndpointBufferAlloc() {
        if (ioctl(mFd, FUNCTIONFS_ENDPOINT_ALLOC, static_cast<__u32>(0)))
            PLOG(ERROR) << "FFS endpoint alloc reset failed!";
    }

    DISALLOW_COPY_AND_ASSIGN(ScopedEndpointBufferAlloc);
};

/* Read from USB and write to a local file. */
int MtpFfsHandle::receiveFile(mtp_file_range mfr) {
    // When receiving files, the incoming length is given in 32 bits.
@@ -507,15 +504,8 @@ int MtpFfsHandle::receiveFile(mtp_file_range mfr) {
    uint32_t file_length = mfr.length;
    uint64_t offset = lseek(mfr.fd, 0, SEEK_CUR);

    int buf1_len = std::min(static_cast<uint32_t>(MAX_FILE_CHUNK_SIZE), file_length);
    std::vector<char> buf1(buf1_len);
    char* data = buf1.data();

    // If necessary, allocate a second buffer for background r/w
    int buf2_len = std::min(static_cast<uint32_t>(MAX_FILE_CHUNK_SIZE),
            file_length - MAX_FILE_CHUNK_SIZE);
    std::vector<char> buf2(std::max(0, buf2_len));
    char *data2 = buf2.data();
    char *data = mBuffer1.data();
    char *data2 = mBuffer2.data();

    struct aiocb aio;
    aio.aio_fildes = mfr.fd;
@@ -527,9 +517,6 @@ int MtpFfsHandle::receiveFile(mtp_file_range mfr) {
    bool write = false;

    posix_fadvise(mfr.fd, 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
    posix_madvise(data, buf1_len, POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED);
    posix_madvise(data2, buf2_len, POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED);
    ScopedEndpointBufferAlloc scoped_alloc(mBulkOut, mMaxRead);

    // Break down the file into pieces that fit in buffers
    while (file_length > 0 || write) {
@@ -608,20 +595,11 @@ int MtpFfsHandle::sendFile(mtp_file_range mfr) {
    }

    int init_read_len = packet_size - sizeof(mtp_data_header);
    int buf1_len = std::max(static_cast<uint64_t>(packet_size), std::min(
                  static_cast<uint64_t>(MAX_FILE_CHUNK_SIZE), file_length - init_read_len));
    std::vector<char> buf1(buf1_len);
    char *data = buf1.data();

    // If necessary, allocate a second buffer for background r/w
    int buf2_len = std::min(static_cast<uint64_t>(MAX_FILE_CHUNK_SIZE),
            file_length - MAX_FILE_CHUNK_SIZE - init_read_len);
    std::vector<char> buf2(std::max(0, buf2_len));
    char *data2 = buf2.data();
    char *data = mBuffer1.data();
    char *data2 = mBuffer2.data();

    posix_fadvise(mfr.fd, 0, 0, POSIX_FADV_SEQUENTIAL | POSIX_FADV_NOREUSE);
    posix_madvise(data, buf1_len, POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED);
    posix_madvise(data2, buf2_len, POSIX_MADV_SEQUENTIAL | POSIX_MADV_WILLNEED);

    struct aiocb aio;
    aio.aio_fildes = mfr.fd;
@@ -647,8 +625,6 @@ int MtpFfsHandle::sendFile(mtp_file_range mfr) {
    if (writeHandle(mBulkIn, data, packet_size) == -1) return -1;
    if (file_length == 0) return 0;

    ScopedEndpointBufferAlloc scoped_alloc(mBulkIn, mMaxWrite);

    // Break down the file into pieces that fit in buffers
    while(file_length > 0) {
        if (read) {
@@ -672,7 +648,7 @@ int MtpFfsHandle::sendFile(mtp_file_range mfr) {
        }

        if (file_length > 0) {
            length = std::min((uint64_t) MAX_FILE_CHUNK_SIZE, file_length);
            length = std::min(static_cast<uint64_t>(MAX_FILE_CHUNK_SIZE), file_length);
            // Queue up another read
            aio.aio_buf = data;
            aio.aio_offset = offset;
+3 −0
Original line number Diff line number Diff line
@@ -48,6 +48,9 @@ private:
    int mMaxWrite;
    int mMaxRead;

    std::vector<char> mBuffer1;
    std::vector<char> mBuffer2;

public:
    int read(void *data, int len);
    int write(const void *data, int len);
+1 −0
Original line number Diff line number Diff line
@@ -179,6 +179,7 @@ void MtpServer::run() {

    if (sHandle->start()) {
        ALOGE("Failed to start usb driver!");
        sHandle->close();
        return;
    }