Home | History | Annotate | Download | only in device
      1 /*
      2  * Copyright (C) 2010 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 package com.android.cts.tradefed.device;
     17 
     18 import com.android.cts.util.AbiUtils;
     19 import com.android.cts.tradefed.result.CtsXmlResultReporter;
     20 import com.android.ddmlib.IDevice;
     21 import com.android.ddmlib.Log;
     22 import com.android.tradefed.build.IBuildInfo;
     23 import com.android.tradefed.build.IFolderBuildInfo;
     24 import com.android.tradefed.device.DeviceNotAvailableException;
     25 import com.android.tradefed.device.ITestDevice;
     26 import com.android.tradefed.result.ITestInvocationListener;
     27 import com.android.tradefed.testtype.InstrumentationTest;
     28 
     29 import java.io.File;
     30 import java.util.HashSet;
     31 import java.util.Set;
     32 
     33 /**
     34  * Collects info from device under test.
     35  * <p/>
     36  * This class simply serves as a conduit for grabbing info from device using the device info
     37  * collector apk, and forwarding that data directly to the {@link ITestInvocationListener} as run
     38  * metrics.
     39  */
     40 public class DeviceInfoCollector {
     41 
     42     private static final String LOG_TAG = "DeviceInfoCollector";
     43     private static final String APK_NAME = "TestDeviceSetup";
     44     public static final String APP_PACKAGE_NAME = "android.tests.devicesetup";
     45     private static final String INSTRUMENTATION_NAME = "android.tests.getinfo.DeviceInfoInstrument";
     46 
     47     private static final String EXTENDED_APK_NAME = "CtsDeviceInfo";
     48     public static final String EXTENDED_APP_PACKAGE_NAME =
     49             "com.android.compatibility.common.deviceinfo";
     50     private static final String EXTENDED_INSTRUMENTATION_NAME =
     51             "com.android.compatibility.common.deviceinfo.DeviceInfoInstrument";
     52     private static final String DEVICE_INFO_FILES = "device-info-files";
     53 
     54     public static final Set<String> IDS = new HashSet<String>();
     55     public static final Set<String> EXTENDED_IDS = new HashSet<String>();
     56 
     57     static {
     58         for (String abi : AbiUtils.getAbisSupportedByCts()) {
     59             IDS.add(AbiUtils.createId(abi, APP_PACKAGE_NAME));
     60             EXTENDED_IDS.add(AbiUtils.createId(abi, EXTENDED_APP_PACKAGE_NAME));
     61         }
     62     }
     63 
     64     /**
     65      * Installs and runs the device info collector instrumentation, and forwards results
     66      * to the listener.
     67      *
     68      * @param device
     69      * @param listener
     70      * @throws DeviceNotAvailableException
     71      */
     72     public static void collectDeviceInfo(ITestDevice device, String abi, File testApkDir,
     73             ITestInvocationListener listener) throws DeviceNotAvailableException {
     74         runInstrumentation(device, abi, testApkDir, listener, APK_NAME, APP_PACKAGE_NAME,
     75             INSTRUMENTATION_NAME);
     76     }
     77 
     78     /**
     79      * Installs and runs the extended device info collector instrumentation, and forwards results
     80      * to the listener.
     81      *
     82      * @param device
     83      * @param listener
     84      * @throws DeviceNotAvailableException
     85      */
     86     public static void collectExtendedDeviceInfo(ITestDevice device, String abi, File testApkDir,
     87             ITestInvocationListener listener, IBuildInfo buildInfo)
     88             throws DeviceNotAvailableException {
     89         // Clear files in device test result directory
     90         String deviceResultDir = getDeviceResultDir(device);
     91         device.executeShellCommand(String.format("rm -rf %s", deviceResultDir));
     92         runInstrumentation(device, abi, testApkDir, listener, EXTENDED_APK_NAME,
     93             EXTENDED_APP_PACKAGE_NAME, EXTENDED_INSTRUMENTATION_NAME);
     94         // Copy files in remote result directory to local directory
     95         pullExtendedDeviceInfoResults(device, buildInfo);
     96     }
     97 
     98     private static void runInstrumentation(ITestDevice device, String abi, File testApkDir,
     99             ITestInvocationListener listener, String apkName, String packageName,
    100             String instrumentName) throws DeviceNotAvailableException {
    101         File apkFile = new File(testApkDir, String.format("%s.apk", apkName));
    102         if (!apkFile.exists()) {
    103             Log.e(LOG_TAG, String.format("Could not find %s", apkFile.getAbsolutePath()));
    104             return;
    105         }
    106         // collect the instrumentation bundle results using instrumentation test
    107         // should work even though no tests will actually be run
    108         InstrumentationTest instrTest = new InstrumentationTest();
    109         instrTest.setDevice(device);
    110         instrTest.setInstallFile(apkFile);
    111         // no need to collect tests and re-run
    112         instrTest.setRerunMode(false);
    113         instrTest.setPackageName(packageName);
    114         instrTest.setRunName(AbiUtils.createId(abi, packageName));
    115         instrTest.setRunnerName(instrumentName);
    116         instrTest.run(listener);
    117     }
    118 
    119     private static void pullExtendedDeviceInfoResults(ITestDevice device, IBuildInfo buildInfo)
    120             throws DeviceNotAvailableException {
    121         if (!(buildInfo instanceof IFolderBuildInfo)) {
    122             Log.e(LOG_TAG, "Invalid instance of buildInfo");
    123             return;
    124         }
    125         File localResultDir = new File(buildInfo.getBuildAttributes().get(
    126                 CtsXmlResultReporter.CTS_RESULT_DIR));
    127         if (localResultDir == null || !localResultDir.isDirectory()) {
    128             Log.e(LOG_TAG, "Local result directory is null or is not a directory");
    129             return;
    130         }
    131 
    132         localResultDir = new File(localResultDir, DEVICE_INFO_FILES);
    133         localResultDir.mkdirs();
    134 
    135 
    136         String deviceResultDir = getDeviceResultDir(device);
    137 
    138         // Pull files from device result directory to local result directory
    139         String command = String.format("adb -s %s pull %s %s", device.getSerialNumber(),
    140                 deviceResultDir, localResultDir.getAbsolutePath());
    141         if (!execute(command)) {
    142             Log.e(LOG_TAG, String.format("Failed to run %s", command));
    143         }
    144     }
    145 
    146     private static boolean execute(String command) {
    147         try {
    148             Process p = Runtime.getRuntime().exec(new String[] {"/bin/bash", "-c", command});
    149             return (p.waitFor() == 0);
    150         } catch (Exception e) {
    151             Log.e(LOG_TAG, e);
    152             return false;
    153         }
    154     }
    155 
    156     private static String getDeviceResultDir(ITestDevice device) {
    157         String externalStorePath = device.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
    158         if (externalStorePath == null) {
    159             Log.e(LOG_TAG, String.format(
    160                     "Failed to get external storage path on device %s", device.getSerialNumber()));
    161             return null;
    162         }
    163         return String.format("%s/%s", externalStorePath, DEVICE_INFO_FILES);
    164     }
    165 }
    166