android7.0 电源(Power)键流程

本文详细分析了Android 7.0中电源键的处理流程,从按下到抬起的各个阶段,包括按键计数、多按行为判断以及不同情况下的响应处理,如休眠、唤醒等操作。通过对`interceptPowerKeyUp`和`powerPress`等关键函数的解析,揭示了系统如何根据用户交互控制设备的电源状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 对于Power键的分析文章较多,本文从android7.0源码的角度大致分析下电源键的流程!参考博主连接:http://blog.youkuaiyun.com/gaugamela/article/details/52912382 和http://blog.youkuaiyun.com/kc58236582/article/details/51568506!

一 android 按键事件简介

    在android系统中,每一个App所呈现的UI都是一个Activity,而UI的呈现实际上则是由Window对象来实现的,每个Window对象实际上又是PhoneWindow对象;而每个PhonewWindow对象又是一个PhoneWindowManager(PWM)对象。在将按键处理操作分发到App之前,首选会回调PWM中的dispatchUnhandledKey()方法,该方法主要是用于在执行当前App处理之前的操作,处理一些特殊按键。

   PWM中有两个对按键比较重要的函数(按键预处理,针对特殊按键,如Power):intercepetKeyBeforeDispatching()和intercepetKeyBeforeQueueing()。

   intercepetKeyBeforeQueueing()主要是用来处理音量和电源键,该函数中有一个重要的变量ACTION_PASS_TO_USER(变量解释:传递按键事件到用户app进行处理),该函数的返回值如果是0则表示该按键事件被消费,按键事件不会传递到用户App,返回1则表示允许按键事件传递给用户App中进行处理。

   intercepetKeyBeforeDispatching()主要是用来预处理home、menu、search按键事件;该函数的返回值如果是-1则表示的是该按键事件被消费,返回0则代表允许事件的往下传递。这些处理的实现都是在PWM,其调用者是InputDispatchThread,这样处理的好处就是把平台相关的东西都放置在PWM中,而InputDispatchThread则是平台通用的,厂商要定制特殊策略只需要更改PWM,这样就很好的做到了Mechanism和Policy的分离。

二 PWM函数解析

@Override
public KeyEventdispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
KeyEvent fallbackEvent = null;
//下面的逻辑主要是用于判断按键事件是否被消费;因为同一时刻可能有两个按键事件同时触发,如组合键(Power+音量下键实现截屏),则必须判断该逻辑表明一个按键还未消费
if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {//按键标识符
final KeyCharacterMap kcm = event.getKeyCharacterMap(); //获得键盘映射----字符映射KeyCharacterMap
final int keyCode = event.getKeyCode(); //按键码
final int metaState = event.getMetaState();//获取功能键状态;如果没有功能键(如alt、shift)按下,则metaState为0
final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
&& event.getRepeatCount() == 0; //首次按键
// Check for fallback actions specified by the key character map.
final FallbackAction fallbackAction; //不太懂
if (initialDown) {
fallbackAction = kcm.getFallbackAction(keyCode, metaState);
} else {
fallbackAction = mFallbackActions.get(keyCode);
}
if (fallbackAction != null) {
final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
fallbackEvent = KeyEvent.obtain(
event.getDownTime(), event.getEventTime(),
event.getAction(), fallbackAction.keyCode,
event.getRepeatCount(), fallbackAction.metaState,
event.getDeviceId(), event.getScanCode(),
flags, event.getSource(), null); //按键事件
if (!interceptFallback(win, fallbackEvent, policyFlags)) {
fallbackEvent.recycle();
fallbackEvent = null;
}
if (initialDown) {
mFallbackActions.put(keyCode, fallbackAction);
} else if (event.getAction() == KeyEvent.ACTION_UP) {
mFallbackActions.remove(keyCode);
fallbackAction.recycle();
}
}
}
return fallbackEvent;
}
   其中最主要分析以下的代码
private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
int actions =interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
if ((actions & ACTION_PASS_TO_USER) != 0) {
long delayMillis =interceptKeyBeforeDispatching(
win, fallbackEvent, policyFlags);
if (delayMillis == 0) {
return true;
}
}
return false;
}

三 电源键(Power)函数分析

