Consolidate NDK and APEX implementations

the NDK APIs are implemented in terms of the APEX APIs to
reduce the number of different implementations serving the
same fundamental purpose.

Bug: 137655431
Test: CtsGraphicsTestCases
Change-Id: Idc7b85403a7e546843b9c1d822acc0a1e740059a
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 0487e13..2dec4b3 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -223,97 +223,11 @@
     bitmap->getSkBitmap(outBitmap);
 }
 
-Bitmap& toBitmap(JNIEnv* env, jobject bitmap) {
-    SkASSERT(env);
-    SkASSERT(bitmap);
-    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
-    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
-    LocalScopedBitmap localBitmap(bitmapHandle);
-    return localBitmap->bitmap();
-}
-
 Bitmap& toBitmap(jlong bitmapHandle) {
     LocalScopedBitmap localBitmap(bitmapHandle);
     return localBitmap->bitmap();
 }
 
-void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info) {
-    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
-    LocalScopedBitmap localBitmap(bitmapHandle);
-
-    const SkImageInfo& imageInfo = localBitmap->info();
-    info->width = imageInfo.width();
-    info->height = imageInfo.height();
-    info->stride = localBitmap->rowBytes();
-    info->flags = 0;
-    switch (imageInfo.colorType()) {
-        case kN32_SkColorType:
-            info->format = ANDROID_BITMAP_FORMAT_RGBA_8888;
-            break;
-        case kRGB_565_SkColorType:
-            info->format = ANDROID_BITMAP_FORMAT_RGB_565;
-            break;
-        case kARGB_4444_SkColorType:
-            info->format = ANDROID_BITMAP_FORMAT_RGBA_4444;
-            break;
-        case kAlpha_8_SkColorType:
-            info->format = ANDROID_BITMAP_FORMAT_A_8;
-            break;
-        case kRGBA_F16_SkColorType:
-            info->format = ANDROID_BITMAP_FORMAT_RGBA_F16;
-            break;
-        default:
-            info->format = ANDROID_BITMAP_FORMAT_NONE;
-            break;
-    }
-    switch (imageInfo.alphaType()) {
-        case kUnknown_SkAlphaType:
-            LOG_ALWAYS_FATAL("Bitmap has no alpha type");
-            break;
-        case kOpaque_SkAlphaType:
-            info->flags |= ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
-            break;
-        case kPremul_SkAlphaType:
-            info->flags |= ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
-            break;
-        case kUnpremul_SkAlphaType:
-            info->flags |= ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL;
-            break;
-    }
-}
-
-void* lockPixels(JNIEnv* env, jobject bitmap) {
-    SkASSERT(env);
-    SkASSERT(bitmap);
-    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
-    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
-
-    LocalScopedBitmap localBitmap(bitmapHandle);
-    if (!localBitmap->valid()) return nullptr;
-
-    SkPixelRef& pixelRef = localBitmap->bitmap();
-    if (!pixelRef.pixels()) {
-        return nullptr;
-    }
-    pixelRef.ref();
-    return pixelRef.pixels();
-}
-
-bool unlockPixels(JNIEnv* env, jobject bitmap) {
-    SkASSERT(env);
-    SkASSERT(bitmap);
-    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
-    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
-
-    LocalScopedBitmap localBitmap(bitmapHandle);
-    if (!localBitmap->valid()) return false;
-
-    SkPixelRef& pixelRef = localBitmap->bitmap();
-    pixelRef.notifyPixelsChanged();
-    pixelRef.unref();
-    return true;
-}
-
 } // namespace bitmap
 
 } // namespace android
@@ -321,6 +235,27 @@
 using namespace android;
 using namespace android::bitmap;
 
