您当前的位置: 首页 >  android

xiangzhihong8

暂无认证

  • 2浏览

    0关注

    1324博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

android的PackageManagerService详解

xiangzhihong8 发布时间:2015-04-14 22:54:04 ,浏览量:2

PackageManagerService主要是一个包的管理服务,在开机的时候会解析以前保存的一些安装包的相关数据,android运行过程中新安装的apk也会保存到PackageManagerService的相关变量中,也会写到相关的文件中永久保存。

首先看一下它的总体流程

PackageManagerService也是由SystemServer启动的

PackageManagerService 的实现是以aidl方式实现的, 我们可以看到继承了 IPackageManager.Stub,其aidl文件为frameworks\base\core\java\android\content\pm\IPackageManager.aidl

主要是负责管理apk包,安装apk的时候负责解析该apk包的manifest.xml,把其中包含的activity,service等添加到packagemanageservice中,以便运行该包的时候就能直接从packagemanageservice中获取该apk的相关信息,还会监控/system/app等目录,当我们把一个apk放到该目录时会自动对其进行安装(调用AppDirObserver的onEvent)

它的启动过程主要涉及以下几个方面

1、建立 java 层的 installer 与 c 层的 installd 的 socket 联接,使得在上层的 install,remove,dexopt等功能最终由installd在底层实现

这里涉及到socket的server和client端,在系统启动时候会启动一个installd的程序,init.rc中

[cpp]  view plain copy print ?
  1. service installd /system/bin/installd  
  2. socket installd stream 600 system system  
有一个socket名字是installd

这个可执行文件的代码在/framework/base/cmds/installd目录下面,比较简单,主要是监听socket上是否有数据来,有的话解析数据,执行相应的命令

在packagemanageservice中则会连接到相应这个socket,然后有需要的操作时,把相应的操作代码发到installd,由其进行解析操作

2、 建立PackageHandler消息循环,用于处理apk安装请求如adbinstall packageinstaller安装apk时就会发送消息

新建了一个HandlerThread的线程,并在其run函数中新建了一个Looper,把它设为PackageHandler,然后就可以利用它进行消息的处理

3、解析/system/etc/permission下的xml文件,主要是platform.xml,建立permission和gid之间的关系,可以指定一个权限与几个组对应,当一个apk被授予这个权限时它也同时属于这几个组,readPermission(parser, perm);给一些底层用户分配一些权限,如shell授予各种permission,把一个权限赋予一个uid,当apk使用这个uid运行时,就具备了这个权限系统增加的一些应用需要link的扩展的jar库,系统每增加一个硬件,都要添加相应的featrue,将解析结果放入mAvailableFeatures

看一下platform.xml中的部分

[cpp]  view plain copy print ?
  1. .......  
  2.       
  3.           
  4.       
  5.   
  6.       
  7.       
  8.           
  9.           
  10.       
  11. ......  
  12.       
  13.       
  14.       
  15.       
  16.       
  17.       
  18. .......  
  19.       
  20.       
  21.               
  22.       
其中readPermission主要是

1、读取permission name添加到mSettings.mPermissions 2、读取gid添加到mSettings.mPermissions

readPermissionsFromXml:

permission

a、读取permission name添加到mSettings.mPermissions

b、读取gid添加到mSettings.mPermissions

assign-permission

a、设置相应uid所具有的权限,保存到mSystemPermissions

 library

a、.jar包保存到mSharedLibraries

 feature

a、  硬件相关信息保存到mAvailableFeatures

4、检查/data/system/packages.xml是否存在,里面记录了系统的ppermission,以及每个apk的name,codePath,flags,ts,version,userid等,这些信息主要是通过apk安装的时候解析AndroidManifest.xml获取到的,解析完apk后将更新信息写入这个文件并保存到flash,下次开机直接从里面读取相关信息添加到内存相关列表中,当有apk安装,升级,删除时会更新这个文件

readLP

解析/data/system/packages.xml

last-platform-version :最后使用的内外部存储器的sdk版本

permissions:构造权限结构BasePermission添加到mPermissions

package:解析每个已经安装apk的name,codePath,sharedUserId,userId,version等,调用addPackageLP构建PackageSetting并添加到mPackages

shared-user:readSharedUserLP通过addSharedUserLP添加一个SharedUserSetting结构,再通过readGrantedPermissionsLP读取给这个userId赋予的权限

 

writeLP 

先把以前的packages.xml备份为packages-backup.xml,再把文件mSettingsFilename和XmlSerializer对象关联,再相关要写入文件的值先写入序列化对象,把相关信息写入序列化对象,再通过序列化对象写入文件

看一下package.xml

