Merge "Initialize bootanimation sound on separate thread"
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 9fad7bf..c773275 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -107,8 +107,6 @@
     mSystemBoot = !property_get_bool(BOOT_COMPLETED_PROP_NAME, 0);
 }
 
-BootAnimation::~BootAnimation() {}
-
 void BootAnimation::onFirstRef() {
     status_t err = mSession->linkToComposerDeath(this);
     ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
@@ -778,11 +776,12 @@
     }
 
     // Create and initialize audioplay if there is a wav file in any of the animations.
+    // Do it on a separate thread so we don't hold up the animation intro.
     if (partWithAudio != NULL) {
         ALOGD("found audio.wav, creating playback engine");
-        if (!audioplay::create(partWithAudio->audioData, partWithAudio->audioLength)) {
-            return false;
-        }
+        mInitAudioThread = new InitAudioThread(partWithAudio->audioData,
+                                               partWithAudio->audioLength);
+        mInitAudioThread->run("BootAnimation::InitAudioThread", PRIORITY_NORMAL);
     }
 
     zip->endIteration(cookie);
@@ -850,9 +849,14 @@
 
     playAnimation(*animation);
 
-    if (mTimeCheckThread != NULL) {
+    if (mTimeCheckThread != nullptr) {
         mTimeCheckThread->requestExit();
-        mTimeCheckThread = NULL;
+        mTimeCheckThread = nullptr;
+    }
+
+    if (mInitAudioThread != nullptr) {
+        mInitAudioThread->requestExit();
+        mInitAudioThread = nullptr;
     }
 
     releaseAnimation(animation);
@@ -892,6 +896,10 @@
             // only play audio file the first time we animate the part
             if (r == 0 && part.audioData && playSoundsAllowed()) {
                 ALOGD("playing clip for part%d, size=%d", (int) i, part.audioLength);
+                // Block until the audio engine is finished initializing.
+                if (mInitAudioThread != nullptr) {
+                    mInitAudioThread->join();
+                }
                 audioplay::playClip(part.audioData, part.audioLength);
             }
 
@@ -1185,6 +1193,17 @@
     return NO_ERROR;
 }
 
+BootAnimation::InitAudioThread::InitAudioThread(uint8_t* exampleAudioData, int exampleAudioLength)
+    : Thread(false),
+      mExampleAudioData(exampleAudioData),
+      mExampleAudioLength(exampleAudioLength) {}
+
+bool BootAnimation::InitAudioThread::threadLoop() {
+    audioplay::create(mExampleAudioData, mExampleAudioLength);
+    // Exit immediately
+    return false;
+}
+
 // ---------------------------------------------------------------------------
 
 }
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index 7a2e4c2..f1fc98e 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -39,8 +39,7 @@
 class BootAnimation : public Thread, public IBinder::DeathRecipient
 {
 public:
-                BootAnimation();
-    virtual     ~BootAnimation();
+    BootAnimation();
 
     sp<SurfaceComposerClient> session() const;
 
@@ -68,6 +67,16 @@
         BootAnimation* mBootAnimation;
     };
 
+    class InitAudioThread : public Thread {
+    public:
+        InitAudioThread(uint8_t* exampleAudioData, int mExampleAudioLength);
+    private:
+        virtual bool threadLoop();
+
+        uint8_t* mExampleAudioData;
+        int mExampleAudioLength;
+    };
+
     struct Texture {
         GLint   w;
         GLint   h;
@@ -156,7 +165,8 @@
     bool        mSystemBoot;
     String8     mZipFileName;
     SortedVector<String8> mLoadedFiles;
-    sp<TimeCheckThread> mTimeCheckThread;
+    sp<TimeCheckThread> mTimeCheckThread = nullptr;
+    sp<InitAudioThread> mInitAudioThread = nullptr;
 };
 
 // ---------------------------------------------------------------------------