android O 手机关机流程与时间

rebootOrShutdown -》lowLevelShutdown-》 SystemProperties.set("sys.powerctl", "shutdown," + reason);

01-01 12:16:31.289   748  2733 D PowerManagerService: releaseWakeLockInternal: lock=147473665 [ActivityManager-Sleep], flags=0x0
01-01 12:16:33.358   748  2733 D PowerManagerService: go to sleep due to quick shutdown
01-01 12:16:33.865   748  2733 D PowerManagerService: set sys.powerctl begin ,reason ==userrequested
01-01 12:16:33.866   748  2733 D PowerManagerService: set sys.powerctl end

L 上面

init.rc 中
on property:sys.powerctl=*
     powerctl ${sys.powerctl}

O 上面:


core/init/property_service.cpp
static uint32_t PropertySetImpl(const std::string& name, const std::string& value) {

...

    // Don't write properties to disk until after we have read all default
    // properties to prevent them from being overwritten by default values.
    if (persistent_properties_loaded && android::base::StartsWith(name, "persist.")) {
        write_persistent_property(name.c_str(), value.c_str());
    }
    property_changed(name, value);

222 #ifdef MTK_INIT

223     if (!(android::base::StartsWith(name, "ro.") || android::base::StartsWith(name, "persist.log.tag"))) {
224         LOG(INFO) << "PropSet [" << name << "]=[" << value << "] Done";
225     }
226 #endif

}

[  139.622966] <1>.(1)[1:init]init: PropSet [sys.powerctl]=[shutdown,userrequested] Done
[  139.624215] <1>.(1)[1:init]init: Clear action queue and start shutdown trigger
[  139.630254] <1>.(1)[1:init]init: processing action (shutdown_done) from (:0)
[  139.631524] <1>.(1)[1:init]init: Reboot start, reason: shutdown,userrequested, rebootTarget: 
[  139.634069] <1>.(1)[1:init]init: Shutdown timeout: 0 ms

[  139.635121] <1>.(1)[1:init]init: Sending signal 9 to service 'healthd' (pid 272) process group...kernel-


system/core/init/init.cpp

void property_changed(const std::string& name, const std::string& value) {

    if (name == "sys.powerctl") {
        // Despite the above comment, we can't call HandlePowerctlMessage() in this function,
        // because it modifies the contents of the action queue, which can cause the action queue
        // to get into a bad state if this function is called from a command being executed by the
        // action queue.  Instead we set this flag and ensure that shutdown happens before the next
        // command is run in the main init loop.
        // TODO: once property service is removed from init, this will never happen from a builtin,
        // but rather from a callback from the property service socket, in which case this hack can
        // go away.
        shutdown_command = value;
        do_shutdown = true;

    }

}

这里设置do_shutdown = true;


system/core/init/init.cpp    

init 主循环中

