-
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