TestUtil.java revision 61ba923ca0cb5c928a16729d0aa67b6bf4b2f027
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; 220f32537e40ee2662d4f0b7b625ee280ca9c02066Daichi Hironoimport android.mtp.MtpConstants; 231d4779c29a95114c89ec353a8899c0cc8eee3ba5Daichi Hironoimport android.os.SystemClock; 24b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono 25f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hironoimport java.io.FileNotFoundException; 26b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hironoimport java.io.IOException; 27b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hironoimport java.util.HashMap; 281d4779c29a95114c89ec353a8899c0cc8eee3ba5Daichi Hironoimport java.util.Objects; 291d4779c29a95114c89ec353a8899c0cc8eee3ba5Daichi Hirono 30b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono/** 31b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono * Static utility methods for testing. 32b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono */ 3399b58052f85c18272e63047b471edfd8089c09d3Daichi Hironofinal class TestUtil { 34b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono private TestUtil() {} 35b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono 360f32537e40ee2662d4f0b7b625ee280ca9c02066Daichi Hirono static final int[] OPERATIONS_SUPPORTED = new int[] { 370f32537e40ee2662d4f0b7b625ee280ca9c02066Daichi Hirono MtpConstants.OPERATION_GET_PARTIAL_OBJECT, 380f32537e40ee2662d4f0b7b625ee280ca9c02066Daichi Hirono MtpConstants.OPERATION_SEND_OBJECT, 390f32537e40ee2662d4f0b7b625ee280ca9c02066Daichi Hirono MtpConstants.OPERATION_SEND_OBJECT_INFO, 4061ba923ca0cb5c928a16729d0aa67b6bf4b2f027Daichi Hirono MtpConstants.OPERATION_DELETE_OBJECT, 410f32537e40ee2662d4f0b7b625ee280ca9c02066Daichi Hirono }; 420f32537e40ee2662d4f0b7b625ee280ca9c02066Daichi Hirono 43b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono /** 44b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono * Requests permission for a MTP device and returns the first MTP device that has at least one 45b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono * storage. 46b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono */ 47b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono static UsbDevice setupMtpDevice( 48b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono TestResultInstrumentation instrumentation, 49b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono UsbManager usbManager, 501d4779c29a95114c89ec353a8899c0cc8eee3ba5Daichi Hirono MtpManager manager) { 511d4779c29a95114c89ec353a8899c0cc8eee3ba5Daichi Hirono while (true) { 52b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono try { 53ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono final UsbDevice device = findMtpDevice(usbManager, manager); 54b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono waitForStorages(instrumentation, manager, device.getDeviceId()); 55b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono return device; 56b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono } catch (IOException exp) { 571d4779c29a95114c89ec353a8899c0cc8eee3ba5Daichi Hirono instrumentation.show(Objects.toString(exp.getMessage())); 581d4779c29a95114c89ec353a8899c0cc8eee3ba5Daichi Hirono SystemClock.sleep(1000); 59b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono // When the MTP device is Android, and it changes the USB device type from 60b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono // "Charging" to "MTP", the device ID will be updated. We need to find a device 61b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono // again. 62b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono continue; 63b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono } 64b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono } 65b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono } 66b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono 67f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono static void addTestDevice(MtpDatabase database) throws FileNotFoundException { 68f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono database.getMapper().startAddingDocuments(null); 69f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono database.getMapper().putDeviceDocument(new MtpDeviceRecord( 700f32537e40ee2662d4f0b7b625ee280ca9c02066Daichi Hirono 0, "Device", "device_key", /* opened is */ true, new MtpRoot[0], 710f32537e40ee2662d4f0b7b625ee280ca9c02066Daichi Hirono OPERATIONS_SUPPORTED, null)); 72f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono database.getMapper().stopAddingDocuments(null); 73f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono } 74f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono 75f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono static void addTestStorage(MtpDatabase database, String parentId) throws FileNotFoundException { 76f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono database.getMapper().startAddingDocuments(parentId); 770f32537e40ee2662d4f0b7b625ee280ca9c02066Daichi Hirono database.getMapper().putStorageDocuments(parentId, OPERATIONS_SUPPORTED, new MtpRoot[] { 78f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono new MtpRoot(0, 100, "Storage", 1024, 1024, ""), 79f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono }); 80f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono database.getMapper().stopAddingDocuments(parentId); 81f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono } 82f578fa275a535016f5322c88ad7a92e517d04a12Daichi Hirono 83b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono private static UsbDevice findMtpDevice( 84af5ea38b8c51f0878e4070671e240f693f3ad796Daichi Hirono UsbManager usbManager, 85ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono MtpManager manager) throws IOException { 86ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono final HashMap<String,UsbDevice> devices = usbManager.getDeviceList(); 87ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono if (devices.size() == 0) { 88ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono throw new IOException("Device not found."); 89ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono } 90ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono final UsbDevice device = devices.values().iterator().next(); 91ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono // Tries to get ownership of the device in case that another application use it. 92ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono if (usbManager.hasPermission(device)) { 93ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono final UsbDeviceConnection connection = usbManager.openDevice(device); 94ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono for (int i = 0; i < device.getInterfaceCount(); i++) { 95ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono // Since the test runs real environment, we need to call claim interface with 96ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono // force = true to rob interfaces from other applications. 97ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono connection.claimInterface(device.getInterface(i), true); 98ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono connection.releaseInterface(device.getInterface(i)); 99b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono } 100ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono connection.close(); 101b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono } 102ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono manager.openDevice(device.getDeviceId()); 103ab03cb1b469940ab672850e0d2de3c78025260d3Daichi Hirono return device; 104b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono } 105b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono 106b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono private static void waitForStorages( 107b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono TestResultInstrumentation instrumentation, 108b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono MtpManager manager, 1091d4779c29a95114c89ec353a8899c0cc8eee3ba5Daichi Hirono int deviceId) throws IOException { 110b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono while (true) { 11120754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono MtpDeviceRecord device = null; 11220754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono for (final MtpDeviceRecord deviceCandidate : manager.getDevices()) { 11320754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono if (deviceCandidate.deviceId == deviceId) { 11420754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono device = deviceCandidate; 11520754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono break; 11620754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono } 11720754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono } 11820754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono if (device == null) { 11920754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono throw new IOException("Device was detached."); 12020754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono } 12120754c5a112e418c11cc88176283db2c4bf2efd6Daichi Hirono if (device.roots.length == 0) { 122b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono instrumentation.show("Wait for storages."); 1231d4779c29a95114c89ec353a8899c0cc8eee3ba5Daichi Hirono SystemClock.sleep(1000); 124b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono continue; 125b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono } 126b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono return; 127b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono } 128b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono } 129b255f58904d7a2aa64ba9f03ed0ede3759fd03c5Daichi Hirono} 130