From 5c2aae0908c0ae84cdc80446a90a8c394045b735 Mon Sep 17 00:00:00 2001 From: Jean-Michel Trivi Date: Fri, 19 Jan 2018 17:53:40 -0800 Subject: [PATCH] Unhide audio offload for android.media.AudioTrack Unhide some compressed audio formats for offloading or direct output. Unhide AudioManager method to query whether a given format can be offloaded on the device. Unhide AudioTrack.Builder method to request offload. Unhide callback for new AudioTrack events and associated methods. Bug: 63934228 Test: same as MediaPlayer2 tests Change-Id: If763eb2424baa6aa55cb60e96bb3564c4234e23f --- api/current.txt | 17 +++++++++++ core/jni/android_media_AudioFormat.h | 5 ++++ media/java/android/media/AudioFormat.java | 48 ++++++++++++++---------------- media/java/android/media/AudioManager.java | 4 +-- media/java/android/media/AudioTrack.java | 41 +++++++++++++++---------- 5 files changed, 71 insertions(+), 44 deletions(-) diff --git a/api/current.txt b/api/current.txt index 3e4dfd217dcc..0457f3d8e623 100644 --- a/api/current.txt +++ b/api/current.txt @@ -21748,7 +21748,13 @@ package android.media { field public static final int CHANNEL_OUT_STEREO = 12; // 0xc field public static final int CHANNEL_OUT_SURROUND = 1052; // 0x41c field public static final android.os.Parcelable.Creator CREATOR; + field public static final int ENCODING_AAC_ELD = 15; // 0xf + field public static final int ENCODING_AAC_HE_V1 = 11; // 0xb + field public static final int ENCODING_AAC_HE_V2 = 12; // 0xc + field public static final int ENCODING_AAC_LC = 10; // 0xa + field public static final int ENCODING_AAC_XHE = 16; // 0x10 field public static final int ENCODING_AC3 = 5; // 0x5 + field public static final int ENCODING_AC4 = 17; // 0x11 field public static final int ENCODING_DEFAULT = 1; // 0x1 field public static final int ENCODING_DOLBY_TRUEHD = 14; // 0xe field public static final int ENCODING_DTS = 7; // 0x7 @@ -21756,6 +21762,7 @@ package android.media { field public static final int ENCODING_E_AC3 = 6; // 0x6 field public static final int ENCODING_IEC61937 = 13; // 0xd field public static final int ENCODING_INVALID = 0; // 0x0 + field public static final int ENCODING_MP3 = 9; // 0x9 field public static final int ENCODING_PCM_16BIT = 2; // 0x2 field public static final int ENCODING_PCM_8BIT = 3; // 0x3 field public static final int ENCODING_PCM_FLOAT = 4; // 0x4 @@ -21798,6 +21805,7 @@ package android.media { method public boolean isBluetoothScoOn(); method public boolean isMicrophoneMute(); method public boolean isMusicActive(); + method public boolean isOffloadedPlaybackSupported(android.media.AudioFormat); method public boolean isSpeakerphoneOn(); method public boolean isStreamMute(int); method public boolean isVolumeFixed(); @@ -22098,6 +22106,7 @@ package android.media { method public int reloadStaticData(); method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener); method public deprecated void removeOnRoutingChangedListener(android.media.AudioTrack.OnRoutingChangedListener); + method public void removeStreamEventCallback(); method public int setAuxEffectSendLevel(float); method public int setBufferSizeInFrames(int); method public int setLoopPoints(int, int, int); @@ -22111,6 +22120,7 @@ package android.media { method public boolean setPreferredDevice(android.media.AudioDeviceInfo); method protected deprecated void setState(int); method public deprecated int setStereoVolume(float, float); + method public void setStreamEventCallback(java.util.concurrent.Executor, android.media.AudioTrack.StreamEventCallback); method public int setVolume(float); method public void stop() throws java.lang.IllegalStateException; method public int write(byte[], int, int); @@ -22146,6 +22156,7 @@ package android.media { method public android.media.AudioTrack.Builder setAudioAttributes(android.media.AudioAttributes) throws java.lang.IllegalArgumentException; method public android.media.AudioTrack.Builder setAudioFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException; method public android.media.AudioTrack.Builder setBufferSizeInBytes(int) throws java.lang.IllegalArgumentException; + method public android.media.AudioTrack.Builder setOffloadedPlayback(boolean); method public android.media.AudioTrack.Builder setPerformanceMode(int); method public android.media.AudioTrack.Builder setSessionId(int) throws java.lang.IllegalArgumentException; method public android.media.AudioTrack.Builder setTransferMode(int) throws java.lang.IllegalArgumentException; @@ -22161,6 +22172,12 @@ package android.media { method public default void onRoutingChanged(android.media.AudioRouting); } + public static abstract class AudioTrack.StreamEventCallback { + method public void onStreamDataRequest(android.media.AudioTrack); + method public void onStreamPresentationEnd(android.media.AudioTrack); + method public void onTearDown(android.media.AudioTrack); + } + public class CamcorderProfile { method public static android.media.CamcorderProfile get(int); method public static android.media.CamcorderProfile get(int, int); diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h index 51cefb9accb8..c79f5bd96e99 100644 --- a/core/jni/android_media_AudioFormat.h +++ b/core/jni/android_media_AudioFormat.h @@ -35,6 +35,7 @@ #define ENCODING_DOLBY_TRUEHD 14 #define ENCODING_AAC_ELD 15 #define ENCODING_AAC_XHE 16 +#define ENCODING_AC4 17 #define ENCODING_INVALID 0 #define ENCODING_DEFAULT 1 @@ -77,6 +78,8 @@ static inline audio_format_t audioFormatToNative(int audioFormat) return AUDIO_FORMAT_AAC_ELD; case ENCODING_AAC_XHE: return AUDIO_FORMAT_AAC; // FIXME temporary value, needs addition of xHE-AAC + case ENCODING_AC4: + return AUDIO_FORMAT_AC4; case ENCODING_DEFAULT: return AUDIO_FORMAT_DEFAULT; default: @@ -125,6 +128,8 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat) // FIXME needs addition of AUDIO_FORMAT_AAC_XHE //case AUDIO_FORMAT_AAC_XHE: // return ENCODING_AAC_XHE; + case AUDIO_FORMAT_AC4: + return ENCODING_AC4; case AUDIO_FORMAT_DEFAULT: return ENCODING_DEFAULT; default: diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java index 46fe89a74ce5..b07d04220046 100644 --- a/media/java/android/media/AudioFormat.java +++ b/media/java/android/media/AudioFormat.java @@ -238,25 +238,13 @@ public final class AudioFormat implements Parcelable { public static final int ENCODING_DTS = 7; /** Audio data format: DTS HD compressed */ public static final int ENCODING_DTS_HD = 8; - /** Audio data format: MP3 compressed - * @hide - * TODO unhide and add to @Encoding (intentional white space - * */ + /** Audio data format: MP3 compressed */ public static final int ENCODING_MP3 = 9; - /** Audio data format: AAC LC compressed - * @hide - * TODO unhide and add to @Encoding (intentional white space - * */ + /** Audio data format: AAC LC compressed */ public static final int ENCODING_AAC_LC = 10; - /** Audio data format: AAC HE V1 compressed - * @hide - * TODO unhide and add to @Encoding (intentional white space - * */ + /** Audio data format: AAC HE V1 compressed */ public static final int ENCODING_AAC_HE_V1 = 11; - /** Audio data format: AAC HE V2 compressed - * @hide - * TODO unhide and add to @Encoding (intentional white space - * */ + /** Audio data format: AAC HE V2 compressed */ public static final int ENCODING_AAC_HE_V2 = 12; /** Audio data format: compressed audio wrapped in PCM for HDMI @@ -271,16 +259,12 @@ public final class AudioFormat implements Parcelable { /** Audio data format: DOLBY TRUEHD compressed **/ public static final int ENCODING_DOLBY_TRUEHD = 14; - /** Audio data format: AAC ELD compressed - * @hide - * TODO unhide and add to @Encoding (intentional white space - * */ + /** Audio data format: AAC ELD compressed */ public static final int ENCODING_AAC_ELD = 15; - /** Audio data format: AAC xHE compressed - * @hide - * TODO unhide and add to @Encoding (intentional white space - * */ + /** Audio data format: AAC xHE compressed */ public static final int ENCODING_AAC_XHE = 16; + /** Audio data format: AC-4 sync frame transport format */ + public static final int ENCODING_AC4 = 17; /** @hide */ public static String toLogFriendlyEncoding(int enc) { @@ -317,6 +301,8 @@ public final class AudioFormat implements Parcelable { return "ENCODING_AAC_ELD"; case ENCODING_AAC_XHE: return "ENCODING_AAC_XHE"; + case ENCODING_AC4: + return "ENCODING_AC4"; default : return "invalid encoding " + enc; } @@ -535,6 +521,7 @@ public final class AudioFormat implements Parcelable { case ENCODING_IEC61937: case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: + case ENCODING_AC4: return true; default: return false; @@ -553,13 +540,13 @@ public final class AudioFormat implements Parcelable { case ENCODING_DTS: case ENCODING_DTS_HD: 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: + case ENCODING_AC4: return true; default: return false; @@ -586,6 +573,7 @@ public final class AudioFormat implements Parcelable { case ENCODING_IEC61937: // wrapped in PCM but compressed case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: + case ENCODING_AC4: return false; case ENCODING_INVALID: default: @@ -613,6 +601,7 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_HE_V2: case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: + case ENCODING_AC4: return false; case ENCODING_INVALID: default: @@ -849,6 +838,7 @@ public final class AudioFormat implements Parcelable { case ENCODING_AAC_HE_V2: case ENCODING_AAC_ELD: case ENCODING_AAC_XHE: + case ENCODING_AC4: mEncoding = encoding; break; case ENCODING_INVALID: @@ -1056,7 +1046,13 @@ public final class AudioFormat implements Parcelable { ENCODING_E_AC3, ENCODING_DTS, ENCODING_DTS_HD, - ENCODING_IEC61937 } + ENCODING_IEC61937, + ENCODING_AAC_HE_V1, + ENCODING_AAC_HE_V2, + ENCODING_AAC_LC, + ENCODING_AAC_ELD, + ENCODING_AAC_XHE, + ENCODING_AC4 } ) @Retention(RetentionPolicy.SOURCE) public @interface Encoding {} diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 4d5343c97b05..2ac4063d1b08 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -1331,15 +1331,13 @@ 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) { + public boolean isOffloadedPlaybackSupported(@NonNull AudioFormat format) { return AudioSystem.isOffloadSupported(format); } diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index 6add381fc885..5928d03dc4a1 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -755,8 +755,8 @@ public class AudioTrack extends PlayerBase * MODE_STREAM will be used. *
If the session ID is not specified with {@link #setSessionId(int)}, a new one will * be generated. + *
Offload is false by default. */ - // TODO add that offload is false by default (intended white space public static class Builder { private AudioAttributes mAttributes; private AudioFormat mFormat; @@ -895,14 +895,11 @@ public class AudioTrack extends PlayerBase } /** - * @hide - * TODO unhide (intentional whitespace - * TODO should offload require POWER_SAVING? * Sets whether this track will play through the offloaded audio path. * When set to true, at build time, the audio format will be checked against * {@link AudioManager#isOffloadedPlaybackSupported(AudioFormat)} to verify the audio format * used by this track is supported on the device's offload path (if any). - *
Offload is only supported for media audio data, and therefore require that + *
Offload is only supported for media audio streams, and therefore requires that * the usage be {@link AudioAttributes#USAGE_MEDIA}. * @param offload true to require the offload path for playback. * @return the same Builder instance. @@ -962,7 +959,7 @@ public class AudioTrack extends PlayerBase throw new UnsupportedOperationException( "Cannot create AudioTrack, offload requires USAGE_MEDIA"); } - if (!AudioManager.isOffloadedPlaybackSupported(mFormat)) { + if (!AudioSystem.isOffloadSupported(mFormat)) { throw new UnsupportedOperationException( "Cannot create AudioTrack, offload format not supported"); } @@ -2942,14 +2939,31 @@ public class AudioTrack extends PlayerBase } /** - * @hide - * TODO unhide (intentional white space to attract attention: * Abstract class to receive event notification about the stream playback. + * See {@link AudioTrack#setStreamEventCallback(Executor, StreamEventCallback)} to register + * the callback on the given {@link AudioTrack} instance. */ public abstract static class StreamEventCallback { - // TODO rename if supported for non offload tracks + /** @hide */ // add hidden empty constructor so it doesn't show in SDK + public StreamEventCallback() { } + /** + * Called when an offloaded track is no longer valid and has been discarded by the system. + * An example of this happening is when an offloaded track has been paused too long, and + * gets invalidated by the system to prevent any other offload. + * @param track the {@link AudioTrack} on which the event happened + */ public void onTearDown(AudioTrack track) { } + /** + * Called when all the buffers of an offloaded track that were queued in the audio system + * (e.g. the combination of the Android audio framework and the device's audio hardware) + * have been played after {@link AudioTrack#stop()} has been called. + * @param track the {@link AudioTrack} on which the event happened + */ public void onStreamPresentationEnd(AudioTrack track) { } + /** + * Called when more audio data can be written without blocking on an offloaded track. + * @param track the {@link AudioTrack} on which the event happened + */ public void onStreamDataRequest(AudioTrack track) { } } @@ -2958,11 +2972,9 @@ public class AudioTrack extends PlayerBase private final Object mStreamEventCbLock = new Object(); /** - * @hide - * TODO unhide (intentional white space to attract attention: - * Registers a callback for notification of stream events. + * Sets the callback for the notification of stream events. * @param executor {@link Executor} to handle the callbacks - * @param eventCallback the callback to receive the stream events + * @param eventCallback the callback to receive the stream event notifications */ public void setStreamEventCallback(@NonNull @CallbackExecutor Executor executor, @NonNull StreamEventCallback eventCallback) { @@ -2979,9 +2991,8 @@ public class AudioTrack extends PlayerBase } /** - * @hide * Unregisters the callback for notification of stream events, previously set - * by {@link #setStreamEventCallback(StreamEventCallback, Executor)}. + * by {@link #setStreamEventCallback(Executor, StreamEventCallback)}. */ public void removeStreamEventCallback() { synchronized (mStreamEventCbLock) { -- 2.11.0