[cpp]  view plain copy print ?
  1.   
  2.   
  3.   
  4.   
  5.   
  6.   
  7.   
  8.   
  9.   
  10. ...................  
  11.   
  12.   
  13.   
  14.   
  15.   
  16. ..............  
  17.   
  18.   
  19.   
  20.   
  21.   
  22.   
  23.   
  24.   
  25.   
  26.   
  27.   
  28.   
  29.   
  30.   
  31.   
  32. ...............  
  33.   
  34.   
  35.   
  36.   
  37.   
  38.   
  39.   
  40.   
  41.   
  42.   
  43.   
5、检查BootClassPath,mSharedLibraries及/system/framework下的jar是否需要dexopt,需要则通过dexopt进行优化

这里面主要是调用mInstaller.dexopt进行相应的优化

6、启动AppDirObserver线程往中监测/system/framework,/system/app,/data/app/data/app-private目录的事件,主要监听add和remove事件,对于目录监听底层通过innotify机制实现,inotify是一种文件系统的变化通知机制如文件增加、删除等事件可以立刻让用户态得知,它为用户态监视文件系统的变化提供了强大的支持,当有add event时调用scanPackageLI(File,int,int)处理,当有remove event时调用removePackageLI处理

ObserverThread中有一段静态程序块(当一个类需要在被载入时就执行一段程序,这样可以使用静态程序块)

[cpp]  view plain copy print ?
  1. static {   
  2.     s_observerThread = new ObserverThread();  
  3.     s_observerThread.start();  
  4. }  
而它的run函数

[cpp]  view plain copy print ?
  1. public void run() {  
  2.     observe(m_fd);  
  3. }  
observer是个native函数,m_fd是ObserverThread初始化时候赋值的

[cpp]  view plain copy print ?
  1. public ObserverThread() {  
  2.     super("FileObserver");  
  3.     m_fd = init();  
  4. }  
看一下这几个native函数

init比较简单,直接调用inotify_init返回一个句柄标识

[cpp]  view plain copy print ?
  1. static void android_os_fileobserver_observe(JNIEnv* env, jobject object, jint fd)  
  2. {  
  3. #ifdef HAVE_INOTIFY  
  4.    
  5.     char event_buf[512];  
  6.     struct inotify_event* event;  
  7.            
  8.     while (1)  
  9.     {  
  10.         int event_pos = 0;  
  11.         int num_bytes = read(fd, event_buf, sizeof(event_buf));  
  12.           
  13.         if (num_bytes = (int)sizeof(*event))  
  14.         {  
  15.             int event_size;  
  16.             event = (struct inotify_event *)(event_buf + event_pos);  
  17.   
  18.             jstring path = NULL;  
  19.               
  20.             if (event->len > 0)  
  21.             {  
  22.                 path = env->NewStringUTF(event->name);  
  23.             }  
  24.   
  25.             env->CallVoidMethod(object, method_onEvent, event->wd, event->mask, path);  
  26.             if (env->ExceptionCheck()) {  
  27.                 env->ExceptionDescribe();  
  28.                 env->ExceptionClear();  
  29.             }  
  30.             if (path != NULL)  
  31.             {  
  32.                 env->DeleteLocalRef(path);  
  33.             }  
  34.   
  35.             event_size = sizeof(*event) + event->len;  
  36.             num_bytes -= event_size;  
  37.             event_pos += event_size;  
  38.         }  
  39.     }  
  40.       
  41. #endif // HAVE_INOTIFY  
  42. }  
observe则从句柄中读取事件,然后调用java层函数onEvent进行处理,看一下java层的onEvent函数

[cpp]  view plain copy print ?
  1. public void onEvent(int wfd, int mask, String path) {  
  2.     // look up our observer, fixing up the map if necessary...  
  3.     FileObserver observer = null;  
  4.   
  5.     synchronized (m_observers) {  
  6.         WeakReference weak = m_observers.get(wfd);  
  7.         if (weak != null) {  // can happen with lots of events from a dead wfd  
  8.             observer = (FileObserver) weak.get();  
  9.             if (observer == null) {  
  10.                 m_observers.remove(wfd);  
  11.             }  
  12.         }  
  13.     }  
  14.   
  15.     // ...then call out to the observer without the sync lock held  
  16.     if (observer != null) {  
  17.         try {  
  18.             observer.onEvent(mask, path);  
  19.         } catch (Throwable throwable) {  
  20.             Log.wtf(LOG_TAG, "Unhandled exception in FileObserver " + observer, throwable);  
  21.         }  
  22.     }  
  23. }  
调用observer的onEvent继续处理,这里的AppDirObserver

[cpp]  view plain copy print ?
  1. public void onEvent(int event, String path) {  
  2.     String removedPackage = null;  
  3.     int removedUid = -1;  
  4.     String addedPackage = null;  
  5.     int addedUid = -1;  
  6.   
  7.     synchronized (mInstallLock) {  
  8.         String fullPathStr = null;  
  9.         File fullPath = null;  
  10.         if (path != null) {  
  11.             fullPath = new File(mRootDir, path);  
  12.             fullPathStr = fullPath.getPath();  
  13.         }  
  14.   
  15.         if (Config.LOGV) Log.v(  
  16.             TAG, "File " + fullPathStr + " changed: "  
  17.             + Integer.toHexString(event));  
  18.   
  19.         if (!isPackageFilename(path)) {  
  20.             if (Config.LOGV) Log.v(  
  21.                 TAG, "Ignoring change of non-package file: " + fullPathStr);  
  22.             return;  
  23.         }  
  24.   
  25.         // Ignore packages that are being installed or  
  26.         // have just been installed.  
  27.         if (ignoreCodePath(fullPathStr)) {  
  28.             return;  
  29.         }  
  30.         PackageParser.Package p = null;  
  31.         synchronized (mPackages) {  
  32.             p = mAppDirs.get(fullPathStr);  
  33.         }  
  34.         if ((event&REMOVE_EVENTS) != 0) {  
  35.             if (p != null) {  
  36.                 removePackageLI(p, true);  
  37.                 removedPackage = p.applicationInfo.packageName;  
  38.                 removedUid = p.applicationInfo.uid;  
  39.             }  
  40.         }  
  41.   
  42.         if ((event&ADD_EVENTS) != 0) {  
  43.             if (p == null) {  
  44.                 p = scanPackageLI(fullPath,  
  45.                         (mIsRom ? PackageParser.PARSE_IS_SYSTEM  
  46.                                 | PackageParser.PARSE_IS_SYSTEM_DIR: 0) |  
  47.                         PackageParser.PARSE_CHATTY |  
  48.                         PackageParser.PARSE_MUST_BE_APK,  
  49.                         SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,  
  50.                         System.currentTimeMillis());  
  51.                 if (p != null) {  
  52.                     synchronized (mPackages) {  
  53.                         updatePermissionsLP(p.packageName, p,  
  54.                                 p.permissions.size() > 0, false, false);  
  55.                     }  
  56.                     addedPackage = p.applicationInfo.packageName;  
  57.                     addedUid = p.applicationInfo.uid;  
  58.                 }  
  59.             }  
  60.         }  
  61.   
  62.         synchronized (mPackages) {  
  63.             mSettings.writeLP();  
  64.         }  
  65.     }  
  66.   
  67.     if (removedPackage != null) {  
  68.         Bundle extras = new Bundle(1);  
  69.         extras.putInt(Intent.EXTRA_UID, removedUid);  
  70.         extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);  
  71.         sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,  
  72.                 extras, null);  
  73.     }  
  74.     if (addedPackage != null) {  
  75.         Bundle extras = new Bundle(1);  
  76.         extras.putInt(Intent.EXTRA_UID, addedUid);  
  77.         sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,  
  78.                 extras, null);  
  79.     }  
  80. }  
这里判断是add还是remove事件,如果是add则调用scanPackageLI安装该apk,如果是remove则调用removePackageLI删除

另外还有一个startWatching是开始监听,其native函数主要是调用inotify_add_watch(fd, path, mask)对指定目录进行监听

7、apk解析

对于以上几个上目录下的apkg逐个解析,主要是解析每个apk的AndroidManifest.xml文件,处理asset/res等资源文件,建立起每个apkr 配置结构信息,

调用parsePackage对apk进行解析,并把相应的数据保存到Package中

8、将解析出的Package的相关信息保存到相关全局变量,还有文件(上面已经提及)

这里主要是上面 PackageManagerService流程流程中的这一段

主要进行:

a、  查找该apk依赖的库是否存在

b、  查找该apk共享的uid是否存在

c、  判断该包是否已经存在,存在的话需要做一些处理

d、  查看它的Setting结构是否存在,不存在则创建它

e、  签名认证

f、  新应用的provider是否与已有的冲突(contentprovider数据共享机制)

g、  安装目录不存在 调用install进行安装

h、  对pkgSetting进行设置并将pkgSetting添加到mPackages(Settings类中的成员)

i、  将Package添加到mPackages(PackageManagerService中)

j、 将(Package中的Provider、Service、Activity、Permission、Instrumentation分别添加到mProviders、mServices、mActivities、mSettings.mPermissionTrees或mSettings.mPermissions、mInstrumentation,

这样,PackageManagerService就基本上完成了他的任务,后面如果我们运行的过程中要安装apk,也会进行相类似的处理
关注
打赏
1482932726
查看更多评论
立即登录/注册

微信扫码登录

0.0635s