Allow more information in bitmap ashmem filenames

Bug: 369619160
Flag: com.android.graphics.hwui.flags.bitmap_ashmem_long_name

This CL allows more information in bitmap ashmem filenames, e.g.

$ adb shell lsof | grep 'ashmem.*bitmap'
system_server    1505   system  mem  unknown  /dev/ashmem/bitmap/writeblob-id_173400011-472x472-size_891136-com.google.android.googlequicksearchbox:search (deleted)
system_server    1505   system  mem  unknown  /dev/ashmem/bitmap/allocate-id_273400014-126x126-size_63504-com.google.android.googlequicksearchbox:search (deleted)
system_server    1505   system  mem  unknown  /dev/ashmem/bitmap/allocate-id_247000010-50x63-size_12600-com.android.phone (deleted)
ndroid.systemui  2155  u0_a238  mem  unknown  /dev/ashmem/bitmap/writeblob-id_173400011-472x472-size_891136-com.google.android.googlequicksearchbox:search (deleted)
ndroid.systemui  2155  u0_a238  mem  unknown  /dev/ashmem/bitmap/allocate-id_214800058-192x192-size_147456-com.google.android.as (deleted)

The long filename will tell us:

  * callsite - where the ashmem bitmap is created, `allocate` means
    in Bitmap::allocateAshmemBitmap where an ashmem backed bitmap is
    directly allocated, or `writeblob` in writeBlob() where existing
    bitmap is turned to an ashmem backed one
  * id - unique to the bitmap, this can also be used to associated to
    the bitmap in a heapdump with the same `mId` field
  * dimension - width x height
  * size - size of the bitmap in bytes
  * origin - the process where the bitmap was created

Change-Id: I7bbb7003d0a0abe62e2008bd708760b6f4e2f8b6
diff --git a/libs/hwui/aconfig/hwui_flags.aconfig b/libs/hwui/aconfig/hwui_flags.aconfig
index 93df478..f255967 100644
--- a/libs/hwui/aconfig/hwui_flags.aconfig
+++ b/libs/hwui/aconfig/hwui_flags.aconfig
@@ -139,3 +139,10 @@
     purpose: PURPOSE_BUGFIX
   }
 }
+
+flag {
+  name: "bitmap_ashmem_long_name"
+  namespace: "core_graphics"
+  description: "Whether to have more information in ashmem filenames for bitmaps"
+  bug: "369619160"
+}
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 3848b5a..f58dcc6 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -15,6 +15,7 @@
  */
 #include "Bitmap.h"
 
+#include <android-base/file.h>
 #include "HardwareBitmapUploader.h"
 #include "Properties.h"
 #ifdef __ANDROID__  // Layoutlib does not support render thread
@@ -57,6 +58,15 @@
 #include <atomic>
 #include <limits>
 
+#ifdef __ANDROID__
+#include <com_android_graphics_hwui_flags.h>
+namespace hwui_flags = com::android::graphics::hwui::flags;
+#else
+namespace hwui_flags {
+constexpr bool bitmap_ashmem_long_name() { return false; }
+}
+#endif
+
 namespace android {
 
 #ifdef __ANDROID__
@@ -140,6 +150,20 @@
     return wrapper;
 }
 
+std::string Bitmap::getAshmemId(const char* tag, uint64_t bitmapId,
+                                int width, int height, size_t size) {
+    if (!hwui_flags::bitmap_ashmem_long_name()) {
+        return "bitmap";
+    }
+    static std::string sCmdline = [] {
+        std::string temp;
+        android::base::ReadFileToString("/proc/self/cmdline", &temp);
+        return temp;
+    }();
+    return std::format("bitmap/{}-id_{}-{}x{}-size_{}-{}",
+                       tag, bitmapId, width, height, size, sCmdline);
+}
+
 sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(SkBitmap* bitmap) {
     return allocateBitmap(bitmap, &Bitmap::allocateAshmemBitmap);
 }
