




已阅读5页,还剩7页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Android7.0 PackageManagerService (5) installd一、installd的初始化 1、installd启动 在init.rc中,有以下代码片段:.service installd /system/bin/installd class main socket installd stream 600 system system.容易看出installd将作为service被init进程启动,同时会创建一个名为installd的socket。在frameworks/native/cmds/installd/installd.cpp中:int 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() 0) ALOGE(Could not create directories; exiting.n); exit(1); . /得到installd socket lsocket = android_get_control_socket(SOCKET_PATH); . /installd变成服务端 if (listen(lsocket, 5) ALOGE(Listen on socket failed: %sn, strerror(errno); exit(1); fcntl(lsocket, F_SETFD, FD_CLOEXEC); for (;) alen = sizeof(addr); /接受Java层的installer服务连接,形成与之连接的socket s s = accept(lsocket, &addr, &alen); . fcntl(s, F_SETFD, FD_CLOEXEC); . for (;) unsigned short count; /读取收到的消息的长度 if (readx(s, &count, sizeof(count) ALOGE(failed to read sizen); break; /判断有效性 if (count = BUFFER_MAX) ALOGE(invalid size %dn, count); break; /读取cmd if (readx(s, buf, count) ALOGE(failed to read commandn); break; . bufcount = 0; /执行cmd if (execute(s, buf) break; . close(s); return 0;上面的代码中,我们省去了selinux相关的代码,只保留主干。 从主干代码容易看出,installd整体的结构非常简单,其实就是启动后,获取作为服务端的socket “installd”; 然后,监听”installd”,等待Java层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; /参数个数+1 n+; /保存参数 argn = cmd; if (n = TOKEN_MAX) ALOGE(too many argumentsn); goto done; if (*cmd) cmd+; /cmds为一个数组,保存了不同命令及对应的处理函数 for (i = 0; i sizeof(cmds) / sizeof(cmds0); i+) if (!strcmp(,arg0) if (n != cmdsi.numargs) /log . else /参数正确时,调用对应的执行函数进行处理 ret = cmdsi.func(arg + 1, reply); .execute函数的思路很清晰,类似于收到命令后查表找到对应的处理函数,然后传入参数并执行函数。在这一部分的最后,我们看看cmds中的内容:struct cmdinfo const char *name; unsigned numargs; int (*func)(char *arg, char replyREPLY_MAX);struct cmdinfo cmds = ping, 0, do_ping , create_app_data, 7, do_create_app_data , restorecon_app_data, 6, do_restorecon_app_data , migrate_app_data, 4, do_migrate_app_data , clear_app_data, 5, do_clear_app_data , destroy_app_data, 5, do_destroy_app_data , move_complete_app, 7, do_move_complete_app , get_app_size, 6, do_get_app_size , get_app_data_inode, 4, do_get_app_data_inode , create_user_data, 4, do_create_user_data , destroy_user_data, 3, do_destroy_user_data , dexopt, 10, do_dexopt , markbootcomplete, 1, do_mark_boot_complete , rmdex, 2, do_rm_dex , freecache, 2, do_free_cache , linklib, 4, do_linklib , idmap, 3, do_idmap , createoatdir, 2, do_create_oat_dir , rmpackagedir, 1, do_rm_package_dir , clear_app_profiles, 1, do_clear_app_profiles , destroy_app_profiles, 1, do_destroy_app_profiles , linkfile, 3, do_link_file , move_ab, 3, do_move_ab , merge_profiles, 2, do_merge_profiles , dump_profiles, 3, do_dump_profiles ,;可以比较清晰地看出cmds数组中存储的就是cmdinfo结构体,结构体中定义了名称、参数个数及对应的处理函数。二、installer服务的启动 1、启动 在SystemServer.java的startBootstrapServices函数中:private void startBootstrapServices() / Wait for installd to finish starting up so that it has a chance to / create critical directories such as /data/user with the appropriate / permissions. We need this to complete before we initialize other services. Installer installer = mSystemServiceManager.startService(Installer.class); .public SystemService startService(String className) final Class serviceClass; try serviceClass = (Class)Class.forName(className); catch (ClassNotFoundException ex) /抛出异常 . return startService(serviceClass);public T startService(Class serviceClass) try final String name = serviceClass.getName(); . 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 . 从上面的代码容易看出,SystemServer利用SystemServerManager的startService启动服务时,其实就是通过反射来创建服务对象,然后调用服务对象的onStart函数。因此,对于installer服务,我们此时只需要关注其构造函数和onStart函数:public final class Installer extends SystemService . public Installer(Context context) super(context); /与installd沟通的桥梁 mInstaller = new InstallerConnection(); . public void onStart() Slog.i(TAG, Waiting for installd to be ready.); /调用InstallerConnection的waitForConnection函数 mInstaller.waitForConnection(); .从上面的代码可以看出,Installer继承自SystemService,其构造函数主要创建出InstallerConnection,然后在onStart函数中调用InstallerConnection的waitForConnection函数。2、连接installd 接下来,我们就来看看InstallerConnection的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) throws 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) 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( Failed to execute + cmd + + Arrays.toString(args) + : + res); return resRaw;容易看出transact函数负责进行实际的传输工作:public synchronized String transact(String cmd) . /连接installd if (!connect() Slog.e(TAG, connection failed); return -1; /发送命令 if (!writeCommand(cmd) Slog.e(TAG, write command failed? reconnect!); if (!connect() | !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() /第一次才需要进行实际的连接,之后就不需要了 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(); 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 & 0xff); buf1 = (byte) (len 8) & 0xff); try /写入长度
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 光伏专业笔试题库及答案
- 2026届黑龙江省大庆市高三第一次质量检测生物试题(解析版)
- 安徽省皖南八校2024-2025学年高二上学期期中考试生物试卷(含答案)
- 体育产业发展趋势预测报告
- 汽车租赁行业优惠活动方案
- 27届八年级上数学入学测试卷
- 焦作古建祠堂施工方案
- 建筑电气临时施工方案
- 婚俗改革联谊活动方案策划
- 湖南职工讲堂活动方案策划
- 十八项核心制度培训培训课件
- 幼儿园警察职业介绍课件
- GB/T 37642-2019聚己内酯(PCL)
- 国防科技大学介绍
- 校音乐厅设计方案
- 新视野大学英语读写教程Unit1教案(含和译文)
- 机电一体化设计
- 新教材教科版五年级上册科学 第二单元 地球表面的变化 单元全套课时练
- (中职中专)财经法规与会计职业道德课件完整版电子教案
- DB37T 5151-2019 园林绿化工程资料管理规程
- 贝多芬F大调浪漫曲—小提琴谱(带钢伴谱)
评论
0/150
提交评论