Fix AudioTrack and AudioRecord documentation

Improve documentation for error codes returned by
AudioTrack.write() and AudioRecord.read() methods.
Fix native to JAVA error code conversion in JNI.

Bug: 28906466

Change-Id: I4d48b1d428834b7a39a14e2d81b6c164696817a8
diff --git a/api/current.txt b/api/current.txt
index 1f7dd26..01fb6c2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -19778,6 +19778,7 @@
     method public void stop() throws java.lang.IllegalStateException;
     field public static final int ERROR = -1; // 0xffffffff
     field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
+    field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
     field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd
     field public static final int READ_BLOCKING = 0; // 0x0
     field public static final int READ_NON_BLOCKING = 1; // 0x1
@@ -19900,6 +19901,7 @@
     method public int write(java.nio.ByteBuffer, int, int, long);
     field public static final int ERROR = -1; // 0xffffffff
     field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
+    field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
     field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd
     field public static final int MODE_STATIC = 0; // 0x0
     field public static final int MODE_STREAM = 1; // 0x1
diff --git a/api/system-current.txt b/api/system-current.txt
index da430c0..d5a813e 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -21294,6 +21294,7 @@
     method public void stop() throws java.lang.IllegalStateException;
     field public static final int ERROR = -1; // 0xffffffff
     field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
+    field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
     field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd
     field public static final int READ_BLOCKING = 0; // 0x0
     field public static final int READ_NON_BLOCKING = 1; // 0x1
@@ -21418,6 +21419,7 @@
     method public int write(java.nio.ByteBuffer, int, int, long);
     field public static final int ERROR = -1; // 0xffffffff
     field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
+    field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
     field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd
     field public static final int MODE_STATIC = 0; // 0x0
     field public static final int MODE_STREAM = 1; // 0x1
diff --git a/api/test-current.txt b/api/test-current.txt
index a67d45e..682d9ce 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -19847,6 +19847,7 @@
     method public void stop() throws java.lang.IllegalStateException;
     field public static final int ERROR = -1; // 0xffffffff
     field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
+    field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
     field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd
     field public static final int READ_BLOCKING = 0; // 0x0
     field public static final int READ_NON_BLOCKING = 1; // 0x1
@@ -19969,6 +19970,7 @@
     method public int write(java.nio.ByteBuffer, int, int, long);
     field public static final int ERROR = -1; // 0xffffffff
     field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
+    field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
     field public static final int ERROR_INVALID_OPERATION = -3; // 0xfffffffd
     field public static final int MODE_STATIC = 0; // 0x0
     field public static final int MODE_STREAM = 1; // 0x1
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 1bc4285..1fc08ed 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -479,17 +479,13 @@
 
 static inline
 jint interpretReadSizeError(ssize_t readSize) {
-    ALOGE_IF(readSize != WOULD_BLOCK, "Error %zd during AudioRecord native read", readSize);
-    switch (readSize) {
-    case WOULD_BLOCK:
+    if (readSize == WOULD_BLOCK) {
         return (jint)0;
-    case BAD_VALUE:
-        return (jint)AUDIO_JAVA_BAD_VALUE;
-    default:
-        // may be possible for other errors such as
-        // NO_INIT to happen if restoreRecord_l fails.
-    case INVALID_OPERATION:
-        return (jint)AUDIO_JAVA_INVALID_OPERATION;
+    } else if (readSize == NO_INIT) {
+        return AUDIO_JAVA_DEAD_OBJECT;
+    } else {
+        ALOGE("Error %zd during AudioRecord native read", readSize);
+        return nativeToJavaStatus(readSize);
     }
 }
 
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 024c21d..982a1f8 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -606,6 +606,18 @@
     env->ReleaseFloatArrayElements(array, elems, mode);
 }
 
+static inline
+jint interpretWriteSizeError(ssize_t writeSize) {
+    if (writeSize == WOULD_BLOCK) {
+        return (jint)0;
+    } else if (writeSize == NO_INIT) {
+        return AUDIO_JAVA_DEAD_OBJECT;
+    } else {
+        ALOGE("Error %zd during AudioTrack native read", writeSize);
+        return nativeToJavaStatus(writeSize);
+    }
+}
+
 // ----------------------------------------------------------------------------
 template <typename T>
 static jint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, const T *data,
