Merge "Modify cts-tradefed xml generator to match current schema." into honeycomb
diff --git a/tools/tradefed-host/Android.mk b/tools/tradefed-host/Android.mk
index c1e5c54..ceec5db 100644
--- a/tools/tradefed-host/Android.mk
+++ b/tools/tradefed-host/Android.mk
@@ -18,7 +18,7 @@
 
 # Only compile source java files in this lib.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_RESOURCE_DIRS := res
+LOCAL_JAVA_RESOURCE_DIRS := res ../host/src/res
 
 LOCAL_MODULE := cts-tradefed
 LOCAL_MODULE_TAGS := optional
diff --git a/tools/tradefed-host/etc/cts-tradefed b/tools/tradefed-host/etc/cts-tradefed
index 82eebe7..8bbce80 100755
--- a/tools/tradefed-host/etc/cts-tradefed
+++ b/tools/tradefed-host/etc/cts-tradefed
@@ -52,7 +52,7 @@
         echo "Unrecognized OS"
         exit
     fi;
-    CTS_ROOT=${ANDROID_BUILD_TOP}/out/host/${OS}/cts/android-cts
+    CTS_ROOT=${ANDROID_BUILD_TOP}/out/host/${OS}/cts
     if [ ! -d ${CTS_ROOT} ]; then
         echo "Could not find $CTS_ROOT in Android build environment. Try 'make cts'"
         exit
@@ -61,10 +61,10 @@
 
 if [ -z ${CTS_ROOT} ]; then
     # assume we're in an extracted cts install
-    CTS_ROOT="$(dirname $0)/.."
+    CTS_ROOT="$(dirname $0)/../.."
 fi;
 
-JAR_DIR=${CTS_ROOT}/tools
+JAR_DIR=${CTS_ROOT}/android-cts/tools
 JARS="ddmlib-prebuilt.jar tradefed-prebuilt.jar hosttestlib.jar cts-tradefed.jar"
 
 for JAR in $JARS; do
