1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.mtp; 18 19 import android.content.Context; 20 import android.hardware.usb.UsbDevice; 21 import android.hardware.usb.UsbManager; 22 import android.mtp.MtpConstants; 23 import android.mtp.MtpEvent; 24 import android.mtp.MtpObjectInfo; 25 import android.os.CancellationSignal; 26 import android.os.OperationCanceledException; 27 import android.os.ParcelFileDescriptor; 28 import android.os.SystemClock; 29 import android.test.InstrumentationTestCase; 30 31 import java.io.IOException; 32 import java.util.Arrays; 33 import java.util.concurrent.Callable; 34 import java.util.concurrent.FutureTask; 35 import java.util.concurrent.TimeUnit; 36 37 @RealDeviceTest 38 public class MtpManagerTest extends InstrumentationTestCase { 39 private static final int TIMEOUT_MS = 1000; 40 UsbManager mUsbManager; 41 MtpManager mManager; 42 UsbDevice mUsbDevice; 43 44 @Override setUp()45 public void setUp() throws Exception { 46 mUsbManager = getContext().getSystemService(UsbManager.class); 47 mManager = new MtpManager(getContext()); 48 mUsbDevice = TestUtil.setupMtpDevice(getInstrumentation(), mUsbManager, mManager); 49 } 50 51 @Override tearDown()52 public void tearDown() throws IOException { 53 mManager.closeDevice(mUsbDevice.getDeviceId()); 54 } 55 56 @Override getInstrumentation()57 public TestResultInstrumentation getInstrumentation() { 58 return (TestResultInstrumentation) super.getInstrumentation(); 59 } 60 testCancelEvent()61 public void testCancelEvent() throws Exception { 62 final CancellationSignal signal = new CancellationSignal(); 63 final FutureTask<Boolean> future = new FutureTask<Boolean>( 64 new Callable<Boolean>() { 65 @Override 66 public Boolean call() throws IOException { 67 try { 68 while (true) { 69 mManager.readEvent(mUsbDevice.getDeviceId(), signal); 70 } 71 } catch (OperationCanceledException exception) { 72 return true; 73 } 74 } 75 }); 76 final Thread thread = new Thread(future); 77 thread.start(); 78 SystemClock.sleep(TIMEOUT_MS); 79 signal.cancel(); 80 assertTrue(future.get(TIMEOUT_MS, TimeUnit.MILLISECONDS)); 81 } 82 testOperationsSupported()83 public void testOperationsSupported() { 84 final MtpDeviceRecord[] records = mManager.getDevices(); 85 assertEquals(1, records.length); 86 assertNotNull(records[0].operationsSupported); 87 getInstrumentation().show(Arrays.toString(records[0].operationsSupported)); 88 } 89 testEventsSupported()90 public void testEventsSupported() { 91 final MtpDeviceRecord[] records = mManager.getDevices(); 92 assertEquals(1, records.length); 93 assertNotNull(records[0].eventsSupported); 94 getInstrumentation().show(Arrays.toString(records[0].eventsSupported)); 95 } 96 testDeviceKey()97 public void testDeviceKey() { 98 final MtpDeviceRecord[] records = mManager.getDevices(); 99 assertEquals(1, records.length); 100 assertNotNull(records[0].deviceKey); 101 getInstrumentation().show("deviceKey: " + records[0].deviceKey); 102 } 103 testEventObjectAdded()104 public void testEventObjectAdded() throws Exception { 105 while (true) { 106 getInstrumentation().show("Please take a photo by using connected MTP device."); 107 final CancellationSignal signal = new CancellationSignal(); 108 MtpEvent event = mManager.readEvent(mUsbDevice.getDeviceId(), signal); 109 if (event.getEventCode() != MtpConstants.EVENT_OBJECT_ADDED) { 110 continue; 111 } 112 assertTrue(event.getObjectHandle() != 0); 113 break; 114 } 115 } 116 testCreateDocumentAndGetPartialObject()117 public void testCreateDocumentAndGetPartialObject() throws Exception { 118 int storageId = 0; 119 for (final MtpDeviceRecord record : mManager.getDevices()) { 120 if (record.deviceId == mUsbDevice.getDeviceId()) { 121 storageId = record.roots[0].mStorageId; 122 break; 123 } 124 } 125 assertTrue("Valid storage not found.", storageId != 0); 126 127 final String testFileName = "MtpManagerTest_testFile.txt"; 128 for (final int handle : mManager.getObjectHandles( 129 mUsbDevice.getDeviceId(), storageId, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN)) { 130 if (mManager.getObjectInfo(mUsbDevice.getDeviceId(), handle) 131 .getName().equals(testFileName)) { 132 mManager.deleteDocument(mUsbDevice.getDeviceId(), handle); 133 break; 134 } 135 } 136 137 final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe(); 138 final byte[] expectedBytes = "Hello Android!".getBytes("ascii"); 139 try (final ParcelFileDescriptor.AutoCloseOutputStream stream = 140 new ParcelFileDescriptor.AutoCloseOutputStream(fds[1])) { 141 stream.write(expectedBytes); 142 } 143 final int objectHandle = mManager.createDocument( 144 mUsbDevice.getDeviceId(), 145 new MtpObjectInfo.Builder() 146 .setStorageId(storageId) 147 .setName(testFileName) 148 .setCompressedSize(expectedBytes.length) 149 .setFormat(MtpConstants.FORMAT_TEXT) 150 .build(), 151 fds[0]); 152 final byte[] bytes = new byte[100]; 153 assertEquals(5, mManager.getPartialObject( 154 mUsbDevice.getDeviceId(), objectHandle, 0, 5, bytes)); 155 assertEquals("Hello", new String(bytes, 0, 5, "ascii")); 156 assertEquals(8, mManager.getPartialObject( 157 mUsbDevice.getDeviceId(), objectHandle, 6, 100, bytes)); 158 assertEquals("Android!", new String(bytes, 0, 8, "ascii")); 159 } 160 getContext()161 private Context getContext() { 162 return getInstrumentation().getContext(); 163 } 164 } 165