Merge "Provide a mechanism for dumping code coverage for the system server."
This commit is contained in:
@@ -24,6 +24,7 @@ services := \
|
||||
appwidget \
|
||||
autofill \
|
||||
backup \
|
||||
coverage\
|
||||
devicepolicy \
|
||||
midi \
|
||||
net \
|
||||
@@ -37,6 +38,10 @@ services := \
|
||||
# The convention is to name each service module 'services.$(module_name)'
|
||||
LOCAL_STATIC_JAVA_LIBRARIES := $(addprefix services.,$(services))
|
||||
|
||||
ifeq ($(EMMA_INSTRUMENT_FRAMEWORK),true)
|
||||
LOCAL_EMMA_INSTRUMENT := true
|
||||
endif
|
||||
|
||||
include $(BUILD_JAVA_LIBRARY)
|
||||
|
||||
# native library
|
||||
|
||||
12
services/coverage/Android.mk
Normal file
12
services/coverage/Android.mk
Normal file
@@ -0,0 +1,12 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := services.coverage
|
||||
|
||||
LOCAL_SRC_FILES += \
|
||||
$(call all-java-files-under,java)
|
||||
|
||||
LOCAL_JAVA_LIBRARIES := jacocoagent
|
||||
|
||||
include $(BUILD_STATIC_JAVA_LIBRARY)
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,7 @@ import com.android.server.camera.CameraService;
|
||||
import com.android.server.clipboard.ClipboardService;
|
||||
import com.android.server.connectivity.IpConnectivityMetrics;
|
||||
import com.android.server.connectivity.MetricsLoggerService;
|
||||
import com.android.server.coverage.CoverageService;
|
||||
import com.android.server.devicepolicy.DevicePolicyManagerService;
|
||||
import com.android.server.display.DisplayManagerService;
|
||||
import com.android.server.display.NightDisplayService;
|
||||
@@ -1260,6 +1261,12 @@ public final class SystemServer {
|
||||
traceEnd();
|
||||
}
|
||||
|
||||
if (!disableNonCoreServices && CoverageService.ENABLED) {
|
||||
traceBeginAndSlog("AddCoverageService");
|
||||
ServiceManager.addService(CoverageService.COVERAGE_SERVICE, new CoverageService());
|
||||
traceEnd();
|
||||
}
|
||||
|
||||
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_PRINTING)) {
|
||||
traceBeginAndSlog("StartPrintManager");
|
||||
mSystemServiceManager.startService(PRINT_MANAGER_SERVICE_CLASS);
|
||||
|
||||
Reference in New Issue
Block a user