diff options
| -rw-r--r-- | cmds/bootanimation/Android.mk | 11 | ||||
| -rw-r--r-- | cmds/bootanimation/iot/BootAction.cpp | 97 | ||||
| -rw-r--r-- | cmds/bootanimation/iot/BootAction.h | 26 | ||||
| -rw-r--r-- | cmds/bootanimation/iot/bootanim_iot.rc | 2 | ||||
| -rw-r--r-- | cmds/bootanimation/iot/iotbootanimation_main.cpp | 4 |
5 files changed, 137 insertions, 3 deletions
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk index 559e8de5ae30..dbd774992031 100644 --- a/cmds/bootanimation/Android.mk +++ b/cmds/bootanimation/Android.mk @@ -24,6 +24,11 @@ LOCAL_SRC_FILES:= \ BootAnimationUtil.cpp \ ifeq ($(PRODUCT_IOT),true) + +LOCAL_SHARED_LIBRARIES += libchrome + +LOCAL_C_INCLUDES += external/libchrome + LOCAL_SRC_FILES += \ iot/iotbootanimation_main.cpp \ iot/BootAction.cpp @@ -84,6 +89,12 @@ LOCAL_SHARED_LIBRARIES := \ libtinyalsa \ libbase +ifeq ($(PRODUCT_IOT),true) + +LOCAL_INIT_RC := iot/bootanim_iot.rc + +endif # PRODUCT_IOT + ifdef TARGET_32_BIT_SURFACEFLINGER LOCAL_32_BIT_ONLY := true endif diff --git a/cmds/bootanimation/iot/BootAction.cpp b/cmds/bootanimation/iot/BootAction.cpp index 889eb2fbabce..2bc73439348b 100644 --- a/cmds/bootanimation/iot/BootAction.cpp +++ b/cmds/bootanimation/iot/BootAction.cpp @@ -18,25 +18,96 @@ #define LOG_TAG "BootAction" +#include <dlfcn.h> +#include <fcntl.h> + +#include <map> + +#include <android-base/file.h> #include <android-base/strings.h> +#include <base/json/json_parser.h> +#include <base/json/json_value_converter.h> #include <cpu-features.h> -#include <dlfcn.h> #include <pio/peripheral_manager_client.h> #include <utils/Log.h> +using android::base::ReadFileToString; +using android::base::RemoveFileIfExists; using android::base::Split; using android::base::Join; using android::base::StartsWith; using android::base::EndsWith; +using base::JSONReader; +using base::Value; namespace android { +// Brightness and volume are stored as integer strings in next_boot.json. +// They are divided by this constant to produce the actual float values in +// range [0.0, 1.0]. This constant must match its counterpart in +// DeviceManager. +constexpr const float kFloatScaleFactor = 1000.0f; + +constexpr const char* kNextBootFile = "/data/misc/bootanimation/next_boot.json"; +constexpr const char* kLastBootFile = "/data/misc/bootanimation/last_boot.json"; + +bool loadParameters(BootAction::SavedBootParameters* parameters) +{ + std::string contents; + if (!ReadFileToString(kLastBootFile, &contents)) { + if (errno != ENOENT) + ALOGE("Unable to read from %s: %s", kLastBootFile, strerror(errno)); + + return false; + } + + std::unique_ptr<Value> json = JSONReader::Read(contents); + if (json.get() == nullptr) return false; + + JSONValueConverter<BootAction::SavedBootParameters> converter; + if (!converter.Convert(*(json.get()), parameters)) return false; + + return true; +} + +void BootAction::SavedBootParameters::RegisterJSONConverter( + JSONValueConverter<SavedBootParameters> *converter) { + converter->RegisterIntField("brightness", &SavedBootParameters::brightness); + converter->RegisterIntField("volume", &SavedBootParameters::volume); + converter->RegisterRepeatedString("param_names", + &SavedBootParameters::param_names); + converter->RegisterRepeatedString("param_values", + &SavedBootParameters::param_values); +} + BootAction::~BootAction() { if (mLibHandle != nullptr) { dlclose(mLibHandle); } } +void BootAction::swapBootConfigs() { + // rename() will fail if next_boot.json doesn't exist, so delete + // last_boot.json manually first. + std::string err; + if (!RemoveFileIfExists(kLastBootFile, &err)) + ALOGE("Unable to delete last boot file: %s", err.c_str()); + + if (rename(kNextBootFile, kLastBootFile) && errno != ENOENT) + ALOGE("Unable to swap boot files: %s", strerror(errno)); + + int fd = open(kNextBootFile, O_CREAT, DEFFILEMODE); + if (fd == -1) { + ALOGE("Unable to create next boot file: %s", strerror(errno)); + } else { + // Make next_boot.json writible to everyone so DeviceManagementService + // can save parameters there. + if (fchmod(fd, DEFFILEMODE)) + ALOGE("Unable to set next boot file permissions: %s", strerror(errno)); + close(fd); + } +} + bool BootAction::init(const std::string& libraryPath) { APeripheralManagerClient* client = nullptr; ALOGD("Connecting to peripheralmanager"); @@ -51,6 +122,28 @@ bool BootAction::init(const std::string& libraryPath) { ALOGD("Peripheralmanager is up."); APeripheralManagerClient_delete(client); + float brightness = -1.0f; + float volume = -1.0f; + std::vector<BootParameter> parameters; + SavedBootParameters saved_parameters; + + if (loadParameters(&saved_parameters)) { + // TODO(b/65462981): Do something with brightness and volume? + brightness = saved_parameters.brightness / kFloatScaleFactor; + volume = saved_parameters.volume / kFloatScaleFactor; + + if (saved_parameters.param_names.size() == saved_parameters.param_values.size()) { + for (size_t i = 0; i < saved_parameters.param_names.size(); i++) { + parameters.push_back({ + .key = saved_parameters.param_names[i]->c_str(), + .value = saved_parameters.param_values[i]->c_str() + }); + } + } else { + ALOGW("Parameter names and values size mismatch"); + } + } + ALOGI("Loading boot action %s", libraryPath.c_str()); mLibHandle = dlopen(libraryPath.c_str(), RTLD_NOW); if (mLibHandle == nullptr) { @@ -82,7 +175,7 @@ bool BootAction::init(const std::string& libraryPath) { } ALOGD("Entering boot_action_init"); - bool result = mLibInit(); + bool 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 495aa4f2180c..d8bff75d7408 100644 --- a/cmds/bootanimation/iot/BootAction.h +++ b/cmds/bootanimation/iot/BootAction.h @@ -17,16 +17,40 @@ #ifndef _BOOTANIMATION_BOOTACTION_H #define _BOOTANIMATION_BOOTACTION_H +#include <map> #include <string> +#include <base/json/json_value_converter.h> #include <utils/RefBase.h> +using base::JSONValueConverter; + namespace android { class BootAction : public RefBase { public: + struct BootParameter { + const char* key; + const char* value; + }; + + struct SavedBootParameters { + int brightness; + int volume; + ScopedVector<std::string> param_names; + ScopedVector<std::string> param_values; + static void RegisterJSONConverter( + JSONValueConverter<SavedBootParameters>* converter); + }; + ~BootAction(); + // Rename next_boot.json to last_boot.json so that we don't repeat + // parameters if there is a crash before the framework comes up. + // TODO(b/65462981): Is this what we want to do? Should we swap in the + // framework instead? + static void swapBootConfigs(); + // libraryPath is a fully qualified path to the target .so library. bool init(const std::string& libraryPath); @@ -41,7 +65,7 @@ public: void shutdown(); private: - typedef bool (*libInit)(); + typedef bool (*libInit)(const BootParameter* parameters, size_t num_parameters); typedef void (*libStartPart)(int partNumber, int playNumber); typedef void (*libShutdown)(); diff --git a/cmds/bootanimation/iot/bootanim_iot.rc b/cmds/bootanimation/iot/bootanim_iot.rc new file mode 100644 index 000000000000..2fc13364b53d --- /dev/null +++ b/cmds/bootanimation/iot/bootanim_iot.rc @@ -0,0 +1,2 @@ +on post-fs-data + mkdir /data/misc/bootanimation 0777 root root diff --git a/cmds/bootanimation/iot/iotbootanimation_main.cpp b/cmds/bootanimation/iot/iotbootanimation_main.cpp index d62478b27638..252748875289 100644 --- a/cmds/bootanimation/iot/iotbootanimation_main.cpp +++ b/cmds/bootanimation/iot/iotbootanimation_main.cpp @@ -80,6 +80,10 @@ private: int main() { setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY); + // TODO(b/65462981): Should we set brightness/volume here in case the boot + // animation is disabled? + BootAction::swapBootConfigs(); + if (bootAnimationDisabled()) { ALOGI("boot animation disabled"); return 0; |