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.compatibility.common.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 "android.support.test.runner.AndroidJUnitRunner"; 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.getAbisSupportedByCompatibility()) { AbiUtils.createId(abi, APP_PACKAGE_NAME)59 IDS.add(AbiUtils.createId(abi, APP_PACKAGE_NAME)); AbiUtils.createId(abi, EXTENDED_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 */ collectDeviceInfo(ITestDevice device, String abi, File testApkDir, ITestInvocationListener listener)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 */ collectExtendedDeviceInfo(ITestDevice device, String abi, File testApkDir, ITestInvocationListener listener, IBuildInfo buildInfo)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 runInstrumentation(ITestDevice device, String abi, File testApkDir, ITestInvocationListener listener, String apkName, String packageName, String instrumentName)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 pullExtendedDeviceInfoResults(ITestDevice device, IBuildInfo buildInfo)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 execute(String command)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 getDeviceResultDir(ITestDevice device)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