CTS Coverage Build Improvements

- Add additional dist goals to copy over the CSS and XSL resources
  to make viewing the report easier.

- Fix CtsApiCoverage to take a path argument for dexdeps since
  the build does not have dexdeps in its path after building.

Change-Id: Ia2b346aa7b3d923a2cce75eb0d92995e4a398eb4
diff --git a/CtsTestCoverage.mk b/CtsTestCoverage.mk
index 459f219..85f13cc 100644
--- a/CtsTestCoverage.mk
+++ b/CtsTestCoverage.mk
@@ -20,28 +20,47 @@
 include cts/CtsTestCaseList.mk
 
 CTS_API_COVERAGE_EXE := $(HOST_OUT_EXECUTABLES)/cts-api-coverage
+DEXDEPS_EXE := $(HOST_OUT_EXECUTABLES)/dexdeps
 
-CTS_API_COVERAGE_DEPENDENCIES := $(CTS_API_COVERAGE_EXE) dexdeps $(ACP)
+COVERAGE_OUT := $(HOST_OUT)/cts/api-coverage
+COVERAGE_RES := cts/tools/cts-api-coverage/res
 
-cts-test-coverage-report := $(HOST_OUT)/cts/test-coverage/api-coverage.xml
+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-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/test-coverage,api-coverage.xml)
+			$(CTS_COVERAGE_TEST_CASE_LIST),xml,$(HOST_OUT)/cts/api-coverage,test-coverage.xml)
+
+$(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))
 
 .PHONY: cts-test-coverage
 cts-test-coverage : $(cts-test-coverage-report)
 
+.PHONY: cts-verifier-coverage
+cts-verifier-coverage : $(cts-verifier-coverage-report)
+
 # 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)
 endif
 
-.PHONY: cts-verifier-coverage
-cts-verifier-coverage: CtsVerifier $(CTS_API_COVERAGE_DEPENDENCIES)
-	$(call generate-coverage-report,"CTS Verifier API Coverage Report",\
-			CtsVerifier,xml,$(HOST_OUT)/cts/verifier-coverage,api-coverage.xml)
-
 # Arguments;
 #  1 - Name of the report printed out on the screen
 #  2 - Name of APK packages that will be scanned to generate the report
@@ -49,12 +68,10 @@
 #  4 - Output directory to put the report
 #  5 - Output file name of the report
 define generate-coverage-report
-	$(hide) rm -rf $(4)
 	$(hide) mkdir -p $(4)
-	$(hide) $(ACP) cts/tools/cts-api-coverage/res/* $(4)
 
 	$(foreach testcase,$(2),$(eval $(call add-testcase-apk,$(testcase))))
-	$(hide) $(CTS_API_COVERAGE_EXE) -f $(3) -o $(4)/$(5) $(TEST_APKS)
+	$(hide) $(CTS_API_COVERAGE_EXE) -d $(DEXDEPS_EXE) -f $(3) -o $(4)/$(5) $(TEST_APKS)
 
 	@echo $(1): file://$(ANDROID_BUILD_TOP)/$(4)/$(5)
 endef
@@ -62,3 +79,11 @@
 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/src/com/android/cts/apicoverage/CtsApiCoverage.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
index 02c4371..4aaae69 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
@@ -53,6 +53,7 @@
         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();
         System.exit(1);
     }
@@ -61,28 +62,23 @@
         List<File> testApks = new ArrayList<File>();
         File outputFile = null;
         int format = FORMAT_TXT;
+        String dexDeps = "dexDeps";
 
         for (int i = 0; i < args.length; i++) {
             if (args[i].startsWith("-")) {
                 if ("-o".equals(args[i])) {
-                    if (i + 1 < args.length) {
-                        outputFile = new File(args[++i]);;
-                    } else {
-                        printUsage();
-                    }
+                    outputFile = new File(getExpectedArg(args, ++i));
                 } else if ("-f".equals(args[i])) {
-                    if (i + 1 < args.length) {
-                        String formatArg = args[++i];
-                        if ("xml".equalsIgnoreCase(formatArg)) {
-                            format = FORMAT_XML;
-                        } else if ("txt".equalsIgnoreCase(formatArg)) {
-                            format = FORMAT_TXT;
-                        } else {
-                            printUsage();
-                        }
+                    String formatSpec = getExpectedArg(args, ++i);
+                    if ("xml".equalsIgnoreCase(formatSpec)) {
+                        format = FORMAT_XML;
+                    } else if ("txt".equalsIgnoreCase(formatSpec)) {
+                        format = FORMAT_TXT;
                     } else {
                         printUsage();
                     }
+                } else if ("-d".equals(args[i])) {
+                    dexDeps = getExpectedArg(args, ++i);
                 } else {
                     printUsage();
                 }
@@ -104,11 +100,21 @@
 
         ApiCoverage apiCoverage = getEmptyApiCoverage();
         for (File testApk : testApks) {
-            addApiCoverage(apiCoverage, testApk);
+            addApiCoverage(apiCoverage, testApk, dexDeps);
         }
         outputCoverageReport(apiCoverage, testApks, outputFile, format);
     }
 
+    /** Get the argument or print out the usage and exit. */
+    private static String getExpectedArg(String[] args, int index) {
+        if (index < args.length) {
+            return args[index];
+        } else {
+            printUsage();
+            return null;    // Never will happen because printUsage will call exit(1)
+        }
+    }
+
     /**
      * Creates an object representing the API that will be used later to collect coverage
      * statistics as we iterate over the test APKs.
@@ -143,15 +149,13 @@
      * @param apiCoverage object to which the coverage statistics will be added to
      * @param testApk containing the tests that will be scanned by dexdeps
      */
-    private static void addApiCoverage(ApiCoverage apiCoverage, File testApk)
+    private static void addApiCoverage(ApiCoverage apiCoverage, File testApk, String dexdeps)
             throws SAXException, IOException {
         XMLReader xmlReader = XMLReaderFactory.createXMLReader();
         DexDepsXmlHandler dexDepsXmlHandler = new DexDepsXmlHandler(apiCoverage);
         xmlReader.setContentHandler(dexDepsXmlHandler);
 
-        // TODO: Take an argument to specify the location of dexdeps.
-        Process process = new ProcessBuilder("out/host/linux-x86/bin/dexdeps",
-                "--format=xml", testApk.getPath()).start();
+        Process process = new ProcessBuilder(dexdeps, "--format=xml", testApk.getPath()).start();
         xmlReader.parse(new InputSource(process.getInputStream()));
     }