From 1fcf501bee2bf97e5972701ddc7f9835dcea0582 Mon Sep 17 00:00:00 2001 From: Xiao Huang Date: Wed, 26 Apr 2023 16:50:42 +0000 Subject: Determine HEIF support by checking HEVC ImageDecoder.isMimeTypeSupported always returns true for HEIF and HEIC, however, according to CDD, this support is optional, and they are only supported when the HEVC is supported by the device. This change is to fix inconsistency with CDD 5.1.5, and won't impact handhelds or TV, as HEVC is a must for them. For auto and watch, HEVC is not supported at all. So this change is safe. Bug: 278664575 Test: atest BitmapFactoryTest ImageDecoderTest Change-Id: Iecceb6f2a498fddc045ccce331f6fcef5debd2f5 --- graphics/java/android/graphics/ImageDecoder.java | 34 ++++++++++++++++++++---- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java index 302c72ead52e..fc286faa41d1 100644 --- a/graphics/java/android/graphics/ImageDecoder.java +++ b/graphics/java/android/graphics/ImageDecoder.java @@ -40,6 +40,7 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.NinePatchDrawable; import android.media.MediaCodecInfo; import android.media.MediaCodecList; +import android.media.MediaFormat; import android.net.Uri; import android.os.Build; import android.os.Trace; @@ -914,8 +915,6 @@ public final class ImageDecoder implements AutoCloseable { case "image/jpeg": case "image/webp": case "image/gif": - case "image/heif": - case "image/heic": case "image/bmp": case "image/x-ico": case "image/vnd.wap.wbmp": @@ -930,6 +929,9 @@ public final class ImageDecoder implements AutoCloseable { case "image/x-pentax-pef": case "image/x-samsung-srw": return true; + case "image/heif": + case "image/heic": + return isHevcDecoderSupported(); case "image/avif": return isP010SupportedForAV1(); default: @@ -2067,6 +2069,28 @@ public final class ImageDecoder implements AutoCloseable { return decodeBitmapImpl(src, null); } + private static boolean sIsHevcDecoderSupported = false; + private static boolean sIsHevcDecoderSupportedInitialized = false; + private static final Object sIsHevcDecoderSupportedLock = new Object(); + + /* + * Check if HEVC decoder is supported by the device. + */ + @SuppressWarnings("AndroidFrameworkCompatChange") + private static boolean isHevcDecoderSupported() { + synchronized (sIsHevcDecoderSupportedLock) { + if (sIsHevcDecoderSupportedInitialized) { + return sIsHevcDecoderSupported; + } + MediaFormat format = new MediaFormat(); + format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_HEVC); + MediaCodecList mcl = new MediaCodecList(MediaCodecList.ALL_CODECS); + sIsHevcDecoderSupported = mcl.findDecoderForFormat(format) != null; + sIsHevcDecoderSupportedInitialized = true; + return sIsHevcDecoderSupported; + } + } + private static boolean sIsP010SupportedForAV1 = false; private static boolean sIsP010SupportedForHEVC = false; private static boolean sIsP010SupportedFlagsInitialized = false; @@ -2111,14 +2135,14 @@ public final class ImageDecoder implements AutoCloseable { continue; } for (String mediaType : mediaCodecInfo.getSupportedTypes()) { - if (mediaType.equalsIgnoreCase("video/av01") - || mediaType.equalsIgnoreCase("video/hevc")) { + if (mediaType.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AV1) + || mediaType.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_HEVC)) { MediaCodecInfo.CodecCapabilities codecCapabilities = mediaCodecInfo.getCapabilitiesForType(mediaType); for (int i = 0; i < codecCapabilities.colorFormats.length; ++i) { if (codecCapabilities.colorFormats[i] == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010) { - if (mediaType.equalsIgnoreCase("video/av01")) { + if (mediaType.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_AV1)) { sIsP010SupportedForAV1 = true; } else { sIsP010SupportedForHEVC = true; -- cgit v1.2.3-59-g8ed1b From 5f8b51b8b05837d83b6896c02ff912e4adb09fa6 Mon Sep 17 00:00:00 2001 From: Xiao Huang Date: Thu, 27 Apr 2023 15:49:46 +0000 Subject: Use REGULAR_CODECS instead of ALL_CODECS Checking if P010 or HEVC is supported does not need ALL_CODECS, which includes codecs supporting special features like secure or tunnel. REGULAR_CODECS is enough to use here. Bug: 278664575 Test: atest BitmapFactoryTest ImageDecoderTest Change-Id: Id7f27ec204d85e1c177bc3101b4be81f21affeae --- graphics/java/android/graphics/ImageDecoder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/graphics/java/android/graphics/ImageDecoder.java b/graphics/java/android/graphics/ImageDecoder.java index fc286faa41d1..dd4b58eb83dc 100644 --- a/graphics/java/android/graphics/ImageDecoder.java +++ b/graphics/java/android/graphics/ImageDecoder.java @@ -2084,7 +2084,7 @@ public final class ImageDecoder implements AutoCloseable { } MediaFormat format = new MediaFormat(); format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_HEVC); - MediaCodecList mcl = new MediaCodecList(MediaCodecList.ALL_CODECS); + MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS); sIsHevcDecoderSupported = mcl.findDecoderForFormat(format) != null; sIsHevcDecoderSupportedInitialized = true; return sIsHevcDecoderSupported; @@ -2129,7 +2129,7 @@ public final class ImageDecoder implements AutoCloseable { * Checks if the device supports decoding 10-bit for the given mime type. */ private static void checkP010SupportforAV1HEVC() { - MediaCodecList codecList = new MediaCodecList(MediaCodecList.ALL_CODECS); + MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS); for (MediaCodecInfo mediaCodecInfo : codecList.getCodecInfos()) { if (mediaCodecInfo.isEncoder()) { continue; -- cgit v1.2.3-59-g8ed1b