PowerManagerService源码分析 :http://blog.csdn.net/king1425/article/details/70224476
Android的亮屏流程从android系统结构层次来分可以分为三个流程。App应用唤醒源;Framework层Power结合Display,Light服务做亮屏绘制准备工作;底层驱动点亮背光灯。这里重点分析一下Framework层亮屏的一系列准备工作流程。

唤醒源

通过了解PowerManagerService的工作流程可以发现android的唤醒屏幕的唤醒源总共有四种:

1.应用直接调用 PowerManager的WakeUp接口。

2.应用在申请wakelock时候,添加ACQUIRE_CAUSES_WAKEUP的flag。

3.应 用Activity在创建时候,带有WindowManager的FLAG_TURN_SCREEN_ON的flag(本质调用到 PowerManagerService的WakeUp操作)。

4.Power键唤醒是通过Input事件调用到PhoneWindowManager中 的按键事件处理函数interceptKeyBeforeQueueing中去调用PowerManager的wakeup接口。

这里先简单介绍一下较为较为特殊的第二,三种类型的唤醒源,后面关于wakeup的流程会详细的说明。

1.应用申请wakelock带有ACQUIRE_CAUSES_WAKEUP标志:当应用在申请wakelok时候,会在 PowerManagerService的中去执行updatePowerStateLocked更新电源状态操作,熟悉 PowerManagerService的人会清楚updatePowerStateLocked是整个PowerManagerService的核心函 数,只要系统接收到与Power相关的事件(如:申请wakelock,开机,设置改变,用户操作等等)之后会第一时间去执行 updatePowerStateLocked更新电源状态。但是在申请wakelock时候,在acquireWakeLockInternal中会调用applyWakeLockFlagsOnAcquireLocked函数去判断wakelock是否带有ACQUIRE_CAUSES_WAKEUP,如果带有该标志会直接跳入wakeUpNoUpdateLocked函数内,该函数是便是WakeUp唤醒系统的必须要走的调用函数。

2. Activity创建带有FLAG_TURN_SCREEN_ON标志:以IncallActivity为例

1).电话来电时首先。会在IncallActivity中的onCreate方法中设置一个FLAG_TURN_SCREEN_ON的flag值。

2).应用会调用到PhoneWindow的addWindow方法时,会调用到WindowManagerService–>relayoutVisibleWindow, 将win的mTurnOnScreen设置为true。

3).最终在最终在WindowSurfacePlacer的
performSurfacePlacement 函数中调用wakeUp:

1.  if (mTurnOnScreen) {
2.  if (mAllowTheaterModeWakeFromLayout
3.  || Settings.Global.getInt(mContext.getContentResolver(),
4.  Settings.Global.THEATER_MODE_ON, 0) == 0) {
5.  if (DEBUG_VISIBILITY || DEBUG_POWER) {
6.  Slog.v(TAG, "Turning screen on after layout!");
7.  }
8.  mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.server.wm:TURN_ON");
9.  }
10. mTurnOnScreen = false;
11. }

唤醒流程

Wakeup流程分两个流程:1.是windowManager绘制屏幕动画;2.是点亮屏幕背光灯;两个流程是两条调用的路线在并行执行;

绘制屏幕动画流程如下:

1)调用到PowerManagerService的wakeup,到WakeupInternal中,到wakeUpNoUpdateLocked函 数,在wakeUpNoUpdateLocked函数中调用setWakefulnessLocked函数,设置mWakeFullness为 WAKEFULLNESS_AWAKE。

2).前面执行wakeup函数执行过程中会调用到setWakefulnessLocked将mWakefulness置成 WAKEFULLNESS_AWAKE,同时调用到mNotifier中的onWakefulnessChangeStarted,在此函数中做三了三件 事:1.通知AMS状态变为wakefulness;2.通知IntputManager状态变为InterActive可交互状态;3.通过 handleEarlyInteractiveChange调用到PhoneWindowManager的startedWakingUp函数,来通知到 PhoneWindowManager屏幕开始启动。

3).wakeup函数执行完成之后再次执行updatePowerStateLock,将mDisplayPowerRequest.policy设置 成POLICY_BRIGHT,在updatePowerStateLock函数中,调用requestPowerState时,调用到 DisplayManagerInternal的requestPowerState函数,转到DisplayManagerService中的 LocalService的内部类的requestPowerState函数中,最终调到DisplayPowerController的 requestPowerState。在DisplayPowerCotroller的requestPowerState函数中仅调用 sendUpdatePowerStateLocked发送了一条MSG_UPDATE_POWER_STATE消息来 updatepowerState,在前面设置了policy为POLICY_BRIGHT,所以会将state标志该设置为 Display.STATE_ON,通过animateScreenStateChange来设置动画处理亮屏幕这个流程,并且 setScreenState设置屏幕状态,setScreenState调用到PhoneWindowManager中的 screenTurningOn。

4).在PhoneWindowManager的screenTurningOn函数用回调onScreenTurningOn来发送 MSG_KEYGUARD_DRAWN_COMPLETE消息,最终调用waitForAllWindowsDrawn等待屏幕绘制完成,在 waitForAllWindowsDrawn也是通过一个回调,来发送MSG_WINDOW_MANAGER_DRAWN_COMPLETE消息,来调 用finishWindowsDrawn函数完成屏幕亮屏的绘制,并将屏幕置成enable状态。

点亮屏幕背光灯的顺序流程:

1).点亮屏幕与绘制屏幕动画是一条流程主线,当调用到animateScreenStateChange函数中,调用到了DisplayPowerState中的setScreenState()函数,在setScreenState函数中通过一系列的调用最终会在postScreenUpdateThreadSafe中通过一个回调函数,回调到mScreenUpdateRunnable线程中,在该线程中通过setState函数仅仅修改了mPhotonicModulator的两个参数mScreenState,brightness,通知该线程mPhotonicModulator参数改变,mPhotonicModulator是一个死循环的阻塞线程,等待mScreenState,brightness改变,去执行更新操作,在run方法中监听到参数改变的通知,便会执行更新操作。

2).关键语句:mBlanker.requestDisplayState(state, backlight);调用到DisplayManagerService中的内部类LocalService中的requestDisplayState,然后调用到函数requestGlobalDisplayStateInternal中,经过applyGlobalDisplayStateLocked函数,调用到线程updateDisplayStateLocked中,最终会调用到LocalDisplayAdapter中的内部类LocalDisplayDevice的函数requestDisplayStateLocked中来调用到Light模块,在LocalDisplayDevice构造函数中有设置LightID为LIGHT_ID_BACKLIGHT屏幕背光灯,关键语句为:


1.  mBacklight=lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
2.  mBacklight.setBrightness(brightness);

3).在LightService中的setBrightness函数,设置了color的参数之后,调用到关键函数setLightLocked中,在setLightLocked中,设置了一些参数之后,
有关键语句:

1.  setLight_native(mNativePointer,mId,color,mode,onMS,offMS,brightnessMode);

便调用到native层的com_android_server_lights_lightsService.cpp中的setLight_native函数。
.setLight_native函数,对一些参数进行赋值之后,通过结构体指针参数,调用到light_state_t中的set_light参数所指向的函数地址,我们可以看到
com_android_server_lights_lightsService.cpp该类初始化的时候调用到init_native函数调用到get_device,在get_device中有关键语句:

1.  err = module->methods->open(module, name, &device);

.调用open函数,在hardware/libhardware/include/hardware/hardware.h中的hw_module_t结构体中method方法,由于method方法是hw_module_methods_t类型
,故调用到hw_module_methods_t中的open函数指针参数,open函数在vendor/*/liblights/lights.c中初始化有:
open=open_lights;
在open_lights函数中有:

1.  if (0 == strcmp(LIGHT_ID_BACKLIGHT, name))
2.  set_light =set_light_backlight;

.故在调用到上面这条语句的时,set_light会调用到中的set_light_backlight函数,set_light_backlight函数中有:

1.  err = write_int(&leds[LCD_BACKLIGHT].brightness, brightness);

brightbess是上层传递下来的亮度参数值;LCD_BACKLIGHT是有如下定义.
brightness={“/sys/class/leds/lcd-backlight/brightness”,-1},
write函数中是将该值写入到/sys/class/leds/lcd-backlight/brightness文件节点中去;

DisplayManagerService和背光的关系

一、DisplayManagerService注册localDisplay的适配层
我们先来看构造函数:

public DisplayManagerService(Context context) {                                                                              super(context);mContext = context;mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper()); //消息处理mUiHandler = UiThread.getHandler();mDisplayAdapterListener = new DisplayAdapterListener();/display适配层监视器mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();//成员变量屏幕亮度}

我们再来看onStart函数,publish了一个BinderService和LocalService,还有发送了一个消息。

 @Overridepublic void onStart() {mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),true /*allowIsolated*/);       publishLocalService(DisplayManagerInternal.class, new LocalService());}  

