android_jni: Add instrumented tests
These tests will run on a real android device or an emulator and
will act as a sanity check for the JNI bindings.
diff --git a/android_jni/README.md b/android_jni/README.md
index 92f0071..9b8cfd9 100644
--- a/android_jni/README.md
+++ b/android_jni/README.md
@@ -52,6 +52,25 @@
The instructions on how to add the AAR package as a dependency to your Android project can be found [here](https://developer.android.com/studio/projects/android-library#psd-add-aar-jar-dependency).
+## Running Instrumented Tests
+
+Step 1 - Build the library
+
+Make sure to build the library by following the steps under
+[Generate the AAR package](#generate-the-aar-package) section above.
+
+Step 2 - Set up a device/emulator
+
+Make sure that a device or an emulator has been set up and is available via
+`adb`.
+
+Step 3 - Run the tests
+
+```
+$ cd android_jni
+$ ./gradlew connectedAndroidTest
+```
+
## Using Android Studio
The entire android_jni directory can be imported as a project into Android Studio.
diff --git a/android_jni/avifandroidjni/build.gradle b/android_jni/avifandroidjni/build.gradle
index 707a32d..956528c 100644
--- a/android_jni/avifandroidjni/build.gradle
+++ b/android_jni/avifandroidjni/build.gradle
@@ -10,6 +10,7 @@
targetSdk 30
versionCode 1
versionName "1.0"
+ testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
}
buildTypes {
@@ -33,4 +34,8 @@
}
dependencies {
-}
\ No newline at end of file
+ androidTestImplementation 'junit:junit:4.+'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.5'
+ androidTestImplementation 'com.google.truth:truth:1.1.3'
+ androidTestImplementation 'androidx.test:runner:1.5.2'
+}
diff --git a/android_jni/avifandroidjni/src/androidTest/assets/README b/android_jni/avifandroidjni/src/androidTest/assets/README
new file mode 100644
index 0000000..2307913
--- /dev/null
+++ b/android_jni/avifandroidjni/src/androidTest/assets/README
@@ -0,0 +1,7 @@
+This file describes the sources of files in this directory.
+
+* Sub-Directory: avif
+ Description: Images used for testing still AVIF decoding.
+ Source: https://github.com/AOMediaCodec/av1-avif/tree/master/testFiles/Link-U
+ Filter: Only a subset of fox* files.
+ Git Hash: 77bd20d
diff --git a/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile0.10bpc.yuv420.avif b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile0.10bpc.yuv420.avif
new file mode 100644
index 0000000..025c185
--- /dev/null
+++ b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile0.10bpc.yuv420.avif
Binary files differ
diff --git a/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile0.10bpc.yuv420.monochrome.avif b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile0.10bpc.yuv420.monochrome.avif
new file mode 100644
index 0000000..5b8a127
--- /dev/null
+++ b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile0.10bpc.yuv420.monochrome.avif
Binary files differ
diff --git a/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile0.8bpc.yuv420.avif b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile0.8bpc.yuv420.avif
new file mode 100644
index 0000000..cf23e6e
--- /dev/null
+++ b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile0.8bpc.yuv420.avif
Binary files differ
diff --git a/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile0.8bpc.yuv420.monochrome.avif b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile0.8bpc.yuv420.monochrome.avif
new file mode 100644
index 0000000..57ca3f1
--- /dev/null
+++ b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile0.8bpc.yuv420.monochrome.avif
Binary files differ
diff --git a/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile1.10bpc.yuv444.avif b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile1.10bpc.yuv444.avif
new file mode 100644
index 0000000..132695e
--- /dev/null
+++ b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile1.10bpc.yuv444.avif
Binary files differ
diff --git a/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile1.8bpc.yuv444.avif b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile1.8bpc.yuv444.avif
new file mode 100644
index 0000000..ba1c5ff
--- /dev/null
+++ b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile1.8bpc.yuv444.avif
Binary files differ
diff --git a/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile2.10bpc.yuv422.avif b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile2.10bpc.yuv422.avif
new file mode 100644
index 0000000..6143168
--- /dev/null
+++ b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile2.10bpc.yuv422.avif
Binary files differ
diff --git a/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile2.12bpc.yuv420.avif b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile2.12bpc.yuv420.avif
new file mode 100644
index 0000000..4299cf7
--- /dev/null
+++ b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile2.12bpc.yuv420.avif
Binary files differ
diff --git a/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile2.12bpc.yuv420.monochrome.avif b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile2.12bpc.yuv420.monochrome.avif
new file mode 100644
index 0000000..34293c2
--- /dev/null
+++ b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile2.12bpc.yuv420.monochrome.avif
Binary files differ
diff --git a/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile2.12bpc.yuv422.avif b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile2.12bpc.yuv422.avif
new file mode 100644
index 0000000..2e69ec6
--- /dev/null
+++ b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile2.12bpc.yuv422.avif
Binary files differ
diff --git a/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile2.12bpc.yuv444.avif b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile2.12bpc.yuv444.avif
new file mode 100644
index 0000000..03c3599
--- /dev/null
+++ b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile2.12bpc.yuv444.avif
Binary files differ
diff --git a/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile2.8bpc.yuv422.avif b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile2.8bpc.yuv422.avif
new file mode 100644
index 0000000..7f3a788
--- /dev/null
+++ b/android_jni/avifandroidjni/src/androidTest/assets/avif/fox.profile2.8bpc.yuv422.avif
Binary files differ
diff --git a/android_jni/avifandroidjni/src/androidTest/java/org/aomedia/avif/android/StillImageTest.java b/android_jni/avifandroidjni/src/androidTest/java/org/aomedia/avif/android/StillImageTest.java
new file mode 100644
index 0000000..6d92493
--- /dev/null
+++ b/android_jni/avifandroidjni/src/androidTest/java/org/aomedia/avif/android/StillImageTest.java
@@ -0,0 +1,84 @@
+package org.aomedia.avif.android;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import androidx.test.platform.app.InstrumentationRegistry;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.aomedia.avif.android.AvifDecoder.Info;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+/** Instrumentation tests for the libavif JNI API, which will execute on an Android device. */
+@RunWith(Parameterized.class)
+public class StillImageTest {
+
+ private static final String ASSET_DIRECTORY = "avif";
+
+ @Parameters
+ public static List<Object[]> data() throws IOException {
+ ArrayList<Object[]> list = new ArrayList<>();
+ for (String asset : getAssetFiles(ASSET_DIRECTORY)) {
+ String assetPath = Paths.get(ASSET_DIRECTORY, asset).toString();
+ // Test ARGB_8888 for all files.
+ list.add(new Object[] {Config.ARGB_8888, assetPath});
+ // For 8bpc files, test only RGB_565. For other files, test only RGBA_F16.
+ Config testConfig = assetPath.contains("8bpc") ? Config.RGB_565 : Config.RGBA_F16;
+ list.add(new Object[] {testConfig, assetPath});
+ }
+ return list;
+ }
+
+ @Parameter(0)
+ public Bitmap.Config config;
+
+ @Parameter(1)
+ public String assetPath;
+
+ @Test
+ public void testIsAvifImageReturnsTrue() throws IOException {
+ ByteBuffer buffer = getBuffer();
+ assertThat(buffer).isNotNull();
+ assertThat(AvifDecoder.isAvifImage(buffer)).isTrue();
+ }
+
+ @Test
+ public void testAvifDecode() throws IOException {
+ ByteBuffer buffer = getBuffer();
+ assertThat(buffer).isNotNull();
+ Info info = new Info();
+ assertThat(AvifDecoder.getInfo(buffer, buffer.remaining(), info)).isTrue();
+ assertThat(info.width).isGreaterThan(0);
+ assertThat(info.height).isGreaterThan(0);
+ assertThat(info.depth).isAnyOf(8, 10, 12);
+ Bitmap bitmap = Bitmap.createBitmap(info.width, info.height, config);
+ assertThat(bitmap).isNotNull();
+ assertThat(AvifDecoder.decode(buffer, buffer.remaining(), bitmap)).isTrue();
+ }
+
+ private ByteBuffer getBuffer() throws IOException {
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ InputStream is = context.getAssets().open(assetPath);
+ ByteBuffer buffer = ByteBuffer.allocateDirect(is.available());
+ Channels.newChannel(is).read(buffer);
+ buffer.rewind();
+ return buffer;
+ }
+
+ private static List<String> getAssetFiles(String directoryName) throws IOException {
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ return Arrays.asList(context.getAssets().list(directoryName));
+ }
+}