frameworks/av: Add AImage::getTransform to public API

Test: CTS test added.

Bug: 395866696
Flag: EXEMPT NDK
Change-Id: I7c46883aa63865582ff2ba24a07abdefec802199
diff --git a/media/ndk/NdkImage.cpp b/media/ndk/NdkImage.cpp
index c2093ac..06ec967 100644
--- a/media/ndk/NdkImage.cpp
+++ b/media/ndk/NdkImage.cpp
@@ -665,6 +665,17 @@
     return AMEDIA_OK;
 }
 
+media_status_t
+AImage::getTransform(/*out*/int32_t* transform) const {
+    if (mBuffer == nullptr || mBuffer->mGraphicBuffer == nullptr) {
+        ALOGE("%s: AImage %p has no buffer.", __FUNCTION__, this);
+        return AMEDIA_ERROR_INVALID_OBJECT;
+    }
+
+    *transform = mBuffer->mTransform;
+    return AMEDIA_OK;
+}
+
 EXPORT
 void AImage_delete(AImage* image) {
     ALOGV("%s", __FUNCTION__);
@@ -845,4 +856,16 @@
         return AMEDIA_ERROR_INVALID_PARAMETER;
     }
     return image->getDataSpace((android_dataspace*)(dataSpace));
+}
+
+EXPORT
+media_status_t AImage_getTransform(
+    AImage* image, /*out*/int32_t* transform) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (image == nullptr || transform == nullptr) {
+        ALOGE("%s: bad argument. image %p transform %p", __FUNCTION__, image, transform);
+        return AMEDIA_ERROR_INVALID_PARAMETER;
+    }
+    return image->getTransform(transform);
 }
\ No newline at end of file
diff --git a/media/ndk/NdkImagePriv.h b/media/ndk/NdkImagePriv.h
index dc10a6a..6d3d272 100644
--- a/media/ndk/NdkImagePriv.h
+++ b/media/ndk/NdkImagePriv.h
@@ -83,6 +83,7 @@
     media_status_t getPlaneData(int planeIdx,/*out*/uint8_t** data, /*out*/int* dataLength) const;
     media_status_t getHardwareBuffer(/*out*/AHardwareBuffer** buffer) const;
     media_status_t getDataSpace(/*out*/android_dataspace* dataSpace) const;
+    media_status_t getTransform(/*out*/int32_t* transform) const;
 
   private:
     // AImage should be deleted through free() API.
diff --git a/media/ndk/include/media/NdkImage.h b/media/ndk/include/media/NdkImage.h
index 76270d3..a81d48e 100644
--- a/media/ndk/include/media/NdkImage.h
+++ b/media/ndk/include/media/NdkImage.h
@@ -575,7 +575,7 @@
  *
  * @param image The {@link AImage} to be deleted.
  */
-void AImage_delete(AImage* image) __INTRODUCED_IN(24);
+void AImage_delete(AImage* _Nullable image) __INTRODUCED_IN(24);
 
 /**
  * Query the width of the input {@link AImage}.
@@ -591,7 +591,8 @@
  *         <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
  *                 image has been deleted.</li></ul>
  */
-media_status_t AImage_getWidth(const AImage* image, /*out*/int32_t* width) __INTRODUCED_IN(24);
+media_status_t AImage_getWidth(const AImage* _Nonnull image, /*out*/int32_t* _Nonnull width)
+                               __INTRODUCED_IN(24);
 
 /**
  * Query the height of the input {@link AImage}.
@@ -607,7 +608,8 @@
  *         <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
  *                 image has been deleted.</li></ul>
  */
-media_status_t AImage_getHeight(const AImage* image, /*out*/int32_t* height) __INTRODUCED_IN(24);
+media_status_t AImage_getHeight(const AImage* _Nonnull image, /*out*/int32_t* _Nonnull height)
+                                __INTRODUCED_IN(24);
 
 /**
  * Query the format of the input {@link AImage}.
@@ -625,7 +627,8 @@
  *         <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
  *                 image has been deleted.</li></ul>
  */
-media_status_t AImage_getFormat(const AImage* image, /*out*/int32_t* format) __INTRODUCED_IN(24);
+media_status_t AImage_getFormat(const AImage* _Nonnull image, /*out*/int32_t* _Nonnull format)
+                                __INTRODUCED_IN(24);
 
 /**
  * Query the cropped rectangle of the input {@link AImage}.
@@ -644,7 +647,8 @@
  *         <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
  *                 image has been deleted.</li></ul>
  */
-media_status_t AImage_getCropRect(const AImage* image, /*out*/AImageCropRect* rect) __INTRODUCED_IN(24);
+media_status_t AImage_getCropRect(const AImage* _Nonnull image,
+                                  /*out*/AImageCropRect* _Nonnull rect) __INTRODUCED_IN(24);
 
 /**
  * Query the timestamp of the input {@link AImage}.
@@ -670,7 +674,8 @@
  *         <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
  *                 image has been deleted.</li></ul>
  */
-media_status_t AImage_getTimestamp(const AImage* image, /*out*/int64_t* timestampNs) __INTRODUCED_IN(24);
+media_status_t AImage_getTimestamp(const AImage* _Nonnull image,
+                                   /*out*/int64_t* _Nonnull timestampNs) __INTRODUCED_IN(24);
 
 /**
  * Query the number of planes of the input {@link AImage}.
@@ -690,7 +695,8 @@
  *         <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
  *                 image has been deleted.</li></ul>
  */
