Android 系统背光设置

news/2024/9/23 6:36:13/

一、一般设置

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 调用处理。到这里背光设置就完成了。

 

 

 

 

 

 

 


http://www.ppmy.cn/news/871313.html

相关文章

背光

关于液晶显示模块使用的背光源&#xff0c;有几种类型的产品&#xff1a;1、LED背光&#xff1b;2、EL背光&#xff1b;3、CCFL背光。LED背光&#xff0c;其具有 操作简单实用、使用奉命长&#xff0c;功耗低、亮度高等优点。 下面介绍一下LED背光源&#xff1a; 1、可选多种色…

手机背光显示

简介 移动设备如智能手机、电子阅读器和手表在当今世界正变得无处不在。这就需要准确的光学工程的来优化手机功能的性能&#xff0c;如相机系统、传感器和显示器。 手机显示的一个关键设计目标是在它的面积和视角范围内实现均匀的照明。另外&#xff0c;它应该具有高的光学效…

LCD背光,功耗,电池总结

问题&#xff1a;屏半亮&#xff0c;出现闪屏 解决方案&#xff1a;背光驱动中使用spin_lock_irqsave和spin_unlock_irqrestore防止多cpu竞争。 问题 如何让Android进入待机睡眠状态&#xff08;测试LCD电流&#xff09;&#xff1f; 在终端中用如下命令&#xff1a; echo …

2023-07-13 Fitz完成PDF转TXT

Fitz完成PDF转TXT 前言 1、本机为Inspiron 5005&#xff0c;为64位&#xff0c;所用操作系统为Windos 10。所使用开发环境为Anaconda和jupyter notebook。 2、本教程主要实现了安装Anaconda和jupyter notebook&#xff0c;使用Fitz完成PDF转TXT。 Anaconda和Jupyter notebook简…

Android应用开发(21)屏幕背光控制

Android应用开发学习笔记——目录索引 最近各手机厂商都在宣传万级调光&#xff0c;宣传数字越来越大&#xff0c;但是到底背光调节平滑度体验如何呢&#xff1f; 如最近realme 11 pro &#xff08;MTK平台天玑7050&#xff09;&#xff0c;宣传20000级自动亮度调节。 发布会截…

ui设计范畴有什么 优漫动游

ui设计包括很多类型的设计&#xff0c;主要包括&#xff1a;平面设计、网页设计、电子商务设计、APP界面设计等。下面是ui设计范畴有什么的内容&#xff0c;一起来看看。   ui设计范畴有什么   1.平面设计   我们通常理解的平面设计大多是线下的实体设计&#xff0…

【CAD二次开发】CAD常用版本 DwgVersion

CAD常用版本 DwgVersion.AC1014 // R14 DwgVersion.AC1015 // 2000 DwgVersion.AC1800 // 2004 DwgVersion.AC1021 // 2007 DwgVersion.AC1024 // 2010 DwgVersion.AC1027 // 2013 DwgVersion.AC1032 // 2018DwgVersion.AC1035 // 2021DwgVersion.Current//当前版本

25、并发的三大特性

并发的三大特性 一、原子性二、可见性三、有序性 一、原子性 原子性是指在一个操作中cpu不可以在中途暂停然后再调度&#xff0c;即不被中断操作&#xff0c;要不全部执行完成&#xff0c;要不都不执行。就好比转账&#xff0c;从账户A向账户B转1000元&#xff0c;那么必然包括…