More CTS Coverage Build Improvements

Bug 3245588

The build server couldn't display the XML report with the XSL
transformation. Thus, when you clicked on the XML file, you
would just see the raw XML which wasn't very useful. So make
the report generator output a single HTML file by transforming
the XML into HTML in code.

Change-Id: Ie8b585551e4150f360a6622b3c6f7298ebd0a1e8
diff --git a/CtsTestCoverage.mk b/CtsTestCoverage.mk
index 85f13cc..3d30554 100644
--- a/CtsTestCoverage.mk
+++ b/CtsTestCoverage.mk
@@ -23,29 +23,18 @@
 DEXDEPS_EXE := $(HOST_OUT_EXECUTABLES)/dexdeps
 
 COVERAGE_OUT := $(HOST_OUT)/cts/api-coverage
-COVERAGE_RES := cts/tools/cts-api-coverage/res
+cts-test-coverage-report := $(COVERAGE_OUT)/test-coverage.html
+cts-verifier-coverage-report := $(COVERAGE_OUT)/verifier-coverage.html
 
-cts-test-coverage-report := $(COVERAGE_OUT)/test-coverage.xml
-cts-verifier-coverage-report := $(COVERAGE_OUT)/verifier-coverage.xml
-api-coverage-css := $(COVERAGE_OUT)/api-coverage.css
-api-coverage-xsl := $(COVERAGE_OUT)/api-coverage.xsl
-
-CTS_API_COVERAGE_DEPENDENCIES := $(CTS_API_COVERAGE_EXE) $(DEXDEPS_EXE) $(ACP) \
-		$(api-coverage-css) $(api-coverage-xsl)
+CTS_API_COVERAGE_DEPENDENCIES := $(CTS_API_COVERAGE_EXE) $(DEXDEPS_EXE) $(ACP)
 
 $(cts-test-coverage-report) : $(CTS_COVERAGE_TEST_CASE_LIST) $(CTS_API_COVERAGE_DEPENDENCIES)
 	$(call generate-coverage-report,"CTS Tests API Coverage Report",\
-			$(CTS_COVERAGE_TEST_CASE_LIST),xml,$(HOST_OUT)/cts/api-coverage,test-coverage.xml)
+			$(CTS_COVERAGE_TEST_CASE_LIST),html,$(HOST_OUT)/cts/api-coverage,test-coverage.html)
 
 $(cts-verifier-coverage-report) : CtsVerifier $(CTS_API_COVERAGE_DEPENDENCIES)
 	$(call generate-coverage-report,"CTS Verifier API Coverage Report",\
-			CtsVerifier,xml,$(HOST_OUT)/cts/api-coverage,verifier-coverage.xml)
-
-$(api-coverage-css) : $(COVERAGE_RES)/api-coverage.css $(ACP)
-	$(call copy-coverage-resource,api-coverage.css,$(api-coverage-css))
-
-$(api-coverage-xsl) : $(COVERAGE_RES)/api-coverage.xsl $(ACP)
-	$(call copy-coverage-resource,api-coverage.xsl,$(api-coverage-xsl))
+			CtsVerifier,html,$(HOST_OUT)/cts/api-coverage,verifier-coverage.html)
 
 .PHONY: cts-test-coverage
 cts-test-coverage : $(cts-test-coverage-report)
@@ -55,10 +44,8 @@
 
 # Put the test coverage report in the dist dir if "cts" is among the build goals.
 ifneq ($(filter cts, $(MAKECMDGOALS)),)
-  $(call dist-for-goals, cts, $(cts-test-coverage-report):cts-test-coverage-report.xml)
-  $(call dist-for-goals, cts, $(cts-verifier-coverage-report):cts-verifier-coverage-report.xml)
-  $(call dist-for-goals, cts, $(api-coverage-css):api-coverage.css)
-  $(call dist-for-goals, cts, $(api-coverage-xsl):api-coverage.xsl)
+  $(call dist-for-goals, cts, $(cts-test-coverage-report):cts-test-coverage-report.html)
+  $(call dist-for-goals, cts, $(cts-verifier-coverage-report):cts-verifier-coverage-report.html)
 endif
 
 # Arguments;
@@ -79,11 +66,3 @@
 define add-testcase-apk
 	TEST_APKS += $(call intermediates-dir-for,APPS,$(1))/package.apk
 endef