diff --git a/tools/tradefed-host/res/result/cts_result.css b/tools/tradefed-host/res/result/cts_result.css
deleted file mode 100644
index d7ce510..0000000
--- a/tools/tradefed-host/res/result/cts_result.css
+++ /dev/null
@@ -1,234 +0,0 @@
-/* Copyright (C) 2008 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.
-*/
-
-body {
-    font-family:arial,sans-serif;
-    color:#000;
-    font-size:13px;
-    color:#333;
-    padding:10;
-    margin:10;
-}
-
-table {
-    font-size:1em;
-    margin:0 0 1em;
-    padding:0;
-    border-collapse:collapse;
-    border-width:0;
-    empty-cells:show;
-    width: 95%;
-}
-
-/* Report logo and device name */
-#title table {
-    padding:5px;
-    border-width: 0px;
-    margin-left:auto;
-    margin-right:auto;
-    vertical-align:middle;
-}
-
-/* Device and test plan summary below the title */
-#summary table {
-    background-color: rgb(212, 233, 169);
-    -moz-border-radius:5px;
-    border-radius:5px;
-    padding:5px;
-    border-color: #A5C639 #A5C639 #A5C639 #A5C639;
-    border-width: 0px 0px 0px 0px;
-    margin-left:auto;
-    margin-right:auto;
-    width:80%;
-}
-
-#summary th {
-    background-color: #A5C639;
-    font-size:1.2em;
-    height: 2em;
-    width: 50%;
-}
-
-#summary td {
-    border-width: 0px 0px 0px 0px;
-    border-color: gray;
-    border-style: inset;
-    font-size:1em;
-    vertical-align: top;
-}
-
-#summaryinfo table {
-    background-color: rgb(212, 233, 169);
-    padding:5px;
-    border-width:0;
-    margin-left:auto;
-    margin-right:auto;
-}
-
-#summaryinfo td {
-    padding:1px;
-    border-width: 0px 0px 0px 0px;
-    vertical-align: top;
-}
-
-/* The test summary */
-#testsummary table {
-    background-color: rgb(212, 233, 169);
-    padding:5px;
-    border-width:1;
-    border-color: #A5C639;
-    margin-left:auto;
-    margin-right:auto;
-    width: 40%;
-}
-
-#testsummary th {
-    background-color: #A5C639;
-    border-width: 1px;
-    border-color: gray;
-    border-style: outset;
-    height: 2em;
-}
-
-#testsummary td {
-    border-width: 1px;
-    border-color: #A5C639;
-    border-style: outset;
-    text-align: center;
-}
-
-/* The test details */
-#testdetail table {
-    background-color: rgb(212, 233, 169);
-    padding:5px;
-    border-width:1;
-    border-color: #A5C639;
-    margin-left:auto;
-    margin-right:auto;
-    width: 95%;
-    table-layout:fixed;
-    vertical-align: top;
-}
-
-#testdetail th {
-    background-color: #A5C639;
-    border-width: 1px;
-    border-color: gray;
-    border-style: outset;
-    height: 2em;
-}
-
-#testdetail td {
-    border-width: 1px;
-    border-color: #A5C639;
-    border-style: outset;
-    text-align: left;
-    vertical-align: top;
-    padding:1;
-}
-
-/* The test package name */
-#none table {
-    border-width:0;
-    border-color: white;
-    background-color: white;
-    text-align:left;
-    border-collapse:collapse;
-}
-
-#none td {
-    border-width:0;
-    border-color: white;
-    background-color: white;
-    text-align:left;
-    border-collapse:collapse;
-    font-weight:bold;
-}
-
-/* Test cell details */
-td.failed {
-    background-color: #FA5858;
-    font-weight:bold;
-    vertical-align: top;
-    text-align: center;
-}
-
-td.failuredetails {
-    text-align: left;
-}
-
-td.pass {
-    text-align: center;
-    margin-left:auto;
-    margin-right:auto;
-}
-
-td.timeout, td.omitted, td.notExecuted {
-    background-color: #A5C639;
-    vertical-align: top;
-    text-align: center;
-}
-
-td.testname {
-    border-width: 1px;
-    border-color: #A5C639;
-    border-style: outset;
-    text-align: left;
-    vertical-align: top;
-    padding:1;
-    overflow:hidden;
-}
-
-td.testcase {
-    border-width: 1px;
-    border-color: #A5C639;
-    border-style: outset;
-    text-align: left;
-    vertical-align: top;
-    padding:1;
-    overflow:hidden;
-    font-weight:bold;
-}
-
-td.testcasespacer {
-    border-width: 1px;
-    border-color: #A5C639;
-    border-style: outset;
-    text-align: left;
-    vertical-align: top;
-    padding:1;
-    overflow:hidden;
-    font-weight:bold;
-}
-
-td.testsuite {
-    border-width: 1px;
-    border-color: #A5C639;
-    border-style: outset;
-    text-align: left;
-    vertical-align: top;
-    padding:1;
-    overflow:hidden;
-    font-weight:bold;
-}
-
-#details {
-    white-space: pre-wrap;       /* css-3 */
-    white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */
-    white-space: -pre-wrap;      /* Opera 4-6 */
-    white-space: -o-pre-wrap;    /* Opera 7 */
-    word-wrap: break-word;       /* Internet Explorer 5.5+ */
-    overflow:auto;
-}
diff --git a/tools/tradefed-host/res/result/cts_result.xsd b/tools/tradefed-host/res/result/cts_result.xsd
deleted file mode 100644
index f2fc3a8..0000000
--- a/tools/tradefed-host/res/result/cts_result.xsd
+++ /dev/null
@@ -1,192 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * Copyright (C) 2009 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.
- -->
-
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
-           targetNamespace="http://compatibility.android.com/cts_result/2.0"
-           xmlns="http://compatibility.android.com/cts_result/2.0"
-           elementFormDefault="qualified">
-
-<xs:element name="TestResult">
-  <xs:complexType>
-    <xs:sequence>
-      <xs:element name="DeviceInfo" type="deviceInfoType"/>
-      <xs:element name="HostInfo" type="hostInfoType"/>
-      <xs:element name="Summary" type="summaryType"/>
-      <xs:element name="TestPackage" type="testPackageType" maxOccurs="unbounded" minOccurs="1"/>
-    </xs:sequence>
-    <xs:attribute name="starttime" type="xs:string"/>
-    <xs:attribute name="endtime" type="xs:string"/>
-    <xs:attribute name="testPlan" type="xs:string"/>
-    <xs:attribute name="version" type="xs:string"/>
-    <xs:attribute name="profile" type="xs:string"/>
-  </xs:complexType>
-</xs:element>
-
-<xs:complexType name="deviceInfoType">
-  <xs:sequence>
-    <xs:element name="Screen">
-      <xs:complexType>
-        <xs:attribute name="resolution" type="xs:string"/>
-      </xs:complexType>
-    </xs:element>
-    <xs:element name="PhoneSubInfo">
-      <xs:complexType>
-        <xs:attribute name="subscriberId" type="xs:string"/>
-      </xs:complexType>
-    </xs:element>
-    <xs:element name="BuildInfo">
-      <xs:complexType>
-        <xs:attribute name="Xdpi" type="xs:decimal"/>
-        <xs:attribute name="Ydpi" type="xs:decimal"/>
-        <xs:attribute name="androidPlatformVersion" type="xs:integer"/>
-        <xs:attribute name="buildID" type="xs:string"/>
-        <xs:attribute name="buildName" type="xs:string"/>
-        <xs:attribute name="buildVersion" type="xs:string"/>
-        <xs:attribute name="build_board" type="xs:string"/>
-        <xs:attribute name="build_brand" type="xs:string"/>
-        <xs:attribute name="build_device" type="xs:string"/>
-        <xs:attribute name="build_fingerprint" type="xs:string"/>
-        <xs:attribute name="build_model" type="xs:string"/>
-        <xs:attribute name="build_type" type="xs:string"/>
-        <xs:attribute name="deviceID" type="xs:string"/>
-        <xs:attribute name="imei" type="xs:integer"/>
-        <xs:attribute name="imsi" type="xs:integer"/>
-        <xs:attribute name="keypad" type="xs:string"/>
-        <xs:attribute name="locales" type="xs:string"/>
-        <xs:attribute name="navigation" type="xs:string"/>
-        <xs:attribute name="network" type="xs:string"/>
-        <xs:attribute name="touch" type="xs:string"/>
-        <xs:attribute name="openGlEsVersion" type="xs:string"/>
-        <xs:attribute name="build_abi" type="xs:string"/>
-        <xs:attribute name="build_abi2" type="xs:string"/>
-      </xs:complexType>
-    </xs:element>
-    <xs:element name="FeatureInfo" type="featureInfoType"/>
-    <xs:element name="ProcessInfo" type="processInfoType"/>
-  </xs:sequence>
-</xs:complexType>
-
-<xs:complexType name="hostInfoType">
-  <xs:sequence>
-    <xs:element name="Os">
-      <xs:complexType>
-        <xs:attribute name="arch" type="xs:string"/>
-        <xs:attribute name="name" type="xs:string"/>
-        <xs:attribute name="version" type="xs:string"/>
-      </xs:complexType>
-    </xs:element>
-    <xs:element name="Java">
-      <xs:complexType>
-        <xs:attribute name="name" type="xs:string"/>
-        <xs:attribute name="version" type="xs:string"/>
-      </xs:complexType>
-    </xs:element>
-    <xs:element name="Cts">
-      <xs:complexType>
-        <xs:sequence>
-          <xs:element name="IntValue" minOccurs="0" maxOccurs="unbounded">
-            <xs:complexType>
-              <xs:attribute name="name" type="xs:string"/>
-              <xs:attribute name="value" type="xs:integer"/>
-            </xs:complexType>
-          </xs:element>
-        </xs:sequence>
-        <xs:attribute name="version" type="xs:string"/>
-      </xs:complexType>
-    </xs:element>
-  </xs:sequence>
-  <xs:attribute name="name" type="xs:string"/>
-</xs:complexType>
-
-<xs:complexType name="featureInfoType">
-    <xs:sequence>
-        <xs:element name="Feature" minOccurs="0" maxOccurs="unbounded">
-            <xs:complexType>
-                <xs:attribute name="name" type="xs:string" />
-                <xs:attribute name="type" type="xs:string" />
-                <xs:attribute name="available" type="xs:string" />
-            </xs:complexType>
-        </xs:element>
-    </xs:sequence>
-</xs:complexType>
-
-<xs:complexType name="processInfoType">
-    <xs:sequence>
-        <xs:element name="Process" minOccurs="0" maxOccurs="unbounded">
-            <xs:complexType>
-                <xs:attribute name="name" type="xs:string" />
-                <xs:attribute name="uid" type="xs:integer" />
-            </xs:complexType>
-        </xs:element>
-    </xs:sequence>
-</xs:complexType>
-
-<xs:complexType name="summaryType">
-  <xs:attribute name="failed" type="xs:integer"/>
-  <xs:attribute name="notExecuted" type="xs:integer"/>
-  <xs:attribute name="pass" type="xs:integer"/>
-  <xs:attribute name="timeout" type="xs:integer"/>
-  <xs:attribute name="omitted" type="xs:integer"/>
-  <xs:attribute name="total" type="xs:integer"/>
-</xs:complexType>
-
-<xs:complexType name="testPackageType">
-    <xs:complexContent>
-        <xs:extension base="summaryType">
-            <xs:sequence>
-                <xs:element name="TestCase" type="testCaseType" />
-            </xs:sequence>
-            <xs:attribute name="digest" type="xs:hexBinary" />
-            <xs:attribute name="name" type="xs:string" use="required" />
-            <xs:attribute name="runtime" type="xs:string" />
-        </xs:extension>
-    </xs:complexContent>
-</xs:complexType>
-
-<xs:complexType name="testCaseType">
-  <xs:sequence>
-    <xs:element name="Test" type="testType" minOccurs="0" maxOccurs="unbounded"/>
-  </xs:sequence>
-  <xs:attribute name="name" type="xs:string" use="required"/>
-</xs:complexType>
-
-<xs:complexType name="testType">
-  <xs:sequence>
-    <xs:element name="FailedScene" minOccurs="0" maxOccurs="1">
-      <xs:complexType>
-          <xs:simpleContent>
-              <xs:extension base="xs:string">
-                  <xs:attribute name="message" type="xs:string" />
-              </xs:extension>
-          </xs:simpleContent>
-      </xs:complexType>
-    </xs:element>
-  </xs:sequence>
-  <xs:attribute name="name" type="xs:string" use="required"/>
-  <xs:attribute name="result" type="resultType" use="required"/>
-</xs:complexType>
-
-<xs:simpleType name="resultType">
-  <xs:restriction base="xs:string">
-    <xs:enumeration value="pass"/>
-    <xs:enumeration value="fail"/>
-    <xs:enumeration value="timeout"/>
-    <xs:enumeration value="notExecuted"/>
-    <xs:enumeration value="omitted"/>
-  </xs:restriction>
-</xs:simpleType>
-</xs:schema>
diff --git a/tools/tradefed-host/res/result/cts_result.xsl b/tools/tradefed-host/res/result/cts_result.xsl
deleted file mode 100644
index cb220e1..0000000
--- a/tools/tradefed-host/res/result/cts_result.xsl
+++ /dev/null
@@ -1,513 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 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.
--->
-
-<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#160;"> ]>
-<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
-    <xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
-
-    <xsl:template match="/">
-
-        <html>
-            <STYLE type="text/css">
-                @import "cts_result.css";
-            </STYLE>
-
-            <body>
-                <!-- Title of the Report -->
-                <DIV id="title">
-                    <TABLE>
-                        <TR>
-                            <TD width="40%" align="left"><img src="logo.gif"></img></TD>
-                            <TD width="60%" align="left">
-                                <h1>Test Report for <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@build_model"/> -
-                                <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@deviceID"/>
-                            </h1>
-                        </TD>
-                    </TR>
-                </TABLE>
-            </DIV>
-            <img src="newrule-green.png" align="left"></img>
-
-            <br></br>
-            <br></br>
-
-            <!-- Header with phone and plan information -->
-            <DIV id="summary">
-                <TABLE width="90%" frame="none">
-                    <TR>
-                        <TH>Device Information</TH>
-                        <TH>Test Summary</TH>
-                    </TR>
-
-                    <TR>
-                        <TD>
-                            <!-- Device information -->
-                            <div id="summaryinfo">
-                                <TABLE width="75%">
-                                    <TR>
-                                        <TD class="rowtitle">Build Model</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@build_model"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Build Name</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@buildName"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Device ID</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@deviceID"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Firmware Version</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@buildVersion"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Firmware Build Number</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@buildID"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Build Fingerprint</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@build_fingerprint"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Build ABI</TD>
-                                        <TD>
-                                            <xsl:value-of
-                                              select="TestResult/DeviceInfo/BuildInfo/@build_abi"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Build ABI2</TD>
-                                        <TD>
-                                            <xsl:value-of
-                                              select="TestResult/DeviceInfo/BuildInfo/@build_abi2"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Android Platform Version</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@androidPlatformVersion"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Supported Locales</TD>
-                                        <TD>
-                                            <xsl:call-template name="formatDelimitedString">
-                                                <xsl:with-param name="string" select="TestResult/DeviceInfo/BuildInfo/@locales"/>
-                                            </xsl:call-template>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Screen size</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/DeviceInfo/Screen/@resolution"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Phone number</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/DeviceInfo/PhoneSubInfo/@subscriberId"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">x dpi</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@Xdpi"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">y dpi</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@Ydpi"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Touch</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@touch"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Navigation</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@navigation"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Keypad</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@keypad"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Network</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@network"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">IMEI</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@imei"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">IMSI</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@imsi"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Open GL ES Version</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@openGlEsVersion"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Features</TD>
-                                        <TD>
-                                            <xsl:for-each select="TestResult/DeviceInfo/FeatureInfo/Feature[@type='sdk']">
-                                                <xsl:text>[</xsl:text>
-                                                <xsl:choose>
-                                                    <xsl:when test="@available = 'true'">
-                                                        <xsl:text>X</xsl:text>
-                                                    </xsl:when>
-                                                    <xsl:otherwise>
-                                                        <xsl:text>_</xsl:text>
-                                                    </xsl:otherwise>
-                                                </xsl:choose>
-                                                <xsl:text>] </xsl:text>
-
-                                                <xsl:value-of select="@name" />
-                                                <br />
-                                            </xsl:for-each>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Other Features</TD>
-                                        <TD>
-                                            <UL>
-                                                <xsl:for-each select="TestResult/DeviceInfo/FeatureInfo/Feature[@type='other']">
-                                                    <LI><xsl:value-of select="@name" /></LI>
-                                                </xsl:for-each>
-                                            </UL>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Root Processes</TD>
-                                        <TD>
-                                            <UL>
-                                                <xsl:for-each select="TestResult/DeviceInfo/ProcessInfo/Process[@uid='0']">
-                                                    <LI><xsl:value-of select="@name" /></LI>
-                                                </xsl:for-each>
-                                            </UL>
-                                        </TD>
-                                    </TR>
-                                </TABLE>
-                            </div>
-                        </TD>
-
-                        <!-- plan information -->
-                        <TD>
-                            <div id="summaryinfo">
-                                <TABLE width="75%">
-                                    <TR>
-                                        <TD class="rowtitle">CTS version</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/HostInfo/Cts/@version"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Test timeout</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/HostInfo/Cts/IntValue[@name='testStatusTimeoutMs']/@value" /> ms
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Host Info</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/HostInfo/@name"/>
-                                            (<xsl:value-of select="TestResult/HostInfo/Os/@name"/> - 
-                                              <xsl:value-of select="TestResult/HostInfo/Os/@version"/>)
-                                        </TD>
-                                    </TR>
-                                    <TR><TD><BR></BR></TD><TD></TD></TR>
-                                    <TR>
-                                        <TD class="rowtitle">Plan name</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/@testPlan"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Profile</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/@profile"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Start time</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/@starttime"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">End time</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/@endtime"/>
-                                        </TD>
-                                    </TR>
-
-                                    <!-- Test Summary -->
-                                    <TR><TD><BR></BR></TD><TD></TD></TR>
-                                    <TR>
-                                        <TD class="rowtitle">Tests Passed</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/Summary/@pass"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Tests Failed</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/Summary/@failed"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Tests Timed out</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/Summary/@timeout"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Tests Omitted</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/Summary/@omitted"/>
-                                        </TD>
-                                    </TR>
-                                    <TR>
-                                        <TD class="rowtitle">Tests Not Executed</TD>
-                                        <TD>
-                                            <xsl:value-of select="TestResult/Summary/@notExecuted"/>
-                                        </TD>
-                                    </TR>
-                                </TABLE>
-                            </div>
-                        </TD>
-                    </TR>
-                </TABLE>
-            </DIV>
-
-            <!-- High level summary of test execution -->
-            <h2 align="center">Test Summary by Package</h2>
-            <DIV id="testsummary">
-                <TABLE>
-                    <TR>
-                        <TH>Test Package</TH>
-                        <TH>Passed</TH>
-                        <TH>Failed</TH>
-                        <TH>Timed Out</TH>
-                        <TH>Total Tests</TH>
-                    </TR>
-                    <xsl:for-each select="TestResult/TestPackage">
-                        <TR>
-                            <TD>
-                                <xsl:variable name="href"><xsl:value-of select="@name"/></xsl:variable>
-                                <a href="#{$href}"><xsl:value-of select="@name"/></a>
-                            </TD>
-                            <TD>
-                                <xsl:value-of select="@pass"/>
-                            </TD>
-                            <TD>
-                                <xsl:value-of select="@failed"/>
-                            </TD>
-                            <TD>
-                                <xsl:value-of select="@timeout"/>
-                            </TD>
-                            <TD>
-                                <xsl:value-of select="@total"/>
-                            </TD>
-                        </TR>
-                    </xsl:for-each> <!-- end package -->
-                </TABLE>
-            </DIV>
-
-            <!-- Details of all the executed tests -->
-            <h2 align="center">Detailed Test Report</h2>
-
-            <!-- test package -->
-            <DIV id="testdetail">
-                <xsl:for-each select="TestResult/TestPackage">
-                    <DIV id="none">
-                        <TABLE>
-                            <TR>
-                                <TD class="none" align="left">
-                                    <xsl:variable name="href"><xsl:value-of select="@name"/></xsl:variable>
-                                    <a name="{$href}">Compatibility Test Package: <xsl:value-of select="@name"/></a>
-                                </TD>
-                            </TR>
-                        </TABLE>
-                    </DIV>
-
-                    <TABLE>
-                        <TR>
-                            <TH width="25%">Test</TH>
-                            <TH width="7%">Result</TH>
-                            <TH width="68%">Failure Details</TH>
-                        </TR>
-
-                        <!-- test case -->
-                        <xsl:for-each select="TestCase">
-
-                            <!-- emit a blank row before every test suite name -->
-                            <xsl:if test="position()!=1">
-                                <TR> <TD class="testcasespacer" colspan="3"></TD> </TR>
-                            </xsl:if>
-
-
-                            <TR>
-                                <TD class="testcase" colspan="3">
-                                    <xsl:value-of select="@name"/>
-                                </TD>
-                            </TR>
-                            
-                            <!-- test -->
-                            <xsl:for-each select="Test">
-                                <TR>
-                                    <TD class="testname"> -- <xsl:value-of select="@name"/></TD>
-
-                                    <!-- test results -->
-                                    <xsl:choose>
-                                        <xsl:when test="string(@KnownFailure)">
-                                            <!-- "pass" indicates the that test actually passed (results have been inverted already) -->
-                                            <xsl:if test="@result='pass'">
-                                                <TD class="pass">
-                                                    <div style="text-align: center; margin-left:auto; margin-right:auto;">
-                                                        known problem
-                                                    </div>
-                                                </TD>
-                                                <TD class="failuredetails"></TD>
-                                            </xsl:if>
-
-                                            <!-- "fail" indicates that a known failure actually passed (results have been inverted already) -->
-                                            <xsl:if test="@result='fail'">
-                                                <TD class="failed">
-                                                    <div style="text-align: center; margin-left:auto; margin-right:auto;">
-                                                        <xsl:value-of select="@result"/>
-                                                    </div>
-                                                </TD>
-                                               <TD class="failuredetails">
-                                                    <div id="details">
-                                                        A test that was a known failure actually passed. Please check.
-                                                    </div>
-                                               </TD>
-                                            </xsl:if>
-                                        </xsl:when>
-
-                                        <xsl:otherwise>
-                                            <xsl:if test="@result='pass'">
-                                                <TD class="pass">
-                                                    <div style="text-align: center; margin-left:auto; margin-right:auto;">
-                                                        <xsl:value-of select="@result"/>
-                                                    </div>
-                                                </TD>
-                                                <TD class="failuredetails"></TD>
-                                            </xsl:if>
-
-                                            <xsl:if test="@result='fail'">
-                                                <TD class="failed">
-                                                    <div style="text-align: center; margin-left:auto; margin-right:auto;">
-                                                        <xsl:value-of select="@result"/>
-                                                    </div>
-                                                </TD>
-                                                <TD class="failuredetails">
-                                                    <div id="details">
-                                                        <xsl:value-of select="FailedScene/@message"/>
-                                                    </div>
-                                                </TD>
-                                            </xsl:if>
-
-                                            <xsl:if test="@result='timeout'">
-                                                <TD class="timeout">
-                                                    <div style="text-align: center; margin-left:auto; margin-right:auto;">
-                                                        <xsl:value-of select="@result"/>
-                                                    </div>
-                                                <TD class="failuredetails"></TD>
-                                                </TD>
-                                            </xsl:if>
-
-                                            <xsl:if test="@result='omitted'">
-                                                <TD class="omitted">
-                                                    <div style="text-align: center; margin-left:auto; margin-right:auto;">
-                                                        <xsl:value-of select="@result"/>
-                                                    </div>
-                                                </TD>
-                                                <TD class="failuredetails"></TD>
-                                            </xsl:if>
-
-                                            <xsl:if test="@result='notExecuted'">
-                                                <TD class="notExecuted">
-                                                    <div style="text-align: center; margin-left:auto; margin-right:auto;">
-                                                        <xsl:value-of select="@result"/>
-                                                    </div>
-                                                </TD>
-                                                <TD class="failuredetails"></TD>
-                                            </xsl:if>
-                                        </xsl:otherwise>
-                                    </xsl:choose>
-                                </TR> <!-- finished with a row -->
-                            </xsl:for-each> <!-- end test -->
-                        </xsl:for-each> <!-- end test case -->
-                    </TABLE>
-                </xsl:for-each> <!-- end test package -->
-            </DIV>
-            </body>
-        </html>
-    </xsl:template>
-
-    <!-- Take a delimited string and insert line breaks after a some number of elements. --> 
-    <xsl:template name="formatDelimitedString">
-        <xsl:param name="string" />
-        <xsl:param name="numTokensPerRow" select="10" />
-        <xsl:param name="tokenIndex" select="1" />
-        <xsl:if test="$string">
-            <!-- Requires the last element to also have a delimiter after it. -->
-            <xsl:variable name="token" select="substring-before($string, ';')" />
-            <xsl:value-of select="$token" />
-            <xsl:text>&#160;</xsl:text>
-          
-            <xsl:if test="$tokenIndex mod $numTokensPerRow = 0">
-                <br />
-            </xsl:if>
-
-            <xsl:call-template name="formatDelimitedString">
-                <xsl:with-param name="string" select="substring-after($string, ';')" />
-                <xsl:with-param name="numTokensPerRow" select="$numTokensPerRow" />
-                <xsl:with-param name="tokenIndex" select="$tokenIndex + 1" />
-            </xsl:call-template>
-        </xsl:if>
-    </xsl:template>
-
-</xsl:stylesheet>
diff --git a/tools/tradefed-host/res/result/logo.gif b/tools/tradefed-host/res/result/logo.gif
deleted file mode 100644
index 61970b3..0000000
--- a/tools/tradefed-host/res/result/logo.gif
+++ /dev/null
Binary files differ
diff --git a/tools/tradefed-host/res/result/newrule-green.png b/tools/tradefed-host/res/result/newrule-green.png
deleted file mode 100644
index 10a4194..0000000
--- a/tools/tradefed-host/res/result/newrule-green.png
+++ /dev/null
Binary files differ
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
index 4c29b01..fcbb5ee 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
@@ -26,7 +26,6 @@
 import com.android.tradefed.result.LogDataType;
 import com.android.tradefed.result.TestResult;
 import com.android.tradefed.result.TestRunResult;
