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.compatibility.common.tradefed.targetprep; 18 19 import com.android.compatibility.common.util.DeviceInfo; 20 import com.android.compatibility.common.util.DevicePropertyInfo; 21 import com.android.tradefed.build.IBuildInfo; 22 import com.android.tradefed.config.Option; 23 import com.android.tradefed.config.OptionClass; 24 import com.android.tradefed.device.DeviceNotAvailableException; 25 import com.android.tradefed.device.ITestDevice; 26 import com.android.tradefed.invoker.TestInformation; 27 import com.android.tradefed.log.ITestLogger; 28 import com.android.tradefed.log.LogUtil.CLog; 29 import com.android.tradefed.result.FileInputStreamSource; 30 import com.android.tradefed.result.ITestLoggerReceiver; 31 import com.android.tradefed.result.LogDataType; 32 import com.android.tradefed.targetprep.BuildError; 33 import com.android.tradefed.targetprep.TargetSetupError; 34 import com.android.tradefed.util.FileUtil; 35 36 import java.io.File; 37 import java.io.IOException; 38 import java.util.Map.Entry; 39 40 /** An {@link ApkInstrumentationPreparer} that collects device info. */ 41 @OptionClass(alias = "device-info-collector") 42 public class DeviceInfoCollector extends ApkInstrumentationPreparer implements ITestLoggerReceiver { 43 44 public static final String DEVICE_INFO_DIR = "device_info_dir"; 45 public static final String SKIP_DEVICE_INFO_OPTION = "skip-device-info"; 46 47 private static final String ABI = "ro.product.cpu.abi"; 48 private static final String ABI2 = "ro.product.cpu.abi2"; 49 private static final String ABIS = "ro.product.cpu.abilist"; 50 private static final String ABIS_32 = "ro.product.cpu.abilist32"; 51 private static final String ABIS_64 = "ro.product.cpu.abilist64"; 52 private static final String BOARD = "ro.product.board"; 53 private static final String BRAND = "ro.product.brand"; 54 private static final String DEVICE = "ro.product.device"; 55 private static final String FINGERPRINT = "ro.build.fingerprint"; 56 private static final String VENDOR_FINGERPRINT = "ro.vendor.build.fingerprint"; 57 private static final String BOOTIMAGE_FINGERPRINT = "ro.bootimage.build.fingerprint"; 58 private static final String ID = "ro.build.id"; 59 private static final String MANUFACTURER = "ro.product.manufacturer"; 60 private static final String MODEL = "ro.product.model"; 61 private static final String PRODUCT = "ro.product.name"; 62 private static final String REFERENCE_FINGERPRINT = "ro.build.reference.fingerprint"; 63 private static final String SERIAL = "ro.serialno"; 64 private static final String TAGS = "ro.build.tags"; 65 private static final String TYPE = "ro.build.type"; 66 private static final String VERSION_BASE_OS = "ro.build.version.base_os"; 67 private static final String VERSION_RELEASE = "ro.build.version.release"; 68 private static final String VERSION_SDK = "ro.build.version.sdk"; 69 private static final String VERSION_SECURITY_PATCH = "ro.build.version.security_patch"; 70 private static final String VERSION_INCREMENTAL = "ro.build.version.incremental"; 71 72 private static final String PREFIX_TAG = "cts:build_"; 73 74 @Option(name = SKIP_DEVICE_INFO_OPTION, 75 shortName = 'd', 76 description = "Whether device info collection should be skipped") 77 private boolean mSkipDeviceInfo = false; 78 79 @Option( 80 name = "force-collect-device-info", 81 description = 82 "Force device info collection. If set to true, " 83 + SKIP_DEVICE_INFO_OPTION 84 + " is ignored.") 85 private boolean mForceCollectDeviceInfo = false; 86 87 @Option(name= "src-dir", description = "The directory to copy to the results dir") 88 private String mSrcDir; 89 90 @Option(name = "dest-dir", description = "The directory under the result to store the files") 91 private String mDestDir = DeviceInfo.RESULT_DIR_NAME; 92 93 @Deprecated 94 @Option(name = "temp-dir", description = "The directory containing host-side device info files") 95 private String mTempDir; 96 97 private ITestLogger mLogger; 98 private File deviceInfoDir = null; 99 DeviceInfoCollector()100 public DeviceInfoCollector() { 101 mWhen = When.BEFORE; 102 } 103 104 @Override setUp(TestInformation testInfo)105 public void setUp(TestInformation testInfo) 106 throws TargetSetupError, BuildError, DeviceNotAvailableException { 107 if (testInfo.getBuildInfo().getFile(DEVICE_INFO_DIR) != null) { 108 CLog.i("Device info already collected, skipping DeviceInfoCollector."); 109 return; 110 } 111 if (mSkipDeviceInfo && !mForceCollectDeviceInfo) { 112 return; 113 } 114 ITestDevice device = testInfo.getDevice(); 115 IBuildInfo buildInfo = testInfo.getBuildInfo(); 116 DevicePropertyInfo devicePropertyInfo = 117 new DevicePropertyInfo( 118 ABI, 119 ABI2, 120 ABIS, 121 ABIS_32, 122 ABIS_64, 123 BOARD, 124 BRAND, 125 DEVICE, 126 FINGERPRINT, 127 VENDOR_FINGERPRINT, 128 ID, 129 MANUFACTURER, 130 MODEL, 131 PRODUCT, 132 REFERENCE_FINGERPRINT, 133 SERIAL, 134 TAGS, 135 TYPE, 136 VERSION_BASE_OS, 137 VERSION_RELEASE, 138 VERSION_SDK, 139 VERSION_SECURITY_PATCH, 140 VERSION_INCREMENTAL, 141 BOOTIMAGE_FINGERPRINT); 142 143 // add device properties to the result with a prefix tag for each key 144 for (Entry<String, String> entry : 145 devicePropertyInfo.getPropertytMapWithPrefix(PREFIX_TAG).entrySet()) { 146 String property = nullToEmpty(device.getProperty(entry.getValue())); 147 buildInfo.addBuildAttribute(entry.getKey(), property); 148 } 149 run(testInfo); 150 try { 151 deviceInfoDir = FileUtil.createTempDir(DeviceInfo.RESULT_DIR_NAME); 152 if (device.pullDir(mSrcDir, deviceInfoDir)) { 153 if (!deviceInfoDir.exists() || deviceInfoDir.listFiles() == null) { 154 CLog.e( 155 "Pulled device-info, but local dir '%s' is not valid. " 156 + "[exists=%s, isDir=%s].", 157 deviceInfoDir, deviceInfoDir.exists(), deviceInfoDir.isDirectory()); 158 } else { 159 for (File deviceInfoFile : deviceInfoDir.listFiles()) { 160 try (FileInputStreamSource source = 161 new FileInputStreamSource(deviceInfoFile)) { 162 mLogger.testLog(deviceInfoFile.getName(), LogDataType.TEXT, source); 163 } 164 } 165 // Some host tests depends on this code. E.g. SELinuxHostTestCases reads device 166 // info files by querying DEVICE_INFO_DIR against buildInfo. Change this with 167 // caution. 168 buildInfo.setFile( 169 DEVICE_INFO_DIR, 170 deviceInfoDir, 171 /** version */ 172 "v1"); 173 } 174 } else { 175 CLog.e("Failed to pull device-info files from device %s", device.getSerialNumber()); 176 } 177 } catch (IOException e) { 178 CLog.e("Failed to pull device-info files from device %s", device.getSerialNumber()); 179 CLog.e(e); 180 } 181 } 182 183 @Override tearDown(TestInformation testInfo, Throwable e)184 public void tearDown(TestInformation testInfo, Throwable e) throws DeviceNotAvailableException { 185 FileUtil.recursiveDelete(deviceInfoDir); 186 super.tearDown(testInfo, e); 187 } 188 189 @Override setTestLogger(ITestLogger testLogger)190 public void setTestLogger(ITestLogger testLogger) { 191 mLogger = testLogger; 192 } 193 nullToEmpty(String value)194 private static String nullToEmpty(String value) { 195 return value == null ? "" : value; 196 } 197 } 198