summaryrefslogtreecommitdiff
path: root/services/coverage/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'services/coverage/java/com')
-rw-r--r--services/coverage/java/com/android/server/coverage/CoverageService.java145
1 files changed, 145 insertions, 0 deletions
diff --git a/services/coverage/java/com/android/server/coverage/CoverageService.java b/services/coverage/java/com/android/server/coverage/CoverageService.java
new file mode 100644
index 000000000000..d600aa8c4276
--- /dev/null
+++ b/services/coverage/java/com/android/server/coverage/CoverageService.java
@@ -0,0 +1,145 @@
+/*
+ * 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.server.coverage;
+
+import android.os.Binder;
+import android.os.ParcelFileDescriptor;
+import android.os.ShellCallback;
+import android.os.ShellCommand;
+import android.os.ResultReceiver;
+
+import org.jacoco.agent.rt.RT;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * A service that responds to `cmd coverage ...` and provides a mechanism for dumping code coverage
+ * information from the system server process.
+ * @hide
+ */
+public class CoverageService extends Binder {
+
+ public static final String COVERAGE_SERVICE = "coverage";
+ public static final boolean ENABLED;
+
+ static {
+ // This service should only be enabled if org.jacoco.agent.rt.RT was added to the build
+ boolean shouldEnable = true;
+ try {
+ Class.forName("org.jacoco.agent.rt.RT");
+ } catch (ClassNotFoundException e) {
+ shouldEnable = false;
+ }
+ ENABLED = shouldEnable;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+ String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
+ new CoverageCommand().exec(this, in, out, err, args, callback, resultReceiver);
+ }
+
+ /**
+ * A {@link ShellCommand} implementation for performing coverage shell commands.
+ */
+ private static class CoverageCommand extends ShellCommand {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int onCommand(String cmd) {
+ if ("dump".equals(cmd)) {
+ return onDump();
+ } else if ("reset".equals(cmd)) {
+ return onReset();
+ } else {
+ return handleDefaultCommands(cmd);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onHelp() {
+ PrintWriter pw = getOutPrintWriter();
+ pw.println("Coverage commands:");
+ pw.println(" help");
+ pw.println(" Print this help text.");
+ pw.println(" dump [FILE]");
+ pw.println(" Dump code coverage to FILE.");
+ pw.println(" reset");
+ pw.println(" Reset coverage information.");
+ }
+
+ /**
+ * Perform the "dump" command to write the collected execution data to a file.
+ *
+ * @return The command result.
+ */
+ private int onDump() {
+ // Figure out where to dump the coverage data
+ String dest = getNextArg();
+ if (dest == null) {
+ dest = "/data/local/tmp/coverage.ec";
+ } else {
+ File f = new File(dest);
+ if (f.isDirectory()) {
+ dest = new File(f, "coverage.ec").getAbsolutePath();
+ }
+ }
+
+ // Try to open the destination file
+ ParcelFileDescriptor fd = openOutputFileForSystem(dest);
+ if (fd == null) {
+ return -1;
+ }
+
+ // Write the execution data to the file
+ try (BufferedOutputStream output = new BufferedOutputStream(
+ new ParcelFileDescriptor.AutoCloseOutputStream(fd))) {
+ output.write(RT.getAgent().getExecutionData(false));
+ output.flush();
+ getOutPrintWriter().println(String.format("Dumped coverage data to %s", dest));
+ } catch (IOException e) {
+ getErrPrintWriter().println("Failed to dump coverage data: " + e.getMessage());
+ return -1;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Perform the "reset" command to clear the collected execution data.
+ *
+ * @return The command result.
+ */
+ private int onReset() {
+ RT.getAgent().reset();
+ getOutPrintWriter().println("Reset coverage data");
+ return 0;
+ }
+ }
+}