@@ -628,11 +640,10 @@
         memcpy(track->sharedBuffer()->pointer(), data + offsetInSamples, sizeInBytes);
         written = sizeInBytes;
     }
-    if (written > 0) {
+    if (written >= 0) {
         return written / sizeof(T);
     }
-    // for compatibility, error codes pass through unchanged
-    return written;
+    return interpretWriteSizeError(written);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 4504e69..8efd599 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -94,6 +94,11 @@
      * Denotes a failure due to the improper use of a method.
      */
     public  static final int ERROR_INVALID_OPERATION               = AudioSystem.INVALID_OPERATION;
+    /**
+     * An error code indicating that the object reporting it is no longer valid and needs to
+     * be recreated.
+     */
+    public  static final int ERROR_DEAD_OBJECT                     = AudioSystem.DEAD_OBJECT;
 
     // Error codes:
     // to keep in sync with frameworks/base/core/jni/android_media_AudioRecord.cpp
@@ -1046,10 +1051,16 @@
      * @param audioData the array to which the recorded audio data is written.
      * @param offsetInBytes index in audioData from which the data is written expressed in bytes.
      * @param sizeInBytes the number of requested bytes.
-     * @return the number of bytes that were read or {@link #ERROR_INVALID_OPERATION}
-     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
-     *    the parameters don't resolve to valid data and indexes.
-     *    The number of bytes will not exceed sizeInBytes.
+     * @return zero or the positive number of bytes that were read, or one of the following
+     *    error codes. The number of bytes will not exceed sizeInBytes.
+     * <ul>
+     * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
+     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+     * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
+     *    needs to be recreated. The dead object error code is not returned if some data was
+     *    successfully transferred. In this case, the error is returned at the next read()</li>
+     * <li>{@link #ERROR} in case of other error</li>
+     * </ul>
      */
     public int read(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes) {
         return read(audioData, offsetInBytes, sizeInBytes, READ_BLOCKING);
@@ -1070,11 +1081,17 @@
      *     is read.
      *     <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after
      *     reading as much audio data as possible without blocking.
-     * @return the number of bytes that were read or {@link #ERROR_INVALID_OPERATION}
-     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
-     *    the parameters don't resolve to valid data and indexes.
-     *    The number of bytes will be a multiple of the frame size in bytes
+     * @return zero or the positive number of bytes that were read, or one of the following
+     *    error codes. The number of bytes will be a multiple of the frame size in bytes
      *    not to exceed sizeInBytes.
+     * <ul>
+     * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
+     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+     * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
+     *    needs to be recreated. The dead object error code is not returned if some data was
+     *    successfully transferred. In this case, the error is returned at the next read()</li>
+     * <li>{@link #ERROR} in case of other error</li>
+     * </ul>
      */
     public int read(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes,
             @ReadMode int readMode) {
@@ -1106,10 +1123,17 @@
      *        Must not be negative, or cause the data access to go out of bounds of the array.
      * @param sizeInShorts the number of requested shorts.
      *        Must not be negative, or cause the data access to go out of bounds of the array.
-     * @return the number of shorts that were read or {@link #ERROR_INVALID_OPERATION}
-     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
-     *    the parameters don't resolve to valid data and indexes.
-     *    The number of shorts will be a multiple of the channel count not to exceed sizeInShorts.
+     * @return zero or the positive number of shorts that were read, or one of the following
+     *    error codes. The number of shorts will be a multiple of the channel count not to exceed
+     *    sizeInShorts.
+     * <ul>
+     * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
+     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+     * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
+     *    needs to be recreated. The dead object error code is not returned if some data was
+     *    successfully transferred. In this case, the error is returned at the next read()</li>
+     * <li>{@link #ERROR} in case of other error</li>
+     * </ul>
      */
     public int read(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts) {
         return read(audioData, offsetInShorts, sizeInShorts, READ_BLOCKING);
@@ -1129,10 +1153,17 @@
      *     is read.
      *     <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after
      *     reading as much audio data as possible without blocking.
-     * @return the number of shorts that were read or {@link #ERROR_INVALID_OPERATION}
-     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
-     *    the parameters don't resolve to valid data and indexes.
-     *    The number of shorts will be a multiple of the channel count not to exceed sizeInShorts.
+     * @return zero or the positive number of shorts that were read, or one of the following
+     *    error codes. The number of shorts will be a multiple of the channel count not to exceed
+     *    sizeInShorts.
+     * <ul>
+     * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
+     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+     * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
+     *    needs to be recreated. The dead object error code is not returned if some data was
+     *    successfully transferred. In this case, the error is returned at the next read()</li>
+     * <li>{@link #ERROR} in case of other error</li>
+     * </ul>
      */
     public int read(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts,
             @ReadMode int readMode) {
@@ -1169,10 +1200,17 @@
      *     is read.
      *     <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after
      *     reading as much audio data as possible without blocking.
-     * @return the number of floats that were read or {@link #ERROR_INVALID_OPERATION}
-     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
-     *    the parameters don't resolve to valid data and indexes.
-     *    The number of floats will be a multiple of the channel count not to exceed sizeInFloats.
+     * @return zero or the positive number of floats that were read, or one of the following
+     *    error codes. The number of floats will be a multiple of the channel count not to exceed
+     *    sizeInFloats.
+     * <ul>
+     * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
+     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+     * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
+     *    needs to be recreated. The dead object error code is not returned if some data was
+     *    successfully transferred. In this case, the error is returned at the next read()</li>
+     * <li>{@link #ERROR} in case of other error</li>
+     * </ul>
      */
     public int read(@NonNull float[] audioData, int offsetInFloats, int sizeInFloats,
             @ReadMode int readMode) {
@@ -1213,11 +1251,17 @@
      * @param sizeInBytes the number of requested bytes. It is recommended but not enforced
      *    that the number of bytes requested be a multiple of the frame size (sample size in
      *    bytes multiplied by the channel count).
-     * @return the number of bytes that were read or {@link #ERROR_INVALID_OPERATION}
-     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
-     *    the parameters don't resolve to valid data and indexes.
-     *    The number of bytes will not exceed sizeInBytes.
-     *    The number of bytes read will be truncated to be a multiple of the frame size.
+     * @return zero or the positive number of bytes that were read, or one of the following
+     *    error codes. The number of bytes will not exceed sizeInBytes and will be truncated to be
+     *    a multiple of the frame size.
+     * <ul>
+     * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
+     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+     * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
+     *    needs to be recreated. The dead object error code is not returned if some data was
+     *    successfully transferred. In this case, the error is returned at the next read()</li>
+     * <li>{@link #ERROR} in case of other error</li>
+     * </ul>
      */
     public int read(@NonNull ByteBuffer audioBuffer, int sizeInBytes) {
         return read(audioBuffer, sizeInBytes, READ_BLOCKING);
@@ -1240,11 +1284,17 @@
      *     is read.
      *     <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after
      *     reading as much audio data as possible without blocking.
-     * @return the number of bytes that were read or {@link #ERROR_INVALID_OPERATION}
-     *    if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
-     *    the parameters don't resolve to valid data and indexes.
-     *    The number of bytes will not exceed sizeInBytes.
-     *    The number of bytes read will be truncated to be a multiple of the frame size.
+     * @return zero or the positive number of bytes that were read, or one of the following
+     *    error codes. The number of bytes will not exceed sizeInBytes and will be truncated to be
+     *    a multiple of the frame size.
+     * <ul>
+     * <li>{@link #ERROR_INVALID_OPERATION} if the object isn't properly initialized</li>
+     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+     * <li>{@link #ERROR_DEAD_OBJECT} if the object is not valid anymore and
+     *    needs to be recreated. The dead object error code is not returned if some data was
+     *    successfully transferred. In this case, the error is returned at the next read()</li>
+     * <li>{@link #ERROR} in case of other error</li>
+     * </ul>
      */
     public int read(@NonNull ByteBuffer audioBuffer, int sizeInBytes, @ReadMode int readMode) {
         if (mState != STATE_INITIALIZED) {
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 12e88a2..9a81668 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -156,7 +156,6 @@
     /**
      * An error code indicating that the object reporting it is no longer valid and needs to
      * be recreated.
-     * @hide
      */
     public  static final int ERROR_DEAD_OBJECT                     = AudioSystem.DEAD_OBJECT;
     /**
@@ -1840,17 +1839,17 @@
      *    Must not be negative, or cause the data access to go out of bounds of the array.
      * @param sizeInBytes the number of bytes to write in audioData after the offset.
      *    Must not be negative, or cause the data access to go out of bounds of the array.
-     * @return zero or the positive number of bytes that were written, or
-     *    {@link #ERROR_INVALID_OPERATION}
-     *    if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
-     *    the parameters don't resolve to valid data and indexes, or
-     *    {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
-     *    needs to be recreated.
-     *    The dead object error code is not returned if some data was successfully transferred.
-     *    In this case, the error is returned at the next write().
-     *    The number of bytes will be a multiple of the frame size in bytes
+     * @return zero or the positive number of bytes that were written, or one of the following
+     *    error codes. The number of bytes will be a multiple of the frame size in bytes
      *    not to exceed sizeInBytes.
-     *
+     * <ul>
+     * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
+     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+     * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+     *    needs to be recreated. The dead object error code is not returned if some data was
+     *    successfully transferred. In this case, the error is returned at the next write()</li>
+     * <li>{@link #ERROR} in case of other error</li>
+     * </ul>
      * This is equivalent to {@link #write(byte[], int, int, int)} with <code>writeMode</code>
      * set to  {@link #WRITE_BLOCKING}.
      */
@@ -1888,16 +1887,17 @@
      *         to the audio sink.
      *     <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
      *     queuing as much audio data for playback as possible without blocking.
-     * @return zero or the positive number of bytes that were written, or
-     *    {@link #ERROR_INVALID_OPERATION}
-     *    if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
-     *    the parameters don't resolve to valid data and indexes, or
-     *    {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
-     *    needs to be recreated.
-     *    The dead object error code is not returned if some data was successfully transferred.
-     *    In this case, the error is returned at the next write().
-     *    The number of bytes will be a multiple of the frame size in bytes
+     * @return zero or the positive number of bytes that were written, or one of the following
+     *    error codes. The number of bytes will be a multiple of the frame size in bytes
      *    not to exceed sizeInBytes.
+     * <ul>
+     * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
+     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+     * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+     *    needs to be recreated. The dead object error code is not returned if some data was
+     *    successfully transferred. In this case, the error is returned at the next write()</li>
+     * <li>{@link #ERROR} in case of other error</li>
+     * </ul>
      */
     public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes,
             @WriteMode int writeMode) {
@@ -1950,16 +1950,17 @@
      *    Must not be negative, or cause the data access to go out of bounds of the array.
      * @param sizeInShorts the number of shorts to read in audioData after the offset.
      *    Must not be negative, or cause the data access to go out of bounds of the array.
-     * @return zero or the positive number of shorts that were written, or
-     *    {@link #ERROR_INVALID_OPERATION}
-     *    if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
-     *    the parameters don't resolve to valid data and indexes, or
-     *    {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
-     *    needs to be recreated.
-     *    The dead object error code is not returned if some data was successfully transferred.
-     *    In this case, the error is returned at the next write().
-     *    The number of shorts will be a multiple of the channel count not to exceed sizeInShorts.
-     *
+     * @return zero or the positive number of shorts that were written, or one of the following
+     *    error codes. The number of shorts will be a multiple of the channel count not to
+     *    exceed sizeInShorts.
+     * <ul>
+     * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
+     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+     * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+     *    needs to be recreated. The dead object error code is not returned if some data was
+     *    successfully transferred. In this case, the error is returned at the next write()</li>
+     * <li>{@link #ERROR} in case of other error</li>
+     * </ul>
      * This is equivalent to {@link #write(short[], int, int, int)} with <code>writeMode</code>
      * set to  {@link #WRITE_BLOCKING}.
      */
@@ -1995,15 +1996,17 @@
      *         to the audio sink.
      *     <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
      *     queuing as much audio data for playback as possible without blocking.
-     * @return zero or the positive number of shorts that were written, or
-     *    {@link #ERROR_INVALID_OPERATION}
-     *    if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
-     *    the parameters don't resolve to valid data and indexes, or
-     *    {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
-     *    needs to be recreated.
-     *    The dead object error code is not returned if some data was successfully transferred.
-     *    In this case, the error is returned at the next write().
-     *    The number of shorts will be a multiple of the channel count not to exceed sizeInShorts.
+     * @return zero or the positive number of shorts that were written, or one of the following
+     *    error codes. The number of shorts will be a multiple of the channel count not to
+     *    exceed sizeInShorts.
+     * <ul>
+     * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
+     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+     * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+     *    needs to be recreated. The dead object error code is not returned if some data was
+     *    successfully transferred. In this case, the error is returned at the next write()</li>
+     * <li>{@link #ERROR} in case of other error</li>
+     * </ul>
      */
     public int write(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts,
             @WriteMode int writeMode) {
@@ -2074,15 +2077,17 @@
      *         to the audio sink.
      *     <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
      *     queuing as much audio data for playback as possible without blocking.
-     * @return zero or the positive number of floats that were written, or
-     *    {@link #ERROR_INVALID_OPERATION}
-     *    if the track isn't properly initialized, or {@link #ERROR_BAD_VALUE} if
-     *    the parameters don't resolve to valid data and indexes, or
-     *    {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
-     *    needs to be recreated.
-     *    The dead object error code is not returned if some data was successfully transferred.
-     *    In this case, the error is returned at the next write().
-     *    The number of floats will be a multiple of the channel count not to exceed sizeInFloats.
+     * @return zero or the positive number of floats that were written, or one of the following
+     *    error codes. The number of floats will be a multiple of the channel count not to
+     *    exceed sizeInFloats.
+     * <ul>
+     * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
+     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+     * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+     *    needs to be recreated. The dead object error code is not returned if some data was
+     *    successfully transferred. In this case, the error is returned at the next write()</li>
+     * <li>{@link #ERROR} in case of other error</li>
+     * </ul>
      */
     public int write(@NonNull float[] audioData, int offsetInFloats, int sizeInFloats,
             @WriteMode int writeMode) {
@@ -2154,12 +2159,16 @@
      *         to the audio sink.
      *     <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
      *     queuing as much audio data for playback as possible without blocking.
-     * @return zero or the positive number of bytes that were written, or
-     *     {@link #ERROR_BAD_VALUE}, {@link #ERROR_INVALID_OPERATION}, or
-     *     {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
-     *     needs to be recreated.
-     *     The dead object error code is not returned if some data was successfully transferred.
-     *     In this case, the error is returned at the next write().
+     * @return zero or the positive number of bytes that were written, or one of the following
+     *    error codes.
+     * <ul>
+     * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
+     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+     * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+     *    needs to be recreated. The dead object error code is not returned if some data was
+     *    successfully transferred. In this case, the error is returned at the next write()</li>
+     * <li>{@link #ERROR} in case of other error</li>
+     * </ul>
      */
     public int write(@NonNull ByteBuffer audioData, int sizeInBytes,
             @WriteMode int writeMode) {
@@ -2223,12 +2232,16 @@
      *     <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
      *     queuing as much audio data for playback as possible without blocking.
      * @param timestamp The timestamp of the first decodable audio frame in the provided audioData.
-     * @return zero or a positive number of bytes that were written, or
-     *     {@link #ERROR_BAD_VALUE}, {@link #ERROR_INVALID_OPERATION}, or
-     *     {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
-     *     needs to be recreated.
-     *     The dead object error code is not returned if some data was successfully transferred.
-     *     In this case, the error is returned at the next write().
+     * @return zero or the positive number of bytes that were written, or one of the following
+     *    error codes.
+     * <ul>
+     * <li>{@link #ERROR_INVALID_OPERATION} if the track isn't properly initialized</li>
+     * <li>{@link #ERROR_BAD_VALUE} if the parameters don't resolve to valid data and indexes</li>
+     * <li>{@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+     *    needs to be recreated. The dead object error code is not returned if some data was
+     *    successfully transferred. In this case, the error is returned at the next write()</li>
+     * <li>{@link #ERROR} in case of other error</li>
+     * </ul>
      */
     public int write(@NonNull ByteBuffer audioData, int sizeInBytes,
             @WriteMode int writeMode, long timestamp) {