Change CTS Verifier reporting to CTSv2 format.

Bug: 32723464
Test: CTS Verifier should make a report in the CTSv2 format. CTS results
should stay consistent.
Make and run compatibility-common-util-tests. The unit tests should pass.

Change-Id: If3cc9dbc83f7eda356d7dbe36dd28615f492bcfe
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
index 08055a3..c35d1da 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
@@ -19,6 +19,7 @@
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
 import com.android.compatibility.common.tradefed.util.CollectorUtil;
+import com.android.compatibility.common.util.DevicePropertyInfo;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.config.Option;
 import com.android.tradefed.device.DeviceNotAvailableException;
@@ -40,30 +41,29 @@
  */
 public class DeviceInfoCollector extends ApkInstrumentationPreparer {
 
-    private static final Map<String, String> BUILD_KEYS = new HashMap<>();
-    static {
-        BUILD_KEYS.put("cts:build_id", "ro.build.id");
-        BUILD_KEYS.put("cts:build_product", "ro.product.name");
-        BUILD_KEYS.put("cts:build_device", "ro.product.device");
-        BUILD_KEYS.put("cts:build_board", "ro.product.board");
-        BUILD_KEYS.put("cts:build_manufacturer", "ro.product.manufacturer");
-        BUILD_KEYS.put("cts:build_brand", "ro.product.brand");
-        BUILD_KEYS.put("cts:build_model", "ro.product.model");
-        BUILD_KEYS.put("cts:build_type", "ro.build.type");
-        BUILD_KEYS.put("cts:build_tags", "ro.build.tags");
-        BUILD_KEYS.put("cts:build_fingerprint", "ro.build.fingerprint");
-        BUILD_KEYS.put("cts:build_abi", "ro.product.cpu.abi");
-        BUILD_KEYS.put("cts:build_abi2", "ro.product.cpu.abi2");
-        BUILD_KEYS.put("cts:build_abis", "ro.product.cpu.abilist");
-        BUILD_KEYS.put("cts:build_abis_32", "ro.product.cpu.abilist32");
-        BUILD_KEYS.put("cts:build_abis_64", "ro.product.cpu.abilist64");
-        BUILD_KEYS.put("cts:build_serial", "ro.serialno");
-        BUILD_KEYS.put("cts:build_version_release", "ro.build.version.release");
-        BUILD_KEYS.put("cts:build_version_sdk", "ro.build.version.sdk");
-        BUILD_KEYS.put("cts:build_version_base_os", "ro.build.version.base_os");
-        BUILD_KEYS.put("cts:build_version_security_patch", "ro.build.version.security_patch");
-        BUILD_KEYS.put("cts:build_reference_fingerprint", "ro.build.reference.fingerprint");
-    }
+    private static final String ABI = "ro.product.cpu.abi";
+    private static final String ABI2 = "ro.product.cpu.abi2";
+    private static final String ABIS = "ro.product.cpu.abilist";
+    private static final String ABIS_32 = "ro.product.cpu.abilist32";
+    private static final String ABIS_64 = "ro.product.cpu.abilist64";
+    private static final String BOARD = "ro.product.board";
+    private static final String BRAND = "ro.product.brand";
+    private static final String DEVICE = "ro.product.device";
+    private static final String FINGERPRINT = "ro.build.fingerprint";
+    private static final String ID = "ro.build.id";
+    private static final String MANUFACTURER = "ro.product.manufacturer";
+    private static final String MODEL = "ro.product.model";
+    private static final String PRODUCT = "ro.product.name";
+    private static final String REFERENCE_FINGERPRINT = "ro.build.reference.fingerprint";
+    private static final String SERIAL = "ro.serialno";
+    private static final String TAGS = "ro.build.tags";
+    private static final String TYPE = "ro.build.type";
+    private static final String VERSION_BASE_OS = "ro.build.version.base_os";
+    private static final String VERSION_RELEASE = "ro.build.version.release";
+    private static final String VERSION_SDK = "ro.build.version.sdk";
+    private static final String VERSION_SECURITY_PATCH = "ro.build.version.security_patch";
+
+    private static final String PREFIX_TAG = "cts:build_";
 
     @Option(name = CompatibilityTest.SKIP_DEVICE_INFO_OPTION,
             shortName = 'd',
@@ -92,7 +92,14 @@
     @Override
     public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
             BuildError, DeviceNotAvailableException {
-        for (Entry<String, String> entry : BUILD_KEYS.entrySet()) {
+        DevicePropertyInfo devicePropertyInfo = new DevicePropertyInfo(ABI, ABI2, ABIS, ABIS_32,
+                ABIS_64, BOARD, BRAND, DEVICE, FINGERPRINT, ID, MANUFACTURER, MODEL, PRODUCT,
+                REFERENCE_FINGERPRINT, SERIAL, TAGS, TYPE, VERSION_BASE_OS, VERSION_RELEASE,
+                VERSION_SDK, VERSION_SECURITY_PATCH);
+
+        // add device properties to the result with a prefix tag for each key
+        for (Entry<String, String> entry :
+                devicePropertyInfo.getPropertytMapWithPrefix(PREFIX_TAG).entrySet()) {
             buildInfo.addBuildAttribute(entry.getKey(),
                     ArrayUtil.join(",", device.getProperty(entry.getValue())));
         }
@@ -112,7 +119,7 @@
             return;
         }
         if (mHostDir != null && mHostDir.isDirectory() &&
-                    mResultDir != null && mResultDir.isDirectory()) {
+                mResultDir != null && mResultDir.isDirectory()) {
             CollectorUtil.pullFromHost(mHostDir, mResultDir);
         }
     }
diff --git a/common/host-side/util/tests/src/com/android/compatibility/common/util/HostUnitTests.java b/common/host-side/util/tests/src/com/android/compatibility/common/util/HostUnitTests.java
index 12fe1a6..a706018 100644
--- a/common/host-side/util/tests/src/com/android/compatibility/common/util/HostUnitTests.java
+++ b/common/host-side/util/tests/src/com/android/compatibility/common/util/HostUnitTests.java
@@ -29,7 +29,6 @@
         super();
         addTestSuite(DynamicConfigHandlerTest.class);
         addTestSuite(ModuleResultTest.class);
-        addTestSuite(ResultHandlerTest.class);
         addTestSuite(TestFilterTest.class);
     }
 
diff --git a/common/util/Android.mk b/common/util/Android.mk
index faf4596..b6cf927 100644
--- a/common/util/Android.mk
+++ b/common/util/Android.mk
@@ -26,6 +26,8 @@
 
 LOCAL_MODULE := compatibility-common-util-devicesidelib
 
+LOCAL_STATIC_JAVA_LIBRARIES :=  guava
+
 LOCAL_SDK_VERSION := current
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
@@ -42,7 +44,10 @@
 
 LOCAL_MODULE := compatibility-common-util-hostsidelib
 
-LOCAL_STATIC_JAVA_LIBRARIES := junit-host kxml2-2.3.0 platform-test-annotations-host
+LOCAL_STATIC_JAVA_LIBRARIES :=  guavalib \
+                                junit-host \
+                                kxml2-2.3.0 \
+                                platform-test-annotations-host
 
 include $(BUILD_HOST_JAVA_LIBRARY)
 
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/ChecksumReporter.java b/common/util/src/com/android/compatibility/common/util/ChecksumReporter.java
similarity index 99%
rename from common/host-side/util/src/com/android/compatibility/common/util/ChecksumReporter.java
rename to common/util/src/com/android/compatibility/common/util/ChecksumReporter.java
index faac61f..32fa532 100644
--- a/common/host-side/util/src/com/android/compatibility/common/util/ChecksumReporter.java
+++ b/common/util/src/com/android/compatibility/common/util/ChecksumReporter.java
@@ -16,8 +16,6 @@
 
 package com.android.compatibility.common.util;
 
-import com.android.annotations.Nullable;
-
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Joiner;
 import com.google.common.base.Strings;
@@ -316,7 +314,7 @@
     }
 
     private static String buildTestId(
-            String suiteName, String caseName, String testName, @Nullable String abi) {
+            String suiteName, String caseName, String testName, String abi) {
         String name = Joiner.on(NAME_SEPARATOR).skipNulls().join(
                 Strings.emptyToNull(suiteName),
                 Strings.emptyToNull(caseName),
diff --git a/common/util/src/com/android/compatibility/common/util/DevicePropertyInfo.java b/common/util/src/com/android/compatibility/common/util/DevicePropertyInfo.java
new file mode 100644
index 0000000..ec24b42
--- /dev/null
+++ b/common/util/src/com/android/compatibility/common/util/DevicePropertyInfo.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibility.common.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Utility class for collecting device information. This is used to enforce
+ * consistent property collection host-side and device-side for CTS reports.
+ *
+ * Note that properties across sources can differ, e.g. {@code android.os.Build}
+ * properties sometimes deviate from the read-only properties that they're based
+ * on.
+ */
+public final class DevicePropertyInfo {
+
+    private final String mAbi;
+    private final String mAbi2;
+    private final String mAbis;
+    private final String mAbis32;
+    private final String mAbis64;
+    private final String mBoard;
+    private final String mBrand;
+    private final String mDevice;
+    private final String mFingerprint;
+    private final String mId;
+    private final String mManufacturer;
+    private final String mModel;
+    private final String mProduct;
+    private final String mReferenceFingerprint;
+    private final String mSerial;
+    private final String mTags;
+    private final String mType;
+    private final String mVersionBaseOs;
+    private final String mVersionRelease;
+    private final String mVersionSdk;
+    private final String mVersionSecurityPatch;
+
+    public DevicePropertyInfo(String abi, String abi2, String abis, String abis32, String abis64,
+            String board, String brand, String device, String fingerprint, String id,
+            String manufacturer, String model, String product, String referenceFigerprint,
+            String serial, String tags, String type, String versionBaseOs, String versionRelease,
+            String versionSdk, String versionSecurityPatch) {
+        mAbi = abi;
+        mAbi2 = abi2;
+        mAbis = abis;
+        mAbis32 = abis32;
+        mAbis64 = abis64;
+        mBoard = board;
+        mBrand = brand;
+        mDevice = device;
+        mFingerprint = fingerprint;
+        mId = id;
+        mManufacturer = manufacturer;
+        mModel = model;
+        mProduct = product;
+        mReferenceFingerprint = referenceFigerprint;
+        mSerial = serial;
+        mTags = tags;
+        mType = type;
+        mVersionBaseOs = versionBaseOs;
+        mVersionRelease = versionRelease;
+        mVersionSdk = versionSdk;
+        mVersionSecurityPatch = versionSecurityPatch;
+    }
+
+    /**
+     * Return a {@code Map} with property keys prepended with a given prefix
+     * string. This is intended to be used to generate entries for
+     * {@code} Build tag attributes in CTS test results.
+     */
+    public Map<String, String> getPropertytMapWithPrefix(String prefix) {
+        Map<String, String> propertyMap = new HashMap<>();
+
+        propertyMap.put(prefix + "abi", mAbi);
+        propertyMap.put(prefix + "abi2", mAbi2);
+        propertyMap.put(prefix + "abis", mAbis);
+        propertyMap.put(prefix + "abis_32", mAbis32);
+        propertyMap.put(prefix + "abis_64", mAbis64);
+        propertyMap.put(prefix + "board", mBoard);
+        propertyMap.put(prefix + "brand", mBrand);
+        propertyMap.put(prefix + "device", mDevice);
+        propertyMap.put(prefix + "fingerprint", mFingerprint);
+        propertyMap.put(prefix + "id", mId);
+        propertyMap.put(prefix + "manufacturer", mManufacturer);
+        propertyMap.put(prefix + "model", mModel);
+        propertyMap.put(prefix + "product", mProduct);
+        propertyMap.put(prefix + "reference_fingerprint", mReferenceFingerprint);
+        propertyMap.put(prefix + "serial", mSerial);
+        propertyMap.put(prefix + "tags", mTags);
+        propertyMap.put(prefix + "type", mType);
+        propertyMap.put(prefix + "version_base_os", mVersionBaseOs);
+        propertyMap.put(prefix + "version_release", mVersionRelease);
+        propertyMap.put(prefix + "version_sdk", mVersionSdk);
+        propertyMap.put(prefix + "version_security_patch", mVersionSecurityPatch);
+
+        return propertyMap;
+    }
+
+}
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/IInvocationResult.java b/common/util/src/com/android/compatibility/common/util/IInvocationResult.java
similarity index 100%
rename from common/host-side/util/src/com/android/compatibility/common/util/IInvocationResult.java
rename to common/util/src/com/android/compatibility/common/util/IInvocationResult.java
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/InvocationResult.java b/common/util/src/com/android/compatibility/common/util/InvocationResult.java
similarity index 100%
rename from common/host-side/util/src/com/android/compatibility/common/util/InvocationResult.java
rename to common/util/src/com/android/compatibility/common/util/InvocationResult.java
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/ModuleResult.java b/common/util/src/com/android/compatibility/common/util/ModuleResult.java
similarity index 87%
rename from common/host-side/util/src/com/android/compatibility/common/util/ModuleResult.java
rename to common/util/src/com/android/compatibility/common/util/ModuleResult.java
index 97677fe..12ffeff 100644
--- a/common/host-side/util/src/com/android/compatibility/common/util/ModuleResult.java
+++ b/common/util/src/com/android/compatibility/common/util/ModuleResult.java
@@ -15,8 +15,6 @@
  */
 package com.android.compatibility.common.util;
 
-import com.android.tradefed.util.AbiUtils;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -96,7 +94,8 @@
      */
     @Override
     public String getName() {
-        return AbiUtils.parseTestName(mId);
+        // TODO: switch to using AbiUtils#parseTestName when available
+        return parseId(mId)[1];
     }
 
     /**
@@ -104,7 +103,21 @@
      */
     @Override
     public String getAbi() {
-        return AbiUtils.parseAbi(mId);
+        // TODO: switch to using AbiUtils#parseAbi when available
+        return parseId(mId)[0];
+    }
+
+    /**
+     * Parses a unique id into the ABI and name.
+     * @param id The id to parse.
+     * @return a string array containing the ABI and name.
+     */
+    private static String[] parseId(String id) {
+        // TODO: remove this when AbiUtils is available for getName and getAbi
+        if (id == null || !id.contains(" ")) {
+            return new String[] {"", ""};
+        }
+        return id.split(" ");
     }
 
     /**
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/ResultHandler.java b/common/util/src/com/android/compatibility/common/util/ResultHandler.java
similarity index 98%
rename from common/host-side/util/src/com/android/compatibility/common/util/ResultHandler.java
rename to common/util/src/com/android/compatibility/common/util/ResultHandler.java
index d8335f4..10a9681 100644
--- a/common/host-side/util/src/com/android/compatibility/common/util/ResultHandler.java
+++ b/common/util/src/com/android/compatibility/common/util/ResultHandler.java
@@ -16,7 +16,6 @@
 package com.android.compatibility.common.util;
 
 import com.android.compatibility.common.util.ChecksumReporter.ChecksumValidationException;
-import com.android.tradefed.util.AbiUtils;
 
 import com.google.common.base.Strings;
 
@@ -53,7 +52,7 @@
     private static final String TYPE = "org.kxml2.io.KXmlParser,org.kxml2.io.KXmlSerializer";
     private static final String NS = null;
     private static final String RESULT_FILE_VERSION = "5.0";
-    /* package */ static final String TEST_RESULT_FILE_NAME = "test_result.xml";
+    public static final String TEST_RESULT_FILE_NAME = "test_result.xml";
 
     // XML constants
     private static final String ABI_ATTR = "abi";
@@ -173,7 +172,8 @@
                     parser.require(XmlPullParser.START_TAG, NS, MODULE_TAG);
                     String name = parser.getAttributeValue(NS, NAME_ATTR);
                     String abi = parser.getAttributeValue(NS, ABI_ATTR);
-                    String moduleId = AbiUtils.createId(abi, name);
+                    // TODO: use AbiUtils#createId when available for use
+                    String moduleId = String.format("%s %s", abi, name);
                     boolean done = Boolean.parseBoolean(parser.getAttributeValue(NS, DONE_ATTR));
                     IModuleResult module = invocation.getOrCreateModule(moduleId);
                     module.setDone(done);
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/RetryChecksumStatus.java b/common/util/src/com/android/compatibility/common/util/RetryChecksumStatus.java
similarity index 100%
rename from common/host-side/util/src/com/android/compatibility/common/util/RetryChecksumStatus.java
rename to common/util/src/com/android/compatibility/common/util/RetryChecksumStatus.java
diff --git a/common/host-side/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java b/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
similarity index 96%
rename from common/host-side/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
rename to common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
index f2fa303..c7471c7 100644
--- a/common/host-side/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
+++ b/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
@@ -72,13 +72,8 @@
     private static final String METHOD_4 = "testBlah4";
     private static final String METHOD_5 = "testBlah5";
     private static final String SUMMARY_SOURCE = String.format("%s#%s:20", CLASS_B, METHOD_4);
-    private static final String DETAILS_SOURCE = String.format("%s#%s:18", CLASS_B, METHOD_4);
     private static final String SUMMARY_MESSAGE = "Headline";
     private static final double SUMMARY_VALUE = 9001;
-    private static final String DETAILS_MESSAGE = "Deats";
-    private static final double DETAILS_VALUE_1 = 14;
-    private static final double DETAILS_VALUE_2 = 18;
-    private static final double DETAILS_VALUE_3 = 17;
     private static final String MESSAGE = "Something small is not alright";
     private static final String STACK_TRACE = "Something small is not alright\n " +
             "at four.big.insects.Marley.sing(Marley.java:10)";
@@ -221,12 +216,9 @@
                     NOT_EXECUTED_A, moduleACases);
             String moduleBTest3 = String.format(XML_TEST_FAIL, METHOD_3, MESSAGE, STACK_TRACE,
                     BUG_REPORT, LOGCAT, SCREENSHOT);
-            String moduleBTest4 = String.format(XML_TEST_RESULT, METHOD_4,
-                    SUMMARY_SOURCE, SUMMARY_MESSAGE, ResultType.HIGHER_BETTER.toReportString(),
-                    ResultUnit.SCORE.toReportString(), Double.toString(SUMMARY_VALUE),
-                    DETAILS_SOURCE, DETAILS_MESSAGE, ResultType.LOWER_BETTER.toReportString(),
-                    ResultUnit.MS.toReportString(), Double.toString(DETAILS_VALUE_1),
-                    Double.toString(DETAILS_VALUE_2), Double.toString(DETAILS_VALUE_3));
+            String moduleBTest4 = String.format(XML_TEST_RESULT, METHOD_4, SUMMARY_SOURCE,
+                    SUMMARY_MESSAGE, ResultType.HIGHER_BETTER.toReportString(),
+                    ResultUnit.SCORE.toReportString(), Double.toString(SUMMARY_VALUE));
             String moduleBTest5 = String.format(XML_TEST_SKIP, METHOD_5);
             String moduleBTests = String.join("", moduleBTest3, moduleBTest4, moduleBTest5);
             String moduleBCases = String.format(XML_CASE, CLASS_B, moduleBTests);
diff --git a/common/util/tests/src/com/android/compatibility/common/util/UnitTests.java b/common/util/tests/src/com/android/compatibility/common/util/UnitTests.java
index 848fc45..96d67e6 100644
--- a/common/util/tests/src/com/android/compatibility/common/util/UnitTests.java
+++ b/common/util/tests/src/com/android/compatibility/common/util/UnitTests.java
@@ -32,6 +32,7 @@
         addTestSuite(MetricsXmlSerializerTest.class);
         addTestSuite(MultipartFormTest.class);
         addTestSuite(ReportLogTest.class);
+        addTestSuite(ResultHandlerTest.class);
         addTestSuite(StatTest.class);
         addTestSuite(TestResultTest.class);
     }