@恢复出厂如何保留自定义属性值
最近有个指令切换型号功能,每次恢复出厂设置之后必在重启一次才可以生效
【方案】
bwrite是可执行文件(out\target\product\xxxx\system\xbin\bwrite),bwrite写persist.sys.xxx=yyy键值对到文件/cache/recovery/last_bird.prop和data/last_bird.prop,开机时将/cache/recovery/last_bird.prop载入内存,应用可通过 SystemProperties.getxxx 获取其中键值对;对于无法使用system property的地方,直接读取文件data/last_bird.prop 获得键值。(/cache/recovery/last_xxx文件恢复出厂设置不会被删除,但是一般应用没有权限读这个文件,所有有个data/last_bird.prop的备份)
开机load last_bird.prop:
system\core\init\property_service.cpp
load_properties_from_file("/cache/recovery/last_bird.prop", NULL); ----------这句话的作用是可以将cache/recovery/last_bird.prop中所有内容当作类似build.prop里当作属性值来获取
修改两个last_bird.prop文件权限
device/sprd/scx35l/sp9832a_5m_volte_bird/rootdir/root/init.sp9832a_5m_volte_bird.rc 添加
on early-boot
chmod 0644 /cache/recovery/last_bird.prop
chmod 0644 /data/last_bird.prop
最重要的是bwrite这个可执行文件----详细如下附件,通过这个创建,修改/cache/recovery/last_bird.prop和data/last_bird.prop
packages/apps/Settings/bwrite/bwrite.c
…
else if(argv[i][0] == ‘m’) {
memset(value, 0, sizeof(value));
for(k = 0, pspace = argv[i]; k < strlen(argv[i]); k++, pspace++) {
if(*pspace == ‘@’) *pspace = ’ ';
}
// sprintf(value, “ro.bird.model=%s\n persist.sys.bird.model=%s\n”, pvalue);
sprintf(value, “persist.sys.bird.model=%s\n”, pvalue);
strcat(writeContent, value);
}
…/data/upload/1/201905/0916573204631dl6.c
在device/sprd/scx35l/common/rootdir/root/init.sc8830_ieb.rc注册bwrite服务
service bwrite /system/xbin/bwrite
user root
group root
oneshot
声明bwrite权限:
device/sprd/scx35l/common/sepolicy/bwrite.te
type bwrite, domain;
type bwrite_exec, exec_type, file_type;
init_daemon_domain(bwrite)
net_domain(bwrite)
allow bwrite system_data_file:dir rw_dir_perms;
allow bwrite system_data_file:dir create_dir_perms;
allow bwrite system_data_file:file { write create open ioctl };
allow bwrite system_data_file:file rw_file_perms;
allow bwrite system_data_file:file create_file_perms;
allow bwrite last_bird_prop:file { read write create open getattr setattr };
allow bwrite self:capability { fsetid dac_override };
allow bwrite shell_exec:file {execute execute_no_trans read open };
allow bwrite system_file:file execute_no_trans;
allow bwrite cache_file:dir { write create add_name };
allow bwrite cache_file:file { write create open setattr };
绑定执行档类型:
device/sprd/scx35l/common/sepolicy/file_contexts
/system/xbin/bwrite u:object_r:bwrite_exec:s0
/cache/recovery/last_bird.prop u:object_r:cache_recovery_file:s0
声明last_bird_prop(bwrite.te里面用了)
device/sprd/scx35l/common/sepolicy/file.te
type last_bird_prop, file_type, data_file_type;
在recovery中给last_bird_prop赋予权限:
device/sprd/scx35l/common/sepolicy/recovery.te
allow recovery last_bird_prop:file {open read write getattr};
从neverallow中去掉bwrite:
external/sepolicy/domain.te
neverallow {
domain
-bwrite
} system_data_file:file no_w_file_perms;
在java 中是如何调用bwrite,以型号为例
在packages/apps/Settings/bird/src/com/bird/settings/BirdModelActivity.java
切换之后发送广播
Intent intent = new Intent(“bird.intent.receiver.model_new”);
intent.putExtra(“model”, model);
mContext.sendBroadcast(intent);
在frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java 中处理广播做如下操作
String command = “bwrite:bird_write_prop” + " " + BIRD_PROP_PATH + " " + param;
Log.i(TAG, “command:” + command);
SystemProperties.set(“ctl.start”, command); ---------启动bwrite服务修改persist.sys.bird.model的值
最终设置下型号和第三方获取型号是从frameworks/base/core/java/android/os/Build.java中获取
public static final String realMODEL = getString(“ro.product.model”);
public static String MODEL = SystemProperties.get(“persist.sys.bird.model”, realMODEL); -----------获取修改后的值
关键点:
1.是需要一个将属性值保存在恢复出厂不被删除的文件,我们这里是cache/recovery/last_bird.prop
2.可以get到属性值,如过get不到可读取data/last_bird.prop文件(这就有可能牵扯到恢复出厂刚开机还没来得及生成此文件,Bug就是由此引起,还有一种方按,写个shell脚本在init.rc中就加载拷贝,可参考网址:https://blog.csdn.net/yang_gaolei/article/details/78864429 ------init.rc 执行shell脚本 ---- 制作一初始化配置文件)
注意:调试过程中很容易遇到avc,等selinux权限相关
比如这行warning log:
avc: denied { write } for name=“last_bird.prop” dev=“mmcblk0p23” ino=23 scontext=u:r:bwrite:s0 tcontext=u:object_r:system_data_file:s0 tclass=file permissive=1
那么我们就得出最后的规则是在bwrite.te中添加:
allow bwrite system_data_file:file { write };
在手机关机或者开启过程中可短暂获取log的命令:adb shell dmesg >1.txt 查询内核缓冲区信息 -------可以看到一些init 的信息
指令切换型号–相机拍照详情型号未改变
原因读取的是ro.product.model 的值,目前两种方案:
1.找到bdA/qiku/vendor/sprd/modules/libcamera/oem2v0/src/cmr_setting.c
这个路径下的文件,修改下
//bird modify by zss
property_get(“persist.sys.bird.model”, property, EXIF_DEF_MODEL);
//property_get(“ro.product.model”, property, EXIF_DEF_MODEL);
int property_get(const char *key, char *value, const char *default_value)
{
int len;
// bird modify by zss begin
ALOGV(“old key=%s\n”,key );
char oldmodel[]= “ro.product.model”;
char newmodel[] = “persist.sys.bird.model”;
if(0 == strncmp(oldmodel,key,strlen(oldmodel))){
key = newmodel;
}
ALOGV(“new key=%s\n”,key );
//property_get(“ro.product.model”, property, EXIF_DEF_MODEL);
// bird modify by zss end
len = __system_property_get(key, value);
if(len > 0) {
return len;
}
if(default_value) {
len = strlen(default_value);
if (len >= PROPERTY_VALUE_MAX) {
len = PROPERTY_VALUE_MAX - 1;
}
memcpy(value, default_value, len);
value[len] = '\0';
}
return len;
}