Android4.2 Settings默认值的浅析
(ubootenv.var.has.accelerometer )
本文[原创],如要转载请注明出处。基于本人水平有限,如有不正确和不恰当之处欢迎拍砖指正!
前言:相信大家都会遇到Android系统中Settings默认值的更改问题,对于普通的网上文章很多,这里讲一种特殊的,即应用环境变量的方式记录的变量,以及分享一个菜鸟分析处理问题的过程。这里通过屏幕旋转参数accelerometer来说明。
相关文件和目录(每一家代码有所不同,如有发现不同请勿死磕!):
/device/xxx/gxxref/system.prop
/packages/apps/Settings/DisplaySettings.java
/packages/apps/Settings/Utils.java
/uboot/include/configs/customer/xx_mbx_v1.h
大家知道,通常Android系统中的Settings的默认值都在
/frameworks/base/packages/SettingsProvider/res/values/default.xml中,
不同个性化平台的在device的相应子目录下。例如:
/device/xxx/gxxref/overlay/frameworks/base/packages/SettingsProvider/res/values/default.xml中。
文件内容大概是这样的:
<resources>
...
<bool name="def_dim_screen">true</bool>
<integer name="def_screen_off_timeout">60000</integer>
<bool name="def_airplane_mode_on">false</bool>
<bool name="def_auto_time">true</bool>
<bool name="def_auto_time_zone">true</bool>
<bool name="def_accelerometer_rotation">true</bool>
....
</resources>
至此,很容易发现accelerometer这个相对应的默认值参数:def_accelerometer_rotation
在这里默认值是TRUE,这用在平板上没什么大问题,但在盒子和TV的软件上就很容易让普通客户产生困惑。因为安装了一些第三方程序,会让屏幕作90度旋转,这时电视看到的画面作了90度旋转,而电视我们不可能象MID那样旋转屏幕过来看。因此,我们在作电视和盒子的开发时,要将其默认值改过来。
<bool name="def_accelerometer_rotation">false</bool>
全编译,结果发现,实际上并未像我们想象中出现的状态。在Settings中显示也没变
Application request to change orientation
很显然,更改没正确。直接查看Settings中的Java代码:
/packages/apps/Settings/DisplaySettings.java
关键字定义:
private static final String KEY_REQUEST_ROTATE = "requestrotate";
private static final String KEY_ACCELEROMETER = "accelerometer";
很快我们发现实际代码中“accelerometer”没有使用,而使用的是
private static final String KEY_REQUEST_ROTATE = "requestrotate";
那会不会转屏这个默认值的变量也不是def_accelerometer_rotation呢?继续查KEY_REQUEST_ROTATE关键字:
mRequstRoateScreen = (CheckBoxPreference) findPreference(KEY_REQUEST_ROTATE);
mRequstRoateScreen.setOnPreferenceChangeListener(this)
...
@Override
public boolean onPreferenceChange(Preference pref, Object value) {
boolean check = "true".equals(value.toString());
String key = pref.getKey();
//Log.d(TAG, "onPreferenceChange() , key = " + key + ", value=" +value.toString());
if (KEY_REQUEST_ROTATE.equals(key)) {
// Log.d(TAG, "onPreferenceChange() ,KEY_REQUEST_ROTATE");
mRequstRoateScreen.setChecked(check);//SEE_MBX_V2
hwSetAccelerometer(value.toString());
...
}
发现:mRequstRoateScreen ,
CheckBoxPreference mRequstRoateScreen = null;
......
private void updateRequestRotationCheckbox() {
if (mRequstRoateScreen != null){
mRequstRoateScreen.setChecked(hwHasAccelerometer());
...
}
}
找到hwSetAccelerometer(string b)的定义,很显然,这时我们已经找到保存值这个rotation的变量名是:
Ubootenv.var.has.accelerometer,并找到与之对应读取的函数。
private boolean hwHasAccelerometer() {
return sw.getPropertyBoolean("ubootenv.var.has.accelerometer", true);
}
private void hwSetAccelerometer(String b) {
sw.setProperty("ubootenv.var.has.accelerometer", b);
}
注意这里的return sw.getPropertyBoolean("ubootenv.var.has.accelerometer", true);
这个true是不是就是默认值呢?将其改为false.编译代码,发现并没有改过来,而只是Settings中显示改变了,原来打的钩不见了。但实际安装旋转屏幕的软件测试,功能并没有更改过来。这是为什么呢?
查询代码ubootenv.var.has.accelerometer中并未有此的定义和初始值,只是这个变量在/device/xxx/gxxref/system.prop中有个定义。
于是将其定义后直接赋值实验。发现依然不行。再次重新检查代码。并未发现异样。能改的地方都改了。这时意外发现,通过鼠标操作了这个值之后,是有效的。那么说明,是这个变量没错。查看其定义头的说明:
######## UBOOTENV VARIBLES - r/w as system properties ##########
#
# Now we can load ubootenv varibles to system properties.
# We use a special prefix ("ubootenv.var" as default) to indicate that the 'property'
# actually is an ubootenv varible.
#
# A ubootenv 'property' will be initialized during system booting. And when user set
# a different value, it will be written back to ubootenv device immediately.
原来他是一个system properties变量。那么应该可以通过串口命令来读取其值查看:
$getprop ubootenv.var.has.acceleromete
$
什么也没有!鼠标操作改变状态。再读,发现值被改变了
$getprop ubootenv.var.has.acceleromete
$true
到此,我们可以说已经锁定了这个变量就是用来存屏幕旋转参数的变量。
但为什么上电未操作之前的值是什么也获取不到呢,查看代码也没找到相关赋值的地方。
于是我们应该怀疑这个值就根本没有被初始化。那么就在上电过程中加上初始化实验吧(方法有很多,这里就不一一缀述了,我这里是加到显示初始化脚本中:
setprop ubootenv.var.has.acceleromete false
OK,成功。但能这样简单的增加吗?不能,因为,这样后期不是不能更改吗?每一次上电都是false了。加上条件,获取值为空的时候,才给其赋值。于是更改如下:
if [ "$(getprop ubootenv.var.has.accelerometer)" = "" ] ; then
setprop ubootenv.var.has.accelerometer false
fi
到此,Finish!
**注:对于mRequstRoateScreen ,它是一个CheckBoxPreference, 其显示的默认状态通常可以在对应display_settings.xml中初始化中设置:
<CheckBoxPreference
android:key="requestrotate"
android:defaultValue="false”
android:title="@string/request_rotate_title"/>
疑问:(1)在函数
private boolean hwHasAccelerometer() {
return sw.getPropertyBoolean("ubootenv.var.has.accelerometer", false);
}
中,为什么将这个return值初始改为false了,只是checkBox的显示状态变了,而实际ubootenv变量初始值并没有改变?因为,如果是一个persist.sys.变量,他是会改变的状态的,而不是显示的状态。
(2)ubootenv.var.变量是一种特殊的system properties变量,他和普通的system properties变量有什么不同呢?
(3)/uboot/include/configs/customer/xx_mbx_v1.h这里面有一些环境变量初始值设置,比如显示cvbsmode.那么这个转屏变量在此能不能也可以在这里使用呢?待验证。