Snap for 5598178 from 3ff8bb8b8d3d9fef71de9d95c9e57c165c65cd3f to emu-29.0-release

Change-Id: I03fe55d97e8bd175a646f9d4cf8a4cbd51a30794
diff --git a/android/cts/runner/src/com/drawelements/deqp/runner/DeqpTestRunner.java b/android/cts/runner/src/com/drawelements/deqp/runner/DeqpTestRunner.java
index 985ab81..37745d5 100644
--- a/android/cts/runner/src/com/drawelements/deqp/runner/DeqpTestRunner.java
+++ b/android/cts/runner/src/com/drawelements/deqp/runner/DeqpTestRunner.java
@@ -42,6 +42,7 @@
 import com.android.tradefed.testtype.IShardableTest;
 import com.android.tradefed.testtype.ITestCollector;
 import com.android.tradefed.testtype.ITestFilterReceiver;
+import com.android.tradefed.testtype.NativeCodeCoverageListener;
 import com.android.tradefed.util.AbiUtils;
 import com.android.tradefed.util.IRunUtil;
 import com.android.tradefed.util.RunInterruptedException;
@@ -148,6 +149,13 @@
             importance=Option.Importance.NEVER)
     private String mAngle = "none";
 
+    @Option(
+            name = "native-coverage",
+            description =
+                    "Collect code coverage for this test run. Note that the build under test must"
+                        + " be a coverage build or else this will fail.")
+    private boolean mCoverage = false;
+
     private Collection<TestDescription> mRemainingTests = null;
     private Map<TestDescription, Set<BatchRunConfiguration>> mTestInstances = null;
     private final TestInstanceResultListener mInstanceListerner = new TestInstanceResultListener();
@@ -2069,6 +2077,8 @@
             loadTests();
         }
 
+        listener = addNativeCoverageListenerIfEnabled(mDevice, listener);
+
         mRemainingTests = new LinkedList<>(mTestInstances.keySet());
         long startTime = System.currentTimeMillis();
         listener.testRunStarted(getId(), mRemainingTests.size());
@@ -2175,6 +2185,8 @@
         mCollectTestsOnly = collectTests;
     }
 
+    public void setNativeCoverage(boolean coverage) { mCoverage = coverage; }
+
     private static void copyOptions(DeqpTestRunner destination, DeqpTestRunner source) {
         destination.mDeqpPackage = source.mDeqpPackage;
         destination.mConfigName = source.mConfigName;
@@ -2190,6 +2202,7 @@
         destination.mLogData = source.mLogData;
         destination.mCollectTestsOnly = source.mCollectTestsOnly;
         destination.mAngle = source.mAngle;
+        destination.mCoverage = source.mCoverage;
     }
 
     /**
@@ -2262,4 +2275,19 @@
         // second. Let's guess 200ms per test.
         return 200 * mTestInstances.size();
     }
+
+    /**
+     * Adds a {@link NativeCodeCoverageListener} to the chain if code coverage is enabled.
+     *
+     * @param device the device to pull coverage results from
+     * @param listener the original listener
+     * @return a chained listener if code coverage is enabled, otherwise the original listener
+     */
+    ITestInvocationListener addNativeCoverageListenerIfEnabled(
+            ITestDevice device, ITestInvocationListener listener) {
+        if (mCoverage) {
+            return new NativeCodeCoverageListener(device, listener);
+        }
+        return listener;
+    }
 }
diff --git a/android/cts/runner/tests/src/com/drawelements/deqp/runner/DeqpTestRunnerTest.java b/android/cts/runner/tests/src/com/drawelements/deqp/runner/DeqpTestRunnerTest.java
index 7ee1751..e12648f 100644
--- a/android/cts/runner/tests/src/com/drawelements/deqp/runner/DeqpTestRunnerTest.java
+++ b/android/cts/runner/tests/src/com/drawelements/deqp/runner/DeqpTestRunnerTest.java
@@ -15,6 +15,9 @@
  */
 package com.drawelements.deqp.runner;
 
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
 import com.android.ddmlib.IDevice;
 import com.android.ddmlib.IShellOutputReceiver;
@@ -31,6 +34,7 @@
 import com.android.tradefed.testtype.IAbi;
 import com.android.tradefed.testtype.IRemoteTest;
 import com.android.tradefed.testtype.IRuntimeHintProvider;
+import com.android.tradefed.testtype.NativeCodeCoverageListener;
 import com.android.tradefed.util.AbiUtils;
 import com.android.tradefed.util.FileUtil;
 import com.android.tradefed.util.IRunUtil;
@@ -2344,4 +2348,40 @@
         deqpTest.addIncludeFilter("dEQP-GLES3.pick_me.yes");
         testFiltering(deqpTest, expectedTrie, activeTests);
     }
+
+    public void testCoverageDisabled_noCoverageListener() throws Exception {
+        final TestDescription testId = new TestDescription("dEQP-GLES3.info", "version");
+
+        ITestDevice mockDevice = EasyMock.createMock(ITestDevice.class);
+        ITestInvocationListener mockListener =
+            EasyMock.createStrictMock(ITestInvocationListener.class);
+
+        Collection<TestDescription> tests = new ArrayList<>();
+        tests.add(testId);
+
+        DeqpTestRunner deqpTest = buildGlesTestRunner(3, 0, tests, mTestsDir);
+        deqpTest.setNativeCoverage(false);
+
+        ITestInvocationListener listener =
+            deqpTest.addNativeCoverageListenerIfEnabled(mockDevice, mockListener);
+        assertSame(listener, mockListener);
+    }
+
+    public void testCoverageEnabled_newCoverageListener() throws Exception {
+        final TestDescription testId = new TestDescription("dEQP-GLES3.info", "version");
+
+        ITestDevice mockDevice = EasyMock.createMock(ITestDevice.class);
+        ITestInvocationListener mockListener =
+            EasyMock.createStrictMock(ITestInvocationListener.class);
+
+        Collection<TestDescription> tests = new ArrayList<>();
+        tests.add(testId);
+
+        DeqpTestRunner deqpTest = buildGlesTestRunner(3, 0, tests, mTestsDir);
+        deqpTest.setNativeCoverage(true);
+
+        ITestInvocationListener listener =
+            deqpTest.addNativeCoverageListenerIfEnabled(mockDevice, mockListener);
+        assertTrue(listener instanceof NativeCodeCoverageListener);
+    }
 }