Android 通過power鍵關(guān)機重啟的流程(Android層)

Android 通過power鍵關(guān)機重啟的流程(Android層)

一、結(jié)論,android系統(tǒng)的關(guān)機和重啟最終都是通過修改SystemProperties的屬性來完成的。

二、屬性名稱?

關(guān)機:name:sys.powerctl? value:shutdown+reason? reason可以為空;所以完全可以在三方應(yīng)用中通過SystemProperties.set("sys.powerctl", "shutdown,"

+ reason);來進行關(guān)機;同事你也可以通過adb shell setprop

sys.powerctl shutdown來進行關(guān)機。

重啟:name:sys.powerctl? value:reboot+reason? 同樣reason可以為空;如果你需要重啟到recovery,那么value對應(yīng)的為reboot,recovery

?三、說明:長按的關(guān)機和重啟是在如下幾個xml中進行聲明定義,完了之后在GlobalActions中進行對應(yīng)的處理

frameworks/base/core/res/res/values/config.xm

frameworks/base/core/res/res/values/strings.xml

frameworks/base/core/res/res/values-zh-rCN/strings.xml

frameworks/base/policy/src/com/Android/internal/policy/impl/GlobalActions.Java

代碼比較簡單,不是本文的重點。這就不貼了。

?四、代碼流程分析:

1、首先在GlobalActions中有處理onPress()和onLongPress(),很簡單,對應(yīng)的就是關(guān)機和重啟;

//關(guān)機

????public void onPress() {

???????????// shutdown by making sure radio and power are handled accordingly.

???????????mWindowManagerFuncs.shutdown(false /* confirm */);

???????}

??? }

? //重啟

?? ?public boolean onLongPress() {

?? ????UserManager um = (UserManager)mContext.getSystemService(Context.USER_SERVICE);

???????????if (!um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) {

???????????????mWindowManagerFuncs.rebootSafeMode(true);

??????????????? return true;

???????????}

???????????return false;

???????}

2、為了方便說明,以關(guān)機流程為例進行說明,重啟的類似。可以看到在代碼中直接調(diào)用mWindowManagerFuncs對應(yīng)的方法。mWindowManagerFuncs是抽象類WindowManagerFuncs的對象,WindowManagerFuncs是WindowManagerPolicy內(nèi)部一個抽象內(nèi)部類,最終是由WindowManagerService來實現(xiàn)的,所以理所當然的接下來代碼會進入到WindowManagerService中的shutdown方法中;

??public void shutdown(boolean confirm) {

???????ShutdownThread.shutdown(mContext, PowerManager.SHUTDOWN_USER_REQUESTED,confirm);

}

沒什么好說的,代碼關(guān)鍵點就一句,直接進入ShutdownThread

3、進入ShutdownThread的方法中,看具體做了什么處理

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

//省略如果

//接下來這個是一個注意點,那么就是為什么再跑monkey時手動關(guān)機關(guān)不了。原

//因就在這里,可以看到如果在monkey的時候直接return了。注意,這并不是說你

//無法關(guān)掉設(shè)備,只是無法通過按鍵關(guān),你同樣可以采用文章開頭的方式進行關(guān)機。

???????if (SystemProperties.getBoolean("ro.monkey", false)) {

???????????Log.d(TAG, "Cannot request to shutdown when Monkey is running,returning.");

???????????return;

???????}

?//真正關(guān)機的重點流程在這

???????shutdownInner(context, confirm);

}

4、shutdownInner的內(nèi)部處理

static void shutdownInner(final Contextcontext, boolean confirm) {

??????//省略

? //在這部分代碼中會構(gòu)造處確定是否關(guān)機的dialog,并處理起對應(yīng)的事件,篇幅過長

? ? ? ?//這里就省略了。關(guān)機對應(yīng)的處理在下面這個方法

???????????beginShutdownSequence(context);

}

private static void

beginShutdownSequence(Context context) {

// 省略

// sInstance是shutdownThread的實例,shutdownThread是一個Thread,所以接下來run()

sInstance.start();

}

5、shutdownThread線程的處理

??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();

???????}

}

6、

private void running() {

?????//省略

???????/*

????????* 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);

???????}

???????/*

????????* If we are rebooting into safe mode, write a system property

????????* indicating so.

????????*/

???????if (mRebootSafeMode) {

???????????SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1");

???????}

? //關(guān)機的廣播在這里發(fā)出去的

???????/// M:2012-05-20ALPS00286063 @{

???????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);

????//關(guān)閉radio,包括藍牙wifi telephony等

? ????????// Shutdown radios.

???????Log.i(TAG, "Shutting down radios...");

???????shutdownRadios(MAX_RADIO_WAIT_TIME);

???????if (mRebootHasProgressBar) {

???????????sInstance.setRebootProgress(RADIO_STOP_PERCENT, null);

???????}

?? //…………

???????????rebootOrShutdown(mContext, mReboot, mReason);

???????}

}

7、在rebootOrShutdown這個方法中直接調(diào)用

PowerManagerService.lowLevelShutdown(reason);

完了之后在lowLevelShutdown中直接通過SystemProperties.set("sys.powerctl", "shutdown,"

+ reason);關(guān)機。

往下之后的處理會進入到kernel進行。后續(xù)在整理。

五、另外,上面說的是按power鍵彈dialog關(guān)機重啟的流程,關(guān)于一直長按power鍵關(guān)機是在PhoneWindowManager中調(diào)用powerLongPress處理的。

?private void powerLongPress() {

???????final int behavior = getResolvedLongPressOnPowerBehavior();

???????switch (behavior) {

???????case LONG_PRESS_POWER_NOTHING:

???????????break;

???????case LONG_PRESS_POWER_GLOBAL_ACTIONS:

???????????mPowerKeyHandled = true;

???????????if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS,false)) {

???????????????performAuditoryFeedbackForAccessibilityIfNeed();

???????????}

???????????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);

//原理一樣,也是調(diào)用?? mWindowManagerFuncs.shutdown方法

???????????break;

???????}

??? }

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。