18d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park/* 28d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * Copyright (C) 2017 The Android Open Source Project 38d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * 48d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * Licensed under the Apache License, Version 2.0 (the "License"); 58d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * you may not use this file except in compliance with the License. 68d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * You may obtain a copy of the License at 78d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * 88d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * http://www.apache.org/licenses/LICENSE-2.0 98d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * 108d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * Unless required by applicable law or agreed to in writing, software 118d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * distributed under the License is distributed on an "AS IS" BASIS, 128d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * See the License for the specific language governing permissions and 148d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * limitations under the License. 158d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park */ 163f5eaae526413a29de899270714469c76dc91ec8Tom Cherry 173f5eaae526413a29de899270714469c76dc91ec8Tom Cherry#include "reboot.h" 183f5eaae526413a29de899270714469c76dc91ec8Tom Cherry 198d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <dirent.h> 208d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <fcntl.h> 212ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park#include <linux/fs.h> 228d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <mntent.h> 23519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez#include <sys/capability.h> 248d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <sys/cdefs.h> 252ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park#include <sys/ioctl.h> 268d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <sys/mount.h> 278d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <sys/reboot.h> 288d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <sys/stat.h> 298d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <sys/syscall.h> 308d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <sys/types.h> 318d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <sys/wait.h> 328d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 338d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <memory> 347830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park#include <set> 358d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <thread> 368d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <vector> 378d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 38ede0d538501dfc78c741fb3b0645406636d1d1fdTom Cherry#include <android-base/chrono_utils.h> 398d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <android-base/file.h> 403f5eaae526413a29de899270714469c76dc91ec8Tom Cherry#include <android-base/logging.h> 418d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <android-base/macros.h> 42ccf23537eeacfa47e5f18dd3b75089886d177c1bTom Cherry#include <android-base/properties.h> 438d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <android-base/stringprintf.h> 448d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <android-base/strings.h> 452ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park#include <android-base/unique_fd.h> 468d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <bootloader_message/bootloader_message.h> 478d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <cutils/android_reboot.h> 488d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <fs_mgr.h> 498d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include <logwrap/logwrap.h> 50fc827be3f9fd76b98859b0c9fe3e79d0d426c3cfTodd Poynor#include <private/android_filesystem_config.h> 518d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 52519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez#include "capabilities.h" 53eeab491efd8f456324f88e444f228b1016712e45Wei Wang#include "init.h" 547830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park#include "property_service.h" 558d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park#include "service.h" 568d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 578d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Parkusing android::base::StringPrintf; 58ede0d538501dfc78c741fb3b0645406636d1d1fdTom Cherryusing android::base::Timer; 598d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 6081f5d3ebef2c3789737bf718fc2a2cdd7b9e8b33Tom Cherrynamespace android { 6181f5d3ebef2c3789737bf718fc2a2cdd7b9e8b33Tom Cherrynamespace init { 6281f5d3ebef2c3789737bf718fc2a2cdd7b9e8b33Tom Cherry 638d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park// represents umount status during reboot / shutdown. 648d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Parkenum UmountStat { 658d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park /* umount succeeded. */ 668d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park UMOUNT_STAT_SUCCESS = 0, 678d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park /* umount was not run. */ 688d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park UMOUNT_STAT_SKIPPED = 1, 698d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park /* umount failed with timeout. */ 708d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park UMOUNT_STAT_TIMEOUT = 2, 718d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park /* could not run due to error */ 728d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park UMOUNT_STAT_ERROR = 3, 738d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park /* not used by init but reserved for other part to use this to represent the 748d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park the state where umount status before reboot is not found / available. */ 758d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park UMOUNT_STAT_NOT_AVAILABLE = 4, 768d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park}; 778d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 788d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park// Utility for struct mntent 798d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Parkclass MountEntry { 808d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park public: 812ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park explicit MountEntry(const mntent& entry) 828d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park : mnt_fsname_(entry.mnt_fsname), 838d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park mnt_dir_(entry.mnt_dir), 848d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park mnt_type_(entry.mnt_type), 852ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park mnt_opts_(entry.mnt_opts) {} 868d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 87bf141af6bee50fdb577bd6e238fb4a2f7ae8e5d1Jaegeuk Kim bool Umount(bool force) { 88bf141af6bee50fdb577bd6e238fb4a2f7ae8e5d1Jaegeuk Kim int r = umount2(mnt_dir_.c_str(), force ? MNT_FORCE : 0); 892ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park if (r == 0) { 902ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park LOG(INFO) << "umounted " << mnt_fsname_ << ":" << mnt_dir_ << " opts " << mnt_opts_; 912ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park return true; 922ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park } else { 932ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park PLOG(WARNING) << "cannot umount " << mnt_fsname_ << ":" << mnt_dir_ << " opts " 942ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park << mnt_opts_; 952ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park return false; 962ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park } 972ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park } 988d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 992ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park void DoFsck() { 1002ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park int st; 1012ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park if (IsF2Fs()) { 1022ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park const char* f2fs_argv[] = { 1032ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park "/system/bin/fsck.f2fs", "-f", mnt_fsname_.c_str(), 1042ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park }; 1052ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park android_fork_execvp_ext(arraysize(f2fs_argv), (char**)f2fs_argv, &st, true, LOG_KLOG, 1062ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park true, nullptr, nullptr, 0); 1072ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park } else if (IsExt4()) { 1082ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park const char* ext4_argv[] = { 1092ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park "/system/bin/e2fsck", "-f", "-y", mnt_fsname_.c_str(), 1102ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park }; 1112ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park android_fork_execvp_ext(arraysize(ext4_argv), (char**)ext4_argv, &st, true, LOG_KLOG, 1122ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park true, nullptr, nullptr, 0); 1132ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park } 1142ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park } 1158d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 1168d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park static bool IsBlockDevice(const struct mntent& mntent) { 1178d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park return android::base::StartsWith(mntent.mnt_fsname, "/dev/block"); 1188d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 1198d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 1208d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park static bool IsEmulatedDevice(const struct mntent& mntent) { 1212ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park return android::base::StartsWith(mntent.mnt_fsname, "/data/"); 1228d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 1238d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 1248d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park private: 1252ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park bool IsF2Fs() const { return mnt_type_ == "f2fs"; } 1262ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park 1272ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park bool IsExt4() const { return mnt_type_ == "ext4"; } 1282ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park 1298d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park std::string mnt_fsname_; 1308d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park std::string mnt_dir_; 1318d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park std::string mnt_type_; 1322ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park std::string mnt_opts_; 1338d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park}; 1348d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 1358d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park// Turn off backlight while we are performing power down cleanup activities. 1368d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Parkstatic void TurnOffBacklight() { 1378d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park static constexpr char OFF[] = "0"; 1388d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 1398d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park android::base::WriteStringToFile(OFF, "/sys/class/leds/lcd-backlight/brightness"); 1408d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 1418d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park static const char backlightDir[] = "/sys/class/backlight"; 1428d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(backlightDir), closedir); 1438d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park if (!dir) { 1448d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park return; 1458d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 1468d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 1478d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park struct dirent* dp; 1488d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park while ((dp = readdir(dir.get())) != nullptr) { 1498d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park if (((dp->d_type != DT_DIR) && (dp->d_type != DT_LNK)) || (dp->d_name[0] == '.')) { 1508d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park continue; 1518d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 1528d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 1538d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park std::string fileName = StringPrintf("%s/%s/brightness", backlightDir, dp->d_name); 1548d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park android::base::WriteStringToFile(OFF, fileName); 1558d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 1568d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park} 1578d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 1588d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Parkstatic void ShutdownVold() { 1598d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park const char* vdc_argv[] = {"/system/bin/vdc", "volume", "shutdown"}; 1608d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park int status; 1618d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park android_fork_execvp_ext(arraysize(vdc_argv), (char**)vdc_argv, &status, true, LOG_KLOG, true, 1628d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park nullptr, nullptr, 0); 1638d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park} 1648d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 1658d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Parkstatic void LogShutdownTime(UmountStat stat, Timer* t) { 166ede0d538501dfc78c741fb3b0645406636d1d1fdTom Cherry LOG(WARNING) << "powerctl_shutdown_time_ms:" << std::to_string(t->duration().count()) << ":" 167ede0d538501dfc78c741fb3b0645406636d1d1fdTom Cherry << stat; 1688d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park} 1698d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 170519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez// Determines whether the system is capable of rebooting. This is conservative, 171519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez// so if any of the attempts to determine this fail, it will still return true. 172519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavezstatic bool IsRebootCapable() { 173519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez if (!CAP_IS_SUPPORTED(CAP_SYS_BOOT)) { 174519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez PLOG(WARNING) << "CAP_SYS_BOOT is not supported"; 175519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez return true; 176519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez } 177519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez 178519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez ScopedCaps caps(cap_get_proc()); 179519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez if (!caps) { 180519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez PLOG(WARNING) << "cap_get_proc() failed"; 181519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez return true; 182519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez } 183519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez 184519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez cap_flag_value_t value = CAP_SET; 185519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez if (cap_get_flag(caps.get(), CAP_SYS_BOOT, CAP_EFFECTIVE, &value) != 0) { 186519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez PLOG(WARNING) << "cap_get_flag(CAP_SYS_BOOT, EFFECTIVE) failed"; 187519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez return true; 188519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez } 189519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez return value == CAP_SET; 190519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez} 191519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez 1928d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Parkstatic void __attribute__((noreturn)) 1938d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young ParkRebootSystem(unsigned int cmd, const std::string& rebootTarget) { 1943cd8c6f9123883d02e1c4c146e1ef7bfcfa170a3Keun-young Park LOG(INFO) << "Reboot ending, jumping to kernel"; 195519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez 196519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez if (!IsRebootCapable()) { 197519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez // On systems where init does not have the capability of rebooting the 198519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez // device, just exit cleanly. 199519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez exit(0); 200519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez } 201519e5f0592eb7ceb812f9e0e61b3bc2d9fc27c74Luis Hector Chavez 2028d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park switch (cmd) { 2038d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park case ANDROID_RB_POWEROFF: 2048d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park reboot(RB_POWER_OFF); 2058d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park break; 2068d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 2078d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park case ANDROID_RB_RESTART2: 2088d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, 2098d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park LINUX_REBOOT_CMD_RESTART2, rebootTarget.c_str()); 2108d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park break; 2118d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 2128d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park case ANDROID_RB_THERMOFF: 2138d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park reboot(RB_POWER_OFF); 2148d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park break; 2158d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 2168d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park // In normal case, reboot should not return. 2178d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park PLOG(FATAL) << "reboot call returned"; 2188d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park abort(); 2198d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park} 2208d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 2218d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park/* Find all read+write block devices and emulated devices in /proc/mounts 2228d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * and add them to correpsponding list. 2238d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park */ 2248d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Parkstatic bool FindPartitionsToUmount(std::vector<MountEntry>* blockDevPartitions, 2252ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park std::vector<MountEntry>* emulatedPartitions, bool dump) { 2268d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park std::unique_ptr<std::FILE, int (*)(std::FILE*)> fp(setmntent("/proc/mounts", "r"), endmntent); 2278d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park if (fp == nullptr) { 2288d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park PLOG(ERROR) << "Failed to open /proc/mounts"; 2298d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park return false; 2308d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 2318d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park mntent* mentry; 2328d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park while ((mentry = getmntent(fp.get())) != nullptr) { 2332ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park if (dump) { 2342ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park LOG(INFO) << "mount entry " << mentry->mnt_fsname << ":" << mentry->mnt_dir << " opts " 2352ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park << mentry->mnt_opts << " type " << mentry->mnt_type; 2362ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park } else if (MountEntry::IsBlockDevice(*mentry) && hasmntopt(mentry, "rw")) { 2376e12b3887e2b964124ab1ba73f84f8049f932df7Keun-young Park std::string mount_dir(mentry->mnt_dir); 2386e12b3887e2b964124ab1ba73f84f8049f932df7Keun-young Park // These are R/O partitions changed to R/W after adb remount. 2396e12b3887e2b964124ab1ba73f84f8049f932df7Keun-young Park // Do not umount them as shutdown critical services may rely on them. 240b7a8764a1250237dec49c6c3d6db4ef88f5f2978Wei Wang if (mount_dir != "/" && mount_dir != "/system" && mount_dir != "/vendor" && 241b7a8764a1250237dec49c6c3d6db4ef88f5f2978Wei Wang mount_dir != "/oem") { 2426e12b3887e2b964124ab1ba73f84f8049f932df7Keun-young Park blockDevPartitions->emplace(blockDevPartitions->begin(), *mentry); 2436e12b3887e2b964124ab1ba73f84f8049f932df7Keun-young Park } 2448d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } else if (MountEntry::IsEmulatedDevice(*mentry)) { 2452ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park emulatedPartitions->emplace(emulatedPartitions->begin(), *mentry); 2468d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 2478d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 2488d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park return true; 2498d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park} 2508d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 2511663e97fe17eea382aa9ba9d9a10d4e83ca6d7e6Keun-young Parkstatic void DumpUmountDebuggingInfo(bool dump_all) { 2522ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park int status; 2532ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park if (!security_getenforce()) { 2542ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park LOG(INFO) << "Run lsof"; 2552ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park const char* lsof_argv[] = {"/system/bin/lsof"}; 2562ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park android_fork_execvp_ext(arraysize(lsof_argv), (char**)lsof_argv, &status, true, LOG_KLOG, 2572ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park true, nullptr, nullptr, 0); 2582ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park } 2592ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park FindPartitionsToUmount(nullptr, nullptr, true); 2601663e97fe17eea382aa9ba9d9a10d4e83ca6d7e6Keun-young Park if (dump_all) { 2611663e97fe17eea382aa9ba9d9a10d4e83ca6d7e6Keun-young Park // dump current tasks, this log can be lengthy, so only dump with dump_all 2621663e97fe17eea382aa9ba9d9a10d4e83ca6d7e6Keun-young Park android::base::WriteStringToFile("t", "/proc/sysrq-trigger"); 2631663e97fe17eea382aa9ba9d9a10d4e83ca6d7e6Keun-young Park } 2642ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park} 2658d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 266ede0d538501dfc78c741fb3b0645406636d1d1fdTom Cherrystatic UmountStat UmountPartitions(std::chrono::milliseconds timeout) { 2672ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park Timer t; 2682ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park UmountStat stat = UMOUNT_STAT_TIMEOUT; 2692ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park int retry = 0; 2702ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park /* data partition needs all pending writes to be completed and all emulated partitions 2712ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park * umounted.If the current waiting is not good enough, give 2722ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park * up and leave it to e2fsck after reboot to fix it. 2732ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park */ 2748d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park while (true) { 2752ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park std::vector<MountEntry> block_devices; 2762ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park std::vector<MountEntry> emulated_devices; 2772ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park if (!FindPartitionsToUmount(&block_devices, &emulated_devices, false)) { 2782ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park return UMOUNT_STAT_ERROR; 2798d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 2802ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park if (block_devices.size() == 0) { 2812ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park stat = UMOUNT_STAT_SUCCESS; 2822ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park break; 2832ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park } 284ede0d538501dfc78c741fb3b0645406636d1d1fdTom Cherry if ((timeout < t.duration()) && retry > 0) { // try umount at least once 2852ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park stat = UMOUNT_STAT_TIMEOUT; 2862ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park break; 2872ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park } 2882ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park if (emulated_devices.size() > 0 && 2892ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park std::all_of(emulated_devices.begin(), emulated_devices.end(), 290bf141af6bee50fdb577bd6e238fb4a2f7ae8e5d1Jaegeuk Kim [](auto& entry) { return entry.Umount(false); })) { 2912ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park sync(); 2922ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park } 2932ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park for (auto& entry : block_devices) { 294bf141af6bee50fdb577bd6e238fb4a2f7ae8e5d1Jaegeuk Kim entry.Umount(timeout == 0ms); 2952ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park } 2962ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park retry++; 2972ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park std::this_thread::sleep_for(100ms); 2988d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 2992ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park return stat; 3008d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park} 3018d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 3023ee0df9bdfef5e872d278b3d4d073a379ca62451Keun-young Parkstatic void KillAllProcesses() { android::base::WriteStringToFile("i", "/proc/sysrq-trigger"); } 3033ee0df9bdfef5e872d278b3d4d073a379ca62451Keun-young Park 3048d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park/* Try umounting all emulated file systems R/W block device cfile systems. 3058d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * This will just try umount and give it up if it fails. 3068d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * For fs like ext4, this is ok as file system will be marked as unclean shutdown 3078d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * and necessary check can be done at the next reboot. 3088d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * For safer shutdown, caller needs to make sure that 3098d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * all processes / emulated partition for the target fs are all cleaned-up. 3108d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * 3118d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park * return true when umount was successful. false when timed out. 3128d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park */ 313ede0d538501dfc78c741fb3b0645406636d1d1fdTom Cherrystatic UmountStat TryUmountAndFsck(bool runFsck, std::chrono::milliseconds timeout) { 3143ee0df9bdfef5e872d278b3d4d073a379ca62451Keun-young Park Timer t; 3152ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park std::vector<MountEntry> block_devices; 3162ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park std::vector<MountEntry> emulated_devices; 3178d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 3188d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park TurnOffBacklight(); // this part can take time. save power. 3198d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 3202ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park if (runFsck && !FindPartitionsToUmount(&block_devices, &emulated_devices, false)) { 3218d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park return UMOUNT_STAT_ERROR; 3228d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 3232ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park 324ede0d538501dfc78c741fb3b0645406636d1d1fdTom Cherry UmountStat stat = UmountPartitions(timeout - t.duration()); 3252ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park if (stat != UMOUNT_STAT_SUCCESS) { 3262ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park LOG(INFO) << "umount timeout, last resort, kill all and try"; 327c59b822d1f6705aad7c00b9a9a98d4f60d979fdcKeun-young Park if (DUMP_ON_UMOUNT_FAILURE) DumpUmountDebuggingInfo(true); 3283ee0df9bdfef5e872d278b3d4d073a379ca62451Keun-young Park KillAllProcesses(); 3292ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park // even if it succeeds, still it is timeout and do not run fsck with all processes killed 330c59b822d1f6705aad7c00b9a9a98d4f60d979fdcKeun-young Park UmountStat st = UmountPartitions(0ms); 331c59b822d1f6705aad7c00b9a9a98d4f60d979fdcKeun-young Park if ((st != UMOUNT_STAT_SUCCESS) && DUMP_ON_UMOUNT_FAILURE) DumpUmountDebuggingInfo(false); 3328d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 3332ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park 3348d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park if (stat == UMOUNT_STAT_SUCCESS && runFsck) { 3352ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park // fsck part is excluded from timeout check. It only runs for user initiated shutdown 3362ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park // and should not affect reboot time. 3372ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park for (auto& entry : block_devices) { 3382ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park entry.DoFsck(); 3398d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 3408d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 3418d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park return stat; 3428d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park} 3438d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 3448d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Parkvoid DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget, 3458d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park bool runFsck) { 3468d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park Timer t; 3473cd8c6f9123883d02e1c4c146e1ef7bfcfa170a3Keun-young Park LOG(INFO) << "Reboot start, reason: " << reason << ", rebootTarget: " << rebootTarget; 3488d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 349fc827be3f9fd76b98859b0c9fe3e79d0d426c3cfTodd Poynor android::base::WriteStringToFile(StringPrintf("%s\n", reason.c_str()), LAST_REBOOT_REASON_FILE, 350fc827be3f9fd76b98859b0c9fe3e79d0d426c3cfTodd Poynor S_IRUSR | S_IWUSR, AID_SYSTEM, AID_SYSTEM); 3518d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 35230173874fce97580dfce99ae8626673fc529af9eKeun-young Park bool is_thermal_shutdown = false; 35330173874fce97580dfce99ae8626673fc529af9eKeun-young Park if (cmd == ANDROID_RB_THERMOFF) { 35430173874fce97580dfce99ae8626673fc529af9eKeun-young Park is_thermal_shutdown = true; 35530173874fce97580dfce99ae8626673fc529af9eKeun-young Park runFsck = false; 3568d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 357aa08ea458a3aea9f671f847f4e005c3bd39da201Keun-young Park 35830173874fce97580dfce99ae8626673fc529af9eKeun-young Park auto shutdown_timeout = 0ms; 359ede0d538501dfc78c741fb3b0645406636d1d1fdTom Cherry if (!SHUTDOWN_ZERO_TIMEOUT) { 36030173874fce97580dfce99ae8626673fc529af9eKeun-young Park if (is_thermal_shutdown) { 36130173874fce97580dfce99ae8626673fc529af9eKeun-young Park constexpr unsigned int thermal_shutdown_timeout = 1; 36230173874fce97580dfce99ae8626673fc529af9eKeun-young Park shutdown_timeout = std::chrono::seconds(thermal_shutdown_timeout); 36330173874fce97580dfce99ae8626673fc529af9eKeun-young Park } else { 36430173874fce97580dfce99ae8626673fc529af9eKeun-young Park constexpr unsigned int shutdown_timeout_default = 6; 36530173874fce97580dfce99ae8626673fc529af9eKeun-young Park auto shutdown_timeout_property = android::base::GetUintProperty( 36630173874fce97580dfce99ae8626673fc529af9eKeun-young Park "ro.build.shutdown_timeout", shutdown_timeout_default); 36730173874fce97580dfce99ae8626673fc529af9eKeun-young Park shutdown_timeout = std::chrono::seconds(shutdown_timeout_property); 36830173874fce97580dfce99ae8626673fc529af9eKeun-young Park } 369c4ffa5c47d0ac84cae57337412c2459f2cb11da5Keun-young Park } 37030173874fce97580dfce99ae8626673fc529af9eKeun-young Park LOG(INFO) << "Shutdown timeout: " << shutdown_timeout.count() << " ms"; 371aa08ea458a3aea9f671f847f4e005c3bd39da201Keun-young Park 3727830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park // keep debugging tools until non critical ones are all gone. 3737830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park const std::set<std::string> kill_after_apps{"tombstoned", "logd", "adbd"}; 3747830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park // watchdogd is a vendor specific component but should be alive to complete shutdown safely. 375cccb34fce8798f2a359c6eb0e394ef9460673629Keun-young Park const std::set<std::string> to_starts{"watchdogd"}; 3767830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park ServiceManager::GetInstance().ForEachService([&kill_after_apps, &to_starts](Service* s) { 3777830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park if (kill_after_apps.count(s->name())) { 3787830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park s->SetShutdownCritical(); 3797830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park } else if (to_starts.count(s->name())) { 3807830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park s->Start(); 3817830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park s->SetShutdownCritical(); 382cccb34fce8798f2a359c6eb0e394ef9460673629Keun-young Park } else if (s->IsShutdownCritical()) { 383cccb34fce8798f2a359c6eb0e394ef9460673629Keun-young Park s->Start(); // start shutdown critical service if not started 3848d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 3857830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park }); 3867830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park 3877830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park Service* bootAnim = ServiceManager::GetInstance().FindServiceByName("bootanim"); 3887830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park Service* surfaceFlinger = ServiceManager::GetInstance().FindServiceByName("surfaceflinger"); 3897830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park if (bootAnim != nullptr && surfaceFlinger != nullptr && surfaceFlinger->IsRunning()) { 3907830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park ServiceManager::GetInstance().ForEachServiceInClass("animation", [](Service* s) { 3917830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park s->SetShutdownCritical(); // will not check animation class separately 3927830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park }); 3938d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 3947830d59500eb0cb24333dc357ac5bed38270e181Keun-young Park 3958d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park // optional shutdown step 3968d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park // 1. terminate all services except shutdown critical ones. wait for delay to finish 39730173874fce97580dfce99ae8626673fc529af9eKeun-young Park if (shutdown_timeout > 0ms) { 3988d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park LOG(INFO) << "terminating init services"; 3998d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 4008d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park // Ask all services to terminate except shutdown critical ones. 4018d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park ServiceManager::GetInstance().ForEachService([](Service* s) { 4028d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park if (!s->IsShutdownCritical()) s->Terminate(); 4038d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park }); 4048d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 4058d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park int service_count = 0; 40630173874fce97580dfce99ae8626673fc529af9eKeun-young Park // Only wait up to half of timeout here 40730173874fce97580dfce99ae8626673fc529af9eKeun-young Park auto termination_wait_timeout = shutdown_timeout / 2; 408ede0d538501dfc78c741fb3b0645406636d1d1fdTom Cherry while (t.duration() < termination_wait_timeout) { 4098d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park ServiceManager::GetInstance().ReapAnyOutstandingChildren(); 4108d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 4118d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park service_count = 0; 4128d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park ServiceManager::GetInstance().ForEachService([&service_count](Service* s) { 4138d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park // Count the number of services running except shutdown critical. 4148d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park // Exclude the console as it will ignore the SIGTERM signal 4158d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park // and not exit. 4168d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park // Note: SVC_CONSOLE actually means "requires console" but 4178d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park // it is only used by the shell. 4188d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park if (!s->IsShutdownCritical() && s->pid() != 0 && (s->flags() & SVC_CONSOLE) == 0) { 4198d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park service_count++; 4208d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 4218d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park }); 4228d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 4238d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park if (service_count == 0) { 4248d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park // All terminable services terminated. We can exit early. 4258d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park break; 4268d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 4278d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 4288d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park // Wait a bit before recounting the number or running services. 4298d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park std::this_thread::sleep_for(50ms); 4308d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 4318d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park LOG(INFO) << "Terminating running services took " << t 4328d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park << " with remaining services:" << service_count; 4338d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 4348d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 4358d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park // minimum safety steps before restarting 4368d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park // 2. kill all services except ones that are necessary for the shutdown sequence. 4372ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park ServiceManager::GetInstance().ForEachService([](Service* s) { 4382ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park if (!s->IsShutdownCritical()) s->Stop(); 4398d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park }); 4408d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park ServiceManager::GetInstance().ReapAnyOutstandingChildren(); 4418d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park 4428d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park // 3. send volume shutdown to vold 4438d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park Service* voldService = ServiceManager::GetInstance().FindServiceByName("vold"); 4448d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park if (voldService != nullptr && voldService->IsRunning()) { 4458d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park ShutdownVold(); 4462ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park voldService->Stop(); 4478d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } else { 4488d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park LOG(INFO) << "vold not running, skipping vold shutdown"; 4498d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park } 4502ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park // logcat stopped here 4512ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park ServiceManager::GetInstance().ForEachService([&kill_after_apps](Service* s) { 4522ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park if (kill_after_apps.count(s->name())) s->Stop(); 4532ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park }); 4548d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park // 4. sync, try umount, and optionally run fsck for user shutdown 4552ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park sync(); 456ede0d538501dfc78c741fb3b0645406636d1d1fdTom Cherry UmountStat stat = TryUmountAndFsck(runFsck, shutdown_timeout - t.duration()); 4572ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park // Follow what linux shutdown is doing: one more sync with little bit delay 4582ba5c8103d0cf748fdf03c9e5be975ccc36fb56aKeun-young Park sync(); 45930173874fce97580dfce99ae8626673fc529af9eKeun-young Park if (!is_thermal_shutdown) std::this_thread::sleep_for(100ms); 4608d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park LogShutdownTime(stat, &t); 4618d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park // Reboot regardless of umount status. If umount fails, fsck after reboot will fix it. 4628d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park RebootSystem(cmd, rebootTarget); 4638d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park abort(); 4648d01f63f50fb001f41835a0dab636981f2ba76ddKeun-young Park} 46598ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry 46698ad32a967079be80a101458d8a29d7ecefbb547Tom Cherrybool HandlePowerctlMessage(const std::string& command) { 46798ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry unsigned int cmd = 0; 46898ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry std::vector<std::string> cmd_params = android::base::Split(command, ","); 46998ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry std::string reboot_target = ""; 47098ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry bool run_fsck = false; 47198ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry bool command_invalid = false; 47298ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry 47398ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry if (cmd_params.size() > 3) { 47498ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry command_invalid = true; 47598ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry } else if (cmd_params[0] == "shutdown") { 47698ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry cmd = ANDROID_RB_POWEROFF; 47798ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry if (cmd_params.size() == 2 && cmd_params[1] == "userrequested") { 47898ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry // The shutdown reason is PowerManager.SHUTDOWN_USER_REQUESTED. 47998ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry // Run fsck once the file system is remounted in read-only mode. 48098ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry run_fsck = true; 48198ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry } 48298ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry } else if (cmd_params[0] == "reboot") { 48398ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry cmd = ANDROID_RB_RESTART2; 48498ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry if (cmd_params.size() >= 2) { 48598ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry reboot_target = cmd_params[1]; 48698ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry // When rebooting to the bootloader notify the bootloader writing 48798ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry // also the BCB. 48898ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry if (reboot_target == "bootloader") { 48998ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry std::string err; 49098ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry if (!write_reboot_bootloader(&err)) { 49198ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry LOG(ERROR) << "reboot-bootloader: Error writing " 49298ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry "bootloader_message: " 49398ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry << err; 49498ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry } 49598ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry } 49698ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry // If there is an additional bootloader parameter, pass it along 49798ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry if (cmd_params.size() == 3) { 49898ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry reboot_target += "," + cmd_params[2]; 49998ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry } 50098ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry } 50198ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry } else if (command == "thermal-shutdown") { // no additional parameter allowed 50263a1d0a5f9d75bd1011678da3a05c0b440efe774Wei Wang // run_fsck is false to avoid delay 50398ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry cmd = ANDROID_RB_THERMOFF; 50498ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry } else { 50598ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry command_invalid = true; 50698ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry } 50798ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry if (command_invalid) { 50898ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry LOG(ERROR) << "powerctl: unrecognized command '" << command << "'"; 50998ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry return false; 51098ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry } 51198ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry 512eeab491efd8f456324f88e444f228b1016712e45Wei Wang LOG(INFO) << "Clear action queue and start shutdown trigger"; 513eeab491efd8f456324f88e444f228b1016712e45Wei Wang ActionManager::GetInstance().ClearQueue(); 514eeab491efd8f456324f88e444f228b1016712e45Wei Wang // Queue shutdown trigger first 515eeab491efd8f456324f88e444f228b1016712e45Wei Wang ActionManager::GetInstance().QueueEventTrigger("shutdown"); 516eeab491efd8f456324f88e444f228b1016712e45Wei Wang // Queue built-in shutdown_done 517eeab491efd8f456324f88e444f228b1016712e45Wei Wang auto shutdown_handler = [cmd, command, reboot_target, 518eeab491efd8f456324f88e444f228b1016712e45Wei Wang run_fsck](const std::vector<std::string>&) { 519eeab491efd8f456324f88e444f228b1016712e45Wei Wang DoReboot(cmd, command, reboot_target, run_fsck); 520eeab491efd8f456324f88e444f228b1016712e45Wei Wang return 0; 521eeab491efd8f456324f88e444f228b1016712e45Wei Wang }; 522eeab491efd8f456324f88e444f228b1016712e45Wei Wang ActionManager::GetInstance().QueueBuiltinAction(shutdown_handler, "shutdown_done"); 523eeab491efd8f456324f88e444f228b1016712e45Wei Wang 524eeab491efd8f456324f88e444f228b1016712e45Wei Wang // Skip wait for prop if it is in progress 525eeab491efd8f456324f88e444f228b1016712e45Wei Wang ResetWaitForProp(); 526eeab491efd8f456324f88e444f228b1016712e45Wei Wang 527eeab491efd8f456324f88e444f228b1016712e45Wei Wang // Skip wait for exec if it is in progress 528eeab491efd8f456324f88e444f228b1016712e45Wei Wang if (ServiceManager::GetInstance().IsWaitingForExec()) { 529eeab491efd8f456324f88e444f228b1016712e45Wei Wang ServiceManager::GetInstance().ClearExecWait(); 530eeab491efd8f456324f88e444f228b1016712e45Wei Wang } 531eeab491efd8f456324f88e444f228b1016712e45Wei Wang 53298ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry return true; 53398ad32a967079be80a101458d8a29d7ecefbb547Tom Cherry} 53481f5d3ebef2c3789737bf718fc2a2cdd7b9e8b33Tom Cherry 53581f5d3ebef2c3789737bf718fc2a2cdd7b9e8b33Tom Cherry} // namespace init 53681f5d3ebef2c3789737bf718fc2a2cdd7b9e8b33Tom Cherry} // namespace android 537