Merge "Update object info when writing a file." into nyc-dev

am: 073f5aaec7

* commit '073f5aaec7256a693dbe09489ddd433ea8267898':
  Update object info when writing a file.
This commit is contained in:
Daichi Hirono
2016-02-22 03:11:26 +00:00
committed by android-build-merger
7 changed files with 94 additions and 32 deletions

View File

@@ -581,6 +581,23 @@ class MtpDatabase {
}
}
void updateObject(String documentId, int deviceId, String parentId, MtpObjectInfo info) {
final ContentValues values = new ContentValues();
getObjectDocumentValues(values, deviceId, parentId, info);
mDatabase.beginTransaction();
try {
mDatabase.update(
TABLE_DOCUMENTS,
values,
Document.COLUMN_DOCUMENT_ID + " = ?",
strings(documentId));
mDatabase.setTransactionSuccessful();
} finally {
mDatabase.endTransaction();
}
}
private static class OpenHelper extends SQLiteOpenHelper {
public OpenHelper(Context context, int flags) {
super(context,

View File

@@ -486,7 +486,7 @@ public class MtpDocumentsProvider extends DocumentsProvider {
public final DocumentLoader mDocumentLoader;
public DeviceToolkit(MtpManager manager, ContentResolver resolver, MtpDatabase database) {
mPipeManager = new PipeManager();
mPipeManager = new PipeManager(database);
mDocumentLoader = new DocumentLoader(manager, resolver, database);
}
}

View File

@@ -29,12 +29,14 @@ import java.util.concurrent.Executors;
class PipeManager {
final ExecutorService mExecutor;
final MtpDatabase mDatabase;
PipeManager() {
this(Executors.newSingleThreadExecutor());
PipeManager(MtpDatabase database) {
this(database, Executors.newSingleThreadExecutor());
}
PipeManager(ExecutorService executor) {
PipeManager(MtpDatabase database, ExecutorService executor) {
this.mDatabase = database;
this.mExecutor = executor;
}
@@ -46,7 +48,7 @@ class PipeManager {
ParcelFileDescriptor writeDocument(Context context, MtpManager model, Identifier identifier)
throws IOException {
final Task task = new WriteDocumentTask(context, model, identifier);
final Task task = new WriteDocumentTask(context, model, identifier, mDatabase);
mExecutor.execute(task);
return task.getWritingFileDescriptor();
}
@@ -100,11 +102,14 @@ class PipeManager {
private static class WriteDocumentTask extends Task {
private final Context mContext;
private final MtpDatabase mDatabase;
WriteDocumentTask(Context context, MtpManager model, Identifier identifier)
WriteDocumentTask(
Context context, MtpManager model, Identifier identifier, MtpDatabase database)
throws IOException {
super(model, identifier);
mContext = context;
mDatabase = database;
}
@Override
@@ -112,7 +117,7 @@ class PipeManager {
File tempFile = null;
try {
// Obtain a temporary file and copy the data to it.
tempFile = mContext.getCacheDir().createTempFile("mtp", "tmp");
tempFile = File.createTempFile("mtp", "tmp", mContext.getCacheDir());
try (
final FileOutputStream tempOutputStream =
new ParcelFileDescriptor.AutoCloseOutputStream(
@@ -140,12 +145,22 @@ class PipeManager {
// Create the target object info with a correct file size and upload the file.
final MtpObjectInfo targetObjectInfo =
new MtpObjectInfo.Builder(placeholderObjectInfo)
.setCompressedSize((int) tempFile.length())
.setCompressedSize(tempFile.length())
.build();
final ParcelFileDescriptor tempInputDescriptor = ParcelFileDescriptor.open(
tempFile, ParcelFileDescriptor.MODE_READ_ONLY);
mManager.createDocument(mIdentifier.mDeviceId,
targetObjectInfo, tempInputDescriptor);
final int newObjectHandle = mManager.createDocument(
mIdentifier.mDeviceId, targetObjectInfo, tempInputDescriptor);
final MtpObjectInfo newObjectInfo = mManager.getObjectInfo(
mIdentifier.mDeviceId, newObjectHandle);
final Identifier parentIdentifier =
mDatabase.getParentIdentifier(mIdentifier.mDocumentId);
mDatabase.updateObject(
mIdentifier.mDocumentId,
mIdentifier.mDeviceId,
parentIdentifier.mDocumentId,
newObjectInfo);
} catch (IOException error) {
Log.w(MtpDocumentsProvider.TAG,
"Failed to send a file because of: " + error.getMessage());

View File

@@ -983,18 +983,10 @@ public class MtpDatabaseTest extends AndroidTestCase {
}
private void addTestDevice() throws FileNotFoundException {
mDatabase.getMapper().startAddingDocuments(null);
mDatabase.getMapper().putDeviceDocument(new MtpDeviceRecord(
0, "Device", "device_key", /* opened is */ true, new MtpRoot[0], null,
null));
mDatabase.getMapper().stopAddingDocuments(null);
TestUtil.addTestDevice(mDatabase);
}
private void addTestStorage(String parentId) throws FileNotFoundException {
mDatabase.getMapper().startAddingDocuments(parentId);
mDatabase.getMapper().putStorageDocuments(parentId, new MtpRoot[] {
new MtpRoot(0, 100, "Storage", 1024, 1024, ""),
});
mDatabase.getMapper().stopAddingDocuments(parentId);
TestUtil.addTestStorage(mDatabase, parentId);
}
}

View File

@@ -16,8 +16,10 @@
package com.android.mtp;
import android.database.Cursor;
import android.mtp.MtpObjectInfo;
import android.os.ParcelFileDescriptor;
import android.provider.DocumentsContract.Document;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
@@ -33,12 +35,14 @@ public class PipeManagerTest extends AndroidTestCase {
private TestMtpManager mtpManager;
private ExecutorService mExecutor;
private PipeManager mPipeManager;
private MtpDatabase mDatabase;
@Override
public void setUp() {
mtpManager = new TestMtpManager(getContext());
mExecutor = Executors.newSingleThreadExecutor();
mPipeManager = new PipeManager(mExecutor);
mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
mPipeManager = new PipeManager(mDatabase, mExecutor);
}
public void testReadDocument_basic() throws Exception {
@@ -57,25 +61,32 @@ public class PipeManagerTest extends AndroidTestCase {
}
public void testWriteDocument_basic() throws Exception {
TestUtil.addTestDevice(mDatabase);
TestUtil.addTestStorage(mDatabase, "1");
final MtpObjectInfo info =
new MtpObjectInfo.Builder().setObjectHandle(1).setName("note.txt").build();
mDatabase.getMapper().startAddingDocuments("2");
mDatabase.getMapper().putChildDocuments(0, "2", new MtpObjectInfo[] { info });
mDatabase.getMapper().stopAddingDocuments("2");
// Create a placeholder file which should be replaced by a real file later.
mtpManager.setObjectInfo(0, new MtpObjectInfo.Builder()
.setObjectHandle(1)
.build());
mtpManager.setObjectInfo(0, info);
// Upload testing bytes.
final ParcelFileDescriptor descriptor = mPipeManager.writeDocument(
getContext(),
mtpManager,
new Identifier(0, 0, 1, null, MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT));
new Identifier(0, 0, 1, "2", MtpDatabaseConstants.DOCUMENT_TYPE_OBJECT));
final ParcelFileDescriptor.AutoCloseOutputStream outputStream =
new ParcelFileDescriptor.AutoCloseOutputStream(descriptor);
outputStream.write(HELLO_BYTES, 0, HELLO_BYTES.length);
outputStream.close();
mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS);
mExecutor.shutdown();
assertTrue(mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS));
// Check if the placeholder file is removed.
try {
final MtpObjectInfo placeholderDocument = mtpManager.getObjectInfo(0, 1);
mtpManager.getObjectInfo(0, 1);
fail(); // The placeholder file has not been deleted.
} catch (IOException e) {
// Expected error, as the file is gone.
@@ -86,6 +97,14 @@ public class PipeManagerTest extends AndroidTestCase {
0, TestMtpManager.CREATED_DOCUMENT_HANDLE);
assertTrue(targetDocument != null);
// Confirm the object handle is updated.
try (final Cursor cursor = mDatabase.queryDocument(
"2", new String[] { MtpDatabaseConstants.COLUMN_OBJECT_HANDLE })) {
assertEquals(1, cursor.getCount());
cursor.moveToNext();
assertEquals(TestMtpManager.CREATED_DOCUMENT_HANDLE, cursor.getInt(0));
}
// Verify uploaded bytes.
final byte[] uploadedBytes = mtpManager.getImportFileBytes(
0, TestMtpManager.CREATED_DOCUMENT_HANDLE);
@@ -112,7 +131,8 @@ public class PipeManagerTest extends AndroidTestCase {
private void assertDescriptor(ParcelFileDescriptor descriptor, byte[] expectedBytes)
throws IOException, InterruptedException {
mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS);
mExecutor.shutdown();
assertTrue(mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS));
try (final ParcelFileDescriptor.AutoCloseInputStream stream =
new ParcelFileDescriptor.AutoCloseInputStream(descriptor)) {
byte[] results = new byte[100];
@@ -125,7 +145,8 @@ public class PipeManagerTest extends AndroidTestCase {
private void assertDescriptorError(ParcelFileDescriptor descriptor)
throws InterruptedException {
mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS);
mExecutor.shutdown();
assertTrue(mExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS));
try {
descriptor.checkError();
fail();

View File

@@ -149,7 +149,9 @@ public class TestMtpManager extends MtpManager {
if (mObjectInfos.containsKey(key)) {
throw new IOException();
}
mObjectInfos.put(key, objectInfo);
final MtpObjectInfo newInfo = new MtpObjectInfo.Builder(objectInfo).
setObjectHandle(CREATED_DOCUMENT_HANDLE).build();
mObjectInfos.put(key, newInfo);
if (objectInfo.getFormat() != 0x3001) {
try (final ParcelFileDescriptor.AutoCloseInputStream inputStream =
new ParcelFileDescriptor.AutoCloseInputStream(source)) {

View File

@@ -21,12 +21,11 @@ import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.os.SystemClock;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Objects;
import junit.framework.Assert;
/**
* Static utility methods for testing.
*/
@@ -57,6 +56,22 @@ final class TestUtil {
}
}
static void addTestDevice(MtpDatabase database) throws FileNotFoundException {
database.getMapper().startAddingDocuments(null);
database.getMapper().putDeviceDocument(new MtpDeviceRecord(
0, "Device", "device_key", /* opened is */ true, new MtpRoot[0], null,
null));
database.getMapper().stopAddingDocuments(null);
}
static void addTestStorage(MtpDatabase database, String parentId) throws FileNotFoundException {
database.getMapper().startAddingDocuments(parentId);
database.getMapper().putStorageDocuments(parentId, new MtpRoot[] {
new MtpRoot(0, 100, "Storage", 1024, 1024, ""),
});
database.getMapper().stopAddingDocuments(parentId);
}
private static UsbDevice findMtpDevice(
UsbManager usbManager,
MtpManager manager) throws IOException {