support shutdown animation from bootanim

- init will set sys.powerctl property and run bootanim.
- Use /oem/media/shutdownanimation.zip or
  /system/media/shutdownanimation.zip for animation file.
  If none of them exist, android animation will be used.
- Disable audio playing for shutdown animation.
- Disable TimeCheckThread for shutdown animation. It
  accesses /data partition and can block umount.

bug: 36526187
Test: many reboots

Change-Id: If02c73cda2015317d88d056cd45201208da49946
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index a6d2986..2435ffa 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -38,6 +38,8 @@
 #include <utils/Log.h>
 #include <utils/SystemClock.h>
 
+#include <android-base/properties.h>
+
 #include <ui/PixelFormat.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
@@ -67,6 +69,9 @@
 static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip";
 static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";
 static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip";
+static const char OEM_SHUTDOWNANIMATION_FILE[] = "/oem/media/shutdownanimation.zip";
+static const char SYSTEM_SHUTDOWNANIMATION_FILE[] = "/system/media/shutdownanimation.zip";
+
 static const char SYSTEM_DATA_DIR_PATH[] = "/data/system";
 static const char SYSTEM_TIME_DIR_NAME[] = "time";
 static const char SYSTEM_TIME_DIR_PATH[] = "/data/system/time";
@@ -106,7 +111,13 @@
     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);
+    mSystemBoot = !android::base::GetBoolProperty(BOOT_COMPLETED_PROP_NAME, false);
+    std::string powerCtl = android::base::GetProperty("sys.powerctl", "");
+    if (powerCtl.empty()) {
+        mShuttingDown = false;
+    } else {
+        mShuttingDown = true;
+    }
 }
 
 void BootAnimation::onFirstRef() {
@@ -314,16 +325,23 @@
     char decrypt[PROPERTY_VALUE_MAX];
     property_get("vold.decrypt", decrypt, "");
 
-    bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt);
+    bool encryptedAnimation = atoi(decrypt) != 0 ||
+        !strcmp("trigger_restart_min_framework", decrypt);
 
-    if (encryptedAnimation && (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0)) {
+    if (!mShuttingDown && encryptedAnimation &&
+        (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0)) {
         mZipFileName = SYSTEM_ENCRYPTED_BOOTANIMATION_FILE;
+        return NO_ERROR;
     }
-    else if (access(OEM_BOOTANIMATION_FILE, R_OK) == 0) {
-        mZipFileName = OEM_BOOTANIMATION_FILE;
-    }
-    else if (access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) {
-        mZipFileName = SYSTEM_BOOTANIMATION_FILE;
+    static const char* bootFiles[] = {OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE};
+    static const char* shutdownFiles[] =
+        {OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE};
+
+    for (const char* f : (!mShuttingDown ? bootFiles : shutdownFiles)) {
+        if (access(f, R_OK) == 0) {
+            mZipFileName = f;
+            return NO_ERROR;
+        }
     }
     return NO_ERROR;
 }
@@ -1047,7 +1065,9 @@
     if (!mSystemBoot) {
         return false;
     }
-
+    if (mShuttingDown) { // no audio while shutting down
+        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)) {
@@ -1073,7 +1093,7 @@
     if (mTimeIsAccurate) {
         return true;
     }
-
+    if (mShuttingDown) return true;
     struct stat statResult;
 
     if(stat(TIME_FORMAT_12_HOUR_FLAG_FILE_PATH, &statResult) == 0) {