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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM