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