在interceptKeyBeforeQueueing函数中对于电源键的处理部分代码如下:
case KeyEvent.KEYCODE_POWER: {
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false; // wake-up will be handled separately
if (down) {
interceptPowerKeyDown(event, interactive); //power键按下
} else {
interceptPowerKeyUp(event, interactive, canceled);//power
<think>我们正在分析Android系统中Power控制屏幕熄灭的代码流程。根据引用内容,我们可以知道在Android 7.0中,当按下Power时,系统会触发一系列事件,最终可能导致屏幕熄灭(即进入睡眠状态)。 根据引用[2]中的描述,当设备处于亮屏状态(interactive为true)且不是从非交互状态开始时,按下Power(短按)会进入一个分支处理。在`powerPress`函数中,根据`mShortPressOnPowerBehavior`的值执行不同的操作。其中,`SHORT_PRESS_POWER_GO_TO_SLEEP`表示短按Power会使设备进入睡眠状态。 具体流程如下: 1. 当用户按下Power时,硬件产生一个按事件,该事件被InputReader捕获,然后传递给InputDispatcher,最终到达WindowManagerService(WMS)的`PhoneWindowManager`。 2. 在`PhoneWindowManager`中,会处理Power的按下事件。在亮屏状态下,短按Power会触发`powerPress`函数。 3. 在`powerPress`函数中,当满足条件(count=1,设备处于交互状态等)时,根据配置的`mShortPressOnPowerBehavior`值执行相应操作。如果配置为`SHORT_PRESS_POWER_GO_TO_SLEEP`(值为1),则调用`PowerManagerService`的`goToSleep`方法。 4. `PowerManagerService`的`goToSleep`方法会进一步调用到底层的`goToSleepInternal`方法,该方法会请求系统进入睡眠状态。 5. 在`goToSleepInternal`中,会更新电源状态,并调用`nativeSetPowerState`(通过JNI)通知底层进行睡眠操作。同时,它会释放唤醒锁,允许系统进入低功耗状态。 6. 底层(包括HAL层和Kernel)接收到睡眠请求后,会关闭屏幕背光,并可能将CPU置于休眠状态。 值得注意的是,在进入睡眠之前,系统会保存状态,并通知其他服务(如DisplayManagerService)屏幕即将关闭。 下面是一个简化的代码流程: ``` 用户按下Power → InputReader捕获事件 → InputDispatcher分发事件到WindowManagerService → PhoneWindowManager.interceptKeyBeforeQueueing() 处理事件,判断为短按Power → 调用PowerManagerService的powerPress()方法 在powerPress()中,根据条件调用goToSleep()PowerManagerService.goToSleep() 内部调用goToSleepInternal() → 在goToSleepInternal()中,更新全局状态,通过native方法调用底层 → 底层(HAL和Kernel)执行关闭屏幕和进入睡眠的操作 ``` 另外,根据引用[3],屏幕熄灭过程涉及释放唤醒锁(wake lock)和调用kernel的睡眠流程。 注意:以上分析基于Android 7.0的代码,不同版本可能有所差异。 相关问题: 1.Android系统中,除了Power,还有其他方式可以使屏幕熄灭吗? 2. 如何配置短按Power的行为(例如修改为锁屏而不是睡眠)? 3. Power按事件的流程是怎样的?</think>### Power控制屏幕熄灭功能的代码流程分析 在Android系统中,Power控制屏幕熄灭的流程涉及多个系统层的协作。以下是基于Android 7.0源码的分析(流程在不同版本中可能略有差异): #### 1. **Input事件捕获** 当用户按下Power时: - Linux内核通过`input`子系统捕获硬件中断 - InputReader线程读取`/dev/input/eventX`设备事件 - 事件被传递到WindowManagerService(WMS)的`InputManager`模块 #### 2. **WindowManagerService处理** 在`PhoneWindowManager.java`中处理事件: ```java // frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java public int interceptKeyBeforeQueueing(...) { if (keyCode == KeyEvent.KEYCODE_POWER) { if (down) { // 按下事件 powerPress(eventTime, interactive, mPowerKeyWakeLock); } else { // 释放事件 powerRelease(); } } } ``` #### 3. **短按Power处理** 在`powerPress()`方法中判断短按行为: ```java private void powerPress(long eventTime, boolean interactive, int count) { if (interactive) { switch (mShortPressOnPowerBehavior) { case SHORT_PRESS_POWER_GO_TO_SLEEP: // 配置值为1 mPowerManager.goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); break; // 其他case处理... } } } ``` [^2] #### 4. **PowerManagerService执行睡眠** 在`PowerManagerService.java`中执行睡眠操作: ```java // frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java @Override public void goToSleep(long eventTime, int reason, int flags) { goToSleepInternal(eventTime, reason, flags, Process.SYSTEM_UID); } private void goToSleepInternal(...) { // 1. 更新唤醒状态 setWakefulnessLocked(WAKEFULNESS_ASLEEP, reason); // 2. 通知DisplayManagerService关闭屏幕 mDisplayManagerInternal.setDisplayPowerState(...); // 3. 释放唤醒锁 updatePowerStateLocked(); } ``` #### 5. **底层驱动执行** 最终通过HAL层和内核关闭屏幕: 1. 通过JNI调用`com_android_server_power_PowerManagerService.cpp` 2. 写入`/sys/power/state`触发内核睡眠流程 3. 显示驱动关闭背光并进入低功耗模式 ```cpp // 内核电源管理 static int suspend_enter(suspend_state_t state) { // 关闭显示控制器 fb_suspend(); // 进入CPU休眠状态 cpu_suspend(); } ``` [^3] ### 关配置点 在`config.xml`中定义Power行为: ```xml <!-- 短按行为:0=无操作 1=睡眠 2=挂断电话 3=锁屏 --> <integer name="config_shortPressOnPowerBehavior">1</integer> ``` ### 流程总结 ``` 硬件中断 → Input子系统 → WindowManagerService → PhoneWindowManager.powerPress()PowerManagerService.goToSleep() → DisplayManagerService → SurfaceFlinger → Framebuffer驱动 → 内核电源管理(suspend) ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值