From 77a1c65610618891ba28d7a10e4f107ea27e392e Mon Sep 17 00:00:00 2001 From: Daichi Hirono Date: Mon, 28 Mar 2016 14:37:12 +0900 Subject: [PATCH] Open 4G+ file by using AppFuse. To open files by using AppFuse, the provider needs to know the size of file. Previously we cannot open 4G+ files because we cannot obtain file size for such large files. Now MtpDatabase contains correct size for 4GB+ file size. The CL starts opening files by using AppFuse which obtains partial bytes by using getObjectPartial64 operation. FIXED=26840097 Change-Id: I1cb41972175c2b98f4aa76981decc6b3ad35486d --- .../src/com/android/mtp/AppFuse.java | 2 ++ .../src/com/android/mtp/MtpDeviceRecord.java | 11 ++++++-- .../com/android/mtp/MtpDocumentsProvider.java | 26 ++++++++++++++----- .../src/com/android/mtp/MtpManager.java | 8 ++++++ 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/AppFuse.java b/packages/MtpDocumentsProvider/src/com/android/mtp/AppFuse.java index 1fd471cb48e2d..777dc606f6c30 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/AppFuse.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/AppFuse.java @@ -144,6 +144,8 @@ public class AppFuse { return mCallback.getFileSize(inode); } catch (FileNotFoundException e) { return -OsConstants.ENOENT; + } catch (UnsupportedOperationException e) { + return -OsConstants.ENOTSUP; } } diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDeviceRecord.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDeviceRecord.java index 393c4de89ea4e..c52b81d76d362 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDeviceRecord.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDeviceRecord.java @@ -56,8 +56,15 @@ class MtpDeviceRecord { } static boolean isPartialReadSupported(@Nullable int[] supportedList, long fileSize) { - return fileSize <= 0xffffffffl && - isSupported(supportedList, MtpConstants.OPERATION_GET_PARTIAL_OBJECT); + if (isSupported(supportedList, MtpConstants.OPERATION_GET_PARTIAL_OBJECT_64)) { + return true; + } + if (0 <= fileSize && + fileSize <= 0xffffffffL && + isSupported(supportedList, MtpConstants.OPERATION_GET_PARTIAL_OBJECT)) { + return true; + } + return false; } static boolean isWritingSupported(@Nullable int[] supportedList) { diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java index 167cb37f72443..9f64046ce64af 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java @@ -234,11 +234,14 @@ public class MtpDocumentsProvider extends DocumentsProvider { final MtpDeviceRecord device = getDeviceToolkit(identifier.mDeviceId).mDeviceRecord; switch (mode) { case "r": - final long fileSize = getFileSize(documentId); + long fileSize; + try { + fileSize = getFileSize(documentId); + } catch (UnsupportedOperationException exception) { + fileSize = -1; + } // MTP getPartialObject operation does not support files that are larger than // 4GB. Fallback to non-seekable file descriptor. - // TODO: Use getPartialObject64 for MTP devices that support Android vendor - // extension. if (MtpDeviceRecord.isPartialReadSupported( device.operationsSupported, fileSize)) { return mAppFuse.openFile( @@ -543,6 +546,9 @@ public class MtpDocumentsProvider extends DocumentsProvider { MtpDatabase.strings(Document.COLUMN_SIZE, Document.COLUMN_DISPLAY_NAME)); try { if (cursor.moveToNext()) { + if (cursor.isNull(0)) { + throw new UnsupportedOperationException(); + } return cursor.getLong(0); } else { throw new FileNotFoundException(); @@ -594,12 +600,20 @@ public class MtpDocumentsProvider extends DocumentsProvider { int inode, long offset, long size, byte[] buffer) throws IOException { final Identifier identifier = mDatabase.createIdentifier(Integer.toString(inode)); final MtpDeviceRecord record = getDeviceToolkit(identifier.mDeviceId).mDeviceRecord; - if (MtpDeviceRecord.isPartialReadSupported(record.operationsSupported, offset)) { + + if (MtpDeviceRecord.isSupported( + record.operationsSupported, MtpConstants.OPERATION_GET_PARTIAL_OBJECT_64)) { + return mMtpManager.getPartialObject64( + identifier.mDeviceId, identifier.mObjectHandle, offset, size, buffer); + } + + if (0 <= offset && offset <= 0xffffffffL && MtpDeviceRecord.isSupported( + record.operationsSupported, MtpConstants.OPERATION_GET_PARTIAL_OBJECT)) { return mMtpManager.getPartialObject( identifier.mDeviceId, identifier.mObjectHandle, offset, size, buffer); - } else { - throw new UnsupportedOperationException(); } + + throw new UnsupportedOperationException(); } @Override diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java index 53873fbe2a7f2..00d31a71a2d66 100644 --- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java +++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java @@ -170,6 +170,14 @@ class MtpManager { } } + long getPartialObject64(int deviceId, int objectHandle, long offset, long size, byte[] buffer) + throws IOException { + final MtpDevice device = getDevice(deviceId); + synchronized (device) { + return device.getPartialObject64(objectHandle, offset, size, buffer); + } + } + byte[] getThumbnail(int deviceId, int objectHandle) throws IOException { final MtpDevice device = getDevice(deviceId); synchronized (device) {