Brillo: 编译运行example-ledflasher程序

我们之前在建立Brillo编译环境的时候(. build/envsetup.sh), 在lunch的时候,就可以看到ledflasher-userdebug的项目,这个项目是给高通dragonboard使用的sample, 今天试着将这个项目移植到RPi 2B上面。相关的代码和配置文件在product/google/example-ledflasher下面,我们需要用到的文件有sepolicy和src下打面的所有文件。因为这个sample是用来控制LED的,所以我们还需要lights HAL层的代码,可以参考hardware/bsp/qcom/lights下面的代码。具体的操用步骤如下:

  • 修改hardware/bsp/qcom/lights下代码,以便生成我们所需要的lights HAL层代码:

修改Android.mk, 将LOCAL_MODULE 改成lights.rpi, 如下所示:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES := lights.c
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"lights\"
LOCAL_MODULE := lights.rpi
LOCAL_MODULE_TAGS := optional

include $(BUILD_SHARED_LIBRARY)

出于测试的目的,我并没有在RPi 2B上外接LED, 为了看到效里,暂时先作改lights.c文件,如果LED的状态发生变成,会在logcat中打印log,之后会在硬件上真正实现。相关的代码修改如下:

static int write_int(char const* path, int value)
{
#if 1
    ALOGI(" -> write: %s value=0x08%x(%d", path, value, value);
    return 0;
#else
    FILE *fd;

    fd = fopen(path, "w+");
    if (fd) {
        int bytes = fprintf(fd, "%d", value);
        fclose(fd);
        return (bytes < 0 ? bytes : 0);
    } else {
        ALOGE("write_int failed to open %s\n", path);
        return -errno;
    }
#endif
}

最后使用mm编译出lights.rpi.so文件。

  • 编译ledflasher与ledservice模块

同样,进入product/google/example-ledflasher/src/ledflasher与product/google/example-ledflasher/src/ledservice文件夹,将这个两模块编译出来。

  • 更新ramdisk7.img (selinux配置文件)

修改device/hzak/rpi/BoardConfig.mk,将product/google/example-ledflasher/sepolicy加入编译脚本:

BOARD_SEPOLICY_DIRS += \
    product/google/example-ledflasher/sepolicy

最后make编译整个项目,以便生成我们所需的ramdisk文件。

  • 更新系统中的其他模块

我们需要将lights.rpi.so, ledflasher和ledservice这几个文件放在特定的目录下。

但是首先将要更新ramdisk7.img:

$ adb push out/target/product/rpi/ramdisk.img /boot/ramdisk7.img

重启系统,这一步很重要,一定要做:

$ adb reboot

最后才去更新lights.rppi.so, ledflasher和ledservice这三个文件:

$ adb remount
$ adb sync system

最后重启系统,就可以通过ps命令看到ledflasher服务在运行了。

由于selinux的关系,system文件夹中的文件是有selinux context的,可以通过ls -Z命令查看

ledflasher与ledservice正确的selinux context应该是:

$ adb shell ls -lZ | grep led                                                                                                                                                                                               
-rwxr-xr-x 1 root   shell u:object_r:ledflasher_exec:s0          67200 2016-01-05 12:14 ledflasher
-rwxr-xr-x 1 root   shell u:object_r:ledservice_exec:s0          38528 2016-01-05 12:14 ledservice

如果在kernel log出现如下log, 那么说明你没有按照上面的步骤来做,这个service是不会运行的:

01-01 00:00:03.973     0     0 E init    : Service ledservice does not have a SELinux domain defined.
01-01 00:00:03.973     0     0 E init    : Service ledflasher does not have a SELinux domain defined.

而你看到的selinux context可能是这样的:

$ adb shell ls -lZ | grep led
-rwxr-xr-x 1 root   shell u:object_r:system_file:s0              67200 2016-01-05 12:14 ledflasher
-rwxr-xr-x 1 root   shell u:object_r:system_file:s0              38528 2016-01-05 12:14 ledservice

从/privet/v3/commandDefs中可以看到,已经有led相关的字段了。接下来就要了解怎么去查询,更新LED的状态了。

NOTE: 关于authorization token的获取,请参考之前的文章。

