summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Eric Miao <ericymiao@google.com> 2024-10-15 12:22:01 -0700
committer Eric Miao <ericymiao@google.com> 2024-10-24 11:02:14 -0700
commit7112c6e2a785a415033112525569d52b3c2d06fd (patch)
tree841bb3e2d286f16f18fc55c60aae33779caa4b6f
parent6ae0cc564d7daa0343cb4aacd6ba786f0a711150 (diff)
Add an ID field to `class Bitmap`
Bug: 369619160 Flag: NONE no public API change To be able to better reason about bitmaps, we added a private mId field to `class Bitmap`. This allows the same ID to be used in heapdump and in log/debugging code for better association. Change-Id: I5f775167266c87428c717014fa01cb73c59a44c9
-rw-r--r--graphics/java/android/graphics/Bitmap.java7
-rw-r--r--libs/hwui/hwui/Bitmap.cpp36
-rw-r--r--libs/hwui/hwui/Bitmap.h15
-rw-r--r--libs/hwui/jni/Bitmap.cpp5
4 files changed, 51 insertions, 12 deletions
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 461a5aec27ec..dfded7321b2c 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -102,6 +102,8 @@ public final class Bitmap implements Parcelable {
private static volatile int sDefaultDensity = -1;
+ private long mId;
+
/**
* For backwards compatibility, allows the app layer to change the default
* density when running old apps.
@@ -152,18 +154,19 @@ public final class Bitmap implements Parcelable {
Bitmap(long nativeBitmap, int width, int height, int density,
boolean requestPremultiplied, byte[] ninePatchChunk,
NinePatch.InsetStruct ninePatchInsets) {
- this(nativeBitmap, width, height, density, requestPremultiplied, ninePatchChunk,
+ this(0, nativeBitmap, width, height, density, requestPremultiplied, ninePatchChunk,
ninePatchInsets, true);
}
// called from JNI and Bitmap_Delegate.
- Bitmap(long nativeBitmap, int width, int height, int density,
+ Bitmap(long id, long nativeBitmap, int width, int height, int density,
boolean requestPremultiplied, byte[] ninePatchChunk,
NinePatch.InsetStruct ninePatchInsets, boolean fromMalloc) {
if (nativeBitmap == 0) {
throw new RuntimeException("internal error: native bitmap is 0");
}
+ mId = id;
mWidth = width;
mHeight = height;
mRequestPremultiplied = requestPremultiplied;
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index b73380e38fd1..3848b5a1e281 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -54,6 +54,7 @@
#include <SkPngEncoder.h>
#include <SkWebpEncoder.h>
+#include <atomic>
#include <limits>
namespace android {
@@ -86,6 +87,28 @@ static uint64_t AHardwareBuffer_getAllocationSize(AHardwareBuffer* aHardwareBuff
}
#endif
+// generate an ID for this Bitmap, id is a 64-bit integer of 3 parts:
+// 0000xxxxxx - the lower 6 decimal digits is a monotonically increasing number
+// 000x000000 - the 7th decimal digit is the storage type (see PixelStorageType)
+// xxx0000000 - the 8th decimal digit and above is the current pid
+//
+// e.g. 43231000076 - means this bitmap is the 76th bitmap created, has the
+// storage type of 'Heap', and is created in a process with pid 4323.
+//
+// NOTE:
+// 1) the monotonic number could increase beyond 1000,000 and wrap around, which
+// only happens when more than 1,000,000 bitmaps have been created over time.
+// This could result in two IDs being the same despite being really rare.
+// 2) the IDs are intentionally represented in decimal to make it easier to
+// reason and associate with numbers shown in heap dump (mostly in decimal)
+// and PIDs shown in different tools (mostly in decimal as well).
+uint64_t Bitmap::getId(PixelStorageType type) {
+ static std::atomic<uint64_t> idCounter{0};
+ return (idCounter.fetch_add(1) % 1000000)
+ + static_cast<uint64_t>(type) * 1000000
+ + static_cast<uint64_t>(getpid()) * 10000000;
+}
+
bool Bitmap::computeAllocationSize(size_t rowBytes, int height, size_t* size) {
return 0 <= height && height <= std::numeric_limits<size_t>::max() &&
!__builtin_mul_overflow(rowBytes, (size_t)height, size) &&
@@ -261,7 +284,8 @@ void Bitmap::reconfigure(const SkImageInfo& newInfo, size_t rowBytes) {
Bitmap::Bitmap(void* address, size_t size, const SkImageInfo& info, size_t rowBytes)
: SkPixelRef(info.width(), info.height(), address, rowBytes)
, mInfo(validateAlpha(info))
- , mPixelStorageType(PixelStorageType::Heap) {
+ , mPixelStorageType(PixelStorageType::Heap)
+ , mId(getId(mPixelStorageType)) {
mPixelStorage.heap.address = address;
mPixelStorage.heap.size = size;
traceBitmapCreate();
@@ -270,7 +294,8 @@ Bitmap::Bitmap(void* address, size_t size, const SkImageInfo& info, size_t rowBy
Bitmap::Bitmap(SkPixelRef& pixelRef, const SkImageInfo& info)
: SkPixelRef(info.width(), info.height(), pixelRef.pixels(), pixelRef.rowBytes())
, mInfo(validateAlpha(info))
- , mPixelStorageType(PixelStorageType::WrappedPixelRef) {
+ , mPixelStorageType(PixelStorageType::WrappedPixelRef)
+ , mId(getId(mPixelStorageType)) {
pixelRef.ref();
mPixelStorage.wrapped.pixelRef = &pixelRef;
traceBitmapCreate();
@@ -279,7 +304,8 @@ Bitmap::Bitmap(SkPixelRef& pixelRef, const SkImageInfo& info)
Bitmap::Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info, size_t rowBytes)
: SkPixelRef(info.width(), info.height(), address, rowBytes)
, mInfo(validateAlpha(info))
- , mPixelStorageType(PixelStorageType::Ashmem) {
+ , mPixelStorageType(PixelStorageType::Ashmem)
+ , mId(getId(mPixelStorageType)) {
mPixelStorage.ashmem.address = address;
mPixelStorage.ashmem.fd = fd;
mPixelStorage.ashmem.size = mappedSize;
@@ -293,7 +319,8 @@ Bitmap::Bitmap(AHardwareBuffer* buffer, const SkImageInfo& info, size_t rowBytes
, mInfo(validateAlpha(info))
, mPixelStorageType(PixelStorageType::Hardware)
, mPalette(palette)
- , mPaletteGenerationId(getGenerationID()) {
+ , mPaletteGenerationId(getGenerationID())
+ , mId(getId(mPixelStorageType)) {
mPixelStorage.hardware.buffer = buffer;
mPixelStorage.hardware.size = AHardwareBuffer_getAllocationSize(buffer);
AHardwareBuffer_acquire(buffer);
@@ -578,6 +605,7 @@ void Bitmap::setGainmap(sp<uirenderer::Gainmap>&& gainmap) {
}
std::mutex Bitmap::mLock{};
+
size_t Bitmap::mTotalBitmapBytes = 0;
size_t Bitmap::mTotalBitmapCount = 0;
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index 3d55d859ed5f..9bbca5bc7378 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -37,10 +37,10 @@ class SkWStream;
namespace android {
enum class PixelStorageType {
- WrappedPixelRef,
- Heap,
- Ashmem,
- Hardware,
+ WrappedPixelRef = 0,
+ Heap = 1,
+ Ashmem = 2,
+ Hardware = 3,
};
// TODO: Find a better home for this. It's here because hwui/Bitmap is exported and CanvasTransform
@@ -104,6 +104,10 @@ public:
void setColorSpace(sk_sp<SkColorSpace> colorSpace);
void setAlphaType(SkAlphaType alphaType);
+ uint64_t getId() const {
+ return mId;
+ }
+
void getSkBitmap(SkBitmap* outBitmap);
SkBitmap getSkBitmap() {
@@ -229,6 +233,9 @@ private:
sk_sp<SkImage> mImage; // Cache is used only for HW Bitmaps with Skia pipeline.
+ uint64_t mId; // unique ID for this bitmap
+ static uint64_t getId(PixelStorageType type);
+
// for tracing total number and memory usage of bitmaps
static std::mutex mLock;
static size_t mTotalBitmapBytes;
diff --git a/libs/hwui/jni/Bitmap.cpp b/libs/hwui/jni/Bitmap.cpp
index 010c4e8dfb3a..f349ad915933 100644
--- a/libs/hwui/jni/Bitmap.cpp
+++ b/libs/hwui/jni/Bitmap.cpp
@@ -196,7 +196,7 @@ jobject createBitmap(JNIEnv* env, Bitmap* bitmap,
int density) {
static jmethodID gBitmap_constructorMethodID =
GetMethodIDOrDie(env, gBitmap_class,
- "<init>", "(JIIIZ[BLandroid/graphics/NinePatch$InsetStruct;Z)V");
+ "<init>", "(JJIIIZ[BLandroid/graphics/NinePatch$InsetStruct;Z)V");
bool isMutable = bitmapCreateFlags & kBitmapCreateFlag_Mutable;
bool isPremultiplied = bitmapCreateFlags & kBitmapCreateFlag_Premultiplied;
@@ -209,7 +209,8 @@ jobject createBitmap(JNIEnv* env, Bitmap* bitmap,
bitmapWrapper->bitmap().setImmutable();
}
jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
- reinterpret_cast<jlong>(bitmapWrapper), bitmap->width(), bitmap->height(), density,
+ static_cast<jlong>(bitmap->getId()), reinterpret_cast<jlong>(bitmapWrapper),
+ bitmap->width(), bitmap->height(), density,
isPremultiplied, ninePatchChunk, ninePatchInsets, fromMalloc);
if (env->ExceptionCheck() != 0) {