PackageManagerService

2024-03-31 09:32
文章标签 packagemanagerservice

本文主要是介绍PackageManagerService,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转自: http://blog.csdn.net/new_abc/article/details/8192587


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中

service installd /system/bin/installd
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中的部分

.......<permission name="android.permission.ACCESS_CACHE_FILESYSTEM" ><group gid="cache" /></permission><!-- RW permissions to any system resources owned by group 'diag'.This is for carrier and manufacture diagnostics tools that must beinstallable from the framework. Be careful. --><permission name="android.permission.DIAGNOSTIC" ><group gid="input" /><group gid="diag" /></permission>
......<assign-permission name="android.permission.WRITE_EXTERNAL_STORAGE" uid="shell" /><assign-permission name="android.permission.SEND_SMS" uid="shell" /><assign-permission name="android.permission.CALL_PHONE" uid="shell" /><assign-permission name="android.permission.READ_CONTACTS" uid="shell" /><assign-permission name="android.permission.WRITE_CONTACTS" uid="shell" /><assign-permission name="android.permission.READ_CALENDAR" uid="shell" />
.......<library name="android.test.runner"file="/system/framework/android.test.runner.jar" /><library name="javax.obex"file="/system/framework/javax.obex.jar"/><feature name="android.hardware.wifi" />

其中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
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<packages>
<last-platform-version internal="9" external="0" />
<permission-trees />
<permissions>
<item name="android.permission.CHANGE_WIFI_MULTICAST_STATE" package="android" protection="1" />
<item name="android.permission.CLEAR_APP_USER_DATA" package="android" protection="2" />
<item name="android.permission.SHUTDOWN" package="android" protection="2" />
<item name="android.permission.BIND_INPUT_METHOD" package="android" protection="2" />
...................
<package name="com.android.settings" codePath="/system/app/XJNTSettings.apk" nativeLibraryPath="/data/data/com.android.settings/lib" flags="1" ft="11b7e237e00" it="11b7e237e00" ut="11b7e237e00" version="1" userId="10020">
<sigs count="1">
<cert index="0" />
</sigs>
</package>
..............
<shared-user name="android.uid.shared" userId="10000">
<sigs count="1">
<cert index="1" />
</sigs>
<perms>
<item name="android.permission.READ_SYNC_STATS" />
<item name="android.permission.USE_CREDENTIALS" />
<item name="android.permission.INTERNET" />
<item name="android.permission.SUBSCRIBED_FEEDS_READ" />
<item name="android.permission.READ_CONTACTS" />
<item name="android.permission.GET_ACCOUNTS" />
<item name="android.permission.WRITE_CONTACTS" />
<item name="android.permission.SUBSCRIBED_FEEDS_WRITE" />
</perms>
</shared-user>
...............
<preferred-activities>
<item name="tv.ipanel.join.xjnt.homefinal/tv.ipanel.join.xjnt.home.XJNTHomeActivity" match="100000" set="2">
<set name="tv.ipanel.join.xjnt.home/.XJNTHomeActivity" />
<set name="tv.ipanel.join.xjnt.homefinal/tv.ipanel.join.xjnt.home.XJNTHomeActivity" />
<filter>
<action name="android.intent.action.MAIN" />
<cat name="android.intent.category.HOME" />
<cat name="android.intent.category.DEFAULT" />
</filter>
</item>
</preferred-activities>


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中有一段静态程序块(当一个类需要在被载入时就执行一段程序,这样可以使用静态程序块)

    static { s_observerThread = new ObserverThread();s_observerThread.start();}

而它的run函数
        public void run() {observe(m_fd);}

observer是个native函数,m_fd是ObserverThread初始化时候赋值的
        public ObserverThread() {super("FileObserver");m_fd = init();}

看一下这几个native函数

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

static void android_os_fileobserver_observe(JNIEnv* env, jobject object, jint fd)
{
#ifdef HAVE_INOTIFYchar event_buf[512];struct inotify_event* event;while (1){int event_pos = 0;int num_bytes = read(fd, event_buf, sizeof(event_buf));if (num_bytes < (int)sizeof(*event)){if (errno == EINTR)continue;LOGE("***** ERROR! android_os_fileobserver_observe() got a short event!");return;}while (num_bytes >= (int)sizeof(*event)){int event_size;event = (struct inotify_event *)(event_buf + event_pos);jstring path = NULL;if (event->len > 0){path = env->NewStringUTF(event->name);}env->CallVoidMethod(object, method_onEvent, event->wd, event->mask, path);if (env->ExceptionCheck()) {env->ExceptionDescribe();env->ExceptionClear();}if (path != NULL){env->DeleteLocalRef(path);}event_size = sizeof(*event) + event->len;num_bytes -= event_size;event_pos += event_size;}}#endif // HAVE_INOTIFY
}


