您的位置:首页 > 其它

Power按键流程分析

2017-11-18 14:20 453 查看
从InputManagerService分析我们知道,当按下手机的Power键之后,按键事件会传到InputDispatcher 的notifyKey 方法,然后调用到调用了NativeInputManager的interceptKeyBeforeQueueing函数,最终在这个函数中会调用到PhoneWindowManager中的interceptKeyBeforeQueueing函数,以上主要属于InputManagerService的范畴,Power按键流程我们从PhoneWindowManager 的interceptKeyBeforeQueueing 方法开始分析。

方法interceptKeyBeforeQueueing关键步骤:

第一步:初始化关键变量

[java] view
plain copy

if (!mSystemBooted) {

return 0;

}

final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;

final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;

final boolean canceled = event.isCanceled();

final int keyCode = event.getKeyCode();

final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;

首先判断系统是否启动完成,然后就是初始化一些关键变量

Interactive 表示屏幕是否点亮,这个变量表示PowerManagerService关于屏幕的状态

Down 表示是否是ActionDown事件

Canceled 事件是否取消

keyCode 按键编码

第二步,根据interative的状态的处理一些基本逻辑

[java] view
plain copy

if (interactive || (isInjected && !isWakeKey)) {

//事件传递给用户

result = ACTION_PASS_TO_USER;

isWakeKey = false;

} else if (!interactive && shouldDispatchInputWhenNonInteractive()) {

result = ACTION_PASS_TO_USER;

} else {

result = 0;

if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {

isWakeKey = false;

}

}

if (isValidGlobalKey(keyCode)

&& mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {

if (isWakeKey) {

//直接唤醒系统

wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, " android.policy:KEY");

}

return result;

}

第三步,处理Power按键的事件

[java] view
plain copy

case KeyEvent.KEYCODE_POWER: {

result &= ~ACTION_PASS_TO_USER;

isWakeKey = false; // wake-up will be handled separately

if (down) {

Power键按下

interceptPowerKeyDown(event, interactive);

} else {

Power键释放

interceptPowerKeyUp(event, interactive, canceled);

}

break;

}

首先是Power按键的事件的话,不再分发到应用,如果是ActionDown事件执行InterceptPowerKeyDown()方法,如果是ActionUP事件则执行InterceptPowerKeyUp()方法

下一步继续分析interceptPowerKeyDown方法

[java] view
plain copy

private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {

if (!mPowerKeyWakeLock.isHeld()) {

mPowerKeyWakeLock.acquire();

}

获取Power按键的锁,直到释放Power键

……

[java] view
plain copy

if (interactive && !mScreenshotChordPowerKeyTriggered

&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {

mScreenshotChordPowerKeyTriggered = true;

mScreenshotChordPowerKeyTime = event.getDownTime();

interceptScreenshotChord();

}

如果当前是亮屏状态,且满足触发截屏的条件,触发截屏功能

[java] view
plain copy

TelecomManager telecomManager = getTelecommService();

boolean hungUp = false;

if (telecomManager != null) {

if (telecomManager.isRinging()) {

telecomManager.silenceRinger();

} else if ((mIncallPowerBehavior

& Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0

&& telecomManager.isInCall() && interactive) {

hungUp = telecomManager.endCall();

}

}

如果有电话拨入,且电话铃声响起的话,这个时候按Power键,设置电话响铃静音

如果正在接听电话,且配置了Power键挂断电话的话,按Power按键挂断正在接听的电话

……

[java] view
plain copy

mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered

|| mScreenshotChordVolumeUpKeyTriggered || gesturedServiceIntercepted;

如果按Power按键执行了截图功能或者电话静音或者挂断电话等功能后,Power事件不在传递,表示已经消耗掉了Power事件

[java] view
plain copy

if (!mPowerKeyHandled) {

如果未消耗掉Power事件,继续执行此处逻辑

分为两种情况

1, 当前是亮屏状态

2, 当前是灭屏状态

[java] view
plain copy

if (interactive) {

//是否支持长按功能

if (hasLongPressOnPowerBehavior()) {

Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);

msg.setAsynchronous(true);

//发送MSG_POWER_LONG_PRESS消息,有Handler来处理

mHandler.sendMessageDelayed(msg,

ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());

}

} else {

//当前灭屏状态,此时按Power键,先唤醒系统

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;

}

}

}

}

}

当前亮屏状态

首先判断是否支持长按的行为

先来看看hasLongPressOnPowerBehavior函数

[java] view
plain copy

private boolean hasLongPressOnPowerBehavior() {

return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;

}

再来看看getResolvedLongPressOnPowerBehavior函数

