1. 作业内容
用socket实现Android client和Android server之间的通信,通过client的命令行给server传递client的进程id和想要传递的字符串,且通过apk的toast将命令行传递来的内容在测试机上show出。
2. 分步解决
(1)Android socket实现client和server之间的通信
Android系统在Unix socket的基础上做了封装,构成了自己的一套Socket。要使用它需要将对应的头文件(cutils/sockets.h)包含进来。
有关Android socket通信,ppt中给出了server端和client端的关键代码:
//server关键代码 server_fd=android_get_control_socket("socket_name"); ret=listen(server_fd,4); while((socket=accept(server_fd,(sockaddr*)&peeraddr,&sockle))>=0) read/write(socket,"hello",5);.....//send or write
//client端 fd=socket_local_client("socket_name",ANDROID_SOCKET_NAMESPACE_RESERVED,SOCK_STREAM); if(fd>=0) read/write(fd,"hello",5);
这是c代码,因此我们首先在vendor下某个目录中新建一个子目录,并新建两个文件:ran_client.c 和 ran_server.c 。client端相对来说比较简单,只需要使用socket_locat_client()函数链接至套接字后用write函数写入数据即可。结合题意使用getpid获取进程id,使用gets()函数接收键盘输入的string,用strcat把这两个内容拼接后一起传入socket中。
对于server端,android_get_control_socket("name")相当于创建了一个socket(也可以理解为连接上以ran_socket为名的socket。listen指对该进程进行监听,此后使用while进入等待socket信息的循环。在收到信息后,使用read函数读取出来socket传递来的数据,再对数据进行下一步的处理。
(2)am broadcast命令
am命令可以直接控制apk。常见的am命令有:
am start -n [apkname] //控制开启apk
结合broadcast广播,可以使用am broadcast -a [apkname] -f [flags] --es [name] [string]命令将string和传入[name]中,apk中就能接收到。
(3)system函数
am broadcast的问题解决了,就要解决如何在ran_server.c中执行这条程序了。c语言调用system(char* command)函数,可以在括号中输入需要在shell命令行执行的语句。如system("getprop | grep -i ran_");
需要注意的是,这里system里的内容对于c语言来说仅仅是一串字符串,因此无法在其中进行任何的读取数据等 *** 作。本题中,需要把server端接收到的数据传递进command中,只能提前读取出数据内容,用strcpy和strcat将内容与对应数据进行拼接再传入system中。
(4).rc和.mk文件设置
在.rc中增加一个ran_server的service,在其中提前申请一个socket,赋予权限并设置在fs-fata下自启动。从其他地方借来一个label给它执行权限。
#ran service ran_server /system/bin/ran_server socket ran_server_socket stream 0660 root system seclabel u:r:asus_bluetooth:s0 class core user root group root oneshot
要使得c文件最终变成可在手机中执行的.ko驱动文件,还需要创建一个Android.mk文件。(这里的mk文件复制于其他类似mk,只改了module名字和部分lib库。)
3. 遇到的问题
(1)在包含头文件时候报错文件不存在。因为mk文件中没有把对应的lib库包含进来,在mk中添加对应lib后解决了问题。
include $(CLEAR_VARS) LOCAL_SHARED_LIBRARIES := libutils libcutils liblog LOCAL_SRC_FILES := ran_server.c
(2)在使用am broadcast时,一开始并没有加-f ,这时候查看log会发现报broadcast not allowed权限不足的错。查询资料得知,Android 8之后对broadcast发送的信息管控更加严格了,有些没有加flag的传送信号会被自动拦截下来。加上-f 0x1000000后解决了这个问题。
(3)一度有过avc报错,虽然后来发现执行失败和avc报错没有关系(selinux已经关闭),还是记录一下如何解决avc报错。 首先,rc中对自己创建的service打了label,那么去对应的te文件中添加权限(又称解sepolicy)。命令:
avc报错:avc:denied {[权限]} for path = "..." dev = "...", ino = ... scontext=[执行者] tcontext = [被执行者] tclass=[被执行者类型] permissive = 0 allow [执行者] [被执行者] : [被执行者类型] {[权限]}
完成后,先执行make sepolicy 来确认改动无错,再执行make vendorimage后刷入vendor。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)