MTP: add a new parameter for cancelEvents function

Currently, cancelEvents in MTP will cancel the requests
one by one, and it will check each response to confirm
success or failure. However, if kernel usb controller
driver got the cancel request, the driver will handle
all requests in the same endpoint so that the second
io_cancel in cancelEvents will be useless. This behavior
change start from kernel 5.x.

This patch will add a parameter to check whether kernel
usb controller driver uses the new behavior so that MTP
could cancel the requests correctly.

Bug: 181729410
Test: cancel a transmitting file and then check the MTP operation
Merged-In: I4e172fa62c297ac33b0c97c67f3f7baa817fd8bf
(cherry picked from commit 305e62ec197f65ebf29d79e8d03ea3b296b4e690)
Signed-off-by: sekaiacg <sekaiacg@gmail.com>
Change-Id: I8963d69b7b7fb6d6d8fe71c293551e2ab9f13470
diff --git a/mtp/ffs/MtpFfsHandle.cpp b/mtp/ffs/MtpFfsHandle.cpp
index 5710aec..9356d4c 100644
--- a/mtp/ffs/MtpFfsHandle.cpp
+++ b/mtp/ffs/MtpFfsHandle.cpp
@@ -73,6 +73,7 @@
 
 MtpFfsHandle::MtpFfsHandle(int controlFd) {
 	mControl.reset(controlFd);
+	mBatchCancel = android::base::GetBoolProperty("sys.usb.mtp.batchcancel", false);
 }
 
 MtpFfsHandle::~MtpFfsHandle() {}
@@ -370,7 +371,7 @@
 }
 
 int MtpFfsHandle::cancelEvents(struct iocb **iocb, struct io_event *events, unsigned start,
-		unsigned end) {
+		unsigned end, bool is_batch_cancel) {
 	// Some manpages for io_cancel are out of date and incorrect.
 	// io_cancel will return -EINPROGRESS on success and does
 	// not place the event in the given memory. We have to use
@@ -386,6 +387,10 @@
 		} else {
 			num_events++;
 		}
+		if (is_batch_cancel && num_events == 1) {
+			num_events = end - start;
+			break;
+		}
 	}
 	if (num_events != end - start) {
 		ret = -1;
@@ -495,7 +500,8 @@
 				num_events += this_events;
 
 				if (event_ret == -1) {
-					cancelEvents(mIobuf[i].iocb.data(), ioevs, num_events, mIobuf[i].actual);
+					cancelEvents(mIobuf[i].iocb.data(), ioevs, num_events, mIobuf[i].actual,
+							mBatchCancel);
 					return -1;
 				}
 				ret += event_ret;
@@ -512,7 +518,7 @@
 				}
 			}
 			if (short_packet) {
-				if (cancelEvents(mIobuf[i].iocb.data(), ioevs, short_i, mIobuf[i].actual)) {
+				if (cancelEvents(mIobuf[i].iocb.data(), ioevs, short_i, mIobuf[i].actual, false)) {
 					write_error = true;
 				}
 			}
@@ -613,7 +619,7 @@
 						&num_events) != ret) {
 				error = true;
 				cancelEvents(mIobuf[(i-1)%NUM_IO_BUFS].iocb.data(), ioevs, num_events,
-						mIobuf[(i-1)%NUM_IO_BUFS].actual);
+						mIobuf[(i-1)%NUM_IO_BUFS].actual, false);
 			}
 			has_write = false;
 		}