Power按键流程分析
2016-09-12 14:01
274 查看
从InputManagerService分析我们知道,当按下手机的Power键之后,按键事件会传到InputDispatcher 的notifyKey 方法,然后调用到调用了NativeInputManager的interceptKeyBeforeQueueing函数,最终在这个函数中会调用到PhoneWindowManager中的interceptKeyBeforeQueueing函数,以上主要属于InputManagerService的范畴,Power按键流程我们从PhoneWindowManager 的interceptKeyBeforeQueueing 方法开始分析。
方法interceptKeyBeforeQueueing关键步骤:
第一步:初始化关键变量
首先判断系统是否启动完成,然后就是初始化一些关键变量
Interactive 表示屏幕是否点亮,这个变量表示PowerManagerService关于屏幕的状态
Down 表示是否是ActionDown事件
Canceled 事件是否取消
keyCode 按键编码
第二步,根据interative的状态的处理一些基本逻辑
第三步,处理Power按键的事件
首先是Power按键的事件的话,不再分发到应用,如果是ActionDown事件执行InterceptPowerKeyDown()方法,如果是ActionUP事件则执行InterceptPowerKeyUp()方法
下一步继续分析interceptPowerKeyDown方法
获取Power按键的锁,直到释放Power键
……
如果当前是亮屏状态,且满足触发截屏的条件,触发截屏功能
如果有电话拨入,且电话铃声响起的话,这个时候按Power键,设置电话响铃静音
如果正在接听电话,且配置了Power键挂断电话的话,按Power按键挂断正在接听的电话
……
如果按Power按键执行了截图功能或者电话静音或者挂断电话等功能后,Power事件不在传递,表示已经消耗掉了Power事件
如果未消耗掉Power事件,继续执行此处逻辑
分为两种情况
1, 当前是亮屏状态
2, 当前是灭屏状态
当前亮屏状态
首先判断是否支持长按的行为
先来看看hasLongPressOnPowerBehavior函数
再来看看getResolvedLongPressOnPowerBehavior函数
由于systemProperty中的factory.long_press_power_off" 配置为0,所以不支持灭屏长按功能,。因此只要看mLongPressOnPowerBehavior这个变量
mLongPreesOnPowerBehavior 默认配置获取为
config_longPressOnPowerBehavior默认值为1,所以mLongPressOnPowerBehavior = 1,最后hasLongPressOnPowerBehavior返回true
当hasLongPressOnPowerBehavior返回true,则发送MSG_POWER_LONG_PRESS的Handler消息,Handler处理消息调用 powerLongPress()方法,接着我们来看下Handler处理消息的逻辑
由以上的分析指导getResolvedLongPressOnPowerBehavior的值为1,所以执行case LONG_PRESS_POWER_GLOBAL_ACTIONS,
将mPowerKeyHandled的值设置为true,表示处理了PowerDown事件,showGlobalActionsInternal()方法弹出关机,重启对话框
1. 当屏幕是灭屏状态
首先执行wakeUpFromPowerKey方法,唤醒手机系统,最终调用mPowerManager.wakeUp(wakeTime, reason)来唤醒手机
然后mSupportLongPressPowerWhenNonInteractive默认不支持,所以默认执行
在灭屏的时候,和亮屏长按的时候mPowerKeyHandled最后设置为true,即handle为true,直接执行finishPowerKeyPress方法,释放mPowerKeyWakeLock
在亮屏短按的时候,handled为false,由以上分析,手机默认不支持多次按键所以maxCount为1,mPowerKeyPressCounter=1,所以直接执行powerPress方法
由于mPowerKeyPressCounter 为1,所以执行case SHORT_PRESS_POWER_GO_TO_SLEEP,调用mPowerManager.goToSleep休眠系统
Power按键流程总结
Power按键
1.亮屏 down
长按 弹出关闭重启对话框
短按 不做处理
亮屏 up
长按 不做处理
短按 调用goToSleep休眠系统
2. 灭屏 down
调用wakeup 唤醒系统
灭屏 up
不做处理
方法interceptKeyBeforeQueueing关键步骤:
第一步:初始化关键变量
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的状态的处理一些基本逻辑
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按键的事件
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方法
private void interceptPowerKeyDown(KeyEvent event, boolean interactive) { if (!mPowerKeyWakeLock.isHeld()) { mPowerKeyWakeLock.acquire(); }
获取Power按键的锁,直到释放Power键
……
if (interactive && !mScreenshotChordPowerKeyTriggered && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { mScreenshotChordPowerKeyTriggered = true; mScreenshotChordPowerKeyTime = event.getDownTime(); interceptScreenshotChord(); }
如果当前是亮屏状态,且满足触发截屏的条件,触发截屏功能
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按键挂断正在接听的电话
……
mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered || mScreenshotChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
如果按Power按键执行了截图功能或者电话静音或者挂断电话等功能后,Power事件不在传递,表示已经消耗掉了Power事件
if (!mPowerKeyHandled) {
如果未消耗掉Power事件,继续执行此处逻辑
分为两种情况
1, 当前是亮屏状态
2, 当前是灭屏状态
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函数
private boolean hasLongPressOnPowerBehavior() { return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING; }
再来看看getResolvedLongPressOnPowerBehavior函数
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 默认配置获取为
mLongPressOnPowerBehavior = mContext.getResources().getInteger( com.android.internal.R.integer.config_longPressOnPowerBehavior);
config_longPressOnPowerBehavior默认值为1,所以mLongPressOnPowerBehavior = 1,最后hasLongPressOnPowerBehavior返回true
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处理消息的逻辑
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默认不支持,所以默认执行
final int maxCount = getMaxMultiPressPowerCount(); if (maxCount <= 1) { mPowerKeyHandled = true; } else { mBeganFromNonInteractive = true; }
getMaxMultiPressPowerCount() ==1,默认不支持对此按键,所以将mPowerKeyHandled设置为true,表示处理了PowerDown事件 2,处理PowerUp事件 PowerUp事件也分为两种情况,分别对应PowerDown的亮屏和灭屏两种情况
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方法
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
不做处理
相关文章推荐
- Power按键流程分析
- Android 4.0按键事件以及电源管理流程分析
- 分析Power key的处理流程
- (十)(1) Z-Stack中OSAL按键事件的触发流程分析
- uboot流程分析--修改android启动模式按键
- 分析Power key的处理流程
- 按键触摸屏流程分析
- TI BLE协议栈 按键流程分析
- Android Framework层Power键关机流程(一,Power长按键操作处理)
- android 应用监听输入法按键事件【比如搜索和回车键等】的整个流程分析
- ZStack协议按键处理流程分析
- android4.0 Power、home、menu等按键处理分析
- 分析Power key的处理流程
- Android 4.0按键事件以及系统流程分析
- Android Framework层Power键关机流程(一,Power长按键操作处理)
- 按键,触摸屏流程分析
- android4.0 Power、home、menu等按键处理分析
- Android 4.0按键事件以及电源管理流程分析
- CC2530按键流程分析相当于zigbee协议栈分析
- android4.4 PowerManagerService流程分析