+Bitmap* GraphicsJNI::getNativeBitmap(JNIEnv* env, jobject bitmap) {
+    SkASSERT(env);
+    SkASSERT(bitmap);
+    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
+    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
+    LocalScopedBitmap localBitmap(bitmapHandle);
+    return localBitmap.valid() ? &localBitmap->bitmap() : nullptr;
+}
+
+SkImageInfo GraphicsJNI::getBitmapInfo(JNIEnv* env, jobject bitmap, uint32_t* outRowBytes) {
+    SkASSERT(env);
+    SkASSERT(bitmap);
+    SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
+    jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
+    LocalScopedBitmap localBitmap(bitmapHandle);
+    if (outRowBytes) {
+        *outRowBytes = localBitmap->rowBytes();
+    }
+    return localBitmap->info();
+}
+
 bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
         int x, int y, int width, int height, SkBitmap* dstBitmap) {
     const jint* array = env->GetIntArrayElements(srcColors, NULL);
diff --git a/core/jni/android/graphics/Bitmap.h b/core/jni/android/graphics/Bitmap.h
index 59adbb2..73eca3a 100644
--- a/core/jni/android/graphics/Bitmap.h
+++ b/core/jni/android/graphics/Bitmap.h
@@ -38,17 +38,8 @@
             int bitmapCreateFlags, jbyteArray ninePatchChunk = nullptr,
             jobject ninePatchInsets = nullptr, int density = -1);
 
-
-Bitmap& toBitmap(JNIEnv* env, jobject bitmap);
 Bitmap& toBitmap(jlong bitmapHandle);
 
-// NDK access
-void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info);
-// Returns a pointer to the pixels or nullptr if the bitmap is not valid
-void* lockPixels(JNIEnv* env, jobject bitmap);
-// Returns true if unlocked, false if the bitmap is no longer valid (destroyed)
-bool unlockPixels(JNIEnv* env, jobject bitmap);
-
 /** Reinitialize a bitmap. bitmap must already have its SkAlphaType set in
     sync with isPremultiplied
 */
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index bc1cc09..aa209cb 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -342,10 +342,6 @@
     return static_cast<SkColorType>(gConfig2ColorType[legacyConfig]);
 }
 
-void GraphicsJNI::getSkBitmap(JNIEnv* env, jobject bitmap, SkBitmap* outBitmap) {
-    bitmap::toBitmap(env, bitmap).getSkBitmap(outBitmap);
-}
-
 AndroidBitmapFormat GraphicsJNI::getFormatFromConfig(JNIEnv* env, jobject jconfig) {
     ALOG_ASSERT(env);
     if (NULL == jconfig) {
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 6e7d9e7..99034ed 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -61,7 +61,8 @@
     static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
 
     static android::Canvas* getNativeCanvas(JNIEnv*, jobject canvas);
-    static void getSkBitmap(JNIEnv*, jobject bitmap, SkBitmap* outBitmap);
+    static android::Bitmap* getNativeBitmap(JNIEnv*, jobject bitmap);
+    static SkImageInfo getBitmapInfo(JNIEnv*, jobject bitmap, uint32_t* outRowBytes);
     static SkRegion* getNativeRegion(JNIEnv*, jobject region);
 
     /*
diff --git a/core/jni/android/graphics/apex/android_bitmap.cpp b/core/jni/android/graphics/apex/android_bitmap.cpp
index a328def..90cc986 100644
--- a/core/jni/android/graphics/apex/android_bitmap.cpp
+++ b/core/jni/android/graphics/apex/android_bitmap.cpp
@@ -14,19 +14,25 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "Bitmap"
+#include <log/log.h>
+
 #include "android/graphics/bitmap.h"
-#include "Bitmap.h"
 #include "TypeCast.h"
 #include "GraphicsJNI.h"
 
+#include <GraphicsJNI.h>
 #include <hwui/Bitmap.h>
 
 using namespace android;
 
 ABitmap* ABitmap_acquireBitmapFromJava(JNIEnv* env, jobject bitmapObj) {
-    Bitmap& bitmap = android::bitmap::toBitmap(env, bitmapObj);
-    bitmap.ref();
-    return TypeCast::toABitmap(&bitmap);
+    Bitmap* bitmap = GraphicsJNI::getNativeBitmap(env, bitmapObj);
+    if (bitmap) {
+        bitmap->ref();
+        return TypeCast::toABitmap(bitmap);
+    }
+    return nullptr;
 }
 
 void ABitmap_acquireRef(ABitmap* bitmap) {
@@ -37,8 +43,8 @@
     SkSafeUnref(TypeCast::toBitmap(bitmap));
 }
 
-static AndroidBitmapFormat getFormat(Bitmap* bitmap) {
-    switch (bitmap->colorType()) {
+static AndroidBitmapFormat getFormat(const SkImageInfo& info) {
+    switch (info.colorType()) {
         case kN32_SkColorType:
             return ANDROID_BITMAP_FORMAT_RGBA_8888;
         case kRGB_565_SkColorType:
@@ -71,6 +77,20 @@
     }
 }
 
+static uint32_t getInfoFlags(const SkImageInfo& info) {
+    switch (info.alphaType()) {
+        case kUnknown_SkAlphaType:
+            LOG_ALWAYS_FATAL("Bitmap has no alpha type");
+            break;
+        case kOpaque_SkAlphaType:
+            return ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
+        case kPremul_SkAlphaType:
+            return ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
+        case kUnpremul_SkAlphaType:
+            return ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL;
+    }
+}
+
 ABitmap* ABitmap_copy(ABitmap* srcBitmapHandle, AndroidBitmapFormat dstFormat) {
     SkColorType dstColorType = getColorType(dstFormat);
     if (srcBitmapHandle && dstColorType != kUnknown_SkColorType) {
@@ -87,15 +107,25 @@
     return nullptr;
 }
 
+static AndroidBitmapInfo getInfo(const SkImageInfo& imageInfo, uint32_t rowBytes) {
+    AndroidBitmapInfo info;
+    info.width = imageInfo.width();
+    info.height = imageInfo.height();
+    info.stride = rowBytes;
+    info.format = getFormat(imageInfo);
+    info.flags = getInfoFlags(imageInfo);
+    return info;
+}
+
 AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmapHandle) {
     Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle);
+    return getInfo(bitmap->info(), bitmap->rowBytes());
+}
 
-    AndroidBitmapInfo info;
-    info.width = bitmap->width();
-    info.height = bitmap->height();
-    info.stride = bitmap->rowBytes();
-    info.format = getFormat(bitmap);
-    return info;
+AndroidBitmapInfo ABitmap_getInfoFromJava(JNIEnv* env, jobject bitmapObj) {
+    uint32_t rowBytes = 0;
+    SkImageInfo imageInfo = GraphicsJNI::getBitmapInfo(env, bitmapObj, &rowBytes);
+    return getInfo(imageInfo, rowBytes);
 }
 
 void* ABitmap_getPixels(ABitmap* bitmapHandle) {
@@ -107,9 +137,17 @@
 }
 
 AndroidBitmapFormat ABitmapConfig_getFormatFromConfig(JNIEnv* env, jobject bitmapConfigObj) {
-  return GraphicsJNI::getFormatFromConfig(env, bitmapConfigObj);
+    return GraphicsJNI::getFormatFromConfig(env, bitmapConfigObj);
 }
 
 jobject ABitmapConfig_getConfigFromFormat(JNIEnv* env, AndroidBitmapFormat format) {
-  return GraphicsJNI::getConfigFromFormat(env, format);
+    return GraphicsJNI::getConfigFromFormat(env, format);
+}
+
+void ABitmap_notifyPixelsChanged(ABitmap* bitmapHandle) {
+    Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle);
+    if (bitmap->isImmutable()) {
+        ALOGE("Attempting to modify an immutable Bitmap!");
+    }
+    return bitmap->notifyPixelsChanged();
 }
diff --git a/core/jni/android/graphics/apex/include/android/graphics/bitmap.h b/core/jni/android/graphics/apex/include/android/graphics/bitmap.h
index dea5517..f231eed 100644
--- a/core/jni/android/graphics/apex/include/android/graphics/bitmap.h
+++ b/core/jni/android/graphics/apex/include/android/graphics/bitmap.h
@@ -27,6 +27,20 @@
  */
 typedef struct ABitmap ABitmap;
 
+/**
+ * Retrieve bitmapInfo for the provided java bitmap even if it has been recycled.  In the case of a
+ * recycled bitmap the values contained in the bitmap before it was recycled are returned.
+ *
+ * NOTE: This API does not need to remain as an APEX API if/when we pull libjnigraphics into the
+ *       UI module.
+ */
+AndroidBitmapInfo ABitmap_getInfoFromJava(JNIEnv* env, jobject bitmapObj);
+
+/**
+ *
+ * @return ptr to an opaque handle to the native bitmap or null if the java bitmap has been recycled
+ *         or does not exist.
+ */
 ABitmap* ABitmap_acquireBitmapFromJava(JNIEnv* env, jobject bitmapObj);
 
 ABitmap* ABitmap_copy(ABitmap* srcBitmap, AndroidBitmapFormat dstFormat);
@@ -37,6 +51,7 @@
 AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmap);
 
 void* ABitmap_getPixels(ABitmap* bitmap);
+void ABitmap_notifyPixelsChanged(ABitmap* bitmap);
 
 AndroidBitmapFormat ABitmapConfig_getFormatFromConfig(JNIEnv* env, jobject bitmapConfigObj);
 jobject ABitmapConfig_getConfigFromFormat(JNIEnv* env, AndroidBitmapFormat format);
@@ -88,10 +103,12 @@
             mBitmap = nullptr;
         }
 
