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() != MtpEvent.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