TestUtil.java revision af5ea38b8c51f0878e4070671e240f693f3ad796
1b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono/*
2b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono * Copyright (C) 2015 The Android Open Source Project
3b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono *
4b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono * Licensed under the Apache License, Version 2.0 (the "License");
5b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono * you may not use this file except in compliance with the License.
6b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono * You may obtain a copy of the License at
7b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono *
8b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono *      http://www.apache.org/licenses/LICENSE-2.0
9b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono *
10b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono * Unless required by applicable law or agreed to in writing, software
11b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono * distributed under the License is distributed on an "AS IS" BASIS,
12b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono * See the License for the specific language governing permissions and
14b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono * limitations under the License.
15b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono */
16b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono
17b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hironopackage com.android.mtp;
18b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono
19b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hironoimport android.hardware.usb.UsbDevice;
20b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hironoimport android.hardware.usb.UsbDeviceConnection;
21b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hironoimport android.hardware.usb.UsbManager;
22b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono
23b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hironoimport java.io.IOException;
24b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hironoimport java.util.HashMap;
25b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hironoimport junit.framework.Assert;
26b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono
27b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono/**
28b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono * Static utility methods for testing.
29b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono */
3099b58052f85c18272e63047b471edfd8089c09d3Daichi Hironofinal class TestUtil {
31b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono    private TestUtil() {}
32b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono
33b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono    /**
34b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono     * Requests permission for a MTP device and returns the first MTP device that has at least one
35b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono     * storage.
36b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono     */
37b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono    static UsbDevice setupMtpDevice(
38b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            TestResultInstrumentation instrumentation,
39b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            UsbManager usbManager,
4099b58052f85c18272e63047b471edfd8089c09d3Daichi Hirono            MtpManager manager) throws InterruptedException, IOException {
41b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono        for (int i = 0; i < 2; i++) {
42af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono            final UsbDevice device = findMtpDevice(instrumentation, usbManager, manager);
43b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            try {
44b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                waitForStorages(instrumentation, manager, device.getDeviceId());
45b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                return device;
46b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            } catch (IOException exp) {
47b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                // When the MTP device is Android, and it changes the USB device type from
48b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                // "Charging" to "MTP", the device ID will be updated. We need to find a device
49b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                // again.
50b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                continue;
51b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            }
52b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono        }
53b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono        throw new IOException("Failed to obtain MTP devices");
54b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono    }
55b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono
56b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono    private static UsbDevice findMtpDevice(
57b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            TestResultInstrumentation instrumentation,
58af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono            UsbManager usbManager,
59af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono            MtpManager manager) throws InterruptedException {
60b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono        while (true) {
61b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            final HashMap<String,UsbDevice> devices = usbManager.getDeviceList();
62b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            if (devices.size() == 0) {
63b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                instrumentation.show("Wait for devices.");
64b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                Thread.sleep(1000);
65b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                continue;
66b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            }
67b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            final UsbDevice device = devices.values().iterator().next();
68af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono            try {
69af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                manager.openDevice(device.getDeviceId());
70af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono            } catch (IOException e) {
71af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                // Maybe other application is using the device.
72af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                // Force to obtain ownership of the device so that we can use the device next call
73af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                // of findMtpDevice.
74af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                instrumentation.show("Tries to get ownership of MTP device.");
75af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                final UsbDeviceConnection connection = usbManager.openDevice(device);
76af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                if (connection == null) {
77af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                    Assert.fail("Cannot open USB connection.");
78af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                    return null;
79af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                }
80af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                for (int i = 0; i < device.getInterfaceCount(); i++) {
81af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                    // Since the test runs real environment, we need to call claim interface with
82af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                    // force = true to rob interfaces from other applications.
83af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                    connection.claimInterface(device.getInterface(i), true);
84af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                    connection.releaseInterface(device.getInterface(i));
85af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                }
86af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                connection.close();
87af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                Thread.sleep(1000);
88af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono                continue;
89b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            }
90b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            return device;
91b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono        }
92b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono    }
93b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono
94b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono    private static void waitForStorages(
95b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            TestResultInstrumentation instrumentation,
96b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            MtpManager manager,
9720754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono            int deviceId) throws InterruptedException, IOException {
98b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono        while (true) {
9920754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono            MtpDeviceRecord device = null;
10020754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono            for (final MtpDeviceRecord deviceCandidate : manager.getDevices()) {
10120754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono                if (deviceCandidate.deviceId == deviceId) {
10220754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono                    device = deviceCandidate;
10320754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono                    break;
10420754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono                }
10520754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono            }
10620754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono            if (device == null) {
10720754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono                throw new IOException("Device was detached.");
10820754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono            }
10920754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono            if (device.roots.length == 0) {
110b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                instrumentation.show("Wait for storages.");
111b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                Thread.sleep(1000);
112b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                continue;
113b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            }
114b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            return;
115b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono        }
116b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono    }
117b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono}
118