赞
踩
修改Android开机动画结束后到加载Launcher页面时android加载条出现亮度变化问题
一开始从上层入手,怀疑有app或者窗口对其进行了修改
//打印堆栈信息查看调用者
android.util.Log.i(TAG,"updateDisplayPowerStateLocked() ",new Throwable());
一般的亮度修改,要么是调用Window中的方法进行修改,要么是写入系统值中,所以第一阶段想到该方案
1.Window.setAttributes方法修改亮度
frameworks\base\core\java\android\view\Window.java
对该文件中setAttributes方法打印Log
public void setAttributes(WindowManager.LayoutParams a) {
mWindowAttributes.copyFrom(a);
dispatchWindowAttributesChanged(mWindowAttributes);
}
2.应用设置亮度时Settings.System.SCREEN_BRIGHTNESS值,所以决定在Settings中对属性值进行putInt时打印Log
\frameworks\base\core\java\android\provider
通过追加日志的方式来获取谁调用、设置了亮度
public static boolean putInt(ContentResolver cr, String name, int value) {
return putString(cr, name, Integer.toString(value));
}
但对于开机亮度值的改变,以上两处地方皆没有进行修改,所以得出结论与上层应用无关,将目光放置到framework层,怀疑为系统对其进行了修改,所以第二阶段在framework中追踪代码。
网上搜索了一下相关的问题,有查看到MTK背光问题处理,于是乎顺着文章定位到DisplayPowerController
frameworks\base\services\core\java\com\android\server\display\DisplayPowerController.java
其中的animateScreenBrightness()函数,作用是处理开机时亮度渐变,定位到调用该方法的函数updatePowerState()
private void updatePowerState() {
...
if (initialRampSkip || hasBrightnessBuckets
|| wasOrWillBeInVr || !isDisplayContentVisible || brightnessIsTemporary) {
animateScreenBrightness(brightness, 0);
} else {
animateScreenBrightness(brightness,
slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
}
}
根据网上方法将else中的animateScreenBrightness改成与if一致
然而得到的结果只是将亮度渐变时间变快,仍旧会有亮度的变化,只是时间快慢问题,没有找到根源
虽然对DisplayPowerController中的animateScreenBrightness进行修改后没有效果,但是通过对updatePowerState打印堆栈信息,最终定位到DisplayManagerService.java、PowerManagerService.java两个文件当中,当然,由于要找到根源,所以也涉及到了LightsService.java这个文件
核心函数
private boolean updateDisplayPowerStateLocked(int dirty) { ... if (!mBootCompleted) { // Keep the brightness steady during boot. This requires the // bootloader brightness and the default brightness to be identical. autoBrightness = false; screenBrightnessOverride = mScreenBrightnessSettingDefault; } else if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) { autoBrightness = false; screenBrightnessOverride = mScreenBrightnessOverrideFromWindowManager; } else { autoBrightness = (mScreenBrightnessModeSetting == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); screenBrightnessOverride = -1; } //Update display power request mDisplayPowerRequest.screenBrightnessOverride = screenBrightnessOverride; ... mDisplayRead = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,mRequestWaitForNegativeProximity);//调用DisplayManagerService }
在该文件中有一个重要的变量:mGlobalDisplayBrightness,顾名思义,全局亮度值
//定义
private int mGlobalDisplayBrightness = PowerManager.BRIGHTNESS_DEFAULT;
//第一次赋值
mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();
因为在第一次赋值时调用了pm进行赋值,所以传给下层的亮度值为系统默认值,而非用户设置值,从而导致开机加载完毕,加载桌面时出现亮度变化
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) {
//第一次传亮度值,采取默认值传递
return device.requestDisplayStateLocked(mGlobalDisplayState, mGlobalDisplayBrightness);
}
return null;
}
在开机时,添加设备阶段,就注册且绑定了LocalDisplayAdapter,在DisplayManagerService中对其进行引用,调用其requestDisplayStateLocked方法
@Override
public Runnable requestDisplayStateLocked(final int state, final int brightness) {
...
return new Runnable(){
...
private void setDisplayBrightness(int brightness) {
...
try{
mBacklight.setBrightness(brightness);
}
}
};
}
private final class LightImpl extends Light {
...
@Override
//为LocalDisplayAdapter所调用
public void setBrightness(int brightness) {
setBrightness(brightness,BRIGHTNESS_MODE_USER);
}
}
@Override
public void setBrightness(int brightness, int brightnessMode) {
synchronized(this) {
...
setLightLocked(color,LIGHT_FLASH_NONE,0,0,brightnessMode);
}
}
private void setLightsLocked(int color, int mode, int onMS, int offMS, int brightnessMode){
...
if (!mInitialized || color != mColor || mode != mMode || onMS != mOnMS || bambchanged || offMS != mOffMS || mBrightnessMode != brightnessMode){
...
try{
//该处是上层调用native函数,将值传给驱动层
setLight_native(mId,color,mode,onMS,offMS,brightnessMode);
}
}
}
原本是想在DisplayManagerService中对用户设置的亮度值进行获取再设置,但是在此java文件中添加System.getInt或者getIntForUser,刷机时都会报错,导致开不了机
所以想到两种方案
一是修改系统默认值,使得第一次开机亮度最大化
二是在修改完后写入到metazone中,在驱动层开机时进行读取
由于只想修改上层而不动驱动,所以采取了第一种方法,但是该方法仍存在问题
将SettingsProvider中的默认值进行修改,修改完之后,刷机验证,正常
通过日志知道,在没有更改任何条件的情况下,值会从255渐变到102,所以也就意味着一开始的值设定的就是40%,即102
<!-- Default screen brightness, from 0 to 255. 102 is 40%. -->
<integer name="def_screen_brightness">255</integer>
虽然修改了默认值,在开机的情况下已经不会在出现该亮度变化的问题,但是在测试时发现,如果将android亮度调节至最暗,再次开机会出现由最亮到最暗的动画过渡,其实这种现象是属于一方案代码修改后的正常变化范围
然而所要达到的效果是开机过程中不再有任何的亮度变化,所以就需要在开机第一时间将亮度设置为用户设置的值,在修改整个问题的过程中,其实一直在kernel层的接收亮度文件中进行修改,但通过追加日志发现,该处与framework层修改默认值的效果一致,即不能完全将整个开机过程的亮度进行囊括
后来查阅MTK资料,发现在arm2中已经进行了修改,也就是达到了开关背光一致性,即关机前设置的亮度,会在开机的那一刻就设置同等的亮度值,在整个开机过程中不会再有变化
发现是要通过写入metazone,供设备在开机时读取metazone来实现该功能
其实在没有深入arm2时,也考虑到是否可以通过写入metazone来确保开机时就保证亮度一致,但由于一直卡在kernel层,导致写入metazone也无法实现,因为通过串口日志以及adb对比,在kernel\drivers\misc\mediatek\leds\的leds.c文件中,亮度值的设定实际上就是开机动画完成后到加载Launcher前的一个亮度设置
所以综上,我调节的系统并没有实现开关背光一致性功能,后续也通过追踪代码,对arm2中display目录下的mt_led.c中代码进行比对,确实存在开机将亮度拉到最大值的函数设定,从而破坏了开关背光一致性功能
对c不是很熟悉,但是理清了一下思路:
1、在开机的时候,系统还未启动,所以系统服务中的一些设定是不管用的,要在开机的时候就读取到亮度值,只有写入到metazone中
2、顺着思路找到arm2开机文件设置亮度的地方,看看是否实现了读取保存的亮度值
通过以上两点找到对应的led文件,果然,去除掉了读取metazone部分,且值固定为最大值,即无论你关机前设置的亮度是多少,都会在开机的时候通通拉到最高
void mt65xx_backlight_on(void)
{
unsigned int First_SetBacklight = 1;
if(First_SetBacklight == 1) {
First_SetBacklight = 0;
mt65xx_leds_brightness_set(MT65XX_LED_TYPE_LCD, LED_FULL);
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。