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

Commit 3195b747 authored by Luan Nguyen's avatar Luan Nguyen Committed by Android Git Automerger
Browse files

Merge branch 'master' of...

parents fd4ffb7d 105295ed
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -14730,6 +14730,16 @@ package android.media {
    field public static final int WRITE_NON_BLOCKING = 1; // 0x1
  }
  public static class AudioTrack.Builder {
    ctor public AudioTrack.Builder();
    method public android.media.AudioTrack build() throws java.lang.UnsupportedOperationException;
    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 setSessionId(int) throws java.lang.IllegalArgumentException;
    method public android.media.AudioTrack.Builder setTransferMode(int) throws java.lang.IllegalArgumentException;
  }
  public static abstract interface AudioTrack.OnPlaybackPositionUpdateListener {
    method public abstract void onMarkerReached(android.media.AudioTrack);
    method public abstract void onPeriodicNotification(android.media.AudioTrack);
+10 −0
Original line number Diff line number Diff line
@@ -15938,6 +15938,16 @@ package android.media {
    field public static final int WRITE_NON_BLOCKING = 1; // 0x1
  }
  public static class AudioTrack.Builder {
    ctor public AudioTrack.Builder();
    method public android.media.AudioTrack build() throws java.lang.UnsupportedOperationException;
    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 setSessionId(int) throws java.lang.IllegalArgumentException;
    method public android.media.AudioTrack.Builder setTransferMode(int) throws java.lang.IllegalArgumentException;
  }
  public static abstract interface AudioTrack.OnPlaybackPositionUpdateListener {
    method public abstract void onMarkerReached(android.media.AudioTrack);
    method public abstract void onPeriodicNotification(android.media.AudioTrack);
+184 −1
Original line number Diff line number Diff line
@@ -21,7 +21,10 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.nio.NioUtils;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.app.AppOpsManager;
import android.content.Context;
@@ -113,6 +116,14 @@ public class AudioTrack
     */
    public static final int MODE_STREAM = 1;

    /** @hide */
    @IntDef({
        MODE_STATIC,
        MODE_STREAM
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface TransferMode {}

    /**
     * State of an AudioTrack that was not successfully initialized upon creation.
     */
@@ -457,6 +468,179 @@ public class AudioTrack
        }
    }

    /**
     * Builder class for {@link AudioTrack} objects.
     * Use this class to configure and create an <code>AudioTrack</code> instance. By setting audio
     * attributes and audio format parameters, you indicate which of those vary from the default
     * behavior on the device.
     * <p> Here is an example where <code>Builder</code> is used to specify all {@link AudioFormat}
     * parameters, to be used by a new <code>AudioTrack</code> instance:
     *
     * <pre class="prettyprint">
     * AudioTrack player = new AudioTrack.Builder()
     *         .setAudioAttributes(new AudioAttributes.Builder()
     *                  .setUsage(AudioAttributes.USAGE_ALARM)
     *                  .setContentType(CONTENT_TYPE_MUSIC)
     *                  .build())
     *         .setAudioFormat(new AudioFormat.Builder()
     *                 .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
     *                 .setSampleRate(441000)
     *                 .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)
     *                 .build())
     *         .setBufferSize(minBuffSize)
     *         .build();
     * </pre>
     * <p>
     * If the audio attributes are not set with {@link #setAudioAttributes(AudioAttributes)},
     * attributes comprising {@link AudioAttributes#USAGE_MEDIA} will be used.
     * <br>If the audio format is not specified or is incomplete, its sample rate will be the
     * default output sample rate of the device (see
     * {@link AudioManager#PROPERTY_OUTPUT_SAMPLE_RATE}), its channel configuration will be
     * {@link AudioFormat#CHANNEL_OUT_STEREO} and the encoding will be
     * {@link AudioFormat#ENCODING_PCM_16BIT}.
     * <br>If the transfer mode is not specified with {@link #setTransferMode(int)},
     * {@link AudioTrack#MODE_STREAM} will be used.
     * <br>If the session ID is not specified with {@link #setSessionId(int)}, a new one will
     * be generated.
     */
    public static class Builder {
        private AudioAttributes mAttributes;
        private AudioFormat mFormat;
        private int mBufferSizeInBytes;
        private int mSessionId = AudioManager.AUDIO_SESSION_ID_GENERATE;
        private int mMode = MODE_STREAM;

        /**
         * Constructs a new Builder with the default values as described above.
         */
        public Builder() {
        }

        /**
         * Sets the {@link AudioAttributes}.
         * @param attributes a non-null {@link AudioAttributes} instance that describes the audio
         *     data to be played.
         * @return the same Builder instance.
         * @throws IllegalArgumentException
         */
        public @NonNull Builder setAudioAttributes(@NonNull AudioAttributes attributes)
                throws IllegalArgumentException {
            if (attributes == null) {
                throw new IllegalArgumentException("Illegal null AudioAttributes argument");
            }
            // keep reference, we only copy the data when building
            mAttributes = attributes;
            return this;
        }

        /**
         * Sets the format of the audio data to be played by the {@link AudioTrack}.
         * See {@link AudioFormat.Builder} for configuring the audio format parameters such
         * as encoding, channel mask and sample rate.
         * @param format a non-null {@link AudioFormat} instance.
         * @return the same Builder instance.
         * @throws IllegalArgumentException
         */
        public @NonNull Builder setAudioFormat(@NonNull AudioFormat format)
                throws IllegalArgumentException {
            if (format == null) {
                throw new IllegalArgumentException("Illegal null AudioFormat argument");
            }
            // keep reference, we only copy the data when building
            mFormat = format;
            return this;
        }

        /**
         * Sets the total size (in bytes) of the buffer where audio data is read from for playback.
         * If using the {@link AudioTrack} in streaming mode
         * (see {@link AudioTrack#MODE_STREAM}, you can write data into this buffer in smaller
         * chunks than this size. See {@link #getMinBufferSize(int, int, int)} to determine
         * the minimum required buffer size for the successful creation of an AudioTrack instance
         * in streaming mode. Using values smaller than <code>getMinBufferSize()</code> will result
         * in an exception when trying to build the <code>AudioTrack</code>.
         * <br>If using the <code>AudioTrack</code> in static mode (see
         * {@link AudioTrack#MODE_STATIC}), this is the maximum size of the sound that will be
         * played by this instance.
         * @param bufferSizeInBytes
         * @return the same Builder instance.
         * @throws IllegalArgumentException
         */
        public @NonNull Builder setBufferSizeInBytes(int bufferSizeInBytes)
                throws IllegalArgumentException {
            if (bufferSizeInBytes <= 0) {
                throw new IllegalArgumentException("Invalid buffer size " + bufferSizeInBytes);
            }
            mBufferSizeInBytes = bufferSizeInBytes;
            return this;
        }

        /**
         * Sets the mode under which buffers of audio data are transferred from the
         * {@link AudioTrack} to the framework.
         * @param mode one of {@link AudioTrack#MODE_STREAM}, {@link AudioTrack#MODE_STATIC}.
         * @return the same Builder instance.
         * @throws IllegalArgumentException
         */
        public @NonNull Builder setTransferMode(@TransferMode int mode)
                throws IllegalArgumentException {
            switch(mode) {
                case MODE_STREAM:
                case MODE_STATIC:
                    mMode = mode;
                    break;
                default:
                    throw new IllegalArgumentException("Invalid transfer mode " + mode);
            }
            return this;
        }

        /**
         * Sets the session ID the {@link AudioTrack} will be attached to.
         * @param sessionId a strictly positive ID number retrieved from another
         *     <code>AudioTrack</code> via {@link AudioTrack#getAudioSessionId()} or allocated by
         *     {@link AudioManager} via {@link AudioManager#generateAudioSessionId()}, or
         *     {@link AudioManager#AUDIO_SESSION_ID_GENERATE}.
         * @return the same Builder instance.
         * @throws IllegalArgumentException
         */
        public @NonNull Builder setSessionId(int sessionId)
                throws IllegalArgumentException {
            if ((sessionId != AudioManager.AUDIO_SESSION_ID_GENERATE) && (sessionId < 1)) {
                throw new IllegalArgumentException("Invalid audio session ID " + sessionId);
            }
            mSessionId = sessionId;
            return this;
        }

        /**
         * Builds an {@link AudioTrack} instance initialized with all the parameters set
         * on this <code>Builder</code>.
         * @return a new {@link AudioTrack} instance.
         * @throws UnsupportedOperationException if the parameters set on the <code>Builder</code>
         *     were incompatible, or if they are not supported by the device.
         */
        public @NonNull AudioTrack build() throws UnsupportedOperationException {
            if (mAttributes == null) {
                mAttributes = new AudioAttributes.Builder()
                        .setUsage(AudioAttributes.USAGE_MEDIA)
                        .build();
            }
            if (mFormat == null) {
                mFormat = new AudioFormat.Builder()
                        .setChannelMask(AudioFormat.CHANNEL_OUT_STEREO)
                        .setSampleRate(AudioSystem.getPrimaryOutputSamplingRate())
                        .setEncoding(AudioFormat.ENCODING_DEFAULT)
                        .build();
            }
            try {
                return new AudioTrack(mAttributes, mFormat, mBufferSizeInBytes, mMode, mSessionId);
            } catch (IllegalArgumentException e) {
                throw new UnsupportedOperationException(e.getMessage());
            }
        }
    }

    // mask of all the channels supported by this implementation
    private static final int SUPPORTED_OUT_CHANNELS =
            AudioFormat.CHANNEL_OUT_FRONT_LEFT |
@@ -1749,5 +1933,4 @@ public class AudioTrack
    private static void loge(String msg) {
        Log.e(TAG, msg);
    }

}