blob: 2cf1c19e9301fd13733c3ce479fccc14b0923369 [file] [log] [blame]
David Pursell54a8fe42017-09-29 16:05:26 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "BootParameters.h"
18
19#define LOG_TAG "BootParameters"
20
Mickey Keeleydfaa9c52018-04-26 15:05:25 -070021#include <errno.h>
David Pursell54a8fe42017-09-29 16:05:26 -070022#include <fcntl.h>
23
David Pursell54a8fe42017-09-29 16:05:26 -070024#include <android-base/file.h>
David Pursell54a8fe42017-09-29 16:05:26 -070025#include <utils/Log.h>
26
David Pursell54a8fe42017-09-29 16:05:26 -070027using android::base::ReadFileToString;
Mickey Keeley1ffcc5e2018-05-07 09:42:19 -070028using android::base::RemoveFileIfExists;
Mickey Keeleydfaa9c52018-04-26 15:05:25 -070029using Json::Reader;
30using Json::Value;
David Pursell54a8fe42017-09-29 16:05:26 -070031
32namespace android {
33
34namespace {
35
Mickey Keeley1ffcc5e2018-05-07 09:42:19 -070036// Keys for supporting a silent boot and user-defined BootAction parameters.
37constexpr const char *kKeySilentBoot = "silent_boot";
Mickey Keeleydfaa9c52018-04-26 15:05:25 -070038constexpr const char* kKeyParams = "params";
David Pursell54a8fe42017-09-29 16:05:26 -070039
40constexpr const char* kNextBootFile = "/data/misc/bootanimation/next_boot.json";
41constexpr const char* kLastBootFile = "/data/misc/bootanimation/last_boot.json";
42
43void swapBootConfigs() {
44 // rename() will fail if next_boot.json doesn't exist, so delete
45 // last_boot.json manually first.
46 std::string err;
47 if (!RemoveFileIfExists(kLastBootFile, &err))
48 ALOGE("Unable to delete last boot file: %s", err.c_str());
49
50 if (rename(kNextBootFile, kLastBootFile) && errno != ENOENT)
51 ALOGE("Unable to swap boot files: %s", strerror(errno));
52
53 int fd = open(kNextBootFile, O_CREAT, DEFFILEMODE);
54 if (fd == -1) {
55 ALOGE("Unable to create next boot file: %s", strerror(errno));
56 } else {
57 // Make next_boot.json writable to everyone so DeviceManagementService
58 // can save saved_parameters there.
59 if (fchmod(fd, DEFFILEMODE))
60 ALOGE("Unable to set next boot file permissions: %s", strerror(errno));
61 close(fd);
62 }
63}
64
65} // namespace
66
David Pursell54a8fe42017-09-29 16:05:26 -070067BootParameters::BootParameters() {
68 swapBootConfigs();
69 loadParameters();
70}
71
72void BootParameters::loadParameters() {
73 std::string contents;
74 if (!ReadFileToString(kLastBootFile, &contents)) {
75 if (errno != ENOENT)
76 ALOGE("Unable to read from %s: %s", kLastBootFile, strerror(errno));
77
78 return;
79 }
80
Mickey Keeley953f1092018-04-26 11:06:06 -070081 loadParameters(contents);
82}
83
Mickey Keeley1ffcc5e2018-05-07 09:42:19 -070084// If the boot parameters -
85// - File is missing, we assume a normal, non-silent boot.
86// - Are well-formed, initially assume a normal, non-silent boot and parse.
Mickey Keeley953f1092018-04-26 11:06:06 -070087void BootParameters::loadParameters(const std::string& raw_json) {
Mickey Keeleydfaa9c52018-04-26 15:05:25 -070088 if (!Reader().parse(raw_json, mJson)) {
89 return;
90 }
David Pursell54a8fe42017-09-29 16:05:26 -070091
Mickey Keeley1ffcc5e2018-05-07 09:42:19 -070092 parseBootParameters();
93}
David Pursell54a8fe42017-09-29 16:05:26 -070094
Mickey Keeley1ffcc5e2018-05-07 09:42:19 -070095void BootParameters::parseBootParameters() {
96 // A missing key returns a safe, missing value.
97 // Ignore invalid or missing JSON parameters.
98 Value &jsonValue = mJson[kKeySilentBoot];
99 if (jsonValue.isBool()) {
100 mIsSilentBoot = jsonValue.asBool();
David Pursell54a8fe42017-09-29 16:05:26 -0700101 }
Mickey Keeley1ffcc5e2018-05-07 09:42:19 -0700102
103 jsonValue = mJson[kKeyParams];
104 if (jsonValue.isObject()) {
105 // getMemberNames returns a copy of the keys which must be stored.
106 mKeys = jsonValue.getMemberNames();
107 for (auto &key : mKeys) {
108 Value &value = jsonValue[key];
109 if (value.isString()) {
110 mParameters.push_back(
111 {.key = key.c_str(), .value = value.asCString()});
112 }
113 }
114 }
David Pursell54a8fe42017-09-29 16:05:26 -0700115}
116
117} // namespace android