MtpManagerTest.java revision f26af124e3552f18f127eabf88ebcb9e13a80855
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
17package com.android.mtp;
18
19import android.app.PendingIntent;
20import android.content.BroadcastReceiver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.IntentFilter;
24import android.hardware.usb.UsbDevice;
25import android.hardware.usb.UsbDeviceConnection;
26import android.hardware.usb.UsbManager;
27import android.os.CancellationSignal;
28import android.os.OperationCanceledException;
29import android.test.InstrumentationTestCase;
30
31import java.io.IOException;
32import java.util.HashMap;
33import java.util.concurrent.CountDownLatch;
34
35@RealDeviceTest
36public class MtpManagerTest extends InstrumentationTestCase {
37    private static final String ACTION_USB_PERMISSION =
38            "com.android.mtp.USB_PERMISSION";
39    private static final int TIMEOUT_MS = 1000;
40    UsbManager mUsbManager;
41    MtpManager mManager;
42    UsbDevice mUsbDevice;
43    int mRequest;
44
45    @Override
46    public void setUp() throws Exception {
47        mUsbManager = getContext().getSystemService(UsbManager.class);
48        for (int i = 0; i < 2; i++) {
49            mUsbDevice = findDevice();
50            mManager = new MtpManager(getContext());
51            mManager.openDevice(mUsbDevice.getDeviceId());
52            try {
53                waitForStorages(mManager, mUsbDevice.getDeviceId());
54                return;
55            } catch (IOException exp) {
56                // When the MTP device is Android, and it changes the USB device type from
57                // "Charging" to "MTP", the device ID will be updated. We need to find a device
58                // again.
59                continue;
60            }
61        }
62    }
63
64    @Override
65    public void tearDown() throws IOException {
66        mManager.closeDevice(mUsbDevice.getDeviceId());
67    }
68
69    public void testCancelEvent() throws Exception {
70        final CancellationSignal signal = new CancellationSignal();
71        final Thread thread = new Thread() {
72            @Override
73            public void run() {
74                try {
75                    mManager.readEvent(mUsbDevice.getDeviceId(), signal);
76                } catch (OperationCanceledException | IOException e) {
77                    show(e.getMessage());
78                }
79            }
80        };
81        thread.start();
82        Thread.sleep(TIMEOUT_MS);
83        signal.cancel();
84        thread.join(TIMEOUT_MS);
85    }
86
87    private void requestPermission(UsbDevice device) throws InterruptedException {
88        if (mUsbManager.hasPermission(device)) {
89            return;
90        }
91        final CountDownLatch latch = new CountDownLatch(1);
92        final BroadcastReceiver receiver = new BroadcastReceiver() {
93            @Override
94            public void onReceive(Context context, Intent intent) {
95                latch.countDown();
96                getInstrumentation().getTargetContext().unregisterReceiver(this);
97            }
98        };
99        getInstrumentation().getTargetContext().registerReceiver(
100                receiver, new IntentFilter(ACTION_USB_PERMISSION));
101        mUsbManager.requestPermission(device, PendingIntent.getBroadcast(
102                getInstrumentation().getTargetContext(),
103                0 /* requstCode */,
104                new Intent(ACTION_USB_PERMISSION),
105                0 /* flags */));
106        latch.await();
107        assertTrue(mUsbManager.hasPermission(device));
108    }
109
110    private UsbDevice findDevice() throws InterruptedException {
111        while (true) {
112            final HashMap<String,UsbDevice> devices = mUsbManager.getDeviceList();
113            if (devices.size() == 0) {
114                show("Wait for devices.");
115                Thread.sleep(1000);
116                continue;
117            }
118            final UsbDevice device = devices.values().iterator().next();
119            requestPermission(device);
120            final UsbDeviceConnection connection = mUsbManager.openDevice(device);
121            if (connection == null) {
122                fail("Cannot open USB connection.");
123            }
124            for (int i = 0; i < device.getInterfaceCount(); i++) {
125                // Since the test runs real environment, we need to call claim interface with
126                // force = true to rob interfaces from other applications.
127                connection.claimInterface(device.getInterface(i), true);
128                connection.releaseInterface(device.getInterface(i));
129            }
130            connection.close();
131            return device;
132        }
133    }
134
135    private void waitForStorages(MtpManager manager, int deviceId) throws Exception {
136        while (true) {
137            if (manager.getRoots(deviceId).length == 0) {
138                show("Wait for storages.");
139                Thread.sleep(1000);
140                continue;
141            }
142            return;
143        }
144    }
145
146    private void show(String message) {
147        if (!(getInstrumentation() instanceof TestResultInstrumentation)) {
148            return;
149        }
150        ((TestResultInstrumentation) getInstrumentation()).show(message);
151    }
152
153    private Context getContext() {
154        return getInstrumentation().getContext();
155    }
156}
157