-        const ABitmap* get() const { return mBitmap; }
+        ABitmap* get() const { return mBitmap; }
 
         AndroidBitmapInfo getInfo() const { return ABitmap_getInfo(mBitmap); }
         void* getPixels() const { return ABitmap_getPixels(mBitmap); }
+        void notifyPixelsChanged() const { ABitmap_notifyPixelsChanged(mBitmap); }
+
     private:
         // takes ownership of the provided ABitmap
         Bitmap(ABitmap* bitmap) : mBitmap(bitmap) {}
diff --git a/native/graphics/jni/bitmap.cpp b/native/graphics/jni/bitmap.cpp
index ff14832..1aebeaf 100644
--- a/native/graphics/jni/bitmap.cpp
+++ b/native/graphics/jni/bitmap.cpp
@@ -15,7 +15,7 @@
  */
 
 #include <android/bitmap.h>
-#include <android/graphics/Bitmap.h>
+#include <android/graphics/bitmap.h>
 
 int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
                           AndroidBitmapInfo* info) {
@@ -24,7 +24,7 @@
     }
 
     if (info) {
-        android::bitmap::imageInfo(env, jbitmap, info);
+        *info = ABitmap_getInfoFromJava(env, jbitmap);
     }
     return ANDROID_BITMAP_RESULT_SUCCESS;
 }
@@ -34,11 +34,15 @@
         return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
     }
 
-    void* addr = android::bitmap::lockPixels(env, jbitmap);
+    android::graphics::Bitmap bitmap(env, jbitmap);
+    void* addr = bitmap.isValid() ? bitmap.getPixels() : nullptr;
+
     if (!addr) {
         return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
     }
 
+    ABitmap_acquireRef(bitmap.get());
+
     if (addrPtr) {
         *addrPtr = addr;
     }
@@ -50,9 +54,13 @@
         return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
     }
 
-    bool unlocked = android::bitmap::unlockPixels(env, jbitmap);
-    if (!unlocked) {
+    android::graphics::Bitmap bitmap(env, jbitmap);
+
+    if (!bitmap.isValid()) {
         return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
     }
+
+    bitmap.notifyPixelsChanged();
+    ABitmap_releaseRef(bitmap.get());
     return ANDROID_BITMAP_RESULT_SUCCESS;
 }