android6.0 power按键深入分析
2016-06-02 20:28
549 查看
这篇博客主要分析power按键点亮屏幕和灭屏,而且我们主要分析在PhoneWIndowManager的流程。
之前的博客我们分析过按键的流程,当有按键会先到PhoneWindowManager的interceptKeyBeforeQueueing函数,然后再去分析到应用,而power按键也是如此,并且其最后不会分发到应用中去,下面我们看下PhoneWindowManager的interceptKeyBeforeQueueing函数对power按键处理的代码:
顺便说下这个interactive这个变量是从NativeInputManager中传过来的,在NativeInputManager也是有一个mInteractive的成员变量,是PowerManagerService改变状态的时候在Notifier.java中调用InputManagerService的Native方法,到NativeInputManager的方法nativeSetInteractive方法来设置的mInteractive变量的。所以这个值也可以说是PowerManagerService关于屏幕的状态。
再来看看getResolvedLongPressOnPowerBehavior函数
其中又调用了isLongPressOnPowerOffEnabled,我们没有支持这个属性。因此只要看mLongPressOnPowerBehavior这个变量
下面再看看mLongPressOnPowerBehavior 这个变量的初始化。
看资源apk:
也就是mLongPressOnPowerBehavior = 1,最后hasLongPressOnPowerBehavior返回1.
然后就发消息,我们再来看处理消息:
再来看powerLongPress函数
上面之前我们再添加长按对话框添加重启功能的那篇博客有涉及,这就是在亮屏的时候长按power的流程。
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;
}
}第一步直接调用wakeUpFromPowerKey函数,我们看下这个函数:
这里mAllowTheaterModeWakeFromPowerKey为true,因此就直接调用了PowerManager的wakeUp函数了,reason是"android.policy:POWER"
而下面mSupportLongPressPowerWhenNonInteractive 我们配置也是false不支持。多按钮也不支持,因此maxCount为1
二、PowerKey On
PowerKey on 又分为之前down的时候是灭屏还是亮屏处理的,逻辑又不一样。
之前在手机灭屏我们按power键down的时候,最后mPowerKeyHandled = true,这里handled = true,最后直接调用
之前power按键 down的时候手机亮屏,power down又分为长按和短按。我们先来看之前power down亮屏,down是长按的情况下,现在是power up的情况:
之前看过这函数,长按mPowerKeyHandled = true,和上面一样。直接最后interceptPowerKeyUp函数就调用finishPowerKeyPress函数了。
然后我们再来看之前powerKey Down的时候是亮屏的,又是短按的情况,我们再来看interceptPowerKeyUp函数:
private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
final boolean handled = canceled || mPowerKeyHandled;//这个实收handled为false了
mScreenshotChordPowerKeyTriggered = false;
cancelPendingScreenshotChordAction();
cancelPendingPowerKeyAction();
if (!handled) {
// Figure out how to handle the key now that it has been released.
mPowerKeyPressCounter += 1;
final int maxCount = getMaxMultiPressPowerCount();//这个返回为1,本来是多次按钮的。这里没有配置
final long eventTime = event.getDownTime();
if (mPowerKeyPressCounter < maxCount) {
// This could be a multi-press. Wait a little bit longer to confirm.
// Continue holding the wake lock.
Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
return;
}
// No other actions. Handle it immediately.
powerPress(eventTime, interactive, mPowerKeyPressCounter);
}
// Done. Reset our state.
finishPowerKeyPress();
}我们先看看getMaxMultiPressPowerCount函数:
这篇博客我们主要分析了,power按键在PhoneWindowManager的处理。
power按键down:
1.down又分长按亮屏 弹出关闭重启对话框
2. 短按灭屏 调用wakeup
power按键on:
1.之前down的时候亮屏短按才会调用goToSleep
2.之前down的时候亮屏长按不作处理
3.之前down的时候灭屏不作处理
之前的博客我们分析过按键的流程,当有按键会先到PhoneWindowManager的interceptKeyBeforeQueueing函数,然后再去分析到应用,而power按键也是如此,并且其最后不会分发到应用中去,下面我们看下PhoneWindowManager的interceptKeyBeforeQueueing函数对power按键处理的代码:
顺便说下这个interactive这个变量是从NativeInputManager中传过来的,在NativeInputManager也是有一个mInteractive的成员变量,是PowerManagerService改变状态的时候在Notifier.java中调用InputManagerService的Native方法,到NativeInputManager的方法nativeSetInteractive方法来设置的mInteractive变量的。所以这个值也可以说是PowerManagerService关于屏幕的状态。
case KeyEvent.KEYCODE_POWER: { result &= ~ACTION_PASS_TO_USER;//不分发到应用 isWakeKey = false; // wake-up will be handled separately if (down) { Log.i(TAG, "PowerKey down, interactive = " + interactive); interceptPowerKeyDown(event, interactive);//按键down } else { Log.i(TAG, "PowerKey up."); interceptPowerKeyUp(event, interactive, canceled);//按键up } break; }
一、Powerkey down
我们先来看下按键down的interceptPowerKeyDown函数:private void interceptPowerKeyDown(KeyEvent event, boolean interactive) { // Hold a wake lock until the power key is released. if (!mPowerKeyWakeLock.isHeld()) {//上层持锁 mPowerKeyWakeLock.acquire(); } // Cancel multi-press detection timeout. if (mPowerKeyPressCounter != 0) {//在我们的手机不支持这块,统计多次按键 mHandler.removeMessages(MSG_POWER_DELAYED_PRESS); } ...... 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; } } } } }
1.1 亮屏 长按键处理
我们先来看看hasLongPressOnPowerBehavior函数:private boolean hasLongPressOnPowerBehavior() { return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;//不为0 }
再来看看getResolvedLongPressOnPowerBehavior函数
private int getResolvedLongPressOnPowerBehavior() { if (FactoryTest.isLongPressOnPowerOffEnabled()) { return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM; } return mLongPressOnPowerBehavior; }
其中又调用了isLongPressOnPowerOffEnabled,我们没有支持这个属性。因此只要看mLongPressOnPowerBehavior这个变量
public static boolean isLongPressOnPowerOffEnabled() { return SystemProperties.getInt("factory.long_press_power_off", 0) != 0; }
下面再看看mLongPressOnPowerBehavior 这个变量的初始化。
mLongPressOnPowerBehavior = mContext.getResources().getInteger( com.android.internal.R.integer.config_longPressOnPowerBehavior);
看资源apk:
./res/values/config.xml:743: <integer name="config_longPressOnPowerBehavior">1</integer
也就是mLongPressOnPowerBehavior = 1,最后hasLongPressOnPowerBehavior返回1.
if (hasLongPressOnPowerBehavior()) { Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS); msg.setAsynchronous(true); mHandler.sendMessageDelayed(msg, ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); }
然后就发消息,我们再来看处理消息:
case MSG_POWER_LONG_PRESS: powerLongPress();
再来看powerLongPress函数
private void powerLongPress() { final int behavior = getResolvedLongPressOnPowerBehavior(); switch (behavior) { case LONG_PRESS_POWER_NOTHING: break; case LONG_PRESS_POWER_GLOBAL_ACTIONS://返回1 mPowerKeyHandled = true; if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) { performAuditoryFeedbackForAccessibilityIfNeed(); } showGlobalActionsInternal();//下面就是弹出关机,重启之类的对话框了 break;
上面之前我们再添加长按对话框添加重启功能的那篇博客有涉及,这就是在亮屏的时候长按power的流程。
1.2 灭屏 按键down处理
下面我们再来看看,interceptPowerKeyDown的另一个分支,关于现在是灭屏的时候,按键down。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;
}
}第一步直接调用wakeUpFromPowerKey函数,我们看下这个函数:
private void wakeUpFromPowerKey(long eventTime) { wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER");//这里mAllowTheaterModeWakeFromPowerKey为true } private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) { final boolean theaterModeEnabled = isTheaterModeEnabled(); if (!wakeInTheaterMode && theaterModeEnabled) { return false; } if (theaterModeEnabled) { Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.THEATER_MODE_ON, 0); } mPolicyLooper.setMessageLogging(mLogPrinter); mPowerManager.wakeUp(wakeTime, reason); return true; }
这里mAllowTheaterModeWakeFromPowerKey为true,因此就直接调用了PowerManager的wakeUp函数了,reason是"android.policy:POWER"
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();//返回为1,不支持多次按钮 if (maxCount <= 1) { mPowerKeyHandled = true;//走这里 } else { mBeganFromNonInteractive = true; } }
而下面mSupportLongPressPowerWhenNonInteractive 我们配置也是false不支持。多按钮也不支持,因此maxCount为1
二、PowerKey On
PowerKey on 又分为之前down的时候是灭屏还是亮屏处理的,逻辑又不一样。2.1 之前power按键 down是灭屏的
我们先来看之前Power按键 down的时候手机是灭屏的情况下,下面我们分析PowerKey on的interceptPowerKeyUp函数:private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) { final boolean handled = canceled || mPowerKeyHandled;//记得之前灭屏按键down的时候,mPowerKeyHandled = true mScreenshotChordPowerKeyTriggered = false; cancelPendingScreenshotChordAction(); cancelPendingPowerKeyAction(); if (!handled) { // Figure out how to handle the key now that it has been released. mPowerKeyPressCounter += 1; final int maxCount = getMaxMultiPressPowerCount(); final long eventTime = event.getDownTime(); if (mPowerKeyPressCounter < maxCount) { // This could be a multi-press. Wait a little bit longer to confirm. // Continue holding the wake lock. Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS, interactive ? 1 : 0, mPowerKeyPressCounter, eventTime); msg.setAsynchronous(true); mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout()); return; } // No other actions. Handle it immediately. powerPress(eventTime, interactive, mPowerKeyPressCounter); } // Done. Reset our state. finishPowerKeyPress(); }
之前在手机灭屏我们按power键down的时候,最后mPowerKeyHandled = true,这里handled = true,最后直接调用
private void finishPowerKeyPress() { mBeganFromNonInteractive = false;//我们手机不支持 mPowerKeyPressCounter = 0;//多按键,不支持 if (mPowerKeyWakeLock.isHeld()) { mPowerKeyWakeLock.release();//之前按power键down时候的锁释放 } }
2.2 之前power按键 down是亮屏的
之前power按键 down的时候手机亮屏,power down又分为长按和短按。我们先来看之前power down亮屏,down是长按的情况下,现在是power up的情况:private void powerLongPress() { final int behavior = getResolvedLongPressOnPowerBehavior(); switch (behavior) { case LONG_PRESS_POWER_NOTHING: break; case LONG_PRESS_POWER_GLOBAL_ACTIONS://为1 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,和上面一样。直接最后interceptPowerKeyUp函数就调用finishPowerKeyPress函数了。
然后我们再来看之前powerKey Down的时候是亮屏的,又是短按的情况,我们再来看interceptPowerKeyUp函数:
private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
final boolean handled = canceled || mPowerKeyHandled;//这个实收handled为false了
mScreenshotChordPowerKeyTriggered = false;
cancelPendingScreenshotChordAction();
cancelPendingPowerKeyAction();
if (!handled) {
// Figure out how to handle the key now that it has been released.
mPowerKeyPressCounter += 1;
final int maxCount = getMaxMultiPressPowerCount();//这个返回为1,本来是多次按钮的。这里没有配置
final long eventTime = event.getDownTime();
if (mPowerKeyPressCounter < maxCount) {
// This could be a multi-press. Wait a little bit longer to confirm.
// Continue holding the wake lock.
Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
return;
}
// No other actions. Handle it immediately.
powerPress(eventTime, interactive, mPowerKeyPressCounter);
}
// Done. Reset our state.
finishPowerKeyPress();
}我们先看看getMaxMultiPressPowerCount函数:
private int getMaxMultiPressPowerCount() { if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {// 为0 return 3; } if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {//为0 return 2; } return 1; }最后这个函数返回为1,因此上面函数就直接调用powerPress函数了。
private void powerPress(long eventTime, boolean interactive, int count) { if (mScreenOnEarly && !mScreenOnFully) { Slog.i(TAG, "Suppressed redundant power key press while " + "already in the process of turning the screen on."); return; } if (count == 2) { powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior); } else if (count == 3) { powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior); } else if (interactive && !mBeganFromNonInteractive) {//之前我们只支持1,必须亮屏,另一个参数这里为false switch (mShortPressOnPowerBehavior) {// 这个参数也是资源apk中配置的,为1 case SHORT_PRESS_POWER_NOTHING: break; case SHORT_PRESS_POWER_GO_TO_SLEEP://直接调用PowerManager的goToSleep函数了 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 /*respectKeyguard*/); break; } } }因为我们没有配置多次power按钮,mShortPressOnPowerBehavior配置为1,所以就直接调用了PowerManager的goToSleep函数了。
三、总结
这篇博客我们主要分析了,power按键在PhoneWindowManager的处理。power按键down:
1.down又分长按亮屏 弹出关闭重启对话框
2. 短按灭屏 调用wakeup
power按键on:
1.之前down的时候亮屏短按才会调用goToSleep
2.之前down的时候亮屏长按不作处理
3.之前down的时候灭屏不作处理
相关文章推荐
- C#控制键盘按键的常用方法
- javascript 响应键盘特定按键(只响应数字键)
- JS实现获取键盘按下的按键并显示在页面上的方法
- Unity3D获取当前键盘按键及Unity3D鼠标、键盘的基本操作
- JavaScript Event学习第十一章 按键的检测
- Atitit.js的键盘按键事件捆绑and事件调度
- js获取及判断键盘按键的方法
- Python可跨平台实现获取按键的方法
- Python实现windows下模拟按键和鼠标点击的方法
- Atitit.js的键盘按键事件捆绑and事件调度
- vbs之sendkey
- 模拟按键
- (一)Qt:键盘输入,两行editline
- 录音项目随笔(一)
- iOS&&Swift入门(三)Button/按键
- stm32 CT117E之按键(扫描)
- 键盘ascll码
- 笔者分享:在不同BIOS上如何让U盘启动【mfxp】
- 移植 tiny210 的按键驱动
- 什么是按键