observe则从句柄中读取事件,然后调用java层函数onEvent进行处理,看一下java层的onEvent函数
        public void onEvent(int wfd, int mask, String path) {// look up our observer, fixing up the map if necessary...FileObserver observer = null;synchronized (m_observers) {WeakReference weak = m_observers.get(wfd);if (weak != null) {  // can happen with lots of events from a dead wfdobserver = (FileObserver) weak.get();if (observer == null) {m_observers.remove(wfd);}}}// ...then call out to the observer without the sync lock heldif (observer != null) {try {observer.onEvent(mask, path);} catch (Throwable throwable) {Log.wtf(LOG_TAG, "Unhandled exception in FileObserver " + observer, throwable);}}}



调用observer的onEvent继续处理,这里的AppDirObserver
        public void onEvent(int event, String path) {String removedPackage = null;int removedUid = -1;String addedPackage = null;int addedUid = -1;synchronized (mInstallLock) {String fullPathStr = null;File fullPath = null;if (path != null) {fullPath = new File(mRootDir, path);fullPathStr = fullPath.getPath();}if (Config.LOGV) Log.v(TAG, "File " + fullPathStr + " changed: "+ Integer.toHexString(event));if (!isPackageFilename(path)) {if (Config.LOGV) Log.v(TAG, "Ignoring change of non-package file: " + fullPathStr);return;}// Ignore packages that are being installed or// have just been installed.if (ignoreCodePath(fullPathStr)) {return;}PackageParser.Package p = null;synchronized (mPackages) {p = mAppDirs.get(fullPathStr);}if ((event&REMOVE_EVENTS) != 0) {if (p != null) {removePackageLI(p, true);removedPackage = p.applicationInfo.packageName;removedUid = p.applicationInfo.uid;}}if ((event&ADD_EVENTS) != 0) {if (p == null) {p = scanPackageLI(fullPath,(mIsRom ? PackageParser.PARSE_IS_SYSTEM| PackageParser.PARSE_IS_SYSTEM_DIR: 0) |PackageParser.PARSE_CHATTY |PackageParser.PARSE_MUST_BE_APK,SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,System.currentTimeMillis());if (p != null) {synchronized (mPackages) {updatePermissionsLP(p.packageName, p,p.permissions.size() > 0, false, false);}addedPackage = p.applicationInfo.packageName;addedUid = p.applicationInfo.uid;}}}synchronized (mPackages) {mSettings.writeLP();}}if (removedPackage != null) {Bundle extras = new Bundle(1);extras.putInt(Intent.EXTRA_UID, removedUid);extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,extras, null);}if (addedPackage != null) {Bundle extras = new Bundle(1);extras.putInt(Intent.EXTRA_UID, addedUid);sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,extras, null);}}


这里判断是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,也会进行相类似的处理

这篇关于PackageManagerService的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/864001

相关文章

Android 11 PackageManagerService源码分析(二):Packages.xml详解

1、开篇 在上一篇文章中提到Settings类会在PackageManagerService启动过程中对packages.xml等一些列xml文件进行解析。那么有以下问题: 这些文件记录了什么内容?为什么需要这些文件? 让我们一起通过阅读源码解决这些问题吧。 2、packages.xml文件详解 要在真机上拿到packages.xml殊为不易,所以我这里是在模拟器上通过adb命令拉取了一

Android 11 PackageManagerService源码分析(一):PMS启动的总体流程

本文并非从上帝视角来描述PMS的总体设计和运行逻辑,而是记录本人阅读源码的一个过程。分析到后面才会出总结性的文章。 1、 PMS概述 PMS是Android系统中负责安装包管理的服务,它的主要职责如下: 管理系统安装的所有应用程序,包括升级、安装、卸载根据Intent匹配相应的Activity、Service、Provider和BroadcastReceiver等,并提供相关信息解析应

Android 源码 PackageManagerService 启动流程分析

《Android 源码 installPackage 流程分析》一节着重分析了 apk 安装流程,接下来我们分析 PackageManagerService 启动时都做了些什么? 执行 PackageManagerService main 静态方法;调用 PackageManagerService 类 isFirstBoot() 方法;调用 PackageManagerService 类 get

安卓PackageManagerService scanDirLI流程分析

最近整理PackageMangerService相关代码,追到scanDirLI这部分内容,感觉整个流程非常繁琐,这一步又是安卓开机必经的路径,在PackageMangerService的构造函数中会把所有机器安装的app进行扫描(加密模式下普通用户app不被扫描onlyCore模式),其中会检查apk的合法性,扫描apk中的AndoridManifens.xml的一些属性,以及读取apk的ass

Android P包管理机制之PackageManagerService授予权限流程解析

PackageManagerService中默认给系统app授予相关需要的权限。 PackageManagerService中的systemReady是在SystemServer中执行的。 \frameworks\base\services\java\com\android\server\SystemServer.java /*** Starts a miscellaneous grab

Android服务之PackageManagerService启动源码分析

http://blog.csdn.net/yangwen123/article/details/9464779 版权声明:本文为博主原创文章,未经博主允许不得转载。 了解了Android系统的启动过程的读者应该知道,Android的所有Java服务都是通过SystemServer进程启动的,并且驻留在SystemServer进程中。SystemServer进程在启动时,通

Android9.0 PMS(PackageManagerService)分析

一. system app扫描安装流程 二. 通过pm install 命令程序安装流程

PackageManagerService初始化

参考资料:PMS 第 1 篇 - PackageManagerService 初始化 这个是基于Android 7的,我看的代码是Android 9 前言 PMS 用来管理所有的 package 信息,包括安装、卸载、更新以及解析 AndroidManifest.xml 以组织相应的数据结构,这些数据结构将会被 其他 service 和 application 使用到。 一、PMS的启动

PackageManagerService启动详解(八)之扫描data分区应用安装目录阶段流程分析

PKMS启动详解(八)之BOOT_PROGRESS_PMS_DATA_SCAN_START阶段流程分析 Android PackageManagerService系列博客目录: PKMS启动详解系列博客概要 PKMS启动详解(一)之整体流程分析 PKMS启动详解(二)之怎么通过packages.xml对已安装应用信息进行持久化管理? PKMS启动详解(三)之BOOT_PROGRESS_P