Android O關(guān)機(jī)流程

Android O關(guān)機(jī)流程


問題起因

*今天測試提出了一個(gè)問題缨叫,關(guān)機(jī)過程中(播放關(guān)機(jī)動畫)按Power鍵可以熄屏卒煞、亮屏狸驳。

解決方案

*首先我想應(yīng)該從關(guān)機(jī)流程開始吧藕咏,然后自己一步步跟進(jìn)代碼,修改framework代碼邏輯贸铜,在關(guān)機(jī)時(shí)堡纬,禁用Power鍵

關(guān)機(jī)流程

想必都很清楚正常關(guān)機(jī)是如何操作的,按Power鍵來確定關(guān)機(jī)蒿秦,這里首先來分析一下PhoneWindowManager這個(gè)類隐轩,這個(gè)類Power、volum等事件處理
PhoneWindowManager.java

public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { 
    ...
    switch (keyCode) {
    ...
        case KeyEvent.KEYCODE_POWER: {
            // Any activity on the power button stops the accessibility shortcut
            cancelPendingAccessibilityShortcutAction();
            result &= ~ACTION_PASS_TO_USER;
            isWakeKey = false; // wake-up will be handled separately
            if (down) {
                interceptPowerKeyDown(event, interactive);
            } else {
                interceptPowerKeyUp(event, interactive, canceled);
            }
            break;
        }
     ...
     }
 }

因?yàn)槭前聪翽ower走的interceptPowerKeyDown這個(gè)函數(shù)渤早。

private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
    ...
    if (!mPowerKeyHandled) {
        if (interactive) {
            // When interactive, we're already awake.
            // Wait for a long press or for the button to be released to decide what to do.
            if (hasLongPressOnPowerBehavior()) {
                Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
                msg.setAsynchronous(true);
                mHandler.sendMessageDelayed(msg,
                        ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
            }
        } else {
            wakeUpFromPowerKey(event.getDownTime());

            if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
                Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
                msg.setAsynchronous(true);
                mHandler.sendMessageDelayed(msg,
                        ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
                mBeganFromNonInteractive = true;
            } else {
                final int maxCount = getMaxMultiPressPowerCount();

                if (maxCount <= 1) {
                    mPowerKeyHandled = true;
                } else {
                    mBeganFromNonInteractive = true;
                }
            }
        }
    }
}

直接看關(guān)鍵部分,判斷是否是LongPress职车,是的話就通過Handler發(fā)送消息處理,追蹤到mHandler鹊杖,handlemessage里面調(diào)用powerLongPress()這個(gè)私有函數(shù)來處理長按power悴灵。

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);
        break;
    }
}

將mPowerKeyHandled設(shè)置為true表示這個(gè)行為已經(jīng)被處理了,其實(shí)是正在處理骂蓖。showGlobalActionsInternal()這個(gè)函數(shù)我想應(yīng)該就是處理長按power顯示的對話框吧积瞒。

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

果不其然,創(chuàng)建了GlobalActions類對象登下,而從注釋該類介紹來看是一個(gè)創(chuàng)建全局對話框的幫助類茫孔,構(gòu)造方法中獲得各種系統(tǒng)服務(wù),其中有AudioManager被芳、WindowManagerFuncs缰贝,其中關(guān)機(jī)我們應(yīng)該看的是WindowManagerFuncs這個(gè)服務(wù),他獲取的是WindowManagerService畔濒。再來看showDialog這個(gè)方法剩晴。

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 GlobalActionsDialog createDialog() {
    ...
    if (GLOBAL_ACTION_KEY_POWER.equals(actionKey)) {
            mItems.add(new PowerAction());
        } else if (GLOBAL_ACTION_KEY_REBOOT.equals(actionKey)) {
            mItems.add(new RebootAction());
        } 
    ...
}

其中handleShow方法最終調(diào)用createDialog();這個(gè)方法來創(chuàng)建GlobalActionsDialog這個(gè)對話框?qū)ο螅渲欣酶鞣N參數(shù)Action來控制item的各種行為侵状,我們這里要看的就是PowerAction

private final class PowerAction extends SinglePressAction implements LongPressAction {
    ...
    @Override
    public void onPress() {         
       mWindowManagerFuncs.shutdown(true/* confirm */);      
    }
}

看到這里就都明白了赞弥,通過對話框關(guān)機(jī),這里調(diào)用的是mWindowManagerFuncs.shutdown趣兄,這個(gè)方法绽左,這里mWindowManagerFuncs也就是WindowManagerService這個(gè)服務(wù)