$ curl -H "Authorization: Privet 4oqc8UPPmgY8z+N7vjZTs4sSBcp/4CRVtQD38GIW5RozOjE6MTQ1MTE5NzM2OQ==" -k http://10.0.0.18/privet/v3/commandDefs
{
   "commands": {
      "_ledflasher": {
         "_animate": {
            "minimalRole": "user",
            "parameters": {
               "_duration": {
                  "maximum": 100.0,
                  "minimum": 0.1,
                  "type": "number"
               },
               "_type": {
                  "enum": [ "none", "marquee_left", "marquee_right", "blink" ],
                  "type": "string"
               }
            }
         },
         "_set": {
            "minimalRole": "user",
            "parameters": {
               "_led": {
                  "maximum": 4,
                  "minimum": 1,
                  "type": "integer"
               },
               "_on": {
                  "type": "boolean"
               }
            }
         },
         "_toggle": {
            "minimalRole": "user",
            "parameters": {
               "_led": {
                  "maximum": 4,
                  "minimum": 1,
                  "type": "integer"
               }
            }
         }
      },
      "_metrics": {
         "_disableAnalyticsReporting": {
            "minimalRole": "manager"
         },
         "_enableAnalyticsReporting": {
            "minimalRole": "manager"
         }
      },
      "base": {
         "updateBaseConfiguration": {
            "minimalRole": "manager",
            "parameters": {
               "localAnonymousAccessMaxRole": {
                  "enum": [ "none", "viewer", "user" ],
                  "type": "string"
               },
               "localDiscoveryEnabled": {
                  "type": "boolean"
               },
               "localPairingEnabled": {
                  "type": "boolean"
               }
            }
         },
         "updateDeviceInfo": {
            "minimalRole": "manager",
            "parameters": {
               "description": {
                  "type": "string"
               },
               "location": {
                  "type": "string"
               },
               "name": {
                  "type": "string"
               }
            }
         }
      }
   },
   "fingerprint": "3"
}

再看看/privet/v3/traits和/privet/v3/components:

$ curl -H "Authorization: Privet 4oqc8UPPmgY8z+N7vjZTs4sSBcp/4CRVtQD38GIW5RozOjE6MTQ1MTE5NzM2OQ==" -k https://10.0.0.18/privet/v3/traits
{
   "fingerprint": "3",
   "traits": {
      "_ledflasher": {
         "commands": {
            "_animate": {
               "minimalRole": "user",
               "parameters": {
                  "_duration": {
                     "maximum": 100.0,
                     "minimum": 0.1,
                     "type": "number"
                  },
                  "_type": {
                     "enum": [ "none", "marquee_left", "marquee_right", "blink" ],
                     "type": "string"
                  }
               }
            },
            "_set": {
               "minimalRole": "user",
               "parameters": {
                  "_led": {
                     "maximum": 4,
                     "minimum": 1,
                     "type": "integer"
                  },
                  "_on": {
                     "type": "boolean"
                  }
               }
            },
            "_toggle": {
               "minimalRole": "user",
               "parameters": {
                  "_led": {
                     "maximum": 4,
                     "minimum": 1,
                     "type": "integer"
                  }
               }
            }
         },
         "states": {
            "_leds": {
               "items": {
                  "type": "boolean"
               },
               "type": "array"
            },
            "_status": {
               "enum": {
                  "enum": [ "idle", "animating" ],
                  "type": "string"
               }
            }
         }
      },
      "_metrics": {
         "commands": {
            "_disableAnalyticsReporting": {
               "minimalRole": "manager"
            },
            "_enableAnalyticsReporting": {
               "minimalRole": "manager"
            }
         },
         "state": {
            "_AnalyticsReportingState": {
               "enum": [ "enabled", "disabled" ],
               "type": "string"
            }
         }
      },
      "base": {
         "commands": {
            "updateBaseConfiguration": {
               "minimalRole": "manager",
               "parameters": {
                  "localAnonymousAccessMaxRole": {
                     "enum": [ "none", "viewer", "user" ],
                     "type": "string"
                  },
                  "localDiscoveryEnabled": {
                     "type": "boolean"
                  },
                  "localPairingEnabled": {
                     "type": "boolean"
                  }
               }
            },
            "updateDeviceInfo": {
               "minimalRole": "manager",
               "parameters": {
                  "description": {
                     "type": "string"
                  },
                  "location": {
                     "type": "string"
                  },
                  "name": {
                     "type": "string"
                  }
               }
            }
         },
         "state": {
            "firmwareVersion": "string",
            "localAnonymousAccessMaxRole": [ "none", "viewer", "user" ],
            "localDiscoveryEnabled": "boolean",
            "localPairingEnabled": "boolean"
         }
      }
   }
}
$ curl -H "Authorization: Privet 4oqc8UPPmgY8z+N7vjZTs4sSBcp/4CRVtQD38GIW5RozOjE6MTQ1MTE5NzM2OQ==" -k https://10.0.0.18/privet/v3/components
{
   "components": {
      "ledflasher": {
         "state": {
            "_ledflasher": {
               "_leds": [ false, false, false, false ],
               "_status": "idle"
            }
         },
         "traits": [ "_ledflasher" ]
      },
      "metrics": {
         "state": {
            "_metrics": {
               "_AnalyticsReportingState": "disabled"
            }
         },
         "traits": [ "_metrics" ]
      },
      "weave": {
         "state": {
            "base": {
               "firmwareVersion": "0.0.0.1451996914",
               "localAnonymousAccessMaxRole": "viewer",
               "localDiscoveryEnabled": true,
               "localPairingEnabled": true
            }
         },
         "traits": [ "base" ]
      }
   },
   "fingerprint": "5"
}

评论

1 Comment on "Brillo: 编译运行example-ledflasher程序"

提醒我
avatar

joy
游客
joy
2 年 6 月 之前

can you tell me, how to provide internet connection to brillo?

wpDiscuz