怎样创建一个systemservice,及使用Android service和native service的心得

在添加一个串口触摸屏读写功能的时候,对我这android 新手来说,可谓历尽万难,经历了尝试利用系统自带的SerialService 改写,到自己写一个system service,再转到native service。简直一把泪啊

先来说说添加system service

1. 定义接口frameworks\base\core\java\android\hardware\ITouch.aidl

interface ITouch {
	void touchsetup();
	int writetouch(byte[] buf);
}

2. \frameworks\base\services\core\java\com\android\server\Touchservice.java

public class Touchservice extends ITouch.Stub {
	private final String TAG = "Touchservice ";
    private final Context mContext;

    public Touchservice (Context context) {
        mContext = context;
    }

	public void TouchSetup()
	{
		native_touchsetup();
	}
	public int writeTouch(byte[] buf)
	{
		return native_writeTouch(buf, buf.length);
	}
	
    private native void native_touchsetup();
    private native int native_writeTouch(byte[] buf, int len);

}

3. 添加JNI 文件 frameworks\base\services\core\jni\com_android_server_touchservice.cpp

void register_android_server_TouchService_Setup(JNIEnv *env, jobject thiz) {
    fd = open("/dev/ttyS1", O_RDWR | O_NOCTTY | O_NONBLOCK);
    if (fd == -1) {
        ALOGE("Cannot open port %s",SERIO_DEVICE);
        return -1;
    }

    /* Configure device */
    int ret;
    int ldisc;
    unsigned long type;
    struct termios tio;

    tcgetattr(fd, &tio);
    tio.c_iflag = IGNPAR | IGNBRK;
    tio.c_cflag = HUPCL | CS8 | CREAD | CLOCAL | B115200;
    tio.c_cc[VMIN] = 1;
    tio.c_cc[VTIME] = 0;
    tio.c_oflag = 0;
    tio.c_lflag = 0;

    cfsetispeed(&tio, B115200);
    cfsetospeed(&tio, B115200);

    ret = tcsetattr(fd, TCSANOW, &tio);
    if (ret < 0) {
		ALOGE("TCSANOW error");
		close(fd);
		return -1;
    }

    ldisc = N_MOUSE;
    ret = ioctl(fd, TIOCSETD, &ldisc);
    if (ret < 0) {
		ALOGE("TIOCSETD error");
		close(fd);
		return -1;
    }
    type = SERIO_GENERAL_IRTSC | (SERIO_ANY << 8) | (SERIO_ANY << 16);
    ret = ioctl(fd, SPIOCSTYPE, &type);
    if (ret < 0) {
		ALOGE("SPIOCSTYPE error");
		close(fd);
		return -1;
    }
    read(fd, NULL, 0);
	return 0;
}

static jint register_android_server_TouchService_Write(JNIEnv *env, jobject thiz, jbyteArray data, jint len)
{
	jbyte *bytes;
	unsigned char *buf;
	int i;
	
	bytes = env->GetByteArrayElements(data,NULL);
	if(bytes == NULL) {
	  return false;
	}
	buf =(unsigned char *)calloc(len,sizeof(char));
	if(buf == NULL)
	{
	  return false;
	}
	for(i=0;i<len;i++)
	{
	  *(buf+i)=(unsigned char)(*(bytes+i));
	}

    i = write(fd, buf, len);

	env->ReleaseByteArrayElements(data,bytes,0);

	free(buf);
	return i;

}

static JNINativeMethod method_table[] = {
	{ "native_Touchsetup", "()V",(void*)register_android_server_TouchService_Setup},
	{ "native_writetouch", "([BI)I",(void*)register_android_server_TouchService_Write},
};

int register_android_server_touchservice(JNIEnv *env)
{

    return jniRegisterNativeMethods(env, "com/android/server/touchservice",
            method_table, NELEM(method_table));

}

frameworks\base\services\core\jni\Android.mk.添加一行,把JNI 文件编译进去

$(LOCAL_REL_DIR)/com_android_server_touchservice.cpp

frameworks\base\services\core\jni\onload.cpp 添加如下内容

..............

int register_android_server_touchservice(JNIEnv* env);

..............

register_android_server_touchservice(env);

4. frameworks\base\core\java\android\hardware\TouchManager.java

	private ITouch mTouchService;

	public TouchManager (Context context, ITouch service) {
		mContext = context;
		mTouchService= service;
	}

	public void WriteTouchManager(byte[] data)
	{
		try{
		    mTouchService.writetouch(data);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
	}
	

5.Context.java 添加下面一行service名称

    public static final String TOUCH_SERVICE = "touchservice";

6. SystemServer.java 照葫芦画瓢addservice

try {
                    Slog.i(TAG, "touchService");
                    touch= new TouchService(context);
                    ServiceManager.addService(Context.TOUCH_SERVICE, touch);
                } catch (Throwable e) {
                    Slog.e(TAG, "Failure starting touch service", e);
                }

 7. SystemServiceRegistry.java 注册service

 registerService(Context.TOUCH_SERVICE, TouchManager.class,
                new CachedServiceFetcher<TouchManager>() {
            @Override
            public TouchManager createService(ContextImpl ctx) {
                IBinder b = ServiceManager.getService(Context.TOUCH_SERVICE);
                return new TouchManager(ctx, ITouch.Stub.asInterface(b));
            }});

全部文件添加,修改完毕,要make update-api, 再make才能把xxx.aidl 的接口更新到两个txt文件,如果直接make, 后面报错会让你先make update-api 一下

编译进系统后,在串口执行命令,就可以看到添加的service 了

touchservice: [android.hardware.ITouch]

重点来了,这样添加的system service ,即使在device/....../sepolicy/目录下的 ***.te 文件添加了该service权限,最大也只能到system, 如果JNI 里open 一个设备,再调用内核里的函数有ioctl 操作就会失败,内核里面有下面这段代码检查权限,要有root 权限才能执行

	if (!capable(CAP_SYS_ADMIN))
		{
		printk(" no CAP_SYS_ADMIN\n");
		return -EPERM;
		}

其他诸如open,read/write 操作,对应内核里的函数没有上面代码,则能操作成功

所以,折腾了几天功夫,有ioctl 操作,在android 的system service无法达成要求,只能改为用native service。因为native service 最后编译出来的执行bin 文件,是放在init.rc 里启动,可以设置权限到root,应用只调用了service 的接口,实际ioctl 操作在native service,所以没有问题。

这里就不叙述native service的东西了,可以参考上一篇博文

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值