粘贴如下:
一. 屏幕的唤醒
首先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
//摘录部分代码:
publicintinterceptKeyBeforeQueueing(longwhenNanos,intaction,intflags,
intkeyCode,intscanCode,intpolicyFlags,booleanisScreenOn) {
finalbooleandown = action == KeyEvent.ACTION_DOWN;
finalbooleancanceled = (flags & KeyEvent.FLAG_CANCELED) !=0;
finalbooleanisInjected = (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.
finalbooleankeyguardActive = (isScreenOn ?
mKeyguardMediator.isShowingAndNotHidden() :
mKeyguardMediator.isShowing());
intresult;//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;
finalbooleanisWakeKey = (policyFlags
& (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
if(down && isWakeKey) {
if(keyguardActive) {
//也就是说,如果当前屏幕是灭的,且按的键是可以唤醒屏幕的,那么WM会首先将此次按键传递给keyguard,由keyguard来唤醒屏幕,并作出相应的动作,否则就自己点亮屏幕,通过返回的policy来通知下层。
// If the keyguard is showing, let it decide what to do with the wake key.
mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode);
} else{
// Otherwise, wake the device ourselves.
result |= ACTION_POKE_USER_ACTIVITY;
}
}
}
....................
}
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的了,贴出代码看看:
int
set_screen_state(inton)
{
//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)returng_error;
charbuf[32];
intlen;
if(on)
len = sprintf(buf, "%s", on_state);
else
len = sprintf(buf, "%s", off_state);
len = write(g_fds[REQUEST_STATE], buf, len);//此处就是写了kernel的设备文件接口。
if(len
LOGE("Failed setting last user activity: g_error=%d\n", g_error);
}
return0;
}
在此函数中写了底层的power控制的设备文件接口,对应的设备文件为:/sys/power/state
接下来的流程就是到了内核空间。
kernel/kernel/power/main.c state_store
//此函数被宏power_attr(state)声明为设备文件接口 sys/power/state,宏power_attr的定义为(power.h):
#define power_attr(_name) \
static struct kobj_attribute _name##_attr = {\
.attr= {\
.name = __stringify(_name),\
.mode = 0644, \
},\
.show= _name##_show,\
.store = _name##_store,\
}
staticssize_t state_store(structkobject *kobj,structkobj_attribute *attr,
constchar*buf,size_tn)
{
#ifdef CONFIG_SUSPEND
#ifdef CONFIG_EARLYSUSPEND
suspend_state_t state = PM_SUSPEND_ON;
#else
suspend_state_t state = PM_SUSPEND_STANDBY;
#endif
constchar*const*s;
#endif
char*p;
intlen;
interror = -EINVAL;
p = memchr(buf, '\n', n);
len = p ? p - buf : n;
/* First, check if we are requested to hibernate */
if(len == 4 && !strncmp(buf,"disk", len)) {
error = hibernate();
gotoExit;
}
#ifdef CONFIG_SUSPEND
for(s = &pm_states[state]; state
if(*s && len == strlen(*s) && !strncmp(buf, *s, len))
break;
}
printk("##: enter %s\n", pm_states[state]);
if(state
#ifdef CONFIG_EARLYSUSPEND // android对linux的睡眠唤醒机制做了一些优化,也就是earlysuspen,laterresume机制,此处宏是有定义的,所以会先走android的那一套
if(state == PM_SUSPEND_ON || valid_state(state)) {
error = 0;
printk("##: entering request_suspend_state()...\n");
request_sus