Switch MtpFfsHandle to aio, add control functions.
MtpFfsHandle now uses kaio to handle usb data.
This achieves better performance without using
the endpoint alloc ioctl.
This also allows ep0 events to be handled without
race conditions. Events will also include control
requests, which will allow both host and device
initiated cancellation.
Bug: 37916658
Bug: 36802721
Test: Transfer various size files, run MtpFfsHandleTest
Test: Cancel transfer on Windows
Test: Allow device to cancel transfer on Windows
Change-Id: Ib3ce996f00782ce7f68f29b2510dbc17f09fdf14
diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h
index b637d65..2f90bd1 100644
--- a/media/mtp/MtpFfsHandle.h
+++ b/media/mtp/MtpFfsHandle.h
@@ -18,26 +18,51 @@
#define _MTP_FFS_HANDLE_H
#include <android-base/unique_fd.h>
+#include <linux/aio_abi.h>
+#include <mutex>
+#include <sys/poll.h>
+#include <time.h>
+#include <thread>
+#include <vector>
+
#include <IMtpHandle.h>
namespace android {
-class MtpFfsHandleTest;
+constexpr char FFS_MTP_EP0[] = "/dev/usb-ffs/mtp/ep0";
+
+constexpr int NUM_IO_BUFS = 2;
+
+struct io_buffer {
+ std::vector<struct iocb> iocbs; // Holds memory for all iocbs. Not used directly.
+ std::vector<struct iocb*> iocb; // Pointers to individual iocbs, for syscalls
+ std::vector<unsigned char> bufs; // A large buffer, used with filesystem io
+ std::vector<unsigned char*> buf; // Pointers within the larger buffer, for syscalls
+ unsigned actual; // The number of buffers submitted for this request
+};
+
+template <class T> class MtpFfsHandleTest;
class MtpFfsHandle : public IMtpHandle {
- friend class android::MtpFfsHandleTest;
-private:
- int writeHandle(int fd, const void *data, int len);
- int readHandle(int fd, void *data, int len);
- int spliceReadHandle(int fd, int fd_out, int len);
+ template <class T> friend class android::MtpFfsHandleTest;
+protected:
bool initFunctionfs();
void closeConfig();
void closeEndpoints();
+ void advise(int fd);
+ int handleControlRequest(const struct usb_ctrlrequest *request);
+ int doAsync(void* data, size_t len, bool read);
+ int handleEvent();
+ void cancelTransaction();
void doSendEvent(mtp_event me);
+ bool openEndpoints();
+
+ static int getPacketSize(int ffs_fd);
bool mPtp;
+ bool mCanceled;
- std::timed_mutex mLock;
+ std::timed_mutex mLock; // protects configure() vs main loop
android::base::unique_fd mControl;
// "in" from the host's perspective => sink for mtp server
@@ -46,28 +71,35 @@
android::base::unique_fd mBulkOut;
android::base::unique_fd mIntr;
- int mMaxWrite;
- int mMaxRead;
+ aio_context_t mCtx;
- std::vector<char> mBuffer1;
- std::vector<char> mBuffer2;
+ android::base::unique_fd mEventFd;
+ struct pollfd mPollFds[2];
+
+ struct io_buffer mIobuf[NUM_IO_BUFS];
+
+ // Submit an io request of given length. Return amount submitted or -1.
+ int iobufSubmit(struct io_buffer *buf, int fd, unsigned length, bool read);
+
+ // Cancel submitted requests from start to end in the given array. Return 0 or -1.
+ int cancelEvents(struct iocb **iocb, struct io_event *events, unsigned start, unsigned end);
+
+ // Wait for at minimum the given number of events. Returns the amount of data in the returned
+ // events. Increments counter by the number of events returned.
+ int waitEvents(struct io_buffer *buf, int min_events, struct io_event *events, int *counter);
public:
- int read(void *data, int len);
- int write(const void *data, int len);
+ int read(void *data, size_t len) override;
+ int write(const void *data, size_t len) override;
- int receiveFile(mtp_file_range mfr, bool zero_packet);
- int sendFile(mtp_file_range mfr);
- int sendEvent(mtp_event me);
+ int receiveFile(mtp_file_range mfr, bool zero_packet) override;
+ int sendFile(mtp_file_range mfr) override;
+ int sendEvent(mtp_event me) override;
- /**
- * Open ffs endpoints and allocate necessary kernel and user memory.
- * Will sleep until endpoints are enabled, for up to 1 second.
- */
- int start();
- void close();
+ int start() override;
+ void close() override;
- int configure(bool ptp);
+ int configure(bool ptp) override;
MtpFfsHandle();
~MtpFfsHandle();
@@ -86,5 +118,5 @@
} // namespace android
-#endif // _MTP_FF_HANDLE_H
+#endif // _MTP_FFS_HANDLE_H