Emphasize distinction between streaming and static

Update comments and improve error checks to match

Change-Id: I7370d6e59a7ef26dfb284a8b058d5ab2e0a42ccf
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index d2739f7..6f85527 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -52,8 +52,11 @@
      * Keep in sync with frameworks/base/media/java/android/media/AudioTrack.java NATIVE_EVENT_*.
      */
     enum event_type {
-        EVENT_MORE_DATA = 0,        // Request to write more data to PCM buffer.
-        EVENT_UNDERRUN = 1,         // PCM buffer underrun occurred.
+        EVENT_MORE_DATA = 0,        // Request to write more data to buffer.
+                                    // If this event is delivered but the callback handler
+                                    // does not want to write more data, the handler must explicitly
+                                    // ignore the event by setting frameCount to zero.
+        EVENT_UNDERRUN = 1,         // Buffer underrun occurred.
         EVENT_LOOP_END = 2,         // Sample loop end was reached; playback restarted from
                                     // loop start if loop count was not 0.
         EVENT_MARKER = 3,           // Playback head is at the specified marker position
@@ -115,14 +118,16 @@
                                       uint32_t sampleRate = 0);
 
     /* Constructs an uninitialized AudioTrack. No connection with
-     * AudioFlinger takes place.
+     * AudioFlinger takes place.  Use set() after this.
      */
                         AudioTrack();
 
     /* Creates an AudioTrack object and registers it with AudioFlinger.
      * Once created, the track needs to be started before it can be used.
-     * Unspecified values are set to the audio hardware's current
-     * values.
+     * Unspecified values are set to appropriate default values.
+     * With this constructor, the track is configured for streaming mode.
+     * Data to be rendered is supplied by write() or by the callback EVENT_MORE_DATA.
+     * Intermixing a combination of write() and non-ignored EVENT_MORE_DATA is deprecated.
      *
      * Parameters:
      *
@@ -136,10 +141,10 @@
      *                     application's contribution to the
      *                     latency of the track. The actual size selected by the AudioTrack could be
      *                     larger if the requested size is not compatible with current audio HAL
-     *                     latency.  Zero means to use a default value.
+     *                     configuration.  Zero means to use a default value.
      * flags:              See comments on audio_output_flags_t in <system/audio.h>.
      * cbf:                Callback function. If not null, this function is called periodically
-     *                     to provide new PCM data.
+     *                     to provide new data and inform of marker, position updates, etc.
      * user:               Context for use by the callback receiver.
      * notificationFrames: The callback function is called each time notificationFrames PCM
      *                     frames have been consumed from track input buffer.
@@ -159,13 +164,16 @@
                                     int notificationFrames = 0,
                                     int sessionId        = 0);
 
-    /* Creates an audio track and registers it with AudioFlinger. With this constructor,
-     * the PCM data to be rendered by AudioTrack is passed in a shared memory buffer
-     * identified by the argument sharedBuffer. This prototype is for static buffer playback.
-     * PCM data must be present in memory before the AudioTrack is started.
+    /* Creates an audio track and registers it with AudioFlinger.
+     * With this constructor, the track is configured for static buffer mode.
+     * The format must not be 8-bit linear PCM.
+     * Data to be rendered is passed in a shared memory buffer
+     * identified by the argument sharedBuffer, which must be non-0.
+     * The memory should be initialized to the desired data before calling start().
      * The write() method is not supported in this case.
      * It is recommended to pass a callback function to be notified of playback end by an
      * EVENT_UNDERRUN event.
+     * FIXME EVENT_MORE_DATA still occurs; it must be ignored.
      */
 
                         AudioTrack( audio_stream_type_t streamType,
@@ -184,13 +192,14 @@
      */
                         ~AudioTrack();
 
-
     /* Initialize an uninitialized AudioTrack.
      * Returned status (from utils/Errors.h) can be:
      *  - NO_ERROR: successful initialization
      *  - INVALID_OPERATION: AudioTrack is already initialized
      *  - BAD_VALUE: invalid parameter (channelMask, format, sampleRate...)
      *  - NO_INIT: audio server or audio hardware not initialized
+     * If sharedBuffer is non-0, the frameCount parameter is ignored and
+     * replaced by the shared buffer's total allocated size in frame units.
      */
             status_t    set(audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT,
                             uint32_t sampleRate = 0,
@@ -205,7 +214,6 @@
                             bool threadCanCallJava = false,
                             int sessionId       = 0);
 
-
     /* Result of constructing the AudioTrack. This must be checked
      * before using any AudioTrack API (except for set()), because using
      * an uninitialized AudioTrack produces undefined results.
@@ -224,25 +232,31 @@
             audio_stream_type_t streamType() const { return mStreamType; }
             audio_format_t format() const   { return mFormat; }
 
-    /* Return channelCount * (bit depth per channel / 8).
+    /* Return frame size in bytes, which for linear PCM is channelCount * (bit depth per channel / 8).
      * channelCount is determined from channelMask, and bit depth comes from format.
+     * For non-linear formats, the frame size is typically 1 byte.
      */
             uint32_t    channelCount() const { return mChannelCount; }
 
             uint32_t    frameCount() const  { return mFrameCount; }
             size_t      frameSize() const   { return mFrameSize; }
 
+    /* Return the static buffer specified in constructor or set(), or 0 for streaming mode */
             sp<IMemory> sharedBuffer() const { return mSharedBuffer; }
 
-
     /* After it's created the track is not active. Call start() to
      * make it active. If set, the callback will start being called.
+     * If the track was previously paused, volume is ramped up over the first mix buffer.
      */
             void        start();
 
-    /* Stop a track. If set, the callback will cease being called and
+    /* Stop a track.
+     * In static buffer mode, the track is stopped immediately.
+     * In streaming mode, the callback will cease being called and
      * obtainBuffer returns STOPPED. Note that obtainBuffer() still works
      * and will fill up buffers until the pool is exhausted.
+     * The stop does not occur immediately: any data remaining in the buffer
+     * is first drained, mixed, and output, and only then is the track marked as stopped.
      */
             void        stop();
             bool        stopped() const;
@@ -254,9 +268,11 @@
      */
             void        flush();
 
-    /* Pause a track. If set, the callback will cease being called and
+    /* Pause a track. After pause, the callback will cease being called and
      * obtainBuffer returns STOPPED. Note that obtainBuffer() still works
      * and will fill up buffers until the pool is exhausted.
+     * Volume is ramped down over the next mix buffer following the pause request,
+     * and then the track is marked as paused.  It can be resumed with ramp up by start().
      */
             void        pause();
 
@@ -285,6 +301,7 @@
             uint32_t    getSampleRate() const;
 
     /* Enables looping and sets the start and end points of looping.
+     * Only supported for static buffer mode.
      *
      * Parameters:
      *
@@ -300,13 +317,15 @@
 
     /* Sets marker position. When playback reaches the number of frames specified, a callback with
      * event type EVENT_MARKER is called. Calling setMarkerPosition with marker == 0 cancels marker
-     * notification callback.
+     * notification callback.  To set a marker at a position which would compute as 0,
+     * a workaround is to the set the marker at a nearby position such as -1 or 1.
      * If the AudioTrack has been opened with no callback function associated, the operation will
      * fail.
      *
      * Parameters:
      *
-     * marker:   marker position expressed in frames.
+     * marker:   marker position expressed in wrapping (overflow) frame units,
+     *           like the return value of getPosition().
      *
      * Returned status (from utils/Errors.h) can be:
      *  - NO_ERROR: successful operation
@@ -315,13 +334,13 @@
             status_t    setMarkerPosition(uint32_t marker);
             status_t    getMarkerPosition(uint32_t *marker) const;
 
-
     /* Sets position update period. Every time the number of frames specified has been played,
      * a callback with event type EVENT_NEW_POS is called.
      * Calling setPositionUpdatePeriod with updatePeriod == 0 cancels new position notification
      * callback.
      * If the AudioTrack has been opened with no callback function associated, the operation will
      * fail.
+     * Extremely small values may be rounded up to a value the implementation can support.
      *
      * Parameters:
      *
@@ -349,20 +368,26 @@
      *
      * Returned status (from utils/Errors.h) can be:
      *  - NO_ERROR: successful operation
-     *  - INVALID_OPERATION: the AudioTrack is not stopped.
+     *  - INVALID_OPERATION: the AudioTrack is not stopped or paused, or is streaming mode.
      *  - BAD_VALUE: The specified position is beyond the number of frames present in AudioTrack
      *               buffer
      */
             status_t    setPosition(uint32_t position);
+
+    /* Return the total number of frames played since playback start.
+     * The counter will wrap (overflow) periodically, e.g. every ~27 hours at 44.1 kHz.
+     * It is reset to zero by flush(), reload(), and stop().
+     */
             status_t    getPosition(uint32_t *position);
 
     /* Forces AudioTrack buffer full condition. When playing a static buffer, this method avoids
      * rewriting the buffer before restarting playback after a stop.
      * This method must be called with the AudioTrack in paused or stopped state.
+     * Not allowed in streaming mode.
      *
      * Returned status (from utils/Errors.h) can be:
      *  - NO_ERROR: successful operation
-     *  - INVALID_OPERATION: the AudioTrack is not stopped.
+     *  - INVALID_OPERATION: the AudioTrack is not stopped or paused, or is streaming mode.
      */
             status_t    reload();
 
@@ -410,6 +435,9 @@
      * or return WOULD_BLOCK depending on the value of the "blocking"
      * parameter.
      *
+     * obtainBuffer() and releaseBuffer() are deprecated for direct use by applications,
+     * which should use write() or callback EVENT_MORE_DATA instead.
+     *
      * Interpretation of waitCount:
      *  +n  limits wait time to n * WAIT_PERIOD_MS,
      *  -1  causes an (almost) infinite wait time,
@@ -447,6 +475,7 @@
      *      STOPPED             AudioTrack was stopped during the write
      *      NO_MORE_BUFFERS     when obtainBuffer() returns same
      *      or any other error code returned by IAudioTrack::start() or restoreTrack_l().
+     * Not supported for static buffer mode.
      */
             ssize_t     write(const void* buffer, size_t size);
 
@@ -548,7 +577,7 @@
     sp<IMemory>             mSharedBuffer;
     int                     mLoopCount;
     uint32_t                mRemainingFrames;
-    uint32_t                mMarkerPosition;        // in frames
+    uint32_t                mMarkerPosition;        // in wrapping (overflow) frame units
     bool                    mMarkerReached;
     uint32_t                mNewPosition;           // in frames
     uint32_t                mUpdatePeriod;          // in frames
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 597d057..ac672a7 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -138,6 +138,11 @@
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
       mPreviousSchedulingGroup(SP_DEFAULT)
 {
+    if (sharedBuffer == 0) {
+        ALOGE("sharedBuffer must be non-0");
+        mStatus = BAD_VALUE;
+        return;
+    }
     mStatus = set(streamType, sampleRate, format, channelMask,
             0 /*frameCount*/, flags, cbf, user, notificationFrames,
             sharedBuffer, false /*threadCanCallJava*/, sessionId);
@@ -535,6 +540,10 @@
 // must be called with mLock held
 status_t AudioTrack::setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount)
 {
+    if (mSharedBuffer == 0 || mIsTimed) {
+        return INVALID_OPERATION;
+    }
+
     audio_track_cblk_t* cblk = mCblk;
 
     Mutex::Autolock _l(cblk->lock);
@@ -547,10 +556,6 @@
         return NO_ERROR;
     }
 
-    if (mIsTimed) {
-        return INVALID_OPERATION;
-    }
-
     if (loopStart >= loopEnd ||
         loopEnd - loopStart > mFrameCount ||
         cblk->server > loopStart) {
@@ -624,7 +629,7 @@
 
 status_t AudioTrack::setPosition(uint32_t position)
 {
-    if (mIsTimed) {
+    if (mSharedBuffer == 0 || mIsTimed) {
         return INVALID_OPERATION;
     }
 
@@ -660,6 +665,10 @@
 
 status_t AudioTrack::reload()
 {
+    if (mSharedBuffer == 0 || mIsTimed) {
+        return INVALID_OPERATION;
+    }
+
     AutoMutex lock(mLock);
 
     if (!stopped_l()) {
@@ -1036,10 +1045,7 @@
 ssize_t AudioTrack::write(const void* buffer, size_t userSize)
 {
 
-    if (mSharedBuffer != 0) {
-        return INVALID_OPERATION;
-    }
-    if (mIsTimed) {
+    if (mSharedBuffer != 0 || mIsTimed) {
         return INVALID_OPERATION;
     }