summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLajos Molnar <lajos@google.com>2015-04-22 17:08:22 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-04-22 17:08:23 +0000
commitce510d5f62a0e4dc46d3d3c05fafe9b08eb5b497 (patch)
tree44db6799c372a47ec1fb65eda6979524a64ce319
parent6bac04abc9f945911498a182cea52b48e0b43f23 (diff)
parent99f8072386ce9891a5973d591dc1a30e45b50bc6 (diff)
downloadframeworks_base-ce510d5f62a0e4dc46d3d3c05fafe9b08eb5b497.zip
frameworks_base-ce510d5f62a0e4dc46d3d3c05fafe9b08eb5b497.tar.gz
frameworks_base-ce510d5f62a0e4dc46d3d3c05fafe9b08eb5b497.tar.bz2
Merge "media: add annotations to low-level Media* classes"
-rw-r--r--api/current.txt2
-rw-r--r--api/system-current.txt2
-rw-r--r--media/java/android/media/MediaCodec.java212
-rw-r--r--media/java/android/media/MediaCrypto.java16
-rw-r--r--media/java/android/media/MediaCryptoException.java4
-rw-r--r--media/java/android/media/MediaDrm.java344
-rw-r--r--media/java/android/media/MediaExtractor.java69
-rw-r--r--media/java/android/media/MediaMuxer.java41
-rw-r--r--media/java/android/media/MediaSync.java34
9 files changed, 532 insertions, 192 deletions
diff --git a/api/current.txt b/api/current.txt
index c7fdc6a..a126699 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -15733,7 +15733,7 @@ package android.media {
method public final void release();
method public void seekTo(long, int);
method public void selectTrack(int);
- method public final void setDataSource(android.media.MediaDataSource) throws java.io.IOException, java.lang.IllegalArgumentException;
+ method public final void setDataSource(android.media.MediaDataSource) throws java.io.IOException;
method public final void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
method public final void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
method public final void setDataSource(java.lang.String) throws java.io.IOException;
diff --git a/api/system-current.txt b/api/system-current.txt
index 35dc610..e149048 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -16946,7 +16946,7 @@ package android.media {
method public final void release();
method public void seekTo(long, int);
method public void selectTrack(int);
- method public final void setDataSource(android.media.MediaDataSource) throws java.io.IOException, java.lang.IllegalArgumentException;
+ method public final void setDataSource(android.media.MediaDataSource) throws java.io.IOException;
method public final void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
method public final void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
method public final void setDataSource(java.lang.String) throws java.io.IOException;
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index d82afdf..b0cd3e4 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -16,6 +16,9 @@
package android.media;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.media.Image;
@@ -30,6 +33,8 @@ import android.os.Message;
import android.view.Surface;
import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.nio.ByteBuffer;
import java.nio.ReadOnlyBufferException;
import java.util.Arrays;
@@ -253,7 +258,7 @@ final public class MediaCodec {
* {@link #BUFFER_FLAG_END_OF_STREAM}.
*/
public void set(
- int newOffset, int newSize, long newTimeUs, int newFlags) {
+ int newOffset, int newSize, long newTimeUs, @BufferFlag int newFlags) {
offset = newOffset;
size = newSize;
presentationTimeUs = newTimeUs;
@@ -293,6 +298,7 @@ final public class MediaCodec {
* be an empty buffer, whose sole purpose is to carry the end-of-stream
* marker.
*/
+ @BufferFlag
public int flags;
};
@@ -325,6 +331,18 @@ final public class MediaCodec {
*/
public static final int BUFFER_FLAG_END_OF_STREAM = 4;
+ /** @hide */
+ @IntDef(
+ flag = true,
+ value = {
+ BUFFER_FLAG_SYNC_FRAME,
+ BUFFER_FLAG_KEY_FRAME,
+ BUFFER_FLAG_CODEC_CONFIG,
+ BUFFER_FLAG_END_OF_STREAM,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface BufferFlag {}
+
private EventHandler mEventHandler;
private Callback mCallback;
@@ -339,13 +357,13 @@ final public class MediaCodec {
private class EventHandler extends Handler {
private MediaCodec mCodec;
- public EventHandler(MediaCodec codec, Looper looper) {
+ public EventHandler(@NonNull MediaCodec codec, @NonNull Looper looper) {
super(looper);
mCodec = codec;
}
@Override
- public void handleMessage(Message msg) {
+ public void handleMessage(@NonNull Message msg) {
switch (msg.what) {
case EVENT_CALLBACK:
{
@@ -364,7 +382,7 @@ final public class MediaCodec {
}
}
- private void handleCallback(Message msg) {
+ private void handleCallback(@NonNull Message msg) {
if (mCallback == null) {
return;
}
@@ -438,7 +456,8 @@ final public class MediaCodec {
* @throws IllegalArgumentException if type is not a valid mime type.
* @throws NullPointerException if type is null.
*/
- public static MediaCodec createDecoderByType(String type)
+ @NonNull
+ public static MediaCodec createDecoderByType(@NonNull String type)
throws IOException {
return new MediaCodec(type, true /* nameIsType */, false /* encoder */);
}
@@ -450,7 +469,8 @@ final public class MediaCodec {
* @throws IllegalArgumentException if type is not a valid mime type.
* @throws NullPointerException if type is null.
*/
- public static MediaCodec createEncoderByType(String type)
+ @NonNull
+ public static MediaCodec createEncoderByType(@NonNull String type)
throws IOException {
return new MediaCodec(type, true /* nameIsType */, true /* encoder */);
}
@@ -464,14 +484,15 @@ final public class MediaCodec {
* @throws IllegalArgumentException if name is not valid.
* @throws NullPointerException if name is null.
*/
- public static MediaCodec createByCodecName(String name)
+ @NonNull
+ public static MediaCodec createByCodecName(@NonNull String name)
throws IOException {
return new MediaCodec(
name, false /* nameIsType */, false /* unused */);
}
private MediaCodec(
- String name, boolean nameIsType, boolean encoder) {
+ @NonNull String name, boolean nameIsType, boolean encoder) {
Looper looper;
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
@@ -524,15 +545,26 @@ final public class MediaCodec {
*/
public static final int CONFIGURE_FLAG_ENCODE = 1;
+ /** @hide */
+ @IntDef(flag = true, value = { CONFIGURE_FLAG_ENCODE })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ConfigureFlag {}
+
/**
* Configures a component.
*
* @param format The format of the input data (decoder) or the desired
- * format of the output data (encoder).
+ * format of the output data (encoder). Passing {@code null}
+ * as {@code format} is equivalent to passing an
+ * {@link MediaFormat#MediaFormat an empty mediaformat}.
* @param surface Specify a surface on which to render the output of this
- * decoder.
+ * decoder. Pass {@code null} as {@code surface} if the
+ * codec does not generate raw video output (e.g. not a video
+ * decoder) and/or if you want to configure the codec for
+ * {@link ByteBuffer} output.
* @param crypto Specify a crypto object to facilitate secure decryption
- * of the media data.
+ * of the media data. Pass {@code null} as {@code crypto} for
+ * non-secure codecs.
* @param flags Specify {@link #CONFIGURE_FLAG_ENCODE} to configure the
* component as an encoder.
* @throws IllegalArgumentException if the surface has been released (or is invalid),
@@ -544,14 +576,14 @@ final public class MediaCodec {
* @throws CodecException upon codec error.
*/
public void configure(
- MediaFormat format,
- Surface surface, MediaCrypto crypto, int flags) {
- Map<String, Object> formatMap = format.getMap();
-
+ @Nullable MediaFormat format,
+ @Nullable Surface surface, @Nullable MediaCrypto crypto,
+ @ConfigureFlag int flags) {
String[] keys = null;
Object[] values = null;
if (format != null) {
+ Map<String, Object> formatMap = format.getMap();
keys = new String[formatMap.size()];
values = new Object[formatMap.size()];
@@ -578,11 +610,11 @@ final public class MediaCodec {
native_configure(keys, values, surface, crypto, flags);
}
- private native final void native_setCallback(Callback cb);
+ private native final void native_setCallback(@Nullable Callback cb);
private native final void native_configure(
- String[] keys, Object[] values,
- Surface surface, MediaCrypto crypto, int flags);
+ @Nullable String[] keys, @Nullable Object[] values,
+ @Nullable Surface surface, @Nullable MediaCrypto crypto, @ConfigureFlag int flags);
/**
* Requests a Surface to use as the input to an encoder, in place of input buffers. This
@@ -596,6 +628,7 @@ final public class MediaCodec {
* unexpected results.
* @throws IllegalStateException if not in the Configured state.
*/
+ @NonNull
public native final Surface createInputSurface();
/**
@@ -669,7 +702,7 @@ final public class MediaCodec {
* Thrown when an internal codec error occurs.
*/
public final static class CodecException extends IllegalStateException {
- CodecException(int errorCode, int actionCode, String detailMessage, int reason) {
+ CodecException(int errorCode, int actionCode, @Nullable String detailMessage, int reason) {
super(detailMessage);
mErrorCode = errorCode;
mReason = reason;
@@ -704,6 +737,7 @@ final public class MediaCodec {
* The reason could be one of {@link #REASON_HARDWARE} or {@link #REASON_RECLAIMED}.
*
*/
+ @ReasonCode
public int getReason() {
return mReason;
}
@@ -725,7 +759,7 @@ final public class MediaCodec {
* since this string will not be localized or generally
* comprehensible to end-users.
*/
- public String getDiagnosticInfo() {
+ public @NonNull String getDiagnosticInfo() {
return mDiagnosticInfo;
}
@@ -742,6 +776,14 @@ final public class MediaCodec {
*/
public static final int REASON_RECLAIMED = 1;
+ /** @hide */
+ @IntDef({
+ REASON_HARDWARE,
+ REASON_RECLAIMED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ReasonCode {}
+
/* Must be in sync with android_media_MediaCodec.cpp */
private final static int ACTION_TRANSIENT = 1;
private final static int ACTION_RECOVERABLE = 2;
@@ -756,7 +798,7 @@ final public class MediaCodec {
* Thrown when a crypto error occurs while queueing a secure input buffer.
*/
public final static class CryptoException extends RuntimeException {
- public CryptoException(int errorCode, String detailMessage) {
+ public CryptoException(int errorCode, @Nullable String detailMessage) {
super(detailMessage);
mErrorCode = errorCode;
}
@@ -789,9 +831,20 @@ final public class MediaCodec {
*/
public static final int ERROR_INSUFFICIENT_OUTPUT_PROTECTION = 4;
+ /** @hide */
+ @IntDef({
+ ERROR_NO_KEY,
+ ERROR_KEY_EXPIRED,
+ ERROR_RESOURCE_BUSY,
+ ERROR_INSUFFICIENT_OUTPUT_PROTECTION,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CryptoErrorCode {}
+
/**
* Retrieve the error code associated with a CryptoException
*/
+ @CryptoErrorCode
public int getErrorCode() {
return mErrorCode;
}
@@ -885,10 +938,10 @@ final public class MediaCodec {
public final static class CryptoInfo {
public void set(
int newNumSubSamples,
- int[] newNumBytesOfClearData,
- int[] newNumBytesOfEncryptedData,
- byte[] newKey,
- byte[] newIV,
+ @NonNull int[] newNumBytesOfClearData,
+ @NonNull int[] newNumBytesOfEncryptedData,
+ @NonNull byte[] newKey,
+ @NonNull byte[] newIV,
int newMode) {
numSubSamples = newNumSubSamples;
numBytesOfClearData = newNumBytesOfClearData;
@@ -970,7 +1023,7 @@ final public class MediaCodec {
public final void queueSecureInputBuffer(
int index,
int offset,
- CryptoInfo info,
+ @NonNull CryptoInfo info,
long presentationTimeUs,
int flags) throws CryptoException {
synchronized(mBufferLock) {
@@ -989,7 +1042,7 @@ final public class MediaCodec {
private native final void native_queueSecureInputBuffer(
int index,
int offset,
- CryptoInfo info,
+ @NonNull CryptoInfo info,
long presentationTimeUs,
int flags) throws CryptoException;
@@ -1043,6 +1096,15 @@ final public class MediaCodec {
*/
public static final int INFO_OUTPUT_BUFFERS_CHANGED = -3;
+ /** @hide */
+ @IntDef({
+ INFO_TRY_AGAIN_LATER,
+ INFO_OUTPUT_FORMAT_CHANGED,
+ INFO_OUTPUT_BUFFERS_CHANGED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface OutputBufferInfo {}
+
/**
* Dequeue an output buffer, block at most "timeoutUs" microseconds.
* Returns the index of an output buffer that has been successfully
@@ -1053,8 +1115,9 @@ final public class MediaCodec {
* or codec is configured in asynchronous mode.
* @throws MediaCodec.CodecException upon codec error.
*/
+ @OutputBufferInfo
public final int dequeueOutputBuffer(
- BufferInfo info, long timeoutUs) {
+ @NonNull BufferInfo info, long timeoutUs) {
int res = native_dequeueOutputBuffer(info, timeoutUs);
synchronized(mBufferLock) {
if (res == INFO_OUTPUT_BUFFERS_CHANGED) {
@@ -1067,7 +1130,7 @@ final public class MediaCodec {
}
private native final int native_dequeueOutputBuffer(
- BufferInfo info, long timeoutUs);
+ @NonNull BufferInfo info, long timeoutUs);
/**
* If you are done with a buffer, use this call to return the buffer to
@@ -1176,6 +1239,7 @@ final public class MediaCodec {
* Configured state.
* @throws MediaCodec.CodecException upon codec error.
*/
+ @NonNull
public final MediaFormat getOutputFormat() {
return new MediaFormat(getFormatNative(false /* input */));
}
@@ -1190,6 +1254,7 @@ final public class MediaCodec {
* Configured state.
* @throws MediaCodec.CodecException upon codec error.
*/
+ @NonNull
public final MediaFormat getInputFormat() {
return new MediaFormat(getFormatNative(true /* input */));
}
@@ -1203,12 +1268,15 @@ final public class MediaCodec {
* @return the format for the output buffer, or null if the index
* is not a dequeued output buffer.
*/
+ @NonNull
public final MediaFormat getOutputFormat(int index) {
return new MediaFormat(getOutputFormatNative(index));
}
+ @NonNull
private native final Map<String, Object> getFormatNative(boolean input);
+ @NonNull
private native final Map<String, Object> getOutputFormatNative(int index);
// used to track dequeued buffers
@@ -1230,12 +1298,12 @@ final public class MediaCodec {
}
}
- public void setImage(Image image) {
+ public void setImage(@Nullable Image image) {
free();
mImage = image;
}
- public void setByteBuffer(ByteBuffer buffer) {
+ public void setByteBuffer(@Nullable ByteBuffer buffer) {
free();
mByteBuffer = buffer;
}
@@ -1252,7 +1320,7 @@ final public class MediaCodec {
}
}
- public void put(int index, ByteBuffer newBuffer) {
+ public void put(int index, @Nullable ByteBuffer newBuffer) {
CodecBuffer buffer = mMap.get(index);
if (buffer == null) { // likely
buffer = new CodecBuffer();
@@ -1261,7 +1329,7 @@ final public class MediaCodec {
buffer.setByteBuffer(newBuffer);
}
- public void put(int index, Image newImage) {
+ public void put(int index, @Nullable Image newImage) {
CodecBuffer buffer = mMap.get(index);
if (buffer == null) { // likely
buffer = new CodecBuffer();
@@ -1285,7 +1353,7 @@ final public class MediaCodec {
final private Object mBufferLock;
private final void invalidateByteBuffer(
- ByteBuffer[] buffers, int index) {
+ @Nullable ByteBuffer[] buffers, int index) {
if (buffers != null && index >= 0 && index < buffers.length) {
ByteBuffer buffer = buffers[index];
if (buffer != null) {
@@ -1295,7 +1363,7 @@ final public class MediaCodec {
}
private final void validateInputByteBuffer(
- ByteBuffer[] buffers, int index) {
+ @Nullable ByteBuffer[] buffers, int index) {
if (buffers != null && index >= 0 && index < buffers.length) {
ByteBuffer buffer = buffers[index];
if (buffer != null) {
@@ -1306,7 +1374,7 @@ final public class MediaCodec {
}
private final void revalidateByteBuffer(
- ByteBuffer[] buffers, int index) {
+ @Nullable ByteBuffer[] buffers, int index) {
synchronized(mBufferLock) {
if (buffers != null && index >= 0 && index < buffers.length) {
ByteBuffer buffer = buffers[index];
@@ -1318,7 +1386,7 @@ final public class MediaCodec {
}
private final void validateOutputByteBuffer(
- ByteBuffer[] buffers, int index, BufferInfo info) {
+ @Nullable ByteBuffer[] buffers, int index, @NonNull BufferInfo info) {
if (buffers != null && index >= 0 && index < buffers.length) {
ByteBuffer buffer = buffers[index];
if (buffer != null) {
@@ -1328,7 +1396,7 @@ final public class MediaCodec {
}
}
- private final void invalidateByteBuffers(ByteBuffer[] buffers) {
+ private final void invalidateByteBuffers(@Nullable ByteBuffer[] buffers) {
if (buffers != null) {
for (ByteBuffer buffer: buffers) {
if (buffer != null) {
@@ -1338,14 +1406,14 @@ final public class MediaCodec {
}
}
- private final void freeByteBuffer(ByteBuffer buffer) {
+ private final void freeByteBuffer(@Nullable ByteBuffer buffer) {
if (buffer != null /* && buffer.isDirect() */) {
// all of our ByteBuffers are direct
java.nio.NioUtils.freeDirectBuffer(buffer);
}
}
- private final void freeByteBuffers(ByteBuffer[] buffers) {
+ private final void freeByteBuffers(@Nullable ByteBuffer[] buffers) {
if (buffers != null) {
for (ByteBuffer buffer: buffers) {
freeByteBuffer(buffer);
@@ -1388,13 +1456,14 @@ final public class MediaCodec {
* @deprecated Use the new {@link #getInputBuffer} method instead
* each time an input buffer is dequeued.
*
- * <b>Note:</b>As of API 21, dequeued input buffers are
+ * <b>Note:</b> As of API 21, dequeued input buffers are
* automatically {@link java.nio.Buffer#clear cleared}.
*
* @throws IllegalStateException if not in the Executing state,
* or codec is configured in asynchronous mode.
* @throws MediaCodec.CodecException upon codec error.
*/
+ @NonNull
public ByteBuffer[] getInputBuffers() {
if (mCachedInputBuffers == null) {
throw new IllegalStateException();
@@ -1415,7 +1484,7 @@ final public class MediaCodec {
* each time an output buffer is dequeued. This method is not
* supported if codec is configured in asynchronous mode.
*
- * <b>Note:</b>As of API 21, the position and limit of output
+ * <b>Note:</b> As of API 21, the position and limit of output
* buffers that are dequeued will be set to the valid data
* range.
*
@@ -1423,6 +1492,7 @@ final public class MediaCodec {
* or codec is configured in asynchronous mode.
* @throws MediaCodec.CodecException upon codec error.
*/
+ @NonNull
public ByteBuffer[] getOutputBuffers() {
if (mCachedOutputBuffers == null) {
throw new IllegalStateException();
@@ -1449,6 +1519,7 @@ final public class MediaCodec {
* @throws IllegalStateException if not in the Executing state.
* @throws MediaCodec.CodecException upon codec error.
*/
+ @Nullable
public ByteBuffer getInputBuffer(int index) {
ByteBuffer newBuffer = getBuffer(true /* input */, index);
synchronized(mBufferLock) {
@@ -1477,6 +1548,7 @@ final public class MediaCodec {
* @throws IllegalStateException if not in the Executing state.
* @throws MediaCodec.CodecException upon codec error.
*/
+ @Nullable
public Image getInputImage(int index) {
Image newImage = getImage(true /* input */, index);
synchronized(mBufferLock) {
@@ -1505,6 +1577,7 @@ final public class MediaCodec {
* @throws IllegalStateException if not in the Executing state.
* @throws MediaCodec.CodecException upon codec error.
*/
+ @Nullable
public ByteBuffer getOutputBuffer(int index) {
ByteBuffer newBuffer = getBuffer(false /* input */, index);
synchronized(mBufferLock) {
@@ -1532,6 +1605,7 @@ final public class MediaCodec {
* @throws IllegalStateException if not in the Executing state.
* @throws MediaCodec.CodecException upon codec error.
*/
+ @Nullable
public Image getOutputImage(int index) {
Image newImage = getImage(false /* input */, index);
synchronized(mBufferLock) {
@@ -1552,19 +1626,28 @@ final public class MediaCodec {
*/
public static final int VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING = 2;
+ /** @hide */
+ @IntDef({
+ VIDEO_SCALING_MODE_SCALE_TO_FIT,
+ VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface VideoScalingMode {}
+
/**
* If a surface has been specified in a previous call to {@link #configure}
* specifies the scaling mode to use. The default is "scale to fit".
* @throws IllegalArgumentException if mode is not recognized.
* @throws IllegalStateException if in the Uninitialized state.
*/
- public native final void setVideoScalingMode(int mode);
+ public native final void setVideoScalingMode(@VideoScalingMode int mode);
/**
* Get the component name. If the codec was created by createDecoderByType
* or createEncoderByType, what component is chosen is not known beforehand.
* @throws IllegalStateException if in the Uninitialized state.
*/
+ @NonNull
public native final String getName();
/**
@@ -1592,9 +1675,12 @@ final public class MediaCodec {
/**
* Communicate additional parameter changes to the component instance.
+ * <b>Note:</b> Some of these parameter changes may silently fail to apply.
+ *
+ * @param params The bundle of parameters to set.
* @throws IllegalStateException if in the Uninitialized state.
*/
- public final void setParameters(Bundle params) {
+ public final void setParameters(@Nullable Bundle params) {
if (params == null) {
return;
}
@@ -1626,9 +1712,11 @@ final public class MediaCodec {
* {@code flush}, you must call {@link #start} to "resume" receiving input buffers,
* even if an input surface was created.
*
- * @param cb The callback that will run.
+ * @param cb The callback that will run. Use {@code null} to clear a previously
+ * set callback (before {@link #configure configure} is called and run
+ * in synchronous mode).
*/
- public void setCallback(/* MediaCodec. */ Callback cb) {
+ public void setCallback(@Nullable /* MediaCodec. */ Callback cb) {
if (mEventHandler != null) {
// set java callback on handler
Message msg = mEventHandler.obtainMessage(EVENT_SET_CALLBACK, 0, 0, cb);
@@ -1652,7 +1740,7 @@ final public class MediaCodec {
* @param codec The MediaCodec object.
* @param index The index of the available input buffer.
*/
- public abstract void onInputBufferAvailable(MediaCodec codec, int index);
+ public abstract void onInputBufferAvailable(@NonNull MediaCodec codec, int index);
/**
* Called when an output buffer becomes available.
@@ -1661,7 +1749,8 @@ final public class MediaCodec {
* @param index The index of the available output buffer.
* @param info Info regarding the available output buffer {@link MediaCodec.BufferInfo}.
*/
- public abstract void onOutputBufferAvailable(MediaCodec codec, int index, BufferInfo info);
+ public abstract void onOutputBufferAvailable(
+ @NonNull MediaCodec codec, int index, @NonNull BufferInfo info);
/**
* Called when the MediaCodec encountered an error
@@ -1669,7 +1758,7 @@ final public class MediaCodec {
* @param codec The MediaCodec object.
* @param e The {@link MediaCodec.CodecException} object describing the error.
*/
- public abstract void onError(MediaCodec codec, CodecException e);
+ public abstract void onError(@NonNull MediaCodec codec, @NonNull CodecException e);
/**
* Called when the output format has changed
@@ -1677,18 +1766,19 @@ final public class MediaCodec {
* @param codec The MediaCodec object.
* @param format The new output format.
*/
- public abstract void onOutputFormatChanged(MediaCodec codec, MediaFormat format);
+ public abstract void onOutputFormatChanged(
+ @NonNull MediaCodec codec, @NonNull MediaFormat format);
}
private void postEventFromNative(
- int what, int arg1, int arg2, Object obj) {
+ int what, int arg1, int arg2, @Nullable Object obj) {
if (mEventHandler != null) {
Message msg = mEventHandler.obtainMessage(what, arg1, arg2, obj);
mEventHandler.sendMessage(msg);
}
}
- private native final void setParameters(String[] keys, Object[] values);
+ private native final void setParameters(@NonNull String[] keys, @NonNull Object[] values);
/**
* Get the codec info. If the codec was created by createDecoderByType
@@ -1696,20 +1786,24 @@ final public class MediaCodec {
* and thus the caller does not have the MediaCodecInfo.
* @throws IllegalStateException if in the Uninitialized state.
*/
+ @NonNull
public MediaCodecInfo getCodecInfo() {
return MediaCodecList.getInfoFor(getName());
}
+ @NonNull
private native final ByteBuffer[] getBuffers(boolean input);
+ @Nullable
private native final ByteBuffer getBuffer(boolean input, int index);
+ @Nullable
private native final Image getImage(boolean input, int index);
private static native final void native_init();
private native final void native_setup(
- String name, boolean nameIsType, boolean encoder);
+ @NonNull String name, boolean nameIsType, boolean encoder);
private native final void native_finalize();
@@ -1756,6 +1850,7 @@ final public class MediaCodec {
return mTimestamp;
}
+ @NonNull
public Plane[] getPlanes() {
checkValid();
return Arrays.copyOf(mPlanes, mPlanes.length);
@@ -1774,7 +1869,7 @@ final public class MediaCodec {
* The crop rectangle specifies the region of valid pixels in the image,
* using coordinates in the largest-resolution plane.
*/
- public void setCropRect(Rect cropRect) {
+ public void setCropRect(@Nullable Rect cropRect) {
if (mIsReadOnly) {
throw new ReadOnlyBufferException();
}
@@ -1787,7 +1882,7 @@ final public class MediaCodec {
}
}
- private int readInt(ByteBuffer buffer, boolean asLong) {
+ private int readInt(@NonNull ByteBuffer buffer, boolean asLong) {
if (asLong) {
return (int)buffer.getLong();
} else {
@@ -1796,8 +1891,8 @@ final public class MediaCodec {
}
public MediaImage(
- ByteBuffer buffer, ByteBuffer info, boolean readOnly,
- long timestamp, int xOffset, int yOffset, Rect cropRect) {
+ @NonNull ByteBuffer buffer, @NonNull ByteBuffer info, boolean readOnly,
+ long timestamp, int xOffset, int yOffset, @Nullable Rect cropRect) {
mFormat = ImageFormat.YUV_420_888;
mTimestamp = timestamp;
mIsValid = true;
@@ -1863,7 +1958,7 @@ final public class MediaCodec {
}
private class MediaPlane extends Plane {
- public MediaPlane(ByteBuffer buffer, int rowInc, int colInc) {
+ public MediaPlane(@NonNull ByteBuffer buffer, int rowInc, int colInc) {
mData = buffer;
mRowInc = rowInc;
mColInc = colInc;
@@ -1882,6 +1977,7 @@ final public class MediaCodec {
}
@Override
+ @NonNull
public ByteBuffer getBuffer() {
checkValid();
return mData;
diff --git a/media/java/android/media/MediaCrypto.java b/media/java/android/media/MediaCrypto.java
index da81b37..474d8b9 100644
--- a/media/java/android/media/MediaCrypto.java
+++ b/media/java/android/media/MediaCrypto.java
@@ -16,6 +16,7 @@
package android.media;
+import android.annotation.NonNull;
import android.media.MediaCryptoException;
import java.util.UUID;
@@ -34,11 +35,12 @@ public final class MediaCrypto {
* this device.
* @param uuid The UUID of the crypto scheme.
*/
- public static final boolean isCryptoSchemeSupported(UUID uuid) {
+ public static final boolean isCryptoSchemeSupported(@NonNull UUID uuid) {
return isCryptoSchemeSupportedNative(getByteArrayFromUUID(uuid));
}
- private static final byte[] getByteArrayFromUUID(UUID uuid) {
+ @NonNull
+ private static final byte[] getByteArrayFromUUID(@NonNull UUID uuid) {
long msb = uuid.getMostSignificantBits();
long lsb = uuid.getLeastSignificantBits();
@@ -51,7 +53,7 @@ public final class MediaCrypto {
return uuidBytes;
}
- private static final native boolean isCryptoSchemeSupportedNative(byte[] uuid);
+ private static final native boolean isCryptoSchemeSupportedNative(@NonNull byte[] uuid);
/**
* Instantiate a MediaCrypto object using opaque, crypto scheme specific
@@ -59,7 +61,7 @@ public final class MediaCrypto {
* @param uuid The UUID of the crypto scheme.
* @param initData Opaque initialization data specific to the crypto scheme.
*/
- public MediaCrypto(UUID uuid, byte[] initData) throws MediaCryptoException {
+ public MediaCrypto(@NonNull UUID uuid, @NonNull byte[] initData) throws MediaCryptoException {
native_setup(getByteArrayFromUUID(uuid), initData);
}
@@ -68,7 +70,7 @@ public final class MediaCrypto {
* to decode data of the given mime type.
* @param mime The mime type of the media data
*/
- public final native boolean requiresSecureDecoderComponent(String mime);
+ public final native boolean requiresSecureDecoderComponent(@NonNull String mime);
/**
* Associate a MediaDrm session with this MediaCrypto instance. The
@@ -81,7 +83,7 @@ public final class MediaCrypto {
* MediaCrypto instance
* @throws MediaCryptoException on failure to set the sessionId
*/
- public final native void setMediaDrmSession(byte[] sessionId)
+ public final native void setMediaDrmSession(@NonNull byte[] sessionId)
throws MediaCryptoException;
@Override
@@ -92,7 +94,7 @@ public final class MediaCrypto {
public native final void release();
private static native final void native_init();
- private native final void native_setup(byte[] uuid, byte[] initData)
+ private native final void native_setup(@NonNull byte[] uuid, @NonNull byte[] initData)
throws MediaCryptoException;
private native final void native_finalize();
diff --git a/media/java/android/media/MediaCryptoException.java b/media/java/android/media/MediaCryptoException.java
index 703e96f..32ddf47 100644
--- a/media/java/android/media/MediaCryptoException.java
+++ b/media/java/android/media/MediaCryptoException.java
@@ -16,12 +16,14 @@
package android.media;
+import android.annotation.Nullable;
+
/**
* Exception thrown if MediaCrypto object could not be instantiated or
* if unable to perform an operation on the MediaCrypto object.
*/
public final class MediaCryptoException extends Exception {
- public MediaCryptoException(String detailMessage) {
+ public MediaCryptoException(@Nullable String detailMessage) {
super(detailMessage);
}
}
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index fc5fc43..acff301 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -16,11 +16,17 @@
package android.media;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StringDef;
import android.annotation.SystemApi;
import android.os.Handler;
import android.os.Looper;
@@ -104,6 +110,8 @@ public final class MediaDrm {
private static final String PERMISSION = android.Manifest.permission.ACCESS_DRM_CERTIFICATES;
private EventHandler mEventHandler;
+ private EventHandler mOnKeysChangeEventHandler;
+ private EventHandler mOnExpirationUpdateEventHandler;
private OnEventListener mOnEventListener;
private OnKeysChangeListener mOnKeysChangeListener;
private OnExpirationUpdateListener mOnExpirationUpdateListener;
@@ -124,12 +132,20 @@ public final class MediaDrm {
*/
public static final int CERTIFICATE_TYPE_X509 = 1;
+ /** @hide */
+ @IntDef({
+ CERTIFICATE_TYPE_NONE,
+ CERTIFICATE_TYPE_X509,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CertificateType {}
+
/**
* Query if the given scheme identified by its UUID is supported on
* this device.
* @param uuid The UUID of the crypto scheme.
*/
- public static final boolean isCryptoSchemeSupported(UUID uuid) {
+ public static final boolean isCryptoSchemeSupported(@NonNull UUID uuid) {
return isCryptoSchemeSupportedNative(getByteArrayFromUUID(uuid), null);
}
@@ -141,11 +157,12 @@ public final class MediaDrm {
* @param mimeType The MIME type of the media container, e.g. "video/mp4"
* or "video/webm"
*/
- public static final boolean isCryptoSchemeSupported(UUID uuid, String mimeType) {
+ public static final boolean isCryptoSchemeSupported(
+ @NonNull UUID uuid, @NonNull String mimeType) {
return isCryptoSchemeSupportedNative(getByteArrayFromUUID(uuid), mimeType);
}
- private static final byte[] getByteArrayFromUUID(UUID uuid) {
+ private static final byte[] getByteArrayFromUUID(@NonNull UUID uuid) {
long msb = uuid.getMostSignificantBits();
long lsb = uuid.getLeastSignificantBits();
@@ -158,8 +175,8 @@ public final class MediaDrm {
return uuidBytes;
}
- private static final native boolean isCryptoSchemeSupportedNative(byte[] uuid,
- String mimeType);
+ private static final native boolean isCryptoSchemeSupportedNative(
+ @NonNull byte[] uuid, @Nullable String mimeType);
/**
* Instantiate a MediaDrm object
@@ -169,7 +186,7 @@ public final class MediaDrm {
* @throws UnsupportedSchemeException if the device does not support the
* specified scheme UUID
*/
- public MediaDrm(UUID uuid) throws UnsupportedSchemeException {
+ public MediaDrm(@NonNull UUID uuid) throws UnsupportedSchemeException {
Looper looper;
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
@@ -198,7 +215,7 @@ public final class MediaDrm {
/**
* @hide
*/
- public MediaDrmStateException(int errorCode, String detailMessage) {
+ public MediaDrmStateException(int errorCode, @Nullable String detailMessage) {
super(detailMessage);
mErrorCode = errorCode;
@@ -224,6 +241,7 @@ public final class MediaDrm {
* since this string will not be localized or generally comprehensible
* to end-users.
*/
+ @NonNull
public String getDiagnosticInfo() {
return mDiagnosticInfo;
}
@@ -233,13 +251,13 @@ public final class MediaDrm {
* Register a callback to be invoked when a session expiration update
* occurs. The app's OnExpirationUpdateListener will be notified
* when the expiration time of the keys in the session have changed.
- * @param listener the callback that will be run
+ * @param listener the callback that will be run, or {@code null} to unregister the
+ * previously registered callback.
* @param handler the handler on which the listener should be invoked, or
- * null if the listener should be invoked on the calling thread's looper.
+ * {@code null} if the listener should be invoked on the calling thread's looper.
*/
- public void setOnExpirationUpdateListener(OnExpirationUpdateListener listener,
- Handler handler)
- {
+ public void setOnExpirationUpdateListener(
+ @Nullable OnExpirationUpdateListener listener, @Nullable Handler handler) {
if (listener != null) {
Looper looper = handler != null ? handler.getLooper() : Looper.myLooper();
if (looper != null) {
@@ -266,20 +284,21 @@ public final class MediaDrm {
* @param expirationTime the new expiration time for the keys in the session.
* The time is in milliseconds, relative to the Unix epoch.
*/
- void onExpirationUpdate(MediaDrm md, byte[] sessionId, long expirationTime);
+ void onExpirationUpdate(
+ @NonNull MediaDrm md, @NonNull byte[] sessionId, long expirationTime);
}
/**
* Register a callback to be invoked when the state of keys in a session
* change, e.g. when a license update occurs or when a license expires.
*
- * @param listener the callback that will be run when key status changes
+ * @param listener the callback that will be run when key status changes, or
+ * {@code null} to unregister the previously registered callback.
* @param handler the handler on which the listener should be invoked, or
* null if the listener should be invoked on the calling thread's looper.
*/
- public void setOnKeysChangeListener(OnKeysChangeListener listener,
- Handler handler)
- {
+ public void setOnKeysChangeListener(
+ @Nullable OnKeysChangeListener listener, @Nullable Handler handler) {
if (listener != null) {
Looper looper = handler != null ? handler.getLooper() : Looper.myLooper();
if (looper != null) {
@@ -309,7 +328,9 @@ public final class MediaDrm {
* which may trigger an attempt to resume playback on the media stream
* if it is currently blocked waiting for a key.
*/
- void onKeysChange(MediaDrm md, byte[] sessionId, List<KeyStatus> keyInformation,
+ void onKeysChange(
+ @NonNull MediaDrm md, @NonNull byte[] sessionId,
+ @NonNull List<KeyStatus> keyInformation,
boolean hasNewUsableKey);
}
@@ -344,6 +365,16 @@ public final class MediaDrm {
*/
public static final int KEY_STATUS_INTERNAL_ERROR = 4;
+ /** @hide */
+ @IntDef({
+ KEY_STATUS_USABLE,
+ KEY_STATUS_EXPIRED,
+ KEY_STATUS_OUTPUT_NOT_ALLOWED,
+ KEY_STATUS_PENDING,
+ KEY_STATUS_INTERNAL_ERROR,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface KeyStatusCode {}
/**
* Defines the status of a key.
@@ -355,7 +386,7 @@ public final class MediaDrm {
private final byte[] mKeyId;
private final int mStatusCode;
- KeyStatus(byte[] keyId, int statusCode) {
+ KeyStatus(@NonNull byte[] keyId, @KeyStatusCode int statusCode) {
mKeyId = keyId;
mStatusCode = statusCode;
}
@@ -363,20 +394,23 @@ public final class MediaDrm {
/**
* Returns the status code for the key
*/
+ @KeyStatusCode
public int getStatusCode() { return mStatusCode; }
/**
* Returns the id for the key
*/
+ @NonNull
public byte[] getKeyId() { return mKeyId; }
}
/**
* Register a callback to be invoked when an event occurs
*
- * @param listener the callback that will be run
+ * @param listener the callback that will be run. Use {@code null} to
+ * stop receiving event callbacks.
*/
- public void setOnEventListener(OnEventListener listener)
+ public void setOnEventListener(@Nullable OnEventListener listener)
{
mOnEventListener = listener;
}
@@ -391,12 +425,16 @@ public final class MediaDrm {
* Called when an event occurs that requires the app to be notified
*
* @param md the MediaDrm object on which the event occurred
- * @param sessionId the DRM session ID on which the event occurred
+ * @param sessionId the DRM session ID on which the event occurred,
+ * or {@code null} if there is no session ID associated with the event.
* @param event indicates the event type
* @param extra an secondary error code
* @param data optional byte array of data that may be associated with the event
*/
- void onEvent(MediaDrm md, byte[] sessionId, int event, int extra, byte[] data);
+ void onEvent(
+ @NonNull MediaDrm md, @Nullable byte[] sessionId,
+ @DrmEvent int event, int extra,
+ @Nullable byte[] data);
}
/**
@@ -433,6 +471,17 @@ public final class MediaDrm {
*/
public static final int EVENT_SESSION_RECLAIMED = 5;
+ /** @hide */
+ @IntDef({
+ EVENT_PROVISION_REQUIRED,
+ EVENT_KEY_REQUIRED,
+ EVENT_KEY_EXPIRED,
+ EVENT_VENDOR_DEFINED,
+ EVENT_SESSION_RECLAIMED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DrmEvent {}
+
private static final int DRM_EVENT = 200;
private static final int EXPIRATION_UPDATE = 201;
private static final int KEYS_CHANGE = 202;
@@ -441,13 +490,13 @@ public final class MediaDrm {
{
private MediaDrm mMediaDrm;
- public EventHandler(MediaDrm md, Looper looper) {
+ public EventHandler(@NonNull MediaDrm md, @NonNull Looper looper) {
super(looper);
mMediaDrm = md;
}
@Override
- public void handleMessage(Message msg) {
+ public void handleMessage(@NonNull Message msg) {
if (mMediaDrm.mNativeContext == 0) {
Log.w(TAG, "MediaDrm went away with unhandled events");
return;
@@ -516,7 +565,8 @@ public final class MediaDrm {
/**
* Parse a list of KeyStatus objects from an event parcel
*/
- private List<KeyStatus> keyStatusListFromParcel(Parcel parcel) {
+ @NonNull
+ private List<KeyStatus> keyStatusListFromParcel(@NonNull Parcel parcel) {
int nelems = parcel.readInt();
List<KeyStatus> keyStatusList = new ArrayList(nelems);
while (nelems-- > 0) {
@@ -534,8 +584,8 @@ public final class MediaDrm {
* code is safe from the object disappearing from underneath it. (This is
* the cookie passed to native_setup().)
*/
- private static void postEventFromNative(Object mediadrm_ref,
- int what, int eventType, int extra, Object obj)
+ private static void postEventFromNative(@NonNull Object mediadrm_ref,
+ int what, int eventType, int extra, @Nullable Object obj)
{
MediaDrm md = (MediaDrm)((WeakReference<MediaDrm>)mediadrm_ref).get();
if (md == null) {
@@ -553,6 +603,7 @@ public final class MediaDrm {
* @throws NotProvisionedException if provisioning is needed
* @throws ResourceBusyException if required resources are in use
*/
+ @NonNull
public native byte[] openSession() throws NotProvisionedException,
ResourceBusyException;
@@ -560,7 +611,7 @@ public final class MediaDrm {
* Close a session on the MediaDrm object that was previously opened
* with {@link #openSession}.
*/
- public native void closeSession(byte[] sessionId);
+ public native void closeSession(@NonNull byte[] sessionId);
/**
* This key request type species that the keys will be for online use, they will
@@ -580,6 +631,15 @@ public final class MediaDrm {
*/
public static final int KEY_TYPE_RELEASE = 3;
+ /** @hide */
+ @IntDef({
+ KEY_TYPE_STREAMING,
+ KEY_TYPE_OFFLINE,
+ KEY_TYPE_RELEASE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface KeyType {}
+
/**
* Key request type is initial license request
*/
@@ -595,6 +655,15 @@ public final class MediaDrm {
*/
public static final int REQUEST_TYPE_RELEASE = 2;
+ /** @hide */
+ @IntDef({
+ REQUEST_TYPE_INITIAL,
+ REQUEST_TYPE_RENEWAL,
+ REQUEST_TYPE_RELEASE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface RequestType {}
+
/**
* Contains the opaque data an app uses to request keys from a license server
*/
@@ -608,18 +677,38 @@ public final class MediaDrm {
/**
* Get the opaque message data
*/
- public byte[] getData() { return mData; }
+ @NonNull
+ public byte[] getData() {
+ if (mData == null) {
+ // this should never happen as mData is initialized in
+ // JNI after construction of the KeyRequest object. The check
+ // is needed here to guarantee @NonNull annotation.
+ throw new RuntimeException("KeyRequest is not initialized");
+ }
+ return mData;
+ }
/**
* Get the default URL to use when sending the key request message to a
* server, if known. The app may prefer to use a different license
* server URL from other sources.
+ * This method returns an empty string if the default URL is not known.
*/
- public String getDefaultUrl() { return mDefaultUrl; }
+ @NonNull
+ public String getDefaultUrl() {
+ if (mDefaultUrl == null) {
+ // this should never happen as mDefaultUrl is initialized in
+ // JNI after construction of the KeyRequest object. The check
+ // is needed here to guarantee @NonNull annotation.
+ throw new RuntimeException("KeyRequest is not initialized");
+ }
+ return mDefaultUrl;
+ }
/**
* Get the type of the request
*/
+ @RequestType
public int getRequestType() { return mRequestType; }
};
@@ -652,12 +741,15 @@ public final class MediaDrm {
* keys, which are identified by a keySetId.
* @param optionalParameters are included in the key request message to
* allow a client application to provide additional message parameters to the server.
- *
+ * This may be {@code null} if no additional parameters are to be sent.
* @throws NotProvisionedException if reprovisioning is needed, due to a
* problem with the certifcate
*/
- public native KeyRequest getKeyRequest(byte[] scope, byte[] init,
- String mimeType, int keyType, HashMap<String, String> optionalParameters)
+ @NonNull
+ public native KeyRequest getKeyRequest(
+ @NonNull byte[] scope, @Nullable byte[] init,
+ @Nullable String mimeType, @KeyType int keyType,
+ @Nullable HashMap<String, String> optionalParameters)
throws NotProvisionedException;
@@ -680,7 +772,9 @@ public final class MediaDrm {
* @throws DeniedByServerException if the response indicates that the
* server rejected the request
*/
- public native byte[] provideKeyResponse(byte[] scope, byte[] response)
+ @Nullable
+ public native byte[] provideKeyResponse(
+ @NonNull byte[] scope, @NonNull byte[] response)
throws NotProvisionedException, DeniedByServerException;
@@ -691,14 +785,14 @@ public final class MediaDrm {
* @param sessionId the session ID for the DRM session
* @param keySetId identifies the saved key set to restore
*/
- public native void restoreKeys(byte[] sessionId, byte[] keySetId);
+ public native void restoreKeys(@NonNull byte[] sessionId, @NonNull byte[] keySetId);
/**
* Remove the current keys from a session.
*
* @param sessionId the session ID for the DRM session
*/
- public native void removeKeys(byte[] sessionId);
+ public native void removeKeys(@NonNull byte[] sessionId);
/**
* Request an informative description of the key status for the session. The status is
@@ -709,7 +803,8 @@ public final class MediaDrm {
*
* @param sessionId the session ID for the DRM session
*/
- public native HashMap<String, String> queryKeyStatus(byte[] sessionId);
+ @NonNull
+ public native HashMap<String, String> queryKeyStatus(@NonNull byte[] sessionId);
/**
* Contains the opaque data an app uses to request a certificate from a provisioning
@@ -721,14 +816,33 @@ public final class MediaDrm {
/**
* Get the opaque message data
*/
- public byte[] getData() { return mData; }
+ @NonNull
+ public byte[] getData() {
+ if (mData == null) {
+ // this should never happen as mData is initialized in
+ // JNI after construction of the KeyRequest object. The check
+ // is needed here to guarantee @NonNull annotation.
+ throw new RuntimeException("ProvisionRequest is not initialized");
+ }
+ return mData;
+ }
/**
* Get the default URL to use when sending the provision request
* message to a server, if known. The app may prefer to use a different
* provisioning server URL obtained from other sources.
+ * This method returns an empty string if the default URL is not known.
*/
- public String getDefaultUrl() { return mDefaultUrl; }
+ @NonNull
+ public String getDefaultUrl() {
+ if (mDefaultUrl == null) {
+ // this should never happen as mDefaultUrl is initialized in
+ // JNI after construction of the ProvisionRequest object. The check
+ // is needed here to guarantee @NonNull annotation.
+ throw new RuntimeException("ProvisionRequest is not initialized");
+ }
+ return mDefaultUrl;
+ }
private byte[] mData;
private String mDefaultUrl;
@@ -743,12 +857,14 @@ public final class MediaDrm {
* is returned in ProvisionRequest.data. The recommended URL to deliver the provision
* request to is returned in ProvisionRequest.defaultUrl.
*/
+ @NonNull
public ProvisionRequest getProvisionRequest() {
return getProvisionRequestNative(CERTIFICATE_TYPE_NONE, "");
}
+ @NonNull
private native ProvisionRequest getProvisionRequestNative(int certType,
- String certAuthority);
+ @NonNull String certAuthority);
/**
* After a provision response is received by the app, it is provided to the DRM
@@ -760,12 +876,14 @@ public final class MediaDrm {
* @throws DeniedByServerException if the response indicates that the
* server rejected the request
*/
- public void provideProvisionResponse(byte[] response)
+ public void provideProvisionResponse(@NonNull byte[] response)
throws DeniedByServerException {
provideProvisionResponseNative(response);
}
- private native Certificate provideProvisionResponseNative(byte[] response)
+ @NonNull
+ /* could there be a valid response with 0-sized certificate or key? */
+ private native Certificate provideProvisionResponseNative(@NonNull byte[] response)
throws DeniedByServerException;
/**
@@ -795,6 +913,7 @@ public final class MediaDrm {
* record on the client is only removed after positive confirmation that the server
* received the message using releaseSecureStops().
*/
+ @NonNull
public native List<byte[]> getSecureStops();
/**
@@ -802,7 +921,8 @@ public final class MediaDrm {
*
* @param ssid - The secure stop ID provided by the license server.
*/
- public native byte[] getSecureStop(byte[] ssid);
+ @NonNull
+ public native byte[] getSecureStop(@NonNull byte[] ssid);
/**
* Process the SecureStop server response message ssRelease. After authenticating
@@ -810,7 +930,7 @@ public final class MediaDrm {
*
* @param ssRelease the server response indicating which secure stops to release
*/
- public native void releaseSecureStops(byte[] ssRelease);
+ public native void releaseSecureStops(@NonNull byte[] ssRelease);
/**
* Remove all secure stops without requiring interaction with the server.
@@ -839,6 +959,16 @@ public final class MediaDrm {
*/
public static final String PROPERTY_ALGORITHMS = "algorithms";
+ /** @hide */
+ @StringDef({
+ PROPERTY_VENDOR,
+ PROPERTY_VERSION,
+ PROPERTY_DESCRIPTION,
+ PROPERTY_ALGORITHMS,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface StringProperty {}
+
/**
* Read a DRM engine plugin String property value, given the property name string.
* <p>
@@ -846,51 +976,68 @@ public final class MediaDrm {
* {@link #PROPERTY_VENDOR}, {@link #PROPERTY_VERSION},
* {@link #PROPERTY_DESCRIPTION}, {@link #PROPERTY_ALGORITHMS}
*/
- public native String getPropertyString(String propertyName);
-
+ /* FIXME this throws IllegalStateException for invalid property names */
+ @NonNull
+ public native String getPropertyString(@NonNull @StringProperty String propertyName);
/**
* Byte array property name: the device unique identifier is established during
* device provisioning and provides a means of uniquely identifying each device.
*/
+ /* FIXME this throws IllegalStateException for invalid property names */
public static final String PROPERTY_DEVICE_UNIQUE_ID = "deviceUniqueId";
+ /** @hide */
+ @StringDef({
+ PROPERTY_DEVICE_UNIQUE_ID,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ArrayProperty {}
+
/**
* Read a DRM engine plugin byte array property value, given the property name string.
* <p>
* Standard fields names are {@link #PROPERTY_DEVICE_UNIQUE_ID}
*/
- public native byte[] getPropertyByteArray(String propertyName);
-
+ @NonNull
+ public native byte[] getPropertyByteArray(@ArrayProperty String propertyName);
/**
* Set a DRM engine plugin String property value.
*/
- public native void setPropertyString(String propertyName, String value);
+ public native void setPropertyString(
+ @StringProperty String propertyName, @NonNull String value);
/**
* Set a DRM engine plugin byte array property value.
*/
- public native void setPropertyByteArray(String propertyName, byte[] value);
+ public native void setPropertyByteArray(
+ @ArrayProperty String propertyName, @NonNull byte[] value);
+ private static final native void setCipherAlgorithmNative(
+ @NonNull MediaDrm drm, @NonNull byte[] sessionId, @NonNull String algorithm);
- private static final native void setCipherAlgorithmNative(MediaDrm drm, byte[] sessionId,
- String algorithm);
+ private static final native void setMacAlgorithmNative(
+ @NonNull MediaDrm drm, @NonNull byte[] sessionId, @NonNull String algorithm);
- private static final native void setMacAlgorithmNative(MediaDrm drm, byte[] sessionId,
- String algorithm);
+ @NonNull
+ private static final native byte[] encryptNative(
+ @NonNull MediaDrm drm, @NonNull byte[] sessionId,
+ @NonNull byte[] keyId, @NonNull byte[] input, @NonNull byte[] iv);
- private static final native byte[] encryptNative(MediaDrm drm, byte[] sessionId,
- byte[] keyId, byte[] input, byte[] iv);
+ @NonNull
+ private static final native byte[] decryptNative(
+ @NonNull MediaDrm drm, @NonNull byte[] sessionId,
+ @NonNull byte[] keyId, @NonNull byte[] input, @NonNull byte[] iv);
- private static final native byte[] decryptNative(MediaDrm drm, byte[] sessionId,
- byte[] keyId, byte[] input, byte[] iv);
+ @NonNull
+ private static final native byte[] signNative(
+ @NonNull MediaDrm drm, @NonNull byte[] sessionId,
+ @NonNull byte[] keyId, @NonNull byte[] message);
- private static final native byte[] signNative(MediaDrm drm, byte[] sessionId,
- byte[] keyId, byte[] message);
-
- private static final native boolean verifyNative(MediaDrm drm, byte[] sessionId,
- byte[] keyId, byte[] message, byte[] signature);
+ private static final native boolean verifyNative(
+ @NonNull MediaDrm drm, @NonNull byte[] sessionId,
+ @NonNull byte[] keyId, @NonNull byte[] message, @NonNull byte[] signature);
/**
* In addition to supporting decryption of DASH Common Encrypted Media, the
@@ -919,8 +1066,8 @@ public final class MediaDrm {
private MediaDrm mDrm;
private byte[] mSessionId;
- CryptoSession(MediaDrm drm, byte[] sessionId,
- String cipherAlgorithm, String macAlgorithm)
+ CryptoSession(@NonNull MediaDrm drm, @NonNull byte[] sessionId,
+ @NonNull String cipherAlgorithm, @NonNull String macAlgorithm)
{
mSessionId = sessionId;
mDrm = drm;
@@ -935,7 +1082,9 @@ public final class MediaDrm {
* @param input the data to encrypt
* @param iv the initialization vector to use for the cipher
*/
- public byte[] encrypt(byte[] keyid, byte[] input, byte[] iv) {
+ @NonNull
+ public byte[] encrypt(
+ @NonNull byte[] keyid, @NonNull byte[] input, @NonNull byte[] iv) {
return encryptNative(mDrm, mSessionId, keyid, input, iv);
}
@@ -946,7 +1095,9 @@ public final class MediaDrm {
* @param input the data to encrypt
* @param iv the initialization vector to use for the cipher
*/
- public byte[] decrypt(byte[] keyid, byte[] input, byte[] iv) {
+ @NonNull
+ public byte[] decrypt(
+ @NonNull byte[] keyid, @NonNull byte[] input, @NonNull byte[] iv) {
return decryptNative(mDrm, mSessionId, keyid, input, iv);
}
@@ -956,7 +1107,8 @@ public final class MediaDrm {
* @param keyid specifies which key to use
* @param message the data for which a signature is to be computed
*/
- public byte[] sign(byte[] keyid, byte[] message) {
+ @NonNull
+ public byte[] sign(@NonNull byte[] keyid, @NonNull byte[] message) {
return signNative(mDrm, mSessionId, keyid, message);
}
@@ -969,7 +1121,8 @@ public final class MediaDrm {
* @param signature the reference signature which will be compared with the
* computed signature
*/
- public boolean verify(byte[] keyid, byte[] message, byte[] signature) {
+ public boolean verify(
+ @NonNull byte[] keyid, @NonNull byte[] message, @NonNull byte[] signature) {
return verifyNative(mDrm, mSessionId, keyid, message, signature);
}
};
@@ -994,8 +1147,9 @@ public final class MediaDrm {
* using the method {@link #getPropertyString} with the property name
* "algorithms".
*/
- public CryptoSession getCryptoSession(byte[] sessionId,
- String cipherAlgorithm, String macAlgorithm)
+ public CryptoSession getCryptoSession(
+ @NonNull byte[] sessionId,
+ @NonNull String cipherAlgorithm, @NonNull String macAlgorithm)
{
return new CryptoSession(this, sessionId, cipherAlgorithm, macAlgorithm);
}
@@ -1010,7 +1164,7 @@ public final class MediaDrm {
private byte[] mData;
private String mDefaultUrl;
- CertificateRequest(byte[] data, String defaultUrl) {
+ CertificateRequest(@NonNull byte[] data, @NonNull String defaultUrl) {
mData = data;
mDefaultUrl = defaultUrl;
}
@@ -1018,6 +1172,7 @@ public final class MediaDrm {
/**
* Get the opaque message data
*/
+ @NonNull
public byte[] getData() { return mData; }
/**
@@ -1025,6 +1180,7 @@ public final class MediaDrm {
* message to a server, if known. The app may prefer to use a different
* certificate server URL obtained from other sources.
*/
+ @NonNull
public String getDefaultUrl() { return mDefaultUrl; }
}
@@ -1040,8 +1196,9 @@ public final class MediaDrm {
*
* @hide - not part of the public API at this time
*/
- public CertificateRequest getCertificateRequest(int certType,
- String certAuthority)
+ @NonNull
+ public CertificateRequest getCertificateRequest(
+ @CertificateType int certType, @NonNull String certAuthority)
{
ProvisionRequest provisionRequest = getProvisionRequestNative(certType, certAuthority);
return new CertificateRequest(provisionRequest.getData(),
@@ -1060,12 +1217,30 @@ public final class MediaDrm {
/**
* Get the wrapped private key data
*/
- public byte[] getWrappedPrivateKey() { return mWrappedKey; }
+ @NonNull
+ public byte[] getWrappedPrivateKey() {
+ if (mWrappedKey == null) {
+ // this should never happen as mWrappedKey is initialized in
+ // JNI after construction of the KeyRequest object. The check
+ // is needed here to guarantee @NonNull annotation.
+ throw new RuntimeException("Cerfificate is not initialized");
+ }
+ return mWrappedKey;
+ }
/**
* Get the PEM-encoded certificate chain
*/
- public byte[] getContent() { return mCertificateData; }
+ @NonNull
+ public byte[] getContent() {
+ if (mCertificateData == null) {
+ // this should never happen as mCertificateData is initialized in
+ // JNI after construction of the KeyRequest object. The check
+ // is needed here to guarantee @NonNull annotation.
+ throw new RuntimeException("Cerfificate is not initialized");
+ }
+ return mCertificateData;
+ }
private byte[] mWrappedKey;
private byte[] mCertificateData;
@@ -1089,13 +1264,16 @@ public final class MediaDrm {
*
* @hide - not part of the public API at this time
*/
- public Certificate provideCertificateResponse(byte[] response)
+ @NonNull
+ public Certificate provideCertificateResponse(@NonNull byte[] response)
throws DeniedByServerException {
return provideProvisionResponseNative(response);
}
- private static final native byte[] signRSANative(MediaDrm drm, byte[] sessionId,
- String algorithm, byte[] wrappedKey, byte[] message);
+ @NonNull
+ private static final native byte[] signRSANative(
+ @NonNull MediaDrm drm, @NonNull byte[] sessionId,
+ @NonNull String algorithm, @NonNull byte[] wrappedKey, @NonNull byte[] message);
/**
* Sign data using an RSA key
@@ -1108,8 +1286,10 @@ public final class MediaDrm {
*
* @hide - not part of the public API at this time
*/
- public byte[] signRSA(byte[] sessionId, String algorithm,
- byte[] wrappedKey, byte[] message) {
+ @NonNull
+ public byte[] signRSA(
+ @NonNull byte[] sessionId, @NonNull String algorithm,
+ @NonNull byte[] wrappedKey, @NonNull byte[] message) {
return signRSANative(this, sessionId, algorithm, wrappedKey, message);
}
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index b4acbc0..0bf995f 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -16,6 +16,9 @@
package android.media;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
@@ -27,6 +30,8 @@ import android.os.IBinder;
import java.io.FileDescriptor;
import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.HashMap;
@@ -69,21 +74,26 @@ final public class MediaExtractor {
* Sets the data source (MediaDataSource) to use.
*
* @param dataSource the MediaDataSource for the media you want to extract from
+ *
+ * @throws IllegalArgumentException if dataSource is invalid.
*/
- public native final void setDataSource(MediaDataSource dataSource) throws IllegalArgumentException, IOException;
+ public native final void setDataSource(@NonNull MediaDataSource dataSource)
+ throws IOException;
/**
* Sets the data source as a content Uri.
*
* @param context the Context to use when resolving the Uri
* @param uri the Content URI of the data you want to extract from.
- * @param headers the headers to be sent together with the request for the data
+ * @param headers the headers to be sent together with the request for the data.
+ * This can be {@code null} if no specific headers are to be sent with the
+ * request.
*/
public final void setDataSource(
- Context context, Uri uri, Map<String, String> headers)
+ @NonNull Context context, @NonNull Uri uri, @Nullable Map<String, String> headers)
throws IOException {
String scheme = uri.getScheme();
- if(scheme == null || scheme.equals("file")) {
+ if (scheme == null || scheme.equals("file")) {
setDataSource(uri.getPath());
return;
}
@@ -122,9 +132,11 @@ final public class MediaExtractor {
* Sets the data source (file-path or http URL) to use.
*
* @param path the path of the file, or the http URL
- * @param headers the headers associated with the http request for the stream you want to play
+ * @param headers the headers associated with the http request for the stream you want to play.
+ * This can be {@code null} if no specific headers are to be sent with the
+ * request.
*/
- public final void setDataSource(String path, Map<String, String> headers)
+ public final void setDataSource(@NonNull String path, @Nullable Map<String, String> headers)
throws IOException {
String[] keys = null;
String[] values = null;
@@ -149,10 +161,10 @@ final public class MediaExtractor {
}
private native final void nativeSetDataSource(
- IBinder httpServiceBinder,
- String path,
- String[] keys,
- String[] values) throws IOException;
+ @NonNull IBinder httpServiceBinder,
+ @NonNull String path,
+ @Nullable String[] keys,
+ @Nullable String[] values) throws IOException;
/**
* Sets the data source (file-path or http URL) to use.
@@ -166,7 +178,7 @@ final public class MediaExtractor {
* As an alternative, the application could first open the file for reading,
* and then use the file descriptor form {@link #setDataSource(FileDescriptor)}.
*/
- public final void setDataSource(String path) throws IOException {
+ public final void setDataSource(@NonNull String path) throws IOException {
nativeSetDataSource(
MediaHTTPService.createHttpServiceBinderIfNecessary(path),
path,
@@ -180,7 +192,7 @@ final public class MediaExtractor {
*
* @param fd the FileDescriptor for the file you want to extract from.
*/
- public final void setDataSource(FileDescriptor fd) throws IOException {
+ public final void setDataSource(@NonNull FileDescriptor fd) throws IOException {
setDataSource(fd, 0, 0x7ffffffffffffffL);
}
@@ -194,7 +206,7 @@ final public class MediaExtractor {
* @param length the length in bytes of the data to be extracted
*/
public native final void setDataSource(
- FileDescriptor fd, long offset, long length) throws IOException;
+ @NonNull FileDescriptor fd, long offset, long length) throws IOException;
@Override
protected void finalize() {
@@ -217,7 +229,9 @@ final public class MediaExtractor {
* Get the PSSH info if present.
* @return a map of uuid-to-bytes, with the uuid specifying
* the crypto scheme, and the bytes being the data specific to that scheme.
+ * This can be {@code null} if the source does not contain PSSH info.
*/
+ @Nullable
public Map<UUID, byte[]> getPsshInfo() {
Map<UUID, byte[]> psshMap = null;
Map<String, Object> formatMap = getFileFormatNative();
@@ -243,16 +257,19 @@ final public class MediaExtractor {
return psshMap;
}
+ @NonNull
private native Map<String, Object> getFileFormatNative();
/**
* Get the track format at the specified index.
* More detail on the representation can be found at {@link android.media.MediaCodec}
*/
+ @NonNull
public MediaFormat getTrackFormat(int index) {
return new MediaFormat(getTrackFormatNative(index));
}
+ @NonNull
private native Map<String, Object> getTrackFormatNative(int index);
/**
@@ -284,11 +301,20 @@ final public class MediaExtractor {
*/
public static final int SEEK_TO_CLOSEST_SYNC = 2;
+ /** @hide */
+ @IntDef({
+ SEEK_TO_PREVIOUS_SYNC,
+ SEEK_TO_NEXT_SYNC,
+ SEEK_TO_CLOSEST_SYNC,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SeekMode {}
+
/**
* All selected tracks seek near the requested time according to the
* specified mode.
*/
- public native void seekTo(long timeUs, int mode);
+ public native void seekTo(long timeUs, @SeekMode int mode);
/**
* Advance to the next sample. Returns false if no more sample data
@@ -305,7 +331,7 @@ final public class MediaExtractor {
* @param byteBuf the destination byte buffer
* @return the sample size (or -1 if no more samples are available).
*/
- public native int readSampleData(ByteBuffer byteBuf, int offset);
+ public native int readSampleData(@NonNull ByteBuffer byteBuf, int offset);
/**
* Returns the track index the current sample originates from (or -1
@@ -334,9 +360,20 @@ final public class MediaExtractor {
*/
public static final int SAMPLE_FLAG_ENCRYPTED = 2;
+ /** @hide */
+ @IntDef(
+ flag = true,
+ value = {
+ SAMPLE_FLAG_SYNC,
+ SAMPLE_FLAG_ENCRYPTED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SampleFlag {}
+
/**
* Returns the current sample's flags.
*/
+ @SampleFlag
public native int getSampleFlags();
/**
@@ -347,7 +384,7 @@ final public class MediaExtractor {
* to be filled in.
* @return true iff the sample flags contain {@link #SAMPLE_FLAG_ENCRYPTED}
*/
- public native boolean getSampleCryptoInfo(MediaCodec.CryptoInfo info);
+ public native boolean getSampleCryptoInfo(@NonNull MediaCodec.CryptoInfo info);
/**
* Returns an estimate of how much data is presently cached in memory
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index f518ab2..4b6b4fa 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -16,12 +16,18 @@
package android.media;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import dalvik.system.CloseGuard;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.RandomAccessFile;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.nio.ByteBuffer;
import java.util.Map;
@@ -80,19 +86,27 @@ final public class MediaMuxer {
public static final int MUXER_OUTPUT_WEBM = 1;
};
+ /** @hide */
+ @IntDef({
+ OutputFormat.MUXER_OUTPUT_MPEG_4,
+ OutputFormat.MUXER_OUTPUT_WEBM,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Format {}
+
// All the native functions are listed here.
- private static native long nativeSetup(FileDescriptor fd, int format);
+ private static native long nativeSetup(@NonNull FileDescriptor fd, int format);
private static native void nativeRelease(long nativeObject);
private static native void nativeStart(long nativeObject);
private static native void nativeStop(long nativeObject);
- private static native int nativeAddTrack(long nativeObject, String[] keys,
- Object[] values);
- private static native void nativeSetOrientationHint(long nativeObject,
- int degrees);
+ private static native int nativeAddTrack(
+ long nativeObject, @NonNull String[] keys, @NonNull Object[] values);
+ private static native void nativeSetOrientationHint(
+ long nativeObject, int degrees);
private static native void nativeSetLocation(long nativeObject, int latitude, int longitude);
- private static native void nativeWriteSampleData(long nativeObject,
- int trackIndex, ByteBuffer byteBuf,
- int offset, int size, long presentationTimeUs, int flags);
+ private static native void nativeWriteSampleData(
+ long nativeObject, int trackIndex, @NonNull ByteBuffer byteBuf,
+ int offset, int size, long presentationTimeUs, @MediaCodec.BufferFlag int flags);
// Muxer internal states.
private static final int MUXER_STATE_UNINITIALIZED = -1;
@@ -115,7 +129,7 @@ final public class MediaMuxer {
* @see android.media.MediaMuxer.OutputFormat
* @throws IOException if failed to open the file for write
*/
- public MediaMuxer(String path, int format) throws IOException {
+ public MediaMuxer(@NonNull String path, @Format int format) throws IOException {
if (path == null) {
throw new IllegalArgumentException("path must not be null");
}
@@ -246,11 +260,12 @@ final public class MediaMuxer {
/**
* Adds a track with the specified format.
- * @param format The media format for the track.
+ * @param format The media format for the track. This must not be an empty
+ * MediaFormat.
* @return The track index for this newly added track, and it should be used
* in the {@link #writeSampleData}.
*/
- public int addTrack(MediaFormat format) {
+ public int addTrack(@NonNull MediaFormat format) {
if (format == null) {
throw new IllegalArgumentException("format must not be null.");
}
@@ -302,8 +317,8 @@ final public class MediaMuxer {
* MediaMuxer uses the flags provided in {@link MediaCodec.BufferInfo},
* to signal sync frames.
*/
- public void writeSampleData(int trackIndex, ByteBuffer byteBuf,
- BufferInfo bufferInfo) {
+ public void writeSampleData(int trackIndex, @NonNull ByteBuffer byteBuf,
+ @NonNull BufferInfo bufferInfo) {
if (trackIndex < 0 || trackIndex > mLastTrackIndex) {
throw new IllegalArgumentException("trackIndex is invalid");
}
diff --git a/media/java/android/media/MediaSync.java b/media/java/android/media/MediaSync.java
index e6bc10d..74a2fb2 100644
--- a/media/java/android/media/MediaSync.java
+++ b/media/java/android/media/MediaSync.java
@@ -18,6 +18,7 @@ package android.media;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.media.AudioTrack;
import android.os.Handler;
import android.os.Looper;
@@ -120,9 +121,10 @@ final public class MediaSync {
*
* @param sync The MediaSync object.
* @param audioBuffer The returned audio buffer.
+ * @param bufferIndex The index associated with the audio buffer
*/
public abstract void onReturnAudioBuffer(
- MediaSync sync, ByteBuffer audioBuffer, int bufferIndex);
+ @NonNull MediaSync sync, @NonNull ByteBuffer audioBuffer, int bufferIndex);
}
private static final String TAG = "MediaSync";
@@ -138,7 +140,7 @@ final public class MediaSync {
public int mSizeInBytes;
long mPresentationTimeUs;
- public AudioBuffer(ByteBuffer byteBuffer, int bufferIndex,
+ public AudioBuffer(@NonNull ByteBuffer byteBuffer, int bufferIndex,
int sizeInBytes, long presentationTimeUs) {
mByteBuffer = byteBuffer;
mBufferIndex = bufferIndex;
@@ -200,13 +202,17 @@ final public class MediaSync {
/**
* Sets an asynchronous callback for actionable MediaSync events.
- * It shouldn't be called inside callback.
+ * <p>
+ * This method can be called multiple times to update a previously set callback. 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 cb The callback that will run.
- * @param handler The Handler that will run the callback. Using null means to use MediaSync's
+ * @param cb 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 setCallback(/* MediaSync. */ Callback cb, Handler handler) {
+ public void setCallback(@Nullable /* MediaSync. */ Callback cb, @Nullable Handler handler) {
synchronized(mCallbackLock) {
if (handler != null) {
mCallbackHandler = handler;
@@ -235,11 +241,11 @@ final public class MediaSync {
* @throws IllegalStateException if not in the Initialized state, or another surface
* has already been configured.
*/
- public void configureSurface(Surface surface) {
+ public void configureSurface(@Nullable Surface surface) {
native_configureSurface(surface);
}
- private native final void native_configureSurface(Surface surface);
+ private native final void native_configureSurface(@Nullable Surface surface);
/**
* Configures the audio track for MediaSync.
@@ -249,7 +255,7 @@ final public class MediaSync {
* @throws IllegalStateException if not in the Initialized state, or another audio track
* has already been configured.
*/
- public void configureAudioTrack(AudioTrack audioTrack) {
+ public void configureAudioTrack(@Nullable AudioTrack audioTrack) {
// AudioTrack has sanity check for configured sample rate.
int nativeSampleRateInHz = (audioTrack == null ? 0 : audioTrack.getSampleRate());
@@ -261,7 +267,7 @@ final public class MediaSync {
}
private native final void native_configureAudioTrack(
- AudioTrack audioTrack, int nativeSampleRateInHz);
+ @Nullable AudioTrack audioTrack, int nativeSampleRateInHz);
/**
* Requests a Surface to use as the input. This may only be called after
@@ -272,6 +278,7 @@ final public class MediaSync {
* @throws IllegalStateException if not configured, or another input surface has
* already been created.
*/
+ @NonNull
public native final Surface createInputSurface();
/**
@@ -412,7 +419,7 @@ final public class MediaSync {
return native_getTimestamp(timestamp);
}
- private native final boolean native_getTimestamp(MediaTimestamp timestamp);
+ private native final boolean native_getTimestamp(@NonNull MediaTimestamp timestamp);
/**
* Queues the audio data asynchronously for playback (AudioTrack must be in streaming mode).
@@ -427,7 +434,8 @@ final public class MediaSync {
* has not been done correctly.
*/
public void queueAudio(
- ByteBuffer audioData, int bufferIndex, int sizeInBytes, long presentationTimeUs) {
+ @NonNull ByteBuffer audioData, int bufferIndex, int sizeInBytes,
+ long presentationTimeUs) {
if (mAudioTrack == null || mAudioThread == null) {
throw new IllegalStateException(
"AudioTrack is NOT configured or audio thread is not created");
@@ -489,7 +497,7 @@ final public class MediaSync {
private native final void native_updateQueuedAudioData(
int sizeInBytes, long presentationTimeUs);
- private final void postReturnByteBuffer(final AudioBuffer audioBuffer) {
+ private final void postReturnByteBuffer(@NonNull final AudioBuffer audioBuffer) {
synchronized(mCallbackLock) {
if (mCallbackHandler != null) {
final MediaSync sync = this;