我们看消息处理,就是调用了registerDefaultDisplayAdapter函数:

 private void registerDefaultDisplayAdapter() {                                                                   // Register default display adapter.synchronized (mSyncRoot) {registerDisplayAdapterLocked(new LocalDisplayAdapter(mSyncRoot, mContext, mHandler, mDisplayAdapterListener));}}

这里就是register了DefaultDisplay的适配层,就是和背光相关的。在新建LocalDisplayAdapter的时候我们把mDisplayAdapterListener传过去了。

二、LocalDisplayAdapter & LocalDisplayDevice

LocalDisplayAdapter构造函数调用了父类的,而父类也就是保存了变量

 // Called with SyncRoot lock held.public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,Context context, Handler handler, Listener listener) {super(syncRoot, context, handler, listener, TAG);}

上面又紧跟着调用了registerLocked函数

@Overridepublic void registerLocked() {super.registerLocked();mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {tryConnectDisplayLocked(builtInDisplayId);}}

tryConnectDisplayLocked 函数,先是看传入的builtInDisplayId是否支持,一个是main,一个是hdmi的。
private void tryConnectDisplayLocked(int builtInDisplayId) {…}
然后再去查找这个LocalDisplayDevice,如果是找到了需要更新下configs,没找到需要新建一个LocalDisplayDevice。最后都调用了sendDisplayDeviceEventLocked回调函数.

我们再来看LocalDisplayDevice构造函数,如果传入的是BUILT_IN_DISPLAY_ID_MAIN就是背光的,我们获取背光的Light,保存在mBackLight变量。

然后上面函数调用了sendDisplayDeviceEventLocked函数,就是调用了传入的参数DisplayAdapterListener

protected final void sendDisplayDeviceEventLocked(                                                                                      final DisplayDevice device, final int event) {mHandler.post(new Runnable() { @Overridepublic void run() {            mListener.onDisplayDeviceEvent(device, event);}});}

如果是新建就调用了DisplayManagerSerivce–>handleDisplayDeviceAdded函数,
我们先来看看handleDisplayDeviceAdded,最后将device保存在了mDisplayDevices中:
mDisplayDevices.add(device);

三、设置背光

//requestGlobalDisplayStateInternal中调用的.@Overridepublic void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,SensorManager sensorManager) {synchronized (mSyncRoot) {         DisplayBlanker blanker = new DisplayBlanker() {@Overridepublic void requestDisplayState(int state, int brightness) {// The order of operations is important for legacy reasons.if (state == Display.STATE_OFF) {  requestGlobalDisplayStateInternal(state, brightness);}callbacks.onDisplayStateChange(state);if (state != Display.STATE_OFF) {  requestGlobalDisplayStateInternal(state, brightness);}// #ifdef LAVA_EDIT            // liuwei.2016-11-25,optimize fingerprintd.if(PowerManagerService.isFingerPrintEvent){Slog.e(TAG, "driver have been finish ");DisplayManagerService.mLastFingeDriverFinishTime = SystemClock.uptimeMillis();}// #endif}};mDisplayPowerController = new DisplayPowerController(                                                                                                                                     mContext, callbacks, handler, sensorManager, blanker);}}

requestGlobalDisplayStateInternal函数:

再看看applyGlobalDisplayStateLocked函数,最后遍历device调用updateDisplayStateLocked函数

updateDisplayStateLocked函数调用device的requestDisplayStateLocked返回是Runnable,最后放在workQueue队列中

我们再来看看LocalDisplayDevice的requestDisplayStateLocked函数

上面函数返回一个Runnable放在workQueue,在Runnable 中会调用mBacklight.setBrightness设置背光。
之前是将Runnable接口都放在了mTempDisplayStateWorkQueue中,然后遍历调用了run函数。最后就调用到了LocalDisplayDevice的Runnable接口中设置背光了。

四、背光hal层

我们先来看看LightsService

setLightLocked中最后调用了setLight_native函数。

setLight_native函数如下,其主要也是依赖上面传下来的ptr,作为devices的指针。

而mNativePointer也是调用了init_native函数

这就到驱动了,最终到hardware目录下有个lights.c文件有下面函数

下面我们再来看set_light_backlight函数:

root@lte26007:/sys/class/leds/lcd-backlight # cat brightness

andriod HAL模块也有一个通用的入口地址,这个入口地址就是HAL_MODULE_INFO_SYM变量,通过它,我们可以访问到HAL模块中的所有想要外部访问到的方法。

亮屏流程之Keyguard Window绘制:

AndroidN DisplayManagerService源码简析,亮屏流程分析相关推荐

  1. android camera 拍照流程,Android -- Camera源码简析,启动流程

    com.android.camera.Camera.java,主要的实现Activity,继承于ActivityBase. ActivityBase 在ActivityBase中执行流程: onCre ...

  2. 【Golang源码分析】Go Web常用程序包gorilla/mux的使用与源码简析

    目录[阅读时间:约10分钟] 一.概述 二.对比: gorilla/mux与net/http DefaultServeMux 三.简单使用 四.源码简析 1.NewRouter函数 2.HandleF ...

  3. django源码简析——后台程序入口

    django源码简析--后台程序入口 这一年一直在用云笔记,平时记录一些tips或者问题很方便,所以也就不再用博客进行记录,还是想把最近学习到的一些东西和大家作以分享,也能够对自己做一个总结.工作中主 ...

  4. (Ajax)axios源码简析(三)——请求与取消请求

    传送门: axios源码简析(一)--axios入口文件 axios源码简析(二)--Axios类与拦截器 axios源码简析(三)--请求与取消请求 请求过程 在Axios.prototype.re ...

  5. java ArrayList 概述 与源码简析

    ArrayList 概述 与源码简析 1 ArrayList 创建 ArrayList<String> list = new ArrayList<>(); //构造一个初始容量 ...

  6. Spring Boot源码简析 @EnableTransactionManagement

    相关阅读 Spring Boot源码简析 事务管理 Spring Boot源码简析 @EnableAspectJAutoProxy Spring Boot源码简析 @EnableAsync Sprin ...

  7. ffmpeg实战教程(十三)iJKPlayer源码简析

    要使用封装优化ijk就必须先了解ffmpeg,然后看ijk对ffmpeg的C层封装! 这是我看ijk源码时候的笔记,比较散乱.不喜勿喷~ ijk源码简析: 1.ijkplayer_jni.c 封装的播 ...

  8. 【Android项目】本地FM收音机开发及源码简析

    [Android项目]本地FM收音机开发及源码简析 目录 1.概述 2.收音机的基本原理 3.收音机其他信息 RDS功能 4.Android开发FM收音机源码解析 5.App层如何设计本地FM应用 6 ...

  9. Log-Pilot 源码简析

    Log-Pilot 源码简析 简单介绍 源码简析 Pilot结构体 Piloter接口 main函数 Pilot.Run Pilot.New Pilot.watch Pilot.processEven ...

  10. 安卓手机来电亮屏流程分析

    来电亮屏流程分析 本文档是针对手机来电时候自主点亮屏幕这一流程的分析,很自然的就将其分为2个阶段,第一个是来电,第二个是点亮屏幕. 来电的流程: 来电消息是从RIL层接收到的,然后才开始传递上来. A ...

最新文章

  1. 解决了一些RSS阅读器不能查看图片的问题
  2. 数据可视化应用案例:从面积到人口,再到经济、房贷等等方面透析重庆市
  3. 使用MyBatista----上传图像
  4. JavaScript 函数(作用域以及闭包)
  5. Nginx反向代理配置配置实例
  6. Pentium 4处理器架构/微架构/流水线 (3) - NetBurst微架构
  7. opencv 图像融合
  8. Oracle数据库sys和system用户的默认密码及如何修改密码
  9. Python基础之完数输出
  10. mysql查询bween_MySQL常用查询语句(23个)
  11. RQNOJ 石子合并
  12. zabbix为啥持续报警
  13. 平安京s9服务器维护,决战平安京S9赛季段位怎么继承_决战平安京S9赛季段位继承详情_素材吧...
  14. 2022年要怎么把PayPal里的美元提到国内?
  15. 计算机主板别称是什么城,武汉别名江城又称什么城 武汉被誉为什么城之称
  16. 【CXY】JAVA应用 之 排序
  17. 自学整理之HTML5常用标签和知识——小白篇
  18. Outlook Connector用途
  19. 教你一招搞定 GitHub 下载加速!
  20. 腾讯蔡晨:十年沉淀,腾讯iOA为企业安全保驾护航 1

热门文章

  1. AHP(层次分析法)学习笔记及多层权重Python实践
  2. 安装imageai,tensorflow
  3. 基于R语言做层次聚类分析
  4. c语言实验报告字符数组,C语言实验报告《数组》
  5. 贝叶斯回归 matlab,逻辑回归模型的贝叶斯分析
  6. 原来系统还能这么装!教你虚拟光驱Daemon重装win10
  7. 5GNR解调分析手持式频谱分析仪
  8. 基于FPGA的数字频率计Verilog开发
  9. PCBLayout相关注意事项和常见问题
  10. 通信算法之三十:Turbo仿真链路开发基于《低压电力线宽带载波通信互联互通技术规范第4—1部分物理层通信协议》