一、systemserver中建立 installer 与 installd 的 socket 联接
// Wait for installdto finished starting up so that it has a chance to
// create criticaldirectories such as /data/user with the appropriate
// permissions. We need this to complete before we initializeother services.
Slog.i(TAG,”Waiting for installd to be ready.”);
installer = new Installer();
installer.ping();
二、systemserver中创建PackageManagerService
pm =PackageManagerService.main(context, installer,
factoryTest!= SystemServer.FACTORY_TEST_OFF, onlyCore);
这里讲installer作为参数传入
三、在PackageManagerService.main中主要功能是构造PackageManagerService 实例,然后添加到 ServiceManager 中。
public static finalIPackageManager main(Context context, boolean factoryTest) {
PackageManagerService m = new PackageManagerService(context, factoryTest);
ServiceManager.addService(“package”, m);
return m;
}
四、PackageManagerService(context, factoryTest) 是 包 管 理服 务 的 主 进 程 。 它 完 成 了对/system/app,/data/app,/system/framework,/data/app-private下的 apk 文件的解析。详细流程如下:
mContext = context;
mFactoryTest =factoryTest;
mOnlyCore =onlyCore;
mNoDexOpt= “eng”.equals(SystemProperties.get(“ro.build.type”));//判断 ro.build.type 是否等于 eng;
mMetrics = new DisplayMetrics();//创建系统显示像素实例
mSettings = new Settings(context);//创建mSetting实例
mSettings.addSharedUserLPw(“android.uid.system”,Process.SYSTEM_UID,
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
mSettings.addSharedUserLPw(“android.uid.phone”,RADIO_UID,
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
mSettings.addSharedUserLPw(“android.uid.log”,LOG_UID,
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
mSettings.addSharedUserLPw(“android.uid.nfc”,NFC_UID,
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
mSettings.addSharedUserLPw(“android.uid.bluetooth”,BLUETOOTH_UID,
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
mSettings.addSharedUserLPw(“android.uid.shell”,SHELL_UID,
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
这个settings是在frameworks/base/services/java/com/android/server/pm/目录下,和系统设置并非同一样东西
Settings(Contextcontext, File dataDir) {
mContext= context;
mSystemDir= new File(dataDir, “system”);
mSystemDir.mkdirs();
FileUtils.setPermissions(mSystemDir.toString(),
FileUtils.S_IRWXU|FileUtils.S_IRWXG
|FileUtils.S_IROTH|FileUtils.S_IXOTH,
-1,-1);
mSettingsFilename= new File(mSystemDir, “packages.xml“);
mBackupSettingsFilename= new File(mSystemDir, “packages-backup.xml“);
mPackageListFilename= new File(mSystemDir, “packages.list“);
FileUtils.setPermissions(mPackageListFilename,0660, SYSTEM_UID, PACKAGE_INFO_GID);
//Deprecated: Needed for migration
mStoppedPackagesFilename= new File(mSystemDir, “packages-stopped.xml”);
mBackupStoppedPackagesFilename= new File(mSystemDir, “packages-stopped-backup.xml”);
}
回到第四步中创建完了Settings实例,紧接着就添加了一系列的权限完成了
五、获取当前缺省的显示像素
WindowManagerwm=(WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
Display d = wm.getDefaultDisplay();
d.getMetrics(mMetrics);
六、建立一个消息循环,用于处理 apk 安装时的请求消息处理(这些请求来自 adbinstall/push,包安装器,android market 下载安装 apk 时发送的)
mHandlerThread.start();
mHandler = newPackageHandler(mHandlerThread.getLooper());
Watchdog.getInstance().addThread(mHandler,mHandlerThread.getName(),WATCHDOG_TIMEOUT);
这个消息循环处理的消息事件如下:
static final int SEND_PENDING_BROADCAST = 1;
static final int MCS_BOUND = 3;
static final int END_COPY = 4;
static final int INIT_COPY = 5;
static final int MCS_UNBIND = 6;
static final int START_CLEANING_PACKAGE = 7;
static final int FIND_INSTALL_LOC = 8;
static final int POST_INSTALL = 9;
static final int MCS_RECONNECT = 10;
static final int MCS_GIVE_UP = 11;
static final int UPDATED_MEDIA_STATUS = 12;
static final int WRITE_SETTINGS = 13;
七、创建/data/data 和/data/app-private等目录
File dataDir =Environment.getDataDirectory();
mAppDataDir = newFile(dataDir, “data”);
mAppInstallDir = newFile(dataDir, “app”);
mAppLibInstallDir =new File(dataDir, “app-lib”);
mAsecInternalPath =new File(dataDir, “app-asec”).getPath();
mUserAppDataDir =new File(dataDir, “user”);
mDrmAppPrivateInstallDir= new File(dataDir, “app-private”);
sUserManager = newUserManagerService(context, this,
mInstallLock, mPackages);
八、从/system/etc/permission目录读取 permissions
readPermissions();
readPermissions函数中的具体步骤
VoidreadPermissions()
{
//解析/system/etc/permission/下的*.xml 文件,获取权限信息
//最后解析该目录下的 platform.xml 文件,使该文件里的权限在栈顶出现,以便预先处理
//这个文件记录了系统级应用的 uid 及其拥有的权限
File permFile = newFile(Environment.getRootDirectory(),”etc/permissions/platform.xml”);
readPermissionsFromXml(permFile);
}
注:getRootDirectory返回的是/system目录
DIR_ANDROID_ROOT =getDirectory(ENV_ANDROID_ROOT, “/system”);
public static FilegetRootDirectory() {
return DIR_ANDROID_ROOT;
}
readPermissionsFromXml函数的功能如下:
通过 xml 解 析 器 解 释 *.xml 文 件 , 提 取 标 签 名 “ group” , “permission” ,”assign-permission”,”library”,”feature”并进行相应处理。在platform.xml 中对底层的系统用户和组ID(group ids)同上层的由平台管理的 permission 名字之间进行了关系映射,使它们关联起来。当一个应用被授予某个权限后,同时属于已知的组 ID,这个应用就可以进行允许这个组的文件系统操作,如(read,write,execute )。这里记录了一些系统级的应用的 uid 对应的permission
group:安装到系统中的所有 APK都具备的组 ID。
permission:可以指定一个权限与几个组ID 对应。当一个 APK 被授予这个权限时,它也同时属于这几个组。
assign-permission:把一个权限赋予一个UID,当进程使用这个 UID 运行时,就具备了这个权限。
library:为系统添加一些扩展库用的。对应的.jar文件放在/system/framework/目录下。比如Google Map 相关的库。
feature : 每 添 加 一 个硬 件 , 都 要 增 加 对 应 的 feature 。 将 以 上 解 析 的 结 果 对 应 放 入
九、readLPw()
mRestoredSettings =mSettings.readLPw(this, sUserManager.getUsers(false),mSdkVersion, mOnlyCore);
mRestoredSettings = mSettings.readLPw(this, sUserManager.getUsers(false), mSdkVersion, mOnlyCore);
判断/data/system/packages.xml文件是否存在,如果不存在则返回 false,如果存在则进行解析
在系统第一次启动时packages.xml 文件是不存在的,由 writeLP()创建该文件,并将该文件写到 nand 上,下次开机会直接读取并解析这个文件。
解析的过程即是按照xml定义的标签,将对应的属性和值添加到全局列表中。packages.xml 文件中记录了系统安装的所有 apk 的属性权限的信息,当系统中的 apk安装,删除或升级时,改文件就会被更新。
<permissions>标签定义了目前系统中定义的所有权限。主要分为两类: 系 统 定 义 的(package 属性为 Android)和 APK 定义的(package 属性为 APK 的包名)
sharedUserId/userId:Android系统启动一个普通的 APK 时,会为这个 APK 分配一个独立的UID , 这 就 是 userId 。 如 果 APK 要 和 系 统 中 其 它 APK使 用 相 同 的 UID 的 话 , 那 就 是sharedUserId。
perms:APK的 AndroidManifest.xml 文件中,每使用一个<uses-permission>标签,<perms>标签中就会增加一项。
<shared-user>代表一个共享UID , 通 常 , 共 同 实 现 一 系 列 相 似 功 能 的 APK 共 享 一 个UID。<perms>标签中的 权限代表了这个共享 UID 的权限,所有使用的同一个共享 UID 的APK 运行在同一进程中,这个进程的 UID 就是这个共享 UID,这些 APK 都具有这个共享UID 的权限。
name:共享 UID 的名字,在APK 的 Android:sharedUserId 属性中使用。
userId:使用这个共享 UID的所有 APK 运行时所在的进程的 UID。
十、判断是否使用了自定义的intentresolver
StringcustomResolverActivity = Resources.getSystem().getString(
R.string.config_customResolverActivity); //这个属性配置在frameworks/base/core/res/res/values/config.xml中
if(TextUtils.isEmpty(customResolverActivity)) {
customResolverActivity =null;//如果配置文件中为空
} else {
mCustomResolverComponentName =ComponentName.unflattenFromString(
customResolverActivity);
}
十一、是否需要做dexopt
需要做dexopt一共有以下几类:
- 所有在java.boot.class.path中的内容都被默认为在zygote阶段已经做过dexopt,所以当前阶段跳过
- 所有external libraries必须做dexopt
- 所有的/framework下的apk和jar都需要做dexopt,但是跳过framework-res.apk和core-libart.jar
十二、启 动AppDirObserver 线 程
主要 监 测/system/framework , /system/priv-app, /system/app , /vendor/app,/data/app,/data/app-private 几个目录的事件 ,AppDirObserver继承于FileObserver,FileObserver中有一些native方法,从而达到监听底层文件状态变化的event,这里主要监听的是 add 和 remove 事件。对于目录监听底层通过 inotify机制实现,inotify 是在 2.6.13中引入的新功能,它为用户态监视文件系统的变化提供了强大的支持;inotify 是一种文件系统的变化通知机制,如文件增加 ,删除等事件可以立刻让用户态得知
mFrameworkInstallObserver= new AppDirObserver(frameworkDir.getPath(),OBSERVER_EVENTS, true, false);
mFrameworkInstallObserver.startWatching();
scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED,
scanMode | SCAN_NO_DEX, 0);
当监测到事件发生时该线程做何处理呢?
十二、清理系统packages
清理策略如下:
mSettings.mPackages.values().iterator();是当前package的全集
1. 不是系统app,跳过不予处理
if ((ps.pkgFlags& ApplicationInfo.FLAG_SYSTEM) == 0) {
continue;
}
2.如果package存在mPackages中,且不是isDisabledSystemPackageLPr,不予处理
if ((ps.pkgFlags& ApplicationInfo.FLAG_SYSTEM) == 0) {
continue;
}
3.如果package存在mPackages中,且是isDisabledSystemPackageLPr,说明是OTA加进来的,需要删除
finalPackageParser.Package scannedPkg = mPackages.get(ps.name);
if (scannedPkg !=null) {
if(mSettings.isDisabledSystemPackageLPr(ps.name)) {
Slog.i(TAG, “Expecting better updatdsystem app for ” + ps.name+ “; removing system app”);
removePackageLI(ps, true);
}
continue;
}
4.既不在mPackages中,也不是isDisabledSystemPackageLPr,说明这个package已经不存在了,删除
5.不在mPackages中,但是isDisabledSystemPackageLPr,加入到possiblyDeletedUpdatedSystemApps中
if(!mSettings.isDisabledSystemPackageLPr(ps.name)) {
psit.remove();
Stringmsg = “System package ” + ps.name+ ” no longer exists; wipingits data”;
reportSettingsProblem(Log.WARN, msg);
removeDataDirsLI(ps.name);
} else {
final PackageSetting disabledPs =mSettings.getDisabledSystemPkgLPr(ps.name);
if (disabledPs.codePath == null ||!disabledPs.codePath.exists()) {
possiblyDeletedUpdatedSystemApps.add(ps.name);
}
}
十三、清除不完整的、临时的包等
//look for anyincomplete package installations
ArrayList<PackageSetting>deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
//clean up list
for(int i = 0; i< deletePkgsList.size(); i++) {
//cleanup here
cleanupInstallFailedPackage(deletePkgsList.get(i));
}
//delete tmp files
deleteTempPackageFiles();
// Remove any shareduserIDs that have no associated packages
mSettings.pruneSharedUsersLPw();
十四、在解析完以上目录下的 apk 后,更新应用的权限
updatePermissionsLPw(null,null, UPDATE_PERMISSIONS_ALL | (regrantPermissions
?(UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL): 0));
十五、生成/更新packages.xml 和 packages.list 文 件
mSettings.writeLPr();
以上是包管理服务在系统启动时做的全部工作。