Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9ca5bbe3 authored by Derek Sollenberger's avatar Derek Sollenberger
Browse files

Create C API for accessing android.graphics.Bitmap in native code.

Restrict access to SkBitmap for libandroid_runtime.so to be only within
the boundaries of the graphics module.

Test: CtsUiRenderingTestCases
Bug: 137655431
Change-Id: I4d0ea227e91d22068966513c4e3a55021b9e924f
parent 00f6e5d2
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -58,6 +58,8 @@ cc_library_shared {

    whole_static_libs: ["libandroid_graphics"],

    export_static_lib_headers: ["libandroid_graphics"],

    shared_libs: [
        "libbase",
        "libcutils",
@@ -340,7 +342,9 @@ cc_library_static {
    cppflags: ["-Wno-conversion-null"],

    srcs: [
        "android/graphics/apex/android_bitmap.cpp",
        "android/graphics/apex/android_region.cpp",
        "android/graphics/apex/android_paint.cpp",

        "android_graphics_Canvas.cpp",
        "android_graphics_ColorSpace.cpp",
@@ -393,7 +397,6 @@ cc_library_static {
    ],

    export_include_dirs: [
        ".",
        "android/graphics/apex/include",
    ],

+0 −2
Original line number Diff line number Diff line
@@ -39,8 +39,6 @@ jobject createBitmap(JNIEnv* env, Bitmap* bitmap,
            jobject ninePatchInsets = nullptr, int density = -1);


void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap);

Bitmap& toBitmap(JNIEnv* env, jobject bitmap);
Bitmap& toBitmap(jlong bitmapHandle);

+70 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.
 */

#ifndef ANDROID_GRAPHICS_TYPECAST_H
#define ANDROID_GRAPHICS_TYPECAST_H

struct ABitmap;
struct ACanvas;
struct APaint;

namespace android {

    class Bitmap;
    class Canvas;
    class Paint;

    class TypeCast {
    public:
        static inline Bitmap& toBitmapRef(const ABitmap* bitmap) {
            return const_cast<Bitmap&>(reinterpret_cast<const Bitmap&>(*bitmap));
        }

        static inline Bitmap* toBitmap(ABitmap* bitmap) {
            return reinterpret_cast<Bitmap*>(bitmap);
        }

        static inline ABitmap* toABitmap(Bitmap* bitmap) {
            return reinterpret_cast<ABitmap*>(bitmap);
        }

        static inline Canvas* toCanvas(ACanvas* canvas) {
            return reinterpret_cast<Canvas*>(canvas);
        }

        static inline ACanvas* toACanvas(Canvas* canvas) {
            return reinterpret_cast<ACanvas *>(canvas);
        }

        static inline const Paint& toPaintRef(const APaint* paint) {
            return reinterpret_cast<const Paint&>(*paint);
        }

        static inline const Paint* toPaint(const APaint* paint) {
            return reinterpret_cast<const Paint*>(paint);
        }

        static inline Paint* toPaint(APaint* paint) {
            return reinterpret_cast<Paint*>(paint);
        }

        static inline APaint* toAPaint(Paint* paint) {
            return reinterpret_cast<APaint*>(paint);
        }
    };
}; // namespace android

#endif // ANDROID_GRAPHICS_TYPECAST_H
+106 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.
 */

#include "android/graphics/bitmap.h"
#include "Bitmap.h"
#include "TypeCast.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);
}

void ABitmap_acquireRef(ABitmap* bitmap) {
    SkSafeRef(TypeCast::toBitmap(bitmap));
}

void ABitmap_releaseRef(ABitmap* bitmap) {
    SkSafeUnref(TypeCast::toBitmap(bitmap));
}

static AndroidBitmapFormat getFormat(Bitmap* bitmap) {
    switch (bitmap->colorType()) {
        case kN32_SkColorType:
            return ANDROID_BITMAP_FORMAT_RGBA_8888;
        case kRGB_565_SkColorType:
            return ANDROID_BITMAP_FORMAT_RGB_565;
        case kARGB_4444_SkColorType:
            return ANDROID_BITMAP_FORMAT_RGBA_4444;
        case kAlpha_8_SkColorType:
            return ANDROID_BITMAP_FORMAT_A_8;
        case kRGBA_F16_SkColorType:
            return ANDROID_BITMAP_FORMAT_RGBA_F16;
        default:
            return ANDROID_BITMAP_FORMAT_NONE;
    }
}

static SkColorType getColorType(AndroidBitmapFormat format) {
    switch (format) {
        case ANDROID_BITMAP_FORMAT_RGBA_8888:
            return kN32_SkColorType;
        case ANDROID_BITMAP_FORMAT_RGB_565:
            return kRGB_565_SkColorType;
        case ANDROID_BITMAP_FORMAT_RGBA_4444:
            return kARGB_4444_SkColorType;
        case ANDROID_BITMAP_FORMAT_A_8:
            return kAlpha_8_SkColorType;
        case ANDROID_BITMAP_FORMAT_RGBA_F16:
            return kRGBA_F16_SkColorType;
        default:
            return kUnknown_SkColorType;
    }
}

ABitmap* ABitmap_copy(ABitmap* srcBitmapHandle, AndroidBitmapFormat dstFormat) {
    SkColorType dstColorType = getColorType(dstFormat);
    if (srcBitmapHandle && dstColorType != kUnknown_SkColorType) {
        SkBitmap srcBitmap;
        TypeCast::toBitmap(srcBitmapHandle)->getSkBitmap(&srcBitmap);

        sk_sp<Bitmap> dstBitmap =
                Bitmap::allocateHeapBitmap(srcBitmap.info().makeColorType(dstColorType));
        if (dstBitmap && srcBitmap.readPixels(dstBitmap->info(), dstBitmap->pixels(),
                                              dstBitmap->rowBytes(), 0, 0)) {
            return TypeCast::toABitmap(dstBitmap.release());
        }
    }
    return nullptr;
}

AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmapHandle) {
    Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle);

    AndroidBitmapInfo info;
    info.width = bitmap->width();
    info.height = bitmap->height();
    info.stride = bitmap->rowBytes();
    info.format = getFormat(bitmap);
    return info;
}