-
-# Arguments:
-#  1 - Name of the resources to copy like "api-coverage.css" with no path.
-#  2 - Destination file name of the copied resource
-define copy-coverage-resource
-	$(hide) mkdir -p `dirname $(2)`
-	$(hide) $(ACP) $(COVERAGE_RES)/$(1) $(2)
-endef
diff --git a/tools/cts-api-coverage/res/api-coverage.css b/tools/cts-api-coverage/res/api-coverage.css
deleted file mode 100644
index b956e16..0000000
--- a/tools/cts-api-coverage/res/api-coverage.css
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Copyright (C) 2010 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 {
-  background-color: #CCCCCC;
-  font-family: sans-serif;
-  margin: 10px;
-}
-
-.info {
-  margin-bottom: 10px;
-}
-
-.apks, .package, .class {
-  cursor: pointer;
-  text-decoration: underline;
-}
-
-.packageDetails {
-  padding-left: 20px;
-}
-
-.classDetails {
-  padding-left: 40px;
-}
-
-.method {
-  font-family: courier;
-  white-space: nowrap;
-}
-
-.red {
-  background-color: #FF0000;
-}
-
-.yellow {
-  background-color: #FFFF00;
-}
-
-.green {
-  background-color: #00FF00;
-}
diff --git a/tools/cts-api-coverage/src/Android.mk b/tools/cts-api-coverage/src/Android.mk
index 67ce8b6..d1fe4ed 100644
--- a/tools/cts-api-coverage/src/Android.mk
+++ b/tools/cts-api-coverage/src/Android.mk
@@ -20,6 +20,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_JAVA_RESOURCE_DIRS := res 
 LOCAL_JAR_MANIFEST := MANIFEST.mf
 
 LOCAL_MODULE := cts-api-coverage
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
index 4aaae69..d6a218e 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
@@ -29,6 +29,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.xml.transform.TransformerException;
+
 /**
  * Tool that generates a report of what Android framework methods are being called from a given
  * set of APKS. See the {@link #printUsage()} method for more details.
@@ -39,6 +41,8 @@
 
     private static final int FORMAT_XML = 1;
 
+    private static final int FORMAT_HTML = 2;
+
     private static void printUsage() {
         System.out.println("Usage: cts-api-coverage [OPTION]... [APK]...");
         System.out.println();
@@ -51,9 +55,9 @@
         System.out.println("directory and dexdeps must be built via \"make dexdeps\".");
         System.out.println();
         System.out.println("Options:");
-        System.out.println("  -o FILE         output file or standard out if not given");
-        System.out.println("  -f [txt|xml]    format of output either text or xml");
-        System.out.println("  -d PATH         path to dexdeps or expected to be in $PATH");
+        System.out.println("  -o FILE              output file or standard out if not given");
+        System.out.println("  -f [txt|xml|html]    format of output");
+        System.out.println("  -d PATH              path to dexdeps or expected to be in $PATH");
         System.out.println();
         System.exit(1);
     }
@@ -74,6 +78,8 @@
                         format = FORMAT_XML;
                     } else if ("txt".equalsIgnoreCase(formatSpec)) {
                         format = FORMAT_TXT;
+                    } else if ("html".equalsIgnoreCase(formatSpec)) {
+                        format = FORMAT_HTML;
                     } else {
                         printUsage();
                     }
@@ -160,7 +166,9 @@
     }
 
     private static void outputCoverageReport(ApiCoverage apiCoverage, List<File> testApks,
-            File outputFile, int format) throws IOException {
+            File outputFile, int format) throws IOException, TransformerException,
+                    InterruptedException {
+
         OutputStream out = outputFile != null
                 ? new FileOutputStream(outputFile)
                 : System.out;
@@ -174,6 +182,10 @@
                 case FORMAT_XML:
                     XmlReport.printXmlReport(testApks, apiCoverage, out);
                     break;
+
+                case FORMAT_HTML:
+                    HtmlReport.printHtmlReport(testApks, apiCoverage, out);
+                    break;
             }
         } finally {
             out.close();
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/HtmlReport.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/HtmlReport.java
new file mode 100644
index 0000000..de9b7a6
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/HtmlReport.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 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.apicoverage;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.util.List;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+/**
+ * Class that outputs an HTML report of the {@link ApiCoverage} collected. It is the XML report
+ * transformed into HTML.
+ */
+class HtmlReport {
+
+    public static void printHtmlReport(final List<File> testApks, final ApiCoverage apiCoverage,
+            final OutputStream out) throws IOException, TransformerException, InterruptedException {
+        final PipedOutputStream xmlOut = new PipedOutputStream();
+        final PipedInputStream xmlIn = new PipedInputStream(xmlOut);
+
+        Thread t = new Thread(new Runnable() {
+            public void run() {
+                XmlReport.printXmlReport(testApks, apiCoverage, xmlOut);
+
+                // Close the output stream to avoid "Write dead end" errors.
+                try {
+                    xmlOut.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        });
+        t.start();
+
+        InputStream xsl = CtsApiCoverage.class.getResourceAsStream("/api-coverage.xsl");
+        StreamSource xslSource = new StreamSource(xsl);
+        TransformerFactory factory = TransformerFactory.newInstance();
+        Transformer transformer = factory.newTransformer(xslSource);
+
+        StreamSource xmlSource = new StreamSource(xmlIn);
+        StreamResult result = new StreamResult(out);
+        transformer.transform(xmlSource, result);
+    }
+}
diff --git a/tools/cts-api-coverage/res/api-coverage.xsl b/tools/cts-api-coverage/src/res/api-coverage.xsl
similarity index 82%
rename from tools/cts-api-coverage/res/api-coverage.xsl
rename to tools/cts-api-coverage/src/res/api-coverage.xsl
index 5d45014..91fe802 100644
--- a/tools/cts-api-coverage/res/api-coverage.xsl
+++ b/tools/cts-api-coverage/src/res/api-coverage.xsl
@@ -32,7 +32,45 @@
                     }
                 </script>
                 <style type="text/css">
-                    @import "api-coverage.css";
+                    body {
+                        background-color: #CCCCCC;
+                        font-family: sans-serif;
+                        margin: 10px;
+                    }
+
+                    .info {
+                        margin-bottom: 10px;
+                    }
+
+                    .apks, .package, .class {
+                        cursor: pointer;
+                        text-decoration: underline;
+                    }
+
+                    .packageDetails {
+                        padding-left: 20px;
+                    }
+
+                    .classDetails {
+                        padding-left: 40px;
+                    }
+
+                    .method {
+                        font-family: courier;
+                        white-space: nowrap;
+                    }
+
+                    .red {
+                        background-color: #FF0000;
+                    }
+
+                    .yellow {
+                        background-color: #FFFF00;
+                    }
+
+                    .green {
+                        background-color: #00FF00;
+                    }
                 </style>
             </head>
             <body>