From e21081b4c80e5ebb2a05f2f0e90f2b49e06bb499 Mon Sep 17 00:00:00 2001 From: dybertwang Date: Thu, 18 Jul 2019 11:05:13 +0800 Subject: [PATCH] [DO NOT MERGE] Parse BCB recovery reason to enable SOTA(Silent OTA). After SOTA completed, SOTA application will send "--wipe_data" and "--reason=enable-sota" into BCB recovery field, then enter recovery for running factory reset. Once factory reset completed, recovery must check "--reason", determine if writing "enable-sota" into vendor misc partition (from offset 32), and then reboot. During next booting, bootloader will re-enable SOTA capability while "enable-sota" found in vendor misc partition. Bug: 144826346 Note: Issue [6] in b/131680543#comment12 Change-Id: I764f2243b4f4c150d5b9fd9e494770e2ad46d89f --- recovery/recovery_ui.cpp | 56 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/recovery/recovery_ui.cpp b/recovery/recovery_ui.cpp index 3133ece..e60b69c 100644 --- a/recovery/recovery_ui.cpp +++ b/recovery/recovery_ui.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -76,6 +77,52 @@ bool WipeBootThemeFlag() { return true; } +bool GetReason(std::string* reason) { + bootloader_message boot = {}; + std::string err; + bool ret = false; + if (!read_bootloader_message(&boot, &err)) { + LOG(ERROR) << err; + return ret; + } + + std::vector args; + boot.recovery[sizeof(boot.recovery) - 1] = '\0'; // Ensure termination + std::string boot_recovery(boot.recovery); + std::vector tokens = android::base::Split(boot_recovery, "\n"); + if (!tokens.empty() && tokens[0] == "recovery") { + for (auto it = tokens.begin() + 1; it != tokens.end(); it++) { + // Skip empty and '\0'-filled tokens. + if (!it->empty() && (*it)[0] != '\0') args.push_back(std::move(*it)); + } + LOG(INFO) << "Got " << args.size() << " arguments from boot message"; + } else if (boot.recovery[0] != 0) { + LOG(ERROR) << "Bad boot message: \"" << boot_recovery << "\""; + return ret; + } + + for (const auto& arg : args) { + if (android::base::StartsWith(arg, "--reason=")) { + *reason = arg.substr(strlen("--reason=")); + LOG(INFO) << "reason is " << *reason; + ret = true; + break; + } + } + return ret; +} + +bool ProvisionSilentOtaFlag() { + const std::string sota_str("enable-sota"); + constexpr size_t kSotaFlagOffsetInVendorSpace = 32; + if (std::string err; !WriteMiscPartitionVendorSpace(sota_str.data(), sota_str.size(), + kSotaFlagOffsetInVendorSpace, &err)) { + LOG(ERROR) << "Failed to write SOTA string: " << err; + return false; + } + LOG(INFO) << "Provision SOTA flag successfully"; + return true; +} } // namespace class RedfinDevice : public ::Device @@ -100,6 +147,15 @@ public: // Extendable to wipe other components + // Additional behavior along with wiping data... + std::string reason; + if (GetReason(&reason) && android::base::StartsWith(reason, "enable-sota")) { + ui->Print("Enabling Silent OTA...\n"); + if (!ProvisionSilentOtaFlag()) { + totalSuccess = false; + } + } + return totalSuccess; } };