Loading cmds/bootanimation/Android.mk +11 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading cmds/bootanimation/iot/BootAction.cpp +95 −2 Original line number Diff line number Diff line Loading @@ -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"); Loading @@ -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) { Loading Loading @@ -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; } Loading cmds/bootanimation/iot/BootAction.h +25 −1 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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)(); Loading cmds/bootanimation/iot/bootanim_iot.rc 0 → 100644 +2 −0 Original line number Diff line number Diff line on post-fs-data mkdir /data/misc/bootanimation 0777 root root cmds/bootanimation/iot/iotbootanimation_main.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading
cmds/bootanimation/Android.mk +11 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 Loading
cmds/bootanimation/iot/BootAction.cpp +95 −2 Original line number Diff line number Diff line Loading @@ -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"); Loading @@ -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) { Loading Loading @@ -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; } Loading
cmds/bootanimation/iot/BootAction.h +25 −1 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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)(); Loading
cmds/bootanimation/iot/bootanim_iot.rc 0 → 100644 +2 −0 Original line number Diff line number Diff line on post-fs-data mkdir /data/misc/bootanimation 0777 root root
cmds/bootanimation/iot/iotbootanimation_main.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -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; Loading