这个系列会分成《App的安装过程》、《App桌面图标显示过程》、《Activity的启动过程》和《Activity渲染过程》四篇文章,来分析从整个应用安装,到用户点击图标并显示首页,整个源码流程是如何调用的。
我们应用程序包的安装需要通过PackageManagerService来操作,而它早在系统启动SystemServer时便注册好了,SystemServer则由init进程启动。
public static void main(String[] args) {
new SystemServer().run();//执行run
}
//运行
private void run() {
......
//创建系统上下文
createSystemContext();
//创建SystemServiceManager,用来管理各种系统service
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// 启动服务
try {
//启动服务,创建PMS,AMS等
startBootstrapServices();
// 启动核心服务
startCoreServices();
//启动IputManagerService等
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
}
}
//创建系统上下文
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}
初始化系统上下文时,生成了ActivityThread ,它相当于系统的主线程,我们看systemMain方法。
public static ActivityThread systemMain() {
if (!ActivityManager.isHighEndGfx()) {
HardwareRenderer.disable(true);
} else {
HardwareRenderer.enableForegroundTrimming();
}
//构造ActivityThread
ActivityThread thread = new ActivityThread();
//true表示系统应用
thread.attach(true);
return thread;
}
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
//不是系统进程
if (!system) {
......
} else {
android.ddm.DdmHandleAppName.setAppName("system_process",UserHandle.myUserId());
try {
//创建Instrumentation
mInstrumentation = new Instrumentation();
//创建上下文
ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);
//创建Application
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
mInitialApplication.onCreate();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate Application():" + e.toString(), e);
}
}
当调用为系统线程时,attach会执行else代码,创建Instrumentation和上下文,我们接着看启动包管理器服务的方法startBootstrapServices。
private void startBootstrapServices() {
//该对象负责与底层通信,进行具体安装卸载等操作
mInstaller = mSystemServiceManager.startService(Installer.class);
//开启ActivityManagerService,对比PowerManagerService等,实际上ActivityManagerService不是一个SystemService,而是Binder,ActivityManagerService.Lifecycle才是SystemService
mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
mActivityManagerService.initPowerManagement();
//开启mDisplayManagerService
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
String cryptState = SystemProperties.get("vold.decrypt");
if (ENCRYPTING_STATE.equals(cryptState)) {
Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
mOnlyCore = true;
} else if (ENCRYPTED_STATE.equals(cryptState)) {
Slog.w(TAG, "Device encrypted - only parsing core apps");
mOnlyCore = true;
}
//构建PackageManagerService
mPackageManagerService = PackageManagerService.main(mSystemContext, mInstaller,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());
AttributeCache.init(mSystemContext);
mActivityManagerService.setSystemProcess();
}
SystemServer启动了许多服务,PackageManagerService通过main方法创建,并将系统上下文和mInstaller工具类传递进去。
public static final PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
//构造PMS对象
PackageManagerService m = new PackageManagerService(context, installer,factoryTest, onlyCore);
//注册到ServiceManager中
ServiceManager.addService("package", m);
return m;
}
构造PMS对象,并将服务对象添加到ServiceManager中。PackageManagerService的构造方法代码比较多,我们分块分析。
//pms启动后对系统中的特定目录进行扫描,获取信息以便进行应用程序安装
public PackageManagerService(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
//向事件日志写入事件,标识PackageManagerService启动时间
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,SystemClock.uptimeMillis());
//版本检查
if (mSdkVersion <= 0) {
Slog.w(TAG, "**** ro.build.version.sdk not set!");
}
mContext = context;
//开机是否工厂模式
mFactoryTest = factoryTest;
//是否启动内核
mOnlyCore = onlyCore;
//如果编译版本为eng,则不要进行dex优化
mLazyDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
//构造DisplayMetrics以便获得尺寸数据
mMetrics = new DisplayMetrics();
//构造Settings存储系统安装时的信息
mSettings = new Settings(context);
//添加一些用户id
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);
//是否在不同的进程中
String separateProcesses = SystemProperties.get("debug.separate_processes");
if (separateProcesses != null && separateProcesses.length() > 0) {
if ("*".equals(separateProcesses)) {
mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
mSeparateProcesses = null;
Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
} else {
mDefParseFlags = 0;
mSeparateProcesses = separateProcesses.split(",");
Slog.w(TAG, "Running with debug.separate_processes: "
+ separateProcesses);
}
} else {
mDefParseFlags = 0;
mSeparateProcesses = null;
}
当一个新应用程序,要安装并运行在Linux中时,系统需要先为其开辟一个用户空间,并分配Linux独立用户id或共享用户id,而这个创建和分配的业务操作,由PackageMangerService来完成。
每当系统重启时,都需要对程序做一次重新安装,为了提高效率,程序在第一次安装时,PackageMangerService会将安装信息进行保存,以便再次安装时进行快速恢复。Settings就是用来保存这些信息的对象。
//赋值mInstaller
mInstaller = installer;
//测量显示对象
getDefaultDisplayMetrics(context, mMetrics);
SystemConfig systemConfig = SystemConfig.getInstance();
mGlobalGids = systemConfig.getGlobalGids();
mSystemPermissions = systemConfig.getSystemPermissions();
mAvailableFeatures = systemConfig.getAvailableFeatures();
synchronized (mInstallLock) {
// writer
synchronized (mPackages) {
//启动处理线程
mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
mHandlerThread.start();
//启动PackageHandler
mHandler = new PackageHandler(mHandlerThread.getLooper());
Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
//获取data目录
File dataDir = Environment.getDataDirectory();
//获取到/data/data目录
mAppDataDir = new File(dataDir, "data");
//获取到/data/app目录,即第三方应用的安装目录
mAppInstallDir = new File(dataDir, "app");
//获取到/data/app-lib目录
mAppLib32InstallDir = new File(dataDir, "app-lib");
//获取到/data/app-asec目录
mAsecInternalPath = new File(dataDir, "app-asec").getPath();
//获取到/data/user目录
mUserAppDataDir = new File(dataDir, "user");
//获取到/data/app-private目录,受DRM保护
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
//构造UserManagerService,mPackages是一个Map,存储了Package
sUserManager = new UserManagerService(context, this,mInstallLock, mPackages);
//读取设置的权限
ArrayMap permConfig= systemConfig.getPermissions();
for (int i=0; i libConfig = systemConfig.getSharedLibraries();
for (int i=0; i
首先扫描了各类型的安装目录,以备后面程序的安装,我们看到构造UserManagerService对象时,传入了mPackages对象,它是一个Map,保存了安装应用的信息,在readLPw传给mSettings进行读取恢复,如果读取解析失败,则重新解析安装并保存以便下一次启动恢复,readLPw读取,而后面的mSettings.writeLPr则是保存。
那么我们看readLPw是如何来解析安装包数据的。先看mSettings的构造方法。
Settings(Context context) {
//dada/data
this(context, Environment.getDataDirectory());
}
Settings(Context context, File dataDir) {
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);
//packages.xml保存了上一次的应用安装信息
mSettingsFilename = new File(mSystemDir, "packages.xml");
//对mSettingsFilename的备份
mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
//存储包名
mPackageListFilename = new File(mSystemDir, "packages.list");
FileUtils.setPermissions(mPackageListFilename, 0660, SYSTEM_UID, PACKAGE_INFO_GID);
mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
}
安装包的信息数据是通过xml来进行存储的,由代码知道,源文件和备份文件完整的相对路径为dada/dada/system/xxx.xml。这里对缓存又进行了一次备份,是起到了双次检测的效果。
//读取上一次保存的应用安装信息
boolean readLPw(PackageManagerService service, List users, int sdkVersion, boolean onlyCore) {
FileInputStream str = null;
//备份文件存在,即packages-backup.xml文件
if (mBackupSettingsFilename.exists()) {
try {
str = new FileInputStream(mBackupSettingsFilename);//读取备份文件
mReadMessages.append("Reading from backup settings file\n");
PackageManagerService.reportSettingsProblem(Log.INFO, "Need to read from backup settings file");
//清除源文件,即packages.xml文件
if (mSettingsFilename.exists()) {
mSettingsFilename.delete();
}
} catch (java.io.IOException e) {
// We'll try for the normal settings file.
}
}
mPendingPackages.clear();
mPastSignatures.clear();
try {
//备份文件不存在
if (str == null) {
//源文件不存在
if (!mSettingsFilename.exists()) {
mReadMessages.append("No settings file found\n");
PackageManagerService.reportSettingsProblem(Log.INFO, "No settings file; creating initial state");
mInternalSdkPlatform = mExternalSdkPlatform = sdkVersion;
mFingerprint = Build.FINGERPRINT;
return false;
}
str = new FileInputStream(mSettingsFilename);//读取源文件存在
}
XmlPullParser parser = Xml.newPullParser();//开始pull解析
parser.setInput(str, null);
对缓存文件的检测可以分为3种情况:
- 如果备份存在,源文件也存在,则读取备份文件并且删除源文件,后面writeLPr会重新保存一份新的源文件;
- 如果备份不存在,源文件不存在,则恢复上一次失败,结束事件;
- 如果备份不存在,源文件存在,则读取源文件;
文件读取成功,会构造XmlPullParser 对象来解析xml文件。xml保存了上一次安装的许多数据,这里贴些关键的标签,其中package和shared-user标签,保存了应用程序和LInux用户Id相关的信息。
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) {
;
}
//开始标签
if (type != XmlPullParser.START_TAG) {
mReadMessages.append("No start tag found in settings file\n");
PackageManagerService.reportSettingsProblem(Log.WARN,
"No start tag found in package manager settings");
Slog.wtf(PackageManagerService.TAG,
"No start tag found in package manager settings");
return false;
}
//开始解析
int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String tagName = parser.getName();
//以包名为根标签,保存了每个应用上次安装的信息
if (tagName.equals("package")) {
//读取包信息,获取上一次分配的Linux用户id
readPackageLPw(parser);
} else if (tagName.equals("permissions")) {
readPermissionsLPw(mPermissions, parser);
} else if (tagName.equals("permission-trees")) {
readPermissionsLPw(mPermissionTrees, parser);
//shared-user上一次分配的共享linux用户
} else if (tagName.equals("shared-user")) {
//获取上一次分配的共享Linux用户id
readSharedUserLPw(parser);
} else if (tagName.equals("preferred-packages")) {
// no longer used.
} else if (tagName.equals("preferred-activities")) {
xml以package为根标签保存了一个应用的完整信息,所以,readPackageLPw从package标签开始解析包数据。
//解析package标签
private void readPackageLPw(XmlPullParser parser) throws XmlPullParserException, IOException {
String name = null;
String realName = null;
String idStr = null;
String sharedIdStr = null;
String codePathStr = null;
String resourcePathStr = null;
String legacyCpuAbiString = null;
String legacyNativeLibraryPathStr = null;
String primaryCpuAbiString = null;
String secondaryCpuAbiString = null;
String cpuAbiOverrideString = null;
String systemStr = null;
String installerPackageName = null;
String uidError = null;
int pkgFlags = 0;
long timeStamp = 0;
long firstInstallTime = 0;
long lastUpdateTime = 0;
PackageSettingBase packageSetting = null;
String version = null;
int versionCode = 0;
try {
name = parser.getAttributeValue(null, ATTR_NAME);//ATTR_NAME为name,应用包名
realName = parser.getAttributeValue(null, "realName");
idStr = parser.getAttributeValue(null, "userId");//独立Linux用户Id
uidError = parser.getAttributeValue(null, "uidError");
sharedIdStr = parser.getAttributeValue(null, "sharedUserId");//共享Linux用户Id
codePathStr = parser.getAttributeValue(null, "codePath");
resourcePathStr = parser.getAttributeValue(null, "resourcePath");
......
if (name == null) { //名字为空,抛出异常,说明包名必须有
PackageManagerService.reportSettingsProblem(Log.WARN, "Error in package manager settings: has no name at "
+ parser.getPositionDescription());
} else if (codePathStr == null) {
PackageManagerService.reportSettingsProblem(Log.WARN, "Error in package manager settings: has no codePath at "
+ parser.getPositionDescription());
} else if (userId > 0) {//说明上一次分配了一个独立的Linux用户Id
//则将上一次分配的Linux用户Id保存下来
packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiString,
secondaryCpuAbiString, cpuAbiOverrideString, userId, versionCode, pkgFlags);
if (PackageManagerService.DEBUG_SETTINGS)
Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId=" + userId + " pkg=" + packageSetting);
if (packageSetting == null) {
PackageManagerService.reportSettingsProblem(Log.ERROR, "Failure adding uid "
+ userId + " while parsing settings at "
+ parser.getPositionDescription());
} else {
packageSetting.setTimeStamp(timeStamp);
packageSetting.firstInstallTime = firstInstallTime;
packageSetting.lastUpdateTime = lastUpdateTime;
}
} else if (sharedIdStr != null) {//说明上一次没有分配独立的Linux用户Id,而是和其他程序共享一个Linux用户Id
userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
if (userId > 0) {
//PendingPackage描述一个还未确定的应用程序
packageSetting = new PendingPackage(name.intern(), realName, new File(
codePathStr), new File(resourcePathStr), legacyNativeLibraryPathStr,
primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
userId, versionCode, pkgFlags);
packageSetting.setTimeStamp(timeStamp);
packageSetting.firstInstallTime = firstInstallTime;
packageSetting.lastUpdateTime = lastUpdateTime;
//将这个描述对象保存在mPendingPackages中
mPendingPackages.add((PendingPackage) packageSetting);
if (PackageManagerService.DEBUG_SETTINGS)
Log.i(PackageManagerService.TAG, "Reading package " + name
+ ": sharedUserId=" + userId + " pkg=" + packageSetting);
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: package " + name
+ " has bad sharedId " + sharedIdStr + " at "
+ parser.getPositionDescription());
}
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: package " + name + " has bad userId "
+ idStr + " at " + parser.getPositionDescription());
}
} catch (NumberFormatException e) {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: package " + name + " has bad userId "
+ idStr + " at " + parser.getPositionDescription());
}
Linux用户id分为共享和独立,如果此应用userId > 0,说明上一次分配了一个独立的Linux用户id,则会调用addPackageLPw将独立id保存下来,如果不是独立的,而sharedIdStr !=null,则说明是分配的是共享id,则暂时不保留这个id,因为这可能是一个无效的id,mPendingPackages会将此类应用保存起来,表示还未确定的应用。要等到解析完所有安装信息后才能确定。
接着看addPackageLPw是如何将Linux用户id保存下来的。
PackageSetting addPackageLPw(String name, String realName, File codePath, File resourcePath,
String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString,
String cpuAbiOverrideString, int uid, int vc, int pkgFlags) {
//缓存Map中获取PackageSetting
PackageSetting p = mPackages.get(name);
//存在这个包名的应用PackageSetting
if (p != null) {
//Linux用户id和appid相同,说明已分配过,直接返回PackageSetting
if (p.appId == uid) {
return p;
}
PackageManagerService.reportSettingsProblem(Log.ERROR, "Adding duplicate package, keeping first: " + name);
return null;
}
//不存在说明是第一次安装,新建一个PackageSetting对象
p = new PackageSetting(name, realName, codePath, resourcePath,
legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
cpuAbiOverrideString, vc, pkgFlags);
//将Linux用户id赋值给appid
p.appId = uid;
//保存此用户id,如果保留成功,则将PackageSetting存到mPackages中
if (addUserIdLPw(uid, p, name)) {
mPackages.put(name, p);
return p;
}
return null;
}
每个应用程序的安装信息都是用PackageSetting对象来存储,并以包名为key,保存在mPackages这个HashMap中,如果程序已安装过,直接从mPackages获取。如果第一次安装,将构建一个PackageSetting对象来保存信息。
addUserIdLPw方法用于在系统中保留分配的uid,如果保留成功,则将PackageSetting保存到mPackages中,说明PMS已经为此应用分配了Linux用户id了。
//保存Linux用户id
private boolean addUserIdLPw(int uid, Object obj, Object name) {
//Process.LAST_APPLICATION_UID是19999
if (uid > Process.LAST_APPLICATION_UID) {
return false;
}
//LAST_APPLICATION_UID是10000
if (uid >= Process.FIRST_APPLICATION_UID) {
int N = mUserIds.size();//mUserIds为用户id列表
final int index = uid - Process.FIRST_APPLICATION_UID;//当前申请的角标
while (index >= N) {//是否超过列表的角标
mUserIds.add(null);//将中间的置为null
N++;
}
//这个id被用了,保留失败
if (mUserIds.get(index) != null) {
PackageManagerService.reportSettingsProblem(Log.ERROR,
"Adding duplicate user id: " + uid
+ " name=" + name);
return false;
}
//以pid为角标,添加应用程序的PackageSetting
mUserIds.set(index, obj);
} else {
//10000以下给特权用户使用
if (mOtherUserIds.get(uid) != null) {
PackageManagerService.reportSettingsProblem(Log.ERROR,
"Adding duplicate shared id: " + uid
+ " name=" + name);
return false;
}
mOtherUserIds.put(uid, obj);
}
return true;
}
用户类型的pid都在10000到19999之间,说明Android系统只分配9999个给用户类型的程序,小于10000保留给特权用户使用,但这些id也可以通过共享的方式给用户程序使用。独立用户的流程分配完成,我们回到xml解析,看标签为shared-user的共享用户,它紧接着调用了Settings的readSharedUserLPw方法。
//获取上一次分配的共享Linux用户id
private void readSharedUserLPw(XmlPullParser parser) throws XmlPullParserException,IOException {
String name = null;
String idStr = null;
int pkgFlags = 0;
SharedUserSetting su = null;
try {
name = parser.getAttributeValue(null, ATTR_NAME);//共享用户名
idStr = parser.getAttributeValue(null, "userId");//用户id
int userId = idStr != null ? Integer.parseInt(idStr) : 0;
if ("true".equals(parser.getAttributeValue(null, "system"))) {//是给系统类型的应用还是用户类型的应用
pkgFlags |= ApplicationInfo.FLAG_SYSTEM;//系统用户为1
}
//name,userId必须存在
if (name == null) {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: has no name at "
+ parser.getPositionDescription());
} else if (userId == 0) {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: shared-user " + name
+ " has bad userId " + idStr + " at "
+ parser.getPositionDescription());
} else {
//保存这个共享用户的id
if ((su = addSharedUserLPw(name.intern(), userId, pkgFlags)) == null) {
PackageManagerService
.reportSettingsProblem(Log.ERROR, "Occurred while parsing settings at "
+ parser.getPositionDescription());
}
}
} catch (NumberFormatException e) {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: package " + name + " has bad userId "
+ idStr + " at " + parser.getPositionDescription());
}
;
......
}
这里有三个元素,name、userId和system,前两个是共享Linux用户的名称和id,最后一个则用于描述此程序是系统类型,还是用户类型的。
和独立用户流程相似,共享用户是通过addSharedUserLPw方法,保存userId为Linux用户id的。
//保存共享用户的id
SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags) {
//SharedUserSetting即一个共享用户对象
SharedUserSetting s = mSharedUsers.get(name);
if (s != null) {
if (s.userId == uid) {
return s;
}
PackageManagerService.reportSettingsProblem(Log.ERROR,
"Adding duplicate shared user, keeping first: " + name);
return null;
}
s = new SharedUserSetting(name, pkgFlags);
s.userId = uid;
//保存共享用户的id
if (addUserIdLPw(uid, s, name)) {
mSharedUsers.put(name, s);//保存起来
return s;
}
return null;
}
独立用户使用PackageSetting对象来描述应用的安装信息,而共享用户则使用SharedUserSetting ,分配和安装成功的用户同样保存到一个Map中,即mSharedUsers。
同样,需要调用addUserIdLPw方法,来判断这个id是否在系统规定的范围,这个方法上面已做了分析。这个时候PMS通过Settings就已将上一次应用程序的安装信息恢复完成了。我们回头看到PMS的构造方法,它会扫描各个安装目录。
//Environment.getRootDirectory()为system目录
//获取/system/famework目录,保存的是资源型的文件,不包含执行代码
File frameworkDir = new File(Environment.getRootDirectory(), "framework");
//加载framework资源
alreadyDexOpted.add(frameworkDir.getPath() + "/framework-res.apk");
//加载核心库
alreadyDexOpted.add(frameworkDir.getPath() + "/core-libart.jar");
String[] frameworkFiles = frameworkDir.list();
if (frameworkFiles != null) {
for (String dexCodeInstructionSet : dexCodeInstructionSets) {
for (int i=0; i
显然scanDirLI是最关键的方法,通过扫描5个安装目录,判断是否存在以".apk"为后缀的文件,如果存在则对文件进行解析。
//扫描安装路径
private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) {
//遍历出所有文件
final File[] files = dir.listFiles();
if (ArrayUtils.isEmpty(files)) {
Log.d(TAG, "No files in app dir " + dir);
return;
}
if (DEBUG_PACKAGE_SCANNING) {
Log.d(TAG, "Scanning app dir " + dir + " scanFlags=" + scanFlags
+ " flags=0x" + Integer.toHexString(parseFlags));
}
//取出所有apk文件进行解析
for (File file : files) {
final boolean isPackage = (isApkFile(file) || file.isDirectory())
&& !PackageInstallerService.isStageName(file.getName());
if (!isPackage) {
continue;
}
try {
//解析apk
scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK,
scanFlags, currentTime, null);
} catch (PackageManagerException e) {
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
e.error == PackageManager.INSTALL_FAILED_INVALID_APK) {
logCriticalInfo(Log.WARN, "Deleting invalid package at " + file);
if (file.isDirectory()) {
FileUtils.deleteContents(file);
}
file.delete();
}
}
}
}
scanPackageLI方法用来解析.apk文件,解析完会返回一个Package对象pkg给调用者。
private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
long currentTime, UserHandle user) throws PackageManagerException {
//设置解析标志mDefParseFlags默认为0
parseFlags |= mDefParseFlags;
//创建一个包解析器
PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);
if ((scanFlags & SCAN_TRUSTED_OVERLAY) != 0) {
parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY;
}
//定义包对象Package
final PackageParser.Package pkg;
try {
//解析apk文件,获得Package
pkg = pp.parsePackage(scanFile, parseFlags);
} catch (PackageParserException e) {
throw PackageManagerException.from(e);
}
PackageSetting ps = null;
PackageSetting updatedPkg;
synchronized (mPackages) {
String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
ps = mSettings.peekPackageLPr(oldName);
}
if (ps == null) {
ps = mSettings.peekPackageLPr(pkg.packageName);
}
updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName);
if (DEBUG_INSTALL && updatedPkg != null) Slog.d(TAG, "updatedPkg = " + updatedPkg);
}
boolean updatedPkgBetter = false;
if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
if (ps != null && !ps.codePath.equals(scanFile)) {
if (pkg.mVersionCode < ps.versionCode) {
if (!updatedPkg.codePath.equals(scanFile)) {
updatedPkg.codePath = scanFile;
updatedPkg.codePathString = scanFile.toString();
if (locationIsPrivileged(scanFile)) {
updatedPkg.pkgFlags |= ApplicationInfo.FLAG_PRIVILEGED;
}
}
updatedPkg.pkg = pkg;
throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE, null);
} else {
synchronized (mPackages) {
mPackages.remove(ps.name);
}
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
getAppDexInstructionSets(ps));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
synchronized (mPackages) {
mSettings.enableSystemPackageLPw(ps.name);
}
updatedPkgBetter = true;
}
}
}
if (updatedPkg != null) {
parseFlags |= PackageParser.PARSE_IS_SYSTEM;
if ((updatedPkg.pkgFlags & ApplicationInfo.FLAG_PRIVILEGED) != 0) {
parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
}
}
collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags);
boolean shouldHideSystemApp = false;
if (updatedPkg == null && ps != null
&& (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) {
if (compareSignatures(ps.signatures.mSignatures, pkg.mSignatures)
!= PackageManager.SIGNATURE_MATCH) {
} else {
if (pkg.mVersionCode < ps.versionCode) {
shouldHideSystemApp = true;
} else {
InstallArgs args = createInstallArgsForExisting(packageFlagsToInstallFlags(ps),
ps.codePathString, ps.resourcePathString, ps.legacyNativeLibraryPathString,
getAppDexInstructionSets(ps));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
}
}
}
}
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
}
}
String resourcePath = null;
String baseResourcePath = null;
if ((parseFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
if (ps != null && ps.resourcePathString != null) {
resourcePath = ps.resourcePathString;
baseResourcePath = ps.resourcePathString;
} else {
}
} else {
resourcePath = pkg.codePath;
baseResourcePath = pkg.baseCodePath;
}
pkg.applicationInfo.setCodePath(pkg.codePath);
pkg.applicationInfo.setBaseCodePath(pkg.baseCodePath);
pkg.applicationInfo.setSplitCodePaths(pkg.splitCodePaths);
pkg.applicationInfo.setResourcePath(resourcePath);
pkg.applicationInfo.setBaseResourcePath(baseResourcePath);
pkg.applicationInfo.setSplitResourcePaths(pkg.splitCodePaths);
//解析Package
PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanFlags| SCAN_UPDATE_SIGNATURE, currentTime, user);
if (shouldHideSystemApp) {
synchronized (mPackages) {
grantPermissionsLPw(pkg, true, pkg.packageName);
mSettings.disableSystemPackageLPw(pkg.packageName);
}
}
return scannedPkg;
}
这里分两步看,第一步是创建PackageParser解析器,通过parsePackage方法,将apk文件解析成Package对象;第二步是使用另一个重载方法scanPackageLI来处理这个Package并返回。我们先看第一步,进入PackageParser这个类的parsePackage方法。
//解析.apk文件
public Package parsePackage(File packageFile, int flags) throws PackageParserException {
if (packageFile.isDirectory()) {
//解析多个apk
return parseClusterPackage(packageFile, flags);
} else {
//解析单个
return parseMonolithicPackage(packageFile, flags);
}
}
如果传入的是一个目录文件,被拆分成多个apk,由一个base APK和一个或多个split APK,称为Cluster,单个称为Monolithic。
两者解析流程差别不大,我们以parseMonolithicPackage为例分析。
@Deprecated
public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
//是否核心应用
if (mOnlyCoreApps) {
//轻量级解析
final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
if (!lite.coreApp) {
throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
"Not a coreApp: " + apkFile);
}
}
//构建AssetManager
final AssetManager assets = new AssetManager();
try {
//开始解析
final Package pkg = parseBaseApk(apkFile, assets, flags);
pkg.codePath = apkFile.getAbsolutePath();
return pkg;
} finally {
IoUtils.closeQuietly(assets);
}
}
轻量级解析是因为解析apk是复杂耗时的操作,这里的逻辑并不需要所有的信息,coreApp指的是AndroidManifest中属性coreApp值为true。继续看解析方法parseBaseApk,注意它接收了一个AssetManager 对象。
private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();
mParseError = PackageManager.INSTALL_SUCCEEDED;
mArchiveSourcePath = apkFile.getAbsolutePath();
final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);
//构建Resources
Resources res = null;
XmlResourceParser parser = null;
try {
//将AssetManager封装在Resources中
res = new Resources(assets, mMetrics, null);
assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Build.VERSION.RESOURCES_SDK_INT);
//打开manifest,构造解析器
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
final String[] outError = new String[1];
//调用重载方法parseBaseApk
final Package pkg = parseBaseApk(res, parser, flags, outError);
if (pkg == null) {
throw new PackageParserException(mParseError,
apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
}
pkg.baseCodePath = apkPath;
pkg.mSignatures = null;
return pkg;
} catch (PackageParserException e) {
throw e;
} catch (Exception e) {
throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
"Failed to read manifest from " + apkPath, e);
} finally {
IoUtils.closeQuietly(parser);
}
}
XmlResourceParser 用于解析编译后的AndroidManifest,通过重载方法parseBaseApk来解析。因为解析标签很多,所以代码非常长,这里贴部分作为示例。
private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,
String[] outError) throws XmlPullParserException, IOException {
final boolean trustedOverlay = (flags & PARSE_TRUSTED_OVERLAY) != 0;
AttributeSet attrs = parser;
mParseInstrumentationArgs = null;
mParseActivityArgs = null;
mParseServiceArgs = null;
mParseProviderArgs = null;
final String pkgName;
final String splitName;
try {
Pair packageSplit = parsePackageSplitNames(parser, attrs, flags);
pkgName = packageSplit.first;//包名
splitName = packageSplit.second;
} catch (PackageParserException e) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
return null;
}
int type;
if (!TextUtils.isEmpty(splitName)) {
outError[0] = "Expected base APK, but found split " + splitName;
mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
return null;
}
//根据包名构建Package对象,将解析manifest后的信息存到这个对象中
final Package pkg = new Package(pkgName);
boolean foundApp = false;
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifest);
pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_versionCode, 0);//版本号
pkg.mVersionName = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifest_versionName, 0);//版本名
if (pkg.mVersionName != null) {
pkg.mVersionName = pkg.mVersionName.intern();
}
String str = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
if (str != null && str.length() > 0) {
String nameError = validateName(str, true);
if (nameError != null && !"android".equals(pkgName)) {
outError[0] = " specifies bad sharedUserId name \""
+ str + "\": " + nameError;
mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
return null;
}
pkg.mSharedUserId = str.intern();
pkg.mSharedUserLabel = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
}
pkg.installLocation = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_installLocation,
PARSE_DEFAULT_INSTALL_LOCATION);
pkg.applicationInfo.installLocation = pkg.installLocation;
pkg.coreApp = attrs.getAttributeBooleanValue(null, "coreApp", false);
sa.recycle();
if ((flags & PARSE_FORWARD_LOCK) != 0) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FORWARD_LOCK;
}
if ((flags & PARSE_ON_SDCARD) != 0) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
}
int supportsSmallScreens = 1;
int supportsNormalScreens = 1;
int supportsLargeScreens = 1;
int supportsXLargeScreens = 1;
int resizeable = 1;
int anyDensity = 1;
int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String tagName = parser.getName();
//解析application标签
if (tagName.equals("application")) {
if (foundApp) {
if (RIGID_PARSER) {
//一个xml只能包含一个标签
outError[0] = " has more than one ";
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return null;
} else {
Slog.w(TAG, " has more than one ");
XmlUtils.skipCurrentTag(parser);
continue;
}
}
foundApp = true;
//解析Application标签
if (!parseBaseApplication(pkg, res, parser, attrs, flags, outError)) {
return null;
}
} else if (tagName.equals("overlay")) {
pkg.mTrustedOverlay = trustedOverlay;
sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifestResourceOverlay);
pkg.mOverlayTarget = sa.getString(
com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
pkg.mOverlayPriority = sa.getInt(
com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
-1);
sa.recycle();
if (pkg.mOverlayTarget == null) {
outError[0] = " does not specify a target package";
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return null;
}
if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
outError[0] = " priority must be between 0 and 9999";
mParseError =
PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return null;
}
XmlUtils.skipCurrentTag(parser);
} else if (tagName.equals("key-sets")) {
if (!parseKeySets(pkg, res, parser, attrs, outError)) {
return null;
}
} else if (tagName.equals("permission-group")) {
if (parsePermissionGroup(pkg, flags, res, parser, attrs, outError) == null) {
return null;
}
} else if (tagName.equals("permission")) {
if (parsePermission(pkg, res, parser, attrs, outError) == null) {
return null;
}
} else if (tagName.equals("permission-tree")) {
if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
return null;
}
//权限
} else if (tagName.equals("uses-permission")) {
if (!parseUsesPermission(pkg, res, parser, attrs, outError)) {
return null;
}
我们看到parseBaseApplication开始解析application标签,它同样非常长。
private boolean parseBaseApplication(Package owner, Resources res,
XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
throws XmlPullParserException, IOException {
//应用信息
final ApplicationInfo ai = owner.applicationInfo;
//包名
final String pkgName = owner.applicationInfo.packageName;
//标签属性
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifestApplication);
//应用名
String name = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_name, 0);
if (name != null) {
ai.className = buildClassName(pkgName, name, outError);
if (ai.className == null) {
sa.recycle();
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
}
String manageSpaceActivity = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
Configuration.NATIVE_CONFIG_VERSION);
if (manageSpaceActivity != null) {
ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
outError);
}
boolean allowBackup = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
if (allowBackup) {
ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
String backupAgent = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
Configuration.NATIVE_CONFIG_VERSION);
if (backupAgent != null) {
ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_killAfterRestore,
true)) {
ai.flags |= ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
}
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_restoreAnyVersion,
false)) {
ai.flags |= ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
}
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_fullBackupOnly,
false)) {
ai.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
}
}
}
TypedValue v = sa.peekValue(
com.android.internal.R.styleable.AndroidManifestApplication_label);
if (v != null && (ai.labelRes=v.resourceId) == 0) {
ai.nonLocalizedLabel = v.coerceToString();
}
//应用图标等
ai.icon = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
ai.logo = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);
ai.banner = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_banner, 0);
ai.theme = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
ai.descriptionRes = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
if ((flags&PARSE_IS_SYSTEM) != 0) {
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_persistent,
false)) {
ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
}
}
......
final int innerDepth = parser.getDepth();
int type;
//循环解析Application元素下所有子元素,如activity,service等
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}
String tagName = parser.getName();
if (tagName.equals("activity")) {//解析activity
Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
owner.baseHardwareAccelerated);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
//将Activity添加到管理的列表当中
owner.activities.add(a);
} else if (tagName.equals("receiver")) {//解析receiver
Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.receivers.add(a);
} else if (tagName.equals("service")) {//解析service
Service s = parseService(owner, res, parser, attrs, flags, outError);
if (s == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.services.add(s);
} else if (tagName.equals("provider")) {//解析provider
Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
if (p == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
owner.providers.add(p);
我们看到包名、应用名还有4大组件都被解析出来了。这里注意到有个owner,它是在parseBaseApk里根据包名生成的Package对象,Manifest标签解析后的数据都存在此对象中。
Package是PackageParser解析器的内部类,Package用了四个列表分别保存四大组件。
public final static class Package {
public String packageName;
public String[] splitNames;
public String codePath;
public String baseCodePath;
public String[] splitCodePaths;
public int[] splitFlags;
public boolean baseHardwareAccelerated;
public final ApplicationInfo applicationInfo = new ApplicationInfo();
public final ArrayList permissions = new ArrayList(0);
public final ArrayList permissionGroups = new ArrayList(0);
//保存四大组件
public final ArrayList activities = new ArrayList(0);
public final ArrayList receivers = new ArrayList(0);
public final ArrayList providers = new ArrayList(0);
public final ArrayList services = new ArrayList(0);
到这里第一步就完成了,得到一个Package对象,它包含了Manifest的所有信息。如上面所提,第二步是调用重载的scanPackageLI方法,解析这个Package。
我们先看下PMS的5个成员变量。
//保存已安装的程序
final HashMap mPackages =
new HashMap();
//保存每个应用的Activity节点,一个应用一个节点,一个节点用一个HashMap存了改应用的所有activity
final ActivityIntentResolver mActivities =
new ActivityIntentResolver();
//保存所有receiver节点
final ActivityIntentResolver mReceivers =
new ActivityIntentResolver();
//保存所有Service节点
final ServiceIntentResolver mServices = new ServiceIntentResolver();
//保存所有Provider节点
final ProviderIntentResolver mProviders = new ProviderIntentResolver();
这些属性类型都采用了自定义类去保存相关信息,从类名上看,类结构都很相似。顺便提一下,我们通过getPackageManager()方法获得的PackageManager对象,只是PackageManagerService的客户端,PackageManager的子类ApplicationPackageManager,显然该类存在于用户空间中。关于跨进程通讯可以看
系统中所有已安装的程序都用Package来描述,而这些Package就保存在mPackages 中,而每一个应用的四大组件都分别保存在mActivities 、mReceivers 、mServices 和mProviders 中。
我们接下去看重载scanPackageLI方法。
private PackageParser.Package scanPackageLI(PackageParser.Package pkg, int parseFlags,
int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
boolean success = false;
try {
//scanPackageDirtyLI进行扫描
final PackageParser.Package res = scanPackageDirtyLI(pkg, parseFlags, scanFlags,
currentTime, user);
success = true;
return res;
} finally {
if (!success && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
removeDataDirsLI(pkg.packageName);
}
}
}
private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags,
int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
......
SharedUserSetting suid = null;
PackageSetting pkgSetting = null;
if (!isSystemApp(pkg)) {
pkg.mOriginalPackages = null;
pkg.mRealPackage = null;
pkg.mAdoptPermissions = null;
}
synchronized (mPackages) {
//根据mSettings保存的分配Linux用户id
if (pkg.mSharedUserId != null) {
suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, true);
if (suid == null) {
throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
"Creating application package " + pkg.packageName
+ " for shared user failed");
}
}
......
// writer
synchronized (mPackages) {
mSettings.insertPackageSettingLPw(pkgSetting, pkg);
//将Package添加到成员变量mPackages中
mPackages.put(pkg.applicationInfo.packageName, pkg);
final Iterator iter = mSettings.mPackagesToBeCleaned.iterator();
while (iter.hasNext()) {
PackageCleanItem item = iter.next();
if (pkgName.equals(item.packageName)) {
iter.remove();
}
}
if (currentTime != 0) {
if (pkgSetting.firstInstallTime == 0) {
pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
} else if ((scanFlags&SCAN_UPDATE_TIME) != 0) {
pkgSetting.lastUpdateTime = currentTime;
}
} else if (pkgSetting.firstInstallTime == 0) {
pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
} else if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
if (scanFileTime != pkgSetting.timeStamp) {
pkgSetting.lastUpdateTime = scanFileTime;
}
}
KeySetManagerService ksms = mSettings.mKeySetManagerService;
try {
ksms.removeAppKeySetDataLPw(pkg.packageName);
ksms.addSigningKeySetToPackageLPw(pkg.packageName, pkg.mSigningKeys);
if (pkg.mKeySetMapping != null) {
for (Map.Entry> entry :
pkg.mKeySetMapping.entrySet()) {
if (entry.getValue() != null) {
ksms.addDefinedKeySetToPackageLPw(pkg.packageName,
entry.getValue(), entry.getKey());
}
}
if (pkg.mUpgradeKeySets != null) {
for (String upgradeAlias : pkg.mUpgradeKeySets) {
ksms.addUpgradeKeySetToPackageLPw(pkg.packageName, upgradeAlias);
}
}
}
} catch (NullPointerException e) {
Slog.e(TAG, "Could not add KeySet to " + pkg.packageName, e);
} catch (IllegalArgumentException e) {
Slog.e(TAG, "Could not add KeySet to malformed package" + pkg.packageName, e);
}
int N = pkg.providers.size();
StringBuilder r = null;
int i;
for (i=0; i
对Package的扫描主要任务是分配Linux用户id,以及将Package和四大组件分别添加到上面说的5成员变量中,前面说过共享用户都使用一个SharedUserSetting 对象来描述,因此根据name去mSharedUsers中查找,如果不存在则新建。
SharedUserSetting getSharedUserLPw(String name,
int pkgFlags, boolean create) {
SharedUserSetting s = mSharedUsers.get(name);
//不存在根据create判断是否新建
if (s == null) {
if (!create) {
return null;
}
s = new SharedUserSetting(name, pkgFlags);
s.userId = newUserIdLPw(s);
//加到mSharedUsers中
if (s.userId >= 0) {
mSharedUsers.put(name, s);
}
}
return s;
}
此时PMS便为应用分配好了Linux用户id,并把它们缓存到成员变量中。但成员数据会随着类的回收而销毁,前面分析时我们知道,这些数据对应的信息会保存到packages.xml和packages-backup.xml中,以便下次启动恢复,这个保存操作也在PMS构造函数执行,我们再次回到PMS的构造方法。
.....
//权限设置,检查sdk版本
final boolean regrantPermissions = mSettings.mInternalSdkPlatform
!= mSdkVersion;
if (regrantPermissions) Slog.i(TAG, "Platform changed from "
+ mSettings.mInternalSdkPlatform + " to " + mSdkVersion
+ "; regranting permissions for internal storage");
mSettings.mInternalSdkPlatform = mSdkVersion;
//分配权限
updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
| (regrantPermissions
? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
: 0));
if (!mRestoredSettings && !onlyCore) {
mSettings.readDefaultPreferredAppsLPw(this, 0);
}
if (!Build.FINGERPRINT.equals(mSettings.mFingerprint) && !onlyCore) {
Slog.i(TAG, "Build fingerprint changed; clearing code caches");
for (String pkgName : mSettings.mPackages.keySet()) {
deleteCodeCacheDirsLI(pkgName);
}
mSettings.mFingerprint = Build.FINGERPRINT;
}
mSettings.updateInternalDatabaseVersion();
//将上面读取到的信息保存成配置,以便下次启动恢复
mSettings.writeLPr();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());
mRequiredVerifierPackage = getRequiredVerifierLPr();
}
}
mInstallerService = new PackageInstallerService(context, this, mAppInstallDir);
//GC回收资源
Runtime.getRuntime().gc();
}
我们再次进到Settings类,看writeLPr方法是如何保存的。
//保存上一次的应用安装信息
void writeLPr() {
//Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
// Keep the old settings around until we know the new ones have
// been successfully written.
//源文件是否存在
if (mSettingsFilename.exists()) {
// Presence of backup settings file indicates that we failed
// to persist settings earlier. So preserve the older
// backup for future reference since the current settings
// might have been corrupted.
//备份文件不存存在
if (!mBackupSettingsFilename.exists()) {
//将源文件重命名为备份文件
if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
Slog.wtf(PackageManagerService.TAG,
"Unable to backup package manager settings, "
+ " current changes will be lost at reboot");
return;
}
} else {
//删掉源文件
mSettingsFilename.delete();
Slog.w(PackageManagerService.TAG, "Preserving older settings backup");
}
}
mPastSignatures.clear();
try {
//初始化文件的一些标签
FileOutputStream fstr = new FileOutputStream(mSettingsFilename);
BufferedOutputStream str = new BufferedOutputStream(fstr);
//XmlSerializer serializer = XmlUtils.serializerInstance();
XmlSerializer serializer = new FastXmlSerializer();
serializer.setOutput(str, "utf-8");
serializer.startDocument(null, true);
serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
serializer.startTag(null, "packages");//包标签
serializer.startTag(null, "last-platform-version");
serializer.attribute(null, "internal", Integer.toString(mInternalSdkPlatform));
serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform));
serializer.attribute(null, "fingerprint", mFingerprint);
serializer.endTag(null, "last-platform-version");
serializer.startTag(null, "database-version");
serializer.attribute(null, "internal", Integer.toString(mInternalDatabaseVersion));
serializer.attribute(null, "external", Integer.toString(mExternalDatabaseVersion));
serializer.endTag(null, "database-version");
if (mVerifierDeviceIdentity != null) {
serializer.startTag(null, "verifier");
serializer.attribute(null, "device", mVerifierDeviceIdentity.toString());
serializer.endTag(null, "verifier");
}
if (mReadExternalStorageEnforced != null) {
serializer.startTag(null, TAG_READ_EXTERNAL_STORAGE);
serializer.attribute(
null, ATTR_ENFORCEMENT, mReadExternalStorageEnforced ? "1" : "0");
serializer.endTag(null, TAG_READ_EXTERNAL_STORAGE);
}
serializer.startTag(null, "permission-trees");
for (BasePermission bp : mPermissionTrees.values()) {
writePermissionLPr(serializer, bp);
}
serializer.endTag(null, "permission-trees");
serializer.startTag(null, "permissions");
for (BasePermission bp : mPermissions.values()) {
writePermissionLPr(serializer, bp);
}
serializer.endTag(null, "permissions");
for (final PackageSetting pkg : mPackages.values()) {
writePackageLPr(serializer, pkg);
}
for (final PackageSetting pkg : mDisabledSysPackages.values()) {
writeDisabledSysPackageLPr(serializer, pkg);
}
for (final SharedUserSetting usr : mSharedUsers.values()) {
serializer.startTag(null, "shared-user");//共享用户标签
serializer.attribute(null, ATTR_NAME, usr.name);
serializer.attribute(null, "userId",Integer.toString(usr.userId));//独立用户id
usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
serializer.startTag(null, "perms");
for (String name : usr.grantedPermissions) {
serializer.startTag(null, TAG_ITEM);
serializer.attribute(null, ATTR_NAME, name);
serializer.endTag(null, TAG_ITEM);
}
serializer.endTag(null, "perms");
serializer.endTag(null, "shared-user");
}
if (mPackagesToBeCleaned.size() > 0) {
for (PackageCleanItem item : mPackagesToBeCleaned) {
final String userStr = Integer.toString(item.userId);
serializer.startTag(null, "cleaning-package");
serializer.attribute(null, ATTR_NAME, item.packageName);
serializer.attribute(null, ATTR_CODE, item.andCode ? "true" : "false");
serializer.attribute(null, ATTR_USER, userStr);
serializer.endTag(null, "cleaning-package");
}
}
if (mRenamedPackages.size() > 0) {
for (Map.Entry e : mRenamedPackages.entrySet()) {
serializer.startTag(null, "renamed-package");
serializer.attribute(null, "new", e.getKey());
serializer.attribute(null, "old", e.getValue());
serializer.endTag(null, "renamed-package");
}
}
mKeySetManagerService.writeKeySetManagerServiceLPr(serializer);
//包标签结束packages
serializer.endTag(null, "packages");
//文档标签结束
serializer.endDocument();
str.flush();
FileUtils.sync(fstr);
str.close();
......
}
可以看到,每个程序都是以package标签为单位来存储的,name表示了包名,userId和sharedUserId描述分配给程序的独立Linux用户id和共享Linux用户id,这两个id是互斥的,即要么为独立用户要么为共享用户。
这一步完成,PMS就将程序所使用的Linux用户id保存起来了,当重装一个应用程序时,它所对应的Linux用户id是不变的。
Android系统是类Linux系统,根据Linux用户id来防止程序的篡改和破坏,程序的进程是AMS向Zygote进程请求创建的,而Zygote正是根据这个id来创建进程。我们可以看下AMS的startProcessLocked方法。
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
long startTime = SystemClock.elapsedRealtime();
//
if (app.pid > 0 && app.pid != MY_PID) {
checkTime(startTime, "startProcess: removing from pids map");
synchronized (mPidsSelfLocked) {
mPidsSelfLocked.remove(app.pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
checkTime(startTime, "startProcess: done removing from pids map");
app.setPid(0);
}
mProcessesOnHold.remove(app);
checkTime(startTime, "startProcess: starting to update cpu stats");
updateCpuStats();
checkTime(startTime, "startProcess: done updating cpu stats");
try {
//获取Linux用户id
int uid = app.uid;
int[] gids = null;
int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {
int[] permGids = null;
try {
checkTime(startTime, "startProcess: getting gids from package manager");
final PackageManager pm = mContext.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName);
if (Environment.isExternalStorageEmulated()) {
checkTime(startTime, "startProcess: checking external storage perm");
if (pm.checkPermission(
android.Manifest.permission.ACCESS_ALL_EXTERNAL_STORAGE,
app.info.packageName) == PERMISSION_GRANTED) {
mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL;
} else {
mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
}
}
} catch (PackageManager.NameNotFoundException e) {
Slog.w(TAG, "Unable to retrieve gids", e);
}
if (permGids == null) {
gids = new int[2];
} else {
gids = new int[permGids.length + 2];
System.arraycopy(permGids, 0, gids, 2, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));
}
......
//告诉Zygote子进程孵化ActivityThread进程后,调用main方法
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
checkTime(startTime, "startProcess: asking zygote to start proc");
//开启进程
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
checkTime(startTime, "startProcess: returned from zygote!");
......
}
Process.start用于通知Zygote开启新进程,在调用的过程会根据第3、4、5个参数来创建进程。
到此,应用程序的安装过程便分析完毕,这个分析过程是从系统启动时开始的,如果一个程序在系统启动后在安装,它的入口会是PMS的installPackage,最终也会执行scanPackageLI,其流程是相似的。
程序安装完成后,我们看到桌面会生成一个图标,这一流程将在下一篇<