-media_status_t AImage_getNumberOfPlanes(const AImage* image, /*out*/int32_t* numPlanes) __INTRODUCED_IN(24);
+media_status_t AImage_getNumberOfPlanes(const AImage* _Nonnull image,
+                                        /*out*/int32_t* _Nonnull numPlanes) __INTRODUCED_IN(24);
 
 /**
  * Query the pixel stride of the input {@link AImage}.
@@ -719,8 +725,8 @@
  *         <li>{@link AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE} if the {@link AImage} cannot be locked
  *                 for CPU access.</li></ul>
  */
-media_status_t AImage_getPlanePixelStride(
-        const AImage* image, int planeIdx, /*out*/int32_t* pixelStride) __INTRODUCED_IN(24);
+media_status_t AImage_getPlanePixelStride(const AImage* _Nonnull image, int planeIdx,
+                                          /*out*/int32_t* _Nonnull pixelStride) __INTRODUCED_IN(24);
 
 /**
  * Query the row stride of the input {@link AImage}.
@@ -749,7 +755,8 @@
  *                 for CPU access.</li></ul>
  */
 media_status_t AImage_getPlaneRowStride(
-        const AImage* image, int planeIdx, /*out*/int32_t* rowStride) __INTRODUCED_IN(24);
+        const AImage* _Nonnull image, int planeIdx, /*out*/int32_t* _Nonnull rowStride)
+        __INTRODUCED_IN(24);
 
 /**
  * Get the data pointer of the input image for direct application access.
@@ -775,8 +782,8 @@
  *                 for CPU access.</li></ul>
  */
 media_status_t AImage_getPlaneData(
-        const AImage* image, int planeIdx,
-        /*out*/uint8_t** data, /*out*/int* dataLength) __INTRODUCED_IN(24);
+        const AImage* _Nonnull image, int planeIdx, /*out*/uint8_t* _Nullable * _Nonnull data,
+        /*out*/int* _Nonnull dataLength) __INTRODUCED_IN(24);
 
 /**
  * Return the image back the the system and delete the AImage object from memory asynchronously.
@@ -794,7 +801,7 @@
  *
  * @see sync.h
  */
-void AImage_deleteAsync(AImage* image, int releaseFenceFd) __INTRODUCED_IN(26);
+void AImage_deleteAsync(AImage* _Nullable image, int releaseFenceFd) __INTRODUCED_IN(26);
 
 /**
  * Get the hardware buffer handle of the input image intended for GPU and/or hardware access.
@@ -824,7 +831,9 @@
  *
  * @see AImageReader_ImageCallback
  */
-media_status_t AImage_getHardwareBuffer(const AImage* image, /*out*/AHardwareBuffer** buffer) __INTRODUCED_IN(26);
+media_status_t AImage_getHardwareBuffer(
+        const AImage* _Nonnull image, /*out*/AHardwareBuffer* _Nullable * _Nonnull buffer)
+        __INTRODUCED_IN(26);
 
 /**
  * Query the dataspace of the input {@link AImage}.
@@ -842,8 +851,36 @@
  *         <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
  *                 image has been deleted.</li></ul>
  */
-media_status_t AImage_getDataSpace(const AImage* image,
-                                   /*out*/int32_t* dataSpace) __INTRODUCED_IN(34);
+media_status_t AImage_getDataSpace(const AImage* _Nonnull image,
+                                   /*out*/int32_t* _Nonnull dataSpace) __INTRODUCED_IN(34);
+
+/**
+ * Query the transform of the input {@link AImage}.
+ *
+ * <p>getTransform retrieves the image transform associated with the {@link AImage}
+ * set by the most recent call to updateTexImage.</p>
+ *
+ * <p>This transform can be a combination of horizontal mirror, vertical
+ * mirror, and clockwise 90 degree rotation. See {@link ANativeWindowTransform}
+ * for more details. This transform is necessary to compensate for transforms
+ * that the stream content producer may implicitly apply to the content. By
+ * forcing users of an AImage to apply this transform we avoid performing an
+ * extracopy of the data that would be needed to hide the transform from the user.</p>
+ *
+ * Available since API level 37.
+ *
+ * @param image the {@link AImage} of interest.
+ * @param transform the transform of the image will be filled here if the method call
+ *         succeeds.
+ *
+ * @return <ul>
+ *         <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ *         <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if image is NULL.</li>
+ *         <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader}
+ * generated this image has been deleted.</li></ul>
+ */
+media_status_t AImage_getTransform(AImage* _Nonnull image,
+                                  /*out*/int32_t* _Nonnull transform) __INTRODUCED_IN(37);
 
 __END_DECLS
 
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index a141b64..50c4f3e 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -57,6 +57,7 @@
     AImage_getPlanePixelStride; # introduced=24
     AImage_getPlaneRowStride; # introduced=24
     AImage_getTimestamp; # introduced=24
+    AImage_getTransform; # introduced=37
     AImage_getWidth; # introduced=24
     AMEDIACODEC_KEY_HDR10_PLUS_INFO; # var introduced=31
     AMEDIACODEC_KEY_LOW_LATENCY; # var introduced=31