aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-06-23 02:30:49 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-06-23 02:30:49 +0000
commitf5d4437fd0945e9601628077cd6f5c3cf510d4f8 (patch)
tree362a5a2b6e57fc8955d3af74ce2cafbbca7f65b3
parent24e6c281dfeedde6fdb8a1cdd0f9f3b4b30f3697 (diff)
parente806b919fa39dea80bb0aa330d568c5464407e9e (diff)
downloadjacoco-android12-mainline-neuralnetworks-release.tar.gz
Change-Id: I9df3c2333ac69099837fe9d6ed412b2480b5a237
-rw-r--r--Android.bp43
-rw-r--r--METADATA1
-rw-r--r--org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java73
-rw-r--r--org.jacoco.cli/src/org/jacoco/cli/internal/commands/ExecInfo.java10
-rw-r--r--org.jacoco.core/src/org/jacoco/core/analysis/Analyzer.java8
-rw-r--r--org.jacoco.core/src/org/jacoco/core/data/ExecutionData.java52
-rw-r--r--org.jacoco.core/src/org/jacoco/core/data/ExecutionDataDelegate.java197
-rw-r--r--org.jacoco.core/src/org/jacoco/core/data/ExecutionDataStore.java48
-rw-r--r--org.jacoco.core/src/org/jacoco/core/data/ExecutionDataWriter.java8
-rw-r--r--org.jacoco.core/src/org/jacoco/core/data/IExecutionData.java129
-rw-r--r--org.jacoco.core/src/org/jacoco/core/data/IExecutionDataVisitor.java4
-rw-r--r--org.jacoco.core/src/org/jacoco/core/data/MappedExecutionData.java304
-rw-r--r--org.jacoco.core/src/org/jacoco/core/internal/instr/InstrSupport.java8
-rw-r--r--org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeInserter.java17
-rw-r--r--org.jacoco.core/src/org/jacoco/core/runtime/LoggerRuntime.java4
-rw-r--r--org.jacoco.core/src/org/jacoco/core/runtime/OfflineInstrumentationAccessGenerator.java6
-rw-r--r--org.jacoco.core/src/org/jacoco/core/runtime/RuntimeData.java20
-rw-r--r--org.jacoco.report/src/org/jacoco/report/IReportVisitor.java6
-rw-r--r--org.jacoco.report/src/org/jacoco/report/MultiReportVisitor.java6
-rw-r--r--org.jacoco.report/src/org/jacoco/report/check/RulesChecker.java6
-rw-r--r--org.jacoco.report/src/org/jacoco/report/csv/CSVFormatter.java6
-rw-r--r--org.jacoco.report/src/org/jacoco/report/html/HTMLFormatter.java10
-rw-r--r--org.jacoco.report/src/org/jacoco/report/internal/html/page/SessionsPage.java22
-rw-r--r--org.jacoco.report/src/org/jacoco/report/xml/XMLFormatter.java6
24 files changed, 907 insertions, 87 deletions
diff --git a/Android.bp b/Android.bp
index 0641bdec..726af1d3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -18,6 +18,44 @@
//
// Note: this is only intended to be used for the platform development. This is *not* intended
// to be used in the SDK where apps can use the official jacoco release.
+package {
+ default_applicable_licenses: ["external_jacoco_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+//
+// large-scale-change included anything that looked like it might be a license
+// text as a license_text. e.g. LICENSE, NOTICE, COPYING etc.
+//
+// Please consider removing redundant or irrelevant files from 'license_text:'.
+// See: http://go/android-license-faq
+license {
+ name: "external_jacoco_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-BSD",
+ "SPDX-license-identifier-EPL",
+ "SPDX-license-identifier-MIT",
+ ],
+ license_text: [
+ "LICENSE.md",
+ "NOTICE",
+ ],
+}
+
java_library {
name: "jacocoagent",
installable: true,
@@ -66,7 +104,10 @@ java_library {
// Generates stubs containing the classes that will be referenced by instrumented bytecode.
droidstubs {
name: "jacoco-stubs-gen",
- srcs: ["org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java"],
+ srcs: [
+ "org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java",
+ "org.jacoco.core/src/org/jacoco/core/data/IExecutionData.java",
+ ],
}
// A stubs target containing the parts of JaCoCo that we need to add to the hidden API whitelist.
diff --git a/METADATA b/METADATA
index 43947c97..16d6e52d 100644
--- a/METADATA
+++ b/METADATA
@@ -10,6 +10,7 @@ third_party {
value: "https://github.com/jacoco/jacoco.git"
}
version: "v0.8.4"
+ license_type: RECIPROCAL
last_upgrade_date {
year: 2019
month: 5
diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java
index 69a9909e..99a054e7 100644
--- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java
+++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Offline.java
@@ -11,12 +11,21 @@
*******************************************************************************/
package org.jacoco.agent.rt.internal;
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.jacoco.core.data.ExecutionData;
+import org.jacoco.core.data.ExecutionDataWriter;
+import org.jacoco.core.data.ExecutionDataDelegate;
+import org.jacoco.core.data.IExecutionData;
import org.jacoco.core.data.ExecutionDataStore;
+import org.jacoco.core.data.MappedExecutionData;
import org.jacoco.core.runtime.AgentOptions;
import org.jacoco.core.runtime.RuntimeData;
@@ -28,7 +37,8 @@ public final class Offline {
// BEGIN android-change
// private static final RuntimeData DATA;
- private static final Map<Long, ExecutionData> DATA = new HashMap<Long, ExecutionData>();
+ private static final Map<Long, ExecutionDataDelegate> DATA = new HashMap<Long, ExecutionDataDelegate>();
+ private static FileChannel CHANNEL;
// END android-change
private static final String CONFIG_RESOURCE = "/jacoco-agent.properties";
@@ -44,6 +54,7 @@ public final class Offline {
// no instances
}
+ // BEGIN android-change
/**
* API for offline instrumented classes.
*
@@ -53,27 +64,69 @@ public final class Offline {
* VM class name
* @param probecount
* probe count for this class
- * @return probe array instance for this class
+ * @return IExecutionData instance for this class
*/
- public static boolean[] getProbes(final long classid,
+ public static IExecutionData getExecutionData(final long classid,
final String classname, final int probecount) {
- // BEGIN android-change
// return DATA.getExecutionData(Long.valueOf(classid), classname,
// probecount).getProbes();
synchronized (DATA) {
- ExecutionData entry = DATA.get(classid);
+ ExecutionDataDelegate entry = DATA.get(classid);
if (entry == null) {
- entry = new ExecutionData(classid, classname, probecount);
+ entry = new ExecutionDataDelegate(
+ classid, classname, probecount, CHANNEL);
DATA.put(classid, entry);
} else {
entry.assertCompatibility(classid, classname, probecount);
}
- return entry.getProbes();
+ return entry;
}
- // END android-change
}
- // BEGIN android-change
+ /**
+ * Enables memory-mapped execution data and converts existing
+ * {@link ExecutionDataDelegate}s.
+ */
+ public static void enableMemoryMappedData() {
+ try {
+ prepareFile(getPid());
+ for (ExecutionDataDelegate data : DATA.values()) {
+ data.convert(CHANNEL);
+ }
+ } catch (IOException e) {
+ // TODO(olivernguyen): Add logging to debug issues more easily.
+ }
+ }
+
+ /**
+ * Creates the output file that will be mapped for probe data.
+ */
+ private static void prepareFile(int pid) throws IOException {
+ // Write header information to the file.
+ ByteBuffer headerBuffer = ByteBuffer.allocate(5);
+ headerBuffer.put(ExecutionDataWriter.BLOCK_HEADER);
+ headerBuffer.putChar(ExecutionDataWriter.MAGIC_NUMBER);
+ headerBuffer.putChar(ExecutionDataWriter.FORMAT_VERSION);
+ headerBuffer.flip();
+
+ // If this file already exists (due to pid re-usage), the previous coverage data
+ // will be lost when the file is overwritten.
+ File outputFile = new File("/data/misc/trace/jacoco-" + pid + ".mm.ec");
+ CHANNEL = new RandomAccessFile(outputFile, "rw").getChannel();
+ synchronized (CHANNEL) {
+ CHANNEL.write(headerBuffer);
+ }
+ }
+
+ /**
+ * Helper function to determine the pid of this process.
+ */
+ private static int getPid() throws IOException {
+ // Read /proc/self and resolve it to obtain its pid.
+ return Integer.parseInt(new File("/proc/self").getCanonicalFile().getName());
+ }
+ // END android-change
+
/**
* Creates a default agent, using config loaded from the classpath resource and the system
* properties, and a runtime data instance populated with the execution data accumulated by
@@ -87,7 +140,7 @@ public final class Offline {
System.getProperties());
synchronized (DATA) {
ExecutionDataStore store = new ExecutionDataStore();
- for (ExecutionData data : DATA.values()) {
+ for (IExecutionData data : DATA.values()) {
store.put(data);
}
return Agent.getInstance(new AgentOptions(config), new RuntimeData(store));
diff --git a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/ExecInfo.java b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/ExecInfo.java
index cacf4cbe..4519d28f 100644
--- a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/ExecInfo.java
+++ b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/ExecInfo.java
@@ -20,7 +20,7 @@ import java.util.Date;
import java.util.List;
import org.jacoco.cli.internal.Command;
-import org.jacoco.core.data.ExecutionData;
+import org.jacoco.core.data.IExecutionData;
import org.jacoco.core.data.ExecutionDataReader;
import org.jacoco.core.data.IExecutionDataVisitor;
import org.jacoco.core.data.ISessionInfoVisitor;
@@ -68,13 +68,15 @@ public class ExecInfo extends Command {
}
});
reader.setExecutionDataVisitor(new IExecutionDataVisitor() {
- public void visitClassExecution(final ExecutionData data) {
+ // BEGIN android-change
+ public void visitClassExecution(final IExecutionData data) {
out.printf("%016x %3d of %3d %s%n",
Long.valueOf(data.getId()),
- Integer.valueOf(getHitCount(data.getProbes())),
- Integer.valueOf(data.getProbes().length),
+ Integer.valueOf(getHitCount(data.getProbesCopy())),
+ Integer.valueOf(data.getProbeCount()),
data.getName());
}
+ // END android-change
});
reader.read();
in.close();
diff --git a/org.jacoco.core/src/org/jacoco/core/analysis/Analyzer.java b/org.jacoco.core/src/org/jacoco/core/analysis/Analyzer.java
index 76b7be3c..7759b89d 100644
--- a/org.jacoco.core/src/org/jacoco/core/analysis/Analyzer.java
+++ b/org.jacoco.core/src/org/jacoco/core/analysis/Analyzer.java
@@ -20,7 +20,7 @@ import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
-import org.jacoco.core.data.ExecutionData;
+import org.jacoco.core.data.IExecutionData;
import org.jacoco.core.data.ExecutionDataStore;
import org.jacoco.core.internal.ContentTypeDetector;
import org.jacoco.core.internal.InputStreams;
@@ -78,16 +78,18 @@ public class Analyzer {
*/
private ClassVisitor createAnalyzingVisitor(final long classid,
final String className) {
- final ExecutionData data = executionData.get(classid);
+ // BEGIN android-change
+ final IExecutionData data = executionData.get(classid);
final boolean[] probes;
final boolean noMatch;
if (data == null) {
probes = null;
noMatch = executionData.contains(className);
} else {
- probes = data.getProbes();
+ probes = data.getProbesCopy();
noMatch = false;
}
+ // END android-change
final ClassCoverageImpl coverage = new ClassCoverageImpl(className,
classid, noMatch);
final ClassAnalyzer analyzer = new ClassAnalyzer(coverage, probes,
diff --git a/org.jacoco.core/src/org/jacoco/core/data/ExecutionData.java b/org.jacoco.core/src/org/jacoco/core/data/ExecutionData.java
index d98775eb..a728e033 100644
--- a/org.jacoco.core/src/org/jacoco/core/data/ExecutionData.java
+++ b/org.jacoco.core/src/org/jacoco/core/data/ExecutionData.java
@@ -20,7 +20,9 @@ import java.util.Arrays;
* has to be taken about the probe data array of type <code>boolean[]</code>
* which can be modified.
*/
-public final class ExecutionData {
+// BEGIN android-change
+public final class ExecutionData implements IExecutionData {
+// END android-change
private final long id;
@@ -81,15 +83,43 @@ public final class ExecutionData {
return name;
}
+ // BEGIN android-change
/**
- * Returns the execution data probes. A value of <code>true</code> indicates
- * that the corresponding probe was executed.
+ * Returns a copy of the current probe values.
+ *
+ * @return copy of the probe array
+ */
+ public boolean[] getProbesCopy() {
+ return Arrays.copyOf(probes, probes.length);
+ }
+
+ /**
+ * The number of probes in this ExecutionData.
+ *
+ * @return the number of probes
+ */
+ public int getProbeCount() {
+ return probes.length;
+ }
+
+ /**
+ * Returns the execution data probe for a given index. A value of
+ * <code>true</code> indicates that the corresponding probe was
+ * executed.
*
* @return probe data
*/
- public boolean[] getProbes() {
- return probes;
+ public boolean getProbe(final int index) {
+ return probes[index];
+ }
+
+ /**
+ * Sets the execution data probe for a given index to <code>true</code>.
+ */
+ public void setProbe(final int index) {
+ probes[index] = true;
}
+ // END android-change
/**
* Sets all probes to <code>false</code>.
@@ -127,7 +157,9 @@ public final class ExecutionData {
* @param other
* execution data to merge
*/
- public void merge(final ExecutionData other) {
+ // BEGIN android-change
+ public void merge(final IExecutionData other) {
+ // END android-change
merge(other, true);
}
@@ -154,10 +186,12 @@ public final class ExecutionData {
* @param flag
* merge mode
*/
- public void merge(final ExecutionData other, final boolean flag) {
+ public void merge(final IExecutionData other, final boolean flag) {
+ // BEGIN android-change
assertCompatibility(other.getId(), other.getName(),
- other.getProbes().length);
- final boolean[] otherData = other.getProbes();
+ other.getProbeCount());
+ final boolean[] otherData = other.getProbesCopy();
+ // END android-change
for (int i = 0; i < probes.length; i++) {
if (otherData[i]) {
probes[i] = flag;
diff --git a/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataDelegate.java b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataDelegate.java
new file mode 100644
index 00000000..7cbe989f
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataDelegate.java
@@ -0,0 +1,197 @@
+// BEGIN android-change
+package org.jacoco.core.data;
+
+import java.io.IOException;
+import java.nio.channels.FileChannel;
+
+/**
+ * Class that delegates calls to {@link IExecutionData} interface methods to another instance.
+ * Also has the ability to convert the underlying implementation to a {@link MappedExecutionData}
+ * instance.
+ */
+public class ExecutionDataDelegate implements IExecutionData {
+ private IExecutionData delegate;
+
+ public ExecutionDataDelegate(
+ final long id, final String name, final int probeCount, final FileChannel channel) {
+ if ((channel != null) && canMapData(name)) {
+ try {
+ delegate = new MappedExecutionData(id, name, probeCount, channel);
+ } catch (IOException e) {
+ delegate = new ExecutionData(id, name, probeCount);
+ }
+ } else {
+ delegate = new ExecutionData(id, name, probeCount);
+ }
+ }
+
+ /**
+ * Converts the existing delegate into a {@link MappedExecutionData} instance if it is not
+ * already one, and copies any probe data into the new instance.
+ */
+ public synchronized void convert(final FileChannel channel) throws IOException {
+ if (!(delegate instanceof MappedExecutionData) && canMapData(getName())) {
+ IExecutionData newDelegate = new MappedExecutionData(
+ getId(), getName(), getProbeCount(), channel);
+ newDelegate.merge(delegate);
+ delegate = newDelegate;
+ }
+ }
+
+ /**
+ * Determines if a class can be converted to memory-mapped.
+ */
+ private static boolean canMapData(final String name) {
+ if (name.startsWith("android/app/")
+ || name.startsWith("android/os/")
+ || name.startsWith("com/android/internal/util/")
+ || name.startsWith("java/")) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Return the unique identifier for this class. The identifier is the CRC64
+ * checksum of the raw class file definition.
+ *
+ * @return class identifier
+ */
+ public long getId() {
+ return delegate.getId();
+ }
+
+ /**
+ * The VM name of the class.
+ *
+ * @return VM name
+ */
+ public String getName() {
+ return delegate.getName();
+ }
+
+ /**
+ * The number of instrumentation probes for this class.
+ *
+ * @return number of probes
+ */
+ public int getProbeCount() {
+ return delegate.getProbeCount();
+ }
+
+ /**
+ * Returns a copy of the probe data as a boolean array.
+ *
+ * Changes to the returned array will not be reflected in the execution data.
+ *
+ * @return copy of the probe data
+ */
+ public boolean[] getProbesCopy() {
+ return delegate.getProbesCopy();
+ }
+
+ /**
+ * Sets all probes to <code>false</code>.
+ */
+ public void reset() {
+ delegate.reset();
+ }
+
+ /**
+ * Checks whether any probe has been hit.
+ *
+ * @return <code>true</code>, if at least one probe has been hit
+ */
+ public boolean hasHits() {
+ return delegate.hasHits();
+ }
+
+ /**
+ * Merges the given execution data into the probe data of this object. I.e.
+ * a probe entry in this object is marked as executed (<code>true</code>) if
+ * this probe or the corresponding other probe was executed. So the result
+ * is
+ *
+ * <pre>
+ * A or B
+ * </pre>
+ *
+ * The probe array of the other object is not modified.
+ *
+ * @param other
+ * execution data to merge
+ */
+ public void merge(final IExecutionData other) {
+ delegate.merge(other);
+ }
+
+ /**
+ * Merges the given execution data into the probe data of this object. A
+ * probe in this object is set to the value of <code>flag</code> if the
+ * corresponding other probe was executed. For <code>flag==true</code> this
+ * corresponds to
+ *
+ * <pre>
+ * A or B
+ * </pre>
+ *
+ * For <code>flag==false</code> this can be considered as a subtraction
+ *
+ * <pre>
+ * A and not B
+ * </pre>
+ *
+ * The probe array of the other object is not modified.
+ *
+ * @param other
+ * execution data to merge
+ * @param flag
+ * merge mode
+ */
+ public void merge(final IExecutionData other, boolean flag) {
+ delegate.merge(other, flag);
+ }
+
+ /**
+ * Asserts that this execution data object is compatible with the given
+ * parameters. The purpose of this check is to detect a very unlikely class
+ * id collision.
+ *
+ * @param id
+ * other class id, must be the same
+ * @param name
+ * other name, must be equal to this name
+ * @param probecount
+ * probe data length, must be the same as for this data
+ * @throws IllegalStateException
+ * if the given parameters do not match this instance
+ */
+ public void assertCompatibility(final long id, final String name, final int probeCount)
+ throws IllegalStateException {
+ delegate.assertCompatibility(id, name, probeCount);
+ }
+
+ /**
+ * Returns the execution data probe for a given index. A value of
+ * <code>true</code> indicates that the corresponding probe was
+ * executed.
+ *
+ * @param index the probe's index to look up
+ *
+ * @return probe data
+ */
+ public boolean getProbe(final int index) {
+ return delegate.getProbe(index);
+ }
+
+ /**
+ * Sets the execution data probe at the given index to <code>true</code>.
+ *
+ * @param index the probe's index to set
+ * @param value the value to set the probe to
+ */
+ public void setProbe(final int index) {
+ delegate.setProbe(index);
+ }
+ }
+ // END android-change
diff --git a/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataStore.java b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataStore.java
index 3e567a3b..ce0bec47 100644
--- a/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataStore.java
+++ b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataStore.java
@@ -28,7 +28,9 @@ import java.util.Set;
*/
public final class ExecutionDataStore implements IExecutionDataVisitor {
- private final Map<Long, ExecutionData> entries = new HashMap<Long, ExecutionData>();
+ // BEGIN android-change
+ private final Map<Long, IExecutionData> entries = new HashMap<Long, IExecutionData>();
+ // END android-change
private final Set<String> names = new HashSet<String>();
@@ -44,9 +46,11 @@ public final class ExecutionDataStore implements IExecutionDataVisitor {
* to a corresponding one, that is already contained
* @see ExecutionData#assertCompatibility(long, String, int)
*/
- public void put(final ExecutionData data) throws IllegalStateException {
+ // BEGIN android-change
+ public void put(final IExecutionData data) throws IllegalStateException {
final Long id = Long.valueOf(data.getId());
- final ExecutionData entry = entries.get(id);
+ final IExecutionData entry = entries.get(id);
+ // END android-change
if (entry == null) {
entries.put(id, data);
names.add(data.getName());
@@ -68,9 +72,11 @@ public final class ExecutionDataStore implements IExecutionDataVisitor {
* to a corresponding one, that is already contained
* @see ExecutionData#assertCompatibility(long, String, int)
*/
- public void subtract(final ExecutionData data) throws IllegalStateException {
+ // BEGIN android-change
+ public void subtract(final IExecutionData data) throws IllegalStateException {
final Long id = Long.valueOf(data.getId());
- final ExecutionData entry = entries.get(id);
+ final IExecutionData entry = entries.get(id);
+ // END android-change
if (entry != null) {
entry.merge(data, false);
}
@@ -84,7 +90,9 @@ public final class ExecutionDataStore implements IExecutionDataVisitor {
* @see #subtract(ExecutionData)
*/
public void subtract(final ExecutionDataStore store) {
- for (final ExecutionData data : store.getContents()) {
+ // BEGIN android-change
+ for (final IExecutionData data : store.getContents()) {
+ // END android-change
subtract(data);
}
}
@@ -97,7 +105,9 @@ public final class ExecutionDataStore implements IExecutionDataVisitor {
* class id
* @return execution data or <code>null</code>
*/
- public ExecutionData get(final long id) {
+ // BEGIN android-change
+ public IExecutionData get(final long id) {
+ // END android-change
return entries.get(Long.valueOf(id));
}
@@ -126,9 +136,11 @@ public final class ExecutionDataStore implements IExecutionDataVisitor {
* probe data length
* @return execution data
*/
- public ExecutionData get(final Long id, final String name,
+ // BEGIN android-change
+ public IExecutionData get(final Long id, final String name,
final int probecount) {
- ExecutionData entry = entries.get(id);
+ IExecutionData entry = entries.get(id);
+ // END android-change
if (entry == null) {
entry = new ExecutionData(id.longValue(), name, probecount);
entries.put(id, entry);
@@ -144,7 +156,9 @@ public final class ExecutionDataStore implements IExecutionDataVisitor {
* execution data objects itself are not removed.
*/
public void reset() {
- for (final ExecutionData executionData : this.entries.values()) {
+ // BEGIN android-change
+ for (final IExecutionData executionData : this.entries.values()) {
+ // END android-change
executionData.reset();
}
}
@@ -154,9 +168,11 @@ public final class ExecutionDataStore implements IExecutionDataVisitor {
*
* @return current contents
*/
- public Collection<ExecutionData> getContents() {
- return new ArrayList<ExecutionData>(entries.values());
+ // BEGIN android-change
+ public Collection<IExecutionData> getContents() {
+ return new ArrayList<IExecutionData>(entries.values());
}
+ // END android-change
/**
* Writes the content of the store to the given visitor interface.
@@ -165,14 +181,18 @@ public final class ExecutionDataStore implements IExecutionDataVisitor {
* interface to write content to
*/
public void accept(final IExecutionDataVisitor visitor) {
- for (final ExecutionData data : getContents()) {
+ // BEGIN android-change
+ for (final IExecutionData data : getContents()) {
+ // END android-change
visitor.visitClassExecution(data);
}
}
// === IExecutionDataVisitor ===
- public void visitClassExecution(final ExecutionData data) {
+ // BEGIN android-change
+ public void visitClassExecution(final IExecutionData data) {
+ // END android-change
put(data);
}
}
diff --git a/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataWriter.java b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataWriter.java
index e697dda3..bdf3445d 100644
--- a/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataWriter.java
+++ b/org.jacoco.core/src/org/jacoco/core/data/ExecutionDataWriter.java
@@ -94,13 +94,17 @@ public class ExecutionDataWriter implements ISessionInfoVisitor,
}
}
- public void visitClassExecution(final ExecutionData data) {
+ // BEGIN android-change
+ public void visitClassExecution(final IExecutionData data) {
+ // END android-change
if (data.hasHits()) {
try {
out.writeByte(BLOCK_EXECUTIONDATA);
out.writeLong(data.getId());
out.writeUTF(data.getName());
- out.writeBooleanArray(data.getProbes());
+ // BEGIN android-change
+ out.writeBooleanArray(data.getProbesCopy());
+ // END android-change
} catch (final IOException e) {
throw new RuntimeException(e);
}
diff --git a/org.jacoco.core/src/org/jacoco/core/data/IExecutionData.java b/org.jacoco.core/src/org/jacoco/core/data/IExecutionData.java
new file mode 100644
index 00000000..289c3726
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/IExecutionData.java
@@ -0,0 +1,129 @@
+// BEGIN android-change
+package org.jacoco.core.data;
+
+/**
+ * Interface for interacting with execution data for a single Java class.
+ */
+public interface IExecutionData {
+
+ /**
+ * Return the unique identifier for this class. The identifier is the CRC64
+ * checksum of the raw class file definition.
+ *
+ * @return class identifier
+ */
+ public abstract long getId();
+
+ /**
+ * The VM name of the class.
+ *
+ * @return VM name
+ */
+ public abstract String getName();
+
+ /**
+ * The number of instrumentation probes for this class.
+ *
+ * @return number of probes
+ */
+ public abstract int getProbeCount();
+
+ /**
+ * Returns a copy of the probe data as a boolean array.
+ *
+ * Changes to the returned array will not be reflected in the execution data.
+ *
+ * @return copy of the probe data
+ */
+ public abstract boolean[] getProbesCopy();
+
+ /**
+ * Sets all probes to <code>false</code>.
+ */
+ public abstract void reset();
+
+ /**
+ * Checks whether any probe has been hit.
+ *
+ * @return <code>true</code>, if at least one probe has been hit
+ */
+ public abstract boolean hasHits();
+
+ /**
+ * Merges the given execution data into the probe data of this object. I.e.
+ * a probe entry in this object is marked as executed (<code>true</code>) if
+ * this probe or the corresponding other probe was executed. So the result
+ * is
+ *
+ * <pre>
+ * A or B
+ * </pre>
+ *
+ * The probe array of the other object is not modified.
+ *
+ * @param other
+ * execution data to merge
+ */
+ public abstract void merge(final IExecutionData other);
+
+ /**
+ * Merges the given execution data into the probe data of this object. A
+ * probe in this object is set to the value of <code>flag</code> if the
+ * corresponding other probe was executed. For <code>flag==true</code> this
+ * corresponds to
+ *
+ * <pre>
+ * A or B
+ * </pre>
+ *
+ * For <code>flag==false</code> this can be considered as a subtraction
+ *
+ * <pre>
+ * A and not B
+ * </pre>
+ *
+ * The probe array of the other object is not modified.
+ *
+ * @param other
+ * execution data to merge
+ * @param flag
+ * merge mode
+ */
+ public abstract void merge(final IExecutionData other, boolean flag);
+
+ /**
+ * Asserts that this execution data object is compatible with the given
+ * parameters. The purpose of this check is to detect a very unlikely class
+ * id collision.
+ *
+ * @param id
+ * other class id, must be the same
+ * @param name
+ * other name, must be equal to this name
+ * @param probecount
+ * probe data length, must be the same as for this data
+ * @throws IllegalStateException
+ * if the given parameters do not match this instance
+ */
+ public abstract void assertCompatibility(final long id, final String name, final int probeCount) throws IllegalStateException;
+
+ /**
+ * Returns the execution data probe for a given index. A value of
+ * <code>true</code> indicates that the corresponding probe was
+ * executed.
+ *
+ * @param index the probe's index to look up
+ *
+ * @return probe data
+ */
+ public abstract boolean getProbe(final int index);
+
+ /**
+ * Sets the execution data probe at the given index to <code>true</code>.
+ *
+ * @param index the probe's index to set
+ * @param value the value to set the probe to
+ */
+ public abstract void setProbe(final int index);
+}
+// END android-change
diff --git a/org.jacoco.core/src/org/jacoco/core/data/IExecutionDataVisitor.java b/org.jacoco.core/src/org/jacoco/core/data/IExecutionDataVisitor.java
index 6cea7c57..14eabbe7 100644
--- a/org.jacoco.core/src/org/jacoco/core/data/IExecutionDataVisitor.java
+++ b/org.jacoco.core/src/org/jacoco/core/data/IExecutionDataVisitor.java
@@ -24,6 +24,8 @@ public interface IExecutionDataVisitor {
* @param data
* execution data for a class
*/
- void visitClassExecution(ExecutionData data);
+ // BEGIN android-change
+ void visitClassExecution(IExecutionData data);
+ // END android-change
}
diff --git a/org.jacoco.core/src/org/jacoco/core/data/MappedExecutionData.java b/org.jacoco.core/src/org/jacoco/core/data/MappedExecutionData.java
new file mode 100644
index 00000000..7e74d17e
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/data/MappedExecutionData.java
@@ -0,0 +1,304 @@
+// BEGIN android-change
+package org.jacoco.core.data;
+
+import static java.lang.String.format;
+
+import java.io.IOException;
+import java.nio.channels.FileChannel;
+import java.nio.charset.Charset;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+
+import org.jacoco.core.data.ExecutionDataWriter;
+
+/**
+ * Memory-mapped execution data implementation.
+ *
+ * Stores the probe data in a section of a memory-mapped file, so that it will be available without
+ * requiring a flush of the coverage data.
+ */
+public final class MappedExecutionData implements IExecutionData {
+ private final long id;
+ private final String name;
+ private final int probeCount;
+
+ // Stores the memory-mapped byte buffer containing the probe data, packed as bits.
+ private MappedByteBuffer probeBuffer;
+
+ /**
+ * Creates the mapped execution data.
+ */
+ public MappedExecutionData(
+ final long id, final String name, final int probeCount, final FileChannel channel)
+ throws IOException {
+ this.id = id;
+ this.name = name;
+ this.probeCount = probeCount;
+
+ createMemoryMappedProbeArray(id, name, probeCount, channel);
+ }
+
+ public MappedExecutionData(
+ final long id,
+ final String name,
+ final boolean[] probes,
+ final FileChannel channel) throws IOException {
+ this.id = id;
+ this.name = name;
+ this.probeCount = probes.length;
+
+ createMemoryMappedProbeArray(id, name, probes.length, channel);
+ for (int i = 0; i < probes.length; i++) {
+ if (probes[i]) {
+ setProbe(i);
+ }
+ }
+ }
+
+ /**
+ * Maps a section of the already-opened file for the probe data.
+ *
+ * @param id the class id
+ * @param name the VM class name
+ * @param probeCount the number of probes for this class
+ */
+ private void createMemoryMappedProbeArray(
+ final long id, final String name, final int probeCount, final FileChannel channel)
+ throws IOException {
+ synchronized (channel) {
+ int byteCount = (probeCount + 7) / 8;
+
+ // Write the ExecutionData block info.
+ ByteBuffer execDataBuffer = ByteBuffer.allocate(11);
+ execDataBuffer.put(ExecutionDataWriter.BLOCK_EXECUTIONDATA);
+ execDataBuffer.putLong(id);
+ execDataBuffer.putShort((short) name.length());
+ execDataBuffer.flip();
+ channel.write(execDataBuffer);
+ channel.write(ByteBuffer.wrap(name.getBytes(Charset.forName("UTF-8"))));
+
+ // Write the probe info and map part of this file for the probe data.
+ channel.write(toVarIntByteBuffer(probeCount));
+ probeBuffer = channel.map(FileChannel.MapMode.READ_WRITE, channel.position(), byteCount);
+ channel.position(channel.position() + byteCount);
+ }
+ }
+
+ /**
+ * Writes a variable-length int to a {@link ByteBuffer}.
+ *
+ * @param value the value to write
+ * @return a ByteBuffer that can be used to write to a FileChannel containing the value
+ */
+ private ByteBuffer toVarIntByteBuffer(int value) {
+ ByteBuffer buffer = ByteBuffer.allocate(5);
+ if (value == 0) {
+ buffer.put((byte) 0);
+ } else {
+ while (value > 0) {
+ if ((value & 0xFFFFFF80) == 0) {
+ buffer.put((byte) value);
+ } else {
+ buffer.put((byte) (0x80 | (value & 0x7F)));
+ }
+ value >>>= 7;
+ }
+ }
+ buffer.flip();
+ return buffer;
+ }
+
+ /**
+ * Return the unique identifier for this class. The identifier is the CRC64
+ * checksum of the raw class file definition.
+ *
+ * @return class identifier
+ */
+ public long getId() {
+ return id;
+ }
+
+ /**
+ * The VM name of the class.
+ *
+ * @return VM name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * The number of instrumentation probes for this class.
+ *
+ * @return number of probes
+ */
+ public int getProbeCount() {
+ return probeCount;
+ }
+
+ /**
+ * Returns a copy of the probe data as a boolean array.
+ *
+ * Changes to the returned array will not be reflected in the execution data.
+ *
+ * @return copy of the probe data
+ */
+ public boolean[] getProbesCopy() {
+ final int bytes = (probeCount + 7) / 8;
+ boolean[] probes = new boolean[probeCount];
+ for (int index = 0; index < probeCount; index += 8) {
+ byte byteProbe = probeBuffer.get(index / 8);
+ for (int bit = 0; (bit < 8) && ((index + bit) < probeCount); bit++) {
+ probes[index + bit] = ((byteProbe & 0x1) > 0);
+ byteProbe >>>= 1;
+ }
+ }
+ return probes;
+ }
+
+ /**
+ * Sets all probes to <code>false</code>.
+ */
+ public void reset() {
+ final int bytes = (probeCount + 7) / 8;
+ synchronized (probeBuffer) {
+ for (int i = 0; i < bytes; i++) {
+ probeBuffer.put(i, (byte) 0);
+ }
+ }
+ }
+
+ /**
+ * Checks whether any probe has been hit.
+ *
+ * @return <code>true</code>, if at least one probe has been hit
+ */
+ public boolean hasHits() {
+ final int bytes = (probeCount + 7) / 8;
+ synchronized (probeBuffer) {
+ for (int i = 0; i < bytes; i++) {
+ if (probeBuffer.get(i) > 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Merges the given execution data into the probe data of this object. I.e.
+ * a probe entry in this object is marked as executed (<code>true</code>) if
+ * this probe or the corresponding other probe was executed. So the result
+ * is
+ *
+ * <pre>
+ * A or B
+ * </pre>
+ *
+ * The probe array of the other object is not modified.
+ *
+ * @param other
+ * execution data to merge
+ */
+ public void merge(final IExecutionData other) {
+ merge(other, true);
+ }
+
+ /**
+ * Merges the given execution data into the probe data of this object. A
+ * probe in this object is set to the value of <code>flag</code> if the
+ * corresponding other probe was executed. For <code>flag==true</code> this
+ * corresponds to
+ *
+ * <pre>
+ * A or B
+ * </pre>
+ *
+ * For <code>flag==false</code> this can be considered as a subtraction
+ *
+ * <pre>
+ * A and not B
+ * </pre>
+ *
+ * The probe array of the other object is not modified.
+ *
+ * @param other
+ * execution data to merge
+ * @param flag
+ * merge mode
+ */
+ public void merge(final IExecutionData other, final boolean flag) {
+ synchronized (probeBuffer) {
+ for (int i = 0; i < probeCount; i++) {
+ if (other.getProbe(i)) {
+ setProbe(i);
+ }
+ }
+ }
+ }
+
+ /**
+ * Asserts that this execution data object is compatible with the given
+ * parameters. The purpose of this check is to detect a very unlikely class
+ * id collision.
+ *
+ * @param id
+ * other class id, must be the same
+ * @param name
+ * other name, must be equal to this name
+ * @param probecount
+ * probe data length, must be the same as for this data
+ * @throws IllegalStateException
+ * if the given parameters do not match this instance
+ */
+ public void assertCompatibility(final long id, final String name, final int probeCount)
+ throws IllegalStateException {
+ if (this.id != id) {
+ throw new IllegalStateException(format(
+ "Different ids (%016x and %016x).", Long.valueOf(this.id),
+ Long.valueOf(id)));
+ }
+ if (!this.name.equals(name)) {
+ throw new IllegalStateException(format(
+ "Different class names %s and %s for id %016x.", this.name,
+ name, Long.valueOf(id)));
+ }
+ if (this.probeCount != probeCount) {
+ throw new IllegalStateException(format(
+ "Incompatible execution data for class %s with id %016x.",
+ name, Long.valueOf(id)));
+ }
+ }
+
+ /**
+ * Returns the execution data probe for a given index. A value of
+ * <code>true</code> indicates that the corresponding probe was
+ * executed.
+ *
+ * @param index the probe's index to look up
+ *
+ * @return probe data
+ */
+ public boolean getProbe(final int index) {
+ int offset = index / 8;
+ int bit = 1 << (index % 8);
+ return (probeBuffer.get(offset) & bit) != 0;
+ }
+
+ /**
+ * Sets the execution data probe at the given index to <code>true</code>.
+ *
+ * @param index the probe's index to set
+ */
+ public void setProbe(final int index) {
+ int offset = index / 8;
+ int bit = 1 << (index % 8);
+ byte currentValue = probeBuffer.get(offset);
+ if ((currentValue & bit) == 0) {
+ synchronized (probeBuffer) {
+ probeBuffer.put(offset, (byte) (probeBuffer.get(offset) | bit));
+ }
+ }
+ }
+}
+// END android-change
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/InstrSupport.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/InstrSupport.java
index 85e83a3a..4d4e1ba1 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/InstrSupport.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/InstrSupport.java
@@ -77,7 +77,9 @@ public final class InstrSupport {
* Data type of the field that stores coverage information for a class (
* <code>boolean[]</code>).
*/
- public static final String DATAFIELD_DESC = "[Z";
+ // BEGIN android-change
+ public static final String DATAFIELD_DESC = "Lorg/jacoco/core/data/IExecutionData;";
+ // END android-change
// === Init Method ===
@@ -89,7 +91,9 @@ public final class InstrSupport {
/**
* Descriptor of the initialization method.
*/
- public static final String INITMETHOD_DESC = "()[Z";
+ // BEGIN android-change
+ public static final String INITMETHOD_DESC = "()Lorg/jacoco/core/data/IExecutionData;";
+ // END android-change
/**
* Access modifiers of the initialization method.
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeInserter.java b/org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeInserter.java
index 63fbf765..0cac8f8f 100644
--- a/org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeInserter.java
+++ b/org.jacoco.core/src/org/jacoco/core/internal/instr/ProbeInserter.java
@@ -67,25 +67,20 @@ class ProbeInserter extends MethodVisitor implements IProbeInserter {
public void insertProbe(final int id) {
- // For a probe we set the corresponding position in the boolean[] array
- // to true.
+ // BEGIN android-change
+ // For a probe we call setProbe on the IExecutionData object.
mv.visitVarInsn(Opcodes.ALOAD, variable);
- // Stack[0]: [Z
+ // Stack[0]: Lorg/jacoco/core/data/IExecutionData;
InstrSupport.push(mv, id);
// Stack[1]: I
- // Stack[0]: [Z
+ // Stack[0]: Lorg/jacoco/core/data/IExecutionData;
- mv.visitInsn(Opcodes.ICONST_1);
-
- // Stack[2]: I
- // Stack[1]: I
- // Stack[0]: [Z
-
- mv.visitInsn(Opcodes.BASTORE);
+ mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "org/jacoco/core/data/IExecutionData", "setProbe", "(I)V", true);
+ // END android-change
}
@Override
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/LoggerRuntime.java b/org.jacoco.core/src/org/jacoco/core/runtime/LoggerRuntime.java
index 72553956..bef42030 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/LoggerRuntime.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/LoggerRuntime.java
@@ -168,7 +168,9 @@ public class LoggerRuntime extends AbstractRuntime {
@Override
public void publish(final LogRecord record) {
if (key.equals(record.getMessage())) {
- data.getProbes(record.getParameters());
+ // BEGIN android-change
+ data.getExecutionData(record.getParameters());
+ // END android-change
}
}
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/OfflineInstrumentationAccessGenerator.java b/org.jacoco.core/src/org/jacoco/core/runtime/OfflineInstrumentationAccessGenerator.java
index af6671ee..a5e88b60 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/OfflineInstrumentationAccessGenerator.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/OfflineInstrumentationAccessGenerator.java
@@ -50,8 +50,10 @@ public class OfflineInstrumentationAccessGenerator implements
mv.visitLdcInsn(Long.valueOf(classid));
mv.visitLdcInsn(classname);
InstrSupport.push(mv, probecount);
- mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeClassName, "getProbes",
- "(JLjava/lang/String;I)[Z", false);
+ // BEGIN android-change
+ mv.visitMethodInsn(Opcodes.INVOKESTATIC, runtimeClassName, "getExecutionData",
+ "(JLjava/lang/String;I)Lorg/jacoco/core/data/IExecutionData;", false);
+ // END android-change
return 4;
}
diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/RuntimeData.java b/org.jacoco.core/src/org/jacoco/core/runtime/RuntimeData.java
index afb5b7f3..c0fbb654 100644
--- a/org.jacoco.core/src/org/jacoco/core/runtime/RuntimeData.java
+++ b/org.jacoco.core/src/org/jacoco/core/runtime/RuntimeData.java
@@ -11,7 +11,7 @@
*******************************************************************************/
package org.jacoco.core.runtime;
-import org.jacoco.core.data.ExecutionData;
+import org.jacoco.core.data.IExecutionData;
import org.jacoco.core.data.ExecutionDataStore;
import org.jacoco.core.data.IExecutionDataVisitor;
import org.jacoco.core.data.ISessionInfoVisitor;
@@ -128,15 +128,18 @@ public class RuntimeData {
* probe data length
* @return execution data
*/
- public ExecutionData getExecutionData(final Long id, final String name,
+ // BEGIN android-change
+ public IExecutionData getExecutionData(final Long id, final String name,
final int probecount) {
+ // END android-change
synchronized (store) {
return store.get(id, name, probecount);
}
}
+ // BEGIN android-change
/**
- * Retrieves the execution probe array for a given class. The passed
+ * Retrieves the execution data for a given class. The passed
* {@link Object} array instance is used for parameters and the return value
* as follows. Call parameters:
*
@@ -149,18 +152,19 @@ public class RuntimeData {
* Return value:
*
* <ul>
- * <li>args[0]: probe array (<code>boolean[]</code>)
+ * <li>args[0]: execution data ({@link IExecutionData})
* </ul>
*
* @param args
* parameter array of length 3
*/
- public void getProbes(final Object[] args) {
+ public void getExecutionData(final Object[] args) {
final Long classid = (Long) args[0];
final String name = (String) args[1];
final int probecount = ((Integer) args[2]).intValue();
- args[0] = getExecutionData(classid, name, probecount).getProbes();
+ args[0] = getExecutionData(classid, name, probecount);
}
+ // END android-change
/**
* In violation of the regular semantic of {@link Object#equals(Object)}
@@ -173,7 +177,9 @@ public class RuntimeData {
@Override
public boolean equals(final Object args) {
if (args instanceof Object[]) {
- getProbes((Object[]) args);
+ // BEGIN android-change
+ getExecutionData((Object[]) args);
+ // END android-change
}
return super.equals(args);
}
diff --git a/org.jacoco.report/src/org/jacoco/report/IReportVisitor.java b/org.jacoco.report/src/org/jacoco/report/IReportVisitor.java
index db36796d..1cf4aed4 100644
--- a/org.jacoco.report/src/org/jacoco/report/IReportVisitor.java
+++ b/org.jacoco.report/src/org/jacoco/report/IReportVisitor.java
@@ -15,7 +15,7 @@ import java.io.IOException;
import java.util.Collection;
import java.util.List;
-import org.jacoco.core.data.ExecutionData;
+import org.jacoco.core.data.IExecutionData;
import org.jacoco.core.data.SessionInfo;
/**
@@ -39,7 +39,9 @@ public interface IReportVisitor extends IReportGroupVisitor {
* in case of IO problems with the report writer
*/
void visitInfo(List<SessionInfo> sessionInfos,
- Collection<ExecutionData> executionData) throws IOException;
+ // BEGIN android-change
+ Collection<IExecutionData> executionData) throws IOException;
+ // END android-change
/**
* Has to be called after all report data has been emitted.
diff --git a/org.jacoco.report/src/org/jacoco/report/MultiReportVisitor.java b/org.jacoco.report/src/org/jacoco/report/MultiReportVisitor.java
index 3cd5e558..f4fefa85 100644
--- a/org.jacoco.report/src/org/jacoco/report/MultiReportVisitor.java
+++ b/org.jacoco.report/src/org/jacoco/report/MultiReportVisitor.java
@@ -17,7 +17,7 @@ import java.util.Collection;
import java.util.List;
import org.jacoco.core.analysis.IBundleCoverage;
-import org.jacoco.core.data.ExecutionData;
+import org.jacoco.core.data.IExecutionData;
import org.jacoco.core.data.SessionInfo;
/**
@@ -41,7 +41,9 @@ public class MultiReportVisitor extends MultiGroupVisitor implements
}
public void visitInfo(final List<SessionInfo> sessionInfos,
- final Collection<ExecutionData> executionData) throws IOException {
+ // BEGIN android-change
+ final Collection<IExecutionData> executionData) throws IOException {
+ // END android-chnage
for (final IReportVisitor v : visitors) {
v.visitInfo(sessionInfos, executionData);
}
diff --git a/org.jacoco.report/src/org/jacoco/report/check/RulesChecker.java b/org.jacoco.report/src/org/jacoco/report/check/RulesChecker.java
index cc6acf04..f7435600 100644
--- a/org.jacoco.report/src/org/jacoco/report/check/RulesChecker.java
+++ b/org.jacoco.report/src/org/jacoco/report/check/RulesChecker.java
@@ -17,7 +17,7 @@ import java.util.Collection;
import java.util.List;
import org.jacoco.core.analysis.IBundleCoverage;
-import org.jacoco.core.data.ExecutionData;
+import org.jacoco.core.data.IExecutionData;
import org.jacoco.core.data.SessionInfo;
import org.jacoco.report.ILanguageNames;
import org.jacoco.report.IReportGroupVisitor;
@@ -86,7 +86,9 @@ public class RulesChecker {
}
public void visitInfo(final List<SessionInfo> sessionInfos,
- final Collection<ExecutionData> executionData)
+ // BEGIN android-change
+ final Collection<IExecutionData> executionData)
+ // END android-change
throws IOException {
}
diff --git a/org.jacoco.report/src/org/jacoco/report/csv/CSVFormatter.java b/org.jacoco.report/src/org/jacoco/report/csv/CSVFormatter.java
index 793e2153..42939daa 100644
--- a/org.jacoco.report/src/org/jacoco/report/csv/CSVFormatter.java
+++ b/org.jacoco.report/src/org/jacoco/report/csv/CSVFormatter.java
@@ -17,7 +17,7 @@ import java.io.OutputStreamWriter;
import java.util.Collection;
import java.util.List;
-import org.jacoco.core.data.ExecutionData;
+import org.jacoco.core.data.IExecutionData;
import org.jacoco.core.data.SessionInfo;
import org.jacoco.report.ILanguageNames;
import org.jacoco.report.IReportVisitor;
@@ -84,7 +84,9 @@ public class CSVFormatter {
}
public void visitInfo(final List<SessionInfo> sessionInfos,
- final Collection<ExecutionData> executionData)
+ // BEGIN android-change
+ final Collection<IExecutionData> executionData)
+ // END android-change
throws IOException {
// Info not used for CSV report
}
diff --git a/org.jacoco.report/src/org/jacoco/report/html/HTMLFormatter.java b/org.jacoco.report/src/org/jacoco/report/html/HTMLFormatter.java
index 9994ced0..ce8cd2d9 100644
--- a/org.jacoco.report/src/org/jacoco/report/html/HTMLFormatter.java
+++ b/org.jacoco.report/src/org/jacoco/report/html/HTMLFormatter.java
@@ -18,7 +18,7 @@ import java.util.Locale;
import org.jacoco.core.analysis.IBundleCoverage;
import org.jacoco.core.analysis.ICoverageNode.CounterEntity;
-import org.jacoco.core.data.ExecutionData;
+import org.jacoco.core.data.IExecutionData;
import org.jacoco.core.data.SessionInfo;
import org.jacoco.report.ILanguageNames;
import org.jacoco.report.IMultiReportOutput;
@@ -193,12 +193,16 @@ public class HTMLFormatter implements IHTMLReportContext {
return new IReportVisitor() {
private List<SessionInfo> sessionInfos;
- private Collection<ExecutionData> executionData;
+ // BEGIN android-change
+ private Collection<IExecutionData> executionData;
+ // END android-change
private HTMLGroupVisitor groupHandler;
public void visitInfo(final List<SessionInfo> sessionInfos,
- final Collection<ExecutionData> executionData)
+ // BEGIN android-change
+ final Collection<IExecutionData> executionData)
+ // END android-change
throws IOException {
this.sessionInfos = sessionInfos;
this.executionData = executionData;
diff --git a/org.jacoco.report/src/org/jacoco/report/internal/html/page/SessionsPage.java b/org.jacoco.report/src/org/jacoco/report/internal/html/page/SessionsPage.java
index 67de4941..3a489025 100644
--- a/org.jacoco.report/src/org/jacoco/report/internal/html/page/SessionsPage.java
+++ b/org.jacoco.report/src/org/jacoco/report/internal/html/page/SessionsPage.java
@@ -20,7 +20,7 @@ import java.util.Comparator;
import java.util.Date;
import java.util.List;
-import org.jacoco.core.data.ExecutionData;
+import org.jacoco.core.data.IExecutionData;
import org.jacoco.core.data.SessionInfo;
import org.jacoco.report.ILanguageNames;
import org.jacoco.report.internal.ReportOutputFolder;
@@ -48,7 +48,7 @@ public class SessionsPage extends ReportPage {
private final DateFormat dateFormat;
- private final List<ExecutionData> executionData;
+ private final List<IExecutionData> executionData;
private final ElementIndex index;
@@ -69,18 +69,24 @@ public class SessionsPage extends ReportPage {
* settings context
*/
public SessionsPage(final List<SessionInfo> sessionInfos,
- final Collection<ExecutionData> executionData,
+ // BEGIN android-change
+ final Collection<IExecutionData> executionData,
+ // END android-change
final ElementIndex index, final ReportPage parent,
final ReportOutputFolder folder, final IHTMLReportContext context) {
super(parent, folder, context);
this.sessionInfos = sessionInfos;
- this.executionData = new ArrayList<ExecutionData>(executionData);
+ // BEGIN android-change
+ this.executionData = new ArrayList<IExecutionData>(executionData);
+ // END android-change
this.index = index;
this.dateFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT,
DateFormat.DEFAULT, context.getLocale());
final ILanguageNames names = context.getLanguageNames();
- Collections.sort(this.executionData, new Comparator<ExecutionData>() {
- public int compare(final ExecutionData e1, final ExecutionData e2) {
+ // BEGIN android-change
+ Collections.sort(this.executionData, new Comparator<IExecutionData>() {
+ public int compare(final IExecutionData e1, final IExecutionData e2) {
+ // END android-change
return names.getQualifiedClassName(e1.getName()).compareTo(
names.getQualifiedClassName(e2.getName()));
}
@@ -129,7 +135,9 @@ public class SessionsPage extends ReportPage {
}
final HTMLElement tbody = table.tbody();
final ILanguageNames names = context.getLanguageNames();
- for (final ExecutionData e : executionData) {
+ // BEGIN android-change
+ for (final IExecutionData e : executionData) {
+ // END android-change
final HTMLElement tr = tbody.tr();
final String link = index.getLinkToClass(e.getId());
final String qualifiedName = names.getQualifiedClassName(e
diff --git a/org.jacoco.report/src/org/jacoco/report/xml/XMLFormatter.java b/org.jacoco.report/src/org/jacoco/report/xml/XMLFormatter.java
index a1fee86e..3bda5ed4 100644
--- a/org.jacoco.report/src/org/jacoco/report/xml/XMLFormatter.java
+++ b/org.jacoco.report/src/org/jacoco/report/xml/XMLFormatter.java
@@ -17,7 +17,7 @@ import java.util.Collection;
import java.util.List;
import org.jacoco.core.analysis.IBundleCoverage;
-import org.jacoco.core.data.ExecutionData;
+import org.jacoco.core.data.IExecutionData;
import org.jacoco.core.data.SessionInfo;
import org.jacoco.report.IReportGroupVisitor;
import org.jacoco.report.IReportVisitor;
@@ -61,7 +61,9 @@ public class XMLFormatter {
private XMLGroupVisitor groupVisitor;
public void visitInfo(final List<SessionInfo> sessionInfos,
- final Collection<ExecutionData> executionData)
+ // BEGIN android-change
+ final Collection<IExecutionData> executionData)
+ // END android-change
throws IOException {
this.sessionInfos = sessionInfos;
}