TestUtil.java revision f578fa275a535016f5322c88ad7a92e517d04a12
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;
221d4779c29a95114c89ec353a8899c0cc8eee3ba5Daichi Hironoimport android.os.SystemClock;
23b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono
24f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hironoimport java.io.FileNotFoundException;
25b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hironoimport java.io.IOException;
26b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hironoimport java.util.HashMap;
271d4779c29a95114c89ec353a8899c0cc8eee3ba5Daichi Hironoimport java.util.Objects;
281d4779c29a95114c89ec353a8899c0cc8eee3ba5Daichi Hirono
29b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono/**
30b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono * Static utility methods for testing.
31b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono */
3299b58052f85c18272e63047b471edfd8089c09d3Daichi Hironofinal class TestUtil {
33b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono    private TestUtil() {}
34b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono
35b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono    /**
36b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono     * Requests permission for a MTP device and returns the first MTP device that has at least one
37b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono     * storage.
38b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono     */
39b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono    static UsbDevice setupMtpDevice(
40b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            TestResultInstrumentation instrumentation,
41b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            UsbManager usbManager,
421d4779c29a95114c89ec353a8899c0cc8eee3ba5Daichi Hirono            MtpManager manager) {
431d4779c29a95114c89ec353a8899c0cc8eee3ba5Daichi Hirono        while (true) {
44b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            try {
45ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono                final UsbDevice device = findMtpDevice(usbManager, manager);
46b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                waitForStorages(instrumentation, manager, device.getDeviceId());
47b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                return device;
48b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            } catch (IOException exp) {
491d4779c29a95114c89ec353a8899c0cc8eee3ba5Daichi Hirono                instrumentation.show(Objects.toString(exp.getMessage()));
501d4779c29a95114c89ec353a8899c0cc8eee3ba5Daichi Hirono                SystemClock.sleep(1000);
51b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                // When the MTP device is Android, and it changes the USB device type from
52b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                // "Charging" to "MTP", the device ID will be updated. We need to find a device
53b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                // again.
54b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                continue;
55b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            }
56b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono        }
57b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono    }
58b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono
59f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono    static void addTestDevice(MtpDatabase database) throws FileNotFoundException {
60f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono        database.getMapper().startAddingDocuments(null);
61f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono        database.getMapper().putDeviceDocument(new MtpDeviceRecord(
62f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono                0, "Device", "device_key", /* opened is */ true, new MtpRoot[0], null,
63f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono                null));
64f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono        database.getMapper().stopAddingDocuments(null);
65f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono    }
66f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono
67f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono    static void addTestStorage(MtpDatabase database, String parentId) throws FileNotFoundException {
68f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono        database.getMapper().startAddingDocuments(parentId);
69f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono        database.getMapper().putStorageDocuments(parentId, new MtpRoot[] {
70f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono                new MtpRoot(0, 100, "Storage", 1024, 1024, ""),
71f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono        });
72f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono        database.getMapper().stopAddingDocuments(parentId);
73f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono    }
74f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono
75b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono    private static UsbDevice findMtpDevice(
76af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono            UsbManager usbManager,
77ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono            MtpManager manager) throws IOException {
78ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono        final HashMap<String,UsbDevice> devices = usbManager.getDeviceList();
79ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono        if (devices.size() == 0) {
80ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono            throw new IOException("Device not found.");
81ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono        }
82ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono        final UsbDevice device = devices.values().iterator().next();
83ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono        // Tries to get ownership of the device in case that another application use it.
84ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono        if (usbManager.hasPermission(device)) {
85ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono            final UsbDeviceConnection connection = usbManager.openDevice(device);
86ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono            for (int i = 0; i < device.getInterfaceCount(); i++) {
87ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono                // Since the test runs real environment, we need to call claim interface with
88ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono                // force = true to rob interfaces from other applications.
89ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono                connection.claimInterface(device.getInterface(i), true);
90ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono                connection.releaseInterface(device.getInterface(i));
91b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            }
92ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono            connection.close();
93b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono        }
94ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono        manager.openDevice(device.getDeviceId());
95ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono        return device;
96b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono    }
97b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono
98b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono    private static void waitForStorages(
99b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            TestResultInstrumentation instrumentation,
100b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            MtpManager manager,
1011d4779c29a95114c89ec353a8899c0cc8eee3ba5Daichi Hirono            int deviceId) throws IOException {
102b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono        while (true) {
10320754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono            MtpDeviceRecord device = null;
10420754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono            for (final MtpDeviceRecord deviceCandidate : manager.getDevices()) {
10520754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono                if (deviceCandidate.deviceId == deviceId) {
10620754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono                    device = deviceCandidate;
10720754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono                    break;
10820754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono                }
10920754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono            }
11020754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono            if (device == null) {
11120754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono                throw new IOException("Device was detached.");
11220754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono            }
11320754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono            if (device.roots.length == 0) {
114b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                instrumentation.show("Wait for storages.");
1151d4779c29a95114c89ec353a8899c0cc8eee3ba5Daichi Hirono                SystemClock.sleep(1000);
116b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono                continue;
117b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            }
118b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono            return;
119b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono        }
120b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono    }
121b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono}
122