diff options
-rw-r--r-- | libs/hwui/Android.bp | 1 | ||||
-rw-r--r-- | libs/hwui/hwui/ImageDecoder.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/jni/BitmapFactory.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/jni/BitmapRegionDecoder.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/jni/ImageDecoder.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/libhwui.map.txt | 1 | ||||
-rw-r--r-- | libs/hwui/utils/StatsUtils.cpp | 102 | ||||
-rw-r--r-- | libs/hwui/utils/StatsUtils.h | 33 | ||||
-rw-r--r-- | native/graphics/jni/Android.bp | 9 | ||||
-rw-r--r-- | native/graphics/jni/imagedecoder.cpp | 41 |
10 files changed, 183 insertions, 20 deletions
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 266c23631800..d93ad4e3255b 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -579,6 +579,7 @@ cc_defaults { "utils/Color.cpp", "utils/LinearAllocator.cpp", "utils/StringUtils.cpp", + "utils/StatsUtils.cpp", "utils/TypefaceUtils.cpp", "utils/VectorDrawableUtils.cpp", "AnimationContext.cpp", diff --git a/libs/hwui/hwui/ImageDecoder.cpp b/libs/hwui/hwui/ImageDecoder.cpp index e074a27db38f..a9a5db8181ba 100644 --- a/libs/hwui/hwui/ImageDecoder.cpp +++ b/libs/hwui/hwui/ImageDecoder.cpp @@ -27,8 +27,8 @@ #include <SkColorSpace.h> #include <SkColorType.h> #include <SkEncodedOrigin.h> -#include <SkImageInfo.h> #include <SkGainmapInfo.h> +#include <SkImageInfo.h> #include <SkMatrix.h> #include <SkPaint.h> #include <SkPngChunkReader.h> @@ -43,6 +43,8 @@ #include <memory> +#include "modules/skcms/src/skcms_public.h" + using namespace android; sk_sp<SkColorSpace> ImageDecoder::getDefaultColorSpace() const { diff --git a/libs/hwui/jni/BitmapFactory.cpp b/libs/hwui/jni/BitmapFactory.cpp index 49a7f73fb3a3..8b43f1db84af 100644 --- a/libs/hwui/jni/BitmapFactory.cpp +++ b/libs/hwui/jni/BitmapFactory.cpp @@ -10,6 +10,7 @@ #include <stdint.h> #include <stdio.h> #include <sys/stat.h> +#include <utils/StatsUtils.h> #include <memory> @@ -630,6 +631,7 @@ static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream, } bitmap::reinitBitmap(env, javaBitmap, outputBitmap.info(), isPremultiplied); outputBitmap.notifyPixelsChanged(); + uirenderer::logBitmapDecode(*reuseBitmap); // If a java bitmap was passed in for reuse, pass it back return javaBitmap; } @@ -650,6 +652,7 @@ static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream, } } + uirenderer::logBitmapDecode(*hardwareBitmap); return bitmap::createBitmap(env, hardwareBitmap.release(), bitmapCreateFlags, ninePatchChunk, ninePatchInsets, -1); } @@ -659,6 +662,7 @@ static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream, heapBitmap->setGainmap(std::move(gainmap)); } + uirenderer::logBitmapDecode(*heapBitmap); // now create the java bitmap return bitmap::createBitmap(env, heapBitmap, bitmapCreateFlags, ninePatchChunk, ninePatchInsets, -1); diff --git a/libs/hwui/jni/BitmapRegionDecoder.cpp b/libs/hwui/jni/BitmapRegionDecoder.cpp index f7e8e073a272..5ffd5b9016d8 100644 --- a/libs/hwui/jni/BitmapRegionDecoder.cpp +++ b/libs/hwui/jni/BitmapRegionDecoder.cpp @@ -19,6 +19,7 @@ #include <HardwareBitmapUploader.h> #include <androidfw/Asset.h> #include <sys/stat.h> +#include <utils/StatsUtils.h> #include <memory> @@ -376,6 +377,7 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in recycledBitmap->setGainmap(std::move(gainmap)); } bitmap::reinitBitmap(env, javaBitmap, recycledBitmap->info(), !requireUnpremul); + uirenderer::logBitmapDecode(*recycledBitmap); return javaBitmap; } @@ -392,12 +394,14 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in hardwareBitmap->setGainmap(std::move(gm)); } } + uirenderer::logBitmapDecode(*hardwareBitmap); return bitmap::createBitmap(env, hardwareBitmap.release(), bitmapCreateFlags); } Bitmap* heapBitmap = heapAlloc.getStorageObjAndReset(); if (hasGainmap && heapBitmap != nullptr) { heapBitmap->setGainmap(std::move(gainmap)); } + uirenderer::logBitmapDecode(*heapBitmap); return android::bitmap::createBitmap(env, heapBitmap, bitmapCreateFlags); } diff --git a/libs/hwui/jni/ImageDecoder.cpp b/libs/hwui/jni/ImageDecoder.cpp index aebc4db37898..90fd3d87cba7 100644 --- a/libs/hwui/jni/ImageDecoder.cpp +++ b/libs/hwui/jni/ImageDecoder.cpp @@ -37,6 +37,7 @@ #include <hwui/Bitmap.h> #include <hwui/ImageDecoder.h> #include <sys/stat.h> +#include <utils/StatsUtils.h> #include "Bitmap.h" #include "BitmapFactory.h" @@ -485,6 +486,7 @@ static jobject ImageDecoder_nDecodeBitmap(JNIEnv* env, jobject /*clazz*/, jlong hwBitmap->setGainmap(std::move(gm)); } } + uirenderer::logBitmapDecode(*hwBitmap); return bitmap::createBitmap(env, hwBitmap.release(), bitmapCreateFlags, ninePatchChunk, ninePatchInsets); } @@ -498,6 +500,8 @@ static jobject ImageDecoder_nDecodeBitmap(JNIEnv* env, jobject /*clazz*/, jlong nativeBitmap->setImmutable(); } + + uirenderer::logBitmapDecode(*nativeBitmap); return bitmap::createBitmap(env, nativeBitmap.release(), bitmapCreateFlags, ninePatchChunk, ninePatchInsets); } diff --git a/libs/hwui/libhwui.map.txt b/libs/hwui/libhwui.map.txt index 2414299321a9..b5591941453d 100644 --- a/libs/hwui/libhwui.map.txt +++ b/libs/hwui/libhwui.map.txt @@ -67,6 +67,7 @@ LIBHWUI_PLATFORM { SkFILEStream::SkFILEStream*; SkImageInfo::*; SkMemoryStream::SkMemoryStream*; + android::uirenderer::logBitmapDecode*; }; local: *; diff --git a/libs/hwui/utils/StatsUtils.cpp b/libs/hwui/utils/StatsUtils.cpp new file mode 100644 index 000000000000..5c4027e1a846 --- /dev/null +++ b/libs/hwui/utils/StatsUtils.cpp @@ -0,0 +1,102 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef __ANDROID__ +#include <dlfcn.h> +#include <log/log.h> +#include <statslog_hwui.h> +#include <statssocket_lazy.h> +#include <utils/Errors.h> + +#include <mutex> +#endif + +#include <unistd.h> + +#include "StatsUtils.h" + +namespace android { +namespace uirenderer { + +#ifdef __ANDROID__ + +namespace { + +int32_t toStatsColorSpaceTransfer(skcms_TFType transferType) { + switch (transferType) { + case skcms_TFType_sRGBish: + return stats::IMAGE_DECODED__COLOR_SPACE_TRANSFER__COLOR_SPACE_TRANSFER_SRGBISH; + case skcms_TFType_PQish: + return stats::IMAGE_DECODED__COLOR_SPACE_TRANSFER__COLOR_SPACE_TRANSFER_PQISH; + case skcms_TFType_HLGish: + return stats::IMAGE_DECODED__COLOR_SPACE_TRANSFER__COLOR_SPACE_TRANSFER_HLGISH; + default: + return stats::IMAGE_DECODED__COLOR_SPACE_TRANSFER__COLOR_SPACE_TRANSFER_UNKNOWN; + } +} + +int32_t toStatsBitmapFormat(SkColorType type) { + switch (type) { + case kAlpha_8_SkColorType: + return stats::IMAGE_DECODED__FORMAT__BITMAP_FORMAT_A_8; + case kRGB_565_SkColorType: + return stats::IMAGE_DECODED__FORMAT__BITMAP_FORMAT_RGB_565; + case kN32_SkColorType: + return stats::IMAGE_DECODED__FORMAT__BITMAP_FORMAT_ARGB_8888; + case kRGBA_F16_SkColorType: + return stats::IMAGE_DECODED__FORMAT__BITMAP_FORMAT_RGBA_F16; + case kRGBA_1010102_SkColorType: + return stats::IMAGE_DECODED__FORMAT__BITMAP_FORMAT_RGBA_1010102; + default: + return stats::IMAGE_DECODED__FORMAT__BITMAP_FORMAT_UNKNOWN; + } +} + +} // namespace + +#endif + +void logBitmapDecode(const SkImageInfo& info, bool hasGainmap) { +#ifdef __ANDROID__ + + if (!statssocket::lazy::IsAvailable()) { + std::once_flag once; + std::call_once(once, []() { ALOGD("libstatssocket not available, dropping stats"); }); + return; + } + + skcms_TFType tfnType = skcms_TFType_Invalid; + + if (info.colorSpace()) { + skcms_TransferFunction tfn; + info.colorSpace()->transferFn(&tfn); + tfnType = skcms_TransferFunction_getType(&tfn); + } + + auto status = + stats::stats_write(uirenderer::stats::IMAGE_DECODED, static_cast<int32_t>(getuid()), + uirenderer::toStatsColorSpaceTransfer(tfnType), hasGainmap, + uirenderer::toStatsBitmapFormat(info.colorType())); + ALOGW_IF(status != OK, "Image decoding logging dropped!"); +#endif +} + +void logBitmapDecode(const Bitmap& bitmap) { + logBitmapDecode(bitmap.info(), bitmap.hasGainmap()); +} + +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/utils/StatsUtils.h b/libs/hwui/utils/StatsUtils.h new file mode 100644 index 000000000000..0c247014a8eb --- /dev/null +++ b/libs/hwui/utils/StatsUtils.h @@ -0,0 +1,33 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <SkBitmap.h> +#include <SkColorSpace.h> +#include <SkColorType.h> +#include <cutils/compiler.h> +#include <hwui/Bitmap.h> + +namespace android { +namespace uirenderer { + +ANDROID_API void logBitmapDecode(const SkImageInfo& info, bool hasGainmap); + +ANDROID_API void logBitmapDecode(const Bitmap& bitmap); + +} // namespace uirenderer +} // namespace android diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp index 0fb3049f63d8..23dd9b7aee37 100644 --- a/native/graphics/jni/Android.bp +++ b/native/graphics/jni/Android.bp @@ -48,7 +48,9 @@ cc_library_shared { "libhwui_internal_headers", ], - static_libs: ["libarect"], + static_libs: [ + "libarect", + ], host_supported: true, target: { @@ -60,6 +62,11 @@ cc_library_shared { shared_libs: [ "libandroid", ], + static_libs: [ + "libstatslog_hwui", + "libstatspull_lazy", + "libstatssocket_lazy", + ], version_script: "libjnigraphics.map.txt", }, host: { diff --git a/native/graphics/jni/imagedecoder.cpp b/native/graphics/jni/imagedecoder.cpp index e18b4a9d2420..cb95bcf5d2b1 100644 --- a/native/graphics/jni/imagedecoder.cpp +++ b/native/graphics/jni/imagedecoder.cpp @@ -14,18 +14,9 @@ * limitations under the License. */ -#include "aassetstreamadaptor.h" - -#include <android/asset_manager.h> -#include <android/bitmap.h> -#include <android/data_space.h> -#include <android/imagedecoder.h> #include <MimeType.h> -#include <android/rect.h> -#include <hwui/ImageDecoder.h> -#include <log/log.h> -#include <SkAndroidCodec.h> #include <SkAlphaType.h> +#include <SkAndroidCodec.h> #include <SkCodec.h> #include <SkCodecAnimation.h> #include <SkColorSpace.h> @@ -35,14 +26,24 @@ #include <SkRefCnt.h> #include <SkSize.h> #include <SkStream.h> -#include <utils/Color.h> - +#include <android/asset_manager.h> +#include <android/bitmap.h> +#include <android/data_space.h> +#include <android/imagedecoder.h> +#include <android/rect.h> #include <fcntl.h> -#include <limits> -#include <optional> +#include <hwui/ImageDecoder.h> +#include <log/log.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> +#include <utils/Color.h> +#include <utils/StatsUtils.h> + +#include <limits> +#include <optional> + +#include "aassetstreamadaptor.h" using namespace android; @@ -400,9 +401,7 @@ size_t AImageDecoder_getMinimumStride(AImageDecoder* decoder) { return info.minRowBytes(); } -int AImageDecoder_decodeImage(AImageDecoder* decoder, - void* pixels, size_t stride, - size_t size) { +int AImageDecoder_decodeImage(AImageDecoder* decoder, void* pixels, size_t stride, size_t size) { if (!decoder || !pixels || !stride) { return ANDROID_IMAGE_DECODER_BAD_PARAMETER; } @@ -419,7 +418,13 @@ int AImageDecoder_decodeImage(AImageDecoder* decoder, return ANDROID_IMAGE_DECODER_FINISHED; } - return ResultToErrorCode(imageDecoder->decode(pixels, stride)); + const auto result = ResultToErrorCode(imageDecoder->decode(pixels, stride)); + + if (result == ANDROID_IMAGE_DECODER_SUCCESS) { + uirenderer::logBitmapDecode(imageDecoder->getOutputInfo(), false); + } + + return result; } void AImageDecoder_delete(AImageDecoder* decoder) { |