blob: fc6e1dc3f65852e2df50c683ba29f4d1c3cae68d [file] [log] [blame]
Alex Deymo40d86b22015-09-03 22:27:10 -07001//
2// Copyright (C) 2015 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
Alex Deymo1b03f9f2015-12-09 00:38:36 -080017#include "update_engine/hardware_android.h"
Alex Deymo40d86b22015-09-03 22:27:10 -070018
Alex Deymofb905d92016-06-03 19:26:58 -070019#include <sys/types.h>
Yifan Hongfd6640f2020-08-27 19:13:17 -070020#include <sys/utsname.h>
Alex Deymofb905d92016-06-03 19:26:58 -070021
Tom Cherryfadd03c2017-10-10 14:45:09 -070022#include <memory>
Kelvin Zhangd7191032020-08-11 10:48:16 -040023#include <string>
24#include <string_view>
Alex Deymofb905d92016-06-03 19:26:58 -070025
Yifan Hong126d13e2020-09-21 19:50:06 -070026#include <android/sysprop/GkiProperties.sysprop.h>
Kelvin Zhangd7191032020-08-11 10:48:16 -040027#include <android-base/parseint.h>
Tom Cherryfadd03c2017-10-10 14:45:09 -070028#include <android-base/properties.h>
Alex Deymodd132f32015-09-14 19:12:07 -070029#include <base/files/file_util.h>
Tao Bao304680c2018-03-31 10:36:52 -070030#include <bootloader_message/bootloader_message.h>
Yifan Hongfd6640f2020-08-27 19:13:17 -070031#include <kver/kernel_release.h>
32#include <kver/utils.h>
Alex Deymo40d86b22015-09-03 22:27:10 -070033
Yifan Hong87029332020-09-01 17:20:08 -070034#include "update_engine/common/error_code_utils.h"
Alex Deymo39910dc2015-11-09 17:04:30 -080035#include "update_engine/common/hardware.h"
Sen Jiang9c123462015-11-19 13:16:23 -080036#include "update_engine/common/platform_constants.h"
Kelvin Zhangd7191032020-08-11 10:48:16 -040037#include "update_engine/common/utils.h"
Alex Deymo40d86b22015-09-03 22:27:10 -070038
Tom Cherryfadd03c2017-10-10 14:45:09 -070039using android::base::GetBoolProperty;
40using android::base::GetIntProperty;
41using android::base::GetProperty;
Yifan Hongfd6640f2020-08-27 19:13:17 -070042using android::kver::IsKernelUpdateValid;
43using android::kver::KernelRelease;
Alex Deymo40d86b22015-09-03 22:27:10 -070044using std::string;
45
46namespace chromeos_update_engine {
47
Alex Deymofb905d92016-06-03 19:26:58 -070048namespace {
49
Alex Deymoebf6e122017-03-10 16:12:01 -080050// Android properties that identify the hardware and potentially non-updatable
51// parts of the bootloader (such as the bootloader version and the baseband
52// version).
53const char kPropBootBootloader[] = "ro.boot.bootloader";
54const char kPropBootBaseband[] = "ro.boot.baseband";
55const char kPropProductManufacturer[] = "ro.product.manufacturer";
56const char kPropBootHardwareSKU[] = "ro.boot.hardware.sku";
57const char kPropBootRevision[] = "ro.boot.revision";
Sen Jiang5011df62017-06-28 17:13:19 -070058const char kPropBuildDateUTC[] = "ro.build.date.utc";
Alex Deymoebf6e122017-03-10 16:12:01 -080059
Yifan Hongfd6640f2020-08-27 19:13:17 -070060string GetPartitionBuildDate(const string& partition_name) {
61 return android::base::GetProperty("ro." + partition_name + ".build.date.utc",
62 "");
63}
64
Alex Deymofb905d92016-06-03 19:26:58 -070065} // namespace
66
Alex Deymo40d86b22015-09-03 22:27:10 -070067namespace hardware {
68
69// Factory defined in hardware.h.
70std::unique_ptr<HardwareInterface> CreateHardware() {
Ben Chanab5a0af2017-10-12 14:57:50 -070071 return std::make_unique<HardwareAndroid>();
Alex Deymo40d86b22015-09-03 22:27:10 -070072}
73
74} // namespace hardware
75
Alex Deymo1c4e84a2015-09-22 16:58:10 -070076// In Android there are normally three kinds of builds: eng, userdebug and user.
77// These builds target respectively a developer build, a debuggable version of
78// the final product and the pristine final product the end user will run.
79// Apart from the ro.build.type property name, they differ in the following
80// properties that characterize the builds:
81// * eng builds: ro.secure=0 and ro.debuggable=1
82// * userdebug builds: ro.secure=1 and ro.debuggable=1
83// * user builds: ro.secure=1 and ro.debuggable=0
84//
85// See IsOfficialBuild() and IsNormalMode() for the meaning of these options in
86// Android.
87
Alex Deymo40d86b22015-09-03 22:27:10 -070088bool HardwareAndroid::IsOfficialBuild() const {
Alex Deymo1c4e84a2015-09-22 16:58:10 -070089 // We run an official build iff ro.secure == 1, because we expect the build to
90 // behave like the end user product and check for updates. Note that while
91 // developers are able to build "official builds" by just running "make user",
92 // that will only result in a more restrictive environment. The important part
93 // is that we don't produce and push "non-official" builds to the end user.
94 //
95 // In case of a non-bool value, we take the most restrictive option and
96 // assume we are in an official-build.
Tom Cherryfadd03c2017-10-10 14:45:09 -070097 return GetBoolProperty("ro.secure", true);
Alex Deymo40d86b22015-09-03 22:27:10 -070098}
99
100bool HardwareAndroid::IsNormalBootMode() const {
Alex Deymo1c4e84a2015-09-22 16:58:10 -0700101 // We are running in "dev-mode" iff ro.debuggable == 1. In dev-mode the
102 // update_engine will allow extra developers options, such as providing a
103 // different update URL. In case of error, we assume the build is in
104 // normal-mode.
Tom Cherryfadd03c2017-10-10 14:45:09 -0700105 return !GetBoolProperty("ro.debuggable", false);
Alex Deymo40d86b22015-09-03 22:27:10 -0700106}
107
Sen Jiange67bb5b2016-06-20 15:53:56 -0700108bool HardwareAndroid::AreDevFeaturesEnabled() const {
109 return !IsNormalBootMode();
110}
111
Alex Deymo46a9aae2016-05-04 20:20:11 -0700112bool HardwareAndroid::IsOOBEEnabled() const {
113 // No OOBE flow blocking updates for Android-based boards.
114 return false;
115}
116
Alex Deymo40d86b22015-09-03 22:27:10 -0700117bool HardwareAndroid::IsOOBEComplete(base::Time* out_time_of_oobe) const {
Alex Deymo46a9aae2016-05-04 20:20:11 -0700118 LOG(WARNING) << "OOBE is not enabled but IsOOBEComplete() called.";
Alex Deymo4d2990d2015-09-15 12:11:26 -0700119 if (out_time_of_oobe)
120 *out_time_of_oobe = base::Time();
Alex Deymo40d86b22015-09-03 22:27:10 -0700121 return true;
122}
123
124string HardwareAndroid::GetHardwareClass() const {
Tom Cherryfadd03c2017-10-10 14:45:09 -0700125 auto manufacturer = GetProperty(kPropProductManufacturer, "");
126 auto sku = GetProperty(kPropBootHardwareSKU, "");
127 auto revision = GetProperty(kPropBootRevision, "");
Alex Deymoebf6e122017-03-10 16:12:01 -0800128
Tom Cherryfadd03c2017-10-10 14:45:09 -0700129 return manufacturer + ":" + sku + ":" + revision;
Alex Deymo40d86b22015-09-03 22:27:10 -0700130}
131
132string HardwareAndroid::GetFirmwareVersion() const {
Tom Cherryfadd03c2017-10-10 14:45:09 -0700133 return GetProperty(kPropBootBootloader, "");
Alex Deymo40d86b22015-09-03 22:27:10 -0700134}
135
136string HardwareAndroid::GetECVersion() const {
Tom Cherryfadd03c2017-10-10 14:45:09 -0700137 return GetProperty(kPropBootBaseband, "");
Alex Deymo40d86b22015-09-03 22:27:10 -0700138}
139
Matt Ziegelbaumaa8e1a42019-05-09 21:41:58 -0400140string HardwareAndroid::GetDeviceRequisition() const {
141 LOG(WARNING) << "STUB: Getting requisition is not supported.";
142 return "";
143}
144
Zentaro Kavanaghbaacb982018-02-20 17:48:39 -0800145int HardwareAndroid::GetMinKernelKeyVersion() const {
146 LOG(WARNING) << "STUB: No Kernel key version is available.";
147 return -1;
148}
149
Marton Hunyady99ced782018-05-08 12:59:50 +0200150int HardwareAndroid::GetMinFirmwareKeyVersion() const {
151 LOG(WARNING) << "STUB: No Firmware key version is available.";
152 return -1;
153}
154
Zentaro Kavanagh8f6f2432018-05-16 13:48:12 -0700155int HardwareAndroid::GetMaxFirmwareKeyRollforward() const {
156 LOG(WARNING) << "STUB: Getting firmware_max_rollforward is not supported.";
157 return -1;
158}
159
160bool HardwareAndroid::SetMaxFirmwareKeyRollforward(
161 int firmware_max_rollforward) {
162 LOG(WARNING) << "STUB: Setting firmware_max_rollforward is not supported.";
163 return false;
164}
165
Zentaro Kavanagh5d956152018-05-15 09:40:33 -0700166bool HardwareAndroid::SetMaxKernelKeyRollforward(int kernel_max_rollforward) {
167 LOG(WARNING) << "STUB: Setting kernel_max_rollforward is not supported.";
Zentaro Kavanaghbaacb982018-02-20 17:48:39 -0800168 return false;
169}
170
Alex Deymo40d86b22015-09-03 22:27:10 -0700171int HardwareAndroid::GetPowerwashCount() const {
172 LOG(WARNING) << "STUB: Assuming no factory reset was performed.";
173 return 0;
174}
175
Zentaro Kavanagh28def4f2019-01-15 17:15:01 -0800176bool HardwareAndroid::SchedulePowerwash(bool save_rollback_data) {
Alex Deymofb905d92016-06-03 19:26:58 -0700177 LOG(INFO) << "Scheduling a powerwash to BCB.";
Zentaro Kavanagh28def4f2019-01-15 17:15:01 -0800178 LOG_IF(WARNING, save_rollback_data) << "save_rollback_data was true but "
179 << "isn't supported.";
Sen Jiangd944faa2018-08-22 18:46:39 -0700180 string err;
181 if (!update_bootloader_message({"--wipe_data", "--reason=wipe_data_from_ota"},
182 &err)) {
183 LOG(ERROR) << "Failed to update bootloader message: " << err;
184 return false;
185 }
186 return true;
Alex Deymofb905d92016-06-03 19:26:58 -0700187}
188
189bool HardwareAndroid::CancelPowerwash() {
Sen Jiangd944faa2018-08-22 18:46:39 -0700190 string err;
191 if (!clear_bootloader_message(&err)) {
192 LOG(ERROR) << "Failed to clear bootloader message: " << err;
193 return false;
194 }
195 return true;
Alex Deymofb905d92016-06-03 19:26:58 -0700196}
197
Alex Deymodd132f32015-09-14 19:12:07 -0700198bool HardwareAndroid::GetNonVolatileDirectory(base::FilePath* path) const {
Sen Jiang9c123462015-11-19 13:16:23 -0800199 base::FilePath local_path(constants::kNonVolatileDirectory);
Kelvin Zhangd2822522020-07-07 17:20:58 -0400200 if (!base::DirectoryExists(local_path)) {
Alex Deymodd132f32015-09-14 19:12:07 -0700201 LOG(ERROR) << "Non-volatile directory not found: " << local_path.value();
202 return false;
203 }
204 *path = local_path;
205 return true;
206}
207
208bool HardwareAndroid::GetPowerwashSafeDirectory(base::FilePath* path) const {
209 // On Android, we don't have a directory persisted across powerwash.
210 return false;
211}
212
Sen Jiang5011df62017-06-28 17:13:19 -0700213int64_t HardwareAndroid::GetBuildTimestamp() const {
Tom Cherryfadd03c2017-10-10 14:45:09 -0700214 return GetIntProperty<int64_t>(kPropBuildDateUTC, 0);
Sen Jiang5011df62017-06-28 17:13:19 -0700215}
216
Tianjie Xu4ad3af62019-10-30 11:59:45 -0700217// Returns true if the device runs an userdebug build, and explicitly allows OTA
218// downgrade.
219bool HardwareAndroid::AllowDowngrade() const {
220 return GetBoolProperty("ro.ota.allow_downgrade", false) &&
221 GetBoolProperty("ro.debuggable", false);
222}
223
Amin Hassani1677e812017-06-21 13:36:36 -0700224bool HardwareAndroid::GetFirstActiveOmahaPingSent() const {
225 LOG(WARNING) << "STUB: Assuming first active omaha was never set.";
226 return false;
227}
228
Amin Hassani80f4d4c2018-05-16 13:34:00 -0700229bool HardwareAndroid::SetFirstActiveOmahaPingSent() {
230 LOG(WARNING) << "STUB: Assuming first active omaha is set.";
231 // We will set it true, so its failure doesn't cause escalation.
232 return true;
Amin Hassani1677e812017-06-21 13:36:36 -0700233}
234
Tianjie Xud6aa91f2019-11-14 11:55:10 -0800235void HardwareAndroid::SetWarmReset(bool warm_reset) {
236 constexpr char warm_reset_prop[] = "ota.warm_reset";
237 if (!android::base::SetProperty(warm_reset_prop, warm_reset ? "1" : "0")) {
238 LOG(WARNING) << "Failed to set prop " << warm_reset_prop;
239 }
240}
241
Yifan Hongfd6640f2020-08-27 19:13:17 -0700242string HardwareAndroid::GetVersionForLogging(
243 const string& partition_name) const {
244 if (partition_name == "boot") {
245 struct utsname buf;
246 if (uname(&buf) != 0) {
247 PLOG(ERROR) << "Unable to call uname()";
248 return "";
249 }
250 auto kernel_release =
251 KernelRelease::Parse(buf.release, true /* allow_suffix */);
252 return kernel_release.has_value() ? kernel_release->string() : "";
253 }
254 return GetPartitionBuildDate(partition_name);
Kelvin Zhangd7191032020-08-11 10:48:16 -0400255}
256
Yifan Hong87029332020-09-01 17:20:08 -0700257ErrorCode HardwareAndroid::IsPartitionUpdateValid(
Yifan Hongfd6640f2020-08-27 19:13:17 -0700258 const string& partition_name, const string& new_version) const {
259 if (partition_name == "boot") {
260 struct utsname buf;
261 if (uname(&buf) != 0) {
262 PLOG(ERROR) << "Unable to call uname()";
263 return ErrorCode::kError;
264 }
Yifan Hong126d13e2020-09-21 19:50:06 -0700265 bool prevent_downgrade =
266 android::sysprop::GkiProperties::prevent_downgrade_version().value_or(
267 false);
268 return IsKernelUpdateValid(buf.release, new_version, prevent_downgrade);
Yifan Hongfd6640f2020-08-27 19:13:17 -0700269 }
270
271 const auto old_version = GetPartitionBuildDate(partition_name);
Kelvin Zhangd7191032020-08-11 10:48:16 -0400272 // TODO(zhangkelvin) for some partitions, missing a current timestamp should
273 // be an error, e.g. system, vendor, product etc.
Yifan Hong87029332020-09-01 17:20:08 -0700274 auto error_code = utils::IsTimestampNewer(old_version, new_version);
275 if (error_code != ErrorCode::kSuccess) {
276 LOG(ERROR) << "Timestamp check failed with "
277 << utils::ErrorCodeToString(error_code)
278 << " Partition timestamp: " << old_version
Kelvin Zhangd7191032020-08-11 10:48:16 -0400279 << " Update timestamp: " << new_version;
280 }
Yifan Hong87029332020-09-01 17:20:08 -0700281 return error_code;
Kelvin Zhangd7191032020-08-11 10:48:16 -0400282}
283
Yifan Hongfd6640f2020-08-27 19:13:17 -0700284ErrorCode HardwareAndroid::IsKernelUpdateValid(const string& old_release,
Yifan Hong126d13e2020-09-21 19:50:06 -0700285 const string& new_release,
286 bool prevent_downgrade) {
Yifan Hongfd6640f2020-08-27 19:13:17 -0700287 // Check that the package either contain an empty version (indicating that the
288 // new build does not use GKI), or a valid GKI kernel release.
289 std::optional<KernelRelease> new_kernel_release;
290 if (new_release.empty()) {
291 LOG(INFO) << "New build does not contain GKI.";
292 } else {
293 new_kernel_release =
294 KernelRelease::Parse(new_release, true /* allow_suffix */);
295 if (!new_kernel_release.has_value()) {
296 LOG(ERROR) << "New kernel release is not valid GKI kernel release: "
297 << new_release;
298 return ErrorCode::kDownloadManifestParseError;
299 }
300 }
301
302 auto old_kernel_release =
303 KernelRelease::Parse(old_release, true /* allow_suffix */);
Yifan Hong126d13e2020-09-21 19:50:06 -0700304 bool is_update_valid = android::kver::IsKernelUpdateValid(old_kernel_release,
305 new_kernel_release);
306
307 if (!is_update_valid) {
308 if (prevent_downgrade) {
309 return ErrorCode::kPayloadTimestampError;
310 }
311 LOG(WARNING) << "Boot version downgrade detected, allowing update because "
312 << "prevent_downgrade_version sysprop is not set.";
313 }
314 return ErrorCode::kSuccess;
Yifan Hongfd6640f2020-08-27 19:13:17 -0700315}
316
Alex Deymo40d86b22015-09-03 22:27:10 -0700317} // namespace chromeos_update_engine