当前位置:   article > 正文

[bug_fix][framework_base] RuntimeException: Failed to set system property——关于SystemProperty设置失败的问题_java.lang.runtimeexception: failed to set system p

java.lang.runtimeexception: failed to set system property

目录

前景提要

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

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

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

拓展


  • 前景提要

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

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

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

  1. public void setXXXXEnable(boolean enable) {
  2. ……
  3. // 新增语句
  4. SystemProperties.set("persist.company.xxxxxx.xxxx.enable", enable? "1" : "0");
  5. }
  6. public boolean getXXXXEnable() {
  7. ……
  8. // 新增语句
  9. return SystemProperties.getInt("persist.company.xxxxxx.xxxx.enable", 1) == 1;
  10. }
  11. // 后续还有多个类似修改

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

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

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

  1. 12-10 16:18:35.948 E/AndroidRuntime( 3193): FATAL EXCEPTION: main
  2. 12-10 16:18:35.948 E/AndroidRuntime( 3193): Process: xxxxx, PID: 3193
  3. 12-10 16:18:35.948 E/AndroidRuntime( 3193): java.lang.RuntimeException: failed to set system property
  4. 12-10 16:18:35.948 E/AndroidRuntime( 3193): at android.os.SystemProperties.native_set(Native Method)
  5. 12-10 16:18:35.948 E/AndroidRuntime( 3193): at android.os.SystemProperties.set(SystemProperties.java:130)
  6. 12-10 16:18:35.948 E/AndroidRuntime( 3193): at // 指向协议栈接口实现
  7. 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:

  1. getprop | grep persist.company
  2. [persist.company.xxxxxx]: [true]
  3. [persist.company.xxxxxxxx]: [0]
  4. [persist.company.xxxxxxxxxx]: [0]
  5. [persist.company.xxxxxxxxxx]: [0]
  6. [persist.company.xxxx]: [1]
  7. [persist.company.xxxxxxx]: [1]

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

  1. xxxxxxx:/ # getenforce
  2. Permissive

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

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

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

  1. setprop persist.company.xxxxxx.xxxx.e --> 成功
  2. setprop persist.company.xxxxxx.xxxx.en --> 成功
  3. setprop persist.company.xxxxxx.xxxx.ena --> 成功
  4. setprop persist.company.xxxxxx.xxxx.enab --> 成功
  5. setprop persist.company.xxxxxx.xxxx.enabl --> 失败
  6. setprop persist.company.xxxxxx.xxxx.enable --> 失败

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

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

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

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

  1. // 当前查看源码版本:Android 8.0
  2. #define PROP_VALUE_MAX 92
  3. /* Deprecated. In Android O and above, there's no limit on property name length. */
  4. #define PROP_NAME_MAX 32

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

  1. - xxxxEnable = SystemProperties.getInt("persist.company.xxxxxx.xxxx.enable", 1) == 1;
  2. + xxxxEnable = SystemProperties.getInt("persist.company.xxxxxx.xxxx.on", 1) == 1;
  3. - SystemProperties.set("persist.company.xxxxxx.xxxx.enable", enable? "1" : "0");
  4. + SystemProperties.set("persist.company.xxxxxx.xxxx.on", enable? "1" : "0");

解决!

 

  • 拓展

查看一下源码:

android_os_SystemProperties.cpp

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/324254
推荐阅读
相关标签
  

闽ICP备14008679号