Loading core/jni/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -445,6 +445,8 @@ cc_library_shared_for_libandroid_runtime { "libutils", "libwebp-decode", "libwebp-encode", "libperfetto_c", "libtracing_perfetto", "libwuffs_mirror_release_c", "libz", "libimage_io", Loading libs/hwui/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -442,6 +442,8 @@ cc_defaults { "liblog", "libminikin", "libz", "libtracing_perfetto", "libperfetto_c", ], static_libs: [ Loading libs/hwui/jni/Bitmap.cpp +116 −1 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ #include <sys/mman.h> #include <sys/syscall.h> #include <unistd.h> #include <utils/Trace.h> #include <memory> Loading @@ -39,6 +40,13 @@ #include "android/binder_parcel.h" #endif #include "android_nio_utils.h" #include "perfetto/public/abi/track_event_abi.h" #include "perfetto/public/producer.h" #include "perfetto/public/protos/trace/track_event/track_event.pzc.h" #include "perfetto/public/te_category_macros.h" #include "perfetto/public/te_macros.h" #include "perfetto/public/track_event.h" #include "tracing_perfetto.h" #define DEBUG_PARCEL 0 Loading Loading @@ -175,6 +183,70 @@ private: namespace bitmap { #define PROTO_FIELDS(size, width, height, density, config, is_mutable, pixel_storage_type, \ bitmap_id) \ PERFETTO_TE_PROTO_FIELDS(PERFETTO_TE_PROTO_FIELD_NESTED( \ /* perfetto_protos_TrackEvent_android_bitmap_field_number */ 2005, \ PERFETTO_TE_PROTO_FIELD_VARINT(1, size), PERFETTO_TE_PROTO_FIELD_VARINT(2, width), \ PERFETTO_TE_PROTO_FIELD_VARINT(3, height), PERFETTO_TE_PROTO_FIELD_VARINT(4, density), \ PERFETTO_TE_PROTO_FIELD_VARINT(5, config), \ PERFETTO_TE_PROTO_FIELD_VARINT(6, is_mutable ? 1 : 0), \ PERFETTO_TE_PROTO_FIELD_VARINT(7, pixel_storage_type), \ PERFETTO_TE_PROTO_FIELD_VARINT(8, bitmap_id))) static void traceSliceBeginWithGlobalFlow(const char* name, uint64_t bitmap_id, int64_t size, int32_t width, int32_t height, int32_t density, int32_t config, bool is_mutable, int32_t pixel_storage_type, uint64_t parcel_id) { struct PerfettoTeCategory* perfettoTeCategory = tracing_perfetto::getPerfettoCategory(ATRACE_TAG_GRAPHICS); if (perfettoTeCategory) { PERFETTO_TE(*perfettoTeCategory, PERFETTO_TE_SLICE_BEGIN(name), PROTO_FIELDS(size, width, height, density, config, is_mutable, pixel_storage_type, bitmap_id), PERFETTO_TE_FLOW(PerfettoTeGlobalFlow(parcel_id))); } } static void traceSliceBeginWithGlobalTerminatingFlow(const char* name, uint64_t bitmap_id, int64_t size, int32_t width, int32_t height, int32_t density, int32_t config, bool is_mutable, int32_t pixel_storage_type, uint64_t parcel_id) { struct PerfettoTeCategory* perfettoTeCategory = tracing_perfetto::getPerfettoCategory(ATRACE_TAG_GRAPHICS); if (perfettoTeCategory) { PERFETTO_TE(*perfettoTeCategory, PERFETTO_TE_SLICE_BEGIN(name), PROTO_FIELDS(size, width, height, density, config, is_mutable, pixel_storage_type, bitmap_id), PERFETTO_TE_TERMINATING_FLOW(PerfettoTeGlobalFlow(parcel_id))); } } static void traceSliceBegin(const char* name, uint64_t bitmap_id, int64_t size, int32_t width, int32_t height, int32_t density, int32_t config, bool is_mutable, int32_t pixel_storage_type) { struct PerfettoTeCategory* perfettoTeCategory = tracing_perfetto::getPerfettoCategory(ATRACE_TAG_GRAPHICS); if (perfettoTeCategory) { PERFETTO_TE(*perfettoTeCategory, PERFETTO_TE_SLICE_BEGIN(name), PROTO_FIELDS(size, width, height, density, config, is_mutable, pixel_storage_type, bitmap_id)); } } static void traceSliceEnd(void) { struct PerfettoTeCategory* perfettoTeCategory = tracing_perfetto::getPerfettoCategory(ATRACE_TAG_GRAPHICS); if (perfettoTeCategory) { PERFETTO_TE(*perfettoTeCategory, PERFETTO_TE_SLICE_END()); } } // Assert that bitmap's SkAlphaType is consistent with isPremultiplied. static void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) { // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is Loading Loading @@ -394,6 +466,9 @@ static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle, jint dstConfig const bool hasGainmap = original.hasGainmap(); SkBitmap src; bitmapHolder->getSkBitmap(&src); traceSliceBegin("bitmap_copy", original.getId(), src.computeByteSize(), src.width(), src.height(), 0, -1, getPremulBitmapCreateFlags(isMutable), (int32_t)original.pixelStorageType()); if (dstConfigHandle == GraphicsJNI::hardwareLegacyBitmapConfig()) { sk_sp<Bitmap> bitmap(Bitmap::allocateHardwareBitmap(src)); Loading @@ -406,6 +481,7 @@ static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle, jint dstConfig bitmap->setGainmap(std::move(gm)); } } traceSliceEnd(); return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(isMutable)); } Loading @@ -429,6 +505,7 @@ static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle, jint dstConfig gainmap->bitmap = sk_sp<Bitmap>(destAllocator.getStorageObjAndReset()); bitmap->setGainmap(std::move(gainmap)); } traceSliceEnd(); return createBitmap(env, bitmap, getPremulBitmapCreateFlags(isMutable)); } Loading @@ -446,10 +523,16 @@ static Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& ds static jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) { SkBitmap src; reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src); BitmapWrapper* wrapper = reinterpret_cast<BitmapWrapper*>(srcHandle); wrapper->getSkBitmap(&src); Bitmap& original = wrapper->bitmap(); SkColorType dstCT = src.colorType(); traceSliceBegin("Bitmap_copyAshmemConfig", original.getId(), src.computeByteSize(), src.width(), src.height(), 0, -1, !src.isImmutable(), (int32_t)original.pixelStorageType()); auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT); jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false)); traceSliceEnd(); return ret; } Loading Loading @@ -799,6 +882,15 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) { const int32_t rowBytes = p.readInt32(); const int32_t density = p.readInt32(); const int64_t sourceId = p.readInt64(); const int64_t parcel_id = p.readInt64(); if (sourceId != UNDEFINED_BITMAP_ID) { traceSliceBeginWithGlobalTerminatingFlow("Bitmap_createFromParcel", sourceId, rowBytes, width, height, density, -1, false, -1, parcel_id); } else { traceSliceBegin("Bitmap_createFromParcel", sourceId, rowBytes, width, height, density, -1, false, -1); } if (kN32_SkColorType != colorType && kRGBA_F16_SkColorType != colorType && Loading Loading @@ -871,6 +963,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) { } nativeBitmap->setSourceId(sourceId); traceSliceEnd(); return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable), nullptr, nullptr, density); #else Loading Loading @@ -898,6 +991,14 @@ static bool shouldParcelAsMutable(SkBitmap& bitmap, AParcel* parcel) { } #endif uint64_t getParcelId() { static std::atomic<uint64_t> parcelCounter{0}; uint32_t pid = getpid(); uint32_t count = parcelCounter.fetch_add(1); return (uint64_t)pid << 32 | count; } static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, jlong bitmapHandle, jint density, jobject parcel) { #ifdef __linux__ // Only Linux support parcel Loading Loading @@ -929,10 +1030,21 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, jlong bitmapHandle, j p.writeInt32(density); p.writeInt64(id); uint64_t parcel_id = getParcelId(); if (id != UNDEFINED_BITMAP_ID) { traceSliceBeginWithGlobalFlow("Bitmap_writeToParcel", id, bitmap.computeByteSize(), bitmap.width(), bitmap.height(), density, -1, !bitmap.isImmutable(), -1, parcel_id); } else { traceSliceBegin("Bitmap_writeToParcel", id, bitmap.computeByteSize(), bitmap.width(), bitmap.height(), density, -1, !bitmap.isImmutable(), -1); } // Transfer the underlying ashmem region if we have one and it's immutable. binder_status_t status; int fd = bitmapWrapper->bitmap().getAshmemFd(); if (fd >= 0 && p.allowFds() && bitmap.isImmutable()) { p.writeInt64(parcel_id); #if DEBUG_PARCEL ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as " "immutable blob (fds %s)", Loading @@ -944,6 +1056,7 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, jlong bitmapHandle, j doThrowRE(env, "Could not write bitmap blob file descriptor."); return JNI_FALSE; } traceSliceEnd(); return JNI_TRUE; } Loading @@ -952,11 +1065,13 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, jlong bitmapHandle, j ALOGD("Bitmap.writeToParcel: copying bitmap into new blob (fds %s)", p.allowFds() ? "allowed" : "forbidden"); #endif p.writeInt64(0Ull); status = writeBlob(p.get(), id, bitmap, !asMutable); if (status) { doThrowRE(env, "Could not copy bitmap to parcel blob."); return JNI_FALSE; } traceSliceEnd(); return JNI_TRUE; #else doThrowRE(env, "Cannot use parcels outside of Linux"); Loading Loading
core/jni/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -445,6 +445,8 @@ cc_library_shared_for_libandroid_runtime { "libutils", "libwebp-decode", "libwebp-encode", "libperfetto_c", "libtracing_perfetto", "libwuffs_mirror_release_c", "libz", "libimage_io", Loading
libs/hwui/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -442,6 +442,8 @@ cc_defaults { "liblog", "libminikin", "libz", "libtracing_perfetto", "libperfetto_c", ], static_libs: [ Loading
libs/hwui/jni/Bitmap.cpp +116 −1 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ #include <sys/mman.h> #include <sys/syscall.h> #include <unistd.h> #include <utils/Trace.h> #include <memory> Loading @@ -39,6 +40,13 @@ #include "android/binder_parcel.h" #endif #include "android_nio_utils.h" #include "perfetto/public/abi/track_event_abi.h" #include "perfetto/public/producer.h" #include "perfetto/public/protos/trace/track_event/track_event.pzc.h" #include "perfetto/public/te_category_macros.h" #include "perfetto/public/te_macros.h" #include "perfetto/public/track_event.h" #include "tracing_perfetto.h" #define DEBUG_PARCEL 0 Loading Loading @@ -175,6 +183,70 @@ private: namespace bitmap { #define PROTO_FIELDS(size, width, height, density, config, is_mutable, pixel_storage_type, \ bitmap_id) \ PERFETTO_TE_PROTO_FIELDS(PERFETTO_TE_PROTO_FIELD_NESTED( \ /* perfetto_protos_TrackEvent_android_bitmap_field_number */ 2005, \ PERFETTO_TE_PROTO_FIELD_VARINT(1, size), PERFETTO_TE_PROTO_FIELD_VARINT(2, width), \ PERFETTO_TE_PROTO_FIELD_VARINT(3, height), PERFETTO_TE_PROTO_FIELD_VARINT(4, density), \ PERFETTO_TE_PROTO_FIELD_VARINT(5, config), \ PERFETTO_TE_PROTO_FIELD_VARINT(6, is_mutable ? 1 : 0), \ PERFETTO_TE_PROTO_FIELD_VARINT(7, pixel_storage_type), \ PERFETTO_TE_PROTO_FIELD_VARINT(8, bitmap_id))) static void traceSliceBeginWithGlobalFlow(const char* name, uint64_t bitmap_id, int64_t size, int32_t width, int32_t height, int32_t density, int32_t config, bool is_mutable, int32_t pixel_storage_type, uint64_t parcel_id) { struct PerfettoTeCategory* perfettoTeCategory = tracing_perfetto::getPerfettoCategory(ATRACE_TAG_GRAPHICS); if (perfettoTeCategory) { PERFETTO_TE(*perfettoTeCategory, PERFETTO_TE_SLICE_BEGIN(name), PROTO_FIELDS(size, width, height, density, config, is_mutable, pixel_storage_type, bitmap_id), PERFETTO_TE_FLOW(PerfettoTeGlobalFlow(parcel_id))); } } static void traceSliceBeginWithGlobalTerminatingFlow(const char* name, uint64_t bitmap_id, int64_t size, int32_t width, int32_t height, int32_t density, int32_t config, bool is_mutable, int32_t pixel_storage_type, uint64_t parcel_id) { struct PerfettoTeCategory* perfettoTeCategory = tracing_perfetto::getPerfettoCategory(ATRACE_TAG_GRAPHICS); if (perfettoTeCategory) { PERFETTO_TE(*perfettoTeCategory, PERFETTO_TE_SLICE_BEGIN(name), PROTO_FIELDS(size, width, height, density, config, is_mutable, pixel_storage_type, bitmap_id), PERFETTO_TE_TERMINATING_FLOW(PerfettoTeGlobalFlow(parcel_id))); } } static void traceSliceBegin(const char* name, uint64_t bitmap_id, int64_t size, int32_t width, int32_t height, int32_t density, int32_t config, bool is_mutable, int32_t pixel_storage_type) { struct PerfettoTeCategory* perfettoTeCategory = tracing_perfetto::getPerfettoCategory(ATRACE_TAG_GRAPHICS); if (perfettoTeCategory) { PERFETTO_TE(*perfettoTeCategory, PERFETTO_TE_SLICE_BEGIN(name), PROTO_FIELDS(size, width, height, density, config, is_mutable, pixel_storage_type, bitmap_id)); } } static void traceSliceEnd(void) { struct PerfettoTeCategory* perfettoTeCategory = tracing_perfetto::getPerfettoCategory(ATRACE_TAG_GRAPHICS); if (perfettoTeCategory) { PERFETTO_TE(*perfettoTeCategory, PERFETTO_TE_SLICE_END()); } } // Assert that bitmap's SkAlphaType is consistent with isPremultiplied. static void assert_premultiplied(const SkImageInfo& info, bool isPremultiplied) { // kOpaque_SkAlphaType and kIgnore_SkAlphaType mean that isPremultiplied is Loading Loading @@ -394,6 +466,9 @@ static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle, jint dstConfig const bool hasGainmap = original.hasGainmap(); SkBitmap src; bitmapHolder->getSkBitmap(&src); traceSliceBegin("bitmap_copy", original.getId(), src.computeByteSize(), src.width(), src.height(), 0, -1, getPremulBitmapCreateFlags(isMutable), (int32_t)original.pixelStorageType()); if (dstConfigHandle == GraphicsJNI::hardwareLegacyBitmapConfig()) { sk_sp<Bitmap> bitmap(Bitmap::allocateHardwareBitmap(src)); Loading @@ -406,6 +481,7 @@ static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle, jint dstConfig bitmap->setGainmap(std::move(gm)); } } traceSliceEnd(); return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(isMutable)); } Loading @@ -429,6 +505,7 @@ static jobject Bitmap_copy(JNIEnv* env, jobject, jlong srcHandle, jint dstConfig gainmap->bitmap = sk_sp<Bitmap>(destAllocator.getStorageObjAndReset()); bitmap->setGainmap(std::move(gainmap)); } traceSliceEnd(); return createBitmap(env, bitmap, getPremulBitmapCreateFlags(isMutable)); } Loading @@ -446,10 +523,16 @@ static Bitmap* Bitmap_copyAshmemImpl(JNIEnv* env, SkBitmap& src, SkColorType& ds static jobject Bitmap_copyAshmem(JNIEnv* env, jobject, jlong srcHandle) { SkBitmap src; reinterpret_cast<BitmapWrapper*>(srcHandle)->getSkBitmap(&src); BitmapWrapper* wrapper = reinterpret_cast<BitmapWrapper*>(srcHandle); wrapper->getSkBitmap(&src); Bitmap& original = wrapper->bitmap(); SkColorType dstCT = src.colorType(); traceSliceBegin("Bitmap_copyAshmemConfig", original.getId(), src.computeByteSize(), src.width(), src.height(), 0, -1, !src.isImmutable(), (int32_t)original.pixelStorageType()); auto bitmap = Bitmap_copyAshmemImpl(env, src, dstCT); jobject ret = createBitmap(env, bitmap, getPremulBitmapCreateFlags(false)); traceSliceEnd(); return ret; } Loading Loading @@ -799,6 +882,15 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) { const int32_t rowBytes = p.readInt32(); const int32_t density = p.readInt32(); const int64_t sourceId = p.readInt64(); const int64_t parcel_id = p.readInt64(); if (sourceId != UNDEFINED_BITMAP_ID) { traceSliceBeginWithGlobalTerminatingFlow("Bitmap_createFromParcel", sourceId, rowBytes, width, height, density, -1, false, -1, parcel_id); } else { traceSliceBegin("Bitmap_createFromParcel", sourceId, rowBytes, width, height, density, -1, false, -1); } if (kN32_SkColorType != colorType && kRGBA_F16_SkColorType != colorType && Loading Loading @@ -871,6 +963,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) { } nativeBitmap->setSourceId(sourceId); traceSliceEnd(); return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable), nullptr, nullptr, density); #else Loading Loading @@ -898,6 +991,14 @@ static bool shouldParcelAsMutable(SkBitmap& bitmap, AParcel* parcel) { } #endif uint64_t getParcelId() { static std::atomic<uint64_t> parcelCounter{0}; uint32_t pid = getpid(); uint32_t count = parcelCounter.fetch_add(1); return (uint64_t)pid << 32 | count; } static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, jlong bitmapHandle, jint density, jobject parcel) { #ifdef __linux__ // Only Linux support parcel Loading Loading @@ -929,10 +1030,21 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, jlong bitmapHandle, j p.writeInt32(density); p.writeInt64(id); uint64_t parcel_id = getParcelId(); if (id != UNDEFINED_BITMAP_ID) { traceSliceBeginWithGlobalFlow("Bitmap_writeToParcel", id, bitmap.computeByteSize(), bitmap.width(), bitmap.height(), density, -1, !bitmap.isImmutable(), -1, parcel_id); } else { traceSliceBegin("Bitmap_writeToParcel", id, bitmap.computeByteSize(), bitmap.width(), bitmap.height(), density, -1, !bitmap.isImmutable(), -1); } // Transfer the underlying ashmem region if we have one and it's immutable. binder_status_t status; int fd = bitmapWrapper->bitmap().getAshmemFd(); if (fd >= 0 && p.allowFds() && bitmap.isImmutable()) { p.writeInt64(parcel_id); #if DEBUG_PARCEL ALOGD("Bitmap.writeToParcel: transferring immutable bitmap's ashmem fd as " "immutable blob (fds %s)", Loading @@ -944,6 +1056,7 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, jlong bitmapHandle, j doThrowRE(env, "Could not write bitmap blob file descriptor."); return JNI_FALSE; } traceSliceEnd(); return JNI_TRUE; } Loading @@ -952,11 +1065,13 @@ static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject, jlong bitmapHandle, j ALOGD("Bitmap.writeToParcel: copying bitmap into new blob (fds %s)", p.allowFds() ? "allowed" : "forbidden"); #endif p.writeInt64(0Ull); status = writeBlob(p.get(), id, bitmap, !asMutable); if (status) { doThrowRE(env, "Could not copy bitmap to parcel blob."); return JNI_FALSE; } traceSliceEnd(); return JNI_TRUE; #else doThrowRE(env, "Cannot use parcels outside of Linux"); Loading