Android关机流程

PowerManager
源码:frameworks/base/core/java/android/os/PowerManager.java
public void reboot(String reason) {
try {
mService.reboot(false, reason, true);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

public void shutdown(boolean confirm, String reason, boolean wait) {
try {
mService.shutdown(confirm, reason, wait);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

IPowerManager
源码:frameworks/base/core/java/android/os/IPowerManager.aidl
定义接口
interface IPowerManager
{
….
void reboot(boolean confirm, String reason, boolean wait);
void shutdown(boolean confirm, String reason, boolean wait);
….
}

PowerManagerService
源码:frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

public void reboot(boolean confirm, String reason, boolean wait) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
if (PowerManager.REBOOT_RECOVERY.equals(reason)
|| PowerManager.REBOOT_RECOVERY_UPDATE.equals(reason)) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
}

        final long ident = Binder.clearCallingIdentity();
        try {
            shutdownOrRebootInternal(HALT_MODE_REBOOT, confirm, reason, wait);
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }

public void shutdown(boolean confirm, String reason, boolean wait) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);

        final long ident = Binder.clearCallingIdentity();
        try {
            shutdownOrRebootInternal(HALT_MODE_SHUTDOWN, confirm, reason, wait);
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }

confirm如果为true则弹出确认对话框

private void shutdownOrRebootInternal(final @HaltMode int haltMode, final boolean confirm,
final String reason, boolean wait) {
if (mHandler == null || !mSystemReady) {
throw new IllegalStateException(“Too early to call shutdown() or reboot()”);
}

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            synchronized (this) {
                if (haltMode == HALT_MODE_REBOOT_SAFE_MODE) {
                    ShutdownThread.rebootSafeMode(mContext, confirm);
                } else if (haltMode == HALT_MODE_REBOOT) {
                    ShutdownThread.reboot(mContext, reason, confirm);
                } else {
                    ShutdownThread.shutdown(mContext, reason, confirm);
                }
            }
        }
    };
  ...
}

ShutdownThread
源码:frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java

public static void shutdown(final Context context, String reason, boolean confirm) {
    mReboot = false;
    mRebootSafeMode = false;
   ...
    if (SystemProperties.getBoolean("ro.monkey", false)) { //monkey测试不允许误关机
        Log.d(TAG, "Cannot request to shutdown when Monkey is running, returning.");
        return;
    }

    shutdownInner(context, confirm);
}

public static void reboot(final Context context, String reason, boolean confirm) {

shutdownInner(context, confirm);
}

static void shutdownInner(final Context context, boolean confirm) {

if (confirm) {

powerOffDialog.setCallBack(new PowerOffDialog.OnCallBack() {
@Override
public void onShutDown() {
beginShutdownSequence(context);
}

        @Override
        public void onReboot() {
            reboot(context,null,false);
        }
        });
 ...

powerOffDialog.show();//关闭对话框
}else{
beginShutdownSequence(context);
}

}

private static void beginShutdownSequence(Context context) {


// start the thread that initiates shutdown
sInstance.mContext = context;
sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
sInstance.mHandler = new Handler() {
};


sInstance.start(); //ShutdownThread run函数运行


PowerManagerService.lowLevelShutdown(mReason);

}

PowerManagerService
源码:frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
public static void lowLevelShutdown(String reason) {
if (reason == null) {
reason = “”;
}
SystemProperties.set(“sys.powerctl”, “shutdown,” + reason);
}

ShutdownThread
源码:frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java
因为ShutdownThread extends Thread,所以 ShutdownThread中run函数自动运行,run函数主要
调用running函数发送关机广播 关闭ActivityManagerService PackageManagerService radios和MountService
最后调用rebootOrShutdown进行关机或者重启处理,
IPO(instent power on mtk设计的快速开关机)

public void run() {
checkShutdownFlow();
while (mShutdownFlow == IPO_SHUTDOWN_FLOW) {
mShutdownManager.saveStates(mContext);
mShutdownManager.enterShutdown(mContext);
switchToLauncher(); //切换至桌面能够停止耗时进程,使关机流程更加流畅
running();
}
if (mShutdownFlow != IPO_SHUTDOWN_FLOW) {
mShutdownManager.enterShutdown(mContext);
switchToLauncher();
running();
}
}

