Commit Graph

83 Commits

Author SHA1 Message Date
Steve McKay
5a10ff1828 Add metadata support to MTP docs provider.
Remove convenience method from DocumentsProvider, clients to use MetadataReader directly.
Concentrate mimetype checking in MetadataReader.isSupportedType.
Update FileSystemProvider to use MetadataReader directly.

Test: Updated mtp tests. Other functioanlity manually verified.
Change-Id: Ie1e3d3092b53107f6c980c18b1451290dd2a9653
2017-08-02 09:45:26 -07:00
Daichi Hirono
66fcb4beae Fix doc flag for device having multiple storages
Previously MtpDocumentsProvider#queryDocument returned
FLAG_DIR_SUPPORTS_CREATE for device having multiple storages.

This was wrong because if the device has multiple storages,
MtpDocumentsProvider places the storages under the device document, thus
users cannot create a document just under the device document.

Bug: 35700994
Test: MtpDocumentsProviderTests
Change-Id: Id73a34a2eaf4e10e23be3c2da7488036cea10000
2017-04-26 11:22:49 +09:00
Daichi Hirono
203be491ef Use Context#startForegroundService in MTP provider
NotificationManager.startServiceInForeground() was moved to
Context#startForegroundService. MtpDocumentsProvider should use new one.

Bug: 36794559
Test: MtpDocumentsProviderTests
Change-Id: I84723ee8c3f0f8bfe4d5ea8ad035c01c42ce8bab
2017-04-07 11:13:56 +09:00
Garfield Tan
b690b4de06 Address comments from API council.
Test: Code builds and tests pass. Also some manual tests around ESP.
Bug: 35813037
Bug: 35812990
Change-Id: Ia9d3a3964e9a83d0c1c08e5db4c2e231504aa99a
2017-03-02 12:48:13 -08:00
Daichi Hirono
d3c6dd1522 Start MtpDocumentsService as foreground service.
Prevously MtpDocumentsService was started as background service, then it
turns into a foreground service by calling Service#startForeground.

The workflow did not work until this, because now background activity
cannot launch a background service.

The CL starts using NotificationManager#startForegroundService to launch
MtpDocumentsService so that the service can be started as foreground
service directly.

Bug: 34468813
Test: MtpDocumentsProviderTests
Test: manual testing with connecting MTP device to Android
Change-Id: Ic35d3e92f234881846e5d82ed04d6681a83035f7
2017-02-02 00:13:08 +00:00
Daichi Hirono
e80ea38489 Use public version of AppFuse in MtpDocumentsProvider.
AppFuse is now a public API. The CL removes the private version from
MtpDocuemntsProvider package and switches to the public version.

Bug: 32891253
Test: MtpDocumentsProviderTest
Change-Id: Ibdf67309bc0678e2f70ac2dddb920125d9e0760e
2017-01-19 14:14:00 +09:00
Daichi Hirono
29de7693f4 Add isChildDocument to MtpDocumentsProvider.
Bug: 32687127
Test: adb shell am instrument -w -e class com.android.mtp.MtpDocumentsProviderTest#testIsChildDocument com.android.mtp.tests/com.android.mtp.TestResultInstrumentation
Change-Id: I44ded3c73443735229a8b3465122f7e10c4da178
2016-11-08 09:09:18 +09:00
TreeHugger Robot
2cf7c483a8 Merge "Not create document under the device." 2016-11-07 06:21:48 +00:00
Daichi Hirono
35b2ec551f Not create document under the device.
The structure of files in MtpDocumentsProvider looks like
/device/storage/files. But MtpDocumentsProvider shows files
just under the device if the device has only single storage.

It causes a problem that MtpDocumentsProvider tries to create a file
under the device. Previously it tries to create a file with storageId =
0, which means MTP device choose a storage to store the file.

Because it only happens when the device has a single storage, the file
is properly written to the device. But the database in
MtpDocumentsProvider goes into the illegal state where the file is
placed just under the device.

Bug: 32561572
Test: adb shell am instrument -w -e class com.android.mtp.MtpDocumentsProviderTest com.android.mtp.tests/com.android.mtp.TestResultInstrumentation
Change-Id: I47a373ceee8a64ba9995934317693e79d2497ee0
2016-11-07 10:29:09 +09:00
Garfield Tan
f46a463e41 Change findPath() to findDocumentPath() in MtpDocumentsProvider.
Test: It builds.
Change-Id: If474e766b5680d49a7557f0e7ee1c039eb4efae0
2016-11-02 16:18:33 -07:00
Daichi Hirono
b9ffa2a1d2 Add findPath method to MtpDocumentsProvider.
Bug: 32515515
Test: adb shell am instrument -w -e class com.android.mtp.MtpDocumentsProviderTest com.android.mtp.tests/com.android.mtp.TestResultInstrumentation
Change-Id: Ib87e8f5258de8fd48a099adbf077b3b9ff85773c
2016-11-02 12:33:45 +09:00
Daichi Hirono
76be46f4d9 Fix crash when deleting multiple files.
When deleting files, MtpDocumentsProvider clears LoadingTask in
DocumentsLoader to update directory contents list. Previously it can
clear ongoing task, and it skips calling Mapper#stopAddingDocuments.
Since Mapper#startAddingDocuments and Mapper#stopAddingDocuments must be
called 1 to 1, it causes precondition check failure at the next call of
Mapper#startAddingDocuments.

Change-Id: I23e2b117da826297e45404be4db4cc29f96e5510
Fix: 28076320
2016-04-11 14:32:03 +09:00
Daichi Hirono
f4e7fa8038 Use AppFuse to write document.
Previously MtpDocumentsProvider used pipes to transfer bytes from an
application to the provider when writing a document.  The problem was
application could not ensure that the last chunk of bytes was
successfully written to MTP device, since pipes had been already closed
when the provider transferred bytes to MTP device. Though the provider
encountered an error, the provider could not report the error to an
application.

The CL switches the method to transfer bytes from pipes to AppFuse. Now
application can flush() bytes on the file descriptor, and flush will not
complete until the provider completes writing bytes to MTP device.

Fixed: 23093747
Change-Id: I4e28f8cbf19d6c97e591943349a7535241d768f7
2016-03-29 16:27:59 +09:00
Daichi Hirono
77a1c65610 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
2016-03-28 14:57:23 +09:00
Daichi Hirono
1c431625b3 Merge "Get object size that is more than 4GB." into nyc-dev 2016-03-28 04:36:01 +00:00
Daichi Hirono
64111e08d9 Get object size that is more than 4GB.
MtpObjectInfo contains object size as 32-bit integer and the provider
needs to invoke MtpDevice#getObjectSizeLong hidden API to get 64-bit
object size.

The CL switches to use MtpDevice#getObjectSizeLong hidden API if
MtpObjectInfo#getCompressedSize() returns 0xffffffffL, which means the
object size is more than 4GB.

BUG=27805369

Change-Id: I87ea02c09aa784246cf016def309d1f39ed20e90
2016-03-28 13:34:03 +09:00
Daichi Hirono
09ece6c68b Implement FUSE_WRITE command in app fuse.
The CL adds a handler for FUSE_WRITE command which invokes a Java
handler.

BUG=23093747

Change-Id: I1903fca6b5663e6241ad540a89fe812310ba6810
(cherry picked from commit 35693da25a)
2016-03-25 11:18:44 +09:00
Daichi Hirono
4f04fd358d Fix the logic to add suffix when copying.
Previously the logic add '.' even if the extension is empty.

BUG=27729309

Change-Id: I3fa4b09fea977b5c716ec5cbbbc7d9f4ab96db08
2016-03-22 10:30:47 +09:00
Daichi Hirono
1360868de8 Merge "Add suffix number when copying a file." into nyc-dev 2016-03-17 04:53:35 +00:00
Daichi Hirono
fc7fb7533f Add suffix number when copying a file.
If we have an existing file in the destination directory, which has the
same name with the source file, adding suffix number is
DocumentsProvider's responsibility.

Because MTP does not provide a way to check existance of files with
given name, the logic is implemented as try-and error strategy. The CL
lets If we MtpDocumentsProvider assume we have a file that shares the
same name with the source file if it failed to invoke
MtpDevice#sendObjectInfo. In this case MtpDocumentsProvider retry to
invoke sendObjectInfo with new name with suffix number.

BUG=26991190

Change-Id: I223ac5031f079bc91eb27709b0356f621a1ed55b
2016-03-17 13:52:21 +09:00
Daichi Hirono
4327283240 Merge "Handle SQLite disk IO error in MtpDocumentsProvider#onCreate." into nyc-dev 2016-03-16 07:34:15 +00:00
Daichi Hirono
5884e1fa87 Handle SQLite disk IO error in MtpDocumentsProvider#onCreate.
The error should be regarded as an expected error that failes onCreate,
rather than crash.

BUG=27244513

Change-Id: Icf5164b0cba6cb919077539afe7701ada1e0c247
2016-03-16 14:36:27 +09:00
Daichi Hirono
acb0e27bb3 Regard timeout as an error in the MtpDocumentsProvider test.
Previously if DocumentsProvider found timeout when terminatnig
RootScanner's background thread, it just output it in error log. Thus
the timeout is not regarded as an error in MtpDocumentsProviderTest, and
it makes flaky PipeManagerTest which runs just after
MtpDocumentsProviderTest.

The CL

 * lets MtpDocumentsProvider throw TimeoutException for timeout.
 * removes redundant resumeRootScanner calls to avoid timeout of
   RootScanner#pause.

Also the CL did cleanup the logic that pauses RootScanner when we don't
find any devices. Previously the logic was in
MtpDocumentsProvider#closeInternal but it is not efficient because we
invokes RootScanner#resume just after
MtpDocumentsProvider#closeInternal. Now the CL moves the logic to
RootScanner so that it can pause itself automatically.

BUG=27638500

Change-Id: Ic11bca67c099cbb0f46679db2f035988045d67d6
2016-03-15 11:35:34 +09:00
Daichi Hirono
3bb37e7ff0 Cleans up the metadata in MtpDatabase at the first launch after booting.
When rebooting a device, applicaitons lose temporary URI permissions so
we don't need to keep document ID that are not granted persistent URI
permissions.

 1. Check Settings.Global.BOOT_COUNT to find out if it's first time to
    launch MtpDocumentsProvider since booting.
 2. If so, invokes clean up method of MtpDatabase.

BUG=26212981
Change-Id: Ic9a8ca7e7a9cac1ed91fdfb01e9dce14ce819243
2016-03-09 12:32:22 +09:00
Daichi Hirono
24ab92a5f7 Ensure to complete background thread of PipeManager.
BUG=27488803

Change-Id: Ib540ab42f6263e1aea4c1bb184a4f88aa1454a14
2016-03-04 17:53:03 +09:00
Daichi Hirono
e5b499bcc5 Merge "Fix RootScanner to execute scan at least once before cancelling it." into nyc-dev 2016-03-01 07:50:18 +00:00
Daichi Hirono
2e9a57b0d4 Fix RootScanner to execute scan at least once before cancelling it.
Previously RootScanner is implemented by FutureTask, and if it is
cancelled before it starts running in background thread, the scan will
be never executed.

The CL stops using FutureTask and introduces CountDownLatch to control
UpdateRootsRunnable.

BUG=27369585

Change-Id: Ica8799faba0a8e5ca91a6b8be36dc4f5118d6333
2016-03-01 13:51:06 +09:00
Daichi Hirono
61ba923ca0 Set document flag by referring MTP supported operations.
BUG=26147375

Change-Id: I6c4244f1f1153c1bbbf21ea9d608dc1a92ca70cd
2016-02-26 16:23:30 +09:00
Daichi Hirono
0f32537e40 Stops performing operations that does not supported by MTP device.
MTP devices can return supported operation list. The CL sets root flag
by referring it.

BUG=26147375

Change-Id: I02397821e208cf5a8fcf7457aa279d2818ce24c7
2016-02-26 16:20:02 +09:00
Daichi Hirono
4e94b8deaa Resolve unmapped document when the device is connected.
Once MTP device is disconnected from Android, the files on MTP device
are marked as 'DISCONNECTED' in metadata database. These metadata will
be back when MtpDocumentsProvider finds the reconnected MTP device and
fetches the files again.

