Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6dd64f3a authored by Braden Kell's avatar Braden Kell
Browse files

Pass saved parameters to boot action

Bug: http://b/65462981
Test: Parameters in next_boot.json are passed to
      boot action; next_boot.json is moved to
      last_boot.json to allow reading by
      DeviceManagementService.

Change-Id: Ie290711ea48a3a221cfad2e9266215b76631ecbd
parent c2840f9f
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -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
+95 −2
Original line number Diff line number Diff line
@@ -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;
}
+25 −1
Original line number Diff line number Diff line
@@ -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)();

+2 −0
Original line number Diff line number Diff line
on post-fs-data
    mkdir /data/misc/bootanimation 0777 root root
+4 −0
Original line number Diff line number Diff line
@@ -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;