[bug_fix][framework_base] RuntimeException: Failed to set system property——关于SystemProperty设置失败的问题

目录

前景提要

应用闪退:java.lang.RuntimeException: failed to set system property

万能百度:SeLinux机制,非系统应用&未注册前缀不可设置

发现端倪:android系统版本限制

拓展


  • 前景提要

今天在系统应用开发维护中遇到了一个很有意思的问题。

为了减少重复工作量,所有平台会共同依赖一个共用协议栈接口,对接系统各项定制功能实现。此为前景提要。

在内置应用进行迭代开发的时候,为了优化原有与其他模块/应用对接的方式,从原本读取contentProvider的方式改为了系统属性prop。因此在协议栈接口中做了兼容处理,如下:

public void setXXXXEnable(boolean enable) {
    ……
    // 新增语句
    SystemProperties.set("persist.company.xxxxxx.xxxx.enable", enable? "1" : "0");
}

public boolean getXXXXEnable() {
    ……
    // 新增语句
    return SystemProperties.getInt("persist.company.xxxxxx.xxxx.enable", 1) == 1;
}

// 后续还有多个类似修改

在完成了系统测试且上线后,在半年后的今天,出现了问题。

  • 应用闪退:java.lang.RuntimeException: failed to set system property

当收到这个问题之后,首先查看了下闪退的crash,如下:

12-10 16:18:35.948 E/AndroidRuntime( 3193): FATAL EXCEPTION: main
12-10 16:18:35.948 E/AndroidRuntime( 3193): Process: xxxxx, PID: 3193
12-10 16:18:35.948 E/AndroidRuntime( 3193): java.lang.RuntimeException: failed to set system property
12-10 16:18:35.948 E/AndroidRuntime( 3193): 	at android.os.SystemProperties.native_set(Native Method)
12-10 16:18:35.948 E/AndroidRuntime( 3193): 	at android.os.SystemProperties.set(SystemProperties.java:130)
12-10 16:18:35.948 E/AndroidRuntime( 3193): 	at // 指向协议栈接口实现
12-10 16:18:35.948 E/AndroidRuntime( 3193): 	……

当收到某个平台报出的这个问题之后,首先非常疑惑,这个实现已经上线了半年之久,为什么突然会在某个平台出现闪退的情况呢?于是问了下对应平台最近有没有什么特殊更新,回复最近才对协议栈接口逻辑大更新了一波。于是判定确实是新增的Systemprop实现导致的问题。

手动在adb试了一下setprop的命令,也打出了failed to set system property的提示。判定不是定制的逻辑问题,而是系统逻辑问题了。接下来开始查问题:

  • 万能百度:SeLinux机制,非系统应用&未注册前缀不可设置

遇到没见过的问题,首先百度下看看。发现大家都是一样的回答:

1.Selinux开启

2.设置property的必须是系统应用,即属于系统组:AndroidManifest下设置 android:sharedUserId="android.uid.system"

3.property_contexts 中有对应prop和权限组(对应2的uid应该要有是系统权限)的声明

※ 注:在源码中,property_contexts 对应的目录应该是 /system/sepolicy/private/property_contexts 、 /system/sepolicy/public/property_contexts (我查阅的是Android9.0源码)。而对应的rom定制系统,应该是在device下厂家自加入的property_contexts 文件。系统编译时会搜索到device下的property_contexts, 并以合并的方式追加到原有system下property_contexts 后。

对着上面的条件进行查验:应用是系统级应用,uid组是系统组,于是去查对应的property_contexts。在device目录下查找persist.company的声明,发现没有。不死心直接在根目录find -name property_contexts找到所有的property_contexts目录,均未发现persist.company的痕迹。在adb里查找了一下prop:

getprop | grep persist.company

[persist.company.xxxxxx]: [true]
[persist.company.xxxxxxxx]: [0]
[persist.company.xxxxxxxxxx]: [0]
[persist.company.xxxxxxxxxx]: [0]
[persist.company.xxxx]: [1]
[persist.company.xxxxxxx]: [1]

 发现均有结果。这里和判定的条件出现了冲突,貌似是selinux的限制并没有其效果。想起来我们的系统都是关闭了selinux的,adb 查看了一下系统状态:( Permissive —— 宽容模式,相当于关闭; enforce —— 强制模式,相当于打开)

xxxxxxx:/ # getenforce
Permissive

果然是关闭了,所以不是这个原因,万能百度探究失败。

  • 发现端倪:android系统版本限制

在上一步adb查看系统内所有属性的时候,发现应用内与这个设置失败的属性同时设置的其他属性出现了几个,开头同为persist.company.xxxxx。于是判断并不是应用设置实现方式出现的问题。这时候我闲着无事,把原来的 persist.company.xxxxxx.xxxx.enable 删掉了一部分,修改成了 persist.company.xxxxxx.xxxx。这时候发现adb设置成功了!所以判断是prop的名字出现了问题。于是逐渐递增尝试:

setprop persist.company.xxxxxx.xxxx.e              --> 成功
setprop persist.company.xxxxxx.xxxx.en             --> 成功
setprop persist.company.xxxxxx.xxxx.ena            --> 成功
setprop persist.company.xxxxxx.xxxx.enab           --> 成功
setprop persist.company.xxxxxx.xxxx.enabl          --> 失败
setprop persist.company.xxxxxx.xxxx.enable         --> 失败

等到失败的时候,数了下长度,prop的长度是33。至少现在已经有方向了,依旧靠万能百度查看一下。

然后确认在bionic/libc/include/sys/system_properties.h 中定义了和prop相关的属性:

// 当前查看源码版本:Android 5.1
#define PROP_NAME_MAX   32
#define PROP_VALUE_MAX  92

和试验的结果一样!于是换成了其他系统查看相同的文件配置:

// 当前查看源码版本:Android 8.0
#define PROP_VALUE_MAX  92

/* Deprecated. In Android O and above, there's no limit on property name length. */
#define PROP_NAME_MAX   32

结案! 源码中已经做了标识,在Android O(Android8.0)以下的系统,PROP_NAME长度限制成了32,而Android O及以上则没有这个限制。在进行迭代开发测试的时候,测试环境只有8.0及以上的系统,5.1作为一个尾单系统没有被兼顾到,因此出现了这个问题。因此,对协议栈中的实现进行了修改:

-    xxxxEnable = SystemProperties.getInt("persist.company.xxxxxx.xxxx.enable", 1) == 1;
+    xxxxEnable = SystemProperties.getInt("persist.company.xxxxxx.xxxx.on", 1) == 1;

-    SystemProperties.set("persist.company.xxxxxx.xxxx.enable", enable? "1" : "0");
+    SystemProperties.set("persist.company.xxxxxx.xxxx.on", enable? "1" : "0");

解决!

 

  • 拓展

查看一下源码:

android_os_SystemProperties.cpp

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值