Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd640e69 authored by Songyue Han's avatar Songyue Han
Browse files

Revert^2 "Java and JNI support for native AudioCapabilities."

Bug: 306023029
Bug: 388337603

Test: atest MediaCodecCapabilitiesTest
Test: atp v2/android-virtual-infra/test_mapping/presubmit-avd

Flag: android.media.codec.native_capabilites

Change-Id: Iff33b8a3a3ddba6f449c52556f2097bb52230bbb
parent c416c737
Loading
Loading
Loading
Loading
+534 −364
Original line number Diff line number Diff line
@@ -1106,10 +1106,11 @@ public final class MediaCodecInfo {
                // does not contain features and bitrate specific keys, keep only keys relevant for
                // a level check.
                Map<String, Object> levelCriticalFormatMap = new HashMap<>(map);
                final Set<String> criticalKeys =
                    isVideo() ? VideoCapabilities.VIDEO_LEVEL_CRITICAL_FORMAT_KEYS :
                    isAudio() ? AudioCapabilities.AUDIO_LEVEL_CRITICAL_FORMAT_KEYS :
                    null;
                final Set<String> criticalKeys = isVideo()
                        ? VideoCapabilities.VIDEO_LEVEL_CRITICAL_FORMAT_KEYS
                        : isAudio()
                        ? AudioCapabilities.AudioCapsLegacyImpl.AUDIO_LEVEL_CRITICAL_FORMAT_KEYS
                        : null;

                // critical keys will always contain KEY_MIME, but should also contain others to be
                // meaningful
@@ -1421,6 +1422,28 @@ public final class MediaCodecInfo {
     */
    public static final class AudioCapabilities {
        private static final String TAG = "AudioCapabilities";

        /* package private */ interface AudioCapsIntf {
            public Range<Integer> getBitrateRange();

            public int[] getSupportedSampleRates();

            public Range<Integer>[] getSupportedSampleRateRanges();

            public int getMaxInputChannelCount();

            public int getMinInputChannelCount();

            public Range<Integer>[] getInputChannelCountRanges();

            public boolean isSampleRateSupported(int sampleRate);

            public void getDefaultFormat(MediaFormat format);

            public boolean supportsFormat(MediaFormat format);
        }

        /* package private */ static final class AudioCapsLegacyImpl implements AudioCapsIntf {
            private CodecCapabilities mParent;
            private Range<Integer> mBitrateRange;

@@ -1430,47 +1453,19 @@ public final class MediaCodecInfo {

            private static final int MAX_INPUT_CHANNEL_COUNT = 30;

        /**
         * Returns the range of supported bitrates in bits/second.
         */
            public Range<Integer> getBitrateRange() {
                return mBitrateRange;
            }

        /**
         * Returns the array of supported sample rates if the codec
         * supports only discrete values.  Otherwise, it returns
         * {@code null}.  The array is sorted in ascending order.
         */
            public int[] getSupportedSampleRates() {
            return mSampleRates != null ? Arrays.copyOf(mSampleRates, mSampleRates.length) : null;
                return mSampleRates != null ? Arrays.copyOf(mSampleRates, mSampleRates.length)
                        : null;
            }

        /**
         * Returns the array of supported sample rate ranges.  The
         * array is sorted in ascending order, and the ranges are
         * distinct.
         */
            public Range<Integer>[] getSupportedSampleRateRanges() {
                return Arrays.copyOf(mSampleRateRanges, mSampleRateRanges.length);
            }

        /**
         * Returns the maximum number of input channels supported.
         *
         * Through {@link android.os.Build.VERSION_CODES#R}, this method indicated support
         * for any number of input channels between 1 and this maximum value.
         *
         * As of {@link android.os.Build.VERSION_CODES#S},
         * the implied lower limit of 1 channel is no longer valid.
         * As of {@link android.os.Build.VERSION_CODES#S}, {@link #getMaxInputChannelCount} is
         * superseded by {@link #getInputChannelCountRanges},
         * which returns an array of ranges of channels.
         * The {@link #getMaxInputChannelCount} method will return the highest value
         * in the ranges returned by {@link #getInputChannelCountRanges}
         *
         */
        @IntRange(from = 1, to = 255)
            public int getMaxInputChannelCount() {
                int overall_max = 0;
                for (int i = mInputChannelRanges.length - 1; i >= 0; i--) {
@@ -1482,14 +1477,6 @@ public final class MediaCodecInfo {
                return overall_max;
            }

        /**
         * Returns the minimum number of input channels supported.
         * This is often 1, but does vary for certain mime types.
         *
         * This returns the lowest channel count in the ranges returned by
         * {@link #getInputChannelCountRanges}.
         */
        @IntRange(from = 1, to = 255)
            public int getMinInputChannelCount() {
                int overall_min = MAX_INPUT_CHANNEL_COUNT;
                for (int i = mInputChannelRanges.length - 1; i >= 0; i--) {
@@ -1501,27 +1488,20 @@ public final class MediaCodecInfo {
                return overall_min;
            }

        /*
         * Returns an array of ranges representing the number of input channels supported.
         * The codec supports any number of input channels within this range.
         *
         * This supersedes the {@link #getMaxInputChannelCount} method.
         *
         * For many codecs, this will be a single range [1..N], for some N.
         */
        @SuppressLint("ArrayReturn")
        @NonNull
            public Range<Integer>[] getInputChannelCountRanges() {
                return Arrays.copyOf(mInputChannelRanges, mInputChannelRanges.length);
            }

            /* no public constructor */
        private AudioCapabilities() { }
            private AudioCapsLegacyImpl() { }

        /** @hide */
        public static AudioCapabilities create(
            public static AudioCapsLegacyImpl create(
                    MediaFormat info, CodecCapabilities parent) {
            AudioCapabilities caps = new AudioCapabilities();
                if (GetFlag(() -> android.media.codec.Flags.nativeCapabilites())) {
                    Log.d(TAG, "Legacy implementation is called while native flag is on.");
                }

                AudioCapsLegacyImpl caps = new AudioCapsLegacyImpl();
                caps.init(info, parent);
                return caps;
            }
@@ -1537,10 +1517,10 @@ public final class MediaCodecInfo {
                mBitrateRange = Range.create(0, Integer.MAX_VALUE);
                mInputChannelRanges = new Range[] {Range.create(1, MAX_INPUT_CHANNEL_COUNT)};
                // mBitrateRange = Range.create(1, 320000);
            final int minSampleRate = SystemProperties.
                getInt("ro.mediacodec.min_sample_rate", 7350);
            final int maxSampleRate = SystemProperties.
                getInt("ro.mediacodec.max_sample_rate", 192000);
                final int minSampleRate = SystemProperties
                        .getInt("ro.mediacodec.min_sample_rate", 7350);
                final int maxSampleRate = SystemProperties
                        .getInt("ro.mediacodec.max_sample_rate", 192000);
                mSampleRateRanges = new Range[] { Range.create(minSampleRate, maxSampleRate) };
                mSampleRates = null;
            }
@@ -1564,9 +1544,6 @@ public final class MediaCodecInfo {
                return true;
            }

        /**
         * Query whether the sample rate is supported by the codec.
         */
            public boolean isSampleRateSupported(int sampleRate) {
                return supports(sampleRate, null);
            }
@@ -1687,14 +1664,16 @@ public final class MediaCodecInfo {
                                break;
                            case CodecProfileLevel.DTS_HDProfileHRA:
                            case CodecProfileLevel.DTS_HDProfileMA:
                            sampleRates = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 };
                                sampleRates =
                                        new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 };
                                bitRates = Range.create(96000, 24500000);
                                break;
                            default:
                                Log.w(TAG, "Unrecognized profile "
                                        + profileLevel.profile + " for " + mime);
                                mParent.mError |= ERROR_UNRECOGNIZED;
                            sampleRates = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 };
                                sampleRates =
                                        new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 };
                                bitRates = Range.create(96000, 24500000);
                        }
                    }
@@ -1708,7 +1687,8 @@ public final class MediaCodecInfo {
                                maxChannels = 10;
                                break;
                            case CodecProfileLevel.DTS_UHDProfileP1:
                            sampleRates = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 };
                                sampleRates =
                                        new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 };
                                bitRates = Range.create(96000, 24500000);
                                maxChannels = 32;
                                break;
@@ -1716,7 +1696,8 @@ public final class MediaCodecInfo {
                                Log.w(TAG, "Unrecognized profile "
                                        + profileLevel.profile + " for " + mime);
                                mParent.mError |= ERROR_UNRECOGNIZED;
                            sampleRates = new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 };
                                sampleRates =
                                        new int[]{ 44100, 48000, 88200, 96000, 176400, 192000 };
                                bitRates = Range.create(96000, 24500000);
                                maxChannels = 32;
                        }
@@ -1824,8 +1805,8 @@ public final class MediaCodecInfo {
            /* package private */
            // must not contain KEY_PROFILE
            static final Set<String> AUDIO_LEVEL_CRITICAL_FORMAT_KEYS = Set.of(
                // We don't set level-specific limits for audio codecs today. Key candidates would
                // be sample rate, bit rate or channel count.
                    // We don't set level-specific limits for audio codecs today. Key candidates
                    // would be sample rate, bit rate or channel count.
                    // MediaFormat.KEY_SAMPLE_RATE,
                    // MediaFormat.KEY_CHANNEL_COUNT,
                    // MediaFormat.KEY_BIT_RATE,
@@ -1852,6 +1833,189 @@ public final class MediaCodecInfo {
            }
        }

        /* package private */ static final class AudioCapsNativeImpl implements AudioCapsIntf {
            private long mNativeContext; // accessed by native methods

            private Range<Integer> mBitrateRange;
            private int[] mSampleRates;
            private Range<Integer>[] mSampleRateRanges;
            private Range<Integer>[] mInputChannelRanges;

            /**
             * Constructor used by JNI.
             *
             * The Java AudioCapabilities object keeps these subobjects to avoid recontruction.
             */
            /* package private */ AudioCapsNativeImpl(Range<Integer> bitrateRange,
                    int[] sampleRates, Range<Integer>[] sampleRateRanges,
                    Range<Integer>[] inputChannelRanges) {
                mBitrateRange = bitrateRange;
                mSampleRates = sampleRates;
                mSampleRateRanges = sampleRateRanges;
                mInputChannelRanges = inputChannelRanges;
            }

            /* no public constructor */
            private AudioCapsNativeImpl() { }

            public Range<Integer> getBitrateRange() {
                return mBitrateRange;
            }

            public int[] getSupportedSampleRates() {
                return mSampleRates != null ? Arrays.copyOf(mSampleRates, mSampleRates.length)
                        : null;
            }

            public Range<Integer>[] getSupportedSampleRateRanges() {
                return Arrays.copyOf(mSampleRateRanges, mSampleRateRanges.length);
            }

            public Range<Integer>[] getInputChannelCountRanges() {
                return Arrays.copyOf(mInputChannelRanges, mInputChannelRanges.length);
            }

            public int getMaxInputChannelCount() {
                return native_getMaxInputChannelCount();
            }

            public int getMinInputChannelCount() {
                return native_getMinInputChannelCount();
            }

            public boolean isSampleRateSupported(int sampleRate) {
                return native_isSampleRateSupported(sampleRate);
            }

            // This API is for internal Java implementation only. Should not be called.
            public void getDefaultFormat(MediaFormat format) {
                throw new UnsupportedOperationException(
                    "Java Implementation should not call native implemenatation");
            }

            // This API is for internal Java implementation only. Should not be called.
            public boolean supportsFormat(MediaFormat format) {
                throw new UnsupportedOperationException(
                    "Java Implementation should not call native implemenatation");
            }

            private native int native_getMaxInputChannelCount();
            private native int native_getMinInputChannelCount();
            private native boolean native_isSampleRateSupported(int sampleRate);
            private static native void native_init();

            static {
                System.loadLibrary("media_jni");
                native_init();
            }
        }

        private AudioCapsIntf mImpl;

        /** @hide */
        public static AudioCapabilities create(
                MediaFormat info, CodecCapabilities parent) {
            AudioCapsLegacyImpl impl = AudioCapsLegacyImpl.create(info, parent);
            AudioCapabilities caps = new AudioCapabilities(impl);
            return caps;
        }

        /* package private */ AudioCapabilities(AudioCapsIntf impl) {
            mImpl = impl;
        }

        /* no public constructor */
        private AudioCapabilities() { }

        /**
         * Returns the range of supported bitrates in bits/second.
         */
        public Range<Integer> getBitrateRange() {
            return mImpl.getBitrateRange();
        }

        /**
         * Returns the array of supported sample rates if the codec
         * supports only discrete values.  Otherwise, it returns
         * {@code null}.  The array is sorted in ascending order.
         */
        public int[] getSupportedSampleRates() {
            return mImpl.getSupportedSampleRates();
        }

        /**
         * Returns the array of supported sample rate ranges.  The
         * array is sorted in ascending order, and the ranges are
         * distinct.
         */
        public Range<Integer>[] getSupportedSampleRateRanges() {
            return mImpl.getSupportedSampleRateRanges();
        }

        /*
         * Returns an array of ranges representing the number of input channels supported.
         * The codec supports any number of input channels within this range.
         *
         * This supersedes the {@link #getMaxInputChannelCount} method.
         *
         * For many codecs, this will be a single range [1..N], for some N.
         */
        @SuppressLint("ArrayReturn")
        @NonNull
        public Range<Integer>[] getInputChannelCountRanges() {
            return mImpl.getInputChannelCountRanges();
        }

        /**
         * Returns the maximum number of input channels supported.
         *
         * Through {@link android.os.Build.VERSION_CODES#R}, this method indicated support
         * for any number of input channels between 1 and this maximum value.
         *
         * As of {@link android.os.Build.VERSION_CODES#S},
         * the implied lower limit of 1 channel is no longer valid.
         * As of {@link android.os.Build.VERSION_CODES#S}, {@link #getMaxInputChannelCount} is
         * superseded by {@link #getInputChannelCountRanges},
         * which returns an array of ranges of channels.
         * The {@link #getMaxInputChannelCount} method will return the highest value
         * in the ranges returned by {@link #getInputChannelCountRanges}
         *
         */
        @IntRange(from = 1, to = 255)
        public int getMaxInputChannelCount() {
            return mImpl.getMaxInputChannelCount();
        }

        /**
         * Returns the minimum number of input channels supported.
         * This is often 1, but does vary for certain mime types.
         *
         * This returns the lowest channel count in the ranges returned by
         * {@link #getInputChannelCountRanges}.
         */
        @IntRange(from = 1, to = 255)
        public int getMinInputChannelCount() {
            return mImpl.getMinInputChannelCount();
        }

        /**
         * Query whether the sample rate is supported by the codec.
         */
        public boolean isSampleRateSupported(int sampleRate) {
            return mImpl.isSampleRateSupported(sampleRate);
        }

        /** @hide */
        public void getDefaultFormat(MediaFormat format) {
            mImpl.getDefaultFormat(format);
        }

        /** @hide */
        public boolean supportsFormat(MediaFormat format) {
            return mImpl.supportsFormat(format);
        }
    }

    /** @hide */
    @IntDef(prefix = {"SECURITY_MODEL_"}, value = {
        SECURITY_MODEL_SANDBOXED,
@@ -5115,4 +5279,10 @@ public final class MediaCodecInfo {
                mName, mCanonicalName, mFlags,
                caps.toArray(new CodecCapabilities[caps.size()]));
    }

    /* package private */ class GenericHelper {
        private static Range<Integer> constructIntegerRange(int lower, int upper) {
            return Range.create(Integer.valueOf(lower), Integer.valueOf(upper));
        }
    }
}
+33 −31
Original line number Diff line number Diff line
@@ -25,10 +25,12 @@ cc_library_shared {
    min_sdk_version: "",

    srcs: [
        "JetPlayer.cpp",
        "android_media_CodecCapabilities.cpp",
        "android_media_JetPlayer.cpp",
        "android_media_MediaCrypto.cpp",
        "android_media_MediaCodec.cpp",
        "android_media_MediaCodecList.cpp",
        "android_media_MediaCrypto.cpp",
        "android_media_MediaDataSource.cpp",
        "android_media_MediaDescrambler.cpp",
        "android_media_MediaDrm.cpp",
@@ -46,49 +48,49 @@ cc_library_shared {
        "android_mtp_MtpDatabase.cpp",
        "android_mtp_MtpDevice.cpp",
        "android_mtp_MtpServer.cpp",
        "JetPlayer.cpp",
    ],

    shared_libs: [
        "android.companion.virtual.virtualdevice_aidl-cpp",
        "android.hardware.cas.native@1.0",
        "android.hardware.cas@1.0",
        "android.hardware.drm-V1-ndk",
        "android.hardware.drm@1.3",
        "android.hardware.drm@1.4",
        "android.hardware.tv.tuner-V3-ndk",
        "android.hidl.memory@1.0",
        "android.hidl.token@1.0-utils",
        "audioclient-types-aidl-cpp",
        "av-types-aidl-cpp",
        "framework-permission-aidl-cpp",
        "libandroid_runtime",
        "libandroidfw",
        "libaudioclient",
        "libnativehelper",
        "libnativewindow",
        "libutils",
        "libbinder",
        "libcamera_client",
        "libcutils",
        "libgui",
        "libhidlallocatorutils",
        "libhidlbase",
        "libhwui",
        "liblog",
        "libmedia",
        "libmedia_codeclist",
        "libmedia_codeclist_capabilities",
        "libmedia_omx",
        "libmediametrics",
        "libmediadrm",
        "libmediadrmmetrics_consumer",
        "libhwui",
        "libui",
        "liblog",
        "libcutils",
        "libgui",
        "libstagefright",
        "libstagefright_foundation",
        "libcamera_client",
        "libmediametrics",
        "libmtp",
        "libnativehelper",
        "libnativewindow",
        "libpiex",
        "libandroidfw",
        "libhidlallocatorutils",
        "libhidlbase",
        "libsonivox",
        "libstagefright",
        "libstagefright_foundation",
        "libui",
        "libutils",
        "server_configurable_flags",
        "android.companion.virtual.virtualdevice_aidl-cpp",
        "android.hardware.cas@1.0",
        "android.hardware.cas.native@1.0",
        "android.hardware.drm@1.3",
        "android.hardware.drm@1.4",
        "android.hidl.memory@1.0",
        "android.hidl.token@1.0-utils",
        "android.hardware.drm-V1-ndk",
        "android.hardware.tv.tuner-V3-ndk",
    ],

    header_libs: [
@@ -97,11 +99,11 @@ cc_library_shared {
    ],

    static_libs: [
        "libgrallocusage",
        "libmedia_midiiowrapper",
        "android.companion.virtualdevice.flags-aconfig-cc",
        "android.media.codec-aconfig-cc",
        "android.media.playback.flags-aconfig-cc",
        "libgrallocusage",
        "libmedia_midiiowrapper",
    ],

    include_dirs: [
@@ -120,8 +122,8 @@ cc_library_shared {
        "-Wall",
        "-Werror",
        "-Wno-error=deprecated-declarations",
        "-Wunused",
        "-Wunreachable-code",
        "-Wunused",
    ],

    // TODO(b/330503129) Workaround build breakage.
@@ -146,8 +148,8 @@ cc_library_shared {
    shared_libs: [
        "android.hardware.graphics.bufferqueue@2.0",
        "android.hardware.tv.tuner-V3-ndk",
        "libbinder_ndk",
        "libandroid_runtime",
        "libbinder_ndk",
        "libcutils",
        "libfmq",
        "libhidlbase",
@@ -181,7 +183,7 @@ cc_library_shared {
        "-Wall",
        "-Werror",
        "-Wno-error=deprecated-declarations",
        "-Wunused",
        "-Wunreachable-code",
        "-Wunused",
    ],
}
+117 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "MediaCodec-JNI"

#include "android_runtime/AndroidRuntime.h"
#include "jni.h"

#include <media/AudioCapabilities.h>
#include <media/stagefright/foundation/ADebug.h>
#include <nativehelper/JNIHelp.h>

namespace android {

struct fields_t {
    jfieldID audioCapsContext;
};
static fields_t fields;

// Getters

static AudioCapabilities* getAudioCapabilities(JNIEnv *env, jobject thiz) {
    AudioCapabilities* const p = (AudioCapabilities*)env->GetLongField(
            thiz, fields.audioCapsContext);
    return p;
}

}  // namespace android

// ----------------------------------------------------------------------------

using namespace android;

// AudioCapabilities

static void android_media_AudioCapabilities_native_init(JNIEnv *env, jobject /* thiz */) {
    jclass audioCapsImplClazz
            = env->FindClass("android/media/MediaCodecInfo$AudioCapabilities$AudioCapsNativeImpl");
    if (audioCapsImplClazz == NULL) {
        return;
    }

    fields.audioCapsContext = env->GetFieldID(audioCapsImplClazz, "mNativeContext", "J");
    if (fields.audioCapsContext == NULL) {
        return;
    }

    env->DeleteLocalRef(audioCapsImplClazz);
}

static jint android_media_AudioCapabilities_getMaxInputChannelCount(JNIEnv *env, jobject thiz) {
    AudioCapabilities* const audioCaps = getAudioCapabilities(env, thiz);
    if (audioCaps == nullptr) {
        jniThrowException(env, "java/lang/IllegalStateException", NULL);
        return 0;
    }

    int32_t maxInputChannelCount = audioCaps->getMaxInputChannelCount();
    return maxInputChannelCount;
}

static jint android_media_AudioCapabilities_getMinInputChannelCount(JNIEnv *env, jobject thiz) {
    AudioCapabilities* const audioCaps = getAudioCapabilities(env, thiz);
    if (audioCaps == nullptr) {
        jniThrowException(env, "java/lang/IllegalStateException", NULL);
        return 0;
    }

    int32_t minInputChannelCount = audioCaps->getMinInputChannelCount();
    return minInputChannelCount;
}

static jboolean android_media_AudioCapabilities_isSampleRateSupported(JNIEnv *env, jobject thiz,
        int sampleRate) {
    AudioCapabilities* const audioCaps = getAudioCapabilities(env, thiz);
    if (audioCaps == nullptr) {
        jniThrowException(env, "java/lang/IllegalStateException", NULL);
        return 0;
    }

    bool res = audioCaps->isSampleRateSupported(sampleRate);
    return res;
}

// ----------------------------------------------------------------------------

static const JNINativeMethod gAudioCapsMethods[] = {
    {"native_init", "()V", (void *)android_media_AudioCapabilities_native_init},
    {"native_getMaxInputChannelCount", "()I", (void *)android_media_AudioCapabilities_getMaxInputChannelCount},
    {"native_getMinInputChannelCount", "()I", (void *)android_media_AudioCapabilities_getMinInputChannelCount},
    {"native_isSampleRateSupported", "(I)Z", (void *)android_media_AudioCapabilities_isSampleRateSupported}
};

int register_android_media_CodecCapabilities(JNIEnv *env) {
    int result = AndroidRuntime::registerNativeMethods(env,
            "android/media/MediaCodecInfo$AudioCapabilities$AudioCapsNativeImpl",
            gAudioCapsMethods, NELEM(gAudioCapsMethods));
    if (result != JNI_OK) {
        return result;
    }

    return result;
}
 No newline at end of file
+6 −0

File changed.

Preview size limit exceeded, changes collapsed.