Android 11.0 动态修改SystemProperties中ro开头系统属性的值

这篇具有很好参考价值的文章主要介绍了Android 11.0 动态修改SystemProperties中ro开头系统属性的值。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

需求: 在11.0的产品开发中,对于定制功能的需求很多,有些机型要求可以修改系统属性值,对于系统本身在10.0以后为了系统安全性,不允许修改ro开头的SystemProperties的值,所以如果要求修改ro的相关系统属性,就得看在设置SystemProperties的相关值的要求,修改这部分要求就可以了

  1. 动态修改SystemProperties中ro开头系统属性的值的核心代码

  frameworks/base/core/java/android/os/SystemProperties.java
  /system/core/init/property_service.cpp

2.动态修改SystemProperties中ro开头系统属性的值的功能分析和实现功能

2.1 关于系统属性SystemProperty分析

系统属性,肯定对整个系统全局共享。通常程序的执行以进程为单位各自相互独立,如何实现全局共享呢?属性系统是android的一个重要特性。它作为一个服务运行,管理系统配置和状态。所有这些配置和状态都是属性。SystemProperties.java每个属性是一个键值对(key/value pair),其类型都是字符串

接下来看下SystemProperties.java相关方法

 
    private static native String native_get(String key);
    private static native String native_get(String key, String def);
    private static native int native_get_int(String key, int def);
    @UnsupportedAppUsage
    private static native long native_get_long(String key, long def);
    private static native boolean native_get_boolean(String key, boolean def);
    private static native void native_set(String key, String def);
 
    /**
     * Get the String value for the given {@code key}.
     *
     * @param key the key to lookup
     * @param def the default value in case the property is not set or empty
     * @return if the {@code key} isn't found, return {@code def} if it isn't null, or an empty
     * string otherwise
     * @hide
     */
    @NonNull
    @SystemApi
    @TestApi
    public static String get(@NonNull String key, @Nullable String def) {
        if (TRACK_KEY_ACCESS) onKeyAccess(key);
        return native_get(key, def);
    }
 
    /**
     * Get the value for the given {@code key}, and return as an integer.
     *
     * @param key the key to lookup
     * @param def a default value to return
     * @return the key parsed as an integer, or def if the key isn't found or
     *         cannot be parsed
     * @hide
     */
    @SystemApi
    public static int getInt(@NonNull String key, int def) {
        if (TRACK_KEY_ACCESS) onKeyAccess(key);
        return native_get_int(key, def);
    }
 
    /**
     * Get the value for the given {@code key}, and return as a long.
     *
     * @param key the key to lookup
     * @param def a default value to return
     * @return the key parsed as a long, or def if the key isn't found or
     *         cannot be parsed
     * @hide
     */
    @SystemApi
    public static long getLong(@NonNull String key, long def) {
        if (TRACK_KEY_ACCESS) onKeyAccess(key);
        return native_get_long(key, def);
    }
 
    @SystemApi
    @TestApi
    public static boolean getBoolean(@NonNull String key, boolean def) {
        if (TRACK_KEY_ACCESS) onKeyAccess(key);
        return native_get_boolean(key, def);
    }
 
    /**
     * Set the value for the given {@code key} to {@code val}.
     *
     * @throws IllegalArgumentException if the {@code val} exceeds 91 characters
     * @hide
     */
    @UnsupportedAppUsage
    public static void set(@NonNull String key, @Nullable String val) {
        if (val != null && !val.startsWith("ro.") && val.length() > PROP_VALUE_MAX) {
            throw new IllegalArgumentException("value of system property '" + key
                    + "' is longer than " + PROP_VALUE_MAX + " characters: " + val);
        }
        if (TRACK_KEY_ACCESS) onKeyAccess(key);
        native_set(key, val);
    }

通过上述get()和set()发现 最终是通过jni的方法设置相关的值

最终通过查阅资料发现是在property_service.cpp中来设置系统相关属性的 接下来看下property_service.cpp

