《android7.0 packagemanagerservice (5) installd》由会员分享,可在线阅读,更多相关《android7.0 packagemanagerservice (5) installd(11页珍藏版)》请在金锄头文库上搜索。
1、Android7.0 PackageManagerService (5) installd一、installd 的初始化 1、installd 启动 在 init.rc 中,有以下代码片段:.service installd /system/bin/installdclass mainsocket installd stream 600 system system.容易看出 installd 将作为 service 被 init 进程启动,同时会创建一个名为 installd 的 socket。在 frameworks/native/cmds/installd/installd.cpp 中:i
2、nt main(const int argc, char *argv) return android:installd:installd_main(argc, argv);static int installd_main(const int argc ATTRIBUTE_UNUSED, char *argv) ./以下初始化全局变量,包括创建 data 下的一些目录等if (!initialize_globals() ALOGE(Could not initialize globals; exiting.n);exit(1);if (initialize_directories() = BUF
3、FER_MAX) ALOGE(invalid size %dn, count);break;/读取 cmdif (readx(s, buf, count) ALOGE(failed to read commandn);break;.bufcount = 0;/执行 cmdif (execute(s, buf) break;.close(s);return 0;上面的代码中,我们省去了 selinux 相关的代码,只保留主干。 从主干代码容易看出,installd 整体的结构非常简单,其实就是启动后,获取作为服务端的socket “installd”; 然后,监听”installd” ,等待 J
4、ava 层 installer 服务的连接及命令的到来。2、命令处理方式 一旦 installd 收到命令后,将调用 execute 函数进行处理,其代码如下:static int execute(int s, char cmdBUFFER_MAX) char replyREPLY_MAX;char *argTOKEN_MAX+1;.arg0 = cmd;/解析参数的个数while (*cmd) /当发现空格时if (isspace(*cmd) *cmd+ = 0;/参数个数+1n+;/保存参数argn = cmd;if (n = TOKEN_MAX) ALOGE(too many argum
5、entsn);goto done;if (*cmd) cmd+;/cmds 为一个数组,保存了不同命令及对应的处理函数for (i = 0; i serviceClass;try serviceClass = (Class)Class.forName(className); catch (ClassNotFoundException ex) /抛出异常.return startService(serviceClass);public T startService(Class serviceClass) try final String name = serviceClass.getName()
6、;.final T service;try /反射调用构造函数Constructor constructor = serviceClass.getConstructor(Context.class); catch(.) ./SystemServiceManager 的 mServices 中存储所有由其启动的服务mServices.add(service);/ Start it.try service.onStart(); catch (RuntimeException ex) /抛出异常. return service; finally /log.从上面的代码容易看出,SystemServe
7、r 利用 SystemServerManager 的 startService 启动服务时,其实就是通过反射来创建服务对象,然后调用服务对象的 onStart 函数。因此,对于 installer 服务,我们此时只需要关注其构造函数和 onStart 函数:public final class Installer extends SystemService .public Installer(Context context) super(context);/与 installd 沟通的桥梁mInstaller = new InstallerConnection();.public void o
8、nStart() Slog.i(TAG, Waiting for installd to be ready.);/调用 InstallerConnection 的 waitForConnection 函数mInstaller.waitForConnection();.从上面的代码可以看出,Installer 继承自 SystemService,其构造函数主要创建出InstallerConnection,然后在 onStart 函数中调用 InstallerConnection 的 waitForConnection 函数。2、连接 installd 接下来,我们就来看看 InstallerCo
9、nnection 的 waitForConnection 函数:public void waitForConnection() for (;) try /ping应该只是确认 installd 是否存活execute(ping);return; catch (InstallerException ignored) Slog.w(TAG, installd not ready); SystemClock.sleep(1000);跟进 InstallerConnection 的 execute 函数:public String execute(String cmd, Object. args) t
10、hrows InstallerException final StringBuilder builder = new StringBuilder(cmd);/处理参数for (Object arg : args) String escaped;if (arg = null) escaped = ; else escaped = String.valueOf(arg);if (escaped.indexOf(0) != -1 | escaped.indexOf( ) != -1 | !.equals(escaped) /错误格式抛出异常.if (TextUtils.isEmpty(escaped
11、) escaped = !;builder.append( ).append(escaped);/transact 发送命令及对应参数,并返回结果final String resRaw = transact(builder.toString().split( );int s = -1;try /解析结果res = Integer.parseInt(resRaw0); catch (ArrayIndexOutOfBoundsException | NumberFormatException ignored) if (res != 0) throw new InstallerException(F
12、ailed to execute + cmd + + Arrays.toString(args) + : + res);return resRaw;容易看出 transact 函数负责进行实际的传输工作:public synchronized String transact(String cmd) ./连接installdif (!connect() Slog.e(TAG, connection failed);return -1;/发送命令if (!writeCommand(cmd) Slog.e(TAG, write command failed? reconnect!);if (!con
13、nect() | !writeCommand(cmd) return -1;/读取返回结果final int replyLength = readReply();if (replyLength 0) String s = new String(buf, 0, replyLength);.return s; else .return -1;从上面的代码来看,整个通信结构非常的清晰,典型的 socket 通信架构。 为了分析的完整性,我们再看看 connect、writeCommand 和 readReply 函数:private boolean connect() /第一次才需要进行实际的连接,
14、之后就不需要了if (mSocket != null) return true;.try mSocket = new LocalSocket();/得到installd目的端地址LocalSocketAddress address = new LocalSocketAddress(installd, LocalSocketAddress.Namespace.RESERVED);/进行连接的过程mSocket.connect(address);/以下得到输入流和输出流mIn = mSocket.getInputStream();mOut = mSocket.getOutputStream();
15、catch (IOException ex) disconnect();return false;return true;private boolean writeCommand(String cmdString) final byte cmd = cmdString.getBytes();final int len = cmd.length;.buf0 = (byte) (len buf1 = (byte) (len 8) try /写入长度mOut.write(buf, 0, 2);/写入命令和参数mOut.write(cmd, 0, len); catch (IOException ex) Slog.e(TAG,