前面已经讲到了lowLevelShutdown()与lowLevelReboot()都在PowerManagerService.java实现,都只是设置一个属性:SystemProperties.set(sys.powerctl, xxx);这里从这继续往下讲:
sys.powerctl属性触发开关在init.rc定义:
on property:sys.powerctl=*
powerctl ${sys.powerctl}
on property:sys.powerctl=*表示当属性sys.powerctl设置为任何值是都会跑到这里,触发动作是powerctl ${sys.powerctl},这个动作的意思是调用powerctl指令,并把sys.powerctl的值传给它。powerctl指令在init进程会执行。
从下面的表可知,powerctl对应的操作是do_powerctl
[system/core/init/keywords.h]
KEYWORD(powerctl, COMMAND, 1, do_powerctl)
do_powerctl的实现代码如下:
794 int do_powerctl(int nargs, char **args)
795 {
796 char command[PROP_VALUE_MAX];
797 int res;
798 int len = 0;
799 int cmd = 0;
800 char *reboot_target;
801
802 res = expand_props(command, args[1], sizeof(command));
803 if (res) {
804 ERROR("powerctl: cannot expand '%s'\n", args[1]);
805 return -EINVAL;
806 }
807
808 if (strncmp(command, "shutdown", 8) == 0) {
809 cmd = ANDROID_RB_POWEROFF;
810 len = 8;
811 } else if (strncmp(command, "reboot", 6) == 0) {
812 cmd = ANDROID_RB_RESTART2;
813 len = 6;
814 } else {
815 ERROR("powerctl: unrecognized command '%s'\n", command);
816 return -EINVAL;
817 }
818
819 if (command[len] == ',') {
820 reboot_target = &command[len + 1];
821 } else if (command[len] == '\0') {
822 reboot_target = "";
823 } else {
824 ERROR("powerctl: unrecognized reboot target '%s'\n", &command[len]);
825 return -EINVAL;
826 }
827
828 return android_reboot(cmd, 0, reboot_target);
829 }
可以看到最后其调用的是android_reboot()函数,其实现如下:
107 int android_reboot(int cmd, int flags UNUSED, char *arg)
108 {
109 int ret;
110
111 sync();
112 remount_ro();
113
114 switch (cmd) {
115 case ANDROID_RB_RESTART:
116 ret = reboot(RB_AUTOBOOT);
117 break;
118
119 case ANDROID_RB_POWEROFF:
120 ret = reboot(RB_POWER_OFF);
121 break;
122
123 case ANDROID_RB_RESTART2:
124 ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
125 LINUX_REBOOT_CMD_RESTART2, arg);
126 break;
127
128