diff options
author | 2025-01-14 20:58:16 +0000 | |
---|---|---|
committer | 2025-02-07 23:57:38 +0000 | |
commit | 734d655a61aa502eb67acd56eb53b4a02c5fa30d (patch) | |
tree | 17ab88a255a9913efb6c8b75dff819230097654e | |
parent | 6a1baafa742ba095e8853daf9ef50fa1f3d33560 (diff) |
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
-rw-r--r-- | graphics/java/android/graphics/Bitmap.java | 4 | ||||
-rw-r--r-- | libs/hwui/hwui/Bitmap.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/hwui/Bitmap.h | 8 | ||||
-rw-r--r-- | libs/hwui/jni/Bitmap.cpp | 26 | ||||
-rw-r--r-- | libs/hwui/jni/Bitmap.h | 7 | ||||
-rw-r--r-- | libs/hwui/jni/ScopedParcel.cpp | 10 | ||||
-rw-r--r-- | libs/hwui/jni/ScopedParcel.h | 4 |
7 files changed, 44 insertions, 21 deletions
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index dfded7321b2c..0c4ea79dd5be 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -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; /** diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp index b1550b0b6888..63a024b8e780 100644 --- a/libs/hwui/hwui/Bitmap.cpp +++ b/libs/hwui/hwui/Bitmap.cpp @@ -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; diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h index 8abe6a8c445a..4e9bcf27c0ef 100644 --- a/libs/hwui/hwui/Bitmap.h +++ b/libs/hwui/hwui/Bitmap.h @@ -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); diff --git a/libs/hwui/jni/Bitmap.cpp b/libs/hwui/jni/Bitmap.cpp index 29efd98b41d0..cfde0b28c0d5 100644 --- a/libs/hwui/jni/Bitmap.cpp +++ b/libs/hwui/jni/Bitmap.cpp @@ -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."); diff --git a/libs/hwui/jni/Bitmap.h b/libs/hwui/jni/Bitmap.h index 21a93f066d9b..c93246a972b6 100644 --- a/libs/hwui/jni/Bitmap.h +++ b/libs/hwui/jni/Bitmap.h @@ -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); diff --git a/libs/hwui/jni/ScopedParcel.cpp b/libs/hwui/jni/ScopedParcel.cpp index b0f5423813b7..95e4e01d8df8 100644 --- a/libs/hwui/jni/ScopedParcel.cpp +++ b/libs/hwui/jni/ScopedParcel.cpp @@ -39,6 +39,16 @@ uint32_t ScopedParcel::readUint32() { return temp; } +int64_t ScopedParcel::readInt64() { + int64_t temp = 0; + // TODO: This behavior-matches what android::Parcel does + // but this should probably be better + if (AParcel_readInt64(mParcel, &temp) != STATUS_OK) { + temp = 0; + } + return temp; +} + float ScopedParcel::readFloat() { float temp = 0.; if (AParcel_readFloat(mParcel, &temp) != STATUS_OK) { diff --git a/libs/hwui/jni/ScopedParcel.h b/libs/hwui/jni/ScopedParcel.h index fd8d6a210f0f..f2f138fda43c 100644 --- a/libs/hwui/jni/ScopedParcel.h +++ b/libs/hwui/jni/ScopedParcel.h @@ -35,12 +35,16 @@ public: uint32_t readUint32(); + int64_t readInt64(); + float readFloat(); void writeInt32(int32_t value) { AParcel_writeInt32(mParcel, value); } void writeUint32(uint32_t value) { AParcel_writeUint32(mParcel, value); } + void writeInt64(int64_t value) { AParcel_writeInt64(mParcel, value); } + void writeFloat(float value) { AParcel_writeFloat(mParcel, value); } bool allowFds() const { return AParcel_getAllowFds(mParcel); } |