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

Commit 734d655a authored by Mark Fasheh's avatar Mark Fasheh
Browse files

Transfer Bitmap.mId whenever we send an ashmem bitmap over the wire

Only do this when we do a zero copy transfer of an ashmem region.
Otherwise a value of zero is sent and mId is generated as usual on
the receiving end.

We can look at this in heap dumps and compare identical bitmaps to see
whether they are shared with another process, or are a process-local copy.

Bug: 386212855
Test: boot phone and take heap dumps
Flag: NONE no public API change
Change-Id: Ic791f256884d18f07a03d2f5c7d4e694855e6527
parent 6a1baafa
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -102,6 +102,10 @@ public final class Bitmap implements Parcelable {

    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;

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

sk_sp<Bitmap> Bitmap::createFrom(const SkImageInfo& info, size_t rowBytes, int fd, void* addr,
                                 size_t size, bool readOnly) {
                                 size_t size, bool readOnly, int64_t id) {
#ifdef _WIN32 // ashmem not implemented on Windows
     return nullptr;
#else
@@ -279,7 +279,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));
    sk_sp<Bitmap> bitmap(new Bitmap(addr, fd, size, info, rowBytes, id));
    if (readOnly) {
        bitmap->setImmutable();
    }
@@ -334,7 +334,7 @@ Bitmap::Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info
        : SkPixelRef(info.width(), info.height(), address, rowBytes)
        , mInfo(validateAlpha(info))
        , mPixelStorageType(PixelStorageType::Ashmem)
        , mId(id != INVALID_BITMAP_ID ? id : getId(mPixelStorageType)) {
        , mId(id != UNDEFINED_BITMAP_ID ? id : getId(mPixelStorageType)) {
    mPixelStorage.ashmem.address = address;
    mPixelStorage.ashmem.fd = fd;
    mPixelStorage.ashmem.size = mappedSize;
+4 −4
Original line number Diff line number Diff line
@@ -97,7 +97,7 @@ public:
                                    BitmapPalette palette);
#endif
    static sk_sp<Bitmap> createFrom(const SkImageInfo& info, size_t rowBytes, int fd, void* addr,
                                    size_t size, bool readOnly);
                                    size_t size, bool readOnly, int64_t id);
    static sk_sp<Bitmap> createFrom(const SkImageInfo&, SkPixelRef&);

    int rowBytesAsPixels() const { return rowBytes() >> mInfo.shiftPerPixel(); }
@@ -183,15 +183,15 @@ public:

  static bool compress(const SkBitmap& bitmap, JavaCompressFormat format,
                       int32_t quality, SkWStream* stream);
private:
    static constexpr uint64_t INVALID_BITMAP_ID = 0u;

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

    Bitmap(void* address, size_t allocSize, const SkImageInfo& info, size_t rowBytes);
    Bitmap(SkPixelRef& pixelRef, const SkImageInfo& info);
    Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info, size_t rowBytes,
           uint64_t id = INVALID_BITMAP_ID);
           uint64_t id = UNDEFINED_BITMAP_ID);
#ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
    Bitmap(AHardwareBuffer* buffer, const SkImageInfo& info, size_t rowBytes,
           BitmapPalette palette);
+15 −11
Original line number Diff line number Diff line
@@ -191,9 +191,8 @@ void reinitBitmap(JNIEnv* env, jobject javaBitmap, const SkImageInfo& info,
            info.width(), info.height(), isPremultiplied);
}

jobject createBitmap(JNIEnv* env, Bitmap* bitmap,
        int bitmapCreateFlags, jbyteArray ninePatchChunk, jobject ninePatchInsets,
        int density) {
jobject createBitmap(JNIEnv* env, Bitmap* bitmap, int bitmapCreateFlags, jbyteArray ninePatchChunk,
                     jobject ninePatchInsets, int density, int64_t id) {
    static jmethodID gBitmap_constructorMethodID =
        GetMethodIDOrDie(env, gBitmap_class,
            "<init>", "(JJIIIZ[BLandroid/graphics/NinePatch$InsetStruct;Z)V");
@@ -208,10 +207,12 @@ jobject createBitmap(JNIEnv* env, Bitmap* bitmap,
    if (!isMutable) {
        bitmapWrapper->bitmap().setImmutable();
    }
    int64_t bitmapId = id != Bitmap::UNDEFINED_BITMAP_ID ? id : bitmap->getId();
    jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
            static_cast<jlong>(bitmap->getId()), reinterpret_cast<jlong>(bitmapWrapper),
            bitmap->width(), bitmap->height(), density,
            isPremultiplied, ninePatchChunk, ninePatchInsets, fromMalloc);
                                 static_cast<jlong>(bitmapId),
                                 reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(),
                                 bitmap->height(), density, isPremultiplied, ninePatchChunk,
                                 ninePatchInsets, fromMalloc);

    if (env->ExceptionCheck() != 0) {
        ALOGE("*** Uncaught exception returned from Java call!\n");
@@ -759,6 +760,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
    const int32_t height = p.readInt32();
    const int32_t rowBytes = p.readInt32();
    const int32_t density = p.readInt32();
    const int64_t sourceId = p.readInt64();

    if (kN32_SkColorType != colorType &&
            kRGBA_F16_SkColorType != colorType &&
@@ -815,7 +817,8 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
                    return STATUS_NO_MEMORY;
                }
                nativeBitmap =
                        Bitmap::createFrom(imageInfo, rowBytes, fd.release(), addr, size, !isMutable);
                        Bitmap::createFrom(imageInfo, rowBytes, fd.release(), addr, size,
                        !isMutable, sourceId);
                return STATUS_OK;
            });

@@ -831,15 +834,15 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
    }

    return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable), nullptr,
                        nullptr, density);
                        nullptr, density, sourceId);
#else
    jniThrowRuntimeException(env, "Cannot use parcels outside of Android");
    return NULL;
#endif
}

static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
                                     jlong bitmapHandle, jint density, jobject parcel) {
static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, jlong bitmapHandle, jint density,
                                     jobject parcel) {
#ifdef __ANDROID__ // Layoutlib does not support parcel
    if (parcel == NULL) {
        ALOGD("------- writeToParcel null parcel\n");
@@ -870,6 +873,7 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
    binder_status_t status;
    int fd = bitmapWrapper->bitmap().getAshmemFd();
    if (fd >= 0 && p.allowFds() && bitmap.isImmutable()) {
        p.writeInt64(bitmapWrapper->bitmap().getId());
#if DEBUG_PARCEL
        ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as "
              "immutable blob (fds %s)",
@@ -889,7 +893,7 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,
    ALOGD("Bitmap.writeToParcel: copying bitmap into new blob (fds %s)",
          p.allowFds() ? "allowed" : "forbidden");
#endif

    p.writeInt64(Bitmap::UNDEFINED_BITMAP_ID);
    status = writeBlob(p.get(), bitmapWrapper->bitmap().getId(), bitmap);
    if (status) {
        doThrowRE(env, "Could not copy bitmap to parcel blob.");
+4 −3
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

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

struct SkImageInfo;

@@ -33,9 +34,9 @@ enum BitmapCreateFlags {
    kBitmapCreateFlag_Premultiplied = 0x2,
};

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

Bitmap& toBitmap(jlong bitmapHandle);

Loading