[java] view
plain copy

private int getResolvedLongPressOnPowerBehavior() {

if (FactoryTest.isLongPressOnPowerOffEnabled()) {

return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;

}

return mLongPressOnPowerBehavior;

}

由于systemProperty中的factory.long_press_power_off" 配置为0,所以不支持灭屏长按功能,。因此只要看mLongPressOnPowerBehavior这个变量

mLongPreesOnPowerBehavior 默认配置获取为

[java] view
plain copy

mLongPressOnPowerBehavior = mContext.getResources().getInteger(

com.android.internal.R.integer.config_longPressOnPowerBehavior);

config_longPressOnPowerBehavior默认值为1,所以mLongPressOnPowerBehavior = 1,最后hasLongPressOnPowerBehavior返回true

[java] view
plain copy

if (hasLongPressOnPowerBehavior()) {

Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);

msg.setAsynchronous(true);

mHandler.sendMessageDelayed(msg,

ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());

}

当hasLongPressOnPowerBehavior返回true,则发送MSG_POWER_LONG_PRESS的Handler消息,Handler处理消息调用 powerLongPress()方法,接着我们来看下Handler处理消息的逻辑

[java] view
plain copy

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;

……

由以上的分析指导getResolvedLongPressOnPowerBehavior的值为1,所以执行case LONG_PRESS_POWER_GLOBAL_ACTIONS,

mPowerKeyHandled的值设置为true,表示处理了PowerDown事件,showGlobalActionsInternal()方法弹出关机,重启对话框

1. 当屏幕是灭屏状态

首先执行wakeUpFromPowerKey方法,唤醒手机系统,最终调用mPowerManager.wakeUp(wakeTime, reason)来唤醒手机

然后mSupportLongPressPowerWhenNonInteractive默认不支持,所以默认执行

[java] view
plain copy

final int maxCount = getMaxMultiPressPowerCount();

if (maxCount <= 1) {

mPowerKeyHandled = true;

} else {

mBeganFromNonInteractive = true;

}

[java] view
plain copy

getMaxMultiPressPowerCount() ==1,默认不支持对此按键,所以将mPowerKeyHandled设置为true,表示处理了PowerDown事件

2,处理PowerUp事件

PowerUp事件也分为两种情况,分别对应PowerDown的亮屏和灭屏两种情况

[java] view
plain copy

private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {

final boolean handled = canceled || mPowerKeyHandled;

……

if (!handled) {

mPowerKeyPressCounter += 1;

final int maxCount = getMaxMultiPressPowerCount();

final long eventTime = event.getDownTime();

if (mPowerKeyPressCounter < maxCount) {

Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,

interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);

msg.setAsynchronous(true);

mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());

return;

}

powerPress(eventTime, interactive, mPowerKeyPressCounter);

}

finishPowerKeyPress();

}

在灭屏的时候,和亮屏长按的时候mPowerKeyHandled最后设置为true,即handle为true,直接执行finishPowerKeyPress方法,释放mPowerKeyWakeLock

在亮屏短按的时候,handled为false,由以上分析,手机默认不支持多次按键所以maxCount为1,mPowerKeyPressCounter=1,所以直接执行powerPress方法

[java] view
plain copy

private void powerPress(long eventTime, boolean interactive, int count) {

if (count == 2) {

powerMultiPressAction(eventTime, interactive,mDoublePressOnPowerBehavior);

} else if (count == 3) {

powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);

} else if (interactive && !mBeganFromNonInteractive) {

switch (mShortPressOnPowerBehavior) {

case SHORT_PRESS_POWER_NOTHING:

break;

case SHORT_PRESS_POWER_GO_TO_SLEEP:

mPowerManager.goToSleep(eventTime,

PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);

break;

case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:

mPowerManager.goToSleep(eventTime,

PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,

PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);

break;

case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:

mPowerManager.goToSleep(eventTime,

PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,

PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);

launchHomeFromHotKey();

break;

case SHORT_PRESS_POWER_GO_HOME:

launchHomeFromHotKey(true /* awakenFromDreams */, false

break;

}

}

}

由于mPowerKeyPressCounter 为1,所以执行case SHORT_PRESS_POWER_GO_TO_SLEEP,调用mPowerManager.goToSleep休眠系统

Power按键流程总结

Power按键

1.亮屏 down

长按 弹出关闭重启对话框

短按 不做处理

亮屏 up

长按 不做处理

短按 调用goToSleep休眠系统

2. 灭屏 down

调用wakeup 唤醒系统

灭屏 up

不做处理

原文地址: http://blog.csdn.net/zhenjie_chang/article/details/52512823
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: