Merge "Add openDevice and closeDevice methods to MtpDocumentsProvider."

This commit is contained in:
Daichi Hirono
2015-07-27 07:00:56 +00:00
committed by Android (Google) Code Review
4 changed files with 197 additions and 7 deletions

View File

@@ -5,6 +5,8 @@ LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := MtpDocumentsProvider
LOCAL_CERTIFICATE := media
LOCAL_PROGUARD_FLAGS := '-keepclassmembers class * {' \
' @com.android.internal.annotations.VisibleForTesting *; }'
include $(BUILD_PACKAGE)
include $(LOCAL_PATH)/tests/Android.mk

View File

@@ -16,14 +16,24 @@
package com.android.mtp;
import android.content.ContentResolver;
import android.database.Cursor;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;
import android.provider.DocumentsProvider;
import java.io.FileNotFoundException;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* DocumentsProvider for MTP devices.
*/
public class MtpDocumentsProvider extends DocumentsProvider {
private static final String TAG = "MtpDocumentsProvider";
public static final String AUTHORITY = "com.android.mtp.documents";
@@ -40,32 +50,89 @@ public class MtpDocumentsProvider extends DocumentsProvider {
Document.COLUMN_FLAGS, Document.COLUMN_SIZE,
};
private MtpManager mDeviceModel;
private ContentResolver mResolver;
@Override
public boolean onCreate() {
mDeviceModel = new MtpManager(getContext());
mResolver = getContext().getContentResolver();
return true;
}
@VisibleForTesting
void onCreateForTesting(MtpManager deviceModel, ContentResolver resolver) {
this.mDeviceModel = deviceModel;
this.mResolver = resolver;
}
@Override
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
return null;
throw new FileNotFoundException();
}
@Override
public Cursor queryDocument(String documentId, String[] projection)
throws FileNotFoundException {
return null;
throw new FileNotFoundException();
}
@Override
public Cursor queryChildDocuments(String parentDocumentId,
String[] projection, String sortOrder)
throws FileNotFoundException {
return null;
throw new FileNotFoundException();
}
@Override
public ParcelFileDescriptor openDocument(String documentId, String mode,
CancellationSignal signal) throws FileNotFoundException {
return null;
throw new FileNotFoundException();
}
// TODO: Remove annotation when the method starts to be used.
@VisibleForTesting
void openDevice(int deviceId) {
try {
mDeviceModel.openDevice(deviceId);
notifyRootsUpdate();
} catch (IOException error) {
Log.d(TAG, "Failed to open the MTP device: " + deviceId);
}
}
// TODO: Remove annotation when the method starts to be used.
@VisibleForTesting
void closeDevice(int deviceId) {
try {
mDeviceModel.closeDevice(deviceId);
notifyRootsUpdate();
} catch (IOException error) {
Log.d(TAG, "Failed to close the MTP device: " + deviceId);
}
}
// TODO: Remove annotation when the method starts to be used.
@VisibleForTesting
void closeAllDevices() {
boolean closed = false;
for (int deviceId : mDeviceModel.getOpenedDeviceIds()) {
try {
mDeviceModel.closeDevice(deviceId);
closed = true;
} catch (IOException d) {
Log.d(TAG, "Failed to close the MTP device: " + deviceId);
}
}
if (closed) {
notifyRootsUpdate();
}
}
private void notifyRootsUpdate() {
mResolver.notifyChange(
DocumentsContract.buildRootsUri(MtpDocumentsProvider.AUTHORITY),
null,
false);
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.mtp;
import android.content.Context;
import java.io.IOException;
/**
* The model wrapping android.mtp API.
*/
class MtpManager {
MtpManager(Context context) {
}
void openDevice(int deviceId) throws IOException {
// TODO: Implement this method.
}
void closeDevice(int deviceId) throws IOException {
// TODO: Implement this method.
}
int[] getOpenedDeviceIds() {
// TODO: Implement this method.
return null;
}
}

View File

@@ -16,13 +16,92 @@
package com.android.mtp;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.test.AndroidTestCase;
import android.test.mock.MockContentResolver;
import android.test.suitebuilder.annotation.SmallTest;
import java.io.IOException;
@SmallTest
public class MtpDocumentsProviderTest extends AndroidTestCase {
public void testBasic() {
public void testOpenAndCloseDevice() throws Exception {
final ContentResolver resolver = new ContentResolver();
final MtpDocumentsProvider provider = new MtpDocumentsProvider();
assertNotNull(provider);
provider.onCreateForTesting(new MtpManagerMock(getContext()), resolver);
provider.openDevice(MtpManagerMock.SUCCESS_DEVICE_ID);
assertEquals(1, resolver.changeCount);
provider.closeDevice(MtpManagerMock.SUCCESS_DEVICE_ID);
assertEquals(2, resolver.changeCount);
provider.openDevice(MtpManagerMock.FAILURE_DEVICE_ID);
assertEquals(2, resolver.changeCount);
provider.closeDevice(MtpManagerMock.FAILURE_DEVICE_ID);
assertEquals(2, resolver.changeCount);
}
public void testCloseAllDevices() {
final ContentResolver resolver = new ContentResolver();
final MtpDocumentsProvider provider = new MtpDocumentsProvider();
provider.onCreateForTesting(new MtpManagerMock(getContext()), resolver);
provider.closeAllDevices();
assertEquals(0, resolver.changeCount);
provider.openDevice(MtpManagerMock.SUCCESS_DEVICE_ID);
assertEquals(1, resolver.changeCount);
provider.closeAllDevices();
assertEquals(2, resolver.changeCount);
}
private static class MtpManagerMock extends MtpManager {
final static int SUCCESS_DEVICE_ID = 1;
final static int FAILURE_DEVICE_ID = 2;
private boolean opened = false;
MtpManagerMock(Context context) {
super(context);
}
@Override
void openDevice(int deviceId) throws IOException {
if (deviceId == SUCCESS_DEVICE_ID) {
opened = true;
} else {
throw new IOException();
}
}
@Override
void closeDevice(int deviceId) throws IOException {
if (opened && deviceId == SUCCESS_DEVICE_ID) {
opened = false;
} else {
throw new IOException();
}
}
@Override
int[] getOpenedDeviceIds() {
if (opened) {
return new int[] { SUCCESS_DEVICE_ID };
} else {
return new int[0];
}
}
}
private static class ContentResolver extends MockContentResolver {
int changeCount = 0;
@Override
public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
changeCount++;
}
}
}