diff --git a/init/README.md b/init/README.md index e66ade236..822d81e6f 100644 --- a/init/README.md +++ b/init/README.md @@ -198,6 +198,13 @@ runs the service. is in the class "default" if one is not specified via the class option. Additional classnames beyond the (required) first one are used to group services. +`animation class` +> 'animation' class should include all services necessary for both + boot animation and shutdown animation. As these services can be + launched very early during bootup and can run until the last stage + of shutdown, access to /data partition is not guaranteed. These + services can check files under /data but it should not keep files opened + and should work when /data is not available. `onrestart` > Execute a Command (see below) when service restarts. diff --git a/init/reboot.cpp b/init/reboot.cpp index e34abdbbf..62e5c85f0 100644 --- a/init/reboot.cpp +++ b/init/reboot.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -41,6 +42,7 @@ #include #include "log.h" +#include "property_service.h" #include "reboot.h" #include "service.h" #include "util.h" @@ -248,8 +250,9 @@ static bool UmountPartitions(std::vector* partitions, int maxRetry, flags); } else { umountDone = false; - PLOG(WARNING) << StringPrintf("cannot umount %s, flags:0x%x", - entry.mnt_fsname().c_str(), flags); + PLOG(WARNING) << StringPrintf("cannot umount %s, mnt_dir %s, flags:0x%x", + entry.mnt_fsname().c_str(), + entry.mnt_dir().c_str(), flags); } } } @@ -351,26 +354,40 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re } LOG(INFO) << "Shutdown timeout: " << shutdownTimeout; - static const constexpr char* shutdown_critical_services[] = {"vold", "watchdogd"}; - for (const char* name : shutdown_critical_services) { - Service* s = ServiceManager::GetInstance().FindServiceByName(name); - if (s == nullptr) { - LOG(WARNING) << "Shutdown critical service not found:" << name; - continue; + // keep debugging tools until non critical ones are all gone. + const std::set kill_after_apps{"tombstoned", "logd", "adbd"}; + // watchdogd is a vendor specific component but should be alive to complete shutdown safely. + const std::set to_starts{"watchdogd", "vold"}; + ServiceManager::GetInstance().ForEachService([&kill_after_apps, &to_starts](Service* s) { + if (kill_after_apps.count(s->name())) { + s->SetShutdownCritical(); + } else if (to_starts.count(s->name())) { + s->Start(); + s->SetShutdownCritical(); } - s->Start(); // make sure that it is running. - s->SetShutdownCritical(); + }); + + Service* bootAnim = ServiceManager::GetInstance().FindServiceByName("bootanim"); + Service* surfaceFlinger = ServiceManager::GetInstance().FindServiceByName("surfaceflinger"); + if (bootAnim != nullptr && surfaceFlinger != nullptr && surfaceFlinger->IsRunning()) { + property_set("service.bootanim.exit", "0"); + // Could be in the middle of animation. Stop and start so that it can pick + // up the right mode. + bootAnim->Stop(); + // start all animation classes if stopped. + ServiceManager::GetInstance().ForEachServiceInClass("animation", [](Service* s) { + s->Start(); + s->SetShutdownCritical(); // will not check animation class separately + }); + bootAnim->Start(); + surfaceFlinger->SetShutdownCritical(); + bootAnim->SetShutdownCritical(); } + // optional shutdown step // 1. terminate all services except shutdown critical ones. wait for delay to finish if (shutdownTimeout > 0) { LOG(INFO) << "terminating init services"; - // tombstoned can write to data when other services are killed. so finish it first. - static const constexpr char* first_to_kill[] = {"tombstoned"}; - for (const char* name : first_to_kill) { - Service* s = ServiceManager::GetInstance().FindServiceByName(name); - if (s != nullptr) s->Stop(); - } // Ask all services to terminate except shutdown critical ones. ServiceManager::GetInstance().ForEachService([](Service* s) { @@ -409,8 +426,8 @@ void DoReboot(unsigned int cmd, const std::string& reason, const std::string& re // minimum safety steps before restarting // 2. kill all services except ones that are necessary for the shutdown sequence. - ServiceManager::GetInstance().ForEachService([](Service* s) { - if (!s->IsShutdownCritical()) s->Stop(); + ServiceManager::GetInstance().ForEachService([&kill_after_apps](Service* s) { + if (!s->IsShutdownCritical() || kill_after_apps.count(s->name())) s->Stop(); }); ServiceManager::GetInstance().ReapAnyOutstandingChildren();