设置属性的相关代码

     static uint32_t PropertySet(const std::string& name, const std::string& value, std::string* error) {
      size_t valuelen = value.size();
  
      if (!IsLegalPropertyName(name)) {
          *error = "Illegal property name";
          return PROP_ERROR_INVALID_NAME;
      }
  
      if (auto result = IsLegalPropertyValue(name, value); !result.ok()) {
          *error = result.error().message();
          return PROP_ERROR_INVALID_VALUE;
      }
  
      prop_info* pi = (prop_info*) __system_property_find(name.c_str());
      if (pi != nullptr) {
          // ro.* properties are actually "write-once".
         // 判断是否ro开头的属性 这只为读的属性 不能修改值
          if (StartsWith(name, "ro.")) {
              *error = "Read-only property was already set";
              return PROP_ERROR_READ_ONLY_PROPERTY;
          }
  
          __system_property_update(pi, value.c_str(), valuelen);
      } else {
          int rc = __system_property_add(name.c_str(), name.size(), value.c_str(), valuelen);
          if (rc < 0) {
              *error = "__system_property_add failed";
              return PROP_ERROR_SET_FAILED;
          }
      }
  
      // Don't write properties to disk until after we have read all default
      // properties to prevent them from being overwritten by default values.
      if (persistent_properties_loaded && StartsWith(name, "persist.")) {
          WritePersistentProperty(name, value);
      }
      // If init hasn't started its main loop, then it won't be handling property changed messages
      // anyway, so there's no need to try to send them.
      auto lock = std::lock_guard{accept_messages_lock};
      if (accept_messages) {
          PropertyChanged(name, value);
      }
      return PROP_SUCCESS;
  }
  // This returns one of the enum of PROP_SUCCESS or PROP_ERROR*.
  uint32_t HandlePropertySet(const std::string& name, const std::string& value,
                             const std::string& source_context, const ucred& cr,
                             SocketConnection* socket, std::string* error) {
      if (auto ret = CheckPermissions(name, value, source_context, cr, error); ret != PROP_SUCCESS) {
          return ret;
      }
  
      if (StartsWith(name, "ctl.")) {
          return SendControlMessage(name.c_str() + 4, value, cr.pid, socket, error);
      }
  
      // sys.powerctl is a special property that is used to make the device reboot.  We want to log
      // any process that sets this property to be able to accurately blame the cause of a shutdown.
      if (name == "sys.powerctl") {
          std::string cmdline_path = StringPrintf("proc/%d/cmdline", cr.pid);
          std::string process_cmdline;
          std::string process_log_string;
          if (ReadFileToString(cmdline_path, &process_cmdline)) {
              // Since cmdline is null deliminated, .c_str() conveniently gives us just the process
              // path.
              process_log_string = StringPrintf(" (%s)", process_cmdline.c_str());
          }
          LOG(INFO) << "Received sys.powerctl='" << value << "' from pid: " << cr.pid
                    << process_log_string;
          if (value == "reboot,userspace" && !is_userspace_reboot_supported().value_or(false)) {
              *error = "Userspace reboot is not supported by this device";
              return PROP_ERROR_INVALID_VALUE;
          }
      }
  
      // If a process other than init is writing a non-empty value, it means that process is
      // requesting that init performs a restorecon operation on the path specified by 'value'.
      // We use a thread to do this restorecon operation to prevent holding up init, as it may take
      // a long time to complete.
      if (name == kRestoreconProperty && cr.pid != 1 && !value.empty()) {
          static AsyncRestorecon async_restorecon;
          async_restorecon.TriggerRestorecon(value);
          return PROP_SUCCESS;
      }
  
      return PropertySet(name, value, error);
  }
 uint32_t InitPropertySet(const std::string& name, const std::string& value) {
      uint32_t result = 0;
      ucred cr = {.pid = 1, .uid = 0, .gid = 0};//获取cr参数
      std::string error;
      result = HandlePropertySet(name, value, kInitContext, cr, nullptr, &error);
      if (result != PROP_SUCCESS) {
          LOG(ERROR) << "Init cannot set '" << name << "' to '" << value << "': " << error;
      }
  
      return result;
  }

在进入property_service修改系统属性时,先调用InitPropertySet(const std::string& name, const std::string& value)

在通过HandlePropertySet(name, value, kInitContext, cr, nullptr, &error) 来获取返回值

在HandlePropertySet()中根据参数name的值分别调用相关的方法来设置值ro 开头的值 最终是由

PropertySet(name, value, error);来设置值时会判断ro开头的值 只读不让修改 所以要修改就去了这个限制

具体修改为:文章来源地址https://www.toymoban.com/news/detail-447188.html

      static uint32_t PropertySet(const std::string& name, const std::string& value, std::string* error) {
      size_t valuelen = value.size();
  
      if (!IsLegalPropertyName(name)) {
          *error = "Illegal property name";
          return PROP_ERROR_INVALID_NAME;
      }
  
      if (auto result = IsLegalPropertyValue(name, value); !result.ok()) {
          *error = result.error().message();
          return PROP_ERROR_INVALID_VALUE;
      }
  
      prop_info* pi = (prop_info*) __system_property_find(name.c_str());
      if (pi != nullptr) {
          // ro.* properties are actually "write-once".
         // 判断是否ro开头的属性 这只为读的属性 不能修改值
        // 修改开始 注释掉这部分代码
        /*  if (StartsWith(name, "ro.")) {
              *error = "Read-only property was already set";
              return PROP_ERROR_READ_ONLY_PROPERTY;
          }*/
 
     // 修改完毕
  
          __system_property_update(pi, value.c_str(), valuelen);
      } else {
          int rc = __system_property_add(name.c_str(), name.size(), value.c_str(), valuelen);
          if (rc < 0) {
              *error = "__system_property_add failed";
              return PROP_ERROR_SET_FAILED;
          }
      }
  
      // Don't write properties to disk until after we have read all default
      // properties to prevent them from being overwritten by default values.
      if (persistent_properties_loaded && StartsWith(name, "persist.")) {
          WritePersistentProperty(name, value);
      }
      // If init hasn't started its main loop, then it won't be handling property changed messages
      // anyway, so there's no need to try to send them.
      auto lock = std::lock_guard{accept_messages_lock};
      if (accept_messages) {
          PropertyChanged(name, value);
      }
      return PROP_SUCCESS;
  }