Previously the 'DISCONNECTED' files are not automatically
refetched. User needs to see files in Documents UI again to reuse
document ID of 'DISCONNECTED' files. The CL changes DocumentLoader so
that it automatically refetches disconnected documents.

BUG=26212981

Change-Id: I5cb2cc9c11af72632e481c59a505794f43ed62ea
2016-02-23 14:39:08 +09:00
Daichi Hirono
f578fa275a Update object info when writing a file.
The MTP spec does not offer a way to update bytes of exisitng files, so
our provider implementation creates a new file with new bytes and
removes old one.

Previously the new file uses new document ID and the exising document ID
is expired. Also the provider does not update the metadata
database. Thus users see the old flie in DocumentsUI but actually the
files is not accessible.

The CL updates the database with exisitng document ID, so that we can
access the new file with exisiting document ID.

BUG=26549400

Change-Id: I629b707a2e662b34625e8b28857ef818d8933996
2016-02-19 18:05:42 +09:00
Daichi Hirono
ebd2405159 Use device key to map device documents.
The CL introduces MAPPING_KEY column to the database and lets Mapper use
the column to map IDs of devices.

It also removes the concept of mapping mode from Mapper for
simplyfing. Now Mapper just tries to multiple mapping keys (MTP
identifier, display name, and mapping key) to find candidate of ID
mapping.

BUG=26212981

Change-Id: I19f6c7dac146047e9978de4eb33d5076406037ad
(cherry picked from commit 637a2010f4)
2016-02-17 08:18:13 +00:00
Daichi Hirono
0abde68519 Merge "Add error message for locked device." into nyc-dev 2016-02-12 02:51:17 +00:00
Daichi Hirono
2965776ba4 Add error message for locked device.
If the remote MTP device is a smartphone, it does not provide files
until a user unlocks the device. The CL adds specific error message for
the situation.

BUG=26318917

Change-Id: Ic4c34609c55ec9c99b7b8a9143d6dae3835784e3
2016-02-11 18:45:30 -08:00
Daichi Hirono
46d537716e Merge "Open the connected device in Files app when tapping notification." into nyc-dev 2016-02-12 02:38:29 +00:00
Daichi Hirono
1e3744441a Open the connected device in Files app when tapping notification.
Previously when tapping the MTP devce notification, MtpDocumentsProvider
opens home direcotry in Files app. The CL adds data URI of connected
device to the intent so that MtpDocumentsProvider can open the connected
device's root in Files app.

BUG=26611224
Change-Id: I97ecd6669852cd2fc875294cbcbf5660fbfaa0da
2016-02-11 16:36:49 -08:00
Daichi Hirono
c18f8076eb Show specific error message for busy device.
When MTP device is busy (e.g. used by other application),
MtpDocumentsProvider cannot open the device. The CL introduces specific
error message for the case.

BUG=26694828

Change-Id: Iffee2e1c554e4089601186469ff0eac2fd04decd
2016-02-11 12:45:55 -08:00
Daichi Hirono
6213cefbc0 Fetch mime type from file name when format code does not help.
MTP spec defines format code as a file type of object, but we don't have
format code for some file types like PDF. This CL adds fallback that
tries to obtain mime type from file name in such case.

BUG=27004957

Change-Id: Id61352bf4726f4e044e57edadcefbf179fe3f882
2016-02-05 17:21:13 +09:00
Daichi Hirono
f83ccbd7ed Drop device name from storage document name.
When device has multiple storages, storage are shown as directory under
the device root. In this case, we would not like to add device name to
storage.

Note that we still use "device name + storage name" for root name if the
device has a single storage because we skip storage directory in this
case and shows storage's contents directly under the device.

BUG=26625708

Change-Id: Ie13b044e71ae9b5131c4a01ee9d605023d05f168
2016-02-04 17:27:52 +09:00
Daichi Hirono
19aa93249e Fix Identifier.equals method.
Previously the string was compared by ==.

BUG=26970351

Change-Id: If88b74392955388c9bf59002f2d2a186c2dff71a
2016-02-04 14:19:52 +09:00
Daichi Hirono
fda7474c5f Open MTP device on demand.
Previously MtpDocumentsProvider opens a device just after device is
connected to Android. But MtpDocumentsProvider should open MTP device on
demand so that other applications can open device if user starts to use
the application before using MtpDocumentsProvider.

