一. 屏幕的唤醒 首先inputread在读取到有keyboard事件上报后,会调用到keydispatch的notifykey,去询问wm是否会对这次按键特殊处理,如果WM不处理,则此处会点亮或者熄灭屏幕。 inputReader.cpp KeyboardInputMapper::processKey getDispatcher()->notifyKey inputDispacher.cpp InputDispatcher::notifyKey mPolicy->interceptKeyBeforeQueueing com_android_server_inputManager.cpp NativeInputManager::interceptKeyBeforeQueueing env->CallIntMethod(mCallbacksObj,
gCallbacksClassInfo.interceptKeyBeforeQueueing,
when, action, flags, keyCode, scanCode, policyFlags, isScreenOn); //此处gCallbacksClassInfo中的各种方法就是InputManager的对应的方法,在JNI初始化的时候就注册了,详情请参看register_android_server_InputManager函数,通过jniRegisterNativeMethods将inputmanager的各种callback注册到gCallbacksClassInfo中。 返回的wmaction就是后面WM对此次按键事件的policy,通过此返回值,此处会决定下一步的动作。 InputManager.Java interceptKeyBeforeQueueing mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing WindowmanagerService.java InputMonitor::interceptKeyBeforeQueueing mPolicy.interceptKeyBeforeQueueing PhonewindowManager.java interceptKeyBeforeQueueing //摘录部分代码:
[java] view plain copy
- <span style="font-weight: bold; "> </span> public int interceptKeyBeforeQueueing(long whenNanos, int action, int flags,
- int keyCode, int scanCode, int policyFlags, boolean isScreenOn) {
- final boolean down = action == KeyEvent.ACTION_DOWN;
- final boolean canceled = (flags & KeyEvent.FLAG_CANCELED) != 0;
-
- final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
-
- // If screen is off then we treat the case where the keyguard is open but hidden
- // the same as if it were open and in front.
- // This will prevent any keys other than the power button from waking the screen
- // when the keyguard is hidden by another activity.
-
- final boolean keyguardActive = (isScreenOn ?
- mKeyguardMediator.isShowingAndNotHidden() :
- mKeyguardMediator.isShowing());
-
- int result; //result即为返回到wmaction
- if (isScreenOn || isInjected) {
- // When the screen is on or if the key is injected pass the key to the application.
- result = ACTION_PASS_TO_USER;
- } else {//我们现在走的应该是这个
- // When the screen is off and the key is not injected, determine whether
- // to wake the device but don't pass the key to the application.
- result = 0;
-
- final boolean isWakeKey = (policyFlags
- & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
- if (down && isWakeKey) {
- if (keyguardActive) {
[java] view plain copy
- //也就是说,如果当前屏幕是灭的,且按的键是可以唤醒屏幕的,那么WM会首先将此次按键传递给keyguard,由keyguard来唤醒屏幕,并作出相应的动作,否则就自己点亮屏幕,通过返回的policy来通知下层。
-
- // If the keyguard is showing, let it decide what to do with the wake key.
- <span style="color:#ff0000;"> </span> mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode);
- } else {
- // Otherwise, wake the device ourselves.
-
- result |= ACTION_POKE_USER_ACTIVITY;
- }
- }
- }<span style="font-weight: bold; ">
- ....................
- }</span>
keyguarViewMediator.java onWakeKeyWhenKeyguardShowingTq
wakeWhenReadyLocked mHandler.obtainMessage(WAKE_WHEN_READY, keyCode, 0); mHandler.handleMessage handleWakeWhenReady mKeyguardViewManager.wakeWhenReadyTq KeyguardViewManager.java mKeyguardView.wakeWhenReadyTq LockpatternKeyguardView.java wakeWhenReadyTq getCallback().pokeWakelock(); KeyguardViewMediator.java pokeWakelock mWakeLock.acquire(); // mWakeLock即为:mWakeLock = mPM.newWakeLock(
PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
"keyguard"); 具有ACQUIRE_CAUSE_WAKUPQ权限的唤醒锁,上层就是通过此锁来唤醒屏幕,接下来就是powermanager的流程了。 PowerManager.java acquire mService.acquireWakeLock PowermanagerService.java acquireWakeLock acquireWakeLockLocked//此处会检查唤醒锁的标志位,作出对应的处理。 setPowerState //此函数为powermanager的核心函数之一,会对屏幕背光/唤醒,睡眠等作出相应的处理 setScreenStateLocked //此函数很关键 Power.setScreenState power.java setScreenState android_os_Power.cpp setScreenState power.c set_screen_state//此函数作为上层的最后一个函数,会打印出标志性的log,*** set_screen_state %d,如果打出这个log,至少证明从APP-HAL都是在正常干活的,那么问题只能是kernel的了,贴出代码看看: [cpp] view plain copy
- int
- set_screen_state(int on)
- {
- //QEMU_FALLBACK(set_screen_state(on));
-
- LOGI("*** set_screen_state %d", on); //神奇的log标志
-
- initialize_fds();
-
- //LOGI("go_to_sleep eventTime=%lld now=%lld g_error=%s\n", eventTime,
- // systemTime(), strerror(g_error));
-
- if (g_error) return g_error;
-
- char buf[32];
- int len;
-
- if(on)
- len = sprintf(buf, "%s", on_state);
- else
- len = sprintf(buf, "%s", off_state);
- <span style="color:#cc0000;"> </span>len = write(g_fds[REQUEST_STATE], buf, len);//此处就是写了kernel的设备文件接口。
- if(len < 0) {
- LOGE("Failed setting last user activity: g_error=%d\n", g_error);
- }
- return 0;
- }
|