private void running() {
mContext.sendBroadcast(new Intent(ACTION_PRE_SHUTDOWN)); //发送关机广播
/// @} 2012-05-20
Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
intent.putExtra(“_mode”, mShutdownFlow);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendOrderedBroadcastAsUser(intent,
UserHandle.ALL, null, br, mHandler, 0, null, null);

//广播等待时间MAX_BROADCAST_TIME,进度条显示等待
final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
synchronized (mActionDoneSync) {
while (!mActionDone) {
long delay = endTime - SystemClock.elapsedRealtime();
if (delay <= 0) {
Log.w(TAG, “Shutdown broadcast ACTION_SHUTDOWN timed out”);
if (mShutdownFlow == IPO_SHUTDOWN_FLOW) {
Log.d(TAG, changeToNormalMessage + “: ACTION_SHUTDOWN timeout”);
mShutdownFlow = NORMAL_SHUTDOWN_FLOW;
}
break;
} else if (mRebootHasProgressBar) {
int status = (int)((MAX_BROADCAST_TIME - delay) * 1.0 *
BROADCAST_STOP_PERCENT / MAX_BROADCAST_TIME);
sInstance.setRebootProgress(status, null);
}
try {
mActionDoneSync.wait(Math.min(delay, PHONE_STATE_POLL_SLEEP_MSEC));
} catch (InterruptedException e) {
}
}
}
if (mRebootHasProgressBar) {
sInstance.setRebootProgress(BROADCAST_STOP_PERCENT, null);
}

/关闭ActivityManager/
if (mShutdownFlow != IPO_SHUTDOWN_FLOW) {
Log.i(TAG, “Shutting down activity manager…”);

        final IActivityManager am =
            ActivityManagerNative.asInterface(ServiceManager.checkService("activity"));
        if (am != null) {
            try {
                am.shutdown(MAX_BROADCAST_TIME);
            } catch (RemoteException e) {
            }
        }
        if (mRebootHasProgressBar) {
            sInstance.setRebootProgress(ACTIVITY_MANAGER_STOP_PERCENT, null);
        }
    }

/关闭PackageManager/
final PackageManagerService pm = (PackageManagerService)
ServiceManager.getService(“package”);
if (pm != null) {
pm.shutdown();
}
if (mRebootHasProgressBar) {
sInstance.setRebootProgress(PACKAGE_MANAGER_STOP_PERCENT, null);
}

/关闭radio,最大等待时间MAX_RADIO_WAIT_TIME,超时则直接强制关闭/
shutdownRadios(MAX_RADIO_WAIT_TIME);
if (mRebootHasProgressBar) {
sInstance.setRebootProgress(RADIO_STOP_PERCENT, null);
}


/关闭mount service/
/关机动画/
SystemProperties.set(“service.shutanim.running”, “1”);

/关机震动/
Vibrator vibrator = new SystemVibrator(mContext);
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);
}

mShutdownManager.shutdown(mContext);
mShutdownManager.finishShutdown(mContext);

if ((mReboot == true && mReason != null && mReason.equals(“recovery”)) ||
(mReboot == false)) {
delayForPlayAnimation(); //延时
}
sInstance.mPowerManager.goToSleep(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_SHUTDOWN, 0);
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);
        } catch (InterruptedException unused) {
        }
    }

    // Shutdown power
    Log.i(TAG, "Performing low-level shutdown...");
    PowerManagerService.lowLevelShutdown(reason);
}

PowerManagerService
源码:frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

关机
public static void lowLevelShutdown(String reason) {
if (reason == null) {
reason = “”;
}
SystemProperties.set(“sys.powerctl”, “shutdown,” + reason); //设置完后便会关机
}

