blob: 91bee9d32219e1516ac5554987a8931a559f86de [file] [log] [blame]
Joe Hattori6de89162025-06-29 21:21:34 -07001/*
2 * Copyright (C) 2025 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 "coldboot.h"
Joe Hattori6aefbea2025-07-01 13:00:14 +000018#include "coldboot_runner.h"
19#include "com_android_ueventd_flags.h"
Joe Hattori6de89162025-06-29 21:21:34 -070020#include "util.h"
21
22#include <android-base/chrono_utils.h>
23#include <android-base/logging.h>
24#include <android-base/properties.h>
25#include <selinux/android.h>
26#include <selinux/selinux.h>
27#include <sys/stat.h>
28
Joe Hattori6aefbea2025-07-01 13:00:14 +000029namespace flags = com::android::ueventd::flags;
30
Joe Hattori6de89162025-06-29 21:21:34 -070031namespace android {
32namespace init {
33
Joe Hattori6aefbea2025-07-01 13:00:14 +000034void RestoreconRecurse(const std::string& dir) {
35 android::base::Timer t;
36 selinux_android_restorecon(dir.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE);
37
38 // Mark a dir restorecon operation for 50ms,
39 // Maybe you can add this dir to the ueventd.rc script to parallel processing
40 if (t.duration() > 50ms) {
41 LOG(INFO) << "took " << t.duration().count() << "ms restorecon '" << dir.c_str() << "'";
42 }
43}
44
Joe Hattori6de89162025-06-29 21:21:34 -070045void ColdBoot::RegenerateUevents() {
46 uevent_listener_.RegenerateUevents([this](const Uevent& uevent) {
47 uevent_queue_.emplace_back(uevent);
48 return ListenerAction::kContinue;
49 });
50}
51
52void ColdBoot::GenerateRestoreCon(const std::string& directory) {
53 std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(directory.c_str()), &closedir);
54
55 if (!dir) {
56 PLOG(WARNING) << "opendir " << directory.c_str();
57 return;
58 }
59
60 struct dirent* dent;
61 while ((dent = readdir(dir.get())) != NULL) {
62 if (strcmp(dent->d_name, ".") == 0 || strcmp(dent->d_name, "..") == 0) continue;
63
64 struct stat st;
65 if (fstatat(dirfd(dir.get()), dent->d_name, &st, 0) == -1) continue;
66
67 if (S_ISDIR(st.st_mode)) {
68 std::string fullpath = directory + "/" + dent->d_name;
69 auto parallel_restorecon = std::find(parallel_restorecon_queue_.begin(),
70 parallel_restorecon_queue_.end(), fullpath);
71 if (parallel_restorecon == parallel_restorecon_queue_.end()) {
72 restorecon_queue_.push_back(fullpath);
73 }
74 }
75 }
76}
77
78void ColdBoot::Run() {
79 android::base::Timer cold_boot_timer;
80
81 RegenerateUevents();
82
83 if (enable_parallel_restorecon_) {
84 if (parallel_restorecon_queue_.empty()) {
85 parallel_restorecon_queue_.emplace_back("/sys");
86 // takes long time for /sys/devices, parallelize it
87 parallel_restorecon_queue_.emplace_back("/sys/devices");
88 LOG(INFO) << "Parallel processing directory is not set, set the default";
89 }
90 for (const auto& dir : parallel_restorecon_queue_) {
91 selinux_android_restorecon(dir.c_str(), 0);
92 GenerateRestoreCon(dir);
93 }
94 }
95
Joe Hattori6aefbea2025-07-01 13:00:14 +000096 std::unique_ptr<ColdbootRunner> runner;
97
98 unsigned int parallelism = std::thread::hardware_concurrency() ?: 4;
Joe Hattori188decd2025-08-25 17:55:42 -070099 if constexpr (flags::enable_threadpool_coldboot()) {
Joe Hattori6aefbea2025-07-01 13:00:14 +0000100 runner = std::make_unique<ColdbootRunnerThreadPool>(
101 parallelism, uevent_queue_, uevent_handlers_, enable_parallel_restorecon_,
102 restorecon_queue_);
103 } else {
104 runner = std::make_unique<ColdbootRunnerSubprocess>(
105 parallelism, uevent_queue_, uevent_handlers_, enable_parallel_restorecon_,
106 restorecon_queue_);
107 }
108
109 runner->StartInBackground();
Joe Hattori6de89162025-06-29 21:21:34 -0700110
111 if (!enable_parallel_restorecon_) {
112 selinux_android_restorecon("/sys", SELINUX_ANDROID_RESTORECON_RECURSE);
113 }
114
Joe Hattori6aefbea2025-07-01 13:00:14 +0000115 runner->Wait();
Joe Hattori6de89162025-06-29 21:21:34 -0700116
117 android::base::SetProperty(kColdBootDoneProp, "true");
118 LOG(INFO) << "Coldboot took " << cold_boot_timer.duration().count() / 1000.0f << " seconds";
119}
120
121} // namespace init
122} // namespace android