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