Home | History | Annotate | Download | only in mtp
      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.hardware.usb.UsbDevice;
     20 import android.hardware.usb.UsbDeviceConnection;
     21 import android.hardware.usb.UsbManager;
     22 import android.mtp.MtpConstants;
     23 import android.os.SystemClock;
     24 
     25 import java.io.FileNotFoundException;
     26 import java.io.IOException;
     27 import java.util.HashMap;
     28 import java.util.Objects;
     29 
     30 /**
     31  * Static utility methods for testing.
     32  */
     33 final class TestUtil {
     34     private TestUtil() {}
     35 
     36     static final int[] OPERATIONS_SUPPORTED = new int[] {
     37             MtpConstants.OPERATION_GET_PARTIAL_OBJECT,
     38             MtpConstants.OPERATION_SEND_OBJECT,
     39             MtpConstants.OPERATION_SEND_OBJECT_INFO,
     40             MtpConstants.OPERATION_DELETE_OBJECT,
     41             MtpConstants.OPERATION_GET_OBJECT_PROP_DESC,
     42             MtpConstants.OPERATION_GET_OBJECT_PROP_VALUE
     43     };
     44 
     45     /**
     46      * Requests permission for a MTP device and returns the first MTP device that has at least one
     47      * storage.
     48      */
     49     static UsbDevice setupMtpDevice(
     50             TestResultInstrumentation instrumentation,
     51             UsbManager usbManager,
     52             MtpManager manager) {
     53         while (true) {
     54             try {
     55                 final UsbDevice device = findMtpDevice(usbManager, manager);
     56                 waitForStorages(instrumentation, manager, device.getDeviceId());
     57                 return device;
     58             } catch (IOException exp) {
     59                 instrumentation.show(Objects.toString(exp.getMessage()));
     60                 SystemClock.sleep(1000);
     61                 // When the MTP device is Android, and it changes the USB device type from
     62                 // "Charging" to "MTP", the device ID will be updated. We need to find a device
     63                 // again.
     64                 continue;
     65             }
     66         }
     67     }
     68 
     69     static void addTestDevice(MtpDatabase database) throws FileNotFoundException {
     70         database.getMapper().startAddingDocuments(null);
     71         database.getMapper().putDeviceDocument(new MtpDeviceRecord(
     72                 0, "Device", "device_key", /* opened is */ true, new MtpRoot[0],
     73                 OPERATIONS_SUPPORTED, null));
     74         database.getMapper().stopAddingDocuments(null);
     75     }
     76 
     77     static void addTestStorage(MtpDatabase database, String parentId) throws FileNotFoundException {
     78         database.getMapper().startAddingDocuments(parentId);
     79         database.getMapper().putStorageDocuments(parentId, OPERATIONS_SUPPORTED, new MtpRoot[] {
     80                 new MtpRoot(0, 100, "Storage", 1024, 1024, ""),
     81         });
     82         database.getMapper().stopAddingDocuments(parentId);
     83     }
     84 
     85     private static UsbDevice findMtpDevice(
     86             UsbManager usbManager,
     87             MtpManager manager) throws IOException {
     88         final HashMap<String,UsbDevice> devices = usbManager.getDeviceList();
     89         if (devices.size() == 0) {
     90             throw new IOException("Device not found.");
     91         }
     92         final UsbDevice device = devices.values().iterator().next();
     93         // Tries to get ownership of the device in case that another application use it.
     94         if (usbManager.hasPermission(device)) {
     95             final UsbDeviceConnection connection = usbManager.openDevice(device);
     96             for (int i = 0; i < device.getInterfaceCount(); i++) {
     97                 // Since the test runs real environment, we need to call claim interface with
     98                 // force = true to rob interfaces from other applications.
     99                 connection.claimInterface(device.getInterface(i), true);
    100                 connection.releaseInterface(device.getInterface(i));
    101             }
    102             connection.close();
    103         }
    104         manager.openDevice(device.getDeviceId());
    105         return device;
    106     }
    107 
    108     private static void waitForStorages(
    109             TestResultInstrumentation instrumentation,
    110             MtpManager manager,
    111             int deviceId) throws IOException {
    112         while (true) {
    113             MtpDeviceRecord device = null;
    114             for (final MtpDeviceRecord deviceCandidate : manager.getDevices()) {
    115                 if (deviceCandidate.deviceId == deviceId) {
    116                     device = deviceCandidate;
    117                     break;
    118                 }
    119             }
    120             if (device == null) {
    121                 throw new IOException("Device was detached.");
    122             }
    123             if (device.roots.length == 0) {
    124                 instrumentation.show("Wait for storages.");
    125                 SystemClock.sleep(1000);
    126                 continue;
    127             }
    128             return;
    129         }
    130     }
    131 }
    132