Add stride support to JPEG/R java API

Bug: 299202809
Test: YuvImageTest.java
Change-Id: Ifb1500114c9c212eb145c8538a74b46066fd5db7
diff --git a/libs/hwui/jni/YuvToJpegEncoder.cpp b/libs/hwui/jni/YuvToJpegEncoder.cpp
index 8c5cc30..c55066a 100644
--- a/libs/hwui/jni/YuvToJpegEncoder.cpp
+++ b/libs/hwui/jni/YuvToJpegEncoder.cpp
@@ -332,7 +332,8 @@
 
 bool P010Yuv420ToJpegREncoder::encode(JNIEnv* env,
         SkWStream* stream, void* hdr, int hdrColorSpace, void* sdr, int sdrColorSpace,
-        int width, int height, int jpegQuality, ScopedByteArrayRO* jExif) {
+        int width, int height, int jpegQuality, ScopedByteArrayRO* jExif,
+        ScopedIntArrayRO* jHdrStrides, ScopedIntArrayRO* jSdrStrides) {
     // Check SDR color space. Now we only support SRGB transfer function
     if ((sdrColorSpace & ADataSpace::TRANSFER_MASK) !=  ADataSpace::TRANSFER_SRGB) {
         jclass IllegalArgumentException = env->FindClass("java/lang/IllegalArgumentException");
@@ -340,6 +341,19 @@
             "The requested SDR color space is not supported. Transfer function must be SRGB");
         return false;
     }
+    // Check HDR and SDR strides length.
+    // HDR is YCBCR_P010 color format, and its strides length must be 2 (Y, chroma (Cb, Cr)).
+    // SDR is YUV_420_888 color format, and its strides length must be 3 (Y, Cb, Cr).
+    if (jHdrStrides->size() != 2) {
+        jclass IllegalArgumentException = env->FindClass("java/lang/IllegalArgumentException");
+        env->ThrowNew(IllegalArgumentException, "HDR stride length must be 2.");
+        return false;
+    }
+    if (jSdrStrides->size() != 3) {
+        jclass IllegalArgumentException = env->FindClass("java/lang/IllegalArgumentException");
+        env->ThrowNew(IllegalArgumentException, "SDR stride length must be 3.");
+        return false;
+    }
 
     ultrahdr_color_gamut hdrColorGamut = findColorGamut(env, hdrColorSpace);
     ultrahdr_color_gamut sdrColorGamut = findColorGamut(env, sdrColorSpace);
@@ -351,18 +365,26 @@
         return false;
     }
 
+    const int* hdrStrides = reinterpret_cast<const int*>(jHdrStrides->get());
+    const int* sdrStrides = reinterpret_cast<const int*>(jSdrStrides->get());
+
     JpegR jpegREncoder;
 
     jpegr_uncompressed_struct p010;
     p010.data = hdr;
     p010.width = width;
     p010.height = height;
+    // Divided by 2 because unit in libultrader is pixel and in YuvImage it is byte.
+    p010.luma_stride = (hdrStrides[0] + 1) / 2;
+    p010.chroma_stride = (hdrStrides[1] + 1) / 2;
     p010.colorGamut = hdrColorGamut;
 
     jpegr_uncompressed_struct yuv420;
     yuv420.data = sdr;
     yuv420.width = width;
     yuv420.height = height;
+    yuv420.luma_stride = sdrStrides[0];
+    yuv420.chroma_stride = sdrStrides[1];
     yuv420.colorGamut = sdrColorGamut;
 
     jpegr_exif_struct exif;
@@ -420,22 +442,27 @@
 static jboolean YuvImage_compressToJpegR(JNIEnv* env, jobject, jbyteArray inHdr,
         jint hdrColorSpace, jbyteArray inSdr, jint sdrColorSpace,
         jint width, jint height, jint quality, jobject jstream,
-        jbyteArray jstorage, jbyteArray jExif) {
+        jbyteArray jstorage, jbyteArray jExif,
+        jintArray jHdrStrides, jintArray jSdrStrides) {
     jbyte* hdr = env->GetByteArrayElements(inHdr, NULL);
     jbyte* sdr = env->GetByteArrayElements(inSdr, NULL);
     ScopedByteArrayRO exif(env, jExif);
+    ScopedIntArrayRO hdrStrides(env, jHdrStrides);
+    ScopedIntArrayRO sdrStrides(env, jSdrStrides);
 
     SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
     P010Yuv420ToJpegREncoder encoder;
 
     jboolean result = JNI_FALSE;
     if (encoder.encode(env, strm, hdr, hdrColorSpace, sdr, sdrColorSpace,
-                       width, height, quality, &exif)) {
+                       width, height, quality, &exif,
+                       &hdrStrides, &sdrStrides)) {
         result = JNI_TRUE;
     }
 
     env->ReleaseByteArrayElements(inHdr, hdr, 0);
     env->ReleaseByteArrayElements(inSdr, sdr, 0);
+
     delete strm;
     return result;
 }
@@ -444,7 +471,7 @@
 static const JNINativeMethod gYuvImageMethods[] = {
     {   "nativeCompressToJpeg",  "([BIII[I[IILjava/io/OutputStream;[B)Z",
         (void*)YuvImage_compressToJpeg },
-    {   "nativeCompressToJpegR",  "([BI[BIIIILjava/io/OutputStream;[B[B)Z",
+    {   "nativeCompressToJpegR",  "([BI[BIIIILjava/io/OutputStream;[B[B[I[I)Z",
         (void*)YuvImage_compressToJpegR }
 };