diff options
author | Ed Coyne <edcoyne@google.com> | 2017-05-31 10:08:28 -0700 |
---|---|---|
committer | Ed Coyne <edcoyne@google.com> | 2017-05-31 10:24:52 -0700 |
commit | 2c9e94aa3e9614f0d202ee008c08a9011fa7f75f (patch) | |
tree | ccc7e6d62479007774b6d58effcff4994298d987 /cmds/bootanimation/bootanimation_main.cpp | |
parent | 0ed316b7f147401d158bd07f188ed2e598b337ba (diff) |
Refactor bootanimation into a shared lib.
We would like to reuse the animation parts of it in Android things.
This refactors the audio part into the _main and gets callbacks from
the BootAnimation class at interesting times. This will be the same
approach we take to integrate with it.
BUG: 37992717
Test: Built locally and pushed to a bullhead, works with sound.
Change-Id: I5eaca07c25eeb5edeab07d7ae7a29945e0e2cd37
Diffstat (limited to 'cmds/bootanimation/bootanimation_main.cpp')
-rw-r--r-- | cmds/bootanimation/bootanimation_main.cpp | 106 |
1 files changed, 105 insertions, 1 deletions
diff --git a/cmds/bootanimation/bootanimation_main.cpp b/cmds/bootanimation/bootanimation_main.cpp index 3689d5ed937e..c11d90522ffd 100644 --- a/cmds/bootanimation/bootanimation_main.cpp +++ b/cmds/bootanimation/bootanimation_main.cpp @@ -27,13 +27,77 @@ #include <utils/Log.h> #include <utils/SystemClock.h> #include <utils/threads.h> +#include <android-base/properties.h> #include "BootAnimation.h" +#include "audioplay.h" using namespace android; // --------------------------------------------------------------------------- +namespace { + +// Create a typedef for readability. +typedef android::BootAnimation::Animation Animation; + +static const char PLAY_SOUND_PROP_NAME[] = "persist.sys.bootanim.play_sound"; +static const char BOOT_COMPLETED_PROP_NAME[] = "sys.boot_completed"; +static const char POWER_CTL_PROP_NAME[] = "sys.powerctl"; +static const char BOOTREASON_PROP_NAME[] = "ro.boot.bootreason"; +static const std::vector<std::string> PLAY_SOUND_BOOTREASON_BLACKLIST { + "kernel_panic", + "Panic", + "Watchdog", +}; + +class InitAudioThread : public Thread { +public: + InitAudioThread(uint8_t* exampleAudioData, int exampleAudioLength) + : Thread(false), + mExampleAudioData(exampleAudioData), + mExampleAudioLength(exampleAudioLength) {} +private: + virtual bool threadLoop() { + audioplay::create(mExampleAudioData, mExampleAudioLength); + // Exit immediately + return false; + } + + uint8_t* mExampleAudioData; + int mExampleAudioLength; +}; + +bool playSoundsAllowed() { + // Only play sounds for system boots, not runtime restarts. + if (android::base::GetBoolProperty(BOOT_COMPLETED_PROP_NAME, false)) { + return false; + } + // no audio while shutting down + if (!android::base::GetProperty(POWER_CTL_PROP_NAME, "").empty()) { + return false; + } + // Read the system property to see if we should play the sound. + // If it's not present, default to allowed. + if (!property_get_bool(PLAY_SOUND_PROP_NAME, 1)) { + return false; + } + + // Don't play sounds if this is a reboot due to an error. + char bootreason[PROPERTY_VALUE_MAX]; + if (property_get(BOOTREASON_PROP_NAME, bootreason, nullptr) > 0) { + for (const auto& str : PLAY_SOUND_BOOTREASON_BLACKLIST) { + if (strcasecmp(str.c_str(), bootreason) == 0) { + return false; + } + } + } + return true; +} + +} // namespace + + int main() { setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY); @@ -71,10 +135,50 @@ int main() ALOGI("Waiting for SurfaceFlinger took %" PRId64 " ms", totalWaited); } + // TODO: Move audio code to a new class that just exports the callbacks. + sp<InitAudioThread> initAudioThread = nullptr; + + auto initCallback = [&](const Vector<Animation::Part>& parts) { + const Animation::Part* partWithAudio = nullptr; + for (const Animation::Part& part : parts) { + if (part.audioData != nullptr) { + partWithAudio = ∂ + } + } + + if (partWithAudio == nullptr) { + return; + } + + ALOGD("found audio.wav, creating playback engine"); + initAudioThread = new InitAudioThread(partWithAudio->audioData, + partWithAudio->audioLength); + initAudioThread->run("BootAnimation::InitAudioThread", PRIORITY_NORMAL); + + }; + + auto partCallback = [&](int partNumber, const Animation::Part& part, + int playNumber) { + // only play audio file the first time we animate the part + if (playNumber == 0 && part.audioData && playSoundsAllowed()) { + ALOGD("playing clip for part%d, size=%d", + partNumber, part.audioLength); + // Block until the audio engine is finished initializing. + if (initAudioThread != nullptr) { + initAudioThread->join(); + } + audioplay::playClip(part.audioData, part.audioLength); + } + }; + // create the boot animation object - sp<BootAnimation> boot = new BootAnimation(); + sp<BootAnimation> boot = new BootAnimation(initCallback, partCallback); IPCThreadState::self()->joinThreadPool(); + + // we've finally played everything we're going to play + audioplay::setPlaying(false); + audioplay::destroy(); } return 0; } |