Android的LocalSocket(应用层和native通信)是android为系统不同层间或同一层内的不同进程间通信封装的一种通信方法,多用来实现上层因没有操作底层的权限而向底层发送消息进行通信.因此大多时候native层常作为服务端,应用层常作为客户端.
native层service与应用层建立client/server模式socket通信主要代码:
应用层主要代码:
String SOCKET_NAME="myserver"; LocalSocket s =null; LocalSocketAddress l; s = new LocalSocket(); l = new LocalSocketAddress(SOCKET_NAME, LocalSocketAddress.Namespace.RESERVED); s.connect(l);
native层主要代码:(可以在system目录下,与netd/vold等进程并列创建自己的进程文件夹)
s_fdListen = android_get_control_socket(SOCKET_NAME; ret = listen(s_fdListen, n); s_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen);
文件夹下包含有main函数的.cpp文件和对应的.h文件以及其它你所需要的头文件和源文件,另外还有Android.mk文件.
我的Android.mk文件内容如下(可仿照此编写):
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SHARED_LIBRARIES := \ libcrypto \ libutils \ libdl \ libhardware_legacy \ liblog \ liblogwrap \ libmdnssd \ libnetutils \ libsysutils \ libwpa_client \ libcutils \ libqsap_sdk\ libstlport \ libstdc++ \ LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog LOCAL_MODULE:=myserver LOCAL_SRC_FILES := \ IpCmdController.cpp \ ***.cpp LOCAL_C_INCLUDES += external/stlport/stlport LOCAL_C_INCLUDES += bionic include $(BUILD_EXECUTABLE)
/system/core/rootdir/init.rc中加入:
service myserver /system/bin/myserver class main socket myserver stream 0660 root system编译完native层的代码后把生成的myserver文件(out/target/product/**/system/bin/下)push到手机的system/bin/下.然而此时还未运行,也无法开机自启动,需要将init.rc中更改的内容编入手机内.于是重新make bootimage,刷机重启.好了,手机中有了myserver进程了,然而由于我通信的一方应用层缺少权限,依旧无法正常通信,可能出现如下错误,关键原因在于SELinux在作怪.
错误:creat localsocket filed!java.io.IOException: No such file or directory
creat localsocket filed!java.io.IOException: Permission denied
此时每次重启手机后在adb shell /root下setenforce 0可正常通信,但每次重启手机设置,不能从根本上解决问题.
解决SELinux权限问题:
这里需要几处配置,
1.首先,在device/qcom/sepolicy/common下新建myservice.te文件,内容如下:
type myservice, domain; type myservice_exec, exec_type, file_type; init_daemon_domain(myservice) allow system_app socket_device:sock_file {read write};
2.在device/qcom/sepolicy/common/file_contexts中添加一句:
/system/bin/myservice u:object_r:myservice_exec:s0
3.如果external/sepolicy/app.te中有"neverallow appdomain socket_device:sock_file write;",可能需要注释掉
配置完之后,再次重新编译boot.img即可.