am aef51d09: am 4a8034ca: AudioTrack: error reporting for getTimestamp()

* commit 'aef51d09ef33eb3f03789c71edc25a7b103728d1':
  AudioTrack: error reporting for getTimestamp()
diff --git a/core/jni/android_media_AudioErrors.h b/core/jni/android_media_AudioErrors.h
index 4907830..c17a020 100644
--- a/core/jni/android_media_AudioErrors.h
+++ b/core/jni/android_media_AudioErrors.h
@@ -32,6 +32,7 @@
     AUDIO_JAVA_PERMISSION_DENIED  = -4,
     AUDIO_JAVA_NO_INIT            = -5,
     AUDIO_JAVA_DEAD_OBJECT        = -6,
+    AUDIO_JAVA_WOULD_BLOCK        = -7,
 };
 
 static inline jint nativeToJavaStatus(status_t status) {
@@ -46,6 +47,8 @@
         return AUDIO_JAVA_PERMISSION_DENIED;
     case NO_INIT:
         return AUDIO_JAVA_NO_INIT;
+    case WOULD_BLOCK:
+        return AUDIO_JAVA_WOULD_BLOCK;
     case DEAD_OBJECT:
         return AUDIO_JAVA_DEAD_OBJECT;
     default:
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index e99a37a..c59d1c7 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -279,6 +279,7 @@
     public static final int PERMISSION_DENIED  = -4;
     public static final int NO_INIT            = -5;
     public static final int DEAD_OBJECT        = -6;
+    public static final int WOULD_BLOCK        = -7;
 
     /*
      * AudioPolicyService methods
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 8880dad..bb4f7d9 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -158,6 +158,18 @@
      * 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.
+     * @hide
+     */
+    public  static final int ERROR_DEAD_OBJECT                     = AudioSystem.DEAD_OBJECT;
+    /**
+     * {@link #getTimestampWithStatus(AudioTimestamp)} is called in STOPPED or FLUSHED state,
+     * or immediately after start/ACTIVE.
+     * @hide
+     */
+    public  static final int ERROR_WOULD_BLOCK                     = AudioSystem.WOULD_BLOCK;
 
     // Error codes:
     // to keep in sync with frameworks/base/core/jni/android_media_AudioTrack.cpp
@@ -1225,6 +1237,44 @@
         return true;
     }
 
+    /**
+     * Poll for a timestamp on demand.
+     * <p>
+     * Same as {@link #getTimestamp(AudioTimestamp)} but with a more useful return code.
+     *
+     * @param timestamp a reference to a non-null AudioTimestamp instance allocated
+     *        and owned by caller.
+     * @return {@link #SUCCESS} if a timestamp is available
+     *         {@link #ERROR_WOULD_BLOCK} if called in STOPPED or FLUSHED state, or if called
+     *         immediately after start/ACTIVE, when the number of frames consumed is less than the
+     *         overall hardware latency to physical output. In WOULD_BLOCK cases, one might poll
+     *         again, or use {@link #getPlaybackHeadPosition}, or use 0 position and current time
+     *         for the timestamp.
+     *         {@link #ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+     *         needs to be recreated.
+     *         {@link #ERROR_INVALID_OPERATION} if current route does not support
+     *         timestamps. In this case, the approximate frame position can be obtained
+     *         using {@link #getPlaybackHeadPosition}.
+     *
+     *         The AudioTimestamp instance is filled in with a position in frame units, together
+     *         with the estimated time when that frame was presented or is committed to
+     *         be presented.
+     * @hide
+     */
+     // Add this text when the "on new timestamp" API is added:
+     //   Use if you need to get the most recent timestamp outside of the event callback handler.
+     public int getTimestampWithStatus(AudioTimestamp timestamp)
+     {
+         if (timestamp == null) {
+             throw new IllegalArgumentException();
+         }
+         // It's unfortunate, but we have to either create garbage every time or use synchronized
+         long[] longArray = new long[2];
+         int ret = native_get_timestamp(longArray);
+         timestamp.framePosition = longArray[0];
+         timestamp.nanoTime = longArray[1];
+         return ret;
+     }
 
     //--------------------------------------------------------------------------
     // Initialization / configuration