到了这里,关于Android 11.0 动态修改SystemProperties中ro开头系统属性的值的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android11.0系统中实现静默安装并启动App以及静默卸载

    本文描述Android11中通过修改系统PackageInstaller应用支持静默安装App,并启动安装的App。 PackageInstaller是系统中专门负责app安装的App,静默安装逻辑添加到此应用中,应用所在路径 /frameworks/base/packages/PackageInstaller/src/com/android/packageinstaller/ 添加SilenceInstallManager,路径为 /frameworks

    2024年02月03日
    浏览(68)
  • Android11.0 生成系统签名.jks文件并对Apk进行签名

    V2签名 对应用手动进行系统签名,需要platform.pk8,platform.x509.pem,signapk.jar这三个文件,应用的AndroidManifest.xml中需要添加 android:sharedUserId=“android.uid.system” ,然后输入以下命令就可得到签名后的apk文件: 如果你的应用 targetSdkVersion=30 ,在7.0以上的设备上安装不成功,会报以

    2024年02月07日
    浏览(55)
  • Android 11.0 系统限制上网系统之iptables用IOemNetd实现创建子链功能的实现

    在11.0的系统rom定制化开发中,对于限制系统上网功能中,需要在system中netd网络这块的产品开发中,会要求设置屏蔽ip地址之内的功能, liunx中iptables命令也是比较重要的,接下来就来在IOemNetd这块实现创建子链的相关功能 在android原生系统中,iptables是在网络过滤包模块非常重

    2024年02月13日
    浏览(95)
  • Android 11.0 系统限制上网系统之iptables用IOemNetd实现删除子链功能的实现

    在11.0的系统rom定制化开发中,对于限制系统上网功能中,在system中netd网络这块的产品开发中,会要求设置屏蔽ip地址之内的功能, liunx中iptables命令也是比较重要的,接下来就来在IOemNetd这块实现删除创建子链的相关功能 在android原生系统中,iptables是在网络过滤包模块非常重

    2024年02月16日
    浏览(49)
  • Android11.0 系统限制上网系统之iptables用IOemNetd实现app上网黑名单的实现

    在11.0的系统rom定制化开发中,对于系统限制网络的使用,在system中netd网络这块的产品需要中,会要求设置屏蔽某个app上网的功能, liunx中iptables命令也是比较重要的,接下来就来在IOemNetd这块实现app上网黑名单的的相关功能,就是在 系统中只能不允许某个app上网,就是除了这

    2024年02月15日
    浏览(50)
  • Android 11.0 系统限制上网系列之iptables用IOemNetd实现app某个时间段禁止上网的功能实现

    在11.0的系统rom定制化开发中,对于系统限制网络的使用,在system中netd网络这块的产品需要中,会要求设置app某个时间段禁止上网的功能, liunx中iptables命令也是比较重要的,接下来就来在IOemNetd这块实现app某个时间段禁止上网的的相关功能,就是在 系统中只能允许某个app某个

    2024年02月14日
    浏览(52)
  • Android11.0 导航栏添加图标截屏

    需求: 导航栏添加截屏和电源键图标,控制截屏和用于设备重启关机功能。设置中添加延时截屏和控制截屏图标显示开关。 1. 导航栏添加图标 1.1 添加布局文件和图标icon 在layout目录下添加nav_power.xml和screenshot.xml文件 frameworks/base/packages/SystemUI/res/layout/nav_power.xml frameworks/base

    2024年02月15日
    浏览(54)
  • Android 11.0 以太网设置默认静态ip地址

    在11.0的系统rom开发过程中,在进行以太网产品开发的过程中,有功能要求设置默认静态ip地址的功能,不使用动态ip, 方便ip地址管理所以就需要熟悉以太网的ip设置流程,然后设置对应的ip地址就可以了

    2024年02月16日
    浏览(52)
  • Android 11.0 SystemUI下拉状态栏禁止QuickQSPanel展开

       在11.0系统rom产品定制化开发中,对于SystemUI定制开发功能也有不少的,增加快捷功能模块,隐藏状态栏图标项目开发需要要求定制QSPanel相关UI和开发功能, 要求首次下拉后展示快捷功能模块以后就是显示QuickQSPanel而不展开QSPanel,接下来要从下滑手势下拉出状态栏分析功能

    2024年02月08日
    浏览(67)
  • Android 11.0 SystemUI 音量条UI定制的功能(一)

    目录 1.概述 2.SystemUI 音量条UI定制的功能(一)的核心类 3.SystemUI 音量条UI定制的

    2024年02月11日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包