重启
public static void lowLevelReboot(String reason) {
if (reason == null) {
reason = “”;
}
if (reason.equals(PowerManager.REBOOT_RECOVERY)
|| reason.equals(PowerManager.REBOOT_RECOVERY_UPDATE)) { //重启进入recovery
SystemProperties.set(“sys.powerctl”, “reboot,recovery”);
} else {
SystemProperties.set(“sys.powerctl”, “reboot,” + reason); //设置完后便会重启,那到底是什么进程在监控控制呢?
}
try {
Thread.sleep(20 * 1000L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
Slog.wtf(TAG, “Unexpected return from lowLevelReboot!”);//超过20秒,说明重启失败,正常情况下不会执行到这里!
}

下面探索底层关机实现原理

在system/core/rootdir/init.rc中定义了powerctl这样一个触发器:
on property:sys.powerctl=*
powerctl ${sys.powerctl}

当sys.powerctl这个属性值不为空的时候,会调用powerctl命令,并将值传递给powerctl
system/core/init/builtins.cpp中

builtins是init.rc解释服务后被init进程启动用于设置各服务入口函数的,上面 powerctl ${sys.powerctl}便是builtins中定义的入口之一。

BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
constexpr std::size_t kMax = std::numeric_limits::max();
static const Map builtin_functions = {

{“powerctl”, {1, 1, do_powerctl}},

};
return builtin_functions;
}
因此会去调用do_powerctl函数
static int do_powerctl(const std::vector& args) {
const char* command = args[1].c_str();
int len = 0;
unsigned int cmd = 0;
const char *reboot_target = “”;
void (callback_on_ro_remount)(const struct mntent) = NULL;

if (strncmp(command, "shutdown", 8) == 0) {
    cmd = ANDROID_RB_POWEROFF;
    len = 8;
} else if (strncmp(command, "reboot", 6) == 0) {
    cmd = ANDROID_RB_RESTART2;
    len = 6;
} else {
    ERROR("powerctl: unrecognized command '%s'\n", command);
    return -EINVAL;
}

if (command[len] == ',') {
    if (cmd == ANDROID_RB_POWEROFF &&
        !strcmp(&command[len + 1], "userrequested")) {
        // The shutdown reason is PowerManager.SHUTDOWN_USER_REQUESTED.
        // Run fsck once the file system is remounted in read-only mode.
        callback_on_ro_remount = unmount_and_fsck;
    } else if (cmd == ANDROID_RB_RESTART2) {
        reboot_target = &command[len + 1];
    }
} else if (command[len] != '\0') {
    ERROR("powerctl: unrecognized reboot target '%s'\n", &command[len]);
    return -EINVAL;
}

std::string timeout = property_get("ro.build.shutdown_timeout");
unsigned int delay = 0;

if (android::base::ParseUint(timeout.c_str(), &delay) && delay > 0) {
    Timer t;
// Ask all services to terminate.
    ServiceManager::GetInstance().ForEachService(
        [] (Service* s) { s->Terminate(); });

    while (t.duration() < delay) {
        ServiceManager::GetInstance().ReapAnyOutstandingChildren();

        int service_count = 0;
        ServiceManager::GetInstance().ForEachService(
            [&service_count] (Service* s) {
                // Count the number of services running.
                // 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->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.
        usleep(kTerminateServiceDelayMicroSeconds);
    }
    NOTICE("Terminating running services took %.02f seconds", t.duration());
}

/前面主要是参数解析,下面调用android_reboot_with_callback执行关机或重启操作/
return android_reboot_with_callback(cmd, 0, reboot_target,
callback_on_ro_remount);
}

继续往下跟进去
system/core/libcutils/android_reboot.c
int android_reboot_with_callback(
int cmd, int flags __unused, const char *arg,
void (cb_on_remount)(const struct mntent))
{
int ret;
remount_ro(cb_on_remount);
switch (cmd) {
case ANDROID_RB_RESTART:
ret = reboot(RB_AUTOBOOT);
break;

    case ANDROID_RB_POWEROFF: //关机
        ret = reboot(RB_POWER_OFF);
        break;

    case ANDROID_RB_RESTART2:  //重启
        ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
                       LINUX_REBOOT_CMD_RESTART2, arg);  //这里使用到了系统调用,还需要继续寻找...
        break;

    default:
        ret = -1;
}

return ret;

}

/旧版本使用的是android_reboot这个函数/
int android_reboot(int cmd, int flags, const char *arg)
{
return android_reboot_with_callback(cmd, flags, arg, NULL);
}

继续走。。。
reboot
源码:bionic/libc/bionic/reboot.cpp
extern “C” int __reboot(int, int, int, void*);
int reboot(int mode) {
return __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, mode, NULL);
}

bionic/libc/kernel/uapi/linux/reboot.h
#ifndef _UAPI_LINUX_REBOOT_H
#define _UAPI_LINUX_REBOOT_H
#define LINUX_REBOOT_MAGIC1 0xfee1dead
#define LINUX_REBOOT_MAGIC2 672274793
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define LINUX_REBOOT_MAGIC2A 85072278
#define LINUX_REBOOT_MAGIC2B 369367448
#define LINUX_REBOOT_MAGIC2C 537993216
#define LINUX_REBOOT_CMD_RESTART 0x01234567
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define LINUX_REBOOT_CMD_HALT 0xCDEF0123
#define LINUX_REBOOT_CMD_CAD_ON 0x89ABCDEF
#define LINUX_REBOOT_CMD_CAD_OFF 0x00000000
#define LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4
#define LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2
#define LINUX_REBOOT_CMD_KEXEC 0x45584543
#endif

bionic/libc/arch-arm64/syscalls/__reboot.S
ENTRY(__reboot)
mov x8, __NR_reboot
svc #0

cmn     x0, #(MAX_ERRNO + 1)
cneg    x0, x0, hi
b.hi    __set_errno_internal

ret

END(__reboot)
.hidden __reboot
~
bionic/libc/kernel/uapi/asm-arm/asm/unistd.h
#define __NR_reboot (__NR_SYSCALL_BASE + 88)

bionic/libc/kernel/uapi/asm-arm/asm/unistd.h
#define __NR_SYSCALL_BASE 0

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值