linux 点亮屏幕,按电源键屏幕唤醒和屏幕睡眠流程(从上层到kernel)

本文详细介绍了Linux系统中,从用户输入到屏幕点亮及熄灭的完整流程。从InputReader捕获键盘事件,经过InputDispatcher、InputManager、WindowManagerService,到PowerManagerService,最终通过kernel的power子系统实现屏幕的开关。屏幕唤醒时,KeyguardMediator会处理唤醒键,通过PowerManager的wakelock机制唤醒屏幕;屏幕熄灭则通过类似的路径,设置电源状态,调用kernel的suspend机制进入睡眠状态。
摘要由CSDN通过智能技术生成

粘贴如下:

一. 屏幕的唤醒

首先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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值