PackageManagerService启动流程
2017-03-14 17:29
393 查看
从这里开始将开始介绍下android的几个重要的进程:WindowManagerService(WMS)、ActivityManagerService(AMS)、PackagerManagerService(简称PMS)。好多文章都是从AMS讲起,本文为了减轻读者的压力就先从简单的PMS开始。众所周知,android的三大管家都是独立的进程运行的,基本上都是在ServerThread进程运行之后逐个起来,但是PMS在各个应用在Launcher中的显示更为重要,因为没有PMS,系统的APK根本无法显示出来,因为没有安装。这里有个地方要澄清下,android系统并不是安装的APK的会永远存在,其实不是,每次开机系统都要去扫描/system/etc/permission和/data/system/packages.xml获取应用程序和权限,从而进行APK包的安装流程,最后安装的程序才显示到界面上。PWS的初始化都放到了构析函数中:
PackageManagerService的初始化工作都是在它的构造函数中完成的,主要分两个大步骤:1、扫描xml文件并解析成对应的数据结构; 2、扫描apk文件并解析成对应的数据结构并执行安装,主要流程如下:
1、建立并启动PackageHandler消息循环,用于处理apk安装卸载APK等请求,如adb
installpackage installer安装apk时就会发送消息到PMS的PackageHandler中进行处理。
mHandlerThread.start();
mHandler= newPackageHandler(mHandlerThread.getLooper());
手动安装APK调用的是installPackage函数,接着就是通过mHandler发送到handleMessage中进行处理的。这里讲的是开机后的APK自动安装流程。
2、通过调用readPermissions()函数解析/system/etc/permission下的xml文件,主要是platform.xml,建立permission和gid之间的关系,可以指定一个权限与几个组对应,当一个apk被授予这个权限时它也同时属于这几个组,readPermission(parser,perm);给一些底层用户分配一些权限,如shell授予各种permission,把一个权限赋予一个uid,当apk使用这个uid运行时,就具备了这个权限系统增加的一些应用需要link的扩展的jar库。
3、通过调用mSettings.readLPw函数检查/data/system/packages.xml是否存在,里面记录了系统的permission,以及每个apk的name,codePath,flags,ts,version,userid等,这些信息主要是通过apk安装的时候解析AndroidManifest.xml获取到的,解析完apk后将更新信息写入这个文件并保存,下次开机直接从里面读取相关信息添加到内存相关列表中,当有apk安装,升级,删除等操作时会更新这个文件;格式如下:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<packages>
<last-platform-version internal="15"external="15" />
<permission-trees />
<permissions>
<item name="android.permission.SHUTDOWN"package="android" protection="3"/>
<item name="android.permission.WRITE_CONTACTS"package="android" protection="1"/>
<item name="android.permission.VIBRATE"package="android" />
</permissions>
<package name="com.android.contacts"codePath="/system/app/Contacts.apk"nativeLibraryPath="/data/data/com.android.contacts/lib"flags="1" ft="157e38c3c28"it="157e38c3c28"ut="157e38c3c28" version="15" sharedUserId="10000">
<sigs count="1">
<cert index="2"/>
</sigs>
</package>
<package name="com.android.calendar"codePath="/system/app/Calendar.apk"nativeLibraryPath="/data/data/com.android.calendar/lib"flags="1" ft="157e38bf9c0"it="157e38bf9c0"ut="157e38bf9c0" version="15" userId="10005">
<sigs count="1">
<cert index="0"/>
</sigs>
</package>
<shared-user name="android.uid.shared"userId="10000">
<sigs count="1">
<cert index="2"/>
</sigs>
<perms>
<item name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<item name="android.permission.REBOOT"/>
</perms>
</shared-user>
<shared-user name="android.uid.log"userId="1007">
<perms />
</shared-user>
</packages>
这里注明下xml的解析用的都是pull xml解析方式,包括布局文件的解析也是,可见安卓系统是多么的喜欢Pull解析方式。
4、启动多个AppDirObserver线程监测/system/framework,/system/app,/data/app/data/app-private目录的事件,主要监听add和remove事件,对于目录监听底层通过innotify机制实现,inotify是一种文件系统的变化通知机制如文件增加、删除等事件可以立刻让用户态得知,它为用户态监视文件系统的变化提供了强大的支持,当有addevent时调用scanPackageLI(File,int,int)处理,当有removeevent时调用removePackageLI处理;其开启的监听线程代码如下:
mFrameworkInstallObserver =newAppDirObserver(
frameworkDir.getPath(),OBSERVER_EVENTS,true,false);
mFrameworkInstallObserver.startWatching();
scanDirLI(frameworkDir,PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanMode |SCAN_NO_DEX,0);
File privilegedAppDir =new File(Environment.getRootDirectory(),"priv-app");
mPrivilegedInstallObserver =new AppDirObserver(
privilegedAppDir.getPath(),OBSERVER_EVENTS,true,true);
mPrivilegedInstallObserver.startWatching();
scanDirLI(privilegedAppDir,PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED,scanMode,0);
File systemAppDir =new File(Environment.getRootDirectory(),"app");
mSystemInstallObserver =new AppDirObserver(
systemAppDir.getPath(),OBSERVER_EVENTS,true,false);
mSystemInstallObserver.startWatching();
scanDirLI(systemAppDir,PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR,scanMode,0);
File vendorAppDir =new File("/vendor/app");
mVendorInstallObserver =new AppDirObserver(
vendorAppDir.getPath(),OBSERVER_EVENTS,true,false);
mVendorInstallObserver.startWatching();
5、 调用scanDirLI函数启动apk解析,解析目录/system/framework、/system/app、/vendor/app、/data/app、/data/app-private下的APK文件,解析后的数据放到PackageParser.Package中。调用流程如下:scanDirLI->scanPackageLI->PackageParser.parsePackage(),parsePackage函数返回的是一个PackageParser.Package结构类,最后会把引用给PackageSetting的PackageParser.Package pkg变量。这里是整个流程最关键的一步,因为前面所做的事情都是为了把包内容等存储到PackageSetting的PackageParser.Package变量中,为的是接着Lancher的显示或者其他应用程序获取应用信息都是通过这个变量进行获取。另外一个要提到的是AndroidMenifest的versionCode属性,当一个APK即存在于/system/app或者/data/app/中时,那么系统将以versionCode值大的那个APK为准。
比如我们经常用到的获取应用列表的函数queryIntentActivities,就是通过PackageManger调用到PMS的queryIntentActivities函数,而queryIntentActivities函数最终也是获取了PackageSetting的PackageParser.Package变量,从而得到APK的相关信息。
7、通过updatePermissionsLPw函数里面的grantPermissionsLPw函数给apk赋权限,实际上也是把相关的权限值添加到PackageSetting的grantedPermissions变量中,
grantedPermissions是HashSet<String>类型的变量,最后APP或者系统其他地方需要获取某个APK的权限,就可以通过PackageSetting类获取了,这里的数据结构设计得比较巧妙,值得深入学习。
8、解析完所有APK相关xml数据后,scanPackageLI函数接着继续调用mInstaller.install(packageName,uid,uid, seinfo)执行正式的安装流程。
9、 最后在构析函数中调用mSettings.writeLPr();函数将解析出的Package的相关信息更新到相关全局变量和文件。主要是把前面解析出来的信息重新更新到原先的文件,因为这时的APK信息可能跟packages.xml的数据不一样了。
PackageManagerService的初始化工作都是在它的构造函数中完成的,主要分两个大步骤:1、扫描xml文件并解析成对应的数据结构; 2、扫描apk文件并解析成对应的数据结构并执行安装,主要流程如下:
1、建立并启动PackageHandler消息循环,用于处理apk安装卸载APK等请求,如adb
installpackage installer安装apk时就会发送消息到PMS的PackageHandler中进行处理。
mHandlerThread.start();
mHandler= newPackageHandler(mHandlerThread.getLooper());
手动安装APK调用的是installPackage函数,接着就是通过mHandler发送到handleMessage中进行处理的。这里讲的是开机后的APK自动安装流程。
2、通过调用readPermissions()函数解析/system/etc/permission下的xml文件,主要是platform.xml,建立permission和gid之间的关系,可以指定一个权限与几个组对应,当一个apk被授予这个权限时它也同时属于这几个组,readPermission(parser,perm);给一些底层用户分配一些权限,如shell授予各种permission,把一个权限赋予一个uid,当apk使用这个uid运行时,就具备了这个权限系统增加的一些应用需要link的扩展的jar库。
3、通过调用mSettings.readLPw函数检查/data/system/packages.xml是否存在,里面记录了系统的permission,以及每个apk的name,codePath,flags,ts,version,userid等,这些信息主要是通过apk安装的时候解析AndroidManifest.xml获取到的,解析完apk后将更新信息写入这个文件并保存,下次开机直接从里面读取相关信息添加到内存相关列表中,当有apk安装,升级,删除等操作时会更新这个文件;格式如下:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<packages>
<last-platform-version internal="15"external="15" />
<permission-trees />
<permissions>
<item name="android.permission.SHUTDOWN"package="android" protection="3"/>
<item name="android.permission.WRITE_CONTACTS"package="android" protection="1"/>
<item name="android.permission.VIBRATE"package="android" />
</permissions>
<package name="com.android.contacts"codePath="/system/app/Contacts.apk"nativeLibraryPath="/data/data/com.android.contacts/lib"flags="1" ft="157e38c3c28"it="157e38c3c28"ut="157e38c3c28" version="15" sharedUserId="10000">
<sigs count="1">
<cert index="2"/>
</sigs>
</package>
<package name="com.android.calendar"codePath="/system/app/Calendar.apk"nativeLibraryPath="/data/data/com.android.calendar/lib"flags="1" ft="157e38bf9c0"it="157e38bf9c0"ut="157e38bf9c0" version="15" userId="10005">
<sigs count="1">
<cert index="0"/>
</sigs>
</package>
<shared-user name="android.uid.shared"userId="10000">
<sigs count="1">
<cert index="2"/>
</sigs>
<perms>
<item name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<item name="android.permission.REBOOT"/>
</perms>
</shared-user>
<shared-user name="android.uid.log"userId="1007">
<perms />
</shared-user>
</packages>
这里注明下xml的解析用的都是pull xml解析方式,包括布局文件的解析也是,可见安卓系统是多么的喜欢Pull解析方式。
4、启动多个AppDirObserver线程监测/system/framework,/system/app,/data/app/data/app-private目录的事件,主要监听add和remove事件,对于目录监听底层通过innotify机制实现,inotify是一种文件系统的变化通知机制如文件增加、删除等事件可以立刻让用户态得知,它为用户态监视文件系统的变化提供了强大的支持,当有addevent时调用scanPackageLI(File,int,int)处理,当有removeevent时调用removePackageLI处理;其开启的监听线程代码如下:
mFrameworkInstallObserver =newAppDirObserver(
frameworkDir.getPath(),OBSERVER_EVENTS,true,false);
mFrameworkInstallObserver.startWatching();
scanDirLI(frameworkDir,PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanMode |SCAN_NO_DEX,0);
File privilegedAppDir =new File(Environment.getRootDirectory(),"priv-app");
mPrivilegedInstallObserver =new AppDirObserver(
privilegedAppDir.getPath(),OBSERVER_EVENTS,true,true);
mPrivilegedInstallObserver.startWatching();
scanDirLI(privilegedAppDir,PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED,scanMode,0);
File systemAppDir =new File(Environment.getRootDirectory(),"app");
mSystemInstallObserver =new AppDirObserver(
systemAppDir.getPath(),OBSERVER_EVENTS,true,false);
mSystemInstallObserver.startWatching();
scanDirLI(systemAppDir,PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR,scanMode,0);
File vendorAppDir =new File("/vendor/app");
mVendorInstallObserver =new AppDirObserver(
vendorAppDir.getPath(),OBSERVER_EVENTS,true,false);
mVendorInstallObserver.startWatching();
5、 调用scanDirLI函数启动apk解析,解析目录/system/framework、/system/app、/vendor/app、/data/app、/data/app-private下的APK文件,解析后的数据放到PackageParser.Package中。调用流程如下:scanDirLI->scanPackageLI->PackageParser.parsePackage(),parsePackage函数返回的是一个PackageParser.Package结构类,最后会把引用给PackageSetting的PackageParser.Package pkg变量。这里是整个流程最关键的一步,因为前面所做的事情都是为了把包内容等存储到PackageSetting的PackageParser.Package变量中,为的是接着Lancher的显示或者其他应用程序获取应用信息都是通过这个变量进行获取。另外一个要提到的是AndroidMenifest的versionCode属性,当一个APK即存在于/system/app或者/data/app/中时,那么系统将以versionCode值大的那个APK为准。
比如我们经常用到的获取应用列表的函数queryIntentActivities,就是通过PackageManger调用到PMS的queryIntentActivities函数,而queryIntentActivities函数最终也是获取了PackageSetting的PackageParser.Package变量,从而得到APK的相关信息。
7、通过updatePermissionsLPw函数里面的grantPermissionsLPw函数给apk赋权限,实际上也是把相关的权限值添加到PackageSetting的grantedPermissions变量中,
grantedPermissions是HashSet<String>类型的变量,最后APP或者系统其他地方需要获取某个APK的权限,就可以通过PackageSetting类获取了,这里的数据结构设计得比较巧妙,值得深入学习。
8、解析完所有APK相关xml数据后,scanPackageLI函数接着继续调用mInstaller.install(packageName,uid,uid, seinfo)执行正式的安装流程。
9、 最后在构析函数中调用mSettings.writeLPr();函数将解析出的Package的相关信息更新到相关全局变量和文件。主要是把前面解析出来的信息重新更新到原先的文件,因为这时的APK信息可能跟packages.xml的数据不一样了。
相关文章推荐
- Android PackageManagerService流程详细分析(一)之启动
- PackageManagerService启动流程源码解析
- Android PackageManagerService启动流程分析
- PackageManagerService启动流程源码解析
- PackageManagerService的启动过程分析
- Android应用程序管理服务启动过程浅析(PackageManagerService)
- PackageManagerService 分析及执行流程
- Android PackageManagerService加载apk流程
- Android PackageManagerService流程详细分析(五)之packages
- PackageManagerService的启动过程分析
- Android ActivityManagerService(AMS)的启动分析 << 代码讲的比较细致,在了解主要流程后再看这篇
- PackageManagerService installPackage 流程
- Android L-preview PackageManagerService启动、安装和卸载分析
- PackageManagerService启动过程
- ActivityManagerService启动流程