diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/.gitignore b/runner/AndroidTestOrchestratorWithTestCoverageSample/.gitignore
new file mode 100644
index 000000000..03eee2ade
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/.gitignore
@@ -0,0 +1,6 @@
+.gradle
+/local.properties
+.idea
+*.iml
+.DS_Store
+build
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/README.md b/runner/AndroidTestOrchestratorWithTestCoverageSample/README.md
new file mode 100644
index 000000000..42e9df801
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/README.md
@@ -0,0 +1,25 @@
+# AndroidTestOrchestrator with test coverage sample
+
+The Android Test Orchestrator allows you to run each of your app's tests in isolation, enabling greater reliability.
+See https://developer.android.com/training/testing/junit-runner#using-android-test-orchestrator for more background.
+
+This sample is a subset of the AndroidJUnitRunner sample, but it
+illustrates how to enable Jacoco test coverage report with the Android Test Orchestrator in the app/build.gradle file.
+
+This project uses the Gradle build system. You don't need an IDE to build and execute it but Android Studio is recommended.
+
+1. Download the project code, preferably using `git clone`.
+1. Open the Android SDK Manager (*Tools* Menu | *Android*).
+1. In Android Studio, select *File* | *Open...* and point to the top-level `./build.gradle` file.
+1. Check out the relevant code:
+ * The application under test is located in `src/main/java`
+ * Tests are in `src/androidTest/java`
+1. Connect a device or start an emulator:
+ * Turn animations off.
+ (On your device, under Settings->Developer options disable the following 3 settings: "Window animation scale", "Transition animation scale" and "Animator duration scale")
+1. Run the newly created configuration.
+
+The application will be started on the device/emulator and a series of actions will be performed automatically.
+
+If you are using Android Studio, the *Run* window will show the test results.
+The test coverage report will be generated in `app/build/reports/coverage/androidTest/debug/index.html`.
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/app/build.gradle b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/build.gradle
new file mode 100644
index 000000000..2260e792f
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/build.gradle
@@ -0,0 +1,39 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 31
+ buildToolsVersion rootProject.buildToolsVersion
+ defaultConfig {
+ applicationId "com.example.android.testing.androidtestorchestratorsample"
+ minSdkVersion 14
+ targetSdkVersion 31
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ testInstrumentationRunnerArguments clearPackageData: 'true'
+ testInstrumentationRunnerArguments useTestStorageService: 'true'
+ }
+ buildTypes {
+ debug {
+ testCoverageEnabled true
+ }
+ }
+ testOptions {
+ execution 'ANDROIDX_TEST_ORCHESTRATOR'
+ }
+}
+
+dependencies {
+ // App's dependencies, including test
+ implementation 'androidx.annotation:annotation:' + rootProject.androidxAnnotationVersion
+ implementation 'com.google.guava:guava:' + rootProject.guavaVersion
+
+ // Testing-only dependencies
+ androidTestImplementation 'androidx.test:core:' + rootProject.coreVersion
+ androidTestImplementation 'androidx.test.ext:junit:' + rootProject.extJUnitVersion
+ androidTestImplementation 'androidx.test:runner:' + rootProject.runnerVersion
+ androidTestImplementation 'androidx.test.espresso:espresso-core:' + rootProject.espressoVersion
+ androidTestUtil 'androidx.test:orchestrator:' + rootProject.runnerVersion
+ androidTestUtil 'androidx.test.services:test-services:' + rootProject.testServicesVersion
+}
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/androidTest/java/com/example/android/testing/androidtestorchestratorsample/CalculatorAddParameterizedTest.java b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/androidTest/java/com/example/android/testing/androidtestorchestratorsample/CalculatorAddParameterizedTest.java
new file mode 100644
index 000000000..63c9e7146
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/androidTest/java/com/example/android/testing/androidtestorchestratorsample/CalculatorAddParameterizedTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2020, 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.example.android.testing.androidtestorchestratorsample;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import androidx.test.filters.SmallTest;
+
+import java.lang.Iterable;
+import java.util.Arrays;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.runners.Parameterized.Parameters;
+
+
+/**
+ * JUnit4 tests for the calculator's add logic.
+ *
+ *
This test uses a Junit4s Parameterized tests features which uses annotations to pass
+ * parameters into a unit test. The way this works is that you have to use the {@link Parameterized}
+ * runner to run your tests.
+ *
+ */
+@RunWith(Parameterized.class)
+@SmallTest
+public class CalculatorAddParameterizedTest {
+
+ /**
+ * @return {@link Iterable} that contains the values that should be passed to the constructor.
+ * In this example we are going to use three parameters: operand one, operand two and the
+ * expected result.
+ */
+ @Parameters
+ public static Iterable data() {
+ return Arrays.asList(new Object[][]{
+ {0, 0, 0},
+ {0, -1, -1},
+ {2, 2, 4},
+ {8, 8, 16},
+ {16, 16, 32},
+ {32, 0, 32},
+ {64, 64, 128}});
+ }
+
+ private final double mOperandOne;
+ private final double mOperandTwo;
+ private final double mExpectedResult;
+
+ private Calculator mCalculator;
+
+ /**
+ * Constructor that takes in the values specified in
+ * {@link CalculatorAddParameterizedTest#data()}. The values need to be saved to fields in order
+ * to reuse them in your tests.
+ */
+ public CalculatorAddParameterizedTest(double operandOne, double operandTwo,
+ double expectedResult) {
+
+ mOperandOne = operandOne;
+ mOperandTwo = operandTwo;
+ mExpectedResult = expectedResult;
+ }
+
+ @Before
+ public void setUp() {
+ mCalculator = new Calculator();
+ }
+
+ @Test
+ public void testAdd_TwoNumbers() {
+ double resultAdd = mCalculator.add(mOperandOne, mOperandTwo);
+ assertThat(resultAdd, is(equalTo(mExpectedResult)));
+ }
+}
\ No newline at end of file
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/androidTest/java/com/example/android/testing/androidtestorchestratorsample/CalculatorInstrumentationTest.java b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/androidTest/java/com/example/android/testing/androidtestorchestratorsample/CalculatorInstrumentationTest.java
new file mode 100644
index 000000000..80b31bae5
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/androidTest/java/com/example/android/testing/androidtestorchestratorsample/CalculatorInstrumentationTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2020, 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.example.android.testing.androidtestorchestratorsample;
+
+import junit.framework.TestSuite;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.internal.builders.AllDefaultPossibilitiesBuilder;
+import org.junit.runner.RunWith;
+
+import androidx.test.core.app.ActivityScenario;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnitRunner;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.action.ViewActions.closeSoftKeyboard;
+import static androidx.test.espresso.action.ViewActions.typeText;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
+/**
+ * JUnit4 Ui Tests for {@link CalculatorActivity} using the {@link AndroidJUnitRunner} with the
+ * Android Test Orchestrator.
+ * This class uses the JUnit4 syntax for tests.
+ *
+ * With the new AndroidJUnit runner you can run both JUnit3 and JUnit4 tests in a single test
+ * suite. The {@link AndroidRunnerBuilder} which extends JUnit's
+ * {@link AllDefaultPossibilitiesBuilder} will create a single {@link
+ * TestSuite} from all tests and run them.
+ */
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class CalculatorInstrumentationTest {
+
+ /**
+ * Use {@link ActivityScenario} to create and launch of the activity.
+ */
+ @Before
+ public void launchActivity() {
+ ActivityScenario.launch(CalculatorActivity.class);
+ }
+
+ @Test
+ public void noOperandShowsComputationError() {
+ final String expectedResult = getApplicationContext().getString(R.string.computationError);
+ onView(withId(R.id.operation_add_btn)).perform(click());
+ onView(withId(R.id.operation_result_text_view)).check(matches(withText(expectedResult)));
+ }
+
+ @Test
+ public void typeOperandsAndPerformAddOperation() {
+ performOperation(R.id.operation_add_btn, "16.0", "16.0", "32.0");
+ }
+
+ @Test
+ public void typeOperandsAndPerformSubOperation() {
+ performOperation(R.id.operation_sub_btn, "32.0", "16.0", "16.0");
+ }
+
+ @Test
+ public void typeOperandsAndPerformDivOperation() {
+ performOperation(R.id.operation_div_btn, "128.0", "16.0", "8.0");
+ }
+
+ @Test
+ public void divZeroForOperandTwoShowsError() {
+ final String expectedResult = getApplicationContext().getString(R.string.computationError);
+ performOperation(R.id.operation_div_btn, "128.0", "0.0", expectedResult);
+ }
+
+ @Test
+ public void typeOperandsAndPerformMulOperation() {
+ performOperation(R.id.operation_mul_btn, "16.0", "16.0", "256.0");
+ }
+
+ private void performOperation(int btnOperationResId, String operandOne,
+ String operandTwo, String expectedResult) {
+ // Type the two operands in the EditText fields
+ onView(withId(R.id.operand_one_edit_text)).perform(typeText(operandOne),
+ closeSoftKeyboard());
+ onView(withId(R.id.operand_two_edit_text)).perform(typeText(operandTwo),
+ closeSoftKeyboard());
+
+ // Click on a given operation button
+ onView(withId(btnOperationResId)).perform(click());
+
+ // Check the expected test is displayed in the Ui
+ onView(withId(R.id.operation_result_text_view)).check(matches(withText(expectedResult)));
+ }
+
+}
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/AndroidManifest.xml b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/AndroidManifest.xml
new file mode 100644
index 000000000..f3b473cae
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/AndroidManifest.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/java/com/example/android/testing/androidtestorchestratorsample/Calculator.java b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/java/com/example/android/testing/androidtestorchestratorsample/Calculator.java
new file mode 100644
index 000000000..b7a17d12e
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/java/com/example/android/testing/androidtestorchestratorsample/Calculator.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2020, 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.example.android.testing.androidtestorchestratorsample;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * A simple calculator with a basic set of operations.
+ */
+public class Calculator {
+
+ public enum Operator {ADD, SUB, DIV, MUL}
+
+ /**
+ * Addition operation
+ */
+ public double add(double firstOperand, double secondOperand) {
+ return firstOperand + secondOperand;
+ }
+
+ /**
+ * Substract operation
+ */
+ public double sub(double firstOperand, double secondOperand) {
+ return firstOperand - secondOperand;
+ }
+
+ /**
+ * Divide operation
+ */
+ public double div(double firstOperand, double secondOperand) {
+ checkArgument(secondOperand != 0, "secondOperand must be != 0, you cannot divide by zero");
+ return firstOperand / secondOperand;
+ }
+
+ /**
+ * Multiply operation
+ */
+ public double mul(double firstOperand, double secondOperand) {
+
+ return firstOperand * secondOperand;
+ }
+}
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/java/com/example/android/testing/androidtestorchestratorsample/CalculatorActivity.java b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/java/com/example/android/testing/androidtestorchestratorsample/CalculatorActivity.java
new file mode 100644
index 000000000..d745a3210
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/java/com/example/android/testing/androidtestorchestratorsample/CalculatorActivity.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2020, 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.example.android.testing.androidtestorchestratorsample;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+
+/**
+ * {@link android.app.Activity} which contains a simple calculator. Numbers can be entered in the
+ * two {@link EditText} fields and result can be obtained by pressing one of the
+ * operation {@link Button}s at the bottom.
+ */
+public class CalculatorActivity extends Activity {
+
+ private static final String TAG = "CalculatorActivity";
+
+ private Calculator mCalculator;
+
+ private EditText mOperandOneEditText;
+ private EditText mOperandTwoEditText;
+
+ private TextView mResultTextView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_calculator);
+ mCalculator = new Calculator();
+ mResultTextView = (TextView) findViewById(R.id.operation_result_text_view);
+ mOperandOneEditText = (EditText) findViewById(R.id.operand_one_edit_text);
+ mOperandTwoEditText = (EditText) findViewById(R.id.operand_two_edit_text);
+ }
+
+ /**
+ * OnClick method that is called when the add {@link Button} is pressed.
+ */
+ public void onAdd(View view) {
+ compute(Calculator.Operator.ADD);
+ }
+
+ /**
+ * OnClick method that is called when the substract {@link Button} is pressed.
+ */
+ public void onSub(View view) {
+ compute(Calculator.Operator.SUB);
+ }
+
+ /**
+ * OnClick method that is called when the divide {@link Button} is pressed.
+ */
+ public void onDiv(View view) {
+ try {
+ compute(Calculator.Operator.DIV);
+ } catch (IllegalArgumentException iae) {
+ Log.e(TAG, "IllegalArgumentException", iae);
+ mResultTextView.setText(getString(R.string.computationError));
+ }
+ }
+
+ /**
+ * OnClick method that is called when the multiply {@link Button} is pressed.
+ */
+ public void onMul(View view) {
+ compute(Calculator.Operator.MUL);
+ }
+
+ private void compute(Calculator.Operator operator) {
+ double operandOne;
+ double operandTwo;
+ try {
+ operandOne = getOperand(mOperandOneEditText);
+ operandTwo = getOperand(mOperandTwoEditText);
+ } catch (NumberFormatException nfe) {
+ Log.e(TAG, "NumberFormatException", nfe);
+ mResultTextView.setText(getString(R.string.computationError));
+ return;
+ }
+
+ String result;
+ switch (operator) {
+ case ADD:
+ result = String.valueOf(mCalculator.add(operandOne, operandTwo));
+ break;
+ case SUB:
+ result = String.valueOf(mCalculator.sub(operandOne, operandTwo));
+ break;
+ case DIV:
+ result = String.valueOf(mCalculator.div(operandOne, operandTwo));
+ break;
+ case MUL:
+ result = String.valueOf(mCalculator.mul(operandOne, operandTwo));
+ break;
+ default:
+ result = getString(R.string.computationError);
+ break;
+ }
+ mResultTextView.setText(result);
+ }
+
+ /**
+ * @return the operand value which was entered in an {@link EditText} as a double
+ */
+ private static Double getOperand(EditText operandEditText) {
+ String operandText = getOperandText(operandEditText);
+ return Double.valueOf(operandText);
+ }
+
+ /**
+ * @return the operand text which was entered in an {@link EditText}.
+ */
+ private static String getOperandText(EditText operandEditText) {
+ String operandText = operandEditText.getText().toString();
+ if (TextUtils.isEmpty(operandText)) {
+ throw new NumberFormatException("operand cannot be empty!");
+ }
+ return operandText;
+ }
+}
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/drawable-hdpi/ic_launcher.png b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100755
index 000000000..965ac9624
Binary files /dev/null and b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/drawable-hdpi/ic_launcher.png differ
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/drawable-mdpi/ic_launcher.png b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100755
index 000000000..df52c5278
Binary files /dev/null and b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/drawable-mdpi/ic_launcher.png differ
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/drawable-xhdpi/ic_launcher.png b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100755
index 000000000..3d479bfe7
Binary files /dev/null and b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100755
index 000000000..c85d90b05
Binary files /dev/null and b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/layout/activity_calculator.xml b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/layout/activity_calculator.xml
new file mode 100644
index 000000000..60f5e3565
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/layout/activity_calculator.xml
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/values-v14/styles.xml b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/values-v14/styles.xml
new file mode 100644
index 000000000..843d5dab7
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/values-v14/styles.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/values-v21/styles.xml b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/values-v21/styles.xml
new file mode 100644
index 000000000..5bb805503
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/values-v21/styles.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/values-w820dp/dimens.xml b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 000000000..8381ee1ee
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+ 64dp
+
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/values/dimens.xml b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/values/dimens.xml
new file mode 100644
index 000000000..9d4ba208d
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/values/dimens.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+ 16dp
+ 16dp
+
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/values/strings.xml b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/values/strings.xml
new file mode 100644
index 000000000..acd3917db
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/values/strings.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+ AndroidTestOrchestratorSample
+ Type Operand 1
+ Type Operand 2
+ Add
+ Sub
+ Div
+ Mul
+ Error
+
+
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/values/styles.xml b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/values/styles.xml
new file mode 100644
index 000000000..7af47cdb5
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/app/src/main/res/values/styles.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/build.gradle b/runner/AndroidTestOrchestratorWithTestCoverageSample/build.gradle
new file mode 100644
index 000000000..5c1f783b0
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/build.gradle
@@ -0,0 +1,36 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ ext.agpVersion = "7.1.0-alpha12"
+ repositories {
+ // Insert local test repo here
+ google()
+ mavenCentral()
+ }
+ dependencies {
+ classpath "com.android.tools.build:gradle:$agpVersion"
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ // Insert local test repo here
+ google()
+ mavenCentral()
+ }
+}
+
+ext {
+ buildToolsVersion = "31.0.0"
+ androidxAnnotationVersion = "1.2.0"
+ guavaVersion = "30.1.1-android"
+ coreVersion = "1.4.1-alpha03"
+ extJUnitVersion = "1.1.4-alpha03"
+ runnerVersion = "1.4.1-alpha03"
+ rulesVersion = "1.4.1-alpha03"
+ testServicesVersion = "1.4.1-alpha03"
+ espressoVersion = "3.5.0-alpha03"
+}
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/gradle.properties b/runner/AndroidTestOrchestratorWithTestCoverageSample/gradle.properties
new file mode 100644
index 000000000..7df85420e
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/gradle.properties
@@ -0,0 +1,20 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+android.useAndroidX=true
+android.enableAdditionalTestOutput=false
\ No newline at end of file
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/gradle/wrapper/gradle-wrapper.jar b/runner/AndroidTestOrchestratorWithTestCoverageSample/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..8c0fb64a8
Binary files /dev/null and b/runner/AndroidTestOrchestratorWithTestCoverageSample/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/gradle/wrapper/gradle-wrapper.properties b/runner/AndroidTestOrchestratorWithTestCoverageSample/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..a70d5d4e4
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Thu Oct 14 15:41:28 PDT 2021
+distributionBase=GRADLE_USER_HOME
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
+distributionPath=wrapper/dists
+zipStorePath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/gradlew b/runner/AndroidTestOrchestratorWithTestCoverageSample/gradlew
new file mode 100755
index 000000000..91a7e269e
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/gradlew.bat b/runner/AndroidTestOrchestratorWithTestCoverageSample/gradlew.bat
new file mode 100644
index 000000000..aec99730b
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/runner/AndroidTestOrchestratorWithTestCoverageSample/settings.gradle b/runner/AndroidTestOrchestratorWithTestCoverageSample/settings.gradle
new file mode 100644
index 000000000..e7b4def49
--- /dev/null
+++ b/runner/AndroidTestOrchestratorWithTestCoverageSample/settings.gradle
@@ -0,0 +1 @@
+include ':app'