BootParameters: Support silent boot.

* If it's a silent boot, call boot_action_silent_boot from lib.
* Otherwise, boot normally (e.g. with callbacks).

Bug: 78525346
Test: Master (sdk_google_iot_x86) builds and validated on oc-mr1-iot-dev,
* With no boot parameters, the boot is not silent,
* With normal parameters, the boot is not silent.
* With silent parameters, the boot is silent.
* With test bootactions lib, verify lib is loaded and non-silent boot
follows expected sequence and a silent boot calls
boot_action_silent_boot.

In all cases above, sample parameters are preserved.

Change-Id: I74bc9b5262fc4a181339da50726b415c3e4d3398
diff --git a/cmds/bootanimation/iot/BootAction.cpp b/cmds/bootanimation/iot/BootAction.cpp
index 7b4ef72..8b55147 100644
--- a/cmds/bootanimation/iot/BootAction.cpp
+++ b/cmds/bootanimation/iot/BootAction.cpp
@@ -32,7 +32,7 @@
 }
 
 bool BootAction::init(const std::string& libraryPath,
-                      const std::vector<ABootActionParameter>& parameters) {
+                      const std::unique_ptr<BootParameters>& bootParameters) {
     APeripheralManagerClient* client = nullptr;
     ALOGD("Connecting to peripheralmanager");
     // Wait for peripheral manager to come up.
@@ -77,9 +77,32 @@
         mLibStartPart = reinterpret_cast<libStartPart>(loaded);
     }
 
-    ALOGD("Entering boot_action_init");
-    bool result = mLibInit(parameters.data(), parameters.size());
-    ALOGD("Returned from boot_action_init");
+    // SilentBoot is considered optional, if it isn't exported by the library
+    // and the boot is silent, no method is called.
+    loaded = nullptr;
+    if (!loadSymbol("boot_action_silent_boot", &loaded) || loaded == nullptr) {
+        ALOGW("No boot_action_silent_boot found, boot action will not be "
+              "executed during a silent boot.");
+    } else {
+        mLibSilentBoot = reinterpret_cast<libInit>(loaded);
+    }
+
+    bool result = true;
+    const auto& parameters = bootParameters->getParameters();
+    if (bootParameters->isSilentBoot()) {
+        if (mLibSilentBoot != nullptr) {
+            ALOGD("Entering boot_action_silent_boot");
+            result = mLibSilentBoot(parameters.data(), parameters.size());
+            ALOGD("Returned from boot_action_silent_boot");
+        } else {
+            ALOGW("Skipping missing boot_action_silent_boot");
+        }
+    } else {
+        ALOGD("Entering boot_action_init");
+        result = mLibInit(parameters.data(), parameters.size());
+        ALOGD("Returned from boot_action_init");
+    }
+
     return result;
 }
 
diff --git a/cmds/bootanimation/iot/BootAction.h b/cmds/bootanimation/iot/BootAction.h
index 5e2495f..7119c35 100644
--- a/cmds/bootanimation/iot/BootAction.h
+++ b/cmds/bootanimation/iot/BootAction.h
@@ -20,6 +20,8 @@
 #include <string>
 #include <vector>
 
+#include "BootParameters.h"
+
 #include <boot_action/boot_action.h>  // libandroidthings native API.
 #include <utils/RefBase.h>
 
@@ -31,7 +33,7 @@
 
     // libraryPath is a fully qualified path to the target .so library.
     bool init(const std::string& libraryPath,
-              const std::vector<ABootActionParameter>& parameters);
+              const std::unique_ptr<BootParameters>& bootParameters);
 
     // The animation is going to start playing partNumber for the playCount'th
     // time, update the action as needed.
@@ -45,7 +47,7 @@
 
 private:
     typedef bool (*libInit)(const ABootActionParameter* parameters,
-                            size_t num_parameters);
+                            size_t numParameters);
     typedef void (*libStartPart)(int partNumber, int playNumber);
     typedef void (*libShutdown)();
 
@@ -55,6 +57,9 @@
     libInit mLibInit = nullptr;
     libStartPart mLibStartPart = nullptr;
     libShutdown mLibShutdown = nullptr;
+
+    // Called only if the boot is silent.
+    libInit mLibSilentBoot = nullptr;
 };
 
 }  // namespace android
diff --git a/cmds/bootanimation/iot/iotbootanimation_main.cpp b/cmds/bootanimation/iot/iotbootanimation_main.cpp
index 00cef43..2a3d376 100644
--- a/cmds/bootanimation/iot/iotbootanimation_main.cpp
+++ b/cmds/bootanimation/iot/iotbootanimation_main.cpp
@@ -59,7 +59,7 @@
         }
 
         mBootAction = new BootAction();
-        if (!mBootAction->init(library_path, mBootParameters->getParameters())) {
+        if (!mBootAction->init(library_path, mBootParameters)) {
             mBootAction = NULL;
         }
     };
@@ -116,8 +116,16 @@
     sp<ProcessState> proc(ProcessState::self());
     ProcessState::self()->startThreadPool();
 
-    sp<BootAnimation> boot = new BootAnimation(
-            new BootActionAnimationCallbacks(std::move(bootParameters)));
+    bool isSilentBoot = bootParameters->isSilentBoot();
+    sp<BootActionAnimationCallbacks> callbacks =
+        new BootActionAnimationCallbacks(std::move(bootParameters));
+
+    // On silent boot, animations aren't displayed.
+    if (isSilentBoot) {
+        callbacks->init({});
+    } else {
+        sp<BootAnimation> boot = new BootAnimation(callbacks);
+    }
 
     IPCThreadState::self()->joinThreadPool();
     return 0;