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

Commit 6a307867 authored by David Pursell's avatar David Pursell Committed by Android (Google) Code Review
Browse files

Merge "iot: extract boot parameter logic."

parents 07999f4b 54a8fe4b
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -31,12 +31,13 @@ LOCAL_SHARED_LIBRARIES += \

LOCAL_SRC_FILES += \
    iot/iotbootanimation_main.cpp \
    iot/BootAction.cpp
    iot/BootAction.cpp \
    iot/BootParameters.cpp \

LOCAL_SHARED_LIBRARIES += \
    libandroidthings \
    libbase \
    libbinder
    libbinder \

LOCAL_STATIC_LIBRARIES += cpufeatures

+2 −99
Original line number Diff line number Diff line
@@ -19,96 +19,20 @@
#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 <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) {
bool BootAction::init(const std::string& libraryPath,
                      const std::vector<ABootActionParameter>& parameters) {
    APeripheralManagerClient* client = nullptr;
    ALOGD("Connecting to peripheralmanager");
    // Wait for peripheral manager to come up.
@@ -122,27 +46,6 @@ bool BootAction::init(const std::string& libraryPath) {
    ALOGD("Peripheralmanager is up.");
    APeripheralManagerClient_delete(client);

    float brightness = -1.0f;
    float volume = -1.0f;
    std::vector<ABootActionParameter> 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);
+3 −20
Original line number Diff line number Diff line
@@ -17,38 +17,21 @@
#ifndef _BOOTANIMATION_BOOTACTION_H
#define _BOOTANIMATION_BOOTACTION_H

#include <map>
#include <string>
#include <vector>

#include <base/json/json_value_converter.h>
#include <boot_action/boot_action.h>  // libandroidthings native API.
#include <utils/RefBase.h>

using base::JSONValueConverter;

namespace android {

class BootAction : public RefBase {
public:
    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);
    bool init(const std::string& libraryPath,
              const std::vector<ABootActionParameter>& parameters);

    // The animation is going to start playing partNumber for the playCount'th
    // time, update the action as needed.
+124 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "BootParameters.h"

#define LOG_TAG "BootParameters"

#include <fcntl.h>

#include <string>

#include <android-base/file.h>
#include <base/json/json_parser.h>
#include <base/json/json_reader.h>
#include <base/json/json_value_converter.h>
#include <utils/Log.h>

using android::base::RemoveFileIfExists;
using android::base::ReadFileToString;
using base::JSONReader;
using base::JSONValueConverter;
using base::Value;

namespace android {

namespace {

// 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";

void 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 writable to everyone so DeviceManagementService
        // can save saved_parameters there.
        if (fchmod(fd, DEFFILEMODE))
            ALOGE("Unable to set next boot file permissions: %s", strerror(errno));
        close(fd);
    }
}

}  // namespace

BootParameters::SavedBootParameters::SavedBootParameters()
    : brightness(-kFloatScaleFactor), volume(-kFloatScaleFactor) {}

void BootParameters::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);
}

BootParameters::BootParameters() {
    swapBootConfigs();
    loadParameters();
}

void BootParameters::loadParameters() {
    std::string contents;
    if (!ReadFileToString(kLastBootFile, &contents)) {
        if (errno != ENOENT)
            ALOGE("Unable to read from %s: %s", kLastBootFile, strerror(errno));

        return;
    }

    std::unique_ptr<Value> json = JSONReader::Read(contents);
    if (json.get() == nullptr) {
        return;
    }

    JSONValueConverter<SavedBootParameters> converter;
    if (converter.Convert(*(json.get()), &mRawParameters)) {
        mBrightness = mRawParameters.brightness / kFloatScaleFactor;
        mVolume = mRawParameters.volume / kFloatScaleFactor;

        if (mRawParameters.param_names.size() == mRawParameters.param_values.size()) {
            for (size_t i = 0; i < mRawParameters.param_names.size(); i++) {
                mParameters.push_back({
                        .key = mRawParameters.param_names[i]->c_str(),
                        .value = mRawParameters.param_values[i]->c_str()
                });
            }
        } else {
            ALOGW("Parameter names and values size mismatch");
        }
    }
}

}  // namespace android
+73 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef _BOOTANIMATION_BOOT_PARAMETERS_H_
#define _BOOTANIMATION_BOOT_PARAMETERS_H_

#include <list>
#include <vector>

#include <base/json/json_value_converter.h>
#include <boot_action/boot_action.h>  // libandroidthings native API.

namespace android {

// Provides access to the parameters set by DeviceManager.reboot().
class BootParameters {
public:
    // Constructor loads the parameters for this boot and swaps the param files
    // to clear the parameters for next boot.
    BootParameters();

    // Returns true if volume/brightness were explicitly set on reboot.
    bool hasVolume() const { return mVolume >= 0; }
    bool hasBrightness() const { return mBrightness >= 0; }

    // Returns volume/brightness in [0,1], or -1 if unset.
    float getVolume() const { return mVolume; }
    float getBrightness() const { return mBrightness; }

    // Returns the additional boot parameters that were set on reboot.
    const std::vector<ABootActionParameter>& getParameters() const { return mParameters; }

private:
    // Raw boot saved_parameters loaded from .json.
    struct SavedBootParameters {
        int brightness;
        int volume;
        ScopedVector<std::string> param_names;
        ScopedVector<std::string> param_values;

        SavedBootParameters();
        static void RegisterJSONConverter(
                ::base::JSONValueConverter<SavedBootParameters>* converter);
    };

    void loadParameters();

    float mVolume = -1.f;
    float mBrightness = -1.f;
    std::vector<ABootActionParameter> mParameters;

    // ABootActionParameter is just a raw pointer so we need to keep the
    // original strings around to avoid losing them.
    SavedBootParameters mRawParameters;
};

}  // namespace android


#endif  // _BOOTANIMATION_BOOT_PARAMETERS_H_
Loading