BUG=26625708

Change-Id: I6083b8c7cef49ee6e9fb0d15ca4adc129734f3eb
2016-02-04 12:45:58 +09:00
Daichi Hirono
6a5ea7eae8 Move logic to skip single storage.
The tree structure of MTP model looks like /device/storage/objects. But
almost all MTP device has only single storage, so it's redundant to show
a single storage as a child of device in UI.

MtpDocumentsProvider has a special logic to skip single storage, and
shows storage's object as a children of device in such case. Previously
the logic was applied when MtpDocumentsProvider returned a root
list. The provider returns a storage as a Documents.Root, instead of
device if the device has only one storage.

However the number of root cannot be obtain for closed device. Thus the
previous logic did not work for closed devices that have a single
storage. The CL moves the logic from queryRoot to
queryChildDocuments. Now MtpDocumentsProvider always returns a device as
root, then it returns storage's objects as the device's children, where
we has already opened the device.

BUG=26481574

Change-Id: I25af0fc220410e321a378d67f226798ec4bba19c
2016-02-03 15:53:48 +09:00
Daichi Hirono
2f310f6d5d Reuse buffer when reading bytes from files.
Previously AppFuse getObjectBytes returns byte array and the array's
length needs to equals to the exact number of bytes the method read.

The CL change the function signature so that it can return the number of
read bytes. And reuse a buffer array instead of slicing the array with
valid length.

BUG=None

Change-Id: I78b714554cac9ae71b895cb8929bc98969f5a8ca
2016-01-28 14:09:26 +09:00
Daichi Hirono
b36b15586a Fix bugs that prevent from using AppFuse.
* Allow buffer size that is greater than requested read size in JNI,
   because we reuse fixed-size buffer among multiple requests.
 * Fix condition to check if the file size is greater than 4GB or
   not. We need to use 0xffffffffl instead of 0xffffffff because
   0xffffffff is int and its value is -1.

BUG=None
Change-Id: I155916e139353b15dc1ab535234faf50d942996d
2016-01-26 16:30:08 +09:00
Daichi Hirono
e6054c0ff0 Fix race in AppFuseTest.
Previously IllegalStateException is thrown in app fuse main loop, if the
loop thread starts just after closing device FD.

BUG=None

Change-Id: Ia5232857d29f9f324446aa38acf3c062f359d406
2016-01-21 10:51:25 +09:00
Daichi Hirono
f52ef008c7 Start to use app fuse in MtpDocumentsProvider.
BUG=25756419

Change-Id: I050e7cf7523926710291875737602e95c47be088
2016-01-19 11:20:59 +09:00
Daichi Hirono
8e3b9db544 Stop to remove device rows at MtpDocumentsProvider.
Previously MtpDocumentsProvider used to remove device info in the
database when the device is closed. It loses a chance that RootScanner
handles the removal of roots. As a result, notifications for root cursor
does not issued.

The CL stops removing device info at MtpDocumentsProvider, and let
RootScanner remove it.

BUG=26321346

Change-Id: I6aec0cf843a1e5c93e7f67a718cabd26841d9799
2015-12-25 15:59:47 +09:00
Daichi Hirono
20754c5a11 Store device document even if the device is not opened.
BUG=26197156

Change-Id: I2a80bb3e85310cf63253173b1110a155ee1391ba
2015-12-16 09:52:56 +09:00
Daichi Hirono
b3fe72bfb2 Revert "Revert "Add device document to MtpDatabase.""
I suspected that the commit was conflicted with ag/833494, but actually it wasn't. Let me reland this CL again.

This reverts commit b63e8c6ccc.

Change-Id: I4e734422ce10ef93ee7c4ef3b8b72a81beaa769b
2015-12-15 07:45:06 +00:00
Daichi Hirono
b63e8c6ccc Revert "Add device document to MtpDatabase."
This reverts commit c0ae45be04.

Change-Id: I03337324e768c509bdcf94c89f7abe7ca00c8a18
2015-12-15 07:34:26 +00:00