Suppress Boot sound for non-standard scenarios.

Blacklisted bootreasons will not play a sound (e.g. "kernel_panic")
If boot has already completed, assume this is a runtime restart and
skip the sound.

Bug: 30654343
Change-Id: I41b1829a93c0d9a63c69aea2d1614eaa18b72230
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 495e56c..a2d34e4 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -77,12 +77,23 @@
 static const char EXIT_PROP_NAME[] = "service.bootanim.exit";
 static const char PLAY_SOUND_PROP_NAME[] = "persist.sys.bootanim.play_sound";
 static const int ANIM_ENTRY_NAME_MAX = 256;
+static const char BOOT_COMPLETED_PROP_NAME[] = "sys.boot_completed";
+static const char BOOTREASON_PROP_NAME[] = "ro.boot.bootreason";
+// bootreasons list in "system/core/bootstat/bootstat.cpp".
+static const std::vector<std::string> PLAY_SOUND_BOOTREASON_BLACKLIST {
+  "kernel_panic",
+  "Panic",
+  "Watchdog",
+};
 
 // ---------------------------------------------------------------------------
 
 BootAnimation::BootAnimation() : Thread(false), mClockEnabled(true), mTimeIsAccurate(false),
         mTimeCheckThread(NULL) {
     mSession = new SurfaceComposerClient();
+
+    // If the system has already booted, the animation is not being used for a boot.
+    mSystemBoot = !property_get_bool(BOOT_COMPLETED_PROP_NAME, 0);
 }
 
 BootAnimation::~BootAnimation() {}
@@ -778,13 +789,9 @@
                 break;
 
             // only play audio file the first time we animate the part
-            if (r == 0 && part.audioData) {
-                // Read the system property to see if we should play the sound.
-                // If not present, default to playing it.
-                if (property_get_bool(PLAY_SOUND_PROP_NAME, 1)) {
-                    ALOGD("playing clip for part%d, size=%d", (int) i, part.audioLength);
-                    audioplay::playClip(part.audioData, part.audioLength);
-                }
+            if (r == 0 && part.audioData && playSoundsAllowed()) {
+                ALOGD("playing clip for part%d, size=%d", (int) i, part.audioLength);
+                audioplay::playClip(part.audioData, part.audioLength);
             }
 
             glClearColor(
@@ -920,6 +927,30 @@
     return animation;
 }
 
+bool BootAnimation::playSoundsAllowed() const {
+    // Only play sounds for system boots, not runtime restarts.
+    if (!mSystemBoot) {
+        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;
+}
+
 bool BootAnimation::updateIsTimeAccurate() {
     static constexpr long long MAX_TIME_IN_PAST =   60000LL * 60LL * 24LL * 30LL;  // 30 days
     static constexpr long long MAX_TIME_IN_FUTURE = 60000LL * 90LL;  // 90 minutes