-import com.android.tradefed.result.TestResult.TestStatus;
 import com.android.tradefed.targetsetup.IBuildInfo;
 import com.android.tradefed.targetsetup.IFolderBuildInfo;
 import com.android.tradefed.util.FileUtil;
@@ -44,7 +43,6 @@
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.HashMap;
-import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
@@ -60,15 +58,14 @@
     private static final String LOG_TAG = "CtsXmlResultReporter";
 
     private static final String TEST_RESULT_FILE_NAME = "testResult.xml";
-    private static final String CTS_RESULT_FILE_VERSION = "2.0";
+    private static final String CTS_RESULT_FILE_VERSION = "1.10";
     private static final String CTS_VERSION = "99";
 
-
     private static final String[] CTS_RESULT_RESOURCES = {"cts_result.xsl", "cts_result.css",
         "logo.gif", "newrule-green.png"};
 
     /** the XML namespace */
-    private static final String ns = null;
+    static final String ns = null;
 
     private static final String REPORT_DIR_NAME = "output-file-path";
     @Option(name=REPORT_DIR_NAME, description="root file system path to directory to store xml " +
@@ -80,6 +77,8 @@
 
     private String mStartTime;
 
+    private String mReportPath = "";
+
     public void setReportDir(File reportDir) {
         mReportDir = reportDir;
     }
@@ -115,7 +114,17 @@
      */
     @Override
     public void testLog(String dataName, LogDataType dataType, InputStream dataStream) {
-        // TODO: implement this
+        // save as zip file in report dir
+        // TODO: ensure uniqueness of file name
+        // TODO: use dataType.getFileExt() when its made public
+        String fileName = String.format("%s.%s", dataName, dataType.name().toLowerCase());
+        // TODO: consider compressing large files
+        File logFile = new File(mReportDir, fileName);
+        try {
+            FileUtil.writeToFile(dataStream, logFile);
+        } catch (IOException e) {
+            Log.e(LOG_TAG, String.format("Failed to write log %s", logFile.getAbsolutePath()));
+        }
     }
 
     /**
@@ -171,7 +180,7 @@
             serializer.endDocument();
             // TODO: output not executed timeout omitted counts
             String msg = String.format("XML test result file generated at %s. Total tests %d, " +
-                    "Failed %d, Error %d", reportDir.getAbsolutePath(), getNumTotalTests(),
+                    "Failed %d, Error %d", getReportPath(), getNumTotalTests(),
                     getNumFailedTests(), getNumErrorTests());
             Log.logAndDisplay(LogLevel.INFO, LOG_TAG, msg);
             Log.logAndDisplay(LogLevel.INFO, LOG_TAG, String.format("Time: %s",
@@ -188,6 +197,10 @@
         }
     }
 
+    private String getReportPath() {
+        return mReportPath;
+    }
+
     /**
      * Output the results XML.
      *
@@ -201,7 +214,6 @@
         serializer.startTag(ns, "TestResult");
         // TODO: output test plan and profile values
         serializer.attribute(ns, "testPlan", "unknown");
-        serializer.attribute(ns, "profile", "unknown");
         serializer.attribute(ns, "starttime", startTime);
         serializer.attribute(ns, "endtime", endTime);
         serializer.attribute(ns, "version", CTS_RESULT_FILE_VERSION);
@@ -387,12 +399,10 @@
         serializer.startTag(ns, "Summary");
         serializer.attribute(ns, "failed", Integer.toString(getNumErrorTests() +
                 getNumFailedTests()));
-        // TODO: output notExecuted, timeout, and omitted count
+        // TODO: output notExecuted, timeout count
         serializer.attribute(ns, "notExecuted", "0");
         serializer.attribute(ns, "timeout", "0");
-        serializer.attribute(ns, "omitted", "0");
         serializer.attribute(ns, "pass", Integer.toString(getNumPassedTests()));
-        serializer.attribute(ns, "total", Integer.toString(getNumTotalTests()));
         serializer.endTag(ns, "Summary");
     }
 
@@ -423,130 +433,34 @@
         }
         serializer.startTag(ns, "TestPackage");
         serializer.attribute(ns, "name", runResult.getName());
-        serializer.attribute(ns, "runTime", formatElapsedTime(runResult.getElapsedTime()));
-        // TODO: generate digest
-        serializer.attribute(ns, "digest", "");
-        serializer.attribute(ns, "failed", Integer.toString(runResult.getNumErrorTests() +
-                runResult.getNumFailedTests()));
-        // TODO: output notExecuted, timeout, and omitted count
-        serializer.attribute(ns, "notExecuted", "0");
-        serializer.attribute(ns, "timeout", "0");
-        serializer.attribute(ns, "omitted", "0");
-        serializer.attribute(ns, "pass", Integer.toString(runResult.getNumPassedTests()));
-        serializer.attribute(ns, "total", Integer.toString(runResult.getNumTests()));
+        serializer.attribute(ns, "appPackageName", runResult.getName());
+        serializer.attribute(ns, "digest", getMetric(runResult, "digest"));
 
-        // the results XML needs to organize test's by class. Build a nested data structure that
-        // group's the results by class name
-        Map<String, Map<TestIdentifier, TestResult>> classResultsMap = buildClassNameMap(
-                runResult.getTestResults());
+        // Dump the results.
 
-        for (Map.Entry<String, Map<TestIdentifier, TestResult>> resultsEntry :
-                classResultsMap.entrySet()) {
-            serializer.startTag(ns, "TestCase");
-            serializer.attribute(ns, "name", resultsEntry.getKey());
-            serializeTests(serializer, resultsEntry.getValue());
-            serializer.endTag(ns, "TestCase");
+        // organize the tests into data structures that mirror the expected xml output.
+        TestSuiteRoot suiteRoot = new TestSuiteRoot();
+        for (Map.Entry<TestIdentifier, TestResult> testEntry : runResult.getTestResults()
+                .entrySet()) {
+            suiteRoot.insertTest(testEntry.getKey(), testEntry.getValue());
         }
+        suiteRoot.serialize(serializer);
         serializer.endTag(ns, "TestPackage");
     }
 
     /**
-     * Organizes the test run results into a format organized by class name.
-     */
-    private Map<String, Map<TestIdentifier, TestResult>> buildClassNameMap(
-            Map<TestIdentifier, TestResult> results) {
-        // use a linked hashmap to have predictable iteration order
-        Map<String, Map<TestIdentifier, TestResult>> classResultMap =
-            new LinkedHashMap<String, Map<TestIdentifier, TestResult>>();
-        for (Map.Entry<TestIdentifier, TestResult> resultEntry : results.entrySet()) {
-            String className = resultEntry.getKey().getClassName();
-            Map<TestIdentifier, TestResult> resultsForClass = classResultMap.get(className);
-            if (resultsForClass == null) {
-                resultsForClass = new LinkedHashMap<TestIdentifier, TestResult>();
-                classResultMap.put(className, resultsForClass);
-            }
-            resultsForClass.put(resultEntry.getKey(), resultEntry.getValue());
-        }
-        return classResultMap;
-    }
-
-    /**
-     * Output XML for given map of tests their results
+     * Helper method to retrieve the metric value with given name, or blank if not found
      *
-     * @param serializer
-     * @param results
-     * @throws IOException
-     */
-    private void serializeTests(KXmlSerializer serializer, Map<TestIdentifier, TestResult> results)
-            throws IOException {
-        for (Map.Entry<TestIdentifier, TestResult> resultEntry : results.entrySet()) {
-            serializeTest(serializer, resultEntry.getKey(), resultEntry.getValue());
-        }
-    }
-
-    /**
-     * Output the XML for given test and result.
-     *
-     * @param serializer
-     * @param testId
-     * @param result
-     * @throws IOException
-     */
-    private void serializeTest(KXmlSerializer serializer, TestIdentifier testId, TestResult result)
-            throws IOException {
-        serializer.startTag(ns, "Test");
-        serializer.attribute(ns, "name", testId.getTestName());
-        serializer.attribute(ns, "result", convertStatus(result.getStatus()));
-
-        if (result.getStackTrace() != null) {
-            String sanitizedStack = sanitizeStackTrace(result.getStackTrace());
-            serializer.startTag(ns, "FailedScene");
-            serializer.attribute(ns, "message", getFailureMessageFromStackTrace(sanitizedStack));
-            serializer.text(sanitizedStack);
-            serializer.endTag(ns, "FailedScene");
-        }
-        serializer.endTag(ns, "Test");
-    }
-
-    /**
-     * Convert a {@link TestStatus} to the result text to output in XML
-     *
-     * @param status the {@link TestStatus}
+     * @param runResult
+     * @param string
      * @return
      */
-    private String convertStatus(TestStatus status) {
-        switch (status) {
-            case ERROR:
-                return "fail";
-            case FAILURE:
-                return "fail";
-            case PASSED:
-                return "pass";
-            // TODO add notExecuted, omitted timeout
+    private String getMetric(TestRunResult runResult, String keyName) {
+        String value = runResult.getRunMetrics().get(keyName);
+        if (value == null) {
+            return "";
         }
-        return "omitted";
-    }
-
-    /**
-     * Strip out any invalid XML characters that might cause the report to be unviewable.
-     * http://www.w3.org/TR/REC-xml/#dt-character
-     */
-    private static String sanitizeStackTrace(String trace) {
-        if (trace != null) {
-            return trace.replaceAll("[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD]", "");
-        } else {
-            return null;
-        }
-    }
-
-    private static String getFailureMessageFromStackTrace(String stack) {
-        // This is probably too simplistic to work in all cases, but for now, just return first
-        // line of stack as failure message
-        int firstNewLine = stack.indexOf('\n');
-        if (firstNewLine != -1) {
-            return stack.substring(0, firstNewLine);
-        }
-        return stack;
+        return value;
     }
 
     /**
@@ -594,11 +508,14 @@
 
     /**
      * Creates the output stream to use for test results. Exposed for mocking.
+     * @param mReportPath
      */
     OutputStream createOutputResultStream(File reportDir) throws IOException {
         File reportFile = new File(reportDir, TEST_RESULT_FILE_NAME);
         Log.i(LOG_TAG, String.format("Created xml report file at %s",
                 reportFile.getAbsolutePath()));
+        // TODO: convert to path relative to cts root
+        mReportPath = reportFile.getAbsolutePath();
         return new FileOutputStream(reportFile);
     }
 
@@ -610,7 +527,7 @@
     private void copyFormattingFiles(File resultsDir) {
         for (String resultFileName : CTS_RESULT_RESOURCES) {
             InputStream configStream = getClass().getResourceAsStream(
-                    String.format("/result/%s", resultFileName));
+                    String.format("%s", resultFileName));
             if (configStream != null) {
                 File resultFile = new File(resultsDir, resultFileName);
                 try {
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestCase.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestCase.java
new file mode 100644
index 0000000..3fce8c4
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestCase.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2011 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.cts.tradefed.result;
+
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestResult.TestStatus;
+
+import org.kxml2.io.KXmlSerializer;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Data structure that represents a "TestCase" XML element and its children.
+ */
+class TestCase {
+
+    private final String mName;
+
+    Map<String, TestResult> mChildTestMap = new LinkedHashMap<String, TestResult>();
+
+    /**
+     * Create a {@link TestCase}
+     * @param testCaseName
+     */
+    public TestCase(String testCaseName) {
+        mName = testCaseName;
+    }
+
+    /**
+     * Inserts given test result
+     *
+     * @param testName
+     * @param testResult
+     */
+    public void insertTest(String testName, TestResult testResult) {
+        mChildTestMap.put(testName, testResult);
+    }
+
+    /**
+     * Serialize this object and all its contents to XML.
+     *
+     * @param serializer
+     * @throws IOException
+     */
+    public void serialize(KXmlSerializer serializer) throws IOException {
+        serializer.startTag(CtsXmlResultReporter.ns, "TestCase");
+        serializer.attribute(CtsXmlResultReporter.ns, "name", mName);
+        // unused
+        serializer.attribute(CtsXmlResultReporter.ns, "priority", "");
+        for (Map.Entry<String, TestResult> resultEntry: mChildTestMap.entrySet()) {
+            serializeTestResult(serializer, resultEntry.getKey(), resultEntry.getValue());
+        }
+       serializer.endTag(CtsXmlResultReporter.ns, "TestCase");
+    }
+
+    private void serializeTestResult(KXmlSerializer serializer, String name, TestResult result)
+            throws IOException {
+        serializer.startTag(CtsXmlResultReporter.ns, "Test");
+        serializer.attribute(CtsXmlResultReporter.ns, "name", name);
+        serializer.attribute(CtsXmlResultReporter.ns, "result", convertStatus(result.getStatus()));
+
+        if (result.getStackTrace() != null) {
+            String sanitizedStack = sanitizeStackTrace(result.getStackTrace());
+            serializer.startTag(CtsXmlResultReporter.ns, "FailedScene");
+            serializer.attribute(CtsXmlResultReporter.ns, "message",
+                    getFailureMessageFromStackTrace(sanitizedStack));
+            serializer.text(sanitizedStack);
+            serializer.endTag(CtsXmlResultReporter.ns, "FailedScene");
+        }
+
+        serializer.endTag(CtsXmlResultReporter.ns, "Test");
+
+    }
+
+    /**
+     * Convert a {@link TestStatus} to the result text to output in XML
+     *
+     * @param status the {@link TestStatus}
+     * @return
+     */
+    private String convertStatus(TestStatus status) {
+        switch (status) {
+            case ERROR:
+                return "fail";
+            case FAILURE:
+                return "fail";
+            case PASSED:
+                return "pass";
+            // TODO add notExecuted
+        }
+        return "omitted";
+    }
+
+    /**
+     * Strip out any invalid XML characters that might cause the report to be unviewable.
+     * http://www.w3.org/TR/REC-xml/#dt-character
+     */
+    private static String sanitizeStackTrace(String trace) {
+        if (trace != null) {
+            return trace.replaceAll("[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD]", "");
+        } else {
+            return null;
+        }
+    }
+
+    private static String getFailureMessageFromStackTrace(String stack) {
+        // This is probably too simplistic to work in all cases, but for now, just return first
+        // line of stack as failure message
+        int firstNewLine = stack.indexOf('\n');
+        if (firstNewLine != -1) {
+            return stack.substring(0, firstNewLine);
+        }
+        return stack;
+    }
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSuite.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSuite.java
new file mode 100644
index 0000000..7711740
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSuite.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2011 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.cts.tradefed.result;
+
+import com.android.tradefed.result.TestResult;
+
+import org.kxml2.io.KXmlSerializer;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Data structure that represents a "TestSuite" XML element and its children.
+ */
+class TestSuite {
+
+    private final String mName;
+
+    // use linked hash map for predictable iteration order
+    Map<String, TestSuite> mChildSuiteMap = new LinkedHashMap<String, TestSuite>();
+    Map<String, TestCase> mChildTestCaseMap = new LinkedHashMap<String, TestCase>();
+
+    /**
+     * @param testSuite
+     */
+    public TestSuite(String suiteName) {
+        mName = suiteName;
+    }
+
+    /**
+     * Insert the given test result into this suite.
+     *
+     * @param suiteNames list of remaining suite names for this test
+     * @param testClassName the test class name
+     * @param testName the test method name
+     * @param testResult the {@link TestResult}
+     */
+    public void insertTest(List<String> suiteNames, String testClassName, String testName,
+            TestResult testResult) {
+        if (suiteNames.size() <= 0) {
+            // no more package segments
+            TestCase testCase = getTestCase(testClassName);
+            testCase.insertTest(testName, testResult);
+        } else {
+            String rootName = suiteNames.remove(0);
+            TestSuite suite = getTestSuite(rootName);
+            suite.insertTest(suiteNames, testClassName, testName, testResult);
+        }
+    }
+
+    /**
+     * Get the child {@link TestSuite} with given name, creating if necessary.
+     *
+     * @param suiteName
+     * @return the {@link TestSuite}
+     */
+    private TestSuite getTestSuite(String suiteName) {
+        TestSuite testSuite = mChildSuiteMap.get(suiteName);
+        if (testSuite == null) {
+            testSuite = new TestSuite(suiteName);
+            mChildSuiteMap.put(suiteName, testSuite);
+        }
+        return testSuite;
+    }
+
+    /**
+     * Get the child {@link TestCase} with given name, creating if necessary.
+     * @param testCaseName
+     * @return
+     */
+    private TestCase getTestCase(String testCaseName) {
+        TestCase testCase = mChildTestCaseMap.get(testCaseName);
+        if (testCase == null) {
+            testCase = new TestCase(testCaseName);
+            mChildTestCaseMap.put(testCaseName, testCase);
+        }
+        return testCase;
+    }
+
+    /**
+     * Serialize this object and all its contents to XML.
+     *
+     * @param serializer
+     * @throws IOException
+     */
+    public void serialize(KXmlSerializer serializer) throws IOException {
+        if (mName != null) {
+            serializer.startTag(CtsXmlResultReporter.ns, "TestSuite");
+            serializer.attribute(CtsXmlResultReporter.ns, "name", mName);
+        }
+        for (TestSuite childSuite : mChildSuiteMap.values()) {
+            childSuite.serialize(serializer);
+        }
+        for (TestCase childCase : mChildTestCaseMap.values()) {
+            childCase.serialize(serializer);
+        }
+        if (mName != null) {
+            serializer.endTag(CtsXmlResultReporter.ns, "TestSuite");
+        }
+    }
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSuiteRoot.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSuiteRoot.java
new file mode 100644
index 0000000..bb0b0fb
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSuiteRoot.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 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.cts.tradefed.result;
+
+import com.android.ddmlib.Log;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.result.TestResult;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Helper class for converting test results into the CTS XML serialization format.
+ * <p/>
+ * A TestIdentifier with name "com.example.ExampleTest#testExample will get serialized as the
+ * following XML
+ * <pre>
+ * TestSuite name="com"
+ *    TestSuite name ="example"
+ *        TestCase name = "ExampleTest"
+ *            Test name="testExample"
+ * </pre>
+ */
+class TestSuiteRoot extends TestSuite {
+
+    private static final String LOG_TAG = "TestSuiteRoot";
+
+    public TestSuiteRoot() {
+        super(null);
+    }
+
+    /**
+     * Insert the given test result.
+     *
+     * @param testId
+     * @param testResult
+     */
+    public void insertTest(TestIdentifier testId, TestResult testResult) {
+        List<String> classNameSegments = new LinkedList<String>();
+        classNameSegments.addAll(Arrays.asList(testId.getClassName().split("\\.")));
+        if (classNameSegments.size() <= 0) {
+            Log.e(LOG_TAG, String.format("Unrecognized package name format for test class '%s'",
+                    testId.getClassName()));
+        } else {
+            String testCaseName = classNameSegments.remove(classNameSegments.size()-1);
+            insertTest(classNameSegments, testCaseName, testId.getTestName(), testResult);
+        }
+    }
+}
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java
index 9aeaccd..88bb5d1 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java
@@ -78,7 +78,7 @@
         final String expectedHeaderOutput = "<?xml version='1.0' encoding='UTF-8' standalone='no' ?>" +
             "<?xml-stylesheet type=\"text/xsl\" href=\"cts_result.xsl\"?>";
         final String expectedTestOutput =
-            "<TestResult testPlan=\"unknown\" profile=\"unknown\" starttime=\"ignore\" endtime=\"ignore\" version=\"2.0\"> ";
+            "<TestResult testPlan=\"unknown\" starttime=\"ignore\" endtime=\"ignore\" version=\"1.10\"> ";
         final String expectedSummaryOutput =
             "<Summary failed=\"0\" notExecuted=\"0\" timeout=\"0\" omitted=\"0\" pass=\"0\" total=\"0\" />";
         final String expectedEndTag = "</TestResult>";
@@ -110,8 +110,8 @@
         // TODO: consider doing xml based compare
         assertTrue(output.contains(
                 "<Summary failed=\"0\" notExecuted=\"0\" timeout=\"0\" omitted=\"0\" pass=\"1\" total=\"1\" />"));
-        assertTrue(output.contains("<TestPackage name=\"run\" runTime=\"3s\" digest=\"\" " +
-                "failed=\"0\" notExecuted=\"0\" timeout=\"0\" omitted=\"0\" pass=\"1\" total=\"1\">"));
+        assertTrue(output.contains("<TestPackage name=\"run\" digest=\"\" " +
+                "failed=\"0\" notExecuted=\"0\" timeout=\"0\" pass=\"1\" >"));
         assertTrue(output.contains(String.format("<TestCase name=\"%s\">", testId.getClassName())));
 
         final String testCaseTag = String.format(