Android系统级深入开发
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

3.4.1 移植的辅助性工作

1.Init时设置设备权限

init可执行文件是Android系统运行的第一个用户空间的程序,它以守护进程的方式运行。

在需要增加驱动程序设备节点时,一个潜在的工作就是更改这些设备节点的属性,更改的内容在system/core/init/devices.c文件中。

struct perms表示设备的类型,如下所示:

    struct perms_ {
        char *name;                         /* 设备的名称 */
        mode_t perm;                        /* 设备的Mode */
        unsigned int uid;                  /* 设备的用户ID */
        unsigned int gid;                  /* 设备的组ID */
        unsigned short prefix;            /* 设备的前缀 */
    };

devperms数组表示系统中的设备,这个数组的类型是perms,如下所示:

    static struct perms_ devperms[] = {
        { "/dev/null",           0666,   AID_ROOT,       AID_ROOT,       0 },
        { "/dev/zero",           0666,   AID_ROOT,       AID_ROOT,       0 },
        { "/dev/full",           0666,   AID_ROOT,       AID_ROOT,       0 },
        { "/dev/ptmx",           0666,   AID_ROOT,       AID_ROOT,       0 },
        { "/dev/tty",            0666,   AID_ROOT,       AID_ROOT,       0 },
        { "/dev/random",        0666,   AID_ROOT,       AID_ROOT,       0 },
        { "/dev/urandom",       0666,   AID_ROOT,       AID_ROOT,       0 },
        { "/dev/ashmem",        0666,   AID_ROOT,       AID_ROOT,       0 },
        { "/dev/binder",        0666,   AID_ROOT,       AID_ROOT,       0 },
        { "/dev/log/",           0662,   AID_ROOT,       AID_LOG,        1 },
        { "/dev/alarm",         0664,   AID_SYSTEM,     AID_RADIO,      0 },
        { "/dev/tty0",           0660,   AID_ROOT,       AID_SYSTEM,     0 },
        { "/dev/graphics/",     0660,   AID_ROOT,       AID_GRAPHICS,   1 },
    /* ......省略部分内容*/
        { "/dev/input/",        0660,   AID_ROOT,       AID_INPUT,      1 },
    /* ......省略部分内容*/
        { "/dev/ppp",            0660,   AID_RADIO,      AID_VPN,        0 },
        { "/dev/tun",            0640,   AID_VPN,        AID_VPN,        0 },
        { NULL, 0, 0, 0, 0 },
    };

其中,主要定义的内容是每一个设备的权限、所属用户、所属组。这个权限的含义和Linux标准的定义相同,3个数字分别表示所属用户、所属组和其他人权限。4表示可读,2表示可写,1表示可执行(设备节点不需要可执行)。

例如,/dev/null是一个Linux标准的设备,这里给它的权限是0666,表示任何用户都可以对其进行读/写。

如果需要增加一个设备节点文件,需要在devperms数组中增加一行内容。

各个与用户名相关的名称在system/core/include/private目录的android_filesystem_config.h文件中定义,android_id_info表示id的属性,内容如下所示:

    struct android_id_info {
        const char *name;
        unsigned aid;
    };

具体各个ID(用户名)的定义在android_ids数组中描述,内容如下所示:

    static struct android_id_info android_ids[] = {
        { "root",      AID_ROOT, },                  /* 字符串 <--> 整数值 */
        { "system",    AID_SYSTEM, },
        { "radio",     AID_RADIO, },
        { "bluetooth", AID_BLUETOOTH, },
        { "graphics",  AID_GRAPHICS, },
        { "input",     AID_INPUT, },
        { "audio",     AID_AUDIO, },
        { "camera",    AID_CAMERA, },
    /* ......省略部分内容*/
        { "nobody",    AID_NOBODY, },
    };

android_ids数组实际上表示了一个映射关系,将字符串和整数值对应起来。

2.init.rc中的内容

在Android中使用启动脚本init.rc,init启动脚本的路径:system/core/rootdir/init.rc可以在系统的初始化过程中进行一些简单的初始化操作。init.rc脚本被直接安装到目标系统的根文件系统中,被init可执行程序解析。

init.rc是在init启动后被执行的启动脚本,其语法主要包含了以下的内容:

Commands:命令

Actions:动作

Triggers:触发条件

Services:服务

Options:选项

Properties:属性

init脚本的关键字可以参考init进程的system/core/init/keyword.h文件。这些功能一般都是通过调用Linux的标准库函数来实现的。关于init.rc脚本的使用方法,可以参考说明文件system/core/init/readme.txt。

Commands(命令)是一些基本的操作,例如:

    export PATH /sbin:/system/sbin:/system/bin:/system/xbin
    mount yaffs2 mtd@system /system
    mount yaffs2 mtd@system /system ro remount
    mkdir /data/misc 01771 system misc
    mkdir /data/lost+found 0770
    mkdir /cache/lost+found 0770

这些命令在init可执行程序中被解析,然后调用相关的函数来实现。

以下命令可以更改系统中目录和文件的权限:

    chmod 0770 /data/misc/wifi
    chmod 0660 /data/misc/wifi/wpa_supplicant.conf

在init.rc脚本中更改权限当然也可以用于更改设备文件的权限,然而init.rc脚本只是在初始化状态下执行,因此这样更改权限只适合用于固定的设备,对于可以热插拔的设备则还是需要通过init进行中的devices.c文件来实现。

Actions(动作)表示一系列的命令,通常在Triggers(触发条件中)中调用,动作和触发条件的形式如下:

    on <trigger>
      <command>
      <command>
      <command>

动作的使用示例如下:

    on init
        export PATH /sbin:/system/sbin:/system/bin:/system/xbin
        mkdir /system

init表示一个触发条件(初始化过程),在这个触发事件发生后,进行设置环境变量和建立目录的操作称为一个“动作”。

Properties(属性)是系统中使用的一些值,可以进行设置和读取。

在启动脚本中,属性的使用如下所示:

    setprop ro.FOREGROUND_APP_MEM 1536
    setprop ro.VISIBLE_APP_MEM 2048
    on property:ro.kernel.qemu=1
    start adbd

setprop用于设置属性,on property可以用于判断属性,这里的属性在整个Android系统运行中都是一致的。

Services(服务)通常表示启动一个可执行程序,Options(选项)是服务的附加内容,用于配合服务使用。

例如,启动电话的进程ril-daemon和开机动画的服务,分别如下所示:

    service ril-daemon /system/bin/rild
        socket rild stream 660 root radio
        socket rild-debug stream 660 radio system
        user root
        group radio cache inet misc audio
    service bootanim /system/bin/bootanimation
        user graphics
        group graphics
        disabled
        oneshot

ril-daemon和bootanim表示服务的名称,/system/bin/rild和/system/bin/bootanimation表示服务所需要执行的可执行程序的路径。

socket、user、group和oneshot就是配合服务使用的选项。oneshot选项表示该服务只启动一次,而如果没有oneshot选项,这个可执行程序会一直存在——如果可执行程序被杀死,则会重新启动。在以上的例子中,ril-daemon是一个守护进程,如果退出,需要重新启动,因此没有使用oneshot;bootanim开机动画,只执行一次,因此加上了oneshot。

3.更改配置文件

在Android硬件抽象层移植的过程中,有时候还需要向系统中加入运行时配置(Executive Time Configuration )文件,来配置系统的功能。

Android中的ETC文件,主要放在/system/etc/目录中,如下所示:

    # ls -l /system/etc/
    -rw-r--r-- root     root        61347 2010-03-09 09:58 NOTICE.html.gz
    -r--r----- bluetooth bluetooth      935 2010-03-06 02:16 dbus.conf
    drwxr-xr-x root     root               2010-03-09 09:14 permissions
    -rw-r--r-- root     root         1093 2010-03-06 02:16 vold.fstab
    -rw-r--r-- root     root         1471 2010-03-06 02:13 apns-conf.xml
    -rw-r--r-- root     root            25 2010-03-06 02:16 hosts
    -rw-r--r-- root     root        10801 2010-03-09 08:56 event-log-tags
    -rw-r--r-- root     root           473 2010-03-06 02:13 pvplayer.cfg
    drwxr-xr-x root     root               2010-03-09 09:14 dhcpcd
    drwxr-xr-x root     root               2010-03-09 09:41 ppp
    drwxr-xr-x root     root               2010-03-09 09:13 security
    -r-xr-x--- root     shell        1200 2010-03-06 02:16 init.goldfish.sh

Android运行时,文件系统根目录的etc目录是到/system/etc/的连接。

此外在/system/usr目录中,也包含了一些运行时的内容,如下所示:

    # ls -l /system/usr
    drwxr-xr-x root     root               2010-03-09 09:14 keylayout
    drwxr-xr-x root     root               2010-03-09 09:14 share
    drwxr-xr-x root     root               2010-03-09 09:28 keychars
    drwxr-xr-x root     root               2010-03-09 09:14 srec

4.文件系统的属性

在system/core/include/private目录的android_filesystem_config.h文件中定义了各个目录的属性,struct fs_path_config表示了文件系统路径的属性,如下所示:

    struct fs_path_config {
        unsigned mode;        // 模式
        unsigned uid;         // 用户ID
        unsigned gid;         // 组ID
        const char *prefix;  // 目录前缀
    };

文件系统中一些子目录的属性在android_dirs数组中定义,如下所示:

    static struct fs_path_config android_dirs[] = {
        { 00770, AID_SYSTEM, AID_CACHE,  "cache" },
        { 00771, AID_SYSTEM, AID_SYSTEM, "data/app" },
        { 00771, AID_SYSTEM, AID_SYSTEM, "data/app-private" },
        { 00771, AID_SYSTEM, AID_SYSTEM, "data/dalvik-cache" },
        { 00771, AID_SYSTEM, AID_SYSTEM, "data/data" },
        { 00771, AID_SHELL,  AID_SHELL,  "data/local/tmp" },
        { 00771, AID_SHELL,  AID_SHELL,  "data/local" },
        { 01771, AID_SYSTEM, AID_MISC,   "data/misc" },
        { 00770, AID_DHCP,   AID_DHCP,   "data/misc/dhcp" },
        { 00771, AID_SYSTEM, AID_SYSTEM, "data" },
        { 00750, AID_ROOT,   AID_SHELL,  "sbin" },
        { 00755, AID_ROOT,   AID_SHELL,  "system/bin" },
        { 00755, AID_ROOT,   AID_SHELL,  "system/xbin" },
        { 00755, AID_ROOT,   AID_ROOT,   "system/etc/ppp" },
        { 00777, AID_ROOT,   AID_ROOT,   "sdcard" },
        { 00755, AID_ROOT,   AID_ROOT,   0 },
    };

默认文件的属性在android_files数组中定义,如下所示:

    static struct fs_path_config android_files[] = {
        { 00440, AID_ROOT,      AID_SHELL,     "system/etc/init.goldfish.rc" },
        { 00550, AID_ROOT,      AID_SHELL,     "system/etc/init.goldfish.sh" },
        { 00440, AID_ROOT,      AID_SHELL,     "system/etc/init.trout.rc" },
        { 00550, AID_ROOT,      AID_SHELL,     "system/etc/init.ril" },
    /* ......省略部分内容 */
    };

如果需要更改文件系统路径的属性等内容,只需要更改android_filesystem_config.h文件即可。