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
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 461a5ae..dfded73 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -102,6 +102,8 @@
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 @@
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 b73380e..3848b5a 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 @@
}
#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 @@
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(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(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 @@
, 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 @@
}
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 3d55d85..9bbca5b 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -37,10 +37,10 @@
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 @@
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 @@
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 010c4e8..f349ad9 100644
--- a/libs/hwui/jni/Bitmap.cpp
+++ b/libs/hwui/jni/Bitmap.cpp
@@ -196,7 +196,7 @@
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 @@
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) {