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

Commit 57b71e60 authored by Jerry Zhang's avatar Jerry Zhang Committed by android-build-merger
Browse files

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

am: 3f6419d0

Change-Id: I8a4b7b7134b1426f3c2e1f854618362eea9602c0
parents 9ae457ec 3f6419d0
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;
    }