PropertyService(一)

setProperty在Android开发中太常用了,很多地方都会用它来记录一下value,以此作为判断条件或者通信的数据。当然ctl.start也可以启动系统服务,前提是要在ServiceManager中有过注册。本篇就来探究下PropertyService的启动过程以及它的处理流程。
 
按照惯例,还是先列一下会用到的文件:

system/core/init/init.cpp
system/core/init/property_service.cpp

 
默认属性是在Android系统开机后由init进程收集起来的,init进行到SecondStage的时候会执行下面的过程,从函数命名也能看出来是和property相关的。主要分为三块:service初始化、读入所有的默认属性、启动property service。

int SecondStageMain(int argc, char** argv) {
   
    ...
    property_init();  //构建所需要的目录,加载属性文件
    property_load_boot_defaults(load_debug_prop);   //加载系统中的prop文件
    StartPropertyService(&epoll);   //启动property服务
    ...
}

 
前面的初始化部分和加载属性部分暂且略过,代码简洁明了,一看就能明白,主要看一下服务的启动过程,因为这部分会涉及到后面Property是如何set下来的。

void StartPropertyService(Epoll* epoll) {
   
    selinux_callback cb;
    cb.func_audit = SelinuxAuditCallback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);  //selinux控制属性的set和get

    property_set("ro.property_service.version", "2");  //设置属性版本号

    property_set_fd = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
                                   false, 0666, 0, 0, nullptr);//创建一个socket进程同行,用以连接native层的jni
    if (property_set_fd == -1) {
   
        PLOG(FATAL) << "start_property_service socket creation failed";
    }

    listen(property_set_fd, 8);   //监听socket文件描述符

    if (auto result = epoll->RegisterHandler(property_set_fd, handle_property_set_fd); !result) {
     //注册到传进来的epoll中
        PLOG(FATAL) << result.error();
    }
}

这部分看起来也很简洁,通过selinux来控制属性的设置,避免随意的访问,然后创建socket描述符进行监听,并且将其注册到epoll中,这样的话init主函数就可以监听到此处的描述符(后面会介绍),进而当收到消息时去处理,而handle_property_set_fd则是处理函数。
 
handle_property_set_fd中主要是用来接收socket中传递的消息,借助property_set_fd这个文件描述符来接收和发送消息。当socket有消息来到的时候,通过property_set_fd重新构造一个socket连接,并读取发送过来的消息。接着分开为两个case处理不同的消息,分别为PROP_MSG_SETPROP和PROP_MSG_SETPROP2,从处理逻辑上看出一个传递char数组指针,一个是string指针,殊途同归,只不过一个按照字符、一个按照字符串,最终都是调用HandlePropertySet函数来处理。

static void handle_property_set_fd() {
   
    static constexpr uint32_t kDefaultSocketTimeout = 2000; /* ms */

    int s = accept4(property_set_fd, nullptr, nullptr, SOCK_CLOEXEC);
    if (s == -1) {
   
        return;
    }

    ucred cr;
    socklen_t cr_size = sizeof(cr);
    if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
   
        close(s);
        PLOG(ERROR) << "sys_prop: unable to get SO_PEERCRED";
        return;
    }

    SocketConnection socket(s, cr);
    uint32_t timeout_ms = kDefaultSocketTimeout;

    uint32_t cmd = 0;
    if (!socket.RecvUint32(&cmd, &timeout_ms)) {
   
        PLOG(ERROR) << "sys_prop: error while reading command from the socket";
        socket.SendUint32(PROP_ERROR_READ_CMD);
        return;
    }

    switch (cmd) {
   
    case PROP_MSG_SETPROP: {
   
        char prop_name[PROP_NAME_MAX];
        char prop_value[PRO
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Android 应用程序中,要调用 `CarPropertyManager` 设置车辆属性,需要按照以下步骤进行: 1. 获取 `Car` 对象: ``` Car car = Car.createCar(context); ``` 其中,`context` 表示上下文对象。 2. 获取 `CarPropertyManager` 对象: ``` CarPropertyManager carPropertyManager = (CarPropertyManager) car.getCarManager(Car.PROPERTY_SERVICE); ``` 3. 设置车辆属性: ``` carPropertyManager.setProperty(CarPropertyManager.IDENTIFICATION_VIN, "vin_value"); ``` 其中,`IDENTIFICATION_VIN` 表示要设置的车辆属性的 ID,`vin_value` 表示要设置的 VIN 码的值。 需要注意的是,不是所有的车辆属性都可以被应用程序设置,有些属性只能被系统或车辆制造商设置。在使用 `CarPropertyManager` 设置车辆属性之前,需要确认该属性是否可写。可以使用 `CarPropertyManager` 的 `isPropertyWritable` 方法来检查属性是否可写。 同时,为了保护车辆和驾驶员的安全,Android 系统可能会限制应用程序对某些车辆属性的访问权限。在 Android 应用程序中使用 `CarPropertyManager` 设置车辆属性时,需要确保应用程序已经获得了相应的权限。可以在 AndroidManifest.xml 文件中声明相应的权限。如下: ``` <uses-permission android:name="android.car.permission.CAR_CONTROL_APP_PERMISSION" /> ``` 这个权限允许应用程序控制车辆。需要注意的是,这个权限只能由车辆制造商或系统级别的应用程序来声明和使用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值