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 ID = "ro.build.id"; 58 private static final String MANUFACTURER = "ro.product.manufacturer"; 59 private static final String MODEL = "ro.product.model"; 60 private static final String PRODUCT = "ro.product.name"; 61 private static final String REFERENCE_FINGERPRINT = "ro.build.reference.fingerprint"; 62 private static final String SERIAL = "ro.serialno"; 63 private static final String TAGS = "ro.build.tags"; 64 private static final String TYPE = "ro.build.type"; 65 private static final String VERSION_BASE_OS = "ro.build.version.base_os"; 66 private static final String VERSION_RELEASE = "ro.build.version.release"; 67 private static final String VERSION_SDK = "ro.build.version.sdk"; 68 private static final String VERSION_SECURITY_PATCH = "ro.build.version.security_patch"; 69 private static final String VERSION_INCREMENTAL = "ro.build.version.incremental"; 70 71 private static final String PREFIX_TAG = "cts:build_"; 72 73 @Option(name = SKIP_DEVICE_INFO_OPTION, 74 shortName = 'd', 75 description = "Whether device info collection should be skipped") 76 private boolean mSkipDeviceInfo = false; 77 78 @Option(name= "src-dir", description = "The directory to copy to the results dir") 79 private String mSrcDir; 80 81 @Option(name = "dest-dir", description = "The directory under the result to store the files") 82 private String mDestDir = DeviceInfo.RESULT_DIR_NAME; 83 84 @Deprecated 85 @Option(name = "temp-dir", description = "The directory containing host-side device info files") 86 private String mTempDir; 87 88 private ITestLogger mLogger; 89 private File deviceInfoDir = null; 90 DeviceInfoCollector()91 public DeviceInfoCollector() { 92 mWhen = When.BEFORE; 93 } 94 95 @Override setUp(TestInformation testInfo)96 public void setUp(TestInformation testInfo) 97 throws TargetSetupError, BuildError, DeviceNotAvailableException { 98 if (testInfo.getBuildInfo().getFile(DEVICE_INFO_DIR) != null) { 99 CLog.i("Device info already collected, skipping DeviceInfoCollector."); 100 return; 101 } 102 ITestDevice device = testInfo.getDevice(); 103 IBuildInfo buildInfo = testInfo.getBuildInfo(); 104 DevicePropertyInfo devicePropertyInfo = 105 new DevicePropertyInfo( 106 ABI, 107 ABI2, 108 ABIS, 109 ABIS_32, 110 ABIS_64, 111 BOARD, 112 BRAND, 113 DEVICE, 114 FINGERPRINT, 115 VENDOR_FINGERPRINT, 116 ID, 117 MANUFACTURER, 118 MODEL, 119 PRODUCT, 120 REFERENCE_FINGERPRINT, 121 SERIAL, 122 TAGS, 123 TYPE, 124 VERSION_BASE_OS, 125 VERSION_RELEASE, 126 VERSION_SDK, 127 VERSION_SECURITY_PATCH, 128 VERSION_INCREMENTAL); 129 130 // add device properties to the result with a prefix tag for each key 131 for (Entry<String, String> entry : 132 devicePropertyInfo.getPropertytMapWithPrefix(PREFIX_TAG).entrySet()) { 133 String property = nullToEmpty(device.getProperty(entry.getValue())); 134 buildInfo.addBuildAttribute(entry.getKey(), property); 135 } 136 if (mSkipDeviceInfo) { 137 return; 138 } 139 run(testInfo); 140 try { 141 deviceInfoDir = FileUtil.createTempDir(DeviceInfo.RESULT_DIR_NAME); 142 if (device.pullDir(mSrcDir, deviceInfoDir)) { 143 if (!deviceInfoDir.exists() || deviceInfoDir.listFiles() == null) { 144 CLog.e( 145 "Pulled device-info, but local dir '%s' is not valid. " 146 + "[exists=%s, isDir=%s].", 147 deviceInfoDir, deviceInfoDir.exists(), deviceInfoDir.isDirectory()); 148 } else { 149 for (File deviceInfoFile : deviceInfoDir.listFiles()) { 150 try (FileInputStreamSource source = 151 new FileInputStreamSource(deviceInfoFile)) { 152 mLogger.testLog(deviceInfoFile.getName(), LogDataType.TEXT, source); 153 } 154 } 155 buildInfo.setFile( 156 DEVICE_INFO_DIR, 157 deviceInfoDir, 158 /** version */ 159 "v1"); 160 } 161 } else { 162 CLog.e("Failed to pull device-info files from device %s", device.getSerialNumber()); 163 } 164 } catch (IOException e) { 165 CLog.e("Failed to pull device-info files from device %s", device.getSerialNumber()); 166 CLog.e(e); 167 } 168 } 169 170 @Override tearDown(TestInformation testInfo, Throwable e)171 public void tearDown(TestInformation testInfo, Throwable e) throws DeviceNotAvailableException { 172 FileUtil.recursiveDelete(deviceInfoDir); 173 super.tearDown(testInfo, e); 174 } 175 176 @Override setTestLogger(ITestLogger testLogger)177 public void setTestLogger(ITestLogger testLogger) { 178 mLogger = testLogger; 179 } 180 nullToEmpty(String value)181 private static String nullToEmpty(String value) { 182 return value == null ? "" : value; 183 } 184 } 185