@@ -147,7 +171,9 @@
 sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(size_t size, const SkImageInfo& info, size_t rowBytes) {
 #ifdef __ANDROID__
     // Create new ashmem region with read/write priv
-    int fd = ashmem_create_region("bitmap", size);
+    uint64_t id = getId(PixelStorageType::Ashmem);
+    auto ashmemId = getAshmemId("allocate", id, info.width(), info.height(), size);
+    int fd = ashmem_create_region(ashmemId.c_str(), size);
     if (fd < 0) {
         return nullptr;
     }
@@ -163,7 +189,7 @@
         close(fd);
         return nullptr;
     }
-    return sk_sp<Bitmap>(new Bitmap(addr, fd, size, info, rowBytes));
+    return sk_sp<Bitmap>(new Bitmap(addr, fd, size, info, rowBytes, id));
 #else
     return Bitmap::allocateHeapBitmap(size, info, rowBytes);
 #endif
@@ -301,11 +327,12 @@
     traceBitmapCreate();
 }
 
-Bitmap::Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info, size_t rowBytes)
+Bitmap::Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info,
+               size_t rowBytes, uint64_t id)
         : SkPixelRef(info.width(), info.height(), address, rowBytes)
         , mInfo(validateAlpha(info))
         , mPixelStorageType(PixelStorageType::Ashmem)
-        , mId(getId(mPixelStorageType)) {
+        , mId(id != INVALID_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 9bbca5b..8abe6a8 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -79,6 +79,9 @@
     static sk_sp<Bitmap> allocateHeapBitmap(const SkImageInfo& info);
     static sk_sp<Bitmap> allocateHeapBitmap(size_t size, const SkImageInfo& i, size_t rowBytes);
 
+    static std::string getAshmemId(const char* tag, uint64_t bitmapId,
+                                   int width, int height, size_t size);
+
     /* The createFrom factories construct a new Bitmap object by wrapping the already allocated
      * memory that is provided as an input param.
      */
@@ -181,11 +184,14 @@
   static bool compress(const SkBitmap& bitmap, JavaCompressFormat format,
                        int32_t quality, SkWStream* stream);
 private:
+    static constexpr uint64_t INVALID_BITMAP_ID = 0u;
+
     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);
+    Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info, size_t rowBytes,
+           uint64_t id = INVALID_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 f349ad9..29efd98 100644
--- a/libs/hwui/jni/Bitmap.cpp
+++ b/libs/hwui/jni/Bitmap.cpp
@@ -669,14 +669,20 @@
     return STATUS_OK;
 }
 
-static binder_status_t writeBlob(AParcel* parcel, const int32_t size, const void* data, bool immutable) {
+static binder_status_t writeBlob(AParcel* parcel, uint64_t bitmapId, const SkBitmap& bitmap) {
+    const size_t size = bitmap.computeByteSize();
+    const void* data = bitmap.getPixels();
+    const bool immutable = bitmap.isImmutable();
+
     if (size <= 0 || data == nullptr) {
         return STATUS_NOT_ENOUGH_DATA;
     }
     binder_status_t error = STATUS_OK;
     if (shouldUseAshmem(parcel, size)) {
         // Create new ashmem region with read/write priv
-        base::unique_fd fd(ashmem_create_region("bitmap", size));
+        auto ashmemId = Bitmap::getAshmemId("writeblob", bitmapId,
+                                            bitmap.width(), bitmap.height(), size);
+        base::unique_fd fd(ashmem_create_region(ashmemId.c_str(), size));
         if (fd.get() < 0) {
             return STATUS_NO_MEMORY;
         }
@@ -884,8 +890,7 @@
           p.allowFds() ? "allowed" : "forbidden");
 #endif
 
-    size_t size = bitmap.computeByteSize();
-    status = writeBlob(p.get(), size, bitmap.getPixels(), bitmap.isImmutable());
+    status = writeBlob(p.get(), bitmapWrapper->bitmap().getId(), bitmap);
     if (status) {
         doThrowRE(env, "Could not copy bitmap to parcel blob.");
         return JNI_FALSE;