Loading core/jni/android_media_AudioFormat.h +30 −0 Original line number Original line Diff line number Diff line Loading @@ -33,6 +33,8 @@ #define ENCODING_AAC_HE_V2 12 #define ENCODING_AAC_HE_V2 12 #define ENCODING_IEC61937 13 #define ENCODING_IEC61937 13 #define ENCODING_DOLBY_TRUEHD 14 #define ENCODING_DOLBY_TRUEHD 14 #define ENCODING_AAC_ELD 15 #define ENCODING_AAC_XHE 16 #define ENCODING_INVALID 0 #define ENCODING_INVALID 0 #define ENCODING_DEFAULT 1 #define ENCODING_DEFAULT 1 Loading Loading @@ -71,6 +73,10 @@ static inline audio_format_t audioFormatToNative(int audioFormat) return AUDIO_FORMAT_DOLBY_TRUEHD; return AUDIO_FORMAT_DOLBY_TRUEHD; case ENCODING_IEC61937: case ENCODING_IEC61937: return AUDIO_FORMAT_IEC61937; return AUDIO_FORMAT_IEC61937; case ENCODING_AAC_ELD: return AUDIO_FORMAT_AAC_ELD; case ENCODING_AAC_XHE: return AUDIO_FORMAT_AAC; // FIXME temporary value, needs addition of xHE-AAC case ENCODING_DEFAULT: case ENCODING_DEFAULT: return AUDIO_FORMAT_DEFAULT; return AUDIO_FORMAT_DEFAULT; default: default: Loading Loading @@ -114,6 +120,11 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat) return ENCODING_IEC61937; return ENCODING_IEC61937; case AUDIO_FORMAT_DOLBY_TRUEHD: case AUDIO_FORMAT_DOLBY_TRUEHD: return ENCODING_DOLBY_TRUEHD; return ENCODING_DOLBY_TRUEHD; case AUDIO_FORMAT_AAC_ELD: return ENCODING_AAC_ELD; // FIXME needs addition of AUDIO_FORMAT_AAC_XHE //case AUDIO_FORMAT_AAC_XHE: // return ENCODING_AAC_XHE; case AUDIO_FORMAT_DEFAULT: case AUDIO_FORMAT_DEFAULT: return ENCODING_DEFAULT; return ENCODING_DEFAULT; default: default: Loading @@ -121,6 +132,25 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat) } } } } // This function converts Java channel masks to a native channel mask. // validity should be checked with audio_is_output_channel(). static inline audio_channel_mask_t nativeChannelMaskFromJavaChannelMasks( jint channelPositionMask, jint channelIndexMask) { // 0 is the java android.media.AudioFormat.CHANNEL_INVALID value if (channelIndexMask != 0) { // channel index mask takes priority // To convert to a native channel mask, the Java channel index mask // requires adding the index representation. return audio_channel_mask_from_representation_and_bits( AUDIO_CHANNEL_REPRESENTATION_INDEX, channelIndexMask); } // To convert to a native channel mask, the Java channel position mask // requires a shift by 2 to skip the two deprecated channel // configurations "default" and "mono". return (audio_channel_mask_t)((uint32_t)channelPositionMask >> 2); } static inline audio_channel_mask_t outChannelMaskToNative(int channelMask) static inline audio_channel_mask_t outChannelMaskToNative(int channelMask) { { switch (channelMask) { switch (channelMask) { Loading core/jni/android_media_AudioSystem.cpp +19 −0 Original line number Original line Diff line number Diff line Loading @@ -1770,6 +1770,24 @@ android_media_AudioSystem_getStreamVolumeDB(JNIEnv *env, jobject thiz, (audio_devices_t)device); (audio_devices_t)device); } } static jboolean android_media_AudioSystem_isOffloadSupported(JNIEnv *env, jobject thiz, jint encoding, jint sampleRate, jint channelMask, jint channelIndexMask) { audio_offload_info_t format = AUDIO_INFO_INITIALIZER; format.format = (audio_format_t) audioFormatToNative(encoding); format.sample_rate = (uint32_t) sampleRate; format.channel_mask = nativeChannelMaskFromJavaChannelMasks(channelMask, channelIndexMask); format.stream_type = AUDIO_STREAM_MUSIC; format.has_video = false; format.is_streaming = false; // offload duration unknown at this point: // client side code cannot access "audio.offload.min.duration.secs" property to make a query // agnostic of duration, so using acceptable estimate of 2mn format.duration_us = 120 * 1000000; return AudioSystem::isOffloadSupported(format); } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- static const JNINativeMethod gMethods[] = { static const JNINativeMethod gMethods[] = { Loading Loading @@ -1823,6 +1841,7 @@ static const JNINativeMethod gMethods[] = { (void *)android_media_AudioSystem_registerRecordingCallback}, (void *)android_media_AudioSystem_registerRecordingCallback}, {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady}, {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady}, {"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB}, {"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB}, {"native_is_offload_supported", "(IIII)Z", (void *)android_media_AudioSystem_isOffloadSupported}, }; }; Loading core/jni/android_media_AudioTrack.cpp +37 −35 Original line number Original line Diff line number Diff line Loading @@ -73,6 +73,7 @@ struct audiotrack_callback_cookie { jobject audioTrack_ref; jobject audioTrack_ref; bool busy; bool busy; Condition cond; Condition cond; bool isOffload; }; }; // keep these values in sync with AudioTrack.java // keep these values in sync with AudioTrack.java Loading @@ -90,6 +91,7 @@ class AudioTrackJniStorage { AudioTrackJniStorage() { AudioTrackJniStorage() { mCallbackData.audioTrack_class = 0; mCallbackData.audioTrack_class = 0; mCallbackData.audioTrack_ref = 0; mCallbackData.audioTrack_ref = 0; mCallbackData.isOffload = false; } } ~AudioTrackJniStorage() { ~AudioTrackJniStorage() { Loading Loading @@ -132,7 +134,12 @@ static void audioCallback(int event, void* user, void *info) { } } switch (event) { switch (event) { case AudioTrack::EVENT_MARKER: { // Offload only events case AudioTrack::EVENT_STREAM_END: case AudioTrack::EVENT_MORE_DATA: // a.k.a. tear down case AudioTrack::EVENT_NEW_IAUDIOTRACK: if (callbackInfo->isOffload) { JNIEnv *env = AndroidRuntime::getJNIEnv(); JNIEnv *env = AndroidRuntime::getJNIEnv(); if (user != NULL && env != NULL) { if (user != NULL && env != NULL) { env->CallStaticVoidMethod( env->CallStaticVoidMethod( Loading @@ -146,6 +153,8 @@ static void audioCallback(int event, void* user, void *info) { } } } break; } break; // PCM and offload events case AudioTrack::EVENT_MARKER: case AudioTrack::EVENT_NEW_POS: { case AudioTrack::EVENT_NEW_POS: { JNIEnv *env = AndroidRuntime::getJNIEnv(); JNIEnv *env = AndroidRuntime::getJNIEnv(); if (user != NULL && env != NULL) { if (user != NULL && env != NULL) { Loading Loading @@ -198,30 +207,12 @@ sp<AudioTrack> android_media_AudioTrack_getAudioTrack(JNIEnv* env, jobject audio return getAudioTrack(env, audioTrackObj); return getAudioTrack(env, audioTrackObj); } } // This function converts Java channel masks to a native channel mask. // validity should be checked with audio_is_output_channel(). static inline audio_channel_mask_t nativeChannelMaskFromJavaChannelMasks( jint channelPositionMask, jint channelIndexMask) { if (channelIndexMask != 0) { // channel index mask takes priority // To convert to a native channel mask, the Java channel index mask // requires adding the index representation. return audio_channel_mask_from_representation_and_bits( AUDIO_CHANNEL_REPRESENTATION_INDEX, channelIndexMask); } // To convert to a native channel mask, the Java channel position mask // requires a shift by 2 to skip the two deprecated channel // configurations "default" and "mono". return (audio_channel_mask_t)(channelPositionMask >> 2); } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- static jint static jint android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, jobject jaa, android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, jobject jaa, jintArray jSampleRate, jint channelPositionMask, jint channelIndexMask, jintArray jSampleRate, jint channelPositionMask, jint channelIndexMask, jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession, jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession, jlong nativeAudioTrack) { jlong nativeAudioTrack, jboolean offload) { ALOGV("sampleRates=%p, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d" ALOGV("sampleRates=%p, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d" "nativeAudioTrack=0x%" PRIX64, "nativeAudioTrack=0x%" PRIX64, Loading Loading @@ -322,8 +313,19 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, job lpJniStorage->mCallbackData.audioTrack_class = (jclass)env->NewGlobalRef(clazz); lpJniStorage->mCallbackData.audioTrack_class = (jclass)env->NewGlobalRef(clazz); // we use a weak reference so the AudioTrack object can be garbage collected. // we use a weak reference so the AudioTrack object can be garbage collected. lpJniStorage->mCallbackData.audioTrack_ref = env->NewGlobalRef(weak_this); lpJniStorage->mCallbackData.audioTrack_ref = env->NewGlobalRef(weak_this); lpJniStorage->mCallbackData.isOffload = offload; lpJniStorage->mCallbackData.busy = false; lpJniStorage->mCallbackData.busy = false; audio_offload_info_t offloadInfo; if (offload) { offloadInfo = AUDIO_INFO_INITIALIZER; offloadInfo.format = format; offloadInfo.sample_rate = sampleRateInHertz; offloadInfo.channel_mask = nativeChannelMask; offloadInfo.has_video = false; offloadInfo.stream_type = AUDIO_STREAM_MUSIC; //required for offload } // initialize the native AudioTrack object // initialize the native AudioTrack object status_t status = NO_ERROR; status_t status = NO_ERROR; switch (memoryMode) { switch (memoryMode) { Loading @@ -342,7 +344,7 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, job true,// thread can call Java true,// thread can call Java sessionId,// audio session ID sessionId,// audio session ID AudioTrack::TRANSFER_SYNC, AudioTrack::TRANSFER_SYNC, NULL, // default offloadInfo offload ? &offloadInfo : NULL, -1, -1, // default uid, pid values -1, -1, // default uid, pid values paa); paa); break; break; Loading Loading @@ -1234,7 +1236,7 @@ static const JNINativeMethod gMethods[] = { {"native_stop", "()V", (void *)android_media_AudioTrack_stop}, {"native_stop", "()V", (void *)android_media_AudioTrack_stop}, {"native_pause", "()V", (void *)android_media_AudioTrack_pause}, {"native_pause", "()V", (void *)android_media_AudioTrack_pause}, {"native_flush", "()V", (void *)android_media_AudioTrack_flush}, {"native_flush", "()V", (void *)android_media_AudioTrack_flush}, {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJ)I", {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJZ)I", (void *)android_media_AudioTrack_setup}, (void *)android_media_AudioTrack_setup}, {"native_finalize", "()V", (void *)android_media_AudioTrack_finalize}, {"native_finalize", "()V", (void *)android_media_AudioTrack_finalize}, {"native_release", "()V", (void *)android_media_AudioTrack_release}, {"native_release", "()V", (void *)android_media_AudioTrack_release}, Loading media/java/android/media/AudioFormat.java +42 −11 Original line number Original line Diff line number Diff line Loading @@ -240,20 +240,25 @@ public final class AudioFormat implements Parcelable { public static final int ENCODING_DTS_HD = 8; public static final int ENCODING_DTS_HD = 8; /** Audio data format: MP3 compressed /** Audio data format: MP3 compressed * @hide * @hide * TODO unhide and add to @Encoding (intentional white space * */ * */ public static final int ENCODING_MP3 = 9; public static final int ENCODING_MP3 = 9; /** Audio data format: AAC LC compressed /** Audio data format: AAC LC compressed * @hide * @hide * TODO unhide and add to @Encoding (intentional white space * */ * */ public static final int ENCODING_AAC_LC = 10; public static final int ENCODING_AAC_LC = 10; /** Audio data format: AAC HE V1 compressed /** Audio data format: AAC HE V1 compressed * @hide * @hide * TODO unhide and add to @Encoding (intentional white space * */ * */ public static final int ENCODING_AAC_HE_V1 = 11; public static final int ENCODING_AAC_HE_V1 = 11; /** Audio data format: AAC HE V2 compressed /** Audio data format: AAC HE V2 compressed * @hide * @hide * TODO unhide and add to @Encoding (intentional white space * */ * */ public static final int ENCODING_AAC_HE_V2 = 12; public static final int ENCODING_AAC_HE_V2 = 12; /** Audio data format: compressed audio wrapped in PCM for HDMI /** Audio data format: compressed audio wrapped in PCM for HDMI * or S/PDIF passthrough. * or S/PDIF passthrough. * IEC61937 uses a stereo stream of 16-bit samples as the wrapper. * IEC61937 uses a stereo stream of 16-bit samples as the wrapper. Loading @@ -266,6 +271,16 @@ public final class AudioFormat implements Parcelable { /** Audio data format: DOLBY TRUEHD compressed /** Audio data format: DOLBY TRUEHD compressed **/ **/ public static final int ENCODING_DOLBY_TRUEHD = 14; public static final int ENCODING_DOLBY_TRUEHD = 14; /** Audio data format: AAC ELD compressed * @hide * TODO unhide and add to @Encoding (intentional white space * */ public static final int ENCODING_AAC_ELD = 15; /** Audio data format: AAC xHE compressed * @hide * TODO unhide and add to @Encoding (intentional white space * */ public static final int ENCODING_AAC_XHE = 16; /** @hide */ /** @hide */ public static String toLogFriendlyEncoding(int enc) { public static String toLogFriendlyEncoding(int enc) { Loading Loading @@ -298,6 +313,10 @@ public final class AudioFormat implements Parcelable { return "ENCODING_IEC61937"; return "ENCODING_IEC61937"; case ENCODING_DOLBY_TRUEHD: case ENCODING_DOLBY_TRUEHD: return "ENCODING_DOLBY_TRUEHD"; return "ENCODING_DOLBY_TRUEHD"; case ENCODING_AAC_ELD: return "ENCODING_AAC_ELD"; case ENCODING_AAC_XHE: return "ENCODING_AAC_XHE"; default : default : return "invalid encoding " + enc; return "invalid encoding " + enc; } } Loading Loading @@ -514,6 +533,8 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_HE_V1: case ENCODING_AAC_HE_V1: case ENCODING_AAC_HE_V2: case ENCODING_AAC_HE_V2: case ENCODING_IEC61937: case ENCODING_IEC61937: case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: return true; return true; default: default: return false; return false; Loading @@ -532,6 +553,13 @@ public final class AudioFormat implements Parcelable { case ENCODING_DTS: case ENCODING_DTS: case ENCODING_DTS_HD: case ENCODING_DTS_HD: case ENCODING_IEC61937: case ENCODING_IEC61937: //TODO not true yet (intended white space case ENCODING_MP3: case ENCODING_AAC_LC: case ENCODING_AAC_HE_V1: case ENCODING_AAC_HE_V2: case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: return true; return true; default: default: return false; return false; Loading @@ -556,6 +584,8 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_HE_V1: case ENCODING_AAC_HE_V1: case ENCODING_AAC_HE_V2: case ENCODING_AAC_HE_V2: case ENCODING_IEC61937: // wrapped in PCM but compressed case ENCODING_IEC61937: // wrapped in PCM but compressed case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: return false; return false; case ENCODING_INVALID: case ENCODING_INVALID: default: default: Loading @@ -581,6 +611,8 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_LC: case ENCODING_AAC_LC: case ENCODING_AAC_HE_V1: case ENCODING_AAC_HE_V1: case ENCODING_AAC_HE_V2: case ENCODING_AAC_HE_V2: case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: return false; return false; case ENCODING_INVALID: case ENCODING_INVALID: default: default: Loading Loading @@ -794,14 +826,7 @@ public final class AudioFormat implements Parcelable { /** /** * Sets the data encoding format. * Sets the data encoding format. * @param encoding one of {@link AudioFormat#ENCODING_DEFAULT}, * @param encoding the specified encoding or default. * {@link AudioFormat#ENCODING_PCM_8BIT}, * {@link AudioFormat#ENCODING_PCM_16BIT}, * {@link AudioFormat#ENCODING_PCM_FLOAT}, * {@link AudioFormat#ENCODING_AC3}, * {@link AudioFormat#ENCODING_E_AC3}. * {@link AudioFormat#ENCODING_DTS}, * {@link AudioFormat#ENCODING_DTS_HD}. * @return the same Builder instance. * @return the same Builder instance. * @throws java.lang.IllegalArgumentException * @throws java.lang.IllegalArgumentException */ */ Loading @@ -818,6 +843,12 @@ public final class AudioFormat implements Parcelable { case ENCODING_DTS: case ENCODING_DTS: case ENCODING_DTS_HD: case ENCODING_DTS_HD: case ENCODING_IEC61937: case ENCODING_IEC61937: case ENCODING_MP3: case ENCODING_AAC_LC: case ENCODING_AAC_HE_V1: case ENCODING_AAC_HE_V2: case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: mEncoding = encoding; mEncoding = encoding; break; break; case ENCODING_INVALID: case ENCODING_INVALID: Loading Loading @@ -1016,7 +1047,7 @@ public final class AudioFormat implements Parcelable { } } /** @hide */ /** @hide */ @IntDef({ @IntDef(flag = false, prefix = "ENCODING", value = { ENCODING_DEFAULT, ENCODING_DEFAULT, ENCODING_PCM_8BIT, ENCODING_PCM_8BIT, ENCODING_PCM_16BIT, ENCODING_PCM_16BIT, Loading @@ -1025,8 +1056,8 @@ public final class AudioFormat implements Parcelable { ENCODING_E_AC3, ENCODING_E_AC3, ENCODING_DTS, ENCODING_DTS, ENCODING_DTS_HD, ENCODING_DTS_HD, ENCODING_IEC61937 ENCODING_IEC61937 } }) ) @Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE) public @interface Encoding {} public @interface Encoding {} Loading media/java/android/media/AudioManager.java +15 −0 Original line number Original line Diff line number Diff line Loading @@ -1328,6 +1328,21 @@ public class AudioManager { } } } } //==================================================================== // Offload query /** * @hide * TODO unhide (intentional white space to attract attention: * Returns whether offloaded playback of an audio format is supported on the device. * Offloaded playback is where the decoding of an audio stream is not competing with other * software resources. In general, it is supported by dedicated hardware, such as audio DSPs. * @param format the audio format (codec, sample rate, channels) being checked. * @return true if the given audio format can be offloaded. */ public static boolean isOffloadedPlaybackSupported(@NonNull AudioFormat format) { return AudioSystem.isOffloadSupported(format); } //==================================================================== //==================================================================== // Bluetooth SCO control // Bluetooth SCO control /** /** Loading Loading
core/jni/android_media_AudioFormat.h +30 −0 Original line number Original line Diff line number Diff line Loading @@ -33,6 +33,8 @@ #define ENCODING_AAC_HE_V2 12 #define ENCODING_AAC_HE_V2 12 #define ENCODING_IEC61937 13 #define ENCODING_IEC61937 13 #define ENCODING_DOLBY_TRUEHD 14 #define ENCODING_DOLBY_TRUEHD 14 #define ENCODING_AAC_ELD 15 #define ENCODING_AAC_XHE 16 #define ENCODING_INVALID 0 #define ENCODING_INVALID 0 #define ENCODING_DEFAULT 1 #define ENCODING_DEFAULT 1 Loading Loading @@ -71,6 +73,10 @@ static inline audio_format_t audioFormatToNative(int audioFormat) return AUDIO_FORMAT_DOLBY_TRUEHD; return AUDIO_FORMAT_DOLBY_TRUEHD; case ENCODING_IEC61937: case ENCODING_IEC61937: return AUDIO_FORMAT_IEC61937; return AUDIO_FORMAT_IEC61937; case ENCODING_AAC_ELD: return AUDIO_FORMAT_AAC_ELD; case ENCODING_AAC_XHE: return AUDIO_FORMAT_AAC; // FIXME temporary value, needs addition of xHE-AAC case ENCODING_DEFAULT: case ENCODING_DEFAULT: return AUDIO_FORMAT_DEFAULT; return AUDIO_FORMAT_DEFAULT; default: default: Loading Loading @@ -114,6 +120,11 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat) return ENCODING_IEC61937; return ENCODING_IEC61937; case AUDIO_FORMAT_DOLBY_TRUEHD: case AUDIO_FORMAT_DOLBY_TRUEHD: return ENCODING_DOLBY_TRUEHD; return ENCODING_DOLBY_TRUEHD; case AUDIO_FORMAT_AAC_ELD: return ENCODING_AAC_ELD; // FIXME needs addition of AUDIO_FORMAT_AAC_XHE //case AUDIO_FORMAT_AAC_XHE: // return ENCODING_AAC_XHE; case AUDIO_FORMAT_DEFAULT: case AUDIO_FORMAT_DEFAULT: return ENCODING_DEFAULT; return ENCODING_DEFAULT; default: default: Loading @@ -121,6 +132,25 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat) } } } } // This function converts Java channel masks to a native channel mask. // validity should be checked with audio_is_output_channel(). static inline audio_channel_mask_t nativeChannelMaskFromJavaChannelMasks( jint channelPositionMask, jint channelIndexMask) { // 0 is the java android.media.AudioFormat.CHANNEL_INVALID value if (channelIndexMask != 0) { // channel index mask takes priority // To convert to a native channel mask, the Java channel index mask // requires adding the index representation. return audio_channel_mask_from_representation_and_bits( AUDIO_CHANNEL_REPRESENTATION_INDEX, channelIndexMask); } // To convert to a native channel mask, the Java channel position mask // requires a shift by 2 to skip the two deprecated channel // configurations "default" and "mono". return (audio_channel_mask_t)((uint32_t)channelPositionMask >> 2); } static inline audio_channel_mask_t outChannelMaskToNative(int channelMask) static inline audio_channel_mask_t outChannelMaskToNative(int channelMask) { { switch (channelMask) { switch (channelMask) { Loading
core/jni/android_media_AudioSystem.cpp +19 −0 Original line number Original line Diff line number Diff line Loading @@ -1770,6 +1770,24 @@ android_media_AudioSystem_getStreamVolumeDB(JNIEnv *env, jobject thiz, (audio_devices_t)device); (audio_devices_t)device); } } static jboolean android_media_AudioSystem_isOffloadSupported(JNIEnv *env, jobject thiz, jint encoding, jint sampleRate, jint channelMask, jint channelIndexMask) { audio_offload_info_t format = AUDIO_INFO_INITIALIZER; format.format = (audio_format_t) audioFormatToNative(encoding); format.sample_rate = (uint32_t) sampleRate; format.channel_mask = nativeChannelMaskFromJavaChannelMasks(channelMask, channelIndexMask); format.stream_type = AUDIO_STREAM_MUSIC; format.has_video = false; format.is_streaming = false; // offload duration unknown at this point: // client side code cannot access "audio.offload.min.duration.secs" property to make a query // agnostic of duration, so using acceptable estimate of 2mn format.duration_us = 120 * 1000000; return AudioSystem::isOffloadSupported(format); } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- static const JNINativeMethod gMethods[] = { static const JNINativeMethod gMethods[] = { Loading Loading @@ -1823,6 +1841,7 @@ static const JNINativeMethod gMethods[] = { (void *)android_media_AudioSystem_registerRecordingCallback}, (void *)android_media_AudioSystem_registerRecordingCallback}, {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady}, {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady}, {"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB}, {"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB}, {"native_is_offload_supported", "(IIII)Z", (void *)android_media_AudioSystem_isOffloadSupported}, }; }; Loading
core/jni/android_media_AudioTrack.cpp +37 −35 Original line number Original line Diff line number Diff line Loading @@ -73,6 +73,7 @@ struct audiotrack_callback_cookie { jobject audioTrack_ref; jobject audioTrack_ref; bool busy; bool busy; Condition cond; Condition cond; bool isOffload; }; }; // keep these values in sync with AudioTrack.java // keep these values in sync with AudioTrack.java Loading @@ -90,6 +91,7 @@ class AudioTrackJniStorage { AudioTrackJniStorage() { AudioTrackJniStorage() { mCallbackData.audioTrack_class = 0; mCallbackData.audioTrack_class = 0; mCallbackData.audioTrack_ref = 0; mCallbackData.audioTrack_ref = 0; mCallbackData.isOffload = false; } } ~AudioTrackJniStorage() { ~AudioTrackJniStorage() { Loading Loading @@ -132,7 +134,12 @@ static void audioCallback(int event, void* user, void *info) { } } switch (event) { switch (event) { case AudioTrack::EVENT_MARKER: { // Offload only events case AudioTrack::EVENT_STREAM_END: case AudioTrack::EVENT_MORE_DATA: // a.k.a. tear down case AudioTrack::EVENT_NEW_IAUDIOTRACK: if (callbackInfo->isOffload) { JNIEnv *env = AndroidRuntime::getJNIEnv(); JNIEnv *env = AndroidRuntime::getJNIEnv(); if (user != NULL && env != NULL) { if (user != NULL && env != NULL) { env->CallStaticVoidMethod( env->CallStaticVoidMethod( Loading @@ -146,6 +153,8 @@ static void audioCallback(int event, void* user, void *info) { } } } break; } break; // PCM and offload events case AudioTrack::EVENT_MARKER: case AudioTrack::EVENT_NEW_POS: { case AudioTrack::EVENT_NEW_POS: { JNIEnv *env = AndroidRuntime::getJNIEnv(); JNIEnv *env = AndroidRuntime::getJNIEnv(); if (user != NULL && env != NULL) { if (user != NULL && env != NULL) { Loading Loading @@ -198,30 +207,12 @@ sp<AudioTrack> android_media_AudioTrack_getAudioTrack(JNIEnv* env, jobject audio return getAudioTrack(env, audioTrackObj); return getAudioTrack(env, audioTrackObj); } } // This function converts Java channel masks to a native channel mask. // validity should be checked with audio_is_output_channel(). static inline audio_channel_mask_t nativeChannelMaskFromJavaChannelMasks( jint channelPositionMask, jint channelIndexMask) { if (channelIndexMask != 0) { // channel index mask takes priority // To convert to a native channel mask, the Java channel index mask // requires adding the index representation. return audio_channel_mask_from_representation_and_bits( AUDIO_CHANNEL_REPRESENTATION_INDEX, channelIndexMask); } // To convert to a native channel mask, the Java channel position mask // requires a shift by 2 to skip the two deprecated channel // configurations "default" and "mono". return (audio_channel_mask_t)(channelPositionMask >> 2); } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- static jint static jint android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, jobject jaa, android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, jobject jaa, jintArray jSampleRate, jint channelPositionMask, jint channelIndexMask, jintArray jSampleRate, jint channelPositionMask, jint channelIndexMask, jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession, jint audioFormat, jint buffSizeInBytes, jint memoryMode, jintArray jSession, jlong nativeAudioTrack) { jlong nativeAudioTrack, jboolean offload) { ALOGV("sampleRates=%p, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d" ALOGV("sampleRates=%p, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d" "nativeAudioTrack=0x%" PRIX64, "nativeAudioTrack=0x%" PRIX64, Loading Loading @@ -322,8 +313,19 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, job lpJniStorage->mCallbackData.audioTrack_class = (jclass)env->NewGlobalRef(clazz); lpJniStorage->mCallbackData.audioTrack_class = (jclass)env->NewGlobalRef(clazz); // we use a weak reference so the AudioTrack object can be garbage collected. // we use a weak reference so the AudioTrack object can be garbage collected. lpJniStorage->mCallbackData.audioTrack_ref = env->NewGlobalRef(weak_this); lpJniStorage->mCallbackData.audioTrack_ref = env->NewGlobalRef(weak_this); lpJniStorage->mCallbackData.isOffload = offload; lpJniStorage->mCallbackData.busy = false; lpJniStorage->mCallbackData.busy = false; audio_offload_info_t offloadInfo; if (offload) { offloadInfo = AUDIO_INFO_INITIALIZER; offloadInfo.format = format; offloadInfo.sample_rate = sampleRateInHertz; offloadInfo.channel_mask = nativeChannelMask; offloadInfo.has_video = false; offloadInfo.stream_type = AUDIO_STREAM_MUSIC; //required for offload } // initialize the native AudioTrack object // initialize the native AudioTrack object status_t status = NO_ERROR; status_t status = NO_ERROR; switch (memoryMode) { switch (memoryMode) { Loading @@ -342,7 +344,7 @@ android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject weak_this, job true,// thread can call Java true,// thread can call Java sessionId,// audio session ID sessionId,// audio session ID AudioTrack::TRANSFER_SYNC, AudioTrack::TRANSFER_SYNC, NULL, // default offloadInfo offload ? &offloadInfo : NULL, -1, -1, // default uid, pid values -1, -1, // default uid, pid values paa); paa); break; break; Loading Loading @@ -1234,7 +1236,7 @@ static const JNINativeMethod gMethods[] = { {"native_stop", "()V", (void *)android_media_AudioTrack_stop}, {"native_stop", "()V", (void *)android_media_AudioTrack_stop}, {"native_pause", "()V", (void *)android_media_AudioTrack_pause}, {"native_pause", "()V", (void *)android_media_AudioTrack_pause}, {"native_flush", "()V", (void *)android_media_AudioTrack_flush}, {"native_flush", "()V", (void *)android_media_AudioTrack_flush}, {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJ)I", {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJZ)I", (void *)android_media_AudioTrack_setup}, (void *)android_media_AudioTrack_setup}, {"native_finalize", "()V", (void *)android_media_AudioTrack_finalize}, {"native_finalize", "()V", (void *)android_media_AudioTrack_finalize}, {"native_release", "()V", (void *)android_media_AudioTrack_release}, {"native_release", "()V", (void *)android_media_AudioTrack_release}, Loading
media/java/android/media/AudioFormat.java +42 −11 Original line number Original line Diff line number Diff line Loading @@ -240,20 +240,25 @@ public final class AudioFormat implements Parcelable { public static final int ENCODING_DTS_HD = 8; public static final int ENCODING_DTS_HD = 8; /** Audio data format: MP3 compressed /** Audio data format: MP3 compressed * @hide * @hide * TODO unhide and add to @Encoding (intentional white space * */ * */ public static final int ENCODING_MP3 = 9; public static final int ENCODING_MP3 = 9; /** Audio data format: AAC LC compressed /** Audio data format: AAC LC compressed * @hide * @hide * TODO unhide and add to @Encoding (intentional white space * */ * */ public static final int ENCODING_AAC_LC = 10; public static final int ENCODING_AAC_LC = 10; /** Audio data format: AAC HE V1 compressed /** Audio data format: AAC HE V1 compressed * @hide * @hide * TODO unhide and add to @Encoding (intentional white space * */ * */ public static final int ENCODING_AAC_HE_V1 = 11; public static final int ENCODING_AAC_HE_V1 = 11; /** Audio data format: AAC HE V2 compressed /** Audio data format: AAC HE V2 compressed * @hide * @hide * TODO unhide and add to @Encoding (intentional white space * */ * */ public static final int ENCODING_AAC_HE_V2 = 12; public static final int ENCODING_AAC_HE_V2 = 12; /** Audio data format: compressed audio wrapped in PCM for HDMI /** Audio data format: compressed audio wrapped in PCM for HDMI * or S/PDIF passthrough. * or S/PDIF passthrough. * IEC61937 uses a stereo stream of 16-bit samples as the wrapper. * IEC61937 uses a stereo stream of 16-bit samples as the wrapper. Loading @@ -266,6 +271,16 @@ public final class AudioFormat implements Parcelable { /** Audio data format: DOLBY TRUEHD compressed /** Audio data format: DOLBY TRUEHD compressed **/ **/ public static final int ENCODING_DOLBY_TRUEHD = 14; public static final int ENCODING_DOLBY_TRUEHD = 14; /** Audio data format: AAC ELD compressed * @hide * TODO unhide and add to @Encoding (intentional white space * */ public static final int ENCODING_AAC_ELD = 15; /** Audio data format: AAC xHE compressed * @hide * TODO unhide and add to @Encoding (intentional white space * */ public static final int ENCODING_AAC_XHE = 16; /** @hide */ /** @hide */ public static String toLogFriendlyEncoding(int enc) { public static String toLogFriendlyEncoding(int enc) { Loading Loading @@ -298,6 +313,10 @@ public final class AudioFormat implements Parcelable { return "ENCODING_IEC61937"; return "ENCODING_IEC61937"; case ENCODING_DOLBY_TRUEHD: case ENCODING_DOLBY_TRUEHD: return "ENCODING_DOLBY_TRUEHD"; return "ENCODING_DOLBY_TRUEHD"; case ENCODING_AAC_ELD: return "ENCODING_AAC_ELD"; case ENCODING_AAC_XHE: return "ENCODING_AAC_XHE"; default : default : return "invalid encoding " + enc; return "invalid encoding " + enc; } } Loading Loading @@ -514,6 +533,8 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_HE_V1: case ENCODING_AAC_HE_V1: case ENCODING_AAC_HE_V2: case ENCODING_AAC_HE_V2: case ENCODING_IEC61937: case ENCODING_IEC61937: case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: return true; return true; default: default: return false; return false; Loading @@ -532,6 +553,13 @@ public final class AudioFormat implements Parcelable { case ENCODING_DTS: case ENCODING_DTS: case ENCODING_DTS_HD: case ENCODING_DTS_HD: case ENCODING_IEC61937: case ENCODING_IEC61937: //TODO not true yet (intended white space case ENCODING_MP3: case ENCODING_AAC_LC: case ENCODING_AAC_HE_V1: case ENCODING_AAC_HE_V2: case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: return true; return true; default: default: return false; return false; Loading @@ -556,6 +584,8 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_HE_V1: case ENCODING_AAC_HE_V1: case ENCODING_AAC_HE_V2: case ENCODING_AAC_HE_V2: case ENCODING_IEC61937: // wrapped in PCM but compressed case ENCODING_IEC61937: // wrapped in PCM but compressed case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: return false; return false; case ENCODING_INVALID: case ENCODING_INVALID: default: default: Loading @@ -581,6 +611,8 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_LC: case ENCODING_AAC_LC: case ENCODING_AAC_HE_V1: case ENCODING_AAC_HE_V1: case ENCODING_AAC_HE_V2: case ENCODING_AAC_HE_V2: case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: return false; return false; case ENCODING_INVALID: case ENCODING_INVALID: default: default: Loading Loading @@ -794,14 +826,7 @@ public final class AudioFormat implements Parcelable { /** /** * Sets the data encoding format. * Sets the data encoding format. * @param encoding one of {@link AudioFormat#ENCODING_DEFAULT}, * @param encoding the specified encoding or default. * {@link AudioFormat#ENCODING_PCM_8BIT}, * {@link AudioFormat#ENCODING_PCM_16BIT}, * {@link AudioFormat#ENCODING_PCM_FLOAT}, * {@link AudioFormat#ENCODING_AC3}, * {@link AudioFormat#ENCODING_E_AC3}. * {@link AudioFormat#ENCODING_DTS}, * {@link AudioFormat#ENCODING_DTS_HD}. * @return the same Builder instance. * @return the same Builder instance. * @throws java.lang.IllegalArgumentException * @throws java.lang.IllegalArgumentException */ */ Loading @@ -818,6 +843,12 @@ public final class AudioFormat implements Parcelable { case ENCODING_DTS: case ENCODING_DTS: case ENCODING_DTS_HD: case ENCODING_DTS_HD: case ENCODING_IEC61937: case ENCODING_IEC61937: case ENCODING_MP3: case ENCODING_AAC_LC: case ENCODING_AAC_HE_V1: case ENCODING_AAC_HE_V2: case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: mEncoding = encoding; mEncoding = encoding; break; break; case ENCODING_INVALID: case ENCODING_INVALID: Loading Loading @@ -1016,7 +1047,7 @@ public final class AudioFormat implements Parcelable { } } /** @hide */ /** @hide */ @IntDef({ @IntDef(flag = false, prefix = "ENCODING", value = { ENCODING_DEFAULT, ENCODING_DEFAULT, ENCODING_PCM_8BIT, ENCODING_PCM_8BIT, ENCODING_PCM_16BIT, ENCODING_PCM_16BIT, Loading @@ -1025,8 +1056,8 @@ public final class AudioFormat implements Parcelable { ENCODING_E_AC3, ENCODING_E_AC3, ENCODING_DTS, ENCODING_DTS, ENCODING_DTS_HD, ENCODING_DTS_HD, ENCODING_IEC61937 ENCODING_IEC61937 } }) ) @Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE) public @interface Encoding {} public @interface Encoding {} Loading
media/java/android/media/AudioManager.java +15 −0 Original line number Original line Diff line number Diff line Loading @@ -1328,6 +1328,21 @@ public class AudioManager { } } } } //==================================================================== // Offload query /** * @hide * TODO unhide (intentional white space to attract attention: * Returns whether offloaded playback of an audio format is supported on the device. * Offloaded playback is where the decoding of an audio stream is not competing with other * software resources. In general, it is supported by dedicated hardware, such as audio DSPs. * @param format the audio format (codec, sample rate, channels) being checked. * @return true if the given audio format can be offloaded. */ public static boolean isOffloadedPlaybackSupported(@NonNull AudioFormat format) { return AudioSystem.isOffloadSupported(format); } //==================================================================== //==================================================================== // Bluetooth SCO control // Bluetooth SCO control /** /** Loading