Android7.0背光調節
一.簡述
Android螢幕背光屬於Android系統中display模組,display是從Power中分出來的,所以和Power有著密不可分的關係。背光調節中,又可以分為手動調節和自動調節兩個功能,Android定義背光值0-255。
日常除錯過程中,我們可以直接cat/sys/class/leds/lcd-backlight/brightness的值,來獲得當前螢幕背光的值。
二.流程原理分析
自動背光手動背光中最核心的當屬DisplayPowerControl和AutomaticBrightnessController,兩個類。其初始化流程如下:
2.1. SystemServer.startBootstrapServices
[->SystemServer.java]
acquireWakeLockInternal(IBinder, int,String, String, WorkSource, String, int, ...)
boostScreenBrightnessInternal(long, int)
goToSleepInternal(long, int, int, int)
handleBatteryStateChangedLocked()
handleSandman()
handleScreenBrightnessBoostTimeout()
handleSettingsChangedLocked()
handleUserActivityTimeout()
napInternal(long, int)
onBootPhase(int)
onReceive(Context, Intent)
removeWakeLockLocked(WakeLock, int)
setDozeOverrideFromDreamManagerInternal(int,int)
setMaximumScreenOffTimeoutFromDeviceAdminInternal(int)
setScreenBrightnessOverrideFromWindowManagerInternal(int)
setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(float)
setTemporaryScreenBrightnessSettingOverrideInternal(int)
setUserActivityTimeoutOverrideFromWindowManagerInternal(long)
setUserInactiveOverrideFromWindowManagerInternal()
systemReady(IAppOpsService)
updatePowerStateLocked()
updateWakeLockDisabledStatesLocked()
userActivityInternal(long, int, int,int)
wakeUpInternal(long, String, int,String, int)
首先DisplayPowerControl的初始化在DisplayManagerService中,
private final class LocalService extends DisplayManagerInternal {
@Override
public void initPowerManagement(final DisplayPowerCallbacks callbacks,Handler handler,
SensorManager sensorManager) {
synchronized (mSyncRoot) {
DisplayBlanker blanker = newDisplayBlanker() {
@Override
public voidrequestDisplayState(int state, int brightness) {
// The order ofoperations is important for legacy reasons.
if (state ==Display.STATE_OFF) {
requestGlobalDisplayStateInternal(state, brightness);
}
callbacks.onDisplayStateChange(state);
if (state !=Display.STATE_OFF) {
requestGlobalDisplayStateInternal(state, brightness);
}
}
};
mDisplayPowerController = new DisplayPowerController(
mContext, callbacks, handler, sensorManager, blanker);
}
}
DisplayManagerInternal的本地服務實現,LocalService,當PowerManagerService呼叫SystemReady的時候,同時也呼叫了DisplayManagerInternal的initPowerManagement。initPowerManagement該方法比較重要,重點在於提供了一個DisplayBlanker回撥,用來與PMS互動設定power相關的狀態,還有就是使用LightService設定背光值。
其中還初始化了背光核心類DisplayPowerControl,在DisplayManagerService中,也就requestPowerState方法中使用了DisplayPowerControl,先看看他的構造方法
public DisplayPowerController(Context context,
DisplayPowerCallbacks callbacks,Handler handler,
SensorManager sensorManager,DisplayBlanker blanker) {
DisplayPowerCallbacks在PowerManagerService中實現,Handler是PMS的handler,在DisplayPowerController的構造方法中,初始化了另一個核心類AutomaticBrightnessController。關於Android自動背光的功能所有的控制都在該類中。
2.2. 自動背光
2.1中介紹了AutomaticBrightnessController,是自動背光的核心,它是在DisplayPowerController的構造方法中,被初始化的。其構造方法如下:
public AutomaticBrightnessController(Callbacks callbacks, Looper looper,
SensorManager sensorManager, SplineautoBrightnessSpline, int lightSensorWarmUpTime,
int brightnessMin, intbrightnessMax, float dozeScaleFactor,
int lightSensorRate, longbrighteningLightDebounceConfig,
long darkeningLightDebounceConfig,boolean resetAmbientLuxAfterWarmUpConfig,
int ambientLightHorizon, floatautoBrightnessAdjustmentMaxGamma )
mSensorManager = sensorManager;//用來獲取光感感測器
mScreenAutoBrightnessSpline =autoBrightnessSpline;//光照/背光mapping對應值,主要靠config匹配,系統配置檔案中有兩個陣列:
<integer-arrayname="config_autoBrightnessLevels">//標示光照1-10000
<integer-arrayname="config_autoBrightnessLcdBacklightValues">//螢幕背光值1-255,他們之間的對應函式靠mScreenAutoBrightnessSpline實現。
mAmbientLightHorizon =ambientLightHorizon;
mWeightingIntercept =ambientLightHorizon;
mScreenAutoBrightnessAdjustmentMaxGamma= autoBrightnessAdjustmentMaxGamma;//gamma值,這個預設為300%,他是自動背光調節,計算光值大小的一個係數,該值得大小,體現為,gamma大於1,越來越大時,當環境光照變化時,螢幕背光值反映的很明顯。當小於1,越來越小時,環境光變化時,螢幕背光值反映越來越緩慢。一般取值在1的左右。
mScreenAutoBrightnessAdjustment;//當手機設定為自動背光,此時還需要手動調節背光條調節背光,此時該值就是對應著背光條的值大小該值範圍大小-1~1。預設為0,代表背光條在最中間位置,最右邊代表1,反之則為-1
2.2.1 自動背光流程
下面就是自動背光詳細的程式碼流程:
SensorEventListener mLightSensorListener.onSensorChanged-> handleLightSensorEvent
1.->applyLightSensorMeasurement
2.->updateAmbientLux(time) ->updateAutoBrightness(true) -> Callbacks.updateBrightness()
-> DisplayPowerController.updateBrightness() -> sendUpdatePowerState()->sendUpdatePowerStateLocked()
-> MSG_UPDATE_POWER_STATE -> updatePowerState ->animateScreenBrightness ----調節螢幕亮度
-> DisplayPowerState$PhotonicModulator.run() ->DisplayBlanker.requestDisplayState() -> DisplayManagerService(newDisplayBlanker)
-> DisplayManagerInternal.DisplayPowerCallbacks.onStateChanged
其中animateScreenBrightness這個方法就是設定螢幕背光的入口,配合animateScreenStateChange,改變DisplayPowerState中的state和backlight值,當DisplayPowerState中這兩個值都變化時其中的PhotonicModulator執行緒就會被喚醒,此時便會開始執行設定背光值的操作,標誌性log如下:DisplayPowerState: Updatingscreen state: state=ON, backlight=255
這裡便會又走進initPowerManagement中初始化的DisplayBlanker,之前我們說該類的作用就是與PMS互動,1.設定power狀態(螢幕狀態…)2.與Light互動設定背光值。分別對應方法DisplayPowerCallbacks.onDisplayStateChange(state),requestGlobalDisplayStateInternal。
2.2.2 自動背光原理
2.2.1中簡述了當手機開啟自動背光功能時,程式碼走的流程,但是實際執行過程中,為了避免頻繁的改變手機背光值,必須採取一些操作。使得使用者體驗更好。
2.2.1程式碼走到handleLightSensorEvent時,會分成兩部分applyLightSensorMeasurement和updateAmbientLux,
private void applyLightSensorMeasurement(long time, float lux) {
mRecentLightSamples++;
// Store all of the light measurements for the intial horizon period.This is to help
// diagnose dim wake ups and slow responses in b/27951906.
if (time <= mLightSensorEnableTime + mAmbientLightHorizon) {
mInitialHorizonAmbientLightRingBuffer.push(time, lux);
}
mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon);
mAmbientLightRingBuffer.push(time, lux);
// Remember this sample value.
mLastObservedLux = lux;
mLastObservedLuxTime = time;
}
這裡需要說明的時,引數time,指的是從開機到現在的毫秒數(手機睡眠的時間不包括在內),所以說這裡的一個判斷指的是設定完自動背光功能開啟之後採集前十秒之內的光線值,但是這個陣列在目前程式碼中只是啟到一個參考作用,真正用到的是mAmbientLightRingBuffer,prune就是裁剪,對於為什麼裁剪一下,我們這裡先暫且放放,push就是講採集到的光線值放入集合內。
因此這裡我們理解為每次當光線感測器接收到光線值時,都會講之前採集到的值,做一個裁剪操作,然後將本次的光線值存入集合。接著就去執行updateAmbientLux操做,
private void updateAmbientLux(long time) {
// If the light sensor was just turned on then immediately update ourinitial
// estimate of the current ambient light level.
if (!mAmbientLuxValid) {
//這裡就是當我們剛設定手機螢幕背光為自動背光時,我們需要手機立即生效的操作
}
long nextBrightenTransition =nextAmbientLightBrighteningTransition(time);
long nextDarkenTransition = nextAmbientLightDarkeningTransition(time);
float ambientLux = calculateAmbientLux(time);
if (ambientLux >= mBrighteningLuxThreshold &&nextBrightenTransition <= time
|| ambientLux <=mDarkeningLuxThreshold && nextDarkenTransition <= time) {
setAmbientLux(ambientLux);
updateAutoBrightness(true);
nextBrightenTransition =nextAmbientLightBrighteningTransition(time);
nextDarkenTransition =nextAmbientLightDarkeningTransition(time);
}
long nextTransitionTime = Math.min(nextDarkenTransition,nextBrightenTransition);
nextTransitionTime =
nextTransitionTime > time ?nextTransitionTime : time + mLightSensorRate;
mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX,nextTransitionTime);
}
nextBrightenTransition下一次變亮的時間nextDarkenTransition下一次變暗的時間,mBrighteningLuxThreshold使螢幕變亮所需要的環境光照閾值,一般為當前光線值的1.1倍,mDarkeningLuxThreshold使螢幕變暗所需要的環境光照閾值,一般為當前光線值的1.2倍,當環境光照小於該數值的時候,螢幕才可能變暗。這裡就是之前所說為了避免頻繁改變螢幕背光,採取一些操作。使得使用者體驗更好。
calculateAmbientLux(time)這裡就是獲取當前時間之前採取的光線值的一個加權平均,權重為採集時間。然後就會設定mAmbientLux為剛剛計算得到的光值。
updateAutoBrightness(true),就是計算出需要設定到螢幕上的光值大小,在前面也介紹過mScreenAutoBrightnessSpline就是用來對應光值和背光值的,其運用的演算法就是數學中的樣條插值,目的在於使得光線變化時,螢幕光值設定的更加平滑。在updateAutoBrightness操作中,會設定成員mScreenAutoBrightness為當前計算的到的光值,之後的設定過程中會同過getAutomaticScreenBrightness獲取其值大小
2.3. 手動改背光
不管是從SystemUI下拉statubar,從qstile拖動背光條,還是從settings的拖動,他們都會向資料庫寫入相應的數值。
此時PowerManagerService裡的SettingsObserver,一旦檢測到資料庫有變化,便會直接執行相關更新操作,與自動區別的只是引數是否為auto的不一樣。
private void handleSettingsChangedLocked() {
updateSettingsLocked();
updatePowerStateLocked();
}
三.實際運用
2.3. 需求:自動背光和手動背光切換時螢幕亮度要求不變化
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.javab/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index 7d986d1..6481cb4 100644
---a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
---a/services/core/java/com/android/server/display/DisplayPowerController.java
+++b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -48,6 +48,13 @@ importandroid.view.WindowManagerPolicy;
import java.io.PrintWriter;
+import android.database.ContentObserver;
+import android.content.ContentResolver;
+import android.provider.Settings;
+import android.os.UserHandle;
+
/**
*Controls the power state of the display.
*
@@ -261,6 +268,8 @@ final classDisplayPowerController implements AutomaticBrightnessController.Call
private static final int BRIGHTNESS_RAMP_RATE_FASTER = 800;
+ private BrightnessModeObserver mBrightnessModeObserver;
/**
* Creates the display power controller.
*/
@@ -388,6 +397,35 @@ final classDisplayPowerController implements AutomaticBrightnessController.Call
}
}
+ mBrightnessModeObserver = new BrightnessModeObserver(null);
+ mBrightnessModeObserver.startObserving();
+
+ }
+
+ private class BrightnessModeObserver extends ContentObserver {
+ public BrightnessModeObserver(Handler handler) {
+ super(handler);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ boolean autoBrightness =Settings.System.getIntForUser(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS_MODE, 1, UserHandle.USER_CURRENT) ==1;
+ if (!autoBrightness) {
+ int brightness =mPowerState.getScreenBrightness();
+ Settings.System.putIntForUser(mContext.getContentResolver(),
+ Settings.System.SCREEN_BRIGHTNESS, brightness, UserHandle.USER_CURRENT);
+ }
+ }
+
+ public void startObserving() {
+ final ContentResolver cr = mContext.getContentResolver();
+ cr.unregisterContentObserver(this);
+ cr.registerContentObserver(Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE),
+ false,this);
+ }
}
/**
這裡就是在DisplayPowerController增加一個觀察者,當是否為自動時,直接獲取當前背光值並寫入資料庫,此時切換時,光值不會改變
相關推薦
Android7.0背光調節
涉及類: 一.簡述 Android螢幕背光屬於Android系統中display模組,display是從Power中分出來的,所以和Power有著密不可分的關係。背光調節中,又可以分為手動調節和
android 關於LCD背光調節漸變過程引起背光閃爍問題
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
基於嵌入式Linux的LCD背光調節及驅動的實現
0 引言 在手持式裝置中,液晶顯示屏的使用越來越廣泛。由於LCD自身是不能發光的,它需要一個強勁的光源來給它提供背光,以便清晰地顯示資訊。這樣的光源是非常耗電的,通常液晶顯示屏的功耗常常佔到系統總功耗的60%以上。以群創的7寸屏為例,通常背光燈的功耗為2.
背光調節亮度預設值修改
1、packages/apps/Settings/res/layout/preference_dialog_brightness.xml 進行背光調節dialog進行佈局。 2、packages/apps/Settings/src/com/android/settings/
使用IOCTL程式碼實現LCD背光調節
國內這樣的程式碼找不到,於是參考了相關程式碼後完善如下程式碼,且實現方式通過IOCTL程式碼實現LCD背光調節的功能。 適合場合為平板電腦或者筆記本。主要還是要靠BIOS支援與否。 編譯環境使用:Dev-cpp工具編寫。 #include <stdio.h>
[RK3288][Android7.1.2] 系統背光亮度顛倒
平臺:RK3288 Android系統:7.1.2 Linux版本:4.4.71 在點亮edp屏幕後,發現在Setting應用裡調節亮度是相反的: #include "rk3288-evb.dtsi" #include "rk3288-android.dtsi" 即最大
在陽光下關閉自動調節功能後,背光很亮,開啟自動調節亮度,背光很暗[FAQ12718][AAL] 開啟MTK_AAL_SUPPORT 後,自動亮度調節速度變慢
[DESCRIPTION] 在陽光下關閉自動調節功能後,背光很亮,開啟自動調節亮度,背光很暗 在設定MTK_AAL_SUPPORT =yes後,選擇自動背光,環境變化後,背光亮度調節比較慢 [SOLUTION] 有兩個地方可以加快AAL 對背光PW
安卓調節背光變化慢的問題
高通預設調節背光的時候,為了滿足人眼的適應性,所以調節是一個漸變的過程。比如從最亮調到最暗,背光是慢慢變暗的;或者從最暗調到最亮,背光也是慢慢變亮的。但是這種特性有時候會讓人感覺不舒服,所以現在討論如何關掉這個特性。 路徑: android\frameworks\base\
android7.1預設背光亮度及編譯除錯
android7.1預設背光亮度及編譯除錯始修改\frameworks\base\packages\SettingsProvider\res\values\defaults.xml<integername="def_screen_brightness">102&l
Android背光亮度調節
最近在做一個App的設定項,亮度調節。真正做時,發現Android亮度調節比預想要複雜一些。其實目前網上已有不少這方面的資料,但有些博文具有一定誤導性。在此將這塊內容按照自己理解整理一下。 整體上看,Android亮度調節分為三個層次,分別是:Android系統亮度調節、A
imx6背光驅動調試
註意 實參 sdn 獲取 kobject ont eve ini bject 1.內核配置pwm背光驅動make menuconfig:Device Driver ---> Graphics support ---> [*] Back
Android7.0對dlopen的改變
tail 地址 npr and eof size strtok log brush 兩個內存段 在同一個進程空間中dlopen一個.so文件,理論上在內存中是同一片區域,但實際調試中發現Android7.0(read "/proc/self/maps")中,先後讀同一個.
appium_v1.4.16版本不適配android7.0系統,運行報錯“Attempt to re-install io.appium.settings without first uninstalling”
urn fail tin ins 找到 auto his ger 問題: 要解決的問題:appium在androidV7.0系統上運行時報錯 Failure [INSTALL_FAILED_ALREADY_EXISTS: Attempt to re-install io.a
Android7.0調用系統相機拍照、讀取系統相冊照片+CropImageView剪裁照片
alpha pri process 點擊事件 self tps 而在 center ase Android手機拍照、剪裁,並非那麽簡單 簡書地址:[我的簡書–T9的第三個三角] 前言 項目中,基本都有用戶自定義頭像或自定義背景的功能,實現方法一般都是調用
Android7.0打包安裝問題
信息 num .com print 應用 ima text ret pan 一.問題描述 Android 7.0 引入一項新的應用簽名方案 APK Signature Scheme v2,先使用APK Signature Scheme v2簽名打包,然後再使用python腳
appium在android7.0上無法啟動問題
ESS cep 升級 代碼 resp 部分 elf back file 前言 由於最近很多android手機升級到7.0系統了,有些小夥伴的appium版本用的還是1.4版本,在運行android7.0的app自動化時候遇到無法啟動問題:WebDriverException
Android7.0 MediaRecorder源碼分析
錄像 stage sdn ice ren oop 新建 n) edi 最近在做Camera的方案(雙進程打開一個Camera),涉及到使用MediaRecorder 進行錄像,還是自己新建一套錄像系統。接下來我將記錄下本次源碼分析的流程。 有關於Client和Server
高通LCD的pwm背光驅動
deb Owner null github sent kernel hub PC nes 發生異常的現象: msm8953 lcd在快速亮滅的情況下背光概率性休眠不滅;測量高通pwm,發現正常的時候pwm的管腳LCM_BL_PWM為低電平,失敗的時候為高電平; 根據原理圖:
Android7.0 API變更
接收消息 靜態鏈接 status pin acc 進程 bsp 文件名 ict Android N 除了提供諸多新特性和功能外,還對系統和 API 行為做出了各種變更。 本文重點介紹您應該了解並在開發應用時加以考慮的一些重要變更。 如果您之前發布過 Android 應用,請
Android7.0文件訪問權限
provide utf load mission perm extern grant download nal 例子:下載apk然後安裝 <provider android:name="android.support.v4.content.FileProvide