diff --git a/extensions/cronet/build.gradle b/extensions/cronet/build.gradle
index b99512935e..975bf4a6e8 100644
--- a/extensions/cronet/build.gradle
+++ b/extensions/cronet/build.gradle
@@ -13,12 +13,25 @@
// limitations under the License.
apply from: "$gradle.ext.exoplayerSettingsDir/common_library_config.gradle"
+android {
+ defaultConfig {
+ multiDexEnabled true
+ }
+}
+
dependencies {
api "com.google.android.gms:play-services-cronet:17.0.0"
implementation project(modulePrefix + 'library-core')
implementation 'androidx.annotation:annotation:' + androidxAnnotationVersion
compileOnly 'org.checkerframework:checker-qual:' + checkerframeworkVersion
compileOnly 'org.jetbrains.kotlin:kotlin-annotations-jvm:' + kotlinAnnotationsVersion
+ androidTestImplementation 'androidx.test:rules:' + androidxTestRulesVersion
+ androidTestImplementation 'androidx.test:runner:' + androidxTestRunnerVersion
+ androidTestImplementation 'androidx.multidex:multidex:' + androidxMultidexVersion
+ // Emulator tests assume that an app-packaged version of cronet is
+ // available.
+ androidTestImplementation 'org.chromium.net:cronet-embedded:76.3809.111'
+ androidTestImplementation(project(modulePrefix + 'testutils'))
testImplementation project(modulePrefix + 'library')
testImplementation project(modulePrefix + 'testutils')
testImplementation 'com.squareup.okhttp3:mockwebserver:' + mockWebServerVersion
diff --git a/extensions/cronet/src/androidTest/AndroidManifest.xml b/extensions/cronet/src/androidTest/AndroidManifest.xml
new file mode 100644
index 0000000000..96e8e54f57
--- /dev/null
+++ b/extensions/cronet/src/androidTest/AndroidManifest.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/extensions/cronet/src/androidTest/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceContractTest.java b/extensions/cronet/src/androidTest/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceContractTest.java
new file mode 100644
index 0000000000..db7ea84eab
--- /dev/null
+++ b/extensions/cronet/src/androidTest/java/com/google/android/exoplayer2/ext/cronet/CronetDataSourceContractTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 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.google.android.exoplayer2.ext.cronet;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.net.Uri;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import com.google.android.exoplayer2.testutil.DataSourceContractTest;
+import com.google.android.exoplayer2.testutil.HttpDataSourceTestEnv;
+import com.google.android.exoplayer2.upstream.DataSource;
+import com.google.android.exoplayer2.upstream.HttpDataSource;
+import com.google.common.collect.ImmutableList;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import org.junit.After;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** {@link DataSource} contract tests for {@link CronetDataSource}. */
+@RunWith(AndroidJUnit4.class)
+public class CronetDataSourceContractTest extends DataSourceContractTest {
+
+ @Rule public HttpDataSourceTestEnv httpDataSourceTestEnv = new HttpDataSourceTestEnv();
+ private final ExecutorService executorService = Executors.newSingleThreadExecutor();
+
+ @After
+ public void tearDown() {
+ executorService.shutdown();
+ }
+
+ @Override
+ protected DataSource createDataSource() {
+ CronetEngineWrapper cronetEngineWrapper =
+ new CronetEngineWrapper(
+ ApplicationProvider.getApplicationContext(),
+ /* userAgent= */ "test-agent",
+ /* preferGMSCoreCronet= */ false);
+ assertThat(cronetEngineWrapper.getCronetEngineSource())
+ .isEqualTo(CronetEngineWrapper.SOURCE_NATIVE);
+ return new CronetDataSource.Factory(cronetEngineWrapper, executorService)
+ .setFallbackFactory(new InvalidDataSourceFactory())
+ .createDataSource();
+ }
+
+ @Override
+ protected ImmutableList getTestResources() {
+ return httpDataSourceTestEnv.getServedResources();
+ }
+
+ @Override
+ protected Uri getNotFoundUri() {
+ return Uri.parse(httpDataSourceTestEnv.getNonexistentUrl());
+ }
+
+ @Override
+ @Test
+ @Ignore
+ public void dataSpecWithLength_readExpectedRange() {}
+
+ @Override
+ @Test
+ @Ignore
+ public void dataSpecWithPositionAndLength_readExpectedRange() {}
+
+ /**
+ * An {@link HttpDataSource.Factory} that throws {@link UnsupportedOperationException} on every
+ * interaction.
+ */
+ private static class InvalidDataSourceFactory implements HttpDataSource.Factory {
+ @Override
+ public HttpDataSource createDataSource() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public HttpDataSource.RequestProperties getDefaultRequestProperties() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public HttpDataSource.Factory setDefaultRequestProperties(
+ Map defaultRequestProperties) {
+ throw new UnsupportedOperationException();
+ }
+ }
+}
diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/HttpDataSourceTestEnv.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/HttpDataSourceTestEnv.java
index bc4c96d908..fe15120260 100644
--- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/HttpDataSourceTestEnv.java
+++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/HttpDataSourceTestEnv.java
@@ -85,7 +85,6 @@ public class HttpDataSourceTestEnv extends ExternalResource {
createTestResource("range supported", RANGE_SUPPORTED),
createTestResource("range supported, length unknown", RANGE_SUPPORTED_LENGTH_UNKNOWN),
createTestResource("range not supported", RANGE_NOT_SUPPORTED),
- createTestResource("range not supported", RANGE_NOT_SUPPORTED),
createTestResource(
"range not supported, length unknown", RANGE_NOT_SUPPORTED_LENGTH_UNKNOWN),
createTestResource("gzip enabled", GZIP_ENABLED),