Merge "Fixes delay when playing first sound in BootAnimation" into nyc-mr1-dev
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index 3cf13d9..3a92b9e 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -36,8 +36,4 @@
 LOCAL_32_BIT_ONLY := true
 endif
 
-# get asserts to work
-APP_OPTIM := debug
-LOCAL_CFLAGS += -UNDEBUG
-
 include $(BUILD_EXECUTABLE)
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 4098772..ebcc9ff 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -588,7 +588,7 @@
         return false;
     }
 
-    bool hasAudio = false;
+    Animation::Part* partWithAudio = NULL;
     ZipEntryRO entry;
     char name[ANIM_ENTRY_NAME_MAX];
     while ((entry = zip->nextEntry(cookie)) != NULL) {
@@ -612,10 +612,10 @@
                             if (map) {
                                 Animation::Part& part(animation.parts.editItemAt(j));
                                 if (leaf == "audio.wav") {
-                                    hasAudio = true;
                                     // a part may have at most one audio file
                                     part.audioData = (uint8_t *)map->getDataPtr();
                                     part.audioLength = map->getDataLength();
+                                    partWithAudio = ∂
                                 } else if (leaf == "trim.txt") {
                                     part.trimData.setTo((char const*)map->getDataPtr(),
                                                         map->getDataLength());
@@ -666,9 +666,11 @@
     }
 
     // Create and initialize audioplay if there is a wav file in any of the animations.
-    if (hasAudio) {
+    if (partWithAudio != NULL) {
         ALOGD("found audio.wav, creating playback engine");
-        audioplay::create();
+        if (!audioplay::create(partWithAudio->audioData, partWithAudio->audioLength)) {
+            return false;
+        }
     }
 
     zip->endIteration(cookie);
@@ -904,7 +906,10 @@
     mLoadedFiles.add(animation->fileName);
 
     parseAnimationDesc(*animation);
-    preloadZip(*animation);
+    if (!preloadZip(*animation)) {
+        return NULL;
+    }
+
 
     mLoadedFiles.remove(fn);
     return animation;
diff --git a/cmds/bootanimation/audioplay.cpp b/cmds/bootanimation/audioplay.cpp
index e20ef0c..8a5c2c6 100644
--- a/cmds/bootanimation/audioplay.cpp
+++ b/cmds/bootanimation/audioplay.cpp
@@ -21,7 +21,6 @@
 
 #define CHATTY ALOGD
 
-#include <assert.h>
 #include <string.h>
 
 #include <utils/Log.h>
@@ -80,8 +79,6 @@
 void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) {
     (void)bq;
     (void)context;
-    assert(bq == bqPlayerBufferQueue);
-    assert(NULL == context);
     audioplay::setPlaying(false);
 }
 
@@ -90,39 +87,56 @@
 }
 
 // create the engine and output mix objects
-void createEngine() {
+bool createEngine() {
     SLresult result;
 
     // create engine
     result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("slCreateEngine failed with result %d", result);
+        return false;
+    }
     (void)result;
 
     // realize the engine
     result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl engine Realize failed with result %d", result);
+        return false;
+    }
     (void)result;
 
     // get the engine interface, which is needed in order to create other objects
     result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl engine GetInterface failed with result %d", result);
+        return false;
+    }
     (void)result;
 
     // create output mix, with environmental reverb specified as a non-required interface
     const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
     const SLboolean req[1] = {SL_BOOLEAN_FALSE};
     result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl engine CreateOutputMix failed with result %d", result);
+        return false;
+    }
     (void)result;
 
     // realize the output mix
     result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl outputMix Realize failed with result %d", result);
+        return false;
+    }
     (void)result;
+
+    return true;
 }
 
 // create buffer queue audio player
-void createBufferQueueAudioPlayer(const ChunkFormat* chunkFormat) {
+bool createBufferQueueAudioPlayer(const ChunkFormat* chunkFormat) {
     SLresult result;
 
     // configure audio source
@@ -148,83 +162,89 @@
     const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
     result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk,
             2, ids, req);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl CreateAudioPlayer failed with result %d", result);
+        return false;
+    }
     (void)result;
 
     // realize the player
     result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl player Realize failed with result %d", result);
+        return false;
+    }
     (void)result;
 
     // get the play interface
     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl player GetInterface failed with result %d", result);
+        return false;
+    }
     (void)result;
 
     // get the buffer queue interface
     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE,
             &bqPlayerBufferQueue);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl playberBufferQueue GetInterface failed with result %d", result);
+        return false;
+    }
     (void)result;
 
     // register callback on the buffer queue
     result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl bqPlayerBufferQueue RegisterCallback failed with result %d", result);
+        return false;
+    }
     (void)result;
 
-#if 0   // mute/solo is not supported for sources that are known to be mono, as this is
-    // get the mute/solo interface
-    result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_MUTESOLO, &bqPlayerMuteSolo);
-    assert(SL_RESULT_SUCCESS == result);
-    (void)result;
-#endif
-
     // get the volume interface
     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl volume GetInterface failed with result %d", result);
+        return false;
+    }
     (void)result;
 
     // set the player's state to playing
     audioplay::setPlaying(true);
     CHATTY("Created buffer queue player: %p", bqPlayerBufferQueue);
+    return true;
 }
 
