亮度调节

亮度调节分两种,一种自动亮度调节,一种手动亮度调节,调用的入口在Settings和SystemUI当中,

SytemUI手动调节亮度方式如下

    //非自动背光下的调节else if (!mAutomatic) {final int val = value + mMinimumBacklight;if (stopTracking) {MetricsLogger.action(mContext, MetricsEvent.ACTION_BRIGHTNESS, val);}//利用aidl调用PowManangerService的内部类BinderService处理背光调节的请求(val的值在0-255之间)setBrightness(val);if (!tracking) {AsyncTask.execute(new Runnable() {public void run() {//把调节的亮度更新到数据库,存取的值为(0-255)Settings.System.putIntForUser(mContext.getContentResolver(),Settings.System.SCREEN_BRIGHTNESS, val,UserHandle.USER_CURRENT);}});}} else {//自动背光开关打开的情况下调节进度条final float adj = value / (BRIGHTNESS_ADJ_RESOLUTION / 2f) - 1;//利用aidl调用PowManangerService的内部类BinderService处理背光调节的请求(adj的值在 -1,1之间)setBrightnessAdj(adj);if (!tracking) {AsyncTask.execute(new Runnable() {public void run() {//把调节的亮度更新到数据库,存取的值为(-1 - 1)Settings.System.putFloatForUser(mContext.getContentResolver(),Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, adj,UserHandle.USER_CURRENT);}});}}

1.先通过Binder进程间通信与PowManangerService的内部类BinderService进行交互,然后更新Settings数据库
把亮度值存到Settings数据库当中
2.自动背光关闭情况下,手动可调节的范围0-255,自动开关打开情况下,手动可调节范围 -1 - 1;

  • setBrightness(val) 方法的实现
   private void setBrightness(int brightness) {try {//通过IPC进程间通信调用内部类BinderService的接口函数mPower.setTemporaryScreenBrightnessSettingOverride(brightness);} catch (RemoteException ex) {}}
  • setBrightnessAdj(adj);
    private void setBrightnessAdj(float adj) {try {//通过IPC进程间通信调用内部类BinderService的接口函数mPower.setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(adj);} catch (RemoteException ex) {}}

继续分析PowerManagerService中的setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternalChj方法

   @Override // Binder callpublic void setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideChj(int dispalyId,float adj) {mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);final long ident = Binder.clearCallingIdentity();try {setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternalChj(dispalyId,adj);} finally {Binder.restoreCallingIdentity(ident);}}

接着调用setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternalChj方法,方法实现如下:

    private void setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternalChj(int displayId,float adj) {synchronized (mLock) {// Note: This condition handles NaN because NaN is not equal to any other// value, including itself.if (displayId == DEFAULT_DISPLAY){if (mTemporaryScreenAutoBrightnessAdjustmentSettingOverride != adj) {mTemporaryScreenAutoBrightnessAdjustmentSettingOverride = adj;mDirty |= DIRTY_SETTINGS;updatePowerStateLocked();}} else if (displayId == SECOND_DISPLAY){if (mTemporaryScreenAutoBrightnessAdjustmentSettingOverrideSecondDisplay != adj) {mTemporaryScreenAutoBrightnessAdjustmentSettingOverrideSecondDisplay = adj;mDirty |= DIRTY_SETTINGS;updatePowerStateLocked();}}}}
  • 1.经过一系列的调用最终都会调到PowerManagerService的setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternalChj方法当中
  • 2.针对不同屏幕设置不同的亮度(mTemporaryScreenAutoBrightnessAdjustmentSettingOverrideSecondDisplay),displayId代表屏幕Id值(0代表中控,1代表副屏幕,2代表仪表,3代表空调)
  • 3.最终都会调用到updatePowerStateLocked方法当中

播放视频下的亮度调节设置

在播放视频时,可以通过上下滑动来调整屏幕的亮度,但是,退出播放视频以后,又恢复到原来的亮度,其调用接口在PowerManagerService的setScreenBrightnessOverrideFromWindowManagerChj方法

        @Overridepublic void setScreenBrightnessOverrideFromWindowManagerChj(int screenBrightness,int displayId){if (screenBrightness < PowerManager.BRIGHTNESS_DEFAULT|| screenBrightness > PowerManager.BRIGHTNESS_ON) {screenBrightness = PowerManager.BRIGHTNESS_DEFAULT;}setScreenBrightnessOverrideFromWindowManagerInternal(screenBrightness,displayId);}
    private void setScreenBrightnessOverrideFromWindowManagerInternal(int brightness,int displayId) {synchronized (mLock) {if (displayId == DEFAULT_DISPLAY){if (mScreenBrightnessOverrideFromWindowManager != brightness) {mScreenBrightnessOverrideFromWindowManager = brightness;mDirty |= DIRTY_SETTINGS;updatePowerStateLocked();}}else if (displayId == SECOND_DISPLAY){if (mScreenBrightnessOverrideSecondFromWindowManager != brightness) {mScreenBrightnessOverrideSecondFromWindowManager = brightness;mDirty |= DIRTY_SETTINGS;updatePowerStateLocked();}}}}

1.针对不同的屏幕适配不同的亮度,这里只针对中屏幕和副屏幕亮度做调节,因为只有中控和副屏才可以播放视频。

2.最终也会调用到updatePowerStateLocked方法当中

在updatePowerStateLocked会调用updateDisplayPowerStateLocked方法处理屏幕的亮灭以及亮度调节的逻辑
所以我们直接看updateDisplayStateLocked方法解析


private boolean updateDisplayPowerStateLocked(int dirty) {final boolean oldDisplayReady = mDisplayReady;if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS| DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED| DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST | DIRTY_VR_MODE_CHANGED |DIRTY_QUIESCENT)) != 0) {mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();// Determine appropriate screen brightness and auto-brightness adjustments.//用来决定中控屏幕使用自动亮度还是手动设置亮度boolean brightnessSetByUser = true;boolean brightnessSetByUserSecondDisplay = true;// 需要设置的亮度值(中控),默认为config.xml中config_screenBrightnessSettingDefault的值int screenBrightness = mScreenBrightnessSettingDefault;// 需要设置的亮度值(副屏),默认为config.xml中config_screenBrightnessSettingDefault的值int screenBrightnessSecondDisplay = mScreenBrightnessSettingDefault;//需要设置的亮度值(仪表),默认为config.xml中config_screenBrightnessSettingDefault的值int screenBrightnessIpc = mScreenBrightnessSettingDefault;//需要设置的亮度值(空调),默认为config.xml中config_screenBrightnessSettingDefault的值int screenBrightnessCcp = mScreenBrightnessSettingDefault;//自动背光调节的比例值(中控)float screenAutoBrightnessAdjustment = 0.0f;//自动背光调节的比例值(副屏)float screenAutoBrightnessAdjustmentSecondDisplay = 0.0f;//是否打开自动背光开关,在Settings设置打开,该值为true,否则为falseboolean autoBrightness = (mScreenBrightnessModeSetting ==Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);boolean autoBrightnessSecondDisplay = autoBrightness;//系统服务未启动完成情况下,设置以下各项都为falseif (!mBootCompleted) {// Keep the brightness steady during boot. This requires the// bootloader brightness and the default brightness to be identical.autoBrightness = false;brightnessSetByUser = false;autoBrightnessSecondDisplay = false;brightnessSetByUserSecondDisplay = false;//VR模式下的设置} else if (mIsVrModeEnabled) {screenBrightness = mScreenBrightnessForVrSetting;autoBrightness = false;//当主屏或者副屏正在播放视频} else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)|| isValidBrightness(mScreenBrightnessOverrideSecondFromWindowManager)) {if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)){screenBrightness = mScreenBrightnessOverrideFromWindowManager;autoBrightness = false;brightnessSetByUser = false;}else if (isValidBrightness(mTemporaryScreenBrightnessSettingOverride)){screenBrightness = mTemporaryScreenBrightnessSettingOverride;screenBrightnessIpc = mTemporaryScreenBrightnessSettingOverride;screenBrightnessCcp = mTemporaryScreenBrightnessSettingOverride;} else if ((isValidBrightness(mScreenBrightnessSetting))){screenBrightness = mScreenBrightnessSetting;screenBrightnessIpc = mScreenBrightnessSetting;screenBrightnessCcp = mScreenBrightnessSetting;}if (isValidBrightness(mScreenBrightnessOverrideSecondFromWindowManager)){screenBrightnessSecondDisplay = mScreenBrightnessOverrideSecondFromWindowManager;autoBrightnessSecondDisplay  = false;brightnessSetByUserSecondDisplay = false;}else if (isValidBrightness(mTemporaryScreenBrightnessSettingOverrideSecondDisplay)|| isValidBrightness(mTemporaryScreenBrightnessSettingOverride)) {screenBrightnessSecondDisplay = mTemporaryScreenBrightnessSettingOverrideSecondDisplay;if (isValidBrightness(mTemporaryScreenBrightnessSettingOverride)){screenBrightnessCcp = mTemporaryScreenBrightnessSettingOverride;screenBrightnessIpc = mTemporaryScreenBrightnessSettingOverride;}}else if (isValidBrightness(mScreenBrightnessSettingSecondDisplay)|| isValidBrightness(mScreenBrightnessSetting)) {if (isValidBrightness(mScreenBrightnessSetting)){screenBrightnessIpc = mScreenBrightnessSetting;screenBrightnessCcp = mScreenBrightnessSetting;}screenBrightnessSecondDisplay = mScreenBrightnessSettingSecondDisplay;}//SystemUI中的调节} else if ((isValidBrightness(mTemporaryScreenBrightnessSettingOverride)) ||(isValidBrightness(mTemporaryScreenBrightnessSettingOverrideSecondDisplay))) {screenBrightness = mTemporaryScreenBrightnessSettingOverride;screenBrightnessSecondDisplay = mTemporaryScreenBrightnessSettingOverrideSecondDisplay;screenBrightnessIpc = mTemporaryScreenBrightnessSettingOverride;screenBrightnessCcp = mTemporaryScreenBrightnessSettingOverride;//Settings中的调节 //Settings.System.SCREEN_BRIGHTNESS的值,即保存在数据库中的亮度值,亮度值设置完成后,都会进行保存} else if ((isValidBrightness(mScreenBrightnessSetting)) ||(isValidBrightness(mScreenBrightnessSettingSecondDisplay))) {screenBrightness = mScreenBrightnessSetting;screenBrightnessSecondDisplay = mScreenBrightnessSettingSecondDisplay;screenBrightnessIpc = mScreenBrightnessSetting;screenBrightnessCcp = mScreenBrightnessSetting;}//自动背光开关打开(主控),手动调节亮度,设置亮度调节的比例值if (autoBrightness) {screenBrightness = mScreenBrightnessSettingDefault;if (isValidAutoBrightnessAdjustment(mTemporaryScreenAutoBrightnessAdjustmentSettingOverride)) {screenAutoBrightnessAdjustment =mTemporaryScreenAutoBrightnessAdjustmentSettingOverride;} else if (isValidAutoBrightnessAdjustment(mScreenAutoBrightnessAdjustmentSetting)) {screenAutoBrightnessAdjustment = mScreenAutoBrightnessAdjustmentSetting;}}//自动背光打开(副屏),调节亮度,设置亮度调节的比例值if (autoBrightnessSecondDisplay) {screenBrightnessSecondDisplay = mScreenBrightnessSettingDefault;if (isValidAutoBrightnessAdjustment(mTemporaryScreenAutoBrightnessAdjustmentSettingOverrideSecondDisplay)) {screenAutoBrightnessAdjustmentSecondDisplay =mTemporaryScreenAutoBrightnessAdjustmentSettingOverrideSecondDisplay;} else if (isValidAutoBrightnessAdjustment(mScreenAutoBrightnessAdjustmentSettingSecondDisplay)) {screenAutoBrightnessAdjustmentSecondDisplay = mScreenAutoBrightnessAdjustmentSettingSecondDisplay;}}screenBrightness = Math.max(Math.min(screenBrightness,mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);screenAutoBrightnessAdjustment = Math.max(Math.min(screenAutoBrightnessAdjustment, 1.0f), -1.0f);screenBrightnessSecondDisplay = Math.max(Math.min(screenBrightnessSecondDisplay,mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);screenAutoBrightnessAdjustmentSecondDisplay = Math.max(Math.min(screenAutoBrightnessAdjustmentSecondDisplay, 1.0f), -1.0f);screenBrightnessIpc = Math.max(Math.min(screenBrightnessIpc,mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);screenBrightnessCcp =Math.max(Math.min(screenBrightnessCcp,mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);// Update display power request.mDisplayPowerRequest.screenBrightness = screenBrightness;mDisplayPowerRequest.screenBrightnessSecondDisplay = screenBrightnessSecondDisplay;mDisplayPowerRequest.screenBrightnessCcp = screenBrightnessCcp;mDisplayPowerRequest.screenBrightnessIpc = screenBrightnessIpc;mDisplayPowerRequest.screenAutoBrightnessAdjustment =screenAutoBrightnessAdjustment;mDisplayPowerRequest.screenAutoBrightnessAdjustment = screenAutoBrightnessAdjustment;mDisplayPowerRequest.screenAutoBrightnessAdjustmentSecondDisplay =screenAutoBrightnessAdjustmentSecondDisplay;mDisplayPowerRequest.brightnessSetByUser = brightnessSetByUser;mDisplayPowerRequest.brightnessSetByUserSecondDisplay = brightnessSetByUserSecondDisplay;mDisplayPowerRequest.useAutoBrightness = autoBrightness;mDisplayPowerRequest.useAutoBrightnessSecondDisplay = autoBrightnessSecondDisplay;mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND&& (mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {mDisplayPowerRequest.dozeScreenState = Display.STATE_DOZE;}mDisplayPowerRequest.dozeScreenBrightness =mDozeScreenBrightnessOverrideFromDreamManager;} else {mDisplayPowerRequest.dozeScreenState = Display.STATE_UNKNOWN;mDisplayPowerRequest.dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;}mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,mRequestWaitForNegativeProximity);mRequestWaitForNegativeProximity = false;if ((dirty & DIRTY_QUIESCENT) != 0) {sQuiescent = false;}return mDisplayReady && !oldDisplayReady;}

四屏幕调节的逻辑,

  • 1.手动调节的时候,无论自动背光开关打开或关闭,都会跟随中控的亮度变化而变换,(即,手动调节中控的亮度条,4个屏幕设置亮度一致)
  • 2.自动背光自动调节亮度上三屏幕一致,使用仪表中的光感Sensor数据(中控,副屏,仪表亮度保持一致),空调屏幕自动背光自动调节单独由空调屏幕的光感Sensor控制
  • 3.把请求的数据封装到mDisplayPowerRequest对象里,交给DisplayManagerService中requestPowerState去处理,最终会调用到DispalyPowerController.java
    中的updatePowerState方法中
  • 4.以上亮度设置值,优先级为:自动调节亮度 > 视频播放时设置亮度 > Settings、SystemUI中设置亮度(因为autoBrightness时将screenBrightness重置了)。

DispalyPowerController : updatePowerState()

  private void updatePowerState() {// Update the power state request.final boolean mustNotify;boolean mustInitialize = false;boolean autoBrightnessAdjustmentChanged = false;//自动背光打开,有没有手动调节亮度,初始值设置为false(中控)boolean autoBrightnessAdjustmentSecondChanged = false;//自动背光打开,有没有手动调节亮度,初始值设置为false(副屏)//自动背光中控控制器AutomaticBrightnessController automaticBrightnessController = getAutomaticBrightnessController(DEFAULT_DISPLAY);//自动背光副屏控制器AutomaticBrightnessController automaticBrightnessControllerSecondDisplay = getAutomaticBrightnessController(SECOND_DISPLAY);//自动背光空调控制器AutomaticBrightnessController automaticCCPBrightnessController = getAutomaticBrightnessController(CCP_DISPLAY);//自动背光仪表控制器AutomaticBrightnessController automaticIPCBrightnessController = getAutomaticBrightnessController(IPC_DISPLAY);if (DEBUG) {Slog.d(TAG, "updatePowerState: original no displayId");}synchronized (mLock) {mPendingUpdatePowerStateLocked = false;if (mPendingRequestLocked == null) {return; // wait until first actual power request}//开机第一次重启会走这边的逻辑.重新创建DisplayPowerRequest对象if (mPowerRequest == null) {mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;mPendingWaitForNegativeProximityLocked = false;mPendingRequestChangedLocked = false;mustInitialize = true;//从PowerManagerService中获取DisplayPowerRequest对象} else if (mPendingRequestChangedLocked) {autoBrightnessAdjustmentChanged = (mPowerRequest.screenAutoBrightnessAdjustment!= mPendingRequestLocked.screenAutoBrightnessAdjustment);autoBrightnessAdjustmentSecondChanged = (mPowerRequest.screenAutoBrightnessAdjustmentSecondDisplay!= mPendingRequestLocked.screenAutoBrightnessAdjustmentSecondDisplay );mPowerRequest.copyFrom(mPendingRequestLocked);mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;mPendingWaitForNegativeProximityLocked = false;mPendingRequestChangedLocked = false;mDisplayReadyLocked = false;}mustNotify = !mDisplayReadyLocked;}// Initialize things the first time the power state is changed.if (mustInitialize) {initialize();}// Compute the basic display state using the policy.// We might override this below based on other factors.int state;//初始化亮度值int brightness = PowerManager.BRIGHTNESS_DEFAULT;int brightnessSecondDisplay = PowerManager.BRIGHTNESS_DEFAULT;int brightnessIpc = PowerManager.BRIGHTNESS_DEFAULT;int brightnessCcp = PowerManager.BRIGHTNESS_DEFAULT;// Configure auto-brightness.//检测是是否开启自动亮度调节boolean autoCCPIPCBrightnessEnabled = mZMQ.checkBrightnessAutomodeEnabled(CCP_DISPLAY);boolean performScreenOffTransition = false;//根据请求的Policy设置屏幕的状态switch (mPowerRequest.policy) {case DisplayPowerRequest.POLICY_OFF:state = Display.STATE_OFF;performScreenOffTransition = true;break;case DisplayPowerRequest.POLICY_DOZE:if (mPowerRequest.dozeScreenState != Display.STATE_UNKNOWN) {state = mPowerRequest.dozeScreenState;} else {state = Display.STATE_DOZE;}if (!mAllowAutoBrightnessWhileDozingConfig) {brightness = mPowerRequest.dozeScreenBrightness;brightnessSecondDisplay = mPowerRequest.dozeScreenBrightness;}break;case DisplayPowerRequest.POLICY_VR:state = Display.STATE_VR;break;case DisplayPowerRequest.POLICY_DIM:case DisplayPowerRequest.POLICY_BRIGHT:default:state = Display.STATE_ON;break;}assert(state != Display.STATE_UNKNOWN);// Apply the proximity sensor.//proximity sensor距离传感器,与打电话有关,后续分析.if (mProximitySensor != null) {if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {setProximitySensorEnabled(true);if (!mScreenOffBecauseOfProximity&& mProximity == PROXIMITY_POSITIVE) {mScreenOffBecauseOfProximity = true;sendOnProximityPositiveWithWakelock();}} else if (mWaitingForNegativeProximity&& mScreenOffBecauseOfProximity&& mProximity == PROXIMITY_POSITIVE&& state != Display.STATE_OFF) {setProximitySensorEnabled(true);} else {setProximitySensorEnabled(false);mWaitingForNegativeProximity = false;}if (mScreenOffBecauseOfProximity&& mProximity != PROXIMITY_POSITIVE) {mScreenOffBecauseOfProximity = false;sendOnProximityNegativeWithWakelock();}} else {mWaitingForNegativeProximity = false;}if (mScreenOffBecauseOfProximity) {state = Display.STATE_OFF;}// Animate the screen state change unless already animating.// The transition may be deferred, so after this point we will use the// actual state instead of the desired one.//获取屏幕状态,此时还未设置新的屏幕状态,因此是”旧”的final int oldState = mPowerState.getScreenState();//在这个方法中会进行屏幕状态、亮度的设置和处理亮灭屏动画animateScreenStateChange(state, performScreenOffTransition);state = mPowerState.getScreenState();// Use zero brightness when screen is off.//根据状态设置是否灭屏,如果是状态是灭屏状态,设置亮度值为0if (state == Display.STATE_OFF) {brightness = PowerManager.BRIGHTNESS_OFF;brightnessSecondDisplay = PowerManager.BRIGHTNESS_OFF;}// Configure auto-brightness.//配置自动亮度调节boolean autoBrightnessEnabled = false;boolean autoBrightnessEnabledSecondDisplay = false;if (automaticBrightnessController != null) {final boolean autoBrightnessEnabledInDoze = mAllowAutoBrightnessWhileDozingConfig&& (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND);autoBrightnessEnabled = mPowerRequest.useAutoBrightness&& (state == Display.STATE_ON || autoBrightnessEnabledInDoze)&& brightness < 0;/*if (mZMQ != null) {autoBrightnessEnabled |= mZMQ.checkBrightnessAutomodeEnabled(DEFAULT_DISPLAY);}*///是否手动调节了亮度,自动开关打开情况下final boolean userInitiatedChange = autoBrightnessAdjustmentChanged&& mPowerRequest.brightnessSetByUser;//配置自动亮度调节功能,后续分析        automaticBrightnessController.configure(autoBrightnessEnabled,mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON,userInitiatedChange);}//副屏幕的自动背光配置if (automaticBrightnessControllerSecondDisplay != null) {final boolean autoBrightnessEnabledInDoze = mAllowAutoBrightnessWhileDozingConfig&& (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND);autoBrightnessEnabledSecondDisplay = mPowerRequest.useAutoBrightnessSecondDisplay&& (state == Display.STATE_ON || autoBrightnessEnabledInDoze)&& brightnessSecondDisplay < 0;/*if (mZMQ != null) {autoBrightnessEnabled |= mZMQ.checkBrightnessAutomodeEnabled(DEFAULT_DISPLAY);}*/final boolean userInitiatedChangeSecondDisplay = autoBrightnessAdjustmentSecondChanged&& mPowerRequest.brightnessSetByUserSecondDisplay;automaticBrightnessControllerSecondDisplay.configure(autoBrightnessEnabledSecondDisplay,mPowerRequest.screenAutoBrightnessAdjustmentSecondDisplay, state != Display.STATE_ON,userInitiatedChangeSecondDisplay);}//仪表屏幕的自动背光配置if (automaticIPCBrightnessController != null) {final boolean autoBrightnessEnabledInDoze = mAllowAutoBrightnessWhileDozingConfig&& (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND);autoBrightnessEnabled = mPowerRequest.useAutoBrightness&& (state == Display.STATE_ON || autoBrightnessEnabledInDoze);final boolean userInitiatedChange = autoBrightnessAdjustmentChanged&& mPowerRequest.brightnessSetByUser;automaticIPCBrightnessController.configure(autoBrightnessEnabled,mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON,userInitiatedChange);}// Apply brightness boost.// We do this here after configuring auto-brightness so that we don't// disable the light sensor during this temporary state.  That way when// boost ends we will be able to resume normal auto-brightness behavior// without any delay.//亮度增强相关(中控),设置亮度增强,if (mPowerRequest.boostScreenBrightness&& brightness != PowerManager.BRIGHTNESS_OFF) {brightness = PowerManager.BRIGHTNESS_ON;}//亮度增强相关(副屏),设置亮度增强,if (mPowerRequest.boostScreenBrightness&& brightnessSecondDisplay != PowerManager.BRIGHTNESS_OFF) {brightnessSecondDisplay = PowerManager.BRIGHTNESS_ON;}// Apply auto-brightness.//自动调节,如果是自动亮度设置缓慢亮度变化boolean slowChange = false;//设置自动亮度(因为上三屏亮度要保持一致,所以自动背光的亮度发生变化,这都会用仪表的亮度,规定用仪表的亮度曲线)if (brightnessIpc < 0) {if (autoCCPIPCBrightnessEnabled && !autoBrightnessAdjustmentChanged ) {brightnessIpc = automaticIPCBrightnessController.getAutomaticScreenBrightness();}if (brightnessIpc >= 0) {// Use current auto-brightness value and slowly adjust to changes.brightnessIpc = clampScreenBrightness(brightnessIpc);if (autoBrightnessEnabled && !autoBrightnessAdjustmentChanged){brightness = brightnessIpc;putScreenBrightnessSetting(brightness);}if (autoBrightnessEnabledSecondDisplay && !autoBrightnessAdjustmentSecondChanged){brightnessSecondDisplay = brightnessIpc;putSecondScreenBrightnessSetting(brightnessSecondDisplay);}if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {slowChange = true; // slowly adapt to auto-brightness}mAppliedAutoBrightness = true;mAppliedAutoBrightnessSecondDisplay = true;mIPCAppliedAutoBrightness = true;} else {mAppliedAutoBrightness = false;mAppliedAutoBrightnessSecondDisplay = false;mIPCAppliedAutoBrightness = false;}} else {mAppliedAutoBrightness = false;mAppliedAutoBrightnessSecondDisplay = false;mIPCAppliedAutoBrightness = false;}//空调屏幕的亮度调节变化if (brightnessCcp < 0) {if (autoCCPIPCBrightnessEnabled) {//当环境光变化,获取自动调节的亮度(后续讲自动亮度调节的逻辑)brightnessCcp = automaticCCPBrightnessController.getAutomaticScreenBrightness();}if (brightnessCcp >= 0) {// Use current auto-brightness value and slowly adjust to changes.brightnessCcp = clampScreenBrightness(brightnessCcp);if (mCCPAppliedAutoBrightness) {slowChange = true; // slowly adapt to auto-brightness}mCCPAppliedAutoBrightness = true;} else {mCCPAppliedAutoBrightness = false;}} else {mCCPAppliedAutoBrightness = false;}// Use default brightness when dozing unless overridden.//Doze状态下配置Doze状态的亮度(中控)if (brightness < 0 && (state == Display.STATE_DOZE|| state == Display.STATE_DOZE_SUSPEND)) {brightness = mScreenBrightnessDozeConfig;}//Doze状态下配置Doze状态的亮度(副屏幕)if (brightnessSecondDisplay < 0 && (state == Display.STATE_DOZE|| state == Display.STATE_DOZE_SUSPEND)) {brightnessSecondDisplay = mScreenBrightnessDozeConfig;}// Apply manual brightness.// Use the current brightness setting from the request, which is expected// provide a nominal default value for the case where auto-brightness// is not ready yet.//自动背光关闭情况下,手动调节亮度值设置(中控)if (brightness < 0) {brightness = clampScreenBrightness(mPowerRequest.screenBrightness);}//自动背光关闭情况下,手动调节亮度值设置(副屏)if (brightnessSecondDisplay < 0) {brightnessSecondDisplay = clampScreenBrightness(mPowerRequest.screenBrightnessSecondDisplay);}//自动背光关闭情况下,手动调节亮度值设置(仪表)if (brightnessIpc < 0){brightnessIpc = clampAbsoluteBrightness(mPowerRequest.screenBrightnessIpc);}//自动背光关闭情况下,手动调节亮度值设置(空调)if (brightnessCcp < 0){brightnessCcp = clampAbsoluteBrightness(mPowerRequest.screenBrightnessCcp);}Slog.d(TAG," brightness: "+brightness+" brightnessSecondDisplay: "+brightnessSecondDisplay+" brightnessIpc: "+brightnessIpc+" brightnessCcp: "+brightnessCcp);// Apply dimming by at least some minimum amount when user activity// timeout is about to expire.//设置暗屏的亮度if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {if (brightness > mScreenBrightnessRangeMinimum) {brightness = Math.max(Math.min(brightness - SCREEN_DIM_MINIMUM_REDUCTION,mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);}if (brightnessSecondDisplay > mScreenBrightnessRangeMinimum) {brightnessSecondDisplay = Math.max(Math.min(brightnessSecondDisplay - SCREEN_DIM_MINIMUM_REDUCTION,mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);}if (!mAppliedDimming) {slowChange = false;}mAppliedDimming = true;} else if (mAppliedDimming) {slowChange = false;mAppliedDimming = false;}//如果当前是低电量模式,设置低电量模式的亮度// If low power mode is enabled, scale brightness by screenLowPowerBrightnessFactor// as long as it is above the minimum threshold.if (mPowerRequest.lowPowerMode) {if (brightness > mScreenBrightnessRangeMinimum) {final float brightnessFactor =Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);final int lowPowerBrightness = (int) (brightness * brightnessFactor);brightness = Math.max(lowPowerBrightness, mScreenBrightnessRangeMinimum);}if (brightnessSecondDisplay > mScreenBrightnessRangeMinimum) {final float brightnessFactorSecondDisplay =Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);final int lowPowerBrightness = (int) (brightnessSecondDisplay * brightnessFactorSecondDisplay);brightnessSecondDisplay = Math.max(lowPowerBrightness, mScreenBrightnessRangeMinimum);}if (!mAppliedLowPower) {slowChange = false;}mAppliedLowPower = true;} else if (mAppliedLowPower) {slowChange = false;mAppliedLowPower = false;}//背光调节时候,设置调节的动画,看起来比较丝滑// Animate the screen brightness when the screen is on or dozing.// Skip the animation when the screen is off or suspended or transition to/from VR.if (!mPendingScreenOff) {if (mSkipScreenOnBrightnessRamp) {if (state == Display.STATE_ON) {if (mSkipRampState == RAMP_STATE_SKIP_NONE && mDozing) {mInitialAutoBrightness = brightness;mInitialAutoBrightnessSecondDisplay = brightnessSecondDisplay;mSkipRampState = RAMP_STATE_SKIP_INITIAL;} else if (mSkipRampState == RAMP_STATE_SKIP_INITIAL&& mUseSoftwareAutoBrightnessConfig&& (brightness != mInitialAutoBrightness|| brightnessSecondDisplay != mInitialAutoBrightnessSecondDisplay)) {mSkipRampState = RAMP_STATE_SKIP_AUTOBRIGHT;} else if (mSkipRampState == RAMP_STATE_SKIP_AUTOBRIGHT) {mSkipRampState = RAMP_STATE_SKIP_NONE;}} else {mSkipRampState = RAMP_STATE_SKIP_NONE;}}boolean wasOrWillBeInVr = (state == Display.STATE_VR || oldState == Display.STATE_VR);int brightnessIPCCCP = (((brightnessCcp&0xff)<<8)|(brightnessIpc&0xff));int chjbrightness = (((brightnessSecondDisplay&0xff)<<8)|(brightness&0xff));if ((state == Display.STATE_ON&& mSkipRampState == RAMP_STATE_SKIP_NONE|| state == Display.STATE_DOZE && !mBrightnessBucketsInDozeConfig)&& !wasOrWillBeInVr) {// 更新仪表和空调的亮度updateIPCCCPBrightnessState(brightnessIPCCCP,slowChange);//进入动画调节,更新中控和副屏的亮度animateScreenBrightness(chjbrightness, slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);} else {animateScreenBrightness(chjbrightness, 0);}}//后续逻辑和亮灭屏相关以后分析// Determine whether the display is ready for use in the newly requested state.// Note that we do not wait for the brightness ramp animation to complete before// reporting the display is ready because we only need to ensure the screen is in the// right power state even as it continues to converge on the desired brightness.final boolean ready = mPendingScreenOnUnblocker == null &&(!mColorFadeEnabled ||(!mColorFadeOnAnimator.isStarted() && !mColorFadeOffAnimator.isStarted()))&& mPowerState.waitUntilClean(mCleanListener);final boolean finished = ready&& !mScreenBrightnessRampAnimator.isAnimating();// Notify policy about screen turned on.if (ready && state != Display.STATE_OFF&& mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_ON) {setReportedScreenState(REPORTED_TO_POLICY_SCREEN_ON);mWindowManagerPolicy.screenTurnedOn();}// Grab a wake lock if we have unfinished business.if (!finished && !mUnfinishedBusiness) {if (DEBUG) {Slog.d(TAG, "Unfinished business...");}mCallbacks.acquireSuspendBlocker();mUnfinishedBusiness = true;}// Notify the power manager when ready.if (ready && mustNotify) {// Send state change.synchronized (mLock) {if (!mPendingRequestChangedLocked) {mDisplayReadyLocked = true;if (DEBUG) {Slog.d(TAG, "Display ready!");}}}sendOnStateChangedWithWakelock();}// Release the wake lock when we have no unfinished business.if (finished && mUnfinishedBusiness) {if (DEBUG) {Slog.d(TAG, "Finished business...");}mUnfinishedBusiness = false;mCallbacks.releaseSuspendBlocker();}// Record if dozing for future comparison.mDozing = state != Display.STATE_ON;}

这里简单做一个小结

  • 1.当要请求进入Doze状态时,如果配置了Doze下LightSensor不可用,则将亮度设置为dozeScreenBrightness,(针对中控和副屏)
  • 2.当要灭屏时候,设置灭屏亮度背光为0(针对中控和副屏)
  • 3.当设置亮度增强的功能时候,设置亮度值255(针对中控和副屏)
  • 4.以上3个条件都不满足,且开启了自动亮度调节功能,则获取自动调节的亮度(中控,副屏,仪表使用同一自动亮度,空调单独使用亮度)
  • 5.以上4个条件都不满足,且当前为Doze状态,则将亮度值设置为mScreenBrightnessDozeConfig;(针对中控和副屏)
  • 6.如果不满足以上5步,则使用手动调节的亮度,这些亮度值从PowerManagerService中获取(四屏幕使用同一亮度值)
  • 7.如果要请求进入DIM状态时,则需要将当前得到的亮度值-10,并和mScreenBrightnessDimConfig比较取最小,和mScreenBrightnessRangeMinimum比较取最大。(针对中控和副屏)
  • 8.如果当前处于低电量模式,则需要将当前得到的亮度值* 低电量模式下亮度缩放比例,然后和mScreenBrightnessRangeMinimum取最大(一般缩放值为0.5,即减半);(针对中控和副屏)

针对中控和副屏幕的亮度调节

animateScreenBrightness()

    private void animateScreenBrightness(int target, int rate) {if (DEBUG) {Slog.d(TAG, "Animating brightness: target=" + target  + ", rate=" + rate);}//target代表最终亮度,rate代表调节动画时调节的速率if (mScreenBrightnessRampAnimator.chjanimateTo(target, rate)) {/*if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {*/Trace.traceCounter(Trace.TRACE_TAG_POWER, "TargetScreenBrightness", target);try {mBatteryStats.noteScreenBrightness(target);} catch (RemoteException ex) {// same process}}}

在这个方法中,第一个参数是updatePowerState()中获得的最终亮度值,第二个参数则和亮度设置时的动画效果有关系,
如果设置为大于0的数,那么会在chjanimateTo()方法中根据这个数逐渐地设置亮度,如果设置为小于等于0,那么则不会有动画效果,直接将亮度值一次性设置。接下来
,说说亮度值设置时的动画相关的逻辑。

RampAnimator.chjanimateTo()

继续跟着上一段分析,mScreenBrightnessRampAnimator是一个RampAnimator对象,RampAnimator类是一个自定义动画类,
专门用于更新亮度,其原理是该类中有一个IntProperty对象作为该类的一个属性:

    public boolean chjanimateTo(int target, int rate) {// Immediately jump to the target the first time.//如果rate<=0,则直接通过mProperty.setValue(mObject, target)设置为目标亮度if (mFirstTime || rate <= 0) {if (mFirstTime || target != mCurrentValue) {mFirstTime = false;mRate = 0;mTargetValue = target;mCurrentValue = target;//rate<=0时直接设置mProperty.setValue(mObject, target);if (mAnimating) {mAnimating = false;cancelAnimationCallback();}if (mListener != null) {mListener.onAnimationEnd();}return true;}return false;}if (!mAnimating|| rate > mRate|| (target <= mCurrentValue && mCurrentValue <= mTargetValue)|| (mTargetValue <= mCurrentValue && mCurrentValue <= target)) {mRate = rate;}final boolean changed = (mTargetValue != target);mTargetValue = target;// Start animating.if (!mAnimating && target != mCurrentValue) {mAnimating = true;mAnimatedValue = mCurrentValue;mAnimatedValueDefaultDisplay = (mCurrentValue&0xff);mAnimatedValueSecondDisplay = ((mCurrentValue>>8)&0xff);mLastFrameTimeNanos = System.nanoTime();postAnimationCallback();}return changed;}

1.如果rate<=0,那么直接调用mProperty.setValue(object,target)设置最终的亮度;如果rate>0,
那么会进入postAnimationCallback()方法,在这个方法中通过rate计算出每次设置的亮度值进行设置,直到设置到最终亮度为止。

2.mProperty.setValue(mObject, target);设置亮度值 ,那这个setValue调用的哪个类的方法呢?
我们先看mScreenBrightnessRampAnimator对象的创建

mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
mScreenBrightnessRampAnimator.setListener(mRampAnimatorListener);

因此当执行mProperty.setValue(object,target)时,执行的是DisplayPowerState.SCREEN_BRIGHTNESS的setValue()方法,
进入DisplayPowerState中查看该对象:

public static final IntProperty<DisplayPowerState> SCREEN_BRIGHTNESS =new IntProperty<DisplayPowerState>("screenBrightness") {@Overridepublic void setValue(DisplayPowerState object, int value) {//设置亮度object.setScreenBrightness(value);}@Overridepublic Integer get(DisplayPowerState object) {return object.getScreenBrightness();}
};

在这里可以看出,当调用setValue()方法后,将调用object.setScreenBrightness(),
从实例化流程可知,object对象还是DisplayPowerState对象。继续setScreenBrightness()方法:


public void setScreenBrightness(int brightness) {if (mScreenBrightness != brightness) {mScreenBrightness = brightness;//对于屏幕状态为State_OFF,根据上面内容的分析,在设置屏幕状态之间就会设置将背光设置为0,此处不进行处理if (mScreenState != Display.STATE_OFF) {mScreenReady = false;scheduleScreenUpdate();}}
}

在这个方法中,如果当前屏幕状态不为STATE_OFF,即当前不是处于灭屏状态,则开始调用scheduleScreenUpdate()更新背光

private void scheduleScreenUpdate() {if (!mScreenUpdatePending) {mScreenUpdatePending = true;postScreenUpdateThreadSafe();}
}

postScreenUpdateThreadSafe方法

private void postScreenUpdateThreadSafe() {mHandler.removeCallbacks(mScreenUpdateRunnable);mHandler.post(mScreenUpdateRunnable);
}

通过mHandler异步调用mScreenUpdateRunnable,mScreenUpdateRunnable是一个Runnable实现
具体方法如下

private final Runnable mScreenUpdateRunnable = new Runnable() {@Overridepublic void run() {//表示是否打算更新屏幕状态,该值在scheduleScreenUpdate()方法中设置为了truemScreenUpdatePending = false;//获取背光亮度值,如果屏幕状态为State_Off的话就是0,其他屏幕状态下都是设置的背光值int brightness = mScreenState != Display.STATE_OFF&& mColorFadeLevel > 0f ? mScreenBrightness : 0;//如果该方法返回false,表示屏幕更新完成,否则表示还没有更新完成if (mPhotonicModulator.setState(mScreenState, brightness)) {if (DEBUG) {Slog.d(TAG, "Screen ready");}mScreenReady = true;//标记屏幕状态是否更新完成invokeCleanListenerIfNeeded();} else {if (DEBUG) {Slog.d(TAG, "Screen not ready");}}}
};
  • 1.先获取背光的亮度值
  • 2.调用mPhotonicModulator的setState去更新亮度值和屏幕状态
  • 3.根据setState方法的返回值来决定是否是屏幕状态更新完成

PhotonicModulator是一个Thread的子类,专门用于更新屏幕和背光亮度值的状态,因此,在DisplayPowerState中,更新屏幕和背光状态是在独立的线程中异步进行的。
现在,先来看看这个线程的setState()方法:

public boolean setState(int state, int backlight) {synchronized (mLock) {//屏幕状态是否改变,和之前的值做比较boolean stateChanged = state != mPendingState;//背光是否改变boolean backlightChanged = backlight != mPendingBacklight;//如果有其中之一改变,进入if中if (stateChanged || backlightChanged) {if (DEBUG) {Slog.d(TAG, "Requesting new screen state: state="+ Display.stateToString(state) + ", backlight=" + backlight);}//设置state值mPendingState = state;//设置将要更新的亮度值mPendingBacklight = backlight;//mStateChangeInProgress和mBacklightChangeInProgress分别表示当前屏幕状态和背光值//正在更新的过程中,changeInProgress表示其中之一是否正在更新的过程中boolean changeInProgress = mStateChangeInProgress || mBacklightChangeInProgress;mStateChangeInProgress = stateChanged || mStateChangeInProgress;mBacklightChangeInProgress = backlightChanged || mBacklightChangeInProgress;//如果为false,则唤醒mPhotonicModulator线程,执行它的run()方法if (!changeInProgress) {mLock.notifyAll();//很关键的一个方法}}//如果该值为true,说明此时正在进行屏幕状态的改变,没有准备好。因此返回falsereturn !mStateChangeInProgress;}
}

其中对mLock.notifyAll()这个逻辑再进行下分析,为何当changeInProgress为false的时候需要mLock.notifyAll()呢?
这是因为该线程启动后就是一个死循环,可以无线执行,但在死循环中进行了mLock.wait()操作,这里看看它的run()方法,如下:


@Override
public void run() {for (;;) {// Get pending change.final int state;final boolean stateChanged;final int backlight;final boolean backlightChanged;synchronized (mLock) {//通过全局变量给局部变量赋值state = mPendingState;//mActualState表示目前实际的状态值stateChanged = (state != mActualState);backlight = mPendingBacklight;//mActualBacklight表示目前实际的亮度值backlightChanged = (backlight != mActualBacklight);//stateChange为false表示此时屏幕状态已应用为需要设置的值了(已应用),则再次执行一遍//postScreenUpdateThreadSafe()方法,这次执行时,PhotonicMudulator.setScreen()将返回//true,表示屏幕更新完成if (!stateChanged) {// State changed applied, notify outer class.postScreenUpdateThreadSafe();mStateChangeInProgress = false;//表示更新屏幕已完成}//说明背光值也已经应用if (!backlightChanged) {//置为false,表示更新背光已完成,没有正在进行的改变操作mBacklightChangeInProgress = false;}//如果屏幕状态和背光值都应用完成,则让该线程进入等待状态if (!stateChanged && !backlightChanged) {try {mLock.wait();} catch (InterruptedException ex) { }continue;}//设置实际状态值和背光值mActualState = state;mActualBacklight = backlight;}// Apply pending change.if (DEBUG) {Slog.d(TAG, "Updating screen state: state="+ Display.stateToString(state) + ", backlight=" + backlight);}//调用DisplayBlanker中去请求DisplaymBlanker.requestDisplayState(state, backlight);}
}

DisplayBlanker.requestPowerState()

DisplayBlanker是一个接口,它专门用来更新实际的屏幕显示状态以及亮度.在DisplayPowerController中,
DisplayBlanker由DisplayManagerService在实例化DisplayPowerController时作为参数传入,
DisplayPowerController中在实例化DisplayPowerState时又通过构造函数传给了DisplayPowerState,
因此,DisplayBlanker的实现还是在DMS中,我们进入DMS中看DisplayBlanker对象:

public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,SensorManager sensorManager) {synchronized (mSyncRoot) {DisplayBlanker blanker = new DisplayBlanker() {@Overridepublic void requestDisplayState(int state, int brightness) {// The order of operations is important for legacy reasons.//对于灭屏和非灭屏状态,调用callback的顺序不同if (state == Display.STATE_OFF) {requestGlobalDisplayStateInternal(state, brightness);}//PMS中调用native层方法callbacks.onDisplayStateChange(state);if (state != Display.STATE_OFF) {requestGlobalDisplayStateInternal(state, brightness);更新状态和亮度值}}};mDisplayPowerController = new DisplayPowerController(mContext, callbacks, handler, sensorManager, blanker);}
}

1.从代码中可以得知当状态亮屏时候,调用requestGlobalDisplayStateInternal更新亮度值
2.从以上逻辑来看先更新状态,后更新亮度(亮屏设置时)

private void requestGlobalDisplayStateInternal(int state, int brightness) {int brightnessdefaultdisplay = (brightness&0xff); //中控亮度值int brightnessseconddisplay = ((brightness>>8)&0xff); //副屏亮度值if (state == Display.STATE_UNKNOWN) {state = Display.STATE_ON;}根据状态设置亮度值,亮度调节时,state为Display.STATE_ONif (state == Display.STATE_OFF) {brightnessdefaultdisplay = PowerManager.BRIGHTNESS_OFF;} else if (brightnessdefaultdisplay < 0) {brightnessdefaultdisplay = PowerManager.BRIGHTNESS_DEFAULT;} else if (brightnessdefaultdisplay > PowerManager.BRIGHTNESS_ON) {brightnessdefaultdisplay = PowerManager.BRIGHTNESS_ON;}if (state == Display.STATE_OFF) {brightnessseconddisplay = PowerManager.BRIGHTNESS_OFF;} else if (brightnessseconddisplay < 0) {brightnessseconddisplay = PowerManager.BRIGHTNESS_DEFAULT;} else if (brightnessseconddisplay > PowerManager.BRIGHTNESS_ON) {brightnessseconddisplay = PowerManager.BRIGHTNESS_ON;}synchronized (mTempDisplayStateWorkQueue) {try {// Update the display state within the lock.// Note that we do not need to schedule traversals here although it// may happen as a side-effect of displays changing state.synchronized (mSyncRoot) {if (mGlobalDisplayState == state&& mGlobalDisplayBrightness == brightnessdefaultdisplay&& mGlobalDisplayBrightnessSecondDisplay == brightnessseconddisplay) {return; // no change}Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState("+ Display.stateToString(state)+ ", brightness=" + brightness + ")");Slog.d(TAG, "requestGlobalDisplayStateInternal mGlobalDisplayState = " + mGlobalDisplayState + " mGlobalDisplayBrightness" + mGlobalDisplayBrightness + " mGlobalDisplayBrightnessSecondDisplay" + mGlobalDisplayBrightnessSecondDisplay);//更新全局亮度值mGlobalDisplayState = state;mGlobalDisplayBrightness = brightnessdefaultdisplay;mGlobalDisplayBrightnessSecondDisplay = brightnessseconddisplay;//调节亮度applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);}// Setting the display power state can take hundreds of milliseconds// to complete so we defer the most expensive part of the work until// after we have exited the critical section to avoid blocking other// threads for a long time.for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) {mTempDisplayStateWorkQueue.get(i).run();}Trace.traceEnd(Trace.TRACE_TAG_POWER);} finally {mTempDisplayStateWorkQueue.clear();}}}

在这个方法中,设置了mGlobalDisplayState和mGlobalDisplayBrightness,这两个全局变量表示整体的显示状态和亮度,然后将这两值传给了下一个方法applyGlobalDisplayStateLocked(),继续分析该方法:

    private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {final int count = mDisplayDevices.size();for (int i = 0; i < count; i++) {DisplayDevice device = mDisplayDevices.get(i);Slog.i(TAG, "applyGlobalDisplayStateLocked UniqueId = " + device.getUniqueId());Runnable runnable = updateDisplayStateLocked(device);if (runnable != null) {workQueue.add(runnable);}}}

在这个方法中,首先会遍历mDisplayDevices,它是表示当前所有显示设备的集合,然后更新每一个显示设备.什么是显示设备呢?目前有5种DisplayDevice:

  • 1.LocalDisplayDevice:中控屏幕就是一个显示设备;
  • 2.WifiDisplayDevice:无线投射,通过wifi将屏幕投射到其他物理屏幕上如TV上.
  • 3.VirtualDisplayDevice:虚拟设备
  • 4.LocalDisplayDevice:副屏幕也是一个显示设备
  • 5.空调和仪表也是显示设备,不过空调和仪表的逻辑不在这里(后续会分享)
    调用updateDisplayStateLocked会对中控和副屏幕做不同的处理

DisplayManagerService.updateDisplayStateLocked

    private Runnable updateDisplayStateLocked(DisplayDevice device) {// Blank or unblank the display immediately to match the state requested// by the display power controller (if known).DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {if (device.getUniqueId().equals("local:1")) {Slog.i(TAG, "updateDisplayStateLocked UniqueId = " + device.getUniqueId() + " mGlobalDisplayStateSecondDisplay = " + mGlobalDisplayState);return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightnessSecondDisplay);}if (((device.getUniqueId().equals("local:0"))) || (device.getUniqueId().equals("local:3"))) {Slog.i(TAG, "updateDisplayStateLocked UniqueId = " + device.getUniqueId() + " mGlobalDisplayState = " + mGlobalDisplayState);return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness);}}return null;}

首先根据DisplayDevice对象的getDisplayDeviceInfoLocked()方法获取了DisplayDeviceInfo对象,
然后根据DisplayDeviceInfo的flag进行决策,调用下一个方法并返回。DisplayDeviceInfo用于描述显示的物理设备特征,如尺寸、分别率等。

  • local:1 代表副屏, local:0代表中控

DisplayDevice是一个抽象类,其方法的实现在LocalDisplayDevice类中,因此我们看requestDisplayStateLocked方法实现直接去LocalDisplayDevice类查找
具体方法实现如下

      @Overridepublic Runnable requestDisplayStateLocked(final int state, final int brightness) {// Assume that the brightness is off if the display is being turned off.assert state != Display.STATE_OFF || brightness == PowerManager.BRIGHTNESS_OFF;final boolean stateChanged = (mState != state);final boolean brightnessChanged = (mBrightness != brightness) && mBacklight != null;if (stateChanged || brightnessChanged) {final int displayId = mBuiltInDisplayId;final IBinder token = getDisplayTokenLocked();final int oldState = mState;if (stateChanged) {mState = state;updateDeviceInfoLocked();}if (brightnessChanged) {mBrightness = brightness;}// Defer actually setting the display state until after we have exited// the critical section since it can take hundreds of milliseconds// to complete.//返回该Runnable对象return new Runnable() {@Overridepublic void run() {// Exit a suspended state before making any changes.int currentState = oldState;if (Display.isSuspendedState(oldState)|| oldState == Display.STATE_UNKNOWN) {if (!Display.isSuspendedState(state)) {setDisplayState(state);currentState = state;} else if (state == Display.STATE_DOZE_SUSPEND|| oldState == Display.STATE_DOZE_SUSPEND) {setDisplayState(Display.STATE_DOZE);currentState = Display.STATE_DOZE;} else {return; // old state and new state is off}}// If the state change was from or to VR, then we need to tell the light// so that it can apply appropriate VR brightness settings. Also, update the// brightness so the state is propogated to light.boolean vrModeChange = false;if ((state == Display.STATE_VR || currentState == Display.STATE_VR) &&currentState != state) {setVrMode(state == Display.STATE_VR);vrModeChange = true;}// Apply brightness changes given that we are in a non-suspended state.if (brightnessChanged || vrModeChange) {setDisplayBrightness(brightness);}// Enter the final desired state, possibly suspended.if (state != currentState) {setDisplayState(state);}}private void setDisplayState(int state) {try {final int mode = getPowerModeForState(state);SurfaceControl.setDisplayPowerMode(token, mode);Trace.traceCounter(Trace.TRACE_TAG_POWER, "DisplayPowerMode", mode);} finally {Trace.traceEnd(Trace.TRACE_TAG_POWER);}}private void setDisplayBrightness(int brightness) {try {//设置中控屏幕的亮度if (mBuiltInDisplayId == DEFAULT_DISPLAY)mBacklight.setBrightness(brightness, true);//设置副屏的亮度if (mBuiltInDisplayId == SECOND_DISPLAY)mBacklight.setBrightness(brightness, false);Trace.traceCounter(Trace.TRACE_TAG_POWER,"ScreenBrightness", brightness);} finally {Trace.traceEnd(Trace.TRACE_TAG_POWER);}}};}return null;}

最终交给LightService去处理亮度的调节。后面我就不做分析了。下面整理亮度调节的时序图

Display 亮度调节相关推荐

  1. ESP8266呼吸灯亮度调节并且实时显示PWM数值

    以下代码实现了ESP8266的网页控制板载LED灯的亮度调节,并且将GPIO_2的PWM数值显示在网页上. 网页显示代码来自: 太极创客http://www.taichi-maker.com/home ...

  2. Android 9.0 亮度调节的变化(伽马曲线)

    平台  RK3399 + Android 9.0 概述  众所周知, Android 平台的上层亮度值的设置值范围为[0, 255], 在9.0之前, 亮度调节一直是线性变化, 在9.0开始, 它变成 ...

  3. 修改注册表关闭 Vari-Bright,无需安装 Radeon 显卡控制台,禁用“屏幕自适应亮度调节”

    情景描述:它会在屏幕颜色浅的时候调亮屏幕,在颜色深的时候调暗屏幕,这样看电影什么的碰到暗的画面它还调暗,结果整个屏幕就变成了一坨浆糊,亮的时候又亮的刺眼.这到底是什么逻辑啊...?而且这个功能不受wi ...

  4. PWM调光方法在LED亮度调节中的应用

    LED 是一种固态电光源, 是一种半导体照明器件,其电学特性具有很强的离散性.它具有体积小.机械强度大.功耗低.寿命长, 便于调节控制及无污染等特征,有极大发展前景的新型光源产品.LED 调光方法的实 ...

  5. UC浏览器屏幕亮度在哪设置 UC浏览器屏幕亮度调节方法2019

    UC浏览器是可以调节屏幕亮度的,大家可以根据自己白天和晚上的浏览习惯去设置,下面,我们来看看UC浏览器屏幕亮度调节方法,希望能够帮助到大家. UC浏览器屏幕亮度在哪设置 打开手机,在手机桌面找到UC浏 ...

  6. [03] Android系统亮度调节

    链接:http://developer.android.com/reference/android/provider/Settings.System.html 最近在做的项目,需要使用亮度调节实现夜间 ...

  7. Ubuntu 13.04开机亮度调节

    终于把我的T430换成Ubuntu,本来还打算等几天13.10,想想反正能升级,趁着101长假就抓紧换了吧~` 总体来说遇到的问题不是很多,可能是Thinkpad在Linux或者ubuntu的方面做的 ...

  8. win11亮度调节不见了怎么办 windows亮度调节不见了的解决方法

    不少小伙伴在升级到Win11系统之后发现电脑的亮度调节选项不见了,出现这个问题的原因是因为注册表被修改了,那么要如何解决呢?下面就和小编一起来看看有什么解决的方法吧.更多windows11系统教程可以 ...

  9. java手机太亮,Android 亮度调节

    最近在做一个App的设置项,亮度调节.真正做时,发现Android亮度调节比预想要复杂一些.其实目前网上已有不少这方面的资料,但有些博文具有一定误导性.在此将这块内容按照自己理解整理一下. 整体上看, ...

  10. 笔记本电脑亮度调节按钮不起作用

    问题:在使用电脑过程中,发现屏幕亮度调节按钮失灵,但是音量以及其他按钮都可以使用? 原因分析:设备管理器--监视器  被禁用了   是比较常见的一种原因 解决方案:进入设备管理器--将监视器启动即可 ...

最新文章

  1. Excel表格快速将公式运用到一整列
  2. 【模型训练】SGD的那些变种,真的比SGD强吗
  3. python生成xml文件工具_Python根据指定文件生成XML的方法
  4. Python打包分发工具setuptools简介
  5. java通过poi读取excel中的日期类型数据或自定义类型日期
  6. vue 动态显示三级路由
  7. miui12怎么自定义开机动画_MIUI12正式发布:视觉/功能大升级
  8. mysql 主命令总结
  9. Python+Django+Hadmin的初级使用
  10. 摄像头各参数的意义_详解:摄像头参数介绍说明
  11. Linux上的Redis客户端软件G-dis3
  12. Vue.js快速原型开发问题汇总
  13. 爆料!爆料!亚马逊跨境电商店铺骗局被骗真相曝光!不要在上当了!
  14. linux搭建http代理服务器
  15. 自适应情侣纪念日记录网站源码
  16. “云上贵州”成全国首个国密算法应用试点项目 阿里政务云实现“国家级”安全保护...
  17. java mail 签名_java mail实现Email的发送,完整代码
  18. ESXI6.0 windows虚拟机 硬盘扩容实例...
  19. WIFI 国家码和信道划分
  20. 多个域名对应一个ip的解决办法

热门文章

  1. mars2d解决底图上下拖动超出边界出现灰色底
  2. 如何进行容器镜像加速?| 深度揭示阿里云 Serverless Kubernetes(3)
  3. linux命令行 jdb,什么使用加多宝(jdb)在linux下调试Java程序
  4. python入门指南阅读答案_第二章 _【Python入门指南】免费在线阅读 - 九六城堡小说论坛...
  5. linux格式化sd卡,并进行挂载
  6. html 的scor属性,html – 什么是css scroll-behavior属性?
  7. 【定制项目】【M13】【数据监控 + 数据分析 + 可视化大屏】- 关键技术 python flask + pandas + echarts + excel
  8. AtCoder Beginner Contest 224题解 A-G
  9. NEO(小蚁)Seraph ID调研
  10. 解决win10邮箱无法登陆163企业邮箱的问题