main(..){

    am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");


    while (true) {
        // By default, sleep until something happens.
        int epoll_timeout_ms = -1;


        if (do_shutdown && !shutting_down) {
            do_shutdown = false;
            if (HandlePowerctlMessage(shutdown_command)) {
                shutting_down = true;
            }

        }

}


system/core/init/reboot.cpp 

bool HandlePowerctlMessage(const std::string& command) {

    if (cmd_params.size() > 3) {
        command_invalid = true;
    } else if (cmd_params[0] == "shutdown") {
        cmd = ANDROID_RB_POWEROFF;
        if (cmd_params.size() == 2 && cmd_params[1] == "userrequested") {
            // The shutdown reason is PowerManager.SHUTDOWN_USER_REQUESTED.
            // Run fsck once the file system is remounted in read-only mode.
            run_fsck = true;
        }

    } 

....

    LOG(INFO) << "Clear action queue and start shutdown trigger";
    ActionManager::GetInstance().ClearQueue();
    // Queue shutdown trigger first
    ActionManager::GetInstance().QueueEventTrigger("shutdown");
    // Queue built-in shutdown_done
    auto shutdown_handler = [cmd, command, reboot_target,
                             run_fsck](const std::vector&) {
        DoReboot(cmd, command, reboot_target, run_fsck);
        return 0;
    };
    ActionManager::GetInstance().QueueBuiltinAction(shutdown_handler, "shutdown_done");

}


system/core/init/action.cpp



void ActionManager::ExecuteOneCommand() {
    // Loop through the event queue until we have an action to execute
    while (current_executing_actions_.empty() && !event_queue_.empty()) {
        for (const auto& action : actions_) {
            if (std::visit([&action](const auto& event) { return action->CheckEvent(event); },
                           event_queue_.front())) {
                current_executing_actions_.emplace(action.get());
            }
        }
        event_queue_.pop();
    }


    if (current_executing_actions_.empty()) {
        return;
    }


    auto action = current_executing_actions_.front();


    if (current_command_ == 0) {
        std::string trigger_name = action->BuildTriggersString();
        LOG(INFO) << "processing action (" << trigger_name << ") from (" << action->filename()
                  << ":" << action->line() << ")";
    }


    action->ExecuteOneCommand(current_command_);


}


system/core/init/reboot.cpp 

void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget,
              bool runFsck) {
    Timer t;
    LOG(ERROR) << "Reboot start, reason: " << reason << ", rebootTarget: " << rebootTarget;


    android::base::WriteStringToFile(StringPrintf("%s\n", reason.c_str()), LAST_REBOOT_REASON_FILE,
                                     S_IRUSR | S_IWUSR, AID_SYSTEM, AID_SYSTEM);


    bool is_thermal_shutdown = false;
    if (cmd == ANDROID_RB_THERMOFF) {
        is_thermal_shutdown = true;
        runFsck = false;
    }


    auto shutdown_timeout = 0ms;
    if (!SHUTDOWN_ZERO_TIMEOUT) {
        if (is_thermal_shutdown) {
            constexpr unsigned int thermal_shutdown_timeout = 1;
            shutdown_timeout = std::chrono::seconds(thermal_shutdown_timeout);
        } else {
            constexpr unsigned int shutdown_timeout_default = 6;
            auto shutdown_timeout_property = android::base::GetUintProperty(
                "ro.build.shutdown_timeout", shutdown_timeout_default);
            shutdown_timeout = std::chrono::seconds(shutdown_timeout_property);
        }
    }
    LOG(INFO) << "Shutdown timeout: " << shutdown_timeout.count() << " ms";


    // 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"};
    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();
        } else if (s->IsShutdownCritical()) {
            s->Start();  // start shutdown critical service if not started
        }
    });


    Service* bootAnim = ServiceManager::GetInstance().FindServiceByName("bootanim");
    Service* surfaceFlinger = ServiceManager::GetInstance().FindServiceByName("surfaceflinger");
    if (bootAnim != nullptr && surfaceFlinger != nullptr && surfaceFlinger->IsRunning()) {
        ServiceManager::GetInstance().ForEachServiceInClass("animation", [](Service* s) {
            s->SetShutdownCritical();  // will not check animation class separately
        });
    }


    // optional shutdown step
    // 1. terminate all services except shutdown critical ones. wait for delay to finish
    if (shutdown_timeout > 0ms) {
        LOG(INFO) << "terminating init services";


        // Ask all services to terminate except shutdown critical ones.
        ServiceManager::GetInstance().ForEachService([](Service* s) {
            if (!s->IsShutdownCritical()) s->Terminate();
        });


        int service_count = 0;
        // Only wait up to half of timeout here
        auto termination_wait_timeout = shutdown_timeout / 2;
        while (t.duration() < termination_wait_timeout) {
            ServiceManager::GetInstance().ReapAnyOutstandingChildren();


            service_count = 0;
            ServiceManager::GetInstance().ForEachService([&service_count](Service* s) {
                // Count the number of services running except shutdown critical.
                // Exclude the console as it will ignore the SIGTERM signal
                // and not exit.
                // Note: SVC_CONSOLE actually means "requires console" but
                // it is only used by the shell.
                if (!s->IsShutdownCritical() && s->pid() != 0 && (s->flags() & SVC_CONSOLE) == 0) {
                    service_count++;
                }
            });


            if (service_count == 0) {
                // All terminable services terminated. We can exit early.
                break;
            }


            // Wait a bit before recounting the number or running services.
            std::this_thread::sleep_for(50ms);
        }
        LOG(INFO) << "Terminating running services took " << t
                  << " with remaining services:" << service_count;
    }


    // 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().ReapAnyOutstandingChildren();


    // 3. send volume shutdown to vold
    Service* voldService = ServiceManager::GetInstance().FindServiceByName("vold");
    if (voldService != nullptr && voldService->IsRunning()) {
        ShutdownVold();
        voldService->Stop();
    } else {
        LOG(INFO) << "vold not running, skipping vold shutdown";
    }
    // logcat stopped here
    ServiceManager::GetInstance().ForEachService([&kill_after_apps](Service* s) {
        if (kill_after_apps.count(s->name())) s->Stop();
    });
    // 4. sync, try umount, and optionally run fsck for user shutdown
    sync();
    UmountStat stat = TryUmountAndFsck(runFsck, shutdown_timeout - t.duration()); //runFsck 会花时间
    // Follow what linux shutdown is doing: one more sync with little bit delay
    sync();
    if (!is_thermal_shutdown) std::this_thread::sleep_for(100ms);
    LogShutdownTime(stat, &t);
    // Reboot regardless of umount status. If umount fails, fsck after reboot will fix it.
    RebootSystem(cmd, rebootTarget);
    abort();

}


开始关机

[  139.622966] <1>.(1)[1:init]init: PropSet [sys.powerctl]=[shutdown,userrequested] Done

关机结束(LogShutdownTime 打印)

[  149.290872] <0>.(0)[1:init]init: powerctl_shutdown_time_ms:9659:0



这个过程时间:

1、关闭服务

[  143.696451] <2>.(2)[1:init]init: PropSet [init.svc.logd]=[stopping] Done
[  143.696936] <2>.(1)[94:kworker/u8:1]Mali<2>: [+] MFG disable_clock 
[  143.698253] <2>.(2)[1:init]init: Sending signal 9 to service 'tombstoned' (pid 367) process group...
[  143.705282] <2>.(2)[1:init]init: Successfully killed process cgroup uid 1058 pid 367 in 5ms
[  143.707150] <2>.(2)[1:init]init: PropSet [init.svc.tombstoned]=[stopping] Done


2、runFsck 为true 的话

[  144.467429] <1>.(1)[1:init]e2fsck: libc: /system/bin/e2fsck: malloc debug enabled
[  144.467429] <1>
[  144.468768] <1>.(1)[1:init]e2fsck: e2fsck 1.43.3 (04-Sep-2016)







system/core/init/reboot.cpp 
static void __attribute__((noreturn))
RebootSystem(unsigned int cmd, const std::string& rebootTarget) {
    LOG(INFO) << "Reboot ending, jumping to kernel";


    if (!IsRebootCapable()) {
        // On systems where init does not have the capability of rebooting the
        // device, just exit cleanly.
        exit(0);
    }


    switch (cmd) {
        case ANDROID_RB_POWEROFF:
            reboot(RB_POWER_OFF);

            break;


        case ANDROID_RB_RESTART2:
            syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
                    LINUX_REBOOT_CMD_RESTART2, rebootTarget.c_str());
            break;


        case ANDROID_RB_THERMOFF:
            reboot(RB_POWER_OFF);
            break;
    }
    // In normal case, reboot should not return.
    PLOG(FATAL) << "reboot call returned";
    abort();
}



#define RB_POWER_OFF    LINUX_REBOOT_CMD_POWER_OFF

4.4/kernel/reboot.c   

SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
void __user *, arg){

     case LINUX_REBOOT_CMD_POWER_OFF:

do_gettimeofday(&start);
printk(KERN_ERR " %14s: %lu.%03lu [sec]\n", "Total time",
       start.tv_sec,
       (unsigned long) (start.tv_usec/1000));
                kernel_power_off();
                do_exit(0);

                break;

}


 

[  139.622966]<1>.(1)[1:init]init: PropSet [sys.powerctl]=[shutdown,userrequested] Done

 

[  139.635121]<1>.(1)[1:init]init: Sending signal 9 to service 'healthd' (pid 272)process group...

[  143.698253]<2>.(2)[1:init]init: Sending signal 9 to service 'tombstoned' (pid 367)process group...

 

关闭服务花时间   4s

 

 

[  143.753199]<2>.(2)[1:init]init: umounted/dev/block/platform/mtk-msdc.0/11120000.msdc0/by-name/persist:/vendor/persistopts rw,seclabel,nosuid,nodev,noatime,nodelalloc,noauto_da_alloc,commit=1,data=ordered

[  144.217226]<2>.(2)[1:init]init: umounted/dev/block/platform/mtk-msdc.0/11120000.msdc0/by-name/userdata:/data optsrw,lazytime,seclabel,nosuid,nodev,noatime,background_gc=on,discard,no_heap,user_xattr,inline_xattr,acl,inline_data,inline_dentry,extent_cache,mode=adaptive,active_logs=6

卸载分区化时间 0.5s

 

 

[  144.467429]<1>.(1)[1:init]e2fsck: libc: /system/bin/e2fsck: malloc debug enabled

[  145.019986]<1>.(1)[1:init]e2fsck: cache: 14/7168 files (0.0% non-contiguous),1490/28672 blocks

[  149.146942]<1>.(1)[1:init]fsck.f2fs: libc: /system/bin/fsck.f2fs: malloc debugenabled

[  149.189094]<0>.(0)[1:init]fsck.f2fs: Done.

e2fsck 跟 fsck 花时间 4.7s

 

 

[  149.290872]<0>.(0)[1:init]init: powerctl_shutdown_time_ms:9659:0

[  149.291735]<0>.(0)[1:init]init: Reboot ending, jumping to kernel

 

 

这里看能不能把 e2fsck 跟 fsck 花时间 4.7s    优化


实测6580平台,关机时间确实较6739平台长;关机时间长 9~10S; 

分析:
关机系统调用前:
在PowerManagerService.java中增加  打印当前时间日志;
    public static void lowLevelShutdown(String reason) {
Slog.e(TAG, "System.currentTimeMillis" + System.currentTimeMillis());
 } 

 Kernel 中,接收到关机系统调用时:
  在reboot.c 增加打印当前时间日志:
SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
void __user *, arg){
case LINUX_REBOOT_CMD_POWER_OFF:
do_gettimeofday(&start);
printk(KERN_ERR " %14s: %lu.%03lu [sec]\n", "Total time",
       start.tv_sec,
       (unsigned long) (start.tv_usec/1000));
}

测试发现:
关机系统调用前 ,系统当前时间:
PowerManagerService: System.currentTimeMillis1514765385955
Kernel收到系统调用时,系统当前时间:
[1:init]     Total time: 1514765395.623 [sec]
  
  这两者的差值接近10s;而内核关机时间在1s左右;
因此大部分时间是消耗在关机系统调用延迟过程中,即:
 SystemProperties.set("sys.powerctl", "shutdown," + reason);




L 上面

https://www.2cto.com/kf/201501/367859.html

你可能感兴趣的:(android,c)