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