• Android6.0亮屏流程分析


    • 1.概述

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

    • 2.流程分析

    •  2.1 唤醒源 

      通过了解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方法时,会调用到relayoutWindow将win的mTurnOnScreen设置为true。

      3).在应用addWindow的时候,绘制屏幕调用WindowAnimator类的animateLocked函数,取得window列表中需要绘制的window,创建相应surface,调用WindowStateAnimator类的prepareSurfaceLocked接口,在这个接口中会调用showSurfaceRobustlyLocked,通过判断win.mTurnOnScreen的值为true,将Animator属性中加入  SET_TURN_ON_SCREEN标志: mAnimator.mBulkUpdateParams |= SET_TURN_ON_SCREEN;

      4).在wms执行animateLocked的时候会通过SET_TURN_ON_SCREEN这个属性将wms的mTurnOnScreen设置为true。

      5).最终在最终在WindowManagerService的performLayoutAndPlaceSurfacesLockedInner函数中调用wakeUp:

      if (mTurnOnScreen) {
      if (mAllowTheaterModeWakeFromLayout
      || Settings.Global.getInt(mContext.getContentResolver(),
      Settings.Global.THEATER_MODE_ON, 0) == 0) {
      if (DEBUG_VISIBILITY || DEBUG_POWER) {
      Slog.v(TAG, "Turning screen on after layout!");
      }
      mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.server.wm:TURN_ON");
      }
      mTurnOnScreen = false;
      }

      2.2唤醒流程

      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屏幕背光灯,关键语句为:

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

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

    有关键语句:

    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中有关键语句:

    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函数中有:

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

    .故在调用到上面这条语句的时 ,set_light会调用到中的set_light_backlight函数,set_light_backlight函数中有:
    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文件节点中去;

    http://m.blog.csdn.net/article/details?id=53205887

  • 相关阅读:
    Visual Assist X 安装失败解决办法
    ACM-水池数目问题
    代码生成器 CodeBuilder 2.7 新版发布
    Fireasy 官网改版
    跟我学: 使用 fireasy 搭建 asp.net core 项目系列之三 —— 配置
    跟我学: 使用 fireasy 搭建 asp.net core 项目系列之二 —— 准备
    跟我学: 使用 fireasy 搭建 asp.net core 项目系列之一 —— 开篇
    nopCommerce 学习之路(一)Nop之强制拆迁
    平庸技术流,用 WebApi +AngularJS 实现网络爬虫
    nopCommerce 学习之路(二)从EF到NPoco
  • 原文地址:https://www.cnblogs.com/xiayexingkong/p/6510252.html
Copyright © 2020-2023  润新知