diff options
Diffstat (limited to 'media/java/android')
-rw-r--r-- | media/java/android/media/AudioFormat.java | 15 | ||||
-rw-r--r-- | media/java/android/media/AudioManager.java | 14 | ||||
-rw-r--r-- | media/java/android/media/AudioTrack.java | 56 | ||||
-rw-r--r-- | media/java/android/media/Image.java | 29 | ||||
-rw-r--r-- | media/java/android/media/ImageReader.java | 16 | ||||
-rw-r--r-- | media/java/android/media/ImageWriter.java | 74 | ||||
-rw-r--r-- | media/java/android/media/MediaCodec.java | 35 | ||||
-rw-r--r-- | media/java/android/media/MediaSync.java | 78 | ||||
-rw-r--r-- | media/java/android/media/PlaybackSettings.java | 12 | ||||
-rw-r--r-- | media/java/android/media/tv/TvContentRating.java | 15 | ||||
-rw-r--r-- | media/java/android/media/tv/TvInputManager.java | 110 | ||||
-rw-r--r-- | media/java/android/media/tv/TvInputService.java | 11 | ||||
-rw-r--r-- | media/java/android/media/tv/TvTrackInfo.java | 9 |
13 files changed, 228 insertions, 246 deletions
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java index ff6fed2..a7e092f 100644 --- a/media/java/android/media/AudioFormat.java +++ b/media/java/android/media/AudioFormat.java @@ -55,16 +55,16 @@ public class AudioFormat { public static final int ENCODING_DTS_HD = 8; /** Invalid audio channel configuration */ - /** @deprecated use CHANNEL_INVALID instead */ + /** @deprecated Use {@link #CHANNEL_INVALID} instead. */ @Deprecated public static final int CHANNEL_CONFIGURATION_INVALID = 0; /** Default audio channel configuration */ - /** @deprecated use CHANNEL_OUT_DEFAULT or CHANNEL_IN_DEFAULT instead */ + /** @deprecated Use {@link #CHANNEL_OUT_DEFAULT} or {@link #CHANNEL_IN_DEFAULT} instead. */ @Deprecated public static final int CHANNEL_CONFIGURATION_DEFAULT = 1; /** Mono audio configuration */ - /** @deprecated use CHANNEL_OUT_MONO or CHANNEL_IN_MONO instead */ + /** @deprecated Use {@link #CHANNEL_OUT_MONO} or {@link #CHANNEL_IN_MONO} instead. */ @Deprecated public static final int CHANNEL_CONFIGURATION_MONO = 2; /** Stereo (2 channel) audio configuration */ - /** @deprecated use CHANNEL_OUT_STEREO or CHANNEL_IN_STEREO instead */ + /** @deprecated Use {@link #CHANNEL_OUT_STEREO} or {@link #CHANNEL_IN_STEREO} instead. */ @Deprecated public static final int CHANNEL_CONFIGURATION_STEREO = 3; /** Invalid audio channel mask */ @@ -117,12 +117,11 @@ public class AudioFormat { public static final int CHANNEL_OUT_5POINT1_SIDE = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_SIDE_LEFT | CHANNEL_OUT_SIDE_RIGHT); - // TODO does this need an @deprecated ? - // different from AUDIO_CHANNEL_OUT_7POINT1 - public static final int CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | + // different from AUDIO_CHANNEL_OUT_7POINT1 used internally, and not accepted by AudioRecord. + /** @deprecated Not the typical 7.1 surround configuration. Use {@link #CHANNEL_OUT_7POINT1_SURROUND} instead. */ + @Deprecated public static final int CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT | CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT | CHANNEL_OUT_FRONT_LEFT_OF_CENTER | CHANNEL_OUT_FRONT_RIGHT_OF_CENTER); - /** @hide */ // matches AUDIO_CHANNEL_OUT_7POINT1 public static final int CHANNEL_OUT_7POINT1_SURROUND = ( CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_FRONT_RIGHT | diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index cb70e8b..d851ad7 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -3147,6 +3147,20 @@ public class AudioManager { "android.media.property.OUTPUT_FRAMES_PER_BUFFER"; /** + * Used as a key for {@link #getProperty} to determine if the default microphone audio source + * supports near-ultrasound frequencies (range of 18 - 21 kHz). + */ + public static final String PROPERTY_SUPPORT_MIC_NEAR_ULTRASOUND = + "android.media.property.SUPPORT_MIC_NEAR_ULTRASOUND"; + + /** + * Used as a key for {@link #getProperty} to determine if the default speaker audio path + * supports near-ultrasound frequencies (range of 18 - 21 kHz). + */ + public static final String PROPERTY_SUPPORT_SPEAKER_NEAR_ULTRASOUND = + "android.media.property.SUPPORT_SPEAKER_NEAR_ULTRASOUND"; + + /** * Returns the value of the property with the specified key. * @param key One of the strings corresponding to a property key: either * {@link #PROPERTY_OUTPUT_SAMPLE_RATE} or diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index 3577357..6f1fd24 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -491,7 +491,7 @@ public class AudioTrack session[0] = sessionId; // native initialization int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes, - mSampleRate, mChannels, mAudioFormat, + mSampleRate, mChannels, mChannelIndexMask, mAudioFormat, mNativeBufferSizeInBytes, mDataLoadMode, session); if (initResult != SUCCESS) { loge("Error code "+initResult+" when initializing AudioTrack."); @@ -701,48 +701,6 @@ public class AudioTrack AudioFormat.CHANNEL_OUT_SIDE_LEFT | AudioFormat.CHANNEL_OUT_SIDE_RIGHT; - // Java channel mask definitions below match those - // in /system/core/include/system/audio.h in the JNI code of AudioTrack. - - // internal maximum size for bits parameter, not part of public API - private static final int AUDIO_CHANNEL_BITS_LOG2 = 30; - - // log(2) of maximum number of representations, not part of public API - private static final int AUDIO_CHANNEL_REPRESENTATION_LOG2 = 2; - - // used to create a channel index mask or channel position mask - // with getChannelMaskFromRepresentationAndBits(); - private static final int CHANNEL_OUT_REPRESENTATION_POSITION = 0; - private static final int CHANNEL_OUT_REPRESENTATION_INDEX = 2; - - /** - * Return the channel mask from its representation and bits. - * - * This creates a channel mask for mChannels which combines a - * representation field and a bits field. This is for internal - * communication to native code, not part of the public API. - * - * @param representation the type of channel mask, - * either CHANNEL_OUT_REPRESENTATION_POSITION - * or CHANNEL_OUT_REPRESENTATION_INDEX - * @param bits is the channel bits specifying occupancy - * @return the channel mask - * @throws java.lang.IllegalArgumentException if representation is not recognized or - * the bits field is not acceptable for that representation - */ - private static int getChannelMaskFromRepresentationAndBits(int representation, int bits) { - switch (representation) { - case CHANNEL_OUT_REPRESENTATION_POSITION: - case CHANNEL_OUT_REPRESENTATION_INDEX: - if ((bits & ~((1 << AUDIO_CHANNEL_BITS_LOG2) - 1)) != 0) { - throw new IllegalArgumentException("invalid bits " + bits); - } - return representation << AUDIO_CHANNEL_BITS_LOG2 | bits; - default: - throw new IllegalArgumentException("invalid representation " + representation); - } - } - // Convenience method for the constructor's parameter checks. // This is where constructor IllegalArgumentException-s are thrown // postconditions: @@ -804,11 +762,6 @@ public class AudioTrack } else if (mChannelCount != channelIndexCount) { throw new IllegalArgumentException("Channel count must match"); } - - // AudioTrack prefers to use the channel index configuration - // over the channel position configuration if both are specified. - mChannels = getChannelMaskFromRepresentationAndBits( - CHANNEL_OUT_REPRESENTATION_INDEX, mChannelIndexMask); } //-------------- @@ -973,8 +926,7 @@ public class AudioTrack return new PlaybackSettings() .setSpeed(floatArray[0]) .setPitch(floatArray[1]) - .setAudioFallbackMode(intArray[0]) - .setAudioStretchMode(intArray[1]); + .setAudioFallbackMode(intArray[0]); } /** @@ -1397,7 +1349,7 @@ public class AudioTrack }; intArray = new int[] { settings.getAudioFallbackMode(), - settings.getAudioStretchMode(), + PlaybackSettings.AUDIO_STRETCH_MODE_DEFAULT, }; } catch (IllegalStateException e) { throw new IllegalArgumentException(e); @@ -2362,7 +2314,7 @@ public class AudioTrack // AudioAttributes.USAGE_MEDIA will map to AudioManager.STREAM_MUSIC private native final int native_setup(Object /*WeakReference<AudioTrack>*/ audiotrack_this, Object /*AudioAttributes*/ attributes, - int sampleRate, int channelMask, int audioFormat, + int sampleRate, int channelMask, int channelIndexMask, int audioFormat, int buffSizeInBytes, int mode, int[] sessionId); private native final void native_finalize(); diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java index 75901fd..195c987 100644 --- a/media/java/android/media/Image.java +++ b/media/java/android/media/Image.java @@ -50,10 +50,25 @@ public abstract class Image implements AutoCloseable { /** * @hide */ + protected boolean mIsImageValid = false; + + /** + * @hide + */ protected Image() { } /** + * Throw IllegalStateException if the image is invalid (already closed). + * + * @hide + */ + protected void throwISEIfImageIsInvalid() { + if (!mIsImageValid) { + throw new IllegalStateException("Image is already closed"); + } + } + /** * Get the format for this image. This format determines the number of * ByteBuffers needed to represent the image, and the general layout of the * pixel data in each in ByteBuffer. @@ -160,7 +175,7 @@ public abstract class Image implements AutoCloseable { * Set the timestamp associated with this frame. * <p> * The timestamp is measured in nanoseconds, and is normally monotonically - * increasing. However, However, the behavior of the timestamp depends on + * increasing. However, the behavior of the timestamp depends on * the destination of this image. See {@link android.hardware.Camera Camera} * , {@link android.hardware.camera2.CameraDevice CameraDevice}, * {@link MediaPlayer} and {@link MediaCodec} for more details. @@ -176,6 +191,7 @@ public abstract class Image implements AutoCloseable { * @param timestamp The timestamp to be set for this image. */ public void setTimestamp(long timestamp) { + throwISEIfImageIsInvalid(); return; } @@ -187,6 +203,7 @@ public abstract class Image implements AutoCloseable { * </p> */ public boolean isOpaque() { + throwISEIfImageIsInvalid(); return false; } @@ -199,6 +216,8 @@ public abstract class Image implements AutoCloseable { * using coordinates in the largest-resolution plane. */ public Rect getCropRect() { + throwISEIfImageIsInvalid(); + if (mCropRect == null) { return new Rect(0, 0, getWidth(), getHeight()); } else { @@ -213,6 +232,8 @@ public abstract class Image implements AutoCloseable { * using coordinates in the largest-resolution plane. */ public void setCropRect(Rect cropRect) { + throwISEIfImageIsInvalid(); + if (cropRect != null) { cropRect = new Rect(cropRect); // make a copy cropRect.intersect(0, 0, getWidth(), getHeight()); @@ -260,6 +281,8 @@ public abstract class Image implements AutoCloseable { * a new owner. */ boolean isAttachable() { + throwISEIfImageIsInvalid(); + return false; } @@ -279,6 +302,8 @@ public abstract class Image implements AutoCloseable { * @return The owner of the Image. */ Object getOwner() { + throwISEIfImageIsInvalid(); + return null; } @@ -294,6 +319,8 @@ public abstract class Image implements AutoCloseable { * @return native context associated with this Image. */ long getNativeContext() { + throwISEIfImageIsInvalid(); + return 0; } diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java index e54525d..6d30208 100644 --- a/media/java/android/media/ImageReader.java +++ b/media/java/android/media/ImageReader.java @@ -368,7 +368,7 @@ public class ImageReader implements AutoCloseable { switch (status) { case ACQUIRE_SUCCESS: si.createSurfacePlanes(); - si.setImageValid(true); + si.mIsImageValid = true; case ACQUIRE_NO_BUFS: case ACQUIRE_MAX_IMAGES: break; @@ -444,7 +444,7 @@ public class ImageReader implements AutoCloseable { si.clearSurfacePlanes(); nativeReleaseImage(i); - si.setImageValid(false); + si.mIsImageValid = false; } /** @@ -686,7 +686,6 @@ public class ImageReader implements AutoCloseable { private class SurfaceImage extends android.media.Image { public SurfaceImage(int format) { - mIsImageValid = false; mFormat = format; } @@ -784,16 +783,6 @@ public class ImageReader implements AutoCloseable { mIsDetached.getAndSet(detached); } - private void setImageValid(boolean isValid) { - mIsImageValid = isValid; - } - - private void throwISEIfImageIsInvalid() { - if (!mIsImageValid) { - throw new IllegalStateException("Image is already closed"); - } - } - private void clearSurfacePlanes() { if (mIsImageValid) { for (int i = 0; i < mPlanes.length; i++) { @@ -877,7 +866,6 @@ public class ImageReader implements AutoCloseable { private long mTimestamp; private SurfacePlane[] mPlanes; - private boolean mIsImageValid; private int mHeight = -1; private int mWidth = -1; private int mFormat = ImageFormat.UNKNOWN; diff --git a/media/java/android/media/ImageWriter.java b/media/java/android/media/ImageWriter.java index c18b463..f805339 100644 --- a/media/java/android/media/ImageWriter.java +++ b/media/java/android/media/ImageWriter.java @@ -29,7 +29,6 @@ import java.nio.ByteOrder; import java.nio.NioUtils; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; /** * <p> @@ -204,7 +203,7 @@ public class ImageWriter implements AutoCloseable { WriterSurfaceImage newImage = new WriterSurfaceImage(this); nativeDequeueInputImage(mNativeContext, newImage); mDequeuedImages.add(newImage); - newImage.setImageValid(true); + newImage.mIsImageValid = true; return newImage; } @@ -260,7 +259,7 @@ public class ImageWriter implements AutoCloseable { throw new IllegalArgumentException("image shouldn't be null"); } boolean ownedByMe = isImageOwnedByMe(image); - if (ownedByMe && !(((WriterSurfaceImage) image).isImageValid())) { + if (ownedByMe && !(((WriterSurfaceImage) image).mIsImageValid)) { throw new IllegalStateException("Image from ImageWriter is invalid"); } @@ -312,7 +311,7 @@ public class ImageWriter implements AutoCloseable { // Do not call close here, as close is essentially cancel image. WriterSurfaceImage wi = (WriterSurfaceImage) image; wi.clearSurfacePlanes(); - wi.setImageValid(false); + wi.mIsImageValid = false; } } @@ -555,7 +554,7 @@ public class ImageWriter implements AutoCloseable { WriterSurfaceImage wi = (WriterSurfaceImage) image; - if (!wi.isImageValid()) { + if (!wi.mIsImageValid) { throw new IllegalStateException("Image is invalid"); } @@ -568,7 +567,7 @@ public class ImageWriter implements AutoCloseable { cancelImage(mNativeContext, image); mDequeuedImages.remove(image); wi.clearSurfacePlanes(); - wi.setImageValid(false); + wi.mIsImageValid = false; } private boolean isImageOwnedByMe(Image image) { @@ -585,7 +584,6 @@ public class ImageWriter implements AutoCloseable { private static class WriterSurfaceImage extends android.media.Image { private ImageWriter mOwner; - private AtomicBoolean mIsImageValid = new AtomicBoolean(false); // This field is used by native code, do not access or modify. private long mNativeBuffer; private int mNativeFenceFd = -1; @@ -604,9 +602,8 @@ public class ImageWriter implements AutoCloseable { @Override public int getFormat() { - if (!mIsImageValid.get()) { - throw new IllegalStateException("Image is already released"); - } + throwISEIfImageIsInvalid(); + if (mFormat == -1) { mFormat = nativeGetFormat(); } @@ -615,9 +612,7 @@ public class ImageWriter implements AutoCloseable { @Override public int getWidth() { - if (!mIsImageValid.get()) { - throw new IllegalStateException("Image is already released"); - } + throwISEIfImageIsInvalid(); if (mWidth == -1) { mWidth = nativeGetWidth(); @@ -628,9 +623,7 @@ public class ImageWriter implements AutoCloseable { @Override public int getHeight() { - if (!mIsImageValid.get()) { - throw new IllegalStateException("Image is already released"); - } + throwISEIfImageIsInvalid(); if (mHeight == -1) { mHeight = nativeGetHeight(); @@ -641,36 +634,28 @@ public class ImageWriter implements AutoCloseable { @Override public long getTimestamp() { - if (!mIsImageValid.get()) { - throw new IllegalStateException("Image is already released"); - } + throwISEIfImageIsInvalid(); return mTimestamp; } @Override public void setTimestamp(long timestamp) { - if (!mIsImageValid.get()) { - throw new IllegalStateException("Image is already released"); - } + throwISEIfImageIsInvalid(); mTimestamp = timestamp; } @Override public boolean isOpaque() { - if (!mIsImageValid.get()) { - throw new IllegalStateException("Image is already released"); - } + throwISEIfImageIsInvalid(); return getFormat() == ImageFormat.PRIVATE; } @Override public Plane[] getPlanes() { - if (!mIsImageValid.get()) { - throw new IllegalStateException("Image is already released"); - } + throwISEIfImageIsInvalid(); if (mPlanes == null) { int numPlanes = ImageUtils.getNumPlanesForFormat(getFormat()); @@ -682,9 +667,7 @@ public class ImageWriter implements AutoCloseable { @Override boolean isAttachable() { - if (!mIsImageValid.get()) { - throw new IllegalStateException("Image is already released"); - } + throwISEIfImageIsInvalid(); // Don't allow Image to be detached from ImageWriter for now, as no // detach API is exposed. return false; @@ -692,17 +675,21 @@ public class ImageWriter implements AutoCloseable { @Override ImageWriter getOwner() { + throwISEIfImageIsInvalid(); + return mOwner; } @Override long getNativeContext() { + throwISEIfImageIsInvalid(); + return mNativeBuffer; } @Override public void close() { - if (mIsImageValid.get()) { + if (mIsImageValid) { getOwner().abortImage(this); } } @@ -716,16 +703,8 @@ public class ImageWriter implements AutoCloseable { } } - private boolean isImageValid() { - return mIsImageValid.get(); - } - - private void setImageValid(boolean isValid) { - mIsImageValid.getAndSet(isValid); - } - private void clearSurfacePlanes() { - if (mIsImageValid.get()) { + if (mIsImageValid) { for (int i = 0; i < mPlanes.length; i++) { if (mPlanes[i] != null) { mPlanes[i].clearBuffer(); @@ -756,26 +735,19 @@ public class ImageWriter implements AutoCloseable { @Override public int getRowStride() { - if (WriterSurfaceImage.this.isImageValid() == false) { - throw new IllegalStateException("Image is already released"); - } + throwISEIfImageIsInvalid(); return mRowStride; } @Override public int getPixelStride() { - if (WriterSurfaceImage.this.isImageValid() == false) { - throw new IllegalStateException("Image is already released"); - } + throwISEIfImageIsInvalid(); return mPixelStride; } @Override public ByteBuffer getBuffer() { - if (WriterSurfaceImage.this.isImageValid() == false) { - throw new IllegalStateException("Image is already released"); - } - + throwISEIfImageIsInvalid(); return mBuffer; } diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index 1f00c7b..d22cfda 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -2059,7 +2059,6 @@ final public class MediaCodec { /** @hide */ public static class MediaImage extends Image { private final boolean mIsReadOnly; - private boolean mIsValid; private final int mWidth; private final int mHeight; private final int mFormat; @@ -2072,36 +2071,42 @@ final public class MediaCodec { private final static int TYPE_YUV = 1; + @Override public int getFormat() { - checkValid(); + throwISEIfImageIsInvalid(); return mFormat; } + @Override public int getHeight() { - checkValid(); + throwISEIfImageIsInvalid(); return mHeight; } + @Override public int getWidth() { - checkValid(); + throwISEIfImageIsInvalid(); return mWidth; } + @Override public long getTimestamp() { - checkValid(); + throwISEIfImageIsInvalid(); return mTimestamp; } + @Override @NonNull public Plane[] getPlanes() { - checkValid(); + throwISEIfImageIsInvalid(); return Arrays.copyOf(mPlanes, mPlanes.length); } + @Override public void close() { - if (mIsValid) { + if (mIsImageValid) { java.nio.NioUtils.freeDirectBuffer(mBuffer); - mIsValid = false; + mIsImageValid = false; } } @@ -2111,6 +2116,7 @@ final public class MediaCodec { * The crop rectangle specifies the region of valid pixels in the image, * using coordinates in the largest-resolution plane. */ + @Override public void setCropRect(@Nullable Rect cropRect) { if (mIsReadOnly) { throw new ReadOnlyBufferException(); @@ -2118,11 +2124,6 @@ final public class MediaCodec { super.setCropRect(cropRect); } - private void checkValid() { - if (!mIsValid) { - throw new IllegalStateException("Image is already released"); - } - } private int readInt(@NonNull ByteBuffer buffer, boolean asLong) { if (asLong) { @@ -2137,7 +2138,7 @@ final public class MediaCodec { long timestamp, int xOffset, int yOffset, @Nullable Rect cropRect) { mFormat = ImageFormat.YUV_420_888; mTimestamp = timestamp; - mIsValid = true; + mIsImageValid = true; mIsReadOnly = buffer.isReadOnly(); mBuffer = buffer.duplicate(); @@ -2208,20 +2209,20 @@ final public class MediaCodec { @Override public int getRowStride() { - checkValid(); + throwISEIfImageIsInvalid(); return mRowInc; } @Override public int getPixelStride() { - checkValid(); + throwISEIfImageIsInvalid(); return mColInc; } @Override @NonNull public ByteBuffer getBuffer() { - checkValid(); + throwISEIfImageIsInvalid(); return mData; } diff --git a/media/java/android/media/MediaSync.java b/media/java/android/media/MediaSync.java index 3b4f8e5..dc6760d 100644 --- a/media/java/android/media/MediaSync.java +++ b/media/java/android/media/MediaSync.java @@ -49,7 +49,7 @@ import java.util.List; * sync.setAudioTrack(audioTrack); * sync.setCallback(new MediaSync.Callback() { * {@literal @Override} - * public void onReturnAudioBuffer(MediaSync sync, ByteBuffer audioBuffer, int bufferIndex) { + * public void onAudioBufferConsumed(MediaSync sync, ByteBuffer audioBuffer, int bufferIndex) { * ... * } * }, null); @@ -88,7 +88,7 @@ import java.util.List; * } * * // This is the callback from MediaSync. - * onReturnAudioBuffer(MediaSync sync, ByteBuffer buffer, int bufferIndex) { + * onAudioBufferConsumed(MediaSync sync, ByteBuffer buffer, int bufferIndex) { * // ... * audioDecoder.releaseBuffer(bufferIndex, false); * // ... @@ -104,7 +104,7 @@ import java.util.List; * <p> * For audio, the client needs to set up audio track correctly, e.g., using {@link * AudioTrack#MODE_STREAM}. The audio buffers are sent to MediaSync directly via {@link - * #queueAudio}, and are returned to the client via {@link Callback#onReturnAudioBuffer} + * #queueAudio}, and are returned to the client via {@link Callback#onAudioBufferConsumed} * asynchronously. The client should not modify an audio buffer till it's returned. * <p> * The client can optionally pre-fill audio/video buffers by setting playback rate to 0.0, @@ -125,10 +125,41 @@ final public class MediaSync { * @param audioBuffer The returned audio buffer. * @param bufferIndex The index associated with the audio buffer */ - public abstract void onReturnAudioBuffer( + public abstract void onAudioBufferConsumed( @NonNull MediaSync sync, @NonNull ByteBuffer audioBuffer, int bufferIndex); } + /** Audio track failed. + * @see android.media.MediaSync.OnErrorListener + */ + public static final int MEDIASYNC_ERROR_AUDIOTRACK_FAIL = 1; + + /** The surface failed to handle video buffers. + * @see android.media.MediaSync.OnErrorListener + */ + public static final int MEDIASYNC_ERROR_SURFACE_FAIL = 2; + + /** + * Interface definition of a callback to be invoked when there + * has been an error during an asynchronous operation (other errors + * will throw exceptions at method call time). + */ + public interface OnErrorListener { + /** + * Called to indicate an error. + * + * @param sync The MediaSync the error pertains to + * @param what The type of error that has occurred: + * <ul> + * <li>{@link #MEDIASYNC_ERROR_AUDIOTRACK_FAIL} + * <li>{@link #MEDIASYNC_ERROR_SURFACE_FAIL} + * </ul> + * @param extra an extra code, specific to the error. Typically + * implementation dependent. + */ + void onError(@NonNull MediaSync sync, int what, int extra); + } + private static final String TAG = "MediaSync"; private static final int EVENT_CALLBACK = 1; @@ -155,6 +186,10 @@ final public class MediaSync { private Handler mCallbackHandler = null; private MediaSync.Callback mCallback = null; + private final Object mOnErrorListenerLock = new Object(); + private Handler mOnErrorListenerHandler = null; + private MediaSync.OnErrorListener mOnErrorListener = null; + private Thread mAudioThread = null; // Created on mAudioThread when mAudioThread is started. When used on user thread, they should // be guarded by checking mAudioThread. @@ -235,6 +270,39 @@ final public class MediaSync { } /** + * Sets an asynchronous callback for error events. + * <p> + * This method can be called multiple times to update a previously set listener. If the + * handler is changed, undelivered notifications scheduled for the old handler may be dropped. + * <p> + * <b>Do not call this inside callback.</b> + * + * @param listener The callback that will run. Use {@code null} to stop receiving callbacks. + * @param handler The Handler that will run the callback. Use {@code null} to use MediaSync's + * internal handler if it exists. + */ + public void setOnErrorListener(@Nullable /* MediaSync. */ OnErrorListener listener, + @Nullable Handler handler) { + synchronized(mOnErrorListenerLock) { + if (handler != null) { + mOnErrorListenerHandler = handler; + } else { + Looper looper; + if ((looper = Looper.myLooper()) == null) { + looper = Looper.getMainLooper(); + } + if (looper == null) { + mOnErrorListenerHandler = null; + } else { + mOnErrorListenerHandler = new Handler(looper); + } + } + + mOnErrorListener = listener; + } + } + + /** * Sets the output surface for MediaSync. * <p> * Currently, this is only supported in the Initialized state. @@ -614,7 +682,7 @@ final public class MediaSync { return; } if (mCallback != null) { - mCallback.onReturnAudioBuffer(sync, audioBuffer.mByteBuffer, + mCallback.onAudioBufferConsumed(sync, audioBuffer.mByteBuffer, audioBuffer.mBufferIndex); } } diff --git a/media/java/android/media/PlaybackSettings.java b/media/java/android/media/PlaybackSettings.java index ceb6bb1..b2e1033 100644 --- a/media/java/android/media/PlaybackSettings.java +++ b/media/java/android/media/PlaybackSettings.java @@ -38,14 +38,6 @@ import android.annotation.IntDef; * Return {@link java.lang.IllegalArgumentException} from * <code>AudioTrack.setPlaybackSettings(PlaybackSettings)</code>.</li> * </ul> - * <p> <strong>audio stretch mode:</strong> select - * timestretch handling. - * <ul> - * <li> {@link PlaybackSettings#AUDIO_STRETCH_MODE_DEFAULT}: - * System will determine best selection. </li> - * <li> {@link PlaybackSettings#AUDIO_STRETCH_MODE_VOICE}: - * Content is primarily voice.</li> - * </ul> * <p> <strong>pitch:</strong> increases or decreases the tonal frequency of the audio content. * It is expressed as a multiplicative factor, where normal pitch is 1.0f. * <p> <strong>speed:</strong> increases or decreases the time to @@ -84,7 +76,9 @@ public final class PlaybackSettings { ) @Retention(RetentionPolicy.SOURCE) public @interface AudioStretchMode {} + /** @hide */ public static final int AUDIO_STRETCH_MODE_DEFAULT = 0; + /** @hide */ public static final int AUDIO_STRETCH_MODE_VOICE = 1; // flags to indicate which settings are actually set @@ -136,6 +130,7 @@ public final class PlaybackSettings { } /** + * @hide * Sets the audio stretch mode. * @param audioStretchMode * @return this <code>PlaybackSettings</code> instance. @@ -147,6 +142,7 @@ public final class PlaybackSettings { } /** + * @hide * Retrieves the audio stretch mode. * @return audio stretch mode * @throws IllegalStateException if the audio stretch mode is not set. diff --git a/media/java/android/media/tv/TvContentRating.java b/media/java/android/media/tv/TvContentRating.java index 754facd..966e41a 100644 --- a/media/java/android/media/tv/TvContentRating.java +++ b/media/java/android/media/tv/TvContentRating.java @@ -16,9 +16,12 @@ package android.media.tv; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.text.TextUtils; +import com.android.internal.util.Preconditions; + import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -693,6 +696,12 @@ public final class TvContentRating { private final int mHashCode; /** + * Rating constant denoting unrated content. + */ + public static final TvContentRating UNRATED = new TvContentRating("com.android.tv", "", + "UNRATED", null); + + /** * Creates a {@code TvContentRating} object with predefined content rating strings. * * @param domain The domain string. For example, "com.android.tv". @@ -833,10 +842,8 @@ public final class TvContentRating { * @hide */ @SystemApi - public final boolean contains(TvContentRating rating) { - if (rating == null) { - throw new IllegalArgumentException("rating cannot be null"); - } + public final boolean contains(@NonNull TvContentRating rating) { + Preconditions.checkNotNull(rating); if (!rating.getMainRating().equals(mRating)) { return false; } diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index 0f265de..601fa45 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -40,6 +40,8 @@ import android.view.KeyEvent; import android.view.Surface; import android.view.View; +import com.android.internal.util.Preconditions; + import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; @@ -934,9 +936,7 @@ public final class TvInputManager { */ @Nullable public TvInputInfo getTvInputInfo(@NonNull String inputId) { - if (inputId == null) { - throw new IllegalArgumentException("inputId cannot be null"); - } + Preconditions.checkNotNull(inputId); try { return mService.getTvInputInfo(inputId, mUserId); } catch (RemoteException e) { @@ -958,9 +958,7 @@ public final class TvInputManager { * @throws IllegalArgumentException if the argument is {@code null}. */ public int getInputState(@NonNull String inputId) { - if (inputId == null) { - throw new IllegalArgumentException("inputId cannot be null"); - } + Preconditions.checkNotNull(inputId); synchronized (mLock) { Integer state = mStateMap.get(inputId); if (state == null) { @@ -976,15 +974,10 @@ public final class TvInputManager { * * @param callback A callback used to monitor status of the TV inputs. * @param handler A {@link Handler} that the status change will be delivered to. - * @throws IllegalArgumentException if any of the arguments is {@code null}. */ public void registerCallback(@NonNull TvInputCallback callback, @NonNull Handler handler) { - if (callback == null) { - throw new IllegalArgumentException("callback cannot be null"); - } - if (handler == null) { - throw new IllegalArgumentException("handler cannot be null"); - } + Preconditions.checkNotNull(callback); + Preconditions.checkNotNull(handler); synchronized (mLock) { mCallbackRecords.add(new TvInputCallbackRecord(callback, handler)); } @@ -994,12 +987,9 @@ public final class TvInputManager { * Unregisters the existing {@link TvInputCallback}. * * @param callback The existing callback to remove. - * @throws IllegalArgumentException if any of the arguments is {@code null}. */ public void unregisterCallback(@NonNull final TvInputCallback callback) { - if (callback == null) { - throw new IllegalArgumentException("callback cannot be null"); - } + Preconditions.checkNotNull(callback); synchronized (mLock) { for (Iterator<TvInputCallbackRecord> it = mCallbackRecords.iterator(); it.hasNext(); ) { @@ -1049,9 +1039,7 @@ public final class TvInputManager { * @return {@code true} if the given TV content rating is blocked, {@code false} otherwise. */ public boolean isRatingBlocked(@NonNull TvContentRating rating) { - if (rating == null) { - throw new IllegalArgumentException("rating cannot be null"); - } + Preconditions.checkNotNull(rating); try { return mService.isRatingBlocked(rating.flattenToString(), mUserId); } catch (RemoteException e) { @@ -1087,10 +1075,8 @@ public final class TvInputManager { * @hide */ @SystemApi - public void addBlockedRating(TvContentRating rating) { - if (rating == null) { - throw new IllegalArgumentException("rating cannot be null"); - } + public void addBlockedRating(@NonNull TvContentRating rating) { + Preconditions.checkNotNull(rating); try { mService.addBlockedRating(rating.flattenToString(), mUserId); } catch (RemoteException e) { @@ -1107,10 +1093,8 @@ public final class TvInputManager { * @hide */ @SystemApi - public void removeBlockedRating(TvContentRating rating) { - if (rating == null) { - throw new IllegalArgumentException("rating cannot be null"); - } + public void removeBlockedRating(@NonNull TvContentRating rating) { + Preconditions.checkNotNull(rating); try { mService.removeBlockedRating(rating.flattenToString(), mUserId); } catch (RemoteException e) { @@ -1140,21 +1124,14 @@ public final class TvInputManager { * @param inputId The id of the TV input. * @param callback A callback used to receive the created session. * @param handler A {@link Handler} that the session creation will be delivered to. - * @throws IllegalArgumentException if any of the arguments is {@code null}. * @hide */ @SystemApi - public void createSession(String inputId, final SessionCallback callback, - Handler handler) { - if (inputId == null) { - throw new IllegalArgumentException("id cannot be null"); - } - if (callback == null) { - throw new IllegalArgumentException("callback cannot be null"); - } - if (handler == null) { - throw new IllegalArgumentException("handler cannot be null"); - } + public void createSession(@NonNull String inputId, @NonNull final SessionCallback callback, + @NonNull Handler handler) { + Preconditions.checkNotNull(inputId); + Preconditions.checkNotNull(callback); + Preconditions.checkNotNull(handler); SessionCallbackRecord record = new SessionCallbackRecord(callback, handler); synchronized (mSessionCallbackRecordMap) { int seq = mNextSeq++; @@ -1436,7 +1413,6 @@ public final class TvInputManager { * Tunes to a given channel. * * @param channelUri The URI of a channel. - * @throws IllegalArgumentException if the argument is {@code null}. */ public void tune(Uri channelUri) { tune(channelUri, null); @@ -1447,14 +1423,11 @@ public final class TvInputManager { * * @param channelUri The URI of a channel. * @param params A set of extra parameters which might be handled with this tune event. - * @throws IllegalArgumentException if {@code channelUri} is {@code null}. * @hide */ @SystemApi - public void tune(Uri channelUri, Bundle params) { - if (channelUri == null) { - throw new IllegalArgumentException("channelUri cannot be null"); - } + public void tune(@NonNull Uri channelUri, Bundle params) { + Preconditions.checkNotNull(channelUri); if (mToken == null) { Log.w(TAG, "The session has been already released"); return; @@ -1790,16 +1763,11 @@ public final class TvInputManager { * * @param view A view playing TV. * @param frame A position of the overlay view. - * @throws IllegalArgumentException if any of the arguments is {@code null}. * @throws IllegalStateException if {@code view} is not attached to a window. */ - void createOverlayView(View view, Rect frame) { - if (view == null) { - throw new IllegalArgumentException("view cannot be null"); - } - if (frame == null) { - throw new IllegalArgumentException("frame cannot be null"); - } + void createOverlayView(@NonNull View view, @NonNull Rect frame) { + Preconditions.checkNotNull(view); + Preconditions.checkNotNull(frame); if (view.getWindowToken() == null) { throw new IllegalStateException("view must be attached to a window"); } @@ -1818,12 +1786,9 @@ public final class TvInputManager { * Relayouts the current overlay view. * * @param frame A new position of the overlay view. - * @throws IllegalArgumentException if the arguments is {@code null}. */ - void relayoutOverlayView(Rect frame) { - if (frame == null) { - throw new IllegalArgumentException("frame cannot be null"); - } + void relayoutOverlayView(@NonNull Rect frame) { + Preconditions.checkNotNull(frame); if (mToken == null) { Log.w(TAG, "The session has been already released"); return; @@ -1853,14 +1818,12 @@ public final class TvInputManager { /** * Requests to unblock content blocked by parental controls. */ - void requestUnblockContent(TvContentRating unblockedRating) { + void requestUnblockContent(@NonNull TvContentRating unblockedRating) { + Preconditions.checkNotNull(unblockedRating); if (mToken == null) { Log.w(TAG, "The session has been already released"); return; } - if (unblockedRating == null) { - throw new IllegalArgumentException("unblockedRating cannot be null"); - } try { mService.requestUnblockContent(mToken, unblockedRating.flattenToString(), mUserId); } catch (RemoteException e) { @@ -1871,25 +1834,22 @@ public final class TvInputManager { /** * Dispatches an input event to this session. * - * @param event An {@link InputEvent} to dispatch. + * @param event An {@link InputEvent} to dispatch. Cannot be {@code null}. * @param token A token used to identify the input event later in the callback. - * @param callback A callback used to receive the dispatch result. - * @param handler A {@link Handler} that the dispatch result will be delivered to. + * @param callback A callback used to receive the dispatch result. Cannot be {@code null}. + * @param handler A {@link Handler} that the dispatch result will be delivered to. Cannot be + * {@code null}. * @return Returns {@link #DISPATCH_HANDLED} if the event was handled. Returns * {@link #DISPATCH_NOT_HANDLED} if the event was not handled. Returns * {@link #DISPATCH_IN_PROGRESS} if the event is in progress and the callback will * be invoked later. - * @throws IllegalArgumentException if any of the necessary arguments is {@code null}. * @hide */ - public int dispatchInputEvent(InputEvent event, Object token, - FinishedInputEventCallback callback, Handler handler) { - if (event == null) { - throw new IllegalArgumentException("event cannot be null"); - } - if (callback != null && handler == null) { - throw new IllegalArgumentException("handler cannot be null"); - } + public int dispatchInputEvent(@NonNull InputEvent event, Object token, + @NonNull FinishedInputEventCallback callback, @NonNull Handler handler) { + Preconditions.checkNotNull(event); + Preconditions.checkNotNull(callback); + Preconditions.checkNotNull(handler); synchronized (mHandler) { if (mChannel == null) { return DISPATCH_NOT_HANDLED; diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java index 4258534..5156ae8 100644 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -51,6 +51,7 @@ import android.view.accessibility.CaptioningManager; import android.widget.FrameLayout; import com.android.internal.os.SomeArgs; +import com.android.internal.util.Preconditions; import java.util.ArrayList; import java.util.HashSet; @@ -313,10 +314,8 @@ public abstract class TvInputService extends Service { * @hide */ @SystemApi - public void notifySessionEvent(final String eventType, final Bundle eventArgs) { - if (eventType == null) { - throw new IllegalArgumentException("eventType cannot be null"); - } + public void notifySessionEvent(@NonNull final String eventType, final Bundle eventArgs) { + Preconditions.checkNotNull(eventType); executeOrPostRunnable(new Runnable() { @Override public void run() { @@ -546,9 +545,7 @@ public abstract class TvInputService extends Service { * @see TvInputManager */ public void notifyContentBlocked(@NonNull final TvContentRating rating) { - if (rating == null) { - throw new IllegalArgumentException("rating cannot be null"); - } + Preconditions.checkNotNull(rating); executeOrPostRunnable(new Runnable() { @Override public void run() { diff --git a/media/java/android/media/tv/TvTrackInfo.java b/media/java/android/media/tv/TvTrackInfo.java index 6eedeb4..2c956e9 100644 --- a/media/java/android/media/tv/TvTrackInfo.java +++ b/media/java/android/media/tv/TvTrackInfo.java @@ -16,10 +16,13 @@ package android.media.tv; +import android.annotation.NonNull; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; +import com.android.internal.util.Preconditions; + /** * Encapsulates the format of tracks played in {@link TvInputService}. */ @@ -245,15 +248,13 @@ public final class TvTrackInfo implements Parcelable { * @param id The ID of the track that uniquely identifies the current track among all the * other tracks in the same TV program. */ - public Builder(int type, String id) { + public Builder(int type, @NonNull String id) { if (type != TYPE_AUDIO && type != TYPE_VIDEO && type != TYPE_SUBTITLE) { throw new IllegalArgumentException("Unknown type: " + type); } - if (id == null) { - throw new IllegalArgumentException("id cannot be null"); - } + Preconditions.checkNotNull(id); mType = type; mId = id; } |