154a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell/*
254a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell * Copyright (C) 2017 The Android Open Source Project
354a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell *
454a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell * Licensed under the Apache License, Version 2.0 (the "License");
554a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell * you may not use this file except in compliance with the License.
654a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell * You may obtain a copy of the License at
754a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell *
854a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell *      http://www.apache.org/licenses/LICENSE-2.0
954a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell *
1054a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell * Unless required by applicable law or agreed to in writing, software
1154a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell * distributed under the License is distributed on an "AS IS" BASIS,
1254a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1354a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell * See the License for the specific language governing permissions and
1454a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell * limitations under the License.
1554a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell */
1654a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
1754a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell#include "BootParameters.h"
1854a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
1954a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell#define LOG_TAG "BootParameters"
2054a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
2154a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell#include <fcntl.h>
2254a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
2354a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell#include <string>
2454a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
2554a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell#include <android-base/file.h>
2654a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell#include <base/json/json_parser.h>
2754a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell#include <base/json/json_reader.h>
2854a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell#include <base/json/json_value_converter.h>
2954a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell#include <utils/Log.h>
3054a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
3154a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursellusing android::base::RemoveFileIfExists;
3254a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursellusing android::base::ReadFileToString;
3354a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursellusing base::JSONReader;
3454a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursellusing base::JSONValueConverter;
3554a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursellusing base::Value;
3654a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
3754a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursellnamespace android {
3854a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
3954a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursellnamespace {
4054a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
4154a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell// Brightness and volume are stored as integer strings in next_boot.json.
4254a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell// They are divided by this constant to produce the actual float values in
4354a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell// range [0.0, 1.0]. This constant must match its counterpart in
4454a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell// DeviceManager.
4554a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursellconstexpr const float kFloatScaleFactor = 1000.0f;
4654a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
4754a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursellconstexpr const char* kNextBootFile = "/data/misc/bootanimation/next_boot.json";
4854a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursellconstexpr const char* kLastBootFile = "/data/misc/bootanimation/last_boot.json";
4954a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
5054a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursellvoid swapBootConfigs() {
5154a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    // rename() will fail if next_boot.json doesn't exist, so delete
5254a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    // last_boot.json manually first.
5354a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    std::string err;
5454a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    if (!RemoveFileIfExists(kLastBootFile, &err))
5554a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell        ALOGE("Unable to delete last boot file: %s", err.c_str());
5654a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
5754a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    if (rename(kNextBootFile, kLastBootFile) && errno != ENOENT)
5854a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell        ALOGE("Unable to swap boot files: %s", strerror(errno));
5954a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
6054a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    int fd = open(kNextBootFile, O_CREAT, DEFFILEMODE);
6154a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    if (fd == -1) {
6254a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell        ALOGE("Unable to create next boot file: %s", strerror(errno));
6354a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    } else {
6454a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell        // Make next_boot.json writable to everyone so DeviceManagementService
6554a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell        // can save saved_parameters there.
6654a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell        if (fchmod(fd, DEFFILEMODE))
6754a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell            ALOGE("Unable to set next boot file permissions: %s", strerror(errno));
6854a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell        close(fd);
6954a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    }
7054a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell}
7154a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
7254a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell}  // namespace
7354a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
7454a8fe4bbe446bdc394ef87e52252fcc1c031db1David PursellBootParameters::SavedBootParameters::SavedBootParameters()
7554a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    : brightness(-kFloatScaleFactor), volume(-kFloatScaleFactor) {}
7654a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
7754a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursellvoid BootParameters::SavedBootParameters::RegisterJSONConverter(
7854a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell        JSONValueConverter<SavedBootParameters>* converter) {
7954a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    converter->RegisterIntField("brightness", &SavedBootParameters::brightness);
8054a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    converter->RegisterIntField("volume", &SavedBootParameters::volume);
8154a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    converter->RegisterRepeatedString("param_names",
8254a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell                                      &SavedBootParameters::param_names);
8354a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    converter->RegisterRepeatedString("param_values",
8454a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell                                      &SavedBootParameters::param_values);
8554a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell}
8654a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
8754a8fe4bbe446bdc394ef87e52252fcc1c031db1David PursellBootParameters::BootParameters() {
8854a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    swapBootConfigs();
8954a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    loadParameters();
9054a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell}
9154a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
9254a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursellvoid BootParameters::loadParameters() {
9354a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    std::string contents;
9454a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    if (!ReadFileToString(kLastBootFile, &contents)) {
9554a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell        if (errno != ENOENT)
9654a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell            ALOGE("Unable to read from %s: %s", kLastBootFile, strerror(errno));
9754a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
9854a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell        return;
9954a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    }
10054a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
10154a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    std::unique_ptr<Value> json = JSONReader::Read(contents);
10254a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    if (json.get() == nullptr) {
10354a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell        return;
10454a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    }
10554a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
10654a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    JSONValueConverter<SavedBootParameters> converter;
10754a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    if (converter.Convert(*(json.get()), &mRawParameters)) {
10854a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell        mBrightness = mRawParameters.brightness / kFloatScaleFactor;
10954a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell        mVolume = mRawParameters.volume / kFloatScaleFactor;
11054a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
11154a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell        if (mRawParameters.param_names.size() == mRawParameters.param_values.size()) {
11254a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell            for (size_t i = 0; i < mRawParameters.param_names.size(); i++) {
11354a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell                mParameters.push_back({
11454a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell                        .key = mRawParameters.param_names[i]->c_str(),
11554a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell                        .value = mRawParameters.param_values[i]->c_str()
11654a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell                });
11754a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell            }
11854a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell        } else {
11954a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell            ALOGW("Parameter names and values size mismatch");
12054a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell        }
12154a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell    }
12254a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell}
12354a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell
12454a8fe4bbe446bdc394ef87e52252fcc1c031db1David Pursell}  // namespace android
125