Loading graphics/java/android/graphics/Bitmap.java +5 −2 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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; Loading libs/hwui/aconfig/hwui_flags.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -139,3 +139,10 @@ flag { 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" } libs/hwui/hwui/Bitmap.cpp +62 −7 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -54,8 +55,18 @@ #include <SkPngEncoder.h> #include <SkWebpEncoder.h> #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__ Loading Loading @@ -86,6 +97,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) && Loading Loading @@ -117,6 +150,20 @@ static sk_sp<Bitmap> allocateBitmap(SkBitmap* bitmap, AllocPixelRef alloc) { 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); } Loading @@ -124,7 +171,9 @@ sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(SkBitmap* bitmap) { 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; } Loading @@ -140,7 +189,7 @@ sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(size_t size, const SkImageInfo& info, 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 Loading Loading @@ -261,7 +310,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(); Loading @@ -270,16 +320,19 @@ 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(); } 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) { , mPixelStorageType(PixelStorageType::Ashmem) , mId(id != INVALID_BITMAP_ID ? id : getId(mPixelStorageType)) { mPixelStorage.ashmem.address = address; mPixelStorage.ashmem.fd = fd; mPixelStorage.ashmem.size = mappedSize; Loading @@ -293,7 +346,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); Loading Loading @@ -578,6 +632,7 @@ void Bitmap::setGainmap(sp<uirenderer::Gainmap>&& gainmap) { } std::mutex Bitmap::mLock{}; size_t Bitmap::mTotalBitmapBytes = 0; size_t Bitmap::mTotalBitmapCount = 0; Loading libs/hwui/hwui/Bitmap.h +18 −5 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -79,6 +79,9 @@ public: 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. */ Loading @@ -104,6 +107,10 @@ public: void setColorSpace(sk_sp<SkColorSpace> colorSpace); void setAlphaType(SkAlphaType alphaType); uint64_t getId() const { return mId; } void getSkBitmap(SkBitmap* outBitmap); SkBitmap getSkBitmap() { Loading Loading @@ -177,11 +184,14 @@ public: 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); Loading Loading @@ -229,6 +239,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; Loading libs/hwui/jni/Bitmap.cpp +12 −6 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading Loading @@ -668,14 +669,20 @@ static binder_status_t writeBlobFromFd(AParcel* parcel, int32_t size, int fd) { 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; } Loading Loading @@ -883,8 +890,7 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, 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; Loading Loading
graphics/java/android/graphics/Bitmap.java +5 −2 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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; Loading
libs/hwui/aconfig/hwui_flags.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -139,3 +139,10 @@ flag { 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" }
libs/hwui/hwui/Bitmap.cpp +62 −7 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -54,8 +55,18 @@ #include <SkPngEncoder.h> #include <SkWebpEncoder.h> #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__ Loading Loading @@ -86,6 +97,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) && Loading Loading @@ -117,6 +150,20 @@ static sk_sp<Bitmap> allocateBitmap(SkBitmap* bitmap, AllocPixelRef alloc) { 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); } Loading @@ -124,7 +171,9 @@ sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(SkBitmap* bitmap) { 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; } Loading @@ -140,7 +189,7 @@ sk_sp<Bitmap> Bitmap::allocateAshmemBitmap(size_t size, const SkImageInfo& info, 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 Loading Loading @@ -261,7 +310,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(); Loading @@ -270,16 +320,19 @@ 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(); } 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) { , mPixelStorageType(PixelStorageType::Ashmem) , mId(id != INVALID_BITMAP_ID ? id : getId(mPixelStorageType)) { mPixelStorage.ashmem.address = address; mPixelStorage.ashmem.fd = fd; mPixelStorage.ashmem.size = mappedSize; Loading @@ -293,7 +346,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); Loading Loading @@ -578,6 +632,7 @@ void Bitmap::setGainmap(sp<uirenderer::Gainmap>&& gainmap) { } std::mutex Bitmap::mLock{}; size_t Bitmap::mTotalBitmapBytes = 0; size_t Bitmap::mTotalBitmapCount = 0; Loading
libs/hwui/hwui/Bitmap.h +18 −5 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -79,6 +79,9 @@ public: 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. */ Loading @@ -104,6 +107,10 @@ public: void setColorSpace(sk_sp<SkColorSpace> colorSpace); void setAlphaType(SkAlphaType alphaType); uint64_t getId() const { return mId; } void getSkBitmap(SkBitmap* outBitmap); SkBitmap getSkBitmap() { Loading Loading @@ -177,11 +184,14 @@ public: 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); Loading Loading @@ -229,6 +239,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; Loading
libs/hwui/jni/Bitmap.cpp +12 −6 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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) { Loading Loading @@ -668,14 +669,20 @@ static binder_status_t writeBlobFromFd(AParcel* parcel, int32_t size, int fd) { 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; } Loading Loading @@ -883,8 +890,7 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, 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; Loading