@Override
public void shutdown(boolean confirm) {
    ShutdownThread.shutdown(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
}

其中通過名字可以知道調(diào)用了一個(gè)關(guān)機(jī)線程來處理,簡單點(diǎn)的話就可以直接追蹤到run方法艇潭。這里就不知道看代碼了拼窥,通過打印信息來看看做了什么

11-18 20:00:17.061 1361-5920/system_process I/ShutdownThread: Sending shutdown broadcast...
11-18 20:00:18.710 1361-5920/system_process I/ShutdownThread: Shutting down activity manager...
11-18 20:00:18.913 1361-5920/system_process I/ShutdownThread: Shutting down package manager...
11-18 20:00:18.937 1361-6051/system_process W/ShutdownThread: Turning off cellular radios...
11-18 20:00:18.953 1361-6051/system_process I/ShutdownThread: Waiting for NFC, Bluetooth and Radio...
11-18 20:00:19.455 1361-6051/system_process I/ShutdownThread: Radio turned off.
11-18 20:00:19.455 1361-6051/system_process I/ShutdownThread: NFC, Radio and Bluetooth shutdown complete.
11-18 20:00:19.459 1361-5920/system_process I/ShutdownThread: Shutting down MountService
11-18 20:00:20.461 1361-5920/system_process W/ShutdownThread: Shutdown wait timed out
11-18 20:00:20.504 1361-5920/system_process I/ShutdownThread: waitShutdownAnimation true
11-18 20:00:20.510 1361-5920/system_process I/ShutdownThread: wait SHUTDOWN_ANIMATION_SERVICE completed. time out 14
11-18 20:00:20.836 1361-1712/system_process W/ShutdownThread: Result code 0 from MountService.shutdown
11-18 20:00:21.510 1361-5920/system_process I/ShutdownThread: wait SHUTDOWN_ANIMATION_SERVICE completed. time out 13
11-18 20:00:22.511 1361-5920/system_process I/ShutdownThread: wait SHUTDOWN_ANIMATION_SERVICE completed. time out 12
11-18 20:00:23.511 1361-5920/system_process I/ShutdownThread: wait SHUTDOWN_ANIMATION_SERVICE completed. time out 11
11-18 20:00:24.512 1361-5920/system_process I/ShutdownThread: wait SHUTDOWN_ANIMATION_SERVICE completed. time out 10
11-18 20:00:26.014 1361-5920/system_process I/ShutdownThread: Performing low-level shutdown...

首先發(fā)送關(guān)機(jī)廣播承粤,關(guān)閉一系列服務(wù)AMS、PKMS闯团、radio、NFC等等等仙粱,等待關(guān)機(jī)動畫完成房交。

  • 流程理清楚了,解決起來就很簡單了伐割,在ShutdownThread設(shè)置一個(gè)靜態(tài)成員變量 public static boolean isShutDowning = false; 候味,執(zhí)行run方法就將這個(gè)標(biāo)示設(shè)為true
  • 然后在PhoneWindowManager的powerPress函數(shù)中添加判斷是否禁用Power。

驗(yàn)證了也確實(shí)OK

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末隔心,一起剝皮案震驚了整個(gè)濱河市白群,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌硬霍,老刑警劉巖帜慢,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異唯卖,居然都是意外死亡粱玲,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進(jìn)店門拜轨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抽减,“玉大人,你說我怎么就攤上這事橄碾÷殉粒” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵法牲,是天一觀的道長史汗。 經(jīng)常有香客問我,道長拒垃,這世上最難降的妖魔是什么淹办? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮恶复,結(jié)果婚禮上怜森,老公的妹妹穿的比我還像新娘。我一直安慰自己谤牡,他們只是感情好副硅,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著翅萤,像睡著了一般恐疲。 火紅的嫁衣襯著肌膚如雪腊满。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天培己,我揣著相機(jī)與錄音碳蛋,去河邊找鬼。 笑死省咨,一個(gè)胖子當(dāng)著我的面吹牛肃弟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播零蓉,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼笤受,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了敌蜂?” 一聲冷哼從身側(cè)響起箩兽,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎章喉,沒想到半個(gè)月后汗贫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡秸脱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年芳绩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片撞反。...
    茶點(diǎn)故事閱讀 39,795評論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡妥色,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出遏片,到底是詐尸還是另有隱情嘹害,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布吮便,位于F島的核電站笔呀,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏髓需。R本人自食惡果不足惜许师,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望僚匆。 院中可真熱鬧微渠,春花似錦、人聲如沸咧擂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽松申。三九已至云芦,卻和暖如春俯逾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背舅逸。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工桌肴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人琉历。 一個(gè)月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓坠七,卻偏偏與公主長得像,于是被迫代替她去往敵國和親善已。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容