diff options
Diffstat (limited to 'hardware_android.cc')
-rw-r--r-- | hardware_android.cc | 95 |
1 files changed, 94 insertions, 1 deletions
diff --git a/hardware_android.cc b/hardware_android.cc index 82f1b9a6..48945224 100644 --- a/hardware_android.cc +++ b/hardware_android.cc @@ -17,19 +17,29 @@ #include "update_engine/hardware_android.h" #include <sys/types.h> +#include <sys/utsname.h> #include <memory> +#include <string> +#include <string_view> +#include <android-base/parseint.h> #include <android-base/properties.h> #include <base/files/file_util.h> #include <bootloader_message/bootloader_message.h> +#include <kver/kernel_release.h> +#include <kver/utils.h> +#include "update_engine/common/error_code_utils.h" #include "update_engine/common/hardware.h" #include "update_engine/common/platform_constants.h" +#include "update_engine/common/utils.h" using android::base::GetBoolProperty; using android::base::GetIntProperty; using android::base::GetProperty; +using android::kver::IsKernelUpdateValid; +using android::kver::KernelRelease; using std::string; namespace chromeos_update_engine { @@ -46,6 +56,11 @@ const char kPropBootHardwareSKU[] = "ro.boot.hardware.sku"; const char kPropBootRevision[] = "ro.boot.revision"; const char kPropBuildDateUTC[] = "ro.build.date.utc"; +string GetPartitionBuildDate(const string& partition_name) { + return android::base::GetProperty("ro." + partition_name + ".build.date.utc", + ""); +} + } // namespace namespace hardware { @@ -181,7 +196,7 @@ bool HardwareAndroid::CancelPowerwash() { bool HardwareAndroid::GetNonVolatileDirectory(base::FilePath* path) const { base::FilePath local_path(constants::kNonVolatileDirectory); - if (!base::PathExists(local_path)) { + if (!base::DirectoryExists(local_path)) { LOG(ERROR) << "Non-volatile directory not found: " << local_path.value(); return false; } @@ -198,6 +213,13 @@ int64_t HardwareAndroid::GetBuildTimestamp() const { return GetIntProperty<int64_t>(kPropBuildDateUTC, 0); } +// Returns true if the device runs an userdebug build, and explicitly allows OTA +// downgrade. +bool HardwareAndroid::AllowDowngrade() const { + return GetBoolProperty("ro.ota.allow_downgrade", false) && + GetBoolProperty("ro.debuggable", false); +} + bool HardwareAndroid::GetFirstActiveOmahaPingSent() const { LOG(WARNING) << "STUB: Assuming first active omaha was never set."; return false; @@ -209,4 +231,75 @@ bool HardwareAndroid::SetFirstActiveOmahaPingSent() { return true; } +void HardwareAndroid::SetWarmReset(bool warm_reset) { + constexpr char warm_reset_prop[] = "ota.warm_reset"; + if (!android::base::SetProperty(warm_reset_prop, warm_reset ? "1" : "0")) { + LOG(WARNING) << "Failed to set prop " << warm_reset_prop; + } +} + +string HardwareAndroid::GetVersionForLogging( + const string& partition_name) const { + if (partition_name == "boot") { + struct utsname buf; + if (uname(&buf) != 0) { + PLOG(ERROR) << "Unable to call uname()"; + return ""; + } + auto kernel_release = + KernelRelease::Parse(buf.release, true /* allow_suffix */); + return kernel_release.has_value() ? kernel_release->string() : ""; + } + return GetPartitionBuildDate(partition_name); +} + +ErrorCode HardwareAndroid::IsPartitionUpdateValid( + const string& partition_name, const string& new_version) const { + if (partition_name == "boot") { + struct utsname buf; + if (uname(&buf) != 0) { + PLOG(ERROR) << "Unable to call uname()"; + return ErrorCode::kError; + } + return IsKernelUpdateValid(buf.release, new_version); + } + + const auto old_version = GetPartitionBuildDate(partition_name); + // TODO(zhangkelvin) for some partitions, missing a current timestamp should + // be an error, e.g. system, vendor, product etc. + auto error_code = utils::IsTimestampNewer(old_version, new_version); + if (error_code != ErrorCode::kSuccess) { + LOG(ERROR) << "Timestamp check failed with " + << utils::ErrorCodeToString(error_code) + << " Partition timestamp: " << old_version + << " Update timestamp: " << new_version; + } + return error_code; +} + +ErrorCode HardwareAndroid::IsKernelUpdateValid(const string& old_release, + const string& new_release) { + // Check that the package either contain an empty version (indicating that the + // new build does not use GKI), or a valid GKI kernel release. + std::optional<KernelRelease> new_kernel_release; + if (new_release.empty()) { + LOG(INFO) << "New build does not contain GKI."; + } else { + new_kernel_release = + KernelRelease::Parse(new_release, true /* allow_suffix */); + if (!new_kernel_release.has_value()) { + LOG(ERROR) << "New kernel release is not valid GKI kernel release: " + << new_release; + return ErrorCode::kDownloadManifestParseError; + } + } + + auto old_kernel_release = + KernelRelease::Parse(old_release, true /* allow_suffix */); + return android::kver::IsKernelUpdateValid(old_kernel_release, + new_kernel_release) + ? ErrorCode::kSuccess + : ErrorCode::kPayloadTimestampError; +} + } // namespace chromeos_update_engine |