OpenSL-based audio support for BootAnimation

Respects dnd settings for sound playback.
Basic implementation uses in-memory wavs as buffers.
audioplay::playClip should not be called before previous clip ends.
Updated FORMAT.md to reflect no more audio_conf.txt

Bug: 29055299
Change-Id: Ifc358d7c85f11b8b54ae6446c40643b87bc567f2
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index e849f4b..6789e2f 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -58,7 +58,7 @@
 #include <EGL/eglext.h>
 
 #include "BootAnimation.h"
-#include "AudioPlayer.h"
+#include "audioplay.h"
 
 namespace android {
 
@@ -106,9 +106,7 @@
     // might be blocked on a condition variable that will never be updated.
     kill( getpid(), SIGKILL );
     requestExit();
-    if (mAudioPlayer != NULL) {
-        mAudioPlayer->requestExit();
-    }
+    audioplay::destroy();
 }
 
 status_t BootAnimation::initTexture(Texture* texture, AssetManager& assets,
@@ -400,9 +398,6 @@
     int exitnow = atoi(value);
     if (exitnow) {
         requestExit();
-        if (mAudioPlayer != NULL) {
-            mAudioPlayer->requestExit();
-        }
     }
 }
 
@@ -524,16 +519,6 @@
     }
     char const* s = desString.string();
 
-    // Create and initialize an AudioPlayer if we have an audio_conf.txt file
-    String8 audioConf;
-    if (readFile(animation.zip, "audio_conf.txt", audioConf)) {
-        mAudioPlayer = new AudioPlayer;
-        if (!mAudioPlayer->init(audioConf.string())) {
-            ALOGE("mAudioPlayer.init failed");
-            mAudioPlayer = NULL;
-        }
-    }
-
     // Parse the description file
     for (;;) {
         const char* endl = strstr(s, "\n");
@@ -564,7 +549,7 @@
             part.pause = pause;
             part.path = path;
             part.clockPosY = clockPosY;
-            part.audioFile = NULL;
+            part.audioData = NULL;
             part.animation = NULL;
             if (!parseColor(color, part.backgroundColor)) {
                 ALOGE("> invalid color '#%s'", color);
@@ -580,7 +565,7 @@
             part.playUntilComplete = false;
             part.count = 1;
             part.pause = 0;
-            part.audioFile = NULL;
+            part.audioData = NULL;
             part.animation = loadAnimation(String8(SYSTEM_BOOTANIMATION_FILE));
             if (part.animation != NULL)
                 animation.parts.add(part);
@@ -601,6 +586,7 @@
         return false;
     }
 
+    bool hasAudio = false;
     ZipEntryRO entry;
     char name[ANIM_ENTRY_NAME_MAX];
     while ((entry = zip->nextEntry(cookie)) != NULL) {
@@ -624,8 +610,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.audioFile = map;
+                                    part.audioData = (uint8_t *)map->getDataPtr();
+                                    part.audioLength = map->getDataLength();
                                 } else if (leaf == "trim.txt") {
                                     part.trimData.setTo((char const*)map->getDataPtr(),
                                                         map->getDataLength());
@@ -640,6 +628,8 @@
                                     part.frames.add(frame);
                                 }
                             }
+                        } else {
+                            ALOGE("bootanimation.zip is compressed; must be only stored");
                         }
                     }
                 }
@@ -673,6 +663,12 @@
         }
     }
 
+    // Create and initialize audioplay if there is a wav file in any of the animations.
+    if (hasAudio) {
+        ALOGD("found audio.wav, creating playback engine");
+        audioplay::create();
+    }
+
     zip->endIteration(cookie);
 
     return true;
@@ -763,8 +759,9 @@
                 break;
 
             // only play audio file the first time we animate the part
-            if (r == 0 && mAudioPlayer != NULL && part.audioFile) {
-                mAudioPlayer->playFile(part.audioFile);
+            if (r == 0 && part.audioData) {
+                ALOGD("playing clip for part%d, size=%d", (int) i, part.audioLength);
+                audioplay::playClip(part.audioData, part.audioLength);
             }
 
             glClearColor(
@@ -847,6 +844,11 @@
             }
         }
     }
+
+    // we've finally played everything we're going to play
+    audioplay::setPlaying(false);
+    audioplay::destroy();
+
     return true;
 }