-} // namespace
-
-void create() {
-    createEngine();
-}
-
-bool playClip(const uint8_t* buf, int size) {
-    // Parse the WAV header
-    nextBuffer = buf;
-    nextSize = size;
-    const RiffWaveHeader* wavHeader = (const RiffWaveHeader*)buf;
-    if (nextSize < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) ||
+bool parseClipBuf(const uint8_t* clipBuf, int clipBufSize, const ChunkFormat** oChunkFormat,
+                  const uint8_t** oSoundBuf, unsigned* oSoundBufSize) {
+    *oSoundBuf = clipBuf;
+    *oSoundBufSize = clipBufSize;
+    *oChunkFormat = NULL;
+    const RiffWaveHeader* wavHeader = (const RiffWaveHeader*)*oSoundBuf;
+    if (*oSoundBufSize < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) ||
         (wavHeader->wave_id != ID_WAVE)) {
         ALOGE("Error: audio file is not a riff/wave file\n");
         return false;
     }
-    nextBuffer += sizeof(*wavHeader);
-    nextSize -= sizeof(*wavHeader);
+    *oSoundBuf += sizeof(*wavHeader);
+    *oSoundBufSize -= sizeof(*wavHeader);
 
-    const ChunkFormat* chunkFormat = nullptr;
     while (true) {
-        const ChunkHeader* chunkHeader = (const ChunkHeader*)nextBuffer;
-        if (nextSize < sizeof(*chunkHeader)) {
+        const ChunkHeader* chunkHeader = (const ChunkHeader*)*oSoundBuf;
+        if (*oSoundBufSize < sizeof(*chunkHeader)) {
             ALOGE("EOF reading chunk headers");
             return false;
         }
 
-        nextBuffer += sizeof(*chunkHeader);
-        nextSize -= sizeof(*chunkHeader);
+        *oSoundBuf += sizeof(*chunkHeader);
+        *oSoundBufSize -= sizeof(*chunkHeader);
 
         bool endLoop = false;
         switch (chunkHeader->id) {
             case ID_FMT:
-                chunkFormat = (const ChunkFormat*)nextBuffer;
-                nextBuffer += chunkHeader->sz;
-                nextSize -= chunkHeader->sz;
+                *oChunkFormat = (const ChunkFormat*)*oSoundBuf;
+                *oSoundBuf += chunkHeader->sz;
+                *oSoundBufSize -= chunkHeader->sz;
                 break;
             case ID_DATA:
                 /* Stop looking for chunks */
@@ -232,27 +252,49 @@
                 break;
             default:
                 /* Unknown chunk, skip bytes */
-                nextBuffer += chunkHeader->sz;
-                nextSize -= chunkHeader->sz;
+                *oSoundBuf += chunkHeader->sz;
+                *oSoundBufSize -= chunkHeader->sz;
         }
         if (endLoop) {
             break;
         }
     }
 
-    if (!chunkFormat) {
+    if (*oChunkFormat == NULL) {
         ALOGE("format not found in WAV file");
         return false;
     }
+    return true;
+}
 
-    // If this is the first clip, create the buffer based on this WAV's header.
-    // We assume all future clips with be in the same format.
-    if (bqPlayerBufferQueue == nullptr) {
-        createBufferQueueAudioPlayer(chunkFormat);
+} // namespace
+
+bool create(const uint8_t* exampleClipBuf, int exampleClipBufSize) {
+    if (!createEngine()) {
+        return false;
     }
 
-    assert(bqPlayerBufferQueue != nullptr);
-    assert(buf != nullptr);
+    // Parse the example clip.
+    const ChunkFormat* chunkFormat;
+    const uint8_t* soundBuf;
+    unsigned soundBufSize;
+    if (!parseClipBuf(exampleClipBuf, exampleClipBufSize, &chunkFormat, &soundBuf, &soundBufSize)) {
+        return false;
+    }
+
+    // Initialize the BufferQueue based on this clip's format.
+    if (!createBufferQueueAudioPlayer(chunkFormat)) {
+        return false;
+    }
+    return true;
+}
+
+bool playClip(const uint8_t* buf, int size) {
+    // Parse the WAV header
+    const ChunkFormat* chunkFormat;
+    if (!parseClipBuf(buf, size, &chunkFormat, &nextBuffer, &nextSize)) {
+        return false;
+    }
 
     if (!hasPlayer()) {
         ALOGD("cannot play clip %p without a player", buf);
@@ -285,8 +327,6 @@
         // set the player's state
         result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay,
             isPlaying ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_STOPPED);
-        assert(SL_RESULT_SUCCESS == result);
-        (void)result;
     }
 
 }
diff --git a/cmds/bootanimation/audioplay.h b/cmds/bootanimation/audioplay.h
index bdc0a1c..0e5705af 100644
--- a/cmds/bootanimation/audioplay.h
+++ b/cmds/bootanimation/audioplay.h
@@ -22,10 +22,12 @@
 
 namespace audioplay {
 
-void create();
+// Initializes the engine with an example of the type of WAV clip to play.
+// All buffers passed to playClip are assumed to be in the same format.
+bool create(const uint8_t* exampleClipBuf, int exampleClipBufSize);
 
-// Play a WAV pointed to by buf.  All clips are assumed to be in the same format.
-// playClip should not be called while a clip is still playing.
+// Plays a WAV contained in buf.
+// Should not be called while a clip is still playing.
 bool playClip(const uint8_t* buf, int size);
 void setPlaying(bool isPlaying);
 void destroy();