Android14中Power键的事件分发和Android10的是不一样的,这里并没有经过interceptKeyBeforeDispatching方法,而是直接走到了interceptKeyBeforeQueueing方法
PhoneWindowManager中的堆栈如下
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相关的堆栈如下
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)
整个流程图如下:
InputManagerService.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/input/InputManagerService.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只是一个接口,没有具体的实现
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这里
InputManagerCallback.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/wm/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.*/@Overridepublic int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);}
然后就走到了PhoneWindowManager中
PhoneWindowManager.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
@Overridepublic int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
//获取键值final int keyCode = event.getKeyCode();
//获取当前是否是按键downfinal boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
//是否是wake keyboolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0|| event.isWakeKey();
...final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
//此按键是否取消final boolean canceled = event.isCanceled();
//获取屏幕的IDfinal 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
//这个意思是此事件只有系统层可以接收,不下发给appresult &= ~ACTION_PASS_TO_USER;isWakeKey = false; // wake-up will be handled separatelyif (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这里的逻辑
PhoneWindowManager.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.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.---Powerfinal 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逻辑。
PhoneWindowManager.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.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 mWakeUpToLastStateTimeoutif (shouldWakeUpWithHomeIntent() && event.getKeyCode() == KEYCODE_HOME) {startDockOrHome(DEFAULT_DISPLAY, /*fromHomeKey*/ true, /*wakenFromDreams*/ true,PowerManager.wakeReasonToString(PowerManager.WAKE_REASON_WAKE_KEY));}}}
PhoneWindowManager.java - OpenGrok cross reference for /frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.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;}
后续流程图如下: