一、一般设置

1、手动设置背光API

// 修改当前Activity界面的窗口亮度
private void setScreenLight(int brightness) {WindowManager.LayoutParams lp = getWindow().getAttributes();lp.screenBrightness = Float.valueOf(brightness) * (1f / 255f);getWindow().setAttributes(lp);
}// 修改系统的亮度值
public void setScreenLight(int brightness) {Uri uri = Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);ContentResolver contentResolver = getContentResolver();Settings.System.putInt(contentResolver, Settings.System.SCREEN_BRIGHTNESS, brightness);contentResolver.notifyChange(uri, null);
}

2、设置系统背光默认亮度值

#frameworks/base/core/res/res/values/config.xml<integer name="config_screenBrightnessSettingMinimum">2</integer>
<integer name="config_screenBrightnessDim">2</integer>

系统背光节点路径:/sys/class/leds/lcd-backlight/brightness

3、自动背光配置设置

自动背光涉及光感值与亮度值对应,需要根据项目进行设置光感和背光值数组,一一对应

# frameworks/base/core/res/res/values/config.xml<integer-array name="config_autoBrightnessLevels">
... 填写亮度值数组 ...
</integer-array><integer-array name="config_autoBrightnessLcdBacklightValues">
... 填写光感值数组 ...
</integer-array>

二、流程分析

系统手动设置,待机休眠等都是通过 PowerManagerService.java 统一管理,自动背光则是由 AutomaticBrightnessController.java 管理。最后统一调用 DisplayPowerController.java 进行处理。

 1、frameworks/base/services/core/java/com/android/server/display/AutomaticBrightnessController.java  主要相关操作:

通过监听L-sersor 值变化发送 handleLightSensorEvent  走到  updateAutoBrightness 函数,最终调用到 DisplayPowerController.java updateBrightness函数。

// 内部创建一个光感监听
private final SensorEventListener mLightSensorListener = new SensorEventListener() {@Overridepublic void onSensorChanged(SensorEvent event) {if (mLightSensorEnabled) {final long time = SystemClock.uptimeMillis();final float lux = event.values[0];handleLightSensorEvent(time, lux);}}@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {// Not used.}
};// 通知update背光
private void updateAutoBrightness(boolean sendUpdate) {if (!mAmbientLuxValid) {return;}// 根据光感值计算对应背光值float value = mScreenAutoBrightnessSpline.interpolate(mAmbientLux);float gamma = 1.0f;if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT&& mScreenAutoBrightnessAdjustment != 0.0f) {final float adjGamma = MathUtils.pow(mScreenAutoBrightnessAdjustmentMaxGamma,Math.min(1.0f, Math.max(-1.0f, -mScreenAutoBrightnessAdjustment)));gamma *= adjGamma;if (DEBUG) {Slog.d(TAG, "updateAutoBrightness: adjGamma=" + adjGamma);}}if (gamma != 1.0f) {final float in = value;value = MathUtils.pow(value, gamma);if (DEBUG) {Slog.d(TAG, "updateAutoBrightness: gamma=" + gamma+ ", in=" + in + ", out=" + value);}}int newScreenAutoBrightness =clampScreenBrightness(Math.round(value * PowerManager.BRIGHTNESS_ON));if (mScreenAutoBrightness != newScreenAutoBrightness) {if (DEBUG) {Slog.d(TAG, "updateAutoBrightness: mScreenAutoBrightness="+ mScreenAutoBrightness + ", newScreenAutoBrightness="+ newScreenAutoBrightness);}mScreenAutoBrightness = newScreenAutoBrightness;mLastScreenAutoBrightnessGamma = gamma;if (sendUpdate) {// 通知mCallbacks背光改变,mCallbacks 即是 DisplayPowerController 类对象mCallbacks.updateBrightness();}}
}// mCallbacks中调用获取当前的自动背光值,后续进行设置
public int getAutomaticScreenBrightness() {if (!mAmbientLuxValid) {return -1;}if (mDisplayPolicy == DisplayPowerRequest.POLICY_DOZE) {return (int) (mScreenAutoBrightness * mDozeScaleFactor);}return mScreenAutoBrightness;
}

2、frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java 主要操作:

上层背光相关操作最终都是走到 PowerManagerService ,统一处理,这里只看设置 SCREEN_BRIGHTNESS 值的流程。通过 SettingsObserver 监听值变化,最终调用到 DisplayPowerController.java requestPowerState 函数。

// 系统启动时进行初始化操作
public void systemReady(IAppOpsService appOps) {... ...// 绑定监听resolver.registerContentObserver(Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS),false, mSettingsObserver, UserHandle.USER_ALL);resolver.registerContentObserver(Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE),false, mSettingsObserver, UserHandle.USER_ALL);... ...
}// 监听变化发送 handleSettingsChangedLocked
private final class SettingsObserver extends ContentObserver {public SettingsObserver(Handler handler) {super(handler);}@Overridepublic void onChange(boolean selfChange, Uri uri) {synchronized (mLock) {handleSettingsChangedLocked();}}
}//handleSettingsChangedLocked -> updatePowerStateLocked -> updateDisplayPowerStateLocked
/***异步更新显示电源状态。 更新完成后,mDisplayReady将设置为true。 显示控制器会发布一条消息,告诉 *我们实际的显示电源状态何时已更新,因此我们回到这里进行仔细检查并完成。*每次该功能都会重新计算显示功率状态。*@return如果显示准备就绪,则为True。
*/
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();... ...// 修改更新 mDisplayPowerRequest 亮度值等属性mDisplayPowerRequest.screenBrightnessOverride = screenBrightnessOverride;mDisplayPowerRequest.useAutoBrightness = autoBrightness;mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();mDisplayPowerRequest.boostScreenBrightness = shouldBoostScreenBrightness();updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);... ...        // 最终调用 DisplayPowerController 处理mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,mRequestWaitForNegativeProximity);... ...}return mDisplayReady && !oldDisplayReady;
}

3、frameworks/base/services/core/java/com/android/server/display/DisplayPowerController.java 主要相关方法分析

通过  Settings.System.SCREEN_BRIGHTNESS 手动设置值,是从调用 requestPowerState 开始,最终调用 sendUpdatePowerStateLocked,如下

// 通过设置settings值手动更新亮度调用
public boolean requestPowerState(DisplayPowerRequest request,boolean waitForNegativeProximity) {if (DEBUG) {Slog.d(TAG, "requestPowerState: "+ request + ", waitForNegativeProximity=" + waitForNegativeProximity);}synchronized (mLock) {boolean changed = false;mRequestPowerStateChangedByUser = false;if (waitForNegativeProximity&& !mPendingWaitForNegativeProximityLocked) {mPendingWaitForNegativeProximityLocked = true;changed = true;}if (mPendingRequestLocked == null) {mPendingRequestLocked = new DisplayPowerRequest(request);changed = true;} else if (!mPendingRequestLocked.equals(request)) {// 这里不同是手动设置的调用mPendingRequestLocked.copyFrom(request);changed = true;mRequestPowerStateChangedByUser = true;}if (changed) {mDisplayReadyLocked = false;}if (changed && !mPendingRequestChangedLocked) {mPendingRequestChangedLocked = true;// 通知更新亮度sendUpdatePowerStateLocked();}return mDisplayReadyLocked;}
}

自动背光调节的流程调用是从 updateBrightness() 开始,最终也是调用 sendUpdatePowerStateLocked,如下

@Override
public void updateBrightness() {sendUpdatePowerState();
}private void sendUpdatePowerState() {synchronized (mLock) {sendUpdatePowerStateLocked();}
}

sendUpdatePowerStateLocked  这个函数就是手动、自动亮度调节最终统一的地方。它里面只是简单的通过handler 发送调用 updatePowerState();updatePowerState() 里面才是真正进行操作的地方。

private void updatePowerState() {// Update the power state request.... ...// P-Sensor的靠近操作if (mProximitySensor != null) {... ...} else {mWaitingForNegativeProximity = false;}if (mScreenOffBecauseOfProximity) {state = Display.STATE_OFF;}// 配置自动亮度值boolean slowChange = false;if (brightness < 0) {if (autoBrightnessEnabled) {// 这里就是获取 AutomaticBrightnessController 保存的自动亮度值brightness = mAutomaticBrightnessController.getAutomaticScreenBrightness();}if (brightness >= 0) {// 这里就是保证 brightness 在系统最小最大设置值 10 ~ 255 之间// 具体看 frameworks/base/core/res/res/values/config.xml 中 config_screenBrightnessSettingMinimum config_screenBrightnessSettingMaximum 值brightness = clampScreenBrightness(brightness);if (mAppliedAutoBrightness && !autoBrightnessAdjustmentChanged) {slowChange = true; // slowly adapt to auto-brightness}mAppliedAutoBrightness = true;} else {mAppliedAutoBrightness = false;}} else {mAppliedAutoBrightness = false;}// Use default brightness when dozing unless overridden.if (brightness < 0 && (state == Display.STATE_DOZE|| state == Display.STATE_DOZE_SUSPEND)) {brightness = mScreenBrightnessDozeConfig;}// 这里是我自己添加判断,过滤重复设置亮度// 保存自动亮度值 mRequestPowerStateAutoBrightness。// 如果 mRequestPowerStateChangedByUser 手动操作为false,且mRequestPowerStateAutoBrightness也没有变化,就直接returnif (mRequestPowerStateAutoBrightness != brightness) {mRequestPowerStateAutoBrightness = brightness;} else if (!mRequestPowerStateChangedByUser) {Slog.d(TAG, "Brightness no changed");return;}// 这里使用手动亮度值Slog.d(TAG, "Apply manual brightness " + brightness + " " + mRequestPowerStateAutoBrightness);if (brightness < 0 || mRequestPowerStateChangedByUser) {int clampBrightness = clampScreenBrightness(mPowerRequest.screenBrightness);if (brightness == clampBrightness) {Slog.d(TAG, "RequestPowerStateChangedByUser Brightness no changed");return;}brightness = clampBrightness;}// 这里就是系统自动休眠前,先变暗一会if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {if (brightness > mScreenBrightnessRangeMinimum) {brightness = Math.max(Math.min(brightness - SCREEN_DIM_MINIMUM_REDUCTION,mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);}if (!mAppliedDimming) {slowChange = false;}mAppliedDimming = true;} else if (mAppliedDimming) {slowChange = false;mAppliedDimming = false;}... ...// 判断屏幕是否是offif (!mPendingScreenOff) {... ...// 通过判断确定背光响应变化速度// mBrightnessRampRateSlow 原生是60,是1s调整60亮度// mBrightnessRampRateFast 原生是180,是1s调整180亮度boolean wasOrWillBeInVr = (state == Display.STATE_VR || oldState == Display.STATE_VR);if (!mRequestPowerStateChangedByUser && (state == Display.STATE_ON&& mSkipRampState == RAMP_STATE_SKIP_NONE|| state == Display.STATE_DOZE && !mBrightnessBucketsInDozeConfig)&& !wasOrWillBeInVr) {// 一般自动亮度变化是会渐变调整的animateScreenBrightness(brightness,slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);} else {// 手动一般是立即变化的,无需动画渐变调整的animateScreenBrightness(brightness, 0);}Slog.d(TAG, "putInt brightness " + brightness);}... ...}

animateScreenBrightness 内部逻辑是在 frameworks/base/services/core/java/com/android/server/display/RampAnimator.java 中 animateTo 处理。

animateTo 中调用 postAnimationCallback ,在 mAnimationCallback 中一直设置值渐变。

private void postAnimationCallback() {mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
}private void cancelAnimationCallback() {mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
}private final Runnable mAnimationCallback = new Runnable() {@Override // Choreographer callbackpublic void run() {final long frameTimeNanos = mChoreographer.getFrameTimeNanos();final float timeDelta = (frameTimeNanos - mLastFrameTimeNanos)* 0.000000001f;mLastFrameTimeNanos = frameTimeNanos;// Advance the animated value towards the target at the specified rate// and clamp to the target. This gives us the new current value but// we keep the animated value around to allow for fractional increments// towards the target.final float scale = ValueAnimator.getDurationScale();if (scale == 0) {// Animation off.mAnimatedValue = mTargetValue;} else {final float amount = timeDelta * mRate / scale;if (mTargetValue > mCurrentValue) {mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue);} else {mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue);}}final int oldCurrentValue = mCurrentValue;mCurrentValue = Math.round(mAnimatedValue);if (oldCurrentValue != mCurrentValue) {mProperty.setValue(mObject, mCurrentValue);}// mCurrentValue 当前值 // mTargetValue 目标值if (mTargetValue != mCurrentValue) {postAnimationCallback();} else {mAnimating = false;if (mListener != null) {// 通知变化完成mListener.onAnimationEnd();}}}
};

mProperty.setValue(mObject, mCurrentValue);

这个方法就是实际操作写入背光值的地方,往下就是通过 native 调用处理。到这里背光设置就完成了。

Android 系统背光设置相关推荐

  1. Android系统中设置TextView的行间距

    Android系统中TextView默认显示中文时会比较紧凑,不是很美观.为了让每行保持一定的行间距,可以设置属性android:lineSpacingExtra或android:lineSpacin ...

  2. android 系统 优化设置,优化设置 让你的Android手机快人一步

    经过几轮"军备竞赛",如今Android设备的性能几乎年年翻番.但是,哪怕很多Android手机配备了顶级的八核处理器和4GB内存,为何操作流畅度还是不如iOS,甚至不如以前用过的 ...

  3. Android系统中设置TextView等的行间距

    1.android:lineSpacingExtra 设置行间距,如"2dp". 2.android:lineSpacingMultiplier 设置行间距的倍数,如"2 ...

  4. android系统密码设置功能,手机怎样设置密码锁屏【详细介绍】

    大家应该知道吧!现在的手机都是智能款式,在众多功能具备的情况之下,它的防盗功能也是很不错的,每一款智能手机在都可以设置开锁密码,这样的话手机的安全性就会比较高了,特别是这几年手机又加入了全新的技术,那 ...

  5. android系统密码设置功能,手机锁屏密码怎么设置 三种安卓手机锁屏方式推荐

    手机中有很多应用都是与金钱挂钩,特别是微信与支付宝等等既涉及到隐私又与财产关联,这是后手机的安全就尤为重要的,而手机的锁屏密码就是一道最基本的防护措施,那么手机锁屏密码怎么设置?来看看小编推荐的三种安 ...

  6. android 系统 dpi设置,安卓系统DPI的划分

    荣耀X1,安卓4.4升级版本改了DPI值,从原来的320DPI改成了Android 4.4中最新的400Dpi. 安卓7.0/7.1:没有260/300/340dpi 1.以前的划分,按照倍率换算 l ...

  7. Android系统语言默认设置为简体中文

       Android系统默认的语言是英语,但是对于中国大陆Android产品厂商来说,不会出厂之后语言还是英语,到用户手里之后,用户自己设置成简体中文吧?有如果客户不懂英语,岂不是就不能设置系统语言了 ...

  8. Android编译默认英语,Android系统语言出厂编译设置为简体中文

    Android系统默认的语言是英语,但是对于中国大陆Android产品厂商来说,不会出厂之后语言还是英语,到用户手里之后,用户自己设置成简体中文吧?有如果客户不懂英语,岂不是就不能设置系统语言了?所以 ...

  9. Android 系统(269)---native保活5.0以上方案推演过程以及代码详述

    Android 进程常驻(4)----native保活5.0以上方案推演过程以及代码详述 这是一个轻量级的库,配置几行代码,就可以实现在android上实现进程常驻,也就是在系统强杀下,以及360获取 ...

最新文章

  1. word2vec 中的数学原理详解
  2. mysql数据库表的基本操作
  3. error: ‘__declspec‘ attributes are not enabled; use ‘-fdeclspec‘ or ‘-fms-extensions‘ to enabl
  4. 中石油训练赛 - 小A进学校(唯一分解定理)
  5. 全国高等学校计算机等级考试(江西考区)一级笔试试卷a,全国高等学校计算机等级考试(江西考区)一级笔试试卷A...
  6. Android:源码环境编译自定义的APP到ROM(System Image)中
  7. php 安装 bzip2,php如何安装bzip2
  8. [Asp.net]Uploadify上传大文件,Http error 500 解决方案
  9. 默认地址路径修改_修改Docker默认路径
  10. 20172311 2017-2018-2 《程序设计与数据结构》实验一报告
  11. 无法连接 Plugins Market 失效的日子
  12. python session过期_python session过期timeout处理
  13. Oracle 执行计划篇
  14. 华为快应用 阻止事件冒泡
  15. Operations-ansible-01
  16. FPGA:vivado2018.1编程界面字体大小与颜色修改
  17. 史上最全的边缘计算应用场景
  18. RAxML下载与使用与ML建树原理
  19. 如何把数据分析做“精准”?
  20. MySQL练习记录——利用Python的pymysql模块操作MySQL数据库

热门文章

  1. PLSQL developer下载、安装、详细教程
  2. SLAM学习资源免费分享-转载
  3. playcanvas 引擎
  4. js获取时间戳,将时间戳转换为年月日时分秒
  5. 修改USB默认选中MTP模式
  6. 在C#使用XML注释
  7. JSON格式转MAP的6种方法
  8. Quick Power
  9. 简单又漂亮的思维导图怎么画?脑图创作分享
  10. Arcpy基础入门-4、arcpy工具进阶