Android14中Power键的事件分发和Android10的是不一样的,这里并没有经过interceptKeyBeforeDispatching方法,而是直接走到了interceptKeyBeforeQueueing方法
PhoneWindowManager中的堆栈如下
java
07-06 08:59:04.481 1844 1984 D WindowManager: interceptKeyTq keycode=26 down=true
07-06 08:59:04.481 1844 1984 W System.err: java.lang.Exception
07-06 08:59:04.481 1844 1984 W System.err: at com.android.server.policy.PhoneWindowManager.interceptKeyBeforeQueueing(PhoneWindowManager.java:4127)
07-06 08:59:04.481 1844 1984 W System.err: at com.android.server.wm.InputManagerCallback.interceptKeyBeforeQueueing(InputManagerCallback.java:149)
07-06 08:59:04.481 1844 1984 W System.err: at com.android.server.input.InputManagerService.interceptKeyBeforeQueueing(InputManagerService.java:2476)
当用户点击物理按键Power键时,input模块会分发此事件,jni层的input相关的堆栈如下
java
07-06 08:59:04.481 1844 1984 D NativeInputManager: #00 pc 000000000007e62c /system/lib64/libandroid_servers.so (android::NativeInputManager::interceptKeyBeforeQueueing(android::KeyEvent const&, unsigned int&)+108) (BuildId: a244f886fcc4e4d7951cb0b0dd8e0a93)
07-06 08:59:04.481 1844 1984 D NativeInputManager: #01 pc 00000000000ac5d0 /system/lib64/libinputflinger.so (android::inputdispatcher::InputDispatcher::notifyKey(android::NotifyKeyArgs const&)+372) (BuildId: a55568bcb9c61a30bcd4f9eba5623696)
07-06 08:59:04.481 1844 1984 D NativeInputManager: #02 pc 0000000000007cd4 /system/lib64/libinputflinger_base.so (android::QueuedInputListener::flush()+132) (BuildId: a9c65a12bbe41d35ccac4bea02eabbf0)
07-06 08:59:04.481 1844 1984 D NativeInputManager: #03 pc 0000000000007cd4 /system/lib64/libinputflinger_base.so (android::QueuedInputListener::flush()+132) (BuildId: a9c65a12bbe41d35ccac4bea02eabbf0)
07-06 08:59:04.481 1844 1984 D NativeInputManager: #04 pc 0000000000007cd4 /system/lib64/libinputflinger_base.so (android::QueuedInputListener::flush()+132) (BuildId: a9c65a12bbe41d35ccac4bea02eabbf0)
07-06 08:59:04.481 1844 1984 D NativeInputManager: #05 pc 00000000000a0d54 /system/lib64/libinputreader.so (android::InputReader::loopOnce()+1424) (BuildId: 7171b6e142e1b4551a0406d673f063e5)
07-06 08:59:04.481 1844 1984 D NativeInputManager: #06 pc 000000000000ad14 /system/lib64/libinputflinger_base.so (android::(anonymous namespace)::InputThreadImpl::threadLoop()+28) (BuildId: a9c65a12bbe41d35ccac4bea02eabbf0)
07-06 08:59:04.481 1844 1984 D NativeInputManager: #07 pc 00000000000142d0 /system/lib64/libutils.so (android::Thread::_threadLoop(void*)+288) (BuildId: 6df8048e2f2c69be0a5d8ee3149d683d)
07-06 08:59:04.481 1844 1984 D NativeInputManager: #08 pc 00000000000ebc40 /system/lib64/libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*)+144) (BuildId: af0fa43783211a0f2494f720559e5d5c)
07-06 08:59:04.481 1844 1984 D NativeInputManager: #09 pc 00000000000c3644 /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+208) (BuildId: 50118287324a156bc7be11d3d940c7be)
07-06 08:59:04.481 1844 1984 D NativeInputManager: #10 pc 000000000005cfa4 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+68) (BuildId: 50118287324a156bc7be11d3d940c7be)
整个流程图如下:
java
// Native callback.
@SuppressWarnings("unused")
private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
synchronized (mFocusEventDebugViewLock) {
if (mFocusEventDebugView != null) {
mFocusEventDebugView.reportEvent(event);
}
}
return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
}
private WindowManagerCallbacks mWindowManagerCallbacks;
mWindowManagerCallbacks定义如上,我们可以看到WindowManagerCallbacks只是一个接口,没有具体的实现
java
public interface WindowManagerCallbacks extends LidSwitchCallback {
/**
* This callback is invoked when an event first arrives to InputDispatcher and before it is
* placed onto InputDispatcher's queue. If this event is intercepted, it will never be
* processed by InputDispacher.
* @param event The key event that's arriving to InputDispatcher
* @param policyFlags The policy flags
* @return the flags that tell InputDispatcher how to handle the event (for example, whether
* to pass it to the user)
*/
int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
}
查找代码会发现InputManagerCallback实现了WindowManagerCallbacks,然后就到了InputManagerCallback这里
java
final class InputManagerCallback implements InputManagerService.WindowManagerCallbacks {
...
/**
* Provides an opportunity for the window manager policy to intercept early key
* processing as soon as the key has been read from the device.
*/
@Override
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
}
然后就走到了PhoneWindowManager中
java
@Override
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
//获取键值
final int keyCode = event.getKeyCode();
//获取当前是否是按键down
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
//是否是wake key
boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
|| event.isWakeKey();
...
final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
//此按键是否取消
final boolean canceled = event.isCanceled();
//获取屏幕的ID
final int displayId = event.getDisplayId();
final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
...
// Handle special keys.
switch (keyCode) {
...
//走进Power按键的处理逻辑
case KeyEvent.KEYCODE_POWER: {
EventLogTags.writeInterceptPower(
KeyEvent.actionToString(event.getAction()),
mPowerKeyHandled ? 1 : 0,
mSingleKeyGestureDetector.getKeyPressCounter(KeyEvent.KEYCODE_POWER));
// Any activity on the power button stops the accessibility shortcut
//这个意思是此事件只有系统层可以接收,不下发给app
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false; // wake-up will be handled separately
if (down) {
interceptPowerKeyDown(event, interactiveAndOn);
} else {
interceptPowerKeyUp(event, canceled);
}
break;
}
...
//使用震动反馈
if (useHapticFeedback) {
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, false,
"Virtual Key - Press");
}
if (isWakeKey) {
wakeUpFromWakeKey(event);
}
...
}
然后就走到了power down这里的逻辑
java
private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
// Hold a wake lock until the power key is released.
//申请wake lock锁,申请这个锁才能亮屏哦!!!
if (!mPowerKeyWakeLock.isHeld()) {
mPowerKeyWakeLock.acquire();
}
//会走到WMS的onPowerKeyDown方法
//mRoot.forAllDisplayPolicies(p -> p.onPowerKeyDown(isScreenOn));
mWindowManagerFuncs.onPowerKeyDown(interactive);
// Stop ringing or end call if configured to do so when power is pressed.
TelecomManager telecomManager = getTelecommService();
boolean hungUp = false;
if (telecomManager != null) {
if (telecomManager.isRinging()) {
// Pressing Power while there's a ringing incoming
// call should silence the ringer.
//如果当前电话正在响铃, 按下power键就会静音
telecomManager.silenceRinger();
} else if ((mIncallPowerBehavior
& Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
&& telecomManager.isInCall() && interactive) {
// Otherwise, if "Power button ends call" is enabled,
// the Power button will hang up any current active call.
//如果正在打电话,按下就是挂断
hungUp = telecomManager.endCall();
}
}
//return true if the proximity sensor was successfully ignored and we should consume the key event.---Power
final boolean handledByPowerManager = mPowerManagerInternal.interceptPowerKeyDown(event);
// Inform the StatusBar; but do not allow it to consume the event.
sendSystemKeyToStatusBarAsync(event);
// If the power key has still not yet been handled, then detect short
// press, long press, or multi press and decide what to do.
mPowerKeyHandled = mPowerKeyHandled || hungUp
|| handledByPowerManager || mKeyCombinationManager.isPowerKeyIntercepted();
if (!mPowerKeyHandled) {
if (!interactive) {
wakeUpFromPowerKey(event.getDownTime());
}
} else {
// handled by another power key policy.
if (mSingleKeyGestureDetector.isKeyIntercepted(KEYCODE_POWER)) {
Slog.d(TAG, "Skip power key gesture for other policy has handled it.");
mSingleKeyGestureDetector.reset();
}
}
}
如果mPowerKeyHandled为false,也就是没有消费掉这个power事件,则,走进wakeUpFromWakeKey逻辑。
java
private void wakeUpFromWakeKey(KeyEvent event) {
//亮屏, 原因是WAKE_REASON_WAKE_KEY, details是"android.policy:KEY"
if (wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey,
PowerManager.WAKE_REASON_WAKE_KEY, "android.policy:KEY")) {
// Start HOME with "reason" extra if sleeping for more than mWakeUpToLastStateTimeout
if (shouldWakeUpWithHomeIntent() && event.getKeyCode() == KEYCODE_HOME) {
startDockOrHome(DEFAULT_DISPLAY, /*fromHomeKey*/ true, /*wakenFromDreams*/ true,
PowerManager.wakeReasonToString(PowerManager.WAKE_REASON_WAKE_KEY));
}
}
}
java
private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, @WakeReason int reason,
String details) {
final boolean theaterModeEnabled = isTheaterModeEnabled();
if (!wakeInTheaterMode && theaterModeEnabled) {
return false;
}
if (theaterModeEnabled) {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.THEATER_MODE_ON, 0);
}
mPowerManager.wakeUp(wakeTime, reason, details);
return true;
}
后续流程图如下: