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

Commit 332540d2 authored by Eric Miao's avatar Eric Miao
Browse files

Keep source bitmap id for received ashmem bitmaps

Bug: 369619160
Flag: NONE - private API for debugging

When transfering bitmap mId from sending side to receiving side,
a same bitmap could be sent multiple times, which ends up with
multiple bitmaps on the receiving end having the same mId.

To keep mId unique while not losing the track of where the bitmap
was originated from, we keep the source mId in a separate source
field, and Bitmap.getSource()/Bitmap.setSource() to retrieve and
specify the source bitmap.

Change-Id: Ic85a0e8324fc0b1bf03b5ed8c1358b8449c00d49
parent 16d79829
Loading
Loading
Loading
Loading
+8 −4
Original line number Original line Diff line number Diff line
@@ -103,12 +103,13 @@ public final class Bitmap implements Parcelable {


    private static volatile int sDefaultDensity = -1;
    private static volatile int sDefaultDensity = -1;


    /**
     * This id is not authoritative and can be duplicated if an ashmem bitmap is decoded from a
     * parcel.
     */
    private long mId;
    private long mId;


    // source id of the bitmap where this bitmap was created from, e.g.
    // in the case of ashmem bitmap received, mSourceId is the mId of
    // the bitmap from the sender
    private long mSourceId = -1;

    /**
    /**
     * For backwards compatibility, allows the app layer to change the default
     * For backwards compatibility, allows the app layer to change the default
     * density when running old apps.
     * density when running old apps.
@@ -182,6 +183,7 @@ public final class Bitmap implements Parcelable {
        }
        }


        mNativePtr = nativeBitmap;
        mNativePtr = nativeBitmap;
        mSourceId = nativeGetSourceId(mNativePtr);
        final int allocationByteCount = getAllocationByteCount();
        final int allocationByteCount = getAllocationByteCount();
        getRegistry(fromMalloc, allocationByteCount).registerNativeAllocation(this, mNativePtr);
        getRegistry(fromMalloc, allocationByteCount).registerNativeAllocation(this, mNativePtr);


@@ -2590,6 +2592,8 @@ public final class Bitmap implements Parcelable {


    private static native Gainmap nativeExtractGainmap(long nativePtr);
    private static native Gainmap nativeExtractGainmap(long nativePtr);
    private static native void nativeSetGainmap(long bitmapPtr, long gainmapPtr);
    private static native void nativeSetGainmap(long bitmapPtr, long gainmapPtr);
    private static native long nativeGetSourceId(long nativePtr);
    private static native void nativeSetSourceId(long nativePtr, long sourceId);


    // ---------------- @CriticalNative -------------------
    // ---------------- @CriticalNative -------------------


+2 −2
Original line number Original line Diff line number Diff line
@@ -262,7 +262,7 @@ sk_sp<Bitmap> Bitmap::createFrom(AHardwareBuffer* hardwareBuffer, const SkImageI
#endif
#endif


sk_sp<Bitmap> Bitmap::createFrom(const SkImageInfo& info, size_t rowBytes, int fd, void* addr,
sk_sp<Bitmap> Bitmap::createFrom(const SkImageInfo& info, size_t rowBytes, int fd, void* addr,
                                 size_t size, bool readOnly, int64_t id) {
                                 size_t size, bool readOnly) {
#ifdef _WIN32 // ashmem not implemented on Windows
#ifdef _WIN32 // ashmem not implemented on Windows
     return nullptr;
     return nullptr;
#else
#else
@@ -281,7 +281,7 @@ sk_sp<Bitmap> Bitmap::createFrom(const SkImageInfo& info, size_t rowBytes, int f
        }
        }
    }
    }


    sk_sp<Bitmap> bitmap(new Bitmap(addr, fd, size, info, rowBytes, id));
    sk_sp<Bitmap> bitmap(new Bitmap(addr, fd, size, info, rowBytes));
    if (readOnly) {
    if (readOnly) {
        bitmap->setImmutable();
        bitmap->setImmutable();
    }
    }
+8 −3
Original line number Original line Diff line number Diff line
@@ -63,6 +63,8 @@ class PixelStorage;


typedef void (*FreeFunc)(void* addr, void* context);
typedef void (*FreeFunc)(void* addr, void* context);


static constexpr uint64_t UNDEFINED_BITMAP_ID = 0u;

class Bitmap : public SkPixelRef {
class Bitmap : public SkPixelRef {
public:
public:
    /* The allocate factories not only construct the Bitmap object but also allocate the
    /* The allocate factories not only construct the Bitmap object but also allocate the
@@ -98,7 +100,7 @@ public:
                                    BitmapPalette palette);
                                    BitmapPalette palette);
#endif
#endif
    static sk_sp<Bitmap> createFrom(const SkImageInfo& info, size_t rowBytes, int fd, void* addr,
    static sk_sp<Bitmap> createFrom(const SkImageInfo& info, size_t rowBytes, int fd, void* addr,
                                    size_t size, bool readOnly, int64_t id);
                                    size_t size, bool readOnly);
    static sk_sp<Bitmap> createFrom(const SkImageInfo&, SkPixelRef&);
    static sk_sp<Bitmap> createFrom(const SkImageInfo&, SkPixelRef&);


    int rowBytesAsPixels() const { return rowBytes() >> mInfo.shiftPerPixel(); }
    int rowBytesAsPixels() const { return rowBytes() >> mInfo.shiftPerPixel(); }
@@ -112,6 +114,9 @@ public:
        return mId;
        return mId;
    }
    }


    uint64_t getSourceId() const { return mSourceId; }
    void setSourceId(uint64_t sourceId) { mSourceId = sourceId; }

    void getSkBitmap(SkBitmap* outBitmap);
    void getSkBitmap(SkBitmap* outBitmap);


    SkBitmap getSkBitmap() {
    SkBitmap getSkBitmap() {
@@ -184,8 +189,6 @@ public:


  static bool compress(const SkBitmap& bitmap, JavaCompressFormat format,
  static bool compress(const SkBitmap& bitmap, JavaCompressFormat format,
                       int32_t quality, SkWStream* stream);
                       int32_t quality, SkWStream* stream);

    static constexpr uint64_t UNDEFINED_BITMAP_ID = 0u;
private:
private:
    static sk_sp<Bitmap> allocateAshmemBitmap(size_t size, const SkImageInfo& i, size_t rowBytes);
    static sk_sp<Bitmap> allocateAshmemBitmap(size_t size, const SkImageInfo& i, size_t rowBytes);


@@ -241,6 +244,8 @@ private:
    sk_sp<SkImage> mImage;  // Cache is used only for HW Bitmaps with Skia pipeline.
    sk_sp<SkImage> mImage;  // Cache is used only for HW Bitmaps with Skia pipeline.


    uint64_t mId;                // unique ID for this bitmap
    uint64_t mId;                // unique ID for this bitmap
    // source Id where this bitmap is orignated from
    uint64_t mSourceId;
    static uint64_t getId(PixelStorageType type);
    static uint64_t getId(PixelStorageType type);


    // for tracing total number and memory usage of bitmaps
    // for tracing total number and memory usage of bitmaps
+23 −10
Original line number Original line Diff line number Diff line
@@ -192,7 +192,7 @@ void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
}
}


jobject createBitmap(JNIEnv* env, Bitmap* bitmap, int bitmapCreateFlags, jbyteArray ninePatchChunk,
jobject createBitmap(JNIEnv* env, Bitmap* bitmap, int bitmapCreateFlags, jbyteArray ninePatchChunk,
                     jobject ninePatchInsets, int density, int64_t id) {
                     jobject ninePatchInsets, int density) {
    static jmethodID gBitmap_constructorMethodID =
    static jmethodID gBitmap_constructorMethodID =
        GetMethodIDOrDie(env, gBitmap_class,
        GetMethodIDOrDie(env, gBitmap_class,
            "<init>", "(JJIIIZ[BLandroid/graphics/NinePatch$InsetStruct;Z)V");
            "<init>", "(JJIIIZ[BLandroid/graphics/NinePatch$InsetStruct;Z)V");
@@ -207,9 +207,8 @@ jobject createBitmap(JNIEnv* env, Bitmap* bitmap, int bitmapCreateFlags, jbyteAr
    if (!isMutable) {
    if (!isMutable) {
        bitmapWrapper->bitmap().setImmutable();
        bitmapWrapper->bitmap().setImmutable();
    }
    }
    int64_t bitmapId = id != Bitmap::UNDEFINED_BITMAP_ID ? id : bitmap->getId();
    jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
    jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
                                 static_cast<jlong>(bitmapId),
                                 static_cast<jlong>(bitmap->getId()),
                                 reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(),
                                 reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(),
                                 bitmap->height(), density, isPremultiplied, ninePatchChunk,
                                 bitmap->height(), density, isPremultiplied, ninePatchChunk,
                                 ninePatchInsets, fromMalloc);
                                 ninePatchInsets, fromMalloc);
@@ -816,9 +815,8 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
                    ALOGW("mmap failed, error %d (%s)", err, strerror(err));
                    ALOGW("mmap failed, error %d (%s)", err, strerror(err));
                    return STATUS_NO_MEMORY;
                    return STATUS_NO_MEMORY;
                }
                }
                nativeBitmap =
                nativeBitmap = Bitmap::createFrom(imageInfo, rowBytes, fd.release(),
                        Bitmap::createFrom(imageInfo, rowBytes, fd.release(), addr, size,
                                                  addr, size, !isMutable);
                        !isMutable, sourceId);
                return STATUS_OK;
                return STATUS_OK;
            });
            });


@@ -833,8 +831,9 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
        return nullptr;
        return nullptr;
    }
    }


    nativeBitmap->setSourceId(sourceId);
    return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable), nullptr,
    return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable), nullptr,
                        nullptr, density, sourceId);
                        nullptr, density);
#else
#else
    jniThrowRuntimeException(env, "Cannot use parcels outside of Linux");
    jniThrowRuntimeException(env, "Cannot use parcels outside of Linux");
    return NULL;
    return NULL;
@@ -854,6 +853,7 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, jlong bitmapHandle, j


    auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
    auto bitmapWrapper = reinterpret_cast<BitmapWrapper*>(bitmapHandle);
    bitmapWrapper->getSkBitmap(&bitmap);
    bitmapWrapper->getSkBitmap(&bitmap);
    uint64_t id = bitmapWrapper->bitmap().getId();


    p.writeInt32(!bitmap.isImmutable());
    p.writeInt32(!bitmap.isImmutable());
    p.writeInt32(bitmap.colorType());
    p.writeInt32(bitmap.colorType());
@@ -868,12 +868,12 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, jlong bitmapHandle, j
    p.writeInt32(bitmap.height());
    p.writeInt32(bitmap.height());
    p.writeInt32(bitmap.rowBytes());
    p.writeInt32(bitmap.rowBytes());
    p.writeInt32(density);
    p.writeInt32(density);
    p.writeInt64(id);


    // Transfer the underlying ashmem region if we have one and it's immutable.
    // Transfer the underlying ashmem region if we have one and it's immutable.
    binder_status_t status;
    binder_status_t status;
    int fd = bitmapWrapper->bitmap().getAshmemFd();
    int fd = bitmapWrapper->bitmap().getAshmemFd();
    if (fd >= 0 && p.allowFds() && bitmap.isImmutable()) {
    if (fd >= 0 && p.allowFds() && bitmap.isImmutable()) {
        p.writeInt64(bitmapWrapper->bitmap().getId());
#if DEBUG_PARCEL
#if DEBUG_PARCEL
        ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
        ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
              "immutable blob (fds %s)",
              "immutable blob (fds %s)",
@@ -893,8 +893,7 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, jlong bitmapHandle, j
    ALOGD("Bitmap.writeToParcel: copying bitmap into new blob (fds %s)",
    ALOGD("Bitmap.writeToParcel: copying bitmap into new blob (fds %s)",
          p.allowFds() ? "allowed" : "forbidden");
          p.allowFds() ? "allowed" : "forbidden");
#endif
#endif
    p.writeInt64(Bitmap::UNDEFINED_BITMAP_ID);
    status = writeBlob(p.get(), id, bitmap);
    status = writeBlob(p.get(), bitmapWrapper->bitmap().getId(), bitmap);
    if (status) {
    if (status) {
        doThrowRE(env, "Could not copy bitmap to parcel blob.");
        doThrowRE(env, "Could not copy bitmap to parcel blob.");
        return JNI_FALSE;
        return JNI_FALSE;
@@ -1226,6 +1225,18 @@ static void Bitmap_setGainmap(JNIEnv*, jobject, jlong bitmapHandle, jlong gainma
    bitmapHolder->bitmap().setGainmap(sp<uirenderer::Gainmap>::fromExisting(gainmap));
    bitmapHolder->bitmap().setGainmap(sp<uirenderer::Gainmap>::fromExisting(gainmap));
}
}


static jlong Bitmap_getSourceId(JNIEnv*, jobject, jlong bitmapHandle) {
    LocalScopedBitmap bitmapHolder(bitmapHandle);
    return bitmapHolder.valid() ? bitmapHolder->bitmap().getSourceId() : UNDEFINED_BITMAP_ID;
}

static void Bitmap_setSourceId(JNIEnv*, jobject, jlong bitmapHandle, jlong sourceId) {
    LocalScopedBitmap bitmapHolder(bitmapHandle);
    if (bitmapHolder.valid()) {
        bitmapHolder->bitmap().setSourceId(sourceId);
    }
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////


static const JNINativeMethod gBitmapMethods[] = {
static const JNINativeMethod gBitmapMethods[] = {
@@ -1278,6 +1289,8 @@ static const JNINativeMethod gBitmapMethods[] = {
        {"nativeSetImmutable", "(J)V", (void*)Bitmap_setImmutable},
        {"nativeSetImmutable", "(J)V", (void*)Bitmap_setImmutable},
        {"nativeExtractGainmap", "(J)Landroid/graphics/Gainmap;", (void*)Bitmap_extractGainmap},
        {"nativeExtractGainmap", "(J)Landroid/graphics/Gainmap;", (void*)Bitmap_extractGainmap},
        {"nativeSetGainmap", "(JJ)V", (void*)Bitmap_setGainmap},
        {"nativeSetGainmap", "(JJ)V", (void*)Bitmap_setGainmap},
        {"nativeGetSourceId", "(J)J", (void*)Bitmap_getSourceId},
        {"nativeSetSourceId", "(JJ)V", (void*)Bitmap_setSourceId},


        // ------------ @CriticalNative ----------------
        // ------------ @CriticalNative ----------------
        {"nativeIsImmutable", "(J)Z", (void*)Bitmap_isImmutable},
        {"nativeIsImmutable", "(J)Z", (void*)Bitmap_isImmutable},
+2 −3
Original line number Original line Diff line number Diff line
@@ -18,7 +18,6 @@


#include <jni.h>
#include <jni.h>
#include <android/bitmap.h>
#include <android/bitmap.h>
#include <hwui/Bitmap.h>


struct SkImageInfo;
struct SkImageInfo;


@@ -36,7 +35,7 @@ enum BitmapCreateFlags {


jobject createBitmap(JNIEnv* env, Bitmap* bitmap, int bitmapCreateFlags,
jobject createBitmap(JNIEnv* env, Bitmap* bitmap, int bitmapCreateFlags,
                    jbyteArray ninePatchChunk = nullptr, jobject ninePatchInsets = nullptr,
                    jbyteArray ninePatchChunk = nullptr, jobject ninePatchInsets = nullptr,
                     int density = -1, int64_t id = Bitmap::UNDEFINED_BITMAP_ID);
                    int density = -1);


Bitmap& toBitmap(jlong bitmapHandle);
Bitmap& toBitmap(jlong bitmapHandle);