当前位置: 首页 > news >正文

Android 14 Power键亮灭屏流程

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)

整个流程图如下:

ecb88a9527a4460d97c2331988816f8d.png
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;}

后续流程图如下:

e1461ef4ec24461ea73c91c813b926c3.png

 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 深入理解小程序的渲染机制与性能优化策略
  • 镜像仓库 Registry 介绍及实践-http
  • python-learning47--高阶教程--基础阶段--python函数--高级用法-作用域
  • Java每日一练_模拟面试题6(JVM的GC过程)
  • 网络协议 从入门到精通系列讲解 - 总目录
  • 【rx rb rz】Centos/Linux rx、rb、rz命令详细介绍
  • React应用(基于react脚手架)
  • 攻防世界-web-ctf-upload
  • Ubuntu 安装 Snipaste
  • springboot mybatis plus 固定查询条件及可选查询条件的组合查询,使用QueryWrapper.and()来解决。
  • Flink的DataStream状态管理
  • 同城信息发布聚合小程序覆盖业态
  • 大数据机器学习算法岗位分析推荐:基于Python的招聘大数据爬虫可视化分析推荐系统
  • 在Docker容器中运行Java应用程序的性能优化技巧
  • Flink-DataWorks第二部分:数据集成(第58天)
  • python3.6+scrapy+mysql 爬虫实战
  • 收藏网友的 源程序下载网
  • 【347天】每日项目总结系列085(2018.01.18)
  • HTTP请求重发
  • java B2B2C 源码多租户电子商城系统-Kafka基本使用介绍
  • JavaScript服务器推送技术之 WebSocket
  • Linux快速配置 VIM 实现语法高亮 补全 缩进等功能
  • opencv python Meanshift 和 Camshift
  • Shell编程
  • 记录:CentOS7.2配置LNMP环境记录
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 吴恩达Deep Learning课程练习题参考答案——R语言版
  • 最近的计划
  • MyCAT水平分库
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • ​ 全球云科技基础设施:亚马逊云科技的海外服务器网络如何演进
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • $.ajax()
  • (1)SpringCloud 整合Python
  • (C语言)共用体union的用法举例
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (二)Eureka服务搭建,服务注册,服务发现
  • (二)fiber的基本认识
  • (三)docker:Dockerfile构建容器运行jar包
  • (深入.Net平台的软件系统分层开发).第一章.上机练习.20170424
  • (四) 虚拟摄像头vivi体验
  • (算法)前K大的和
  • (一)80c52学习之旅-起始篇
  • (一)搭建springboot+vue前后端分离项目--前端vue搭建
  • (转)chrome浏览器收藏夹(书签)的导出与导入
  • (转)创业家杂志:UCWEB天使第一步
  • .net core 6 redis操作类
  • .NET Core 发展历程和版本迭代
  • .Net Core缓存组件(MemoryCache)源码解析
  • .Net 垃圾回收机制原理(二)
  • .netcore 如何获取系统中所有session_ASP.NET Core如何解决分布式Session一致性问题
  • .net反混淆脱壳工具de4dot的使用
  • .NET和.COM和.CN域名区别
  • .NET框架设计—常被忽视的C#设计技巧
  • .NET企业级应用架构设计系列之开场白