Android O关机流程

Android O关机流程


问题起因

*今天测试提出了一个问题,关机过程中(播放关机动画)按Power键可以熄屏、亮屏。

解决方案

*首先我想应该从关机流程开始吧,然后自己一步步跟进代码,修改framework代码逻辑,在关机时,禁用Power键

关机流程

想必都很清楚正常关机是如何操作的,按Power键来确定关机,这里首先来分析一下PhoneWindowManager这个类,这个类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;
        }
     ...
     }
 }

因为是按下Power走的interceptPowerKeyDown这个函数。

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

直接看关键部分,判断是否是LongPress,是的话就通过Handler发送消息处理,追踪到mHandler,handlemessage里面调用powerLongPress()这个私有函数来处理长按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设置为true表示这个行为已经被处理了,其实是正在处理。showGlobalActionsInternal()这个函数我想应该就是处理长按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);
    }
}

果不其然,创建了GlobalActions类对象,而从注释该类介绍来看是一个创建全局对话框的帮助类,构造方法中获得各种系统服务,其中有AudioManager、WindowManagerFuncs,其中关机我们应该看的是WindowManagerFuncs这个服务,他获取的是WindowManagerService。再来看showDialog这个方法。

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方法最终调用createDialog();这个方法来创建GlobalActionsDialog这个对话框对象,其中利用各种参数Action来控制item的各种行为,我们这里要看的就是PowerAction

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

看到这里就都明白了,通过对话框关机,这里调用的是mWindowManagerFuncs.shutdown,这个方法,这里mWindowManagerFuncs也就是WindowManagerService这个服务

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

其中通过名字可以知道调用了一个关机线程来处理,简单点的话就可以直接追踪到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...

首先发送关机广播,关闭一系列服务AMS、PKMS、radio、NFC等等等,等待关机动画完成。

  • 流程理清楚了,解决起来就很简单了,在ShutdownThread设置一个静态成员变量 public static boolean isShutDowning = false; ,执行run方法就将这个标示设为true
  • 然后在PhoneWindowManager的powerPress函数中添加判断是否禁用Power。

验证了也确实OK

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容

  • 前面我们讲解了系统截屏按键处理流程,HOME按键处理流程,今天再来讲解一下电源开关机按键事件流程。关机操作也是系统...
    一航jason阅读 2,118评论 0 0
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,913评论 25 707
  • 1:InputChannel提供函数创建底层的Pipe对象 2: 1)客户端需要新建窗口 2)new ViewRo...
    自由人是工程师阅读 5,291评论 0 18
  • 今天是我的生日,父亲! 哦,忘了,这不需要我提醒你的,你一直都记得从来不会忘记,从小到大,从我成为你的儿子...
    稻泓阅读 225评论 0 0
  • 懂得那么多的道理却还是过不好这一生,或许是现代人最真实的写照。困顿,迷惘,彷徨,谁都有过,有人终其一生也无法自拔。...
    李彧飞阅读 255评论 6 1