void* ABitmap_getPixels(ABitmap* bitmapHandle) {
    Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle);
    if (bitmap->isHardware()) {
        return nullptr;
    }
    return bitmap->pixels();
}
+37 −18
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#include "android/graphics/canvas.h"

#include "TypeCast.h"
#include "GraphicsJNI.h"

#include <hwui/Canvas.h>
@@ -25,14 +26,6 @@

using namespace android;

static inline Canvas* toCanvas(ACanvas* aCanvas) {
    return reinterpret_cast<Canvas*>(aCanvas);
}

static inline ACanvas* toACanvas(Canvas* canvas) {
    return reinterpret_cast<ACanvas*>(canvas);
}

bool ACanvas_isSupportedPixelFormat(int32_t bufferFormat) {
    ANativeWindow_Buffer buffer { 0, 0, 0, bufferFormat, nullptr, {0} };
    const SkColorType colorType = uirenderer::ANativeWindowToImageInfo(buffer, nullptr).colorType();
@@ -40,10 +33,10 @@ bool ACanvas_isSupportedPixelFormat(int32_t bufferFormat) {
}

ACanvas* ACanvas_getNativeHandleFromJava(JNIEnv* env, jobject canvasObj) {
    return toACanvas(GraphicsJNI::getNativeCanvas(env, canvasObj));
    return TypeCast::toACanvas(GraphicsJNI::getNativeCanvas(env, canvasObj));
}

void ACanvas_setBuffer(ACanvas* canvas, const ANativeWindow_Buffer* buffer,
static SkBitmap convert(const ANativeWindow_Buffer* buffer,
                        int32_t /*android_dataspace_t*/ dataspace) {
    SkBitmap bitmap;
    if (buffer != nullptr && buffer->width > 0 && buffer->height > 0) {
@@ -53,18 +46,44 @@ void ACanvas_setBuffer(ACanvas* canvas, const ANativeWindow_Buffer* buffer,
        bitmap.setInfo(imageInfo, rowBytes);
        bitmap.setPixels(buffer->bits);
    }
    return bitmap;
}

    toCanvas(canvas)->setBitmap(bitmap);
ACanvas* ACanvas_createCanvas(const ANativeWindow_Buffer* buffer,
                              int32_t /*android_dataspace_t*/ dataspace) {
    return TypeCast::toACanvas(Canvas::create_canvas(convert(buffer, dataspace)));
}

void ACanvas_clipRect(ACanvas* canvas, const ARect& clipRect, bool /*doAA*/) {
void ACanvas_destroyCanvas(ACanvas* canvas) {
    delete TypeCast::toCanvas(canvas);
}

void ACanvas_setBuffer(ACanvas* canvas, const ANativeWindow_Buffer* buffer,
                       int32_t /*android_dataspace_t*/ dataspace) {


    TypeCast::toCanvas(canvas)->setBitmap(convert(buffer, dataspace));
}

void ACanvas_clipRect(ACanvas* canvas, const ARect* clipRect, bool /*doAA*/) {
    //TODO update Canvas to take antialias param
    toCanvas(canvas)->clipRect(clipRect.left, clipRect.top, clipRect.right, clipRect.bottom,
                               SkClipOp::kIntersect);
    TypeCast::toCanvas(canvas)->clipRect(clipRect->left, clipRect->top, clipRect->right,
                                         clipRect->bottom, SkClipOp::kIntersect);
}

void ACanvas_clipOutRect(ACanvas* canvas, const ARect& clipRect, bool /*doAA*/) {
void ACanvas_clipOutRect(ACanvas* canvas, const ARect* clipRect, bool /*doAA*/) {
    //TODO update Canvas to take antialias param
    toCanvas(canvas)->clipRect(clipRect.left, clipRect.top, clipRect.right, clipRect.bottom,
                               SkClipOp::kDifference);
    TypeCast::toCanvas(canvas)->clipRect(clipRect->left, clipRect->top, clipRect->right,
                                         clipRect->bottom, SkClipOp::kDifference);
}

void ACanvas_drawRect(ACanvas* canvas, const ARect* rect, const APaint* paint) {
    TypeCast::toCanvas(canvas)->drawRect(rect->left, rect->top, rect->right, rect->bottom,
                                         TypeCast::toPaintRef(paint));
}

void ACanvas_drawBitmap(ACanvas* canvas, const ABitmap* bitmap, float left, float top,
                        const APaint* paint) {
    TypeCast::toCanvas(canvas)->drawBitmap(TypeCast::toBitmapRef(bitmap), left, top,
                                           TypeCast::toPaint(paint));
}
Loading