赞
踩
我们前面看到了,可以编写自己的 .te 文件, 定义自己的类型。
目标案例可以参考, 高通或者 mtk 平台下自带的 system\core\init\readme.txt
一、 init.rc
1.1 如何写服务
在android源码根目录下有android/system/core/rootdir/init.rc文件, 有很多地方都有
.rc 文件, 类似 init.target.rc init.usb.rc init.environ.rc.in
注:每个设备下都会有自己对应的init.rc,init.设备名.rc脚本文件
init.rc 该脚本文件中有很多 服务权限的赋予,定义等等,
假设我现在写了一个脚本 my.sh 那么,我需要赋予它权限的,所以就可以在 init.rc 中去定义和赋予
service usblp_test /data/setip/my.sh
oneshot
disabled
oneshot disabled向我们说明了在系统启动的时候这个服务是不会自动启动的,并且该服务的目的是执行/data/setip/init.usblpmod.sh脚本。脚本的内容你可以随便写,只要符合shell语法就可以了
这里。我后面会好好 总结一下 一些 sh脚本的用法等等
书写完 sh 脚本后,需要编译进 android 系统中 比如 system/bin vender/
(1)有几种在模块中的 mk文件中, 要看这个sh是为哪个模块工作的
编译进 system
include $(CLEAR_VARS)
LOCAL_MODULE := my.sh
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_SRC_FILES := assets/my.sh
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_EXECUTABLES)
include $(BUILD_PREBUILT)
(2)再就是编译的时候 copy file 了
前面是文件源路径,后面的是目的路径
PRODUCT_COPY_FILES += \
device/xx/xx/etc/my.sh:system/etc/my.sh
1.2 添加 服务
添加启动动作,使Android在启动时候执行。
init.rc文件末尾处加入以下内容
service mount-usbfs /system/etc/usbfs.sh
class main
user root
group root
oneshot
chown root shell /system/etc/usbfs.sh
chmod 0550 /system/etc/usbfs.sh
其实这里赋予了权限并没有什么用,这里也是转载网上的
为什么?接着查,在查看init.rc的过程中,发现了以下内容:
mount ext4 ext4@system /system ro 原来system分区是以只读的形式进行挂载的,忽略这点了。以只读形式挂载,再怎么赋权限,也是徒劳啊
那为什么相同目录下的 其他sh可以
6.0 /android/system/core/include/private/android_filesystem_config.h
这里定义的,谁对应的谁 比如: AID_SYSTEM - “system”
#define AID_ROOT 0 /* traditional unix root user */
#define AID_SYSTEM 1000 /* system server */
#define AID_RADIO 1001 /* telephony subsystem, RIL */
#define AID_BLUETOOTH 1002 /* bluetooth subsystem */
#define AID_GRAPHICS 1003 /* graphics devices */
#define AID_INPUT 1004 /* input devices */
#define AID_AUDIO 1005 /* audio devices */
#define AID_CAMERA 1006 /* camera devices */
#define AID_LOG 1007 /* log devices */
#define AID_COMPASS 1008 /* compass device */
#define AID_MOUNT 1009 /* mountd socket */
#define AID_WIFI 1010 /* wifi subsystem */
static const 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, },
{ "log", AID_LOG, },
{ "compass", AID_COMPASS, },
{ "mount", AID_MOUNT, },
......
/android/system/core/libcutils/fs_config.c 有对他的定义, 这里就定义了哪些sh 属于哪个权限组了
....
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <private/android_filesystem_config.h>
....
static const struct fs_path_config android_dirs[] = {
{ 00770, AID_SYSTEM, AID_CACHE, 0, "cache" },
{ 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app" },
{ 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private" },
{ 00771, AID_ROOT, AID_ROOT, 0, "data/dalvik-cache" },
{ 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/data" },
{ 00771, AID_SHELL, AID_SHELL, 0, "data/local/tmp" },
{ 00771, AID_SHELL, AID_SHELL, 0, "data/local" },
{ 01771, AID_SYSTEM, AID_MISC, 0, "data/misc" },
{ 00770, AID_DHCP, AID_DHCP, 0, "data/misc/dhcp" },
{ 00771, AID_SHARED_RELRO, AID_SHARED_RELRO, 0, "data/misc/shared_relro" },
{ 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media" },
{ 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/Music" },
{ 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },
{ 00750, AID_ROOT, AID_SHELL, 0, "sbin" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/bin" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/vendor" },
{ 00755, AID_ROOT, AID_SHELL, 0, "system/xbin" },
{ 00755, AID_ROOT, AID_ROOT, 0, "system/etc/ppp" },
{ 00755, AID_ROOT, AID_SHELL, 0, "vendor" },
{ 00777, AID_ROOT, AID_ROOT, 0, "sdcard" },
{ 00755, AID_ROOT, AID_ROOT, 0, 0 },
static const struct fs_path_config android_files[] = {
{ 00440, AID_ROOT, AID_SHELL, 0, "system/etc/init.goldfish.rc" },
{ 00550, AID_ROOT, AID_SHELL, 0, "system/etc/init.goldfish.sh" },
{ 00771, AID_ROOT, AID_SHELL, 0, "system/bin/atmel_ts.sh" },
{ 00550, AID_ROOT, AID_SHELL, 0, "system/etc/init.ril" },
{ 00550, AID_DHCP, AID_SHELL, 0, "system/etc/dhcpcd/dhcpcd-run-hooks" },
{ 00555, AID_ROOT, AID_ROOT, 0, "system/etc/ppp/*" },
{ 00555, AID_ROOT, AID_ROOT, 0, "system/etc/rc.*" },
{ 00444, AID_ROOT, AID_ROOT, 0, conf_dir + 1 },
{ 00444, AID_ROOT, AID_ROOT, 0, conf_file + 1 },
{ 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app/*" },
{ 00644, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/*" },
{ 00644, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private/*" },
{ 00644, AID_APP, AID_APP, 0, "data/data/*" },
1)首先了解下在服务启动的流程
Main函数的for(;;)循环中有一个handle_property_set_fd(),函数:
for (i = 0; i < fd_count; i++) {
if (ufds[i].revents == POLLIN) {
if (ufds[i].fd == get_property_set_fd())
handle_property_set_fd();
else if (ufds[i].fd == get_keychord_fd())
handle_keychord();
else if (ufds[i].fd == get_signal_fd())
handle_signal();
}
}
这个函数的实现也在system/core/init目录下,该函数中的check_control_perms(msg.value, cr.uid, cr.gid)函数就是检查该uid是否有权限启动服务(msg.value就是你服务的名字),如果应用为root或system用户则直接返回1.之后就是调用handle_control_message((char*) msg.name + 4, (char*) msg.value),该函数的参数就是去掉1.ctl.后的start和2.你服务的名字。这个函数的详细内容:
void handle_control_message(const char *msg, const char *arg)
{
if (!strcmp(msg,”start”)) {
msg_start(arg);
} else if (!strcmp(msg,”stop”)) {
msg_stop(arg);
} else if (!strcmp(msg,”restart”)) {
msg_stop(arg);
msg_start(arg);
} else {
ERROR(“unknown control msg ‘%s’\n”, msg);
}
}
匹配start后调用msg_start.服务就这样起来了,我们的解决方案就是在检查权限的地方“下点功夫”,因为我们不确定uid,所以就让check_control_perms这个函数不要检查我们的uid,直接检查我们服务的名字,看看这个函数:
static int check_control_perms(const char *name, unsigned int uid, unsigned int gid) {
int i;
if (uid == AID_SYSTEM || uid == AID_ROOT)
return 1;
/* Search the ACL */
for (i = 0; control_perms[i].service; i++) {
if (strcmp(control_perms[i].service, name) == 0) {
if ((uid && control_perms[i].uid == uid) ||
(gid && control_perms[i].gid == gid)) {
return 1;
}
}
}
return 0;
}
这个函数里面是必须要检查uid的,我们只要在for循环上写上。
if(strcmp(“usblp_test”,name)==0) //usblp_test就是我们服务的名字。
return 1;
这样做不会破坏android原本的结构,不会有什么副作用。
init.c和init.rc都改好了,现在就可以编译源码了,编译好了装到机子开发板上就可以了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。