Merge cherrypicks of ['googleplex-android-review.googlesource.com/33153634'] into 25Q2-release. Change-Id: I6eccfa805014ca464062d105f647cab75035abe7
diff --git a/init/Android.bp b/init/Android.bp index b209c47..ed8123e 100644 --- a/init/Android.bp +++ b/init/Android.bp
@@ -80,6 +80,7 @@ "sigchld_handler.cpp", "snapuserd_transition.cpp", "switch_root.cpp", + "tradeinmode.cpp", "uevent_listener.cpp", "ueventd.cpp", "ueventd_parser.cpp",
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp index aa6b551..6b413f6 100644 --- a/init/first_stage_mount.cpp +++ b/init/first_stage_mount.cpp
@@ -32,12 +32,9 @@ #include <android-base/chrono_utils.h> #include <android-base/file.h> #include <android-base/logging.h> -#include <android-base/parseint.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android/avf_cc_flags.h> -#include <bootloader_message/bootloader_message.h> -#include <cutils/android_reboot.h> #include <fs_avb/fs_avb.h> #include <fs_mgr.h> #include <fs_mgr_dm_linear.h> @@ -49,7 +46,6 @@ #include "block_dev_initializer.h" #include "devices.h" -#include "reboot_utils.h" #include "result.h" #include "snapuserd_transition.h" #include "switch_root.h" @@ -115,8 +111,6 @@ bool GetDmVerityDevices(std::set<std::string>* devices); bool SetUpDmVerity(FstabEntry* fstab_entry); - void RequestTradeInModeWipeIfNeeded(); - bool InitAvbHandle(); bool need_dm_verity_; @@ -269,8 +263,6 @@ } bool FirstStageMountVBootV2::DoFirstStageMount() { - RequestTradeInModeWipeIfNeeded(); - if (!IsDmLinearEnabled() && fstab_.empty()) { // Nothing to mount. LOG(INFO) << "First stage mount skipped (missing/incompatible/empty fstab in device tree)"; @@ -890,55 +882,6 @@ return true; } -void FirstStageMountVBootV2::RequestTradeInModeWipeIfNeeded() { - static constexpr const char* kWipeIndicator = "/metadata/tradeinmode/wipe"; - static constexpr size_t kWipeAttempts = 3; - - if (access(kWipeIndicator, R_OK) == -1) { - return; - } - - // Write a counter to the wipe indicator, to try and prevent boot loops if - // recovery fails to wipe data. - uint32_t counter = 0; - std::string contents; - if (ReadFileToString(kWipeIndicator, &contents)) { - android::base::ParseUint(contents, &counter); - contents = std::to_string(++counter); - if (android::base::WriteStringToFile(contents, kWipeIndicator)) { - sync(); - } else { - PLOG(ERROR) << "Failed to update " << kWipeIndicator; - } - } else { - PLOG(ERROR) << "Failed to read " << kWipeIndicator; - } - - std::string err; - auto misc_device = get_misc_blk_device(&err); - if (misc_device.empty()) { - LOG(FATAL) << "Could not find misc device: " << err; - } - - auto misc_name = android::base::Basename(misc_device); - if (!block_dev_init_.InitDevices({misc_name})) { - LOG(FATAL) << "Could not find misc device: " << misc_device; - } - - // If we've failed to wipe three times, don't include the wipe command. This - // will force us to boot into the recovery menu instead where a manual wipe - // can be attempted. - std::vector<std::string> options; - if (counter <= kWipeAttempts) { - options.emplace_back("--wipe_data"); - options.emplace_back("--reason=tradeinmode"); - } - if (!write_bootloader_message(options, &err)) { - LOG(FATAL) << "Could not issue wipe: " << err; - } - RebootSystem(ANDROID_RB_RESTART2, "recovery", "reboot,tradeinmode,wipe"); -} - void SetInitAvbVersionInRecovery() { if (!IsRecoveryMode()) { LOG(INFO) << "Skipped setting INIT_AVB_VERSION (not in recovery mode)";
diff --git a/init/init.cpp b/init/init.cpp index 920b926..f6b2941 100644 --- a/init/init.cpp +++ b/init/init.cpp
@@ -88,6 +88,7 @@ #include "snapuserd_transition.h" #include "subcontext.h" #include "system/core/init/property_service.pb.h" +#include "tradeinmode.h" #include "util.h" #ifndef RECOVERY @@ -923,6 +924,11 @@ return {}; } +static Result<void> CheckTradeInModeStatus([[maybe_unused]] const BuiltinArguments& args) { + RequestTradeInModeWipeIfNeeded(); + return {}; +} + static void SecondStageBootMonitor(int timeout_sec) { auto cur_time = boot_clock::now().time_since_epoch(); int cur_sec = std::chrono::duration_cast<std::chrono::seconds>(cur_time).count(); @@ -1111,6 +1117,7 @@ // Queue an action that waits for coldboot done so we know ueventd has set up all of /dev... am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done"); + am.QueueBuiltinAction(CheckTradeInModeStatus, "CheckTradeInModeStatus"); // ... so that we can start queuing up actions that require stuff from /dev. am.QueueBuiltinAction(SetMmapRndBitsAction, "SetMmapRndBits"); Keychords keychords;
diff --git a/init/tradeinmode.cpp b/init/tradeinmode.cpp new file mode 100644 index 0000000..1913bae --- /dev/null +++ b/init/tradeinmode.cpp
@@ -0,0 +1,79 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <stddef.h> +#include <stdint.h> +#include <unistd.h> + +#include <string> +#include <vector> + +#include <android-base/file.h> +#include <android-base/logging.h> +#include <android-base/parseint.h> +#include <bootloader_message/bootloader_message.h> +#include <cutils/android_reboot.h> + +#include "reboot_utils.h" + +namespace android { +namespace init { + +void RequestTradeInModeWipeIfNeeded() { + static constexpr const char* kWipeIndicator = "/metadata/tradeinmode/wipe"; + static constexpr size_t kWipeAttempts = 3; + + if (access(kWipeIndicator, R_OK) == -1) { + return; + } + + // Write a counter to the wipe indicator, to try and prevent boot loops if + // recovery fails to wipe data. + uint32_t counter = 0; + std::string contents; + if (android::base::ReadFileToString(kWipeIndicator, &contents)) { + android::base::ParseUint(contents, &counter); + contents = std::to_string(++counter); + if (android::base::WriteStringToFile(contents, kWipeIndicator)) { + sync(); + } else { + PLOG(ERROR) << "Failed to update " << kWipeIndicator; + } + } else { + PLOG(ERROR) << "Failed to read " << kWipeIndicator; + } + + std::string err; + auto misc_device = get_misc_blk_device(&err); + if (misc_device.empty()) { + LOG(FATAL) << "Could not find misc device: " << err; + } + + // If we've failed to wipe three times, don't include the wipe command. This + // will force us to boot into the recovery menu instead where a manual wipe + // can be attempted. + std::vector<std::string> options; + if (counter <= kWipeAttempts) { + options.emplace_back("--wipe_data"); + options.emplace_back("--reason=tradeinmode"); + } + if (!write_bootloader_message(options, &err)) { + LOG(FATAL) << "Could not issue wipe: " << err; + } + RebootSystem(ANDROID_RB_RESTART2, "recovery", "reboot,tradeinmode,wipe"); +} + +} // namespace init +} // namespace android
diff --git a/init/tradeinmode.h b/init/tradeinmode.h new file mode 100644 index 0000000..fec2a01 --- /dev/null +++ b/init/tradeinmode.h
@@ -0,0 +1,25 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +namespace android { +namespace init { + +void RequestTradeInModeWipeIfNeeded(); + +} // namespace init +} // namespace android