背景
修改andorid framework,希望新增一个socket 与自定义的程序进行信息交互
实现代码
服务端
//LocalSocket graal_start_sock_raw = new LocalSocket(LocalSocket.SOCKET_SEQPACKET);
Process.ProcessStartResult my_spec_result = new Process.ProcessStartResult();
try {
LocalServerSocket graal_start_sock_server = new LocalServerSocket("_sock_graal");
LocalSocket graal_start_sock = graal_start_sock_server.accept();
BufferedWriter cmd_out_stream = new BufferedWriter(
new OutputStreamWriter(graal_start_sock.getOutputStream()),
Zygote.SOCKET_BUFFER_SIZE);
DataInputStream cmd_in_stream = new DataInputStream(graal_start_sock.getInputStream());
//seee startViaZygote in ZygoteProcess.java
ArrayList
args_for_graal.add(“seq=” + app.startSeq);
String msgStr = args_for_graal.size() + “\n” + String.join(“\n”, args_for_graal) + “\n”;
cmd_out_stream.write(msgStr);
读取端
LocalSocket graal_start_sock = new LocalSocket();
long seq = -1;
try {
graal_start_sock.connect(
new LocalSocketAddress(“_sock_graal”,
LocalSocketAddress.Namespace.ABSTRACT));
BufferedReader cmd_in_stream = new BufferedReader(
new InputStreamReader(graal_start_sock.getInputStream()), 256);
DataOutputStream cmd_out_stream = new DataOutputStream(graal_start_sock.getOutputStream());
String[] args = readArgumentList(cmd_in_stream);
seq = get_seq_from_args(args);
cmd_out_stream.writeInt((int)android.os.Process.myPid());
cmd_out_stream.flush();
} catch (IOException ex) {
graal_start_sock = null;
ex.printStackTrace();
return -1;
}
问题
读取端总是报连接被拒绝,使用如下测试用例,尝试规避https://www.v2ex.com/t/738374 提到的addr size问题,仍然无法解决问题。
1 | #include <sys/types.h> /* See NOTES */ |
并且使用lsof -p 查看服务端pid,可以看到确实已经成功的出现了新建的socket端口。
查看logcat,发现这里是触发了android 上的StrictMode
保护。可参考https://droidyue.com/blog/2015/09/26/android-tuning-tool-strictmode/ ,简单的说,就是在UI线程中不允许使用wait/connect这样可能会引起阻塞的操作。
由于使用C程序测试无法收到异常消息,这里只能看到连接被拒绝。
问题解决
知道问题后,可以参考frameworks/base/services/core/java/com/android/server/am/ProcessList.java的如下片段。
临时性开放权限,运行在消息循环中进行socket动作即可。
1 | StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy(); |
参考动作
1 | if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { |