学到的才是自己的,干活都是扯淡
1. 应用的安装
PackageManagerService负责管理应用的安装。在第14章中讲到,SystemService会启动PackageManagerService,那么我们就从SystemService启动PackageManagerService开始分析。
1.1 PackageManagerService.main
创建PackageManagerService对象。
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java :
1.2 PackageManagerService.PackageManagerService
PackageManagerService的构造函数。
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java :
1.3 Settings.readLPw
读取保存的应用信息。
frameworks/base/services/core/java/com/android/server/pm/Settings.java :
1.4 Settings.readPackageLPw
读取package信息。
frameworks/base/services/core/java/com/android/server/pm/Settings.java :
1.5 Setttings.addPackageLPw
为该package分配UID,创建保存package信息的PackageSetting对象。
frameworks/base/services/core/java/com/android/server/pm/Settings.java :
在系统中保留指定的UID。这里可以看出,一共可以分配10000个uid给应用程序,小于10000的uid是分配给特权用户的。这些特权用户的uid可以通过共享的形式给其它应用使用。例如,一个想修改系统时间的的应用可以共享”android.uid.system”的特权用户的uid,即在配置文件中将它的android:sharedUserId的属性设置为“android.uid.system”。uid不能重复,但是shareduid是可以共享的。
frameworks/base/services/core/java/com/android/server/pm/Settings.java :
到这里,应用的uid已经分配完成。下面回到1.3,看如何读取shareduid。
1.6 Setttings.readSharedUserLPw
读取共享uid。
frameworks/base/services/core/java/com/android/server/pm/Settings.java :
1.7 Settings.addSharedUserLPw
添加共享用户。
frameworks/base/services/core/java/com/android/server/pm/Settings.java :
在1.4中,mPendingPackages保存了一些使用共享用户id的package。现在已经解析完毕共享用户的信息,在1.3 readLPw函数中将会处理这些package了。
frameworks/base/services/core/java/com/android/server/pm/Settings.java :
1.8 PackageManagerService.scanDirLI
到此,PackageManagerService已经将上一次保存的应用信息恢复完毕,在1.2中接下来需要进一步安装各个目录下的应用。
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java :
1.9 PackageManagerService.scanPackageLI
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java :
1.10 PackageParser.parsePackage
frameworks/base/core/java/android/content/pm/PackageParser.java :
1.11 PackageParser.parseMonolithicPackage
frameworks/base/core/java/android/content/pm/PackageParser.java :
1.12 PackageParser.parseBaseApk
frameworks/base/core/java/android/content/pm/PackageParser.java :
frameworks/base/core/java/android/content/pm/PackageParser.java :
一个应用可以申请多个权限,应用权限是和用户组ID对应的。应用申请权限就是获得该用户组id的过程。
1.13
framework/base/core/java/android/content/pm/PackageParser.java
1.14 下面步骤笼统讲一下
到这里,PackageManagerService已经解析完成一个apk文件。下面回到1.9 scanPackageLI中,继续下面的工作。1.9步中会调用重载函数scanPackageLI继续解析获得的package。重载函数会调用scanPackageDirtyLI来分析package。
这一步会为package分配id,当然该package可能使用的是一个共享id。首先,每个package信息会被保存在一个PackageSetting对象中,然后将其放到mPackages这个HashMap中。
因为在前面步骤中已经从上一次安装的应用信息中读取了一些package信息,所以需要先在HashMap中确定一下这个新解析的应用是否是已经在mPackages中。如果已经存在,说明这是一个老应用,就直接将PackageSetting 返回。如果不在,则新建一个PackageSetting,下面开始为它分配uid:
1. 使用共享id。将pkg的uid设置为想要共享的uid。
2. 使用原来的uid。禁用的系统程序使用它原来的uid。
3. 使用新的uid。创建一个新的uid给pkg。
4. 使用first application uid。所有应用使用同一个uid。
下面来看一下如何为新的应用分配新uid。mUserIds管理了所有的分配给用户的uid,这里会在规定的范围内找到一个uid分配。
到此为止,所有的安装了应用都存在PackageManagerService的mPackages中,下面需要依次为这些应用分配权限。在设备/system/etc/permissions/platform.xml
文件中,表述了该设备的资源访问权限列表。如:
|
|
gid指明了该资源权限所在的用户组,当然一个权限可以拥有多个用户组。应用获取权限就是加入相应的用户组。Package的申请的权限已经保存到它对应的PackageSetting对象中,如果当前package使用的是共享uid,则它获得权限与它共享的linux用户的资源权限相同。对于有自己独立uid的应用,它会首先获得一组默认的用户权限,这是所有应用都具有的基本权限。然后会一一验证应用申请的权限是否合法,如果合法,则会为其增加该项权限。
现在,应用已经被安装、分配uid和分配权限,接下来需要将这些应用的信息保存下来以备下次使用。保存的位置就是/data/system/packages.xml
。注意,在保存uid时,userId和sharedUserId只能有一个。
Android系统就是通过用户id和用户组id来限制应用的资源访问权限,防止破坏其它应用的数据。分配的uid和gid会在创建应用进程时使用,是该进程在特定的用户组下运行。