一,先直接上流程图
二,代码详细分析
1. @frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager());
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
}
2. @WindowManagerService.java (frameworks\base\services\core\java\com\android\server\wm)
public static WindowManagerService main(final Context context, final InputManagerService im,
final boolean haveInputMethods, final boolean showBootMsgs, final boolean onlyCore,
WindowManagerPolicy policy) {
DisplayThread.getHandler().runWithScissors(() ->
sInstance = new WindowManagerService(context, im, haveInputMethods, showBootMsgs,
onlyCore, policy), 0);
return sInstance;
}
// Called by window manager policy. Not exposed externally.
@Override
public void shutdown(boolean confirm) {
// Pass in the UI context, since ShutdownThread requires it (to show UI).
ShutdownThread.shutdown(ActivityThread.currentActivityThread().getSystemUiContext(),
PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
}
3. @PhoneWindowManager.java (frameworks\base\services\core\java\com\android\server\policy)
没有构造函数?用默认的?
public class PhoneWindowManager implements WindowManagerPolicy {
mWindowManagerFuncs = windowManagerFuncs;
@Override 在哪调用?
public void init(Context context, IWindowManager windowManager,
WindowManagerFuncs windowManagerFuncs) {
mContext = context;
mWindowManager = windowManager;
mWindowManagerFuncs = windowManagerFuncs; //指向 WindowManagerService
}
private class PolicyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
case MSG_POWER_LONG_PRESS:
powerLongPress();
break;
}
private void powerLongPress() {
final int behavior = getResolvedLongPressOnPowerBehavior(); 永远是1 !!!!!
switch (behavior) {
case LONG_PRESS_POWER_GLOBAL_ACTIONS:
showGlobalActionsInternal();
break
case LONG_PRESS_POWER_SHUT_OFF:
case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
mPowerKeyHandled = true;
performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF); //实际调用WindowManagerService.shutdown
break;
}
}
void showGlobalActionsInternal() {
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
if (mGlobalActions == null) {
mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
}
final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());显示关机对话框
if (keyguardShowing) {
// since it took two seconds of long press to bring this up,
// poke the wake lock so they have some time to see the dialog.
mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
}
}
@GlobalActions.java (frameworks\base\services\core\java\com\android\server\policy)
public void showDialog(boolean keyguardShowing, boolean deviceProvisioned) {
mKeyguardShowing = keyguardShowing;
mDeviceProvisioned = deviceProvisioned;
mShowing = true;
if (mStatusBarConnected) {
mStatusBarInternal.showGlobalActions(); //StatusBarManagerInternal mStatusBarInternal;
mHandler.postDelayed(mShowTimeout, 5000);
} else {
// SysUI isn't alive, show legacy menu.
ensureLegacyCreated();
mLegacyGlobalActions.showDialog(mKeyguardShowing, mDeviceProvisioned);
}
}
@StatusBarManagerService.java (frameworks\base\services\core\java\com\android\server\statusbar)
public void showGlobalActions() {
if (mBar != null) {
try {
mBar.showGlobalActionsMenu(); //mBar 是CommandQueue
} catch (RemoteException ex) {}
}
}
@StatusBar.java (frameworks\base\packages\systemui\src\com\android\systemui\statusbar\phone) 323521 10/25/2017
mBarService = IStatusBarService.Stub.asInterface(ServiceManager.getService(Context.STATUS_BAR_SERVICE));
// Connect in to the status bar manager service
mCommandQueue = getComponent(CommandQueue.class);
mCommandQueue.addCallbacks(this);
try {
mBarService.registerStatusBar(mCommandQueue, iconSlots, icons, switches, binders,
fullscreenStackBounds, dockedStackBounds);
} catch (RemoteException ex) {
// If the system process isn't there we're doomed anyway.
}
@CommandQueue.java (frameworks\base\packages\systemui\src\com\android\systemui\statusbar)
public void showGlobalActionsMenu() {
synchronized (mLock) {
mHandler.removeMessages(MSG_SHOW_GLOBAL_ACTIONS);
mHandler.obtainMessage(MSG_SHOW_GLOBAL_ACTIONS).sendToTarget(); //mCallbacks.get(i).handleShowGlobalActionsMenu();
}
}
@GlobalActionsComponent.java (frameworks\base\packages\systemui\src\com\android\systemui\globalactions)
public void handleShowGlobalActionsMenu() {
mExtension.get().showGlobalActions(this); //mExtension.get() = GlobalActionsImpl
}
@GlobalActionsImpl.java (frameworks\base\packages\systemui\src\com\android\systemui\globalactions)
public void showGlobalActions(GlobalActionsManager manager) {
if (mGlobalActions == null) {
mGlobalActions = new GlobalActionsDialog(mContext, manager);
}
mGlobalActions.showDialog(mKeyguardMonitor.isShowing(), mDeviceProvisionedController.isDeviceProvisioned());
}
@GlobalActionsDialog.java (frameworks\base\packages\systemui\src\com\android\systemui\globalactions)
public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned) {
mKeyguardShowing = keyguardShowing;
mDeviceProvisioned = isDeviceProvisioned;
if (mDialog != null) {
mDialog.dismiss();
mDialog = null;
// Show delayed, so that the dismiss of the previous dialog completes
mHandler.sendEmptyMessage(MESSAGE_SHOW);
} else {
handleShow();
}
}
private void handleShow() {
awakenIfNecessary();
mDialog = createDialog(); //创建ActionsDialog
prepareDialog();
// If we only have 1 item and it's a simple press action, just do this action.
if (mAdapter.getCount() == 1
&& mAdapter.getItem(0) instanceof SinglePressAction
&& !(mAdapter.getItem(0) instanceof LongPressAction)) {
((SinglePressAction) mAdapter.getItem(0)).onPress();
} else {
WindowManager.LayoutParams attrs = mDialog.getWindow().getAttributes();
attrs.setTitle("ActionsDialog");
mDialog.getWindow().setAttributes(attrs);
mDialog.show(); //此处显示关机对话框!!!!
mWindowManagerFuncs.onGlobalActionsShown();
}
}
public void onClick(DialogInterface dialog, int which) {
Action item = mAdapter.getItem(which);
if (!(item instanceof SilentModeTriStateAction)) {
dialog.dismiss();
}
item.onPress(); //item = PowerAction 此处处理关机的选项
}
private final class PowerAction extends SinglePressAction implements LongPressAction {
@Override
public void onPress() {
// shutdown by making sure radio and power are handled accordingly.
mWindowManagerFuncs.shutdown(); 指向 WindowManagerService
}
}
4. @WindowManagerService.java (frameworks\base\services\core\java\com\android\server\wm)
public class WindowManagerService extends IWindowManager.Stub implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs
// Called by window manager policy. Not exposed externally.
@Override
public void shutdown(boolean confirm) {
// Pass in the UI context, since ShutdownThread requires it (to show UI).
ShutdownThread.shutdown(ActivityThread.currentActivityThread().getSystemUiContext(),
PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
}
5. @ShutdownThread.java (frameworks\base\services\core\java\com\android\server\power)
// static instance of this thread
private static final ShutdownThread sInstance = new ShutdownThread();
public static void shutdown(final Context context, String reason, boolean confirm) {
mReboot = false;
mRebootSafeMode = false;
mReason = reason;
shutdownInner(context, confirm); -> beginShutdownSequence
}
private static void beginShutdownSequence(Context context) {
sInstance.mProgressDialog = showShutdownDialog(context);
sInstance.mContext = context;
sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
// make sure we never fall asleep again
sInstance.mCpuWakeLock = null;
try {
sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock( 申请一把锁,防止系统休眠
PowerManager.PARTIAL_WAKE_LOCK, TAG + "-cpu");
sInstance.mCpuWakeLock.setReferenceCounted(false);
sInstance.mCpuWakeLock.acquire();
} catch (SecurityException e) {
Log.w(TAG, "No permission to acquire wake lock", e);
sInstance.mCpuWakeLock = null;
}
// also make sure the screen stays on for better user experience, 此处可以直接黑屏
//添加sInstance.mPowerManager.setBacklightBrightnessOff(true);
sInstance.mScreenWakeLock = null;
if (sInstance.mPowerManager.isScreenOn()) {
try {
sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock(
PowerManager.FULL_WAKE_LOCK, TAG + "-screen");
sInstance.mScreenWakeLock.setReferenceCounted(false);
sInstance.mScreenWakeLock.acquire();
} catch (SecurityException e) {
Log.w(TAG, "No permission to acquire wake lock", e);
sInstance.mScreenWakeLock = null;
}
}
// start the thread that initiates shutdown
sInstance.mHandler = new Handler() {
};
sInstance.start(); //开始ShutdownThread.run
}
public void run() {
TimingsTraceLog shutdownTimingLog = newTimingsLog(); 耗费时间的输出
shutdownTimingLog.traceBegin("SystemServerShutdown");
BroadcastReceiver br = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
// We don't allow apps to cancel this, so ignore the result.
actionDone();
}
};
/*
* Write a system property in case the system_server reboots before we
* get to the actual hardware restart. If that happens, we'll retry at
* the beginning of the SystemServer startup.
*/
{
String reason = (mReboot ? "1" : "0") + (mReason != null ? mReason : "");
SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason); //SHUTDOWN_ACTION_PROPERTY = sys.shutdown.requested
}
//1. First send the high-level shut down broadcast. 发送关机广播,最大超时MAX_BROADCAST_TIME=10*1000;
shutdownTimingLog.traceBegin("SendShutdownBroadcast");
mActionDone = false;
Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
mContext.sendOrderedBroadcastAsUser(intent,
UserHandle.ALL, null, br, mHandler, 0, null, null);
shutdownTimingLog.traceEnd(); // 输出 log: SendShutdownBroadcast took to complete: 836ms
2.
final IActivityManager am =
IActivityManager.Stub.asInterface(ServiceManager.checkService("activity"));
if (am != null) {
try {
am.shutdown(MAX_BROADCAST_TIME); 关闭activitymanager
} catch (RemoteException e) {
}
}
3.
final PackageManagerService pm = (PackageManagerService)
ServiceManager.getService("package");
if (pm != null) {
pm.shutdown(); 关闭Packagemanager
}
4.
shutdownRadios(MAX_RADIO_WAIT_TIME); 关闭无线, 最大超时MAX_RADIO_WAIT_TIME=12*1000;
5.
final IStorageManager storageManager = IStorageManager.Stub.asInterface(
ServiceManager.checkService("mount"));
if (storageManager != null) {
storageManager.shutdown(observer); 关闭storageManager, 最大超时MAX_SHUTDOWN_WAIT_TIME=20*1000
} else {
Log.w(TAG, "StorageManagerService unavailable for shutdown");
}
rebootOrShutdown(mContext, mReboot, mReason);
}
public static void rebootOrShutdown(final Context context, boolean reboot, String reason) {
if (reboot) {
Log.i(TAG, "Rebooting, reason: " + reason);
PowerManagerService.lowLevelReboot(reason);
Log.e(TAG, "Reboot failed, will attempt shutdown instead");
reason = null;
} else if (SHUTDOWN_VIBRATE_MS > 0 && context != null) {
// vibrate before shutting down
Vibrator vibrator = new SystemVibrator(context);
try {
vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES);
} catch (Exception e) {
// Failure to vibrate shouldn't interrupt shutdown. Just log it.
Log.w(TAG, "Failed to vibrate during shutdown.", e);
}
// vibrator is asynchronous so we need to wait to avoid shutting down too soon.
try {
Thread.sleep(SHUTDOWN_VIBRATE_MS);持续500ms的震动
} catch (InterruptedException unused) {
}
}
// Shutdown power
Log.i(TAG, "Performing low-level shutdown...");
PowerManagerService.lowLevelShutdown(reason);
}
6. @PowerManagerService.java (frameworks\base\services\core\java\com\android\server\power)
public static void lowLevelShutdown(String reason) {
if (reason == null) {
reason = "";
}
SystemProperties.set("sys.powerctl", "shutdown," + reason);
}
6.1. @Property_service.cpp (system\core\init) 如何知道和处理system prop的改变
void start_property_service() {
property_set("ro.property_service.version", "2");
property_set_fd = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
false, 0666, 0, 0, nullptr, sehandle); 创建socket: dev/socket/property_service, 用于监听
if (property_set_fd == -1) {
PLOG(ERROR) << "start_property_service socket creation failed";
exit(1);
}
listen(property_set_fd, 8);
register_epoll_handler(property_set_fd, handle_property_set_fd);
}
handle_property_set_fd()
->handle_property_set(socket, prop_value, prop_value, true);
->property_set(name, value);
->PropertySetImpl(name, value)
->property_changed(name, value);
6.2. @Init.cpp (system\core\init)
void property_changed(const std::string& name, const std::string& value) {
// If the property is sys.powerctl, we bypass the event queue and immediately handle it.
// This is to ensure that init will always and immediately shutdown/reboot, regardless of
// if there are other pending events to process or if init is waiting on an exec service or
// waiting on a property.
// In non-thermal-shutdown case, 'shutdown' trigger will be fired to let device specific
// commands to be executed.
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;
}
if (property_triggers_enabled) ActionManager::GetInstance().QueuePropertyChange(name, value);
if (waiting_for_prop) {
if (wait_prop_name == name && wait_prop_value == value) {
LOG(INFO) << "Wait for property took " << *waiting_for_prop;
ResetWaitForProp();
}
}
}
7. @Init.cpp (system\core\init)
int main(int argc, char** argv) {
init进程启动*.rc中的进程后,开始处理下列事件等
while (true) {
// By default, sleep until something happens. 使用的是epoll机制
int epoll_timeout_ms = -1;
if (do_shutdown && !shutting_down) { 等待property_changed中收到sys.powerctl属性的改变,do_shutdown会变为true
do_shutdown = false;
if (HandlePowerctlMessage(shutdown_command)) {
shutting_down = true;
}
}
if (!(waiting_for_prop || sm.IsWaitingForExec())) {
am.ExecuteOneCommand(); 从ActionManager的执行队列中,取出命令逐个执行
}
if (!(waiting_for_prop || sm.IsWaitingForExec())) {
if (!shutting_down) restart_processes();
// If there's a process that needs restarting, wake up in time for that.
if (process_needs_restart_at != 0) {
epoll_timeout_ms = (process_needs_restart_at - time(nullptr)) * 1000;
if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;
}
// If there's more work to do, wake up again immediately.
if (am.HasMoreCommands()) epoll_timeout_ms = 0;
}
epoll_event ev;
int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms)); 如何等待的?
if (nr == -1) {
PLOG(ERROR) << "epoll_wait failed";
} else if (nr == 1) {
((void (*)()) ev.data.ptr)();
}
}
}
8. @Reboot.cpp (system\core\init)
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;
}
}
// Queue shutdown trigger first
ActionManager::GetInstance().ClearQueue(); 清除队列中所有action, 然后再添加shutdown action到ActionManager的执行队列中,main@init.cpp会从该队列中取出命令逐个执行
ActionManager::GetInstance().QueueEventTrigger("shutdown"); 在哪解析的这个shutdown命令呢?这个直接忽略!!!
// Queue built-in shutdown_done
auto shutdown_handler = [cmd, command, reboot_target,
run_fsck](const std::vector<std::string>&) {
DoReboot(cmd, command, reboot_target, run_fsck);
return 0;
};
ActionManager::GetInstance().QueueBuiltinAction(shutdown_handler, "shutdown_done"); 关机执行的后期关键函数是shutdown_handler->DoReboot
// Skip wait for prop if it is in progress
ResetWaitForProp();
// Skip wait for exec if it is in progress
if (ServiceManager::GetInstance().IsWaitingForExec()) {
ServiceManager::GetInstance().ClearExecWait();
}
return true;
}
void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget, bool runFsck) {
{
// optional shutdown step
// 1. terminate all services except shutdown critical ones. wait for delay to finish, "ro.build.shutdown_timeout"
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++;
}
});
// 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(); //数据回写到EMMC
UmountStat stat = TryUmountAndFsck(runFsck, shutdown_timeout - t.duration());
// 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();
}
tatic 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();
}
9. @Reboot.cpp (bionic\libc\bionic)
extern "C" int __reboot(int, int, int, void*);
int reboot(int mode) {
return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, mode, NULL); _reboot通过syscall来到内核
}
10. @bionic/libc/arch-arm/syscalls/__reboot.S
ENTRY(__reboot)
mov ip, r7
.cfi_register r7, ip
ldr r7, =__NR_reboot
swi #0
mov r7, ip
.cfi_restore r7
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno_internal
END(__reboot)
11. @Linux-syscalls.h (bionic\tools\versioner\platforms\android-9\include\sys)
#define __NR_reboot (__NR_SYSCALL_BASE + 88)
其被指定了一个固定的偏移量,在被调用的时候就是通过这个偏移量去内核中寻找对应的入口的,由此可见,内核中一定有着相同的定义,否则将不能成功调用。
内核中对syscall偏移量的定义 在内核源码中的arch/arm/include/asm/unistd.h,相关信息完全一致。
12. @kernel-3.18/arch/arm64/include/asm/unistd32.h
#define __NR_reboot 88
__SYSCALL(__NR_reboot, sys_reboot)
13. @Syscalls.h (kernel-3.18/include\linux)
asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user *arg);
#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)
14. @Reboot.c (kernel-3.18/kernel)
/*
* Reboot system call: for obvious reasons only root may call it,
* and even root needs to set up some magic numbers in the registers
* so that some mistake won't make this reboot the whole machine.
* You can also set the meaning of the ctrl-alt-del-key here.
*
* reboot doesn't sync: do that yourself before calling this.
*/
SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
void __user *, arg)
{
switch (cmd) {
case LINUX_REBOOT_CMD_POWER_OFF:
kernel_power_off();
do_exit(0);
break;
}
}
/**
* kernel_power_off - power_off the system
*
* Shutdown everything and perform a clean system power_off.
*/
void kernel_power_off(void)
{
kernel_shutdown_prepare(SYSTEM_POWER_OFF);
if (pm_power_off_prepare)
pm_power_off_prepare();
migrate_to_reboot_cpu();
syscore_shutdown();
pr_emerg("Power down\n");
kmsg_dump(KMSG_DUMP_POWEROFF);
machine_power_off();
}
由此进入kernel的关机流程了,以后再继续分析!!!
static void kernel_shutdown_prepare(enum system_states state)
{
blocking_notifier_call_chain(&reboot_notifier_list, 通知注册过监听关机或重启消息的模块
(state == SYSTEM_HALT) ? SYS_HALT : SYS_POWER_OFF, NULL);
system_state = state;
usermodehelper_disable();
device_shutdown(); 关闭所有驱动设备
}
15. @Core.c (drivers\base)
/**
* device_shutdown - call ->shutdown() on each device to shutdown.
*/
void device_shutdown(void)
{
while (!list_empty(&devices_kset->list)) {
dev = list_entry(devices_kset->list.prev, struct device,
kobj.entry);
if (dev->bus && dev->bus->shutdown) {
if (1)
dev_info(dev, "shutdown\n");
dev->bus->shutdown(dev);
} else if (dev->driver && dev->driver->shutdown) {
if (1)
dev_info(dev, "shutdown\n");
dev->driver->shutdown(dev);
}
}
16. @Syscore.c (drivers\base)
/**
* syscore_shutdown - Execute all the registered system core shutdown callbacks.
*/
void syscore_shutdown(void)
{
struct syscore_ops *ops;
mutex_lock(&syscore_ops_lock);
list_for_each_entry_reverse(ops, &syscore_ops_list, node)
if (ops->shutdown) {
if (initcall_debug)
pr_info("PM: Calling %pF\n", ops->shutdown);
ops->shutdown();
}
mutex_unlock(&syscore_ops_lock);
}
17. @Process.c (arch\arm\kernel)
/*
* Power-off simply requires that the secondary CPUs stop performing any
* activity (executing tasks, handling interrupts). smp_send_stop()
* achieves this. When the system power is turned off, it will take all CPUs
* with it.
*/
void machine_power_off(void)
{
local_irq_disable();
smp_send_stop();
pr_emerg("machine_power_off, pm_power_off(%p)\n", pm_power_off);
dump_stack();
if (pm_power_off) 各个硬件平台的PMIC power off函数
pm_power_off();
}
18. @Psci.c (arch\arm\kernel)
static int psci_0_2_init(struct device_node *np)
{
pm_power_off = psci_sys_poweroff; 平台级别的power off函数
}