天天看點

Android6.0亮屏流程分析1.概述

  • 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