1、系统开机时PackageManagerService()构造函数会调用readPermissions()解析etc/permissions目录下的xml文件,然后将配置信息分别进行保存:assign-permission项保存在mSystemPermissions队列中、library项保存在mSharedLibraries队列中、feature项保存在mAvailableFeatures中;
2、对于mSharedLibraries,其实都是一些jar包,系统开机时还会调用Installer.dexopt()做odex优化,
3、mAvailableFeatures中保存的是一些硬件feature;
4、Intent的目的地址可以分为两类, 一类是明确定义了ComponentName, 对于此类intent, android系统直接查找所需的受体就可, 不存在匹配过程. 另一类则是没有定义ComponentName, 但是确通过对action, category和data的定义给出匹配信息, android系统根据这些信息查找系统内已经登记的所有受体的intentFilter信息, 匹配出合适的intent受体, 如果受体是多个,则按照priority和preference挑选出最适合的intent受体.参考:http://blog.chinaunix.net/uid-433806-id-266778.html
5、Intent MIME类型:在资源管理器的中实现打开文件的操作,此时就需要用到文件的MIME类型。
6、IntentResolver.queryIntent()
public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly,
int userId) {
String scheme = intent.getScheme();
ArrayList<R> finalList = new ArrayList<R>();
final boolean debug = localLOGV ||
((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
if (debug) Slog.v(
TAG, "Resolving type=" + resolvedType + " scheme=" + scheme
+ " defaultOnly=" + defaultOnly + " userId=" + userId + " of " + intent);
F[] firstTypeCut = null;
F[] secondTypeCut = null;
F[] thirdTypeCut = null;
F[] schemeCut = null;
// If the intent includes a MIME type, then we want to collect all of
// the filters that match that MIME type.
if (resolvedType != null) { //如果存在MIME类型,那么先开始匹配MIME;
int slashpos = resolvedType.indexOf('/'); //①从type中确定“/”字符位置,slash为“斜线”之意;
if (slashpos > 0) {
final String baseType = resolvedType.substring(0, slashpos); //②提取出“/”字符之前的字符串,代表基本类型;
if (!baseType.equals("*")) { //③基本类型不为“*”
if (resolvedType.length() != slashpos+2
|| resolvedType.charAt(slashpos+1) != '*') { //④这两个条件排除“basetype/”和“basetype/*”这种情况,此时先从mTypeToFilter中匹配resolvedType,然后从mWildTypeToFilter中匹配baseType;
// Not a wild card, so we can just look for all filters that
// completely match or wildcards whose base type matches.
firstTypeCut = mTypeToFilter.get(resolvedType);
if (debug) Slog.v(TAG, "First type cut: " + Arrays.toString(firstTypeCut));
secondTypeCut = mWildTypeToFilter.get(baseType);
if (debug) Slog.v(TAG, "Second type cut: "
+ Arrays.toString(secondTypeCut));
} else { //⑤对应“basetype/”和“basetype/*”这种情况,此时先从mBaseTypeToFilter中匹配baseType,然后从mWildTypeToFilter中匹配baseType;
// We can match anything with our base type.
firstTypeCut = mBaseTypeToFilter.get(baseType);
if (debug) Slog.v(TAG, "First type cut: " + Arrays.toString(firstTypeCut));
secondTypeCut = mWildTypeToFilter.get(baseType);
if (debug) Slog.v(TAG, "Second type cut: "
+ Arrays.toString(secondTypeCut));
}
// Any */* types always apply, but we only need to do this
// if the intent type was not already */*.
thirdTypeCut = mWildTypeToFilter.get("*");
if (debug) Slog.v(TAG, "Third type cut: " + Arrays.toString(thirdTypeCut));
} else if (intent.getAction() != null) { //⑥对于基本类型为“*”,肯定会匹配出一堆出来,此时用action匹配来替代基本类型匹配规则;
// The intent specified any type ({@literal *}/*). This
// can be a whole heck of a lot of things, so as a first
// cut let's use the action instead.
firstTypeCut = mTypedActionToFilter.get(intent.getAction());
if (debug) Slog.v(TAG, "Typed Action list: " + Arrays.toString(firstTypeCut));
}
}
}
// If the intent includes a data URI, then we want to collect all of
// the filters that match its scheme (we will further refine matches
// on the authority and path by directly matching each resulting filter).
if (scheme != null) { //⑥如果intent带有URI,那么从mSchemeToFilter中匹配scheme
schemeCut = mSchemeToFilter.get(scheme);
if (debug) Slog.v(TAG, "Scheme list: " + Arrays.toString(schemeCut));
}
// If the intent does not specify any data -- either a MIME type or
// a URI -- then we will only be looking for matches against empty
// data.
if (resolvedType == null && scheme == null && intent.getAction() != null) { //⑥如果Intent既没有MIME,又没有URI,有action,那么就匹配action吧;
firstTypeCut = mActionToFilter.get(intent.getAction());
if (debug) Slog.v(TAG, "Action list: " + Arrays.toString(firstTypeCut));
}
FastImmutableArraySet<String> categories = getFastIntentCategories(intent); //⑥将Intent中的Category取出来;
if (firstTypeCut != null) { //⑦以下四个if()语句分别调用buildResolveList()进行最终匹配,如果匹配,那么放入finalList列表中,此函数在下面详细分析;
buildResolveList(intent, categories, debug, defaultOnly,
resolvedType, scheme, firstTypeCut, finalList, userId);
}
if (secondTypeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly,
resolvedType, scheme, secondTypeCut, finalList, userId);
}
if (thirdTypeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly,
resolvedType, scheme, thirdTypeCut, finalList, userId);
}
if (schemeCut != null) {
buildResolveList(intent, categories, debug, defaultOnly,
resolvedType, scheme, schemeCut, finalList, userId);
}
sortResults(finalList); //⑦将finalList列表进行排序,最后返回该队列;对结果进行排序, 可以看到IntentResolver的排序规则是根据priority. 而ActivityIntentResolver和ServiceIntentResolver则复杂些, 还考虑了preferredOrder和intentFilter是否是default的情况;
if (debug) {
Slog.v(TAG, "Final result list:");
for (int i=0; i<finalList.size(); i++) {
Slog.v(TAG, " " + finalList.get(i));
}
}
return finalList;
}
buildResolveList():该函数在上面第⑦点中被四次调用进行最终匹配,下面分析下:
private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories,
boolean debug, boolean defaultOnly,
String resolvedType, String scheme, F[] src, List<R> dest, int userId) { //①src中保存着初次匹配出来的所有IntentFilter,接下来的逻辑就是从这里面找出最匹配的来;
final String action = intent.getAction();
final Uri data = intent.getData();
final String packageName = intent.getPackage();
final boolean excludingStopped = intent.isExcludingStopped();
final Printer logPrinter;
final PrintWriter logPrintWriter;
if (debug) {
logPrinter = new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM);
logPrintWriter = new FastPrintWriter(logPrinter);
} else {
logPrinter = null;
logPrintWriter = null;
}
final int N = src != null ? src.length : 0;
boolean hasNonDefaults = false;
int i;
F filter;
for (i=0; i<N && (filter=src[i]) != null; i++) { //②将src中对象一个个拿出来进行匹配;
int match;
if (debug) Slog.v(TAG, "Matching against filter " + filter);
if (excludingStopped && isFilterStopped(filter, userId)) {
if (debug) {
Slog.v(TAG, " Filter's target is stopped; skipping");
}
continue;
}
// Is delivery being limited to filters owned by a particular package?
if (packageName != null && !isPackageForFilter(packageName, filter)) { //③如果指定了包名,那么就通过包名进行匹配,匹配不成功自然被skip掉;
if (debug) {
Slog.v(TAG, " Filter is not from package " + packageName + "; skipping");
}
continue;
}
// Do we already have this one?
if (!allowFilterResult(filter, dest)) {
if (debug) {
Slog.v(TAG, " Filter's target already added");
}
continue;
}
match = filter.match(action, resolvedType, scheme, data, categories, TAG); //④匹配action、data,匹配成功返回值大于0;
if (match >= 0) {
if (debug) Slog.v(TAG, " Filter matched! match=0x" +
Integer.toHexString(match) + " hasDefault="
+ filter.hasCategory(Intent.CATEGORY_DEFAULT));
if (!defaultOnly || filter.hasCategory(Intent.CATEGORY_DEFAULT)) {
final R oneResult = newResult(filter, match, userId);
if (oneResult != null) {
dest.add(oneResult); //⑤匹配成功,add到dest中;
if (debug) {
dumpFilter(logPrintWriter, " ", filter);
logPrintWriter.flush();
filter.dump(logPrinter, " ");
}
}
} else {
hasNonDefaults = true;
}
} else {
if (debug) {
String reason;
switch (match) {
case IntentFilter.NO_MATCH_ACTION: reason = "action"; break;
case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break;
case IntentFilter.NO_MATCH_DATA: reason = "data"; break;
case IntentFilter.NO_MATCH_TYPE: reason = "type"; break;
default: reason = "unknown reason"; break;
}
Slog.v(TAG, " Filter did not match: " + reason);
}
}
}
if (hasNonDefaults) {
if (dest.size() == 0) {
Slog.w(TAG, "resolveIntent failed: found match, but none with CATEGORY_DEFAULT");
} else if (dest.size() > 1) {
Slog.w(TAG, "resolveIntent: multiple matches, only some with CATEGORY_DEFAULT");
}
}
}
7、apk安装分析
a)、installPackageLI()
private void installPackageLI(InstallArgs args,
boolean newInstall, PackageInstalledInfo res) {
int pFlags = args.flags;
String installerPackageName = args.installerPackageName;
File tmpPackageFile = new File(args.getCodePath());
boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
boolean replace = false;
int scanMode = (onSd ? 0 : SCAN_MONITOR) | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
| (newInstall ? SCAN_NEW_INSTALL : 0);
// Result object to be returned
res.returnCode = PackageManager.INSTALL_SUCCEEDED;
if (DEBUG_INSTALL) Slog.d(TAG, "installPackageLI: path=" + tmpPackageFile);
// Retrieve PackageSettings and parse package
int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
| (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
| (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
PackageParser pp = new PackageParser(tmpPackageFile.getPath()); //①new一个包解析器,用于解析AndroidManifest.xml文件;
pp.setSeparateProcesses(mSeparateProcesses);
final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile, //②调用PackageParser.parsePackage()进行解析,解析的结果保存在一个PackageParser.Package对象中;
null, mMetrics, parseFlags);
if (pkg == null) {
res.returnCode = pp.getParseError();
return;
}
String pkgName = res.name = pkg.packageName;
if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_TEST_ONLY) != 0) {
if ((pFlags&PackageManager.INSTALL_ALLOW_TEST) == 0) {
res.returnCode = PackageManager.INSTALL_FAILED_TEST_ONLY;
return;
}
}
if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
res.returnCode = pp.getParseError();
return;
}
/* If the installer passed in a manifest digest, compare it now. */
if (args.manifestDigest != null) {
if (DEBUG_INSTALL) {
final String parsedManifest = pkg.manifestDigest == null ? "null"
: pkg.manifestDigest.toString();
Slog.d(TAG, "Comparing manifests: " + args.manifestDigest.toString() + " vs. "
+ parsedManifest);
}
if (!args.manifestDigest.equals(pkg.manifestDigest)) {
res.returnCode = PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
return;
}
} else if (DEBUG_INSTALL) {
final String parsedManifest = pkg.manifestDigest == null
? "null" : pkg.manifestDigest.toString();
Slog.d(TAG, "manifestDigest was not present, but parser got: " + parsedManifest);
}
// Get rid of all references to package scan path via parser.
pp = null;
String oldCodePath = null;
boolean systemApp = false;
synchronized (mPackages) {
// Check if installing already existing package
if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
String oldName = mSettings.mRenamedPackages.get(pkgName);
if (pkg.mOriginalPackages != null
&& pkg.mOriginalPackages.contains(oldName)
&& mPackages.containsKey(oldName)) {
// This package is derived from an original package,
// and this device has been updating from that original
// name. We must continue using the original name, so
// rename the new package here.
pkg.setPackageName(oldName);
pkgName = pkg.packageName;
replace = true;
if (DEBUG_INSTALL) Slog.d(TAG, "Replacing existing renamed package: oldName="
+ oldName + " pkgName=" + pkgName);
} else if (mPackages.containsKey(pkgName)) {
// This package, under its official name, already exists
// on the device; we should replace it.
replace = true;
if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName);
}
}
PackageSetting ps = mSettings.mPackages.get(pkgName);
if (ps != null) {
if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);
oldCodePath = mSettings.mPackages.get(pkgName).codePathString;
if (ps.pkg != null && ps.pkg.applicationInfo != null) {
systemApp = (ps.pkg.applicationInfo.flags &
ApplicationInfo.FLAG_SYSTEM) != 0;
}
res.origUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
}
}
if (systemApp && onSd) {
// Disable updates to system apps on sdcard
Slog.w(TAG, "Cannot install updates to system apps on sdcard");
res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
return;
}
if (!args.doRename(res.returnCode, pkgName, oldCodePath)) {
res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
return;
}
// Set application objects path explicitly after the rename
setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
if (replace) {
replacePackageLI(pkg, parseFlags, scanMode, args.user,
installerPackageName, res);
} else {
installNewPackageLI(pkg, parseFlags, scanMode | SCAN_DELETE_DATA_ON_FAILURES, args.user,
installerPackageName, res);
}
synchronized (mPackages) {
final PackageSetting ps = mSettings.mPackages.get(pkgName);
if (ps != null) {
res.newUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
}
}
}
8、scanPackageLI()--安装apk
private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
int parseFlags, int scanMode, long currentTime, UserHandle user) {
File scanFile = new File(pkg.mScanPath);
if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
pkg.applicationInfo.publicSourceDir == null) {
// Bail out. The resource and code paths haven't been set.
Slog.w(TAG, " Code and resource paths haven't been set correctly");
mLastScanError = PackageManager.INSTALL_FAILED_INVALID_APK;
return null;
}
if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
}
if ((parseFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_PRIVILEGED;
}
if (mCustomResolverComponentName != null &&
mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) {
setUpCustomResolverActivity(pkg);
}
if (pkg.packageName.equals("android")) { //①如果安装的apk是/system/framework/framework-res.apk,将信息额外保存;
synchronized (mPackages) {
if (mAndroidApplication != null) {
Slog.w(TAG, "*************************************************");
Slog.w(TAG, "Core android package being redefined. Skipping.");
Slog.w(TAG, " file=" + scanFile);
Slog.w(TAG, "*************************************************");
mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
return null;
}
// Set up information for our fall-back user intent resolution activity.
mPlatformPackage = pkg;
pkg.mVersionCode = mSdkVersion;
mAndroidApplication = pkg.applicationInfo;
if (!mResolverReplaced) {
mResolveActivity.applicationInfo = mAndroidApplication;
mResolveActivity.name = ResolverActivity.class.getName();
mResolveActivity.packageName = mAndroidApplication.packageName;
mResolveActivity.processName = "system:ui";
mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
mResolveActivity.theme = com.android.internal.R.style.Theme_Holo_Dialog_Alert;
mResolveActivity.exported = true;
mResolveActivity.enabled = true;
mResolveInfo.activityInfo = mResolveActivity;
mResolveInfo.priority = 0;
mResolveInfo.preferredOrder = 0;
mResolveInfo.match = 0;
mResolveComponentName = new ComponentName(
mAndroidApplication.packageName, mResolveActivity.name);
}
}
}
if (DEBUG_PACKAGE_SCANNING) {
if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
Log.d(TAG, "Scanning package " + pkg.packageName);
}
if (mPackages.containsKey(pkg.packageName)
|| mSharedLibraries.containsKey(pkg.packageName)) { //②mPackages中保存着所有已经安装的apk,以packagename、PackageParser.Package键值对保存。
Slog.w(TAG, "Application package " + pkg.packageName
+ " already installed. Skipping duplicate.");
mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
return null;
}
// Initialize package source and resource directories
File destCodeFile = new File(pkg.applicationInfo.sourceDir);
File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);
SharedUserSetting suid = null;
PackageSetting pkgSetting = null;
if (!isSystemApp(pkg)) { //③这三个变量只有system apk才能使用;
// Only system apps can use these features.
pkg.mOriginalPackages = null;
pkg.mRealPackage = null;
pkg.mAdoptPermissions = null;
}
// writer
synchronized (mPackages) {
if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) { //对于非system apk,调用updateSharedLibrariesLPw()把pkg.usesLibraries和pkg.usesOptionalLibraries更新到pkg.usesLibraryFiles中去;
// Check all shared libraries and map to their actual file path.
// We only do this here for apps not on a system dir, because those
// are the only ones that can fail an install due to this. We
// will take care of the system apps by updating all of their
// library paths after the scan is done.
if (!updateSharedLibrariesLPw(pkg, null)) {
return null;
}
}
if (pkg.mSharedUserId != null) { //③判断ShareUserID是否是系统中已经存在,Settings.mSharedUsers哈希map中保存着所有的ShareUserID;
suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, true);
if (suid == null) {
Slog.w(TAG, "Creating application package " + pkg.packageName
+ " for shared user failed");
mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
return null;
}
if (DEBUG_PACKAGE_SCANNING) {
if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid=" + suid.userId
+ "): packages=" + suid.packages);
}
}
// Check if we are renaming from an original package name.
PackageSetting origPackage = null;
String realName = null;
if (pkg.mOriginalPackages != null) { //④mOriginalPackages中保存着从AndroidManifest.xml中解析的“original-package”tag项,<original-package>标签用以设置应用源码包名,第三方apk不存在这个;
// This package may need to be renamed to a previously
// installed name. Let's check on that...
final String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
if (pkg.mOriginalPackages.contains(renamed)) {
// This package had originally been installed as the
// original name, and we have already taken care of
// transitioning to the new one. Just update the new
// one to continue using the old name.
realName = pkg.mRealPackage;
if (!pkg.packageName.equals(renamed)) {
// Callers into this function may have already taken
// care of renaming the package; only do it here if
// it is not already done.
pkg.setPackageName(renamed);
}
} else {
for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
if ((origPackage = mSettings.peekPackageLPr(
pkg.mOriginalPackages.get(i))) != null) {
// We do have the package already installed under its
// original name... should we use it?
if (!verifyPackageUpdateLPr(origPackage, pkg)) {
// New package is not compatible with original.
origPackage = null;
continue;
} else if (origPackage.sharedUser != null) {
// Make sure uid is compatible between packages.
if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
Slog.w(TAG, "Unable to migrate data from " + origPackage.name
+ " to " + pkg.packageName + ": old uid "
+ origPackage.sharedUser.name
+ " differs from " + pkg.mSharedUserId);
origPackage = null;
continue;
}
} else {
if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
+ pkg.packageName + " to old name " + origPackage.name);
}
break;
}
}
}
}
if (mTransferedPackages.contains(pkg.packageName)) {
Slog.w(TAG, "Package " + pkg.packageName
+ " was transferred to another, but its .apk remains");
}
// Just create the setting, don't add it yet. For already existing packages
// the PkgSetting exists already and doesn't have to be created.
pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile, //④new 一个PackageSetting对象;
destResourceFile, pkg.applicationInfo.nativeLibraryDir,
pkg.applicationInfo.flags, user, false);
if (pkgSetting == null) {
Slog.w(TAG, "Creating application package " + pkg.packageName + " failed");
mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
return null;
}
if (pkgSetting.origPackage != null) {
// If we are first transitioning from an original package,
// fix up the new package's name now. We need to do this after
// looking up the package under its new name, so getPackageLP
// can take care of fiddling things correctly.
pkg.setPackageName(origPackage.name);
// File a report about this.
String msg = "New package " + pkgSetting.realName
+ " renamed to replace old package " + pkgSetting.name;
reportSettingsProblem(Log.WARN, msg);
// Make a note of it.
mTransferedPackages.add(origPackage.name);
// No longer need to retain this.
pkgSetting.origPackage = null;
}
if (realName != null) {
// Make a note of it.
mTransferedPackages.add(pkg.packageName);
}
if (mSettings.isDisabledSystemPackageLPr(pkg.packageName)) { //如果当前安装的apk在mDisabledSysPackages列表中表示当前正在升级system apk;
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
}
if (mFoundPolicyFile) {
SELinuxMMAC.assignSeinfoValue(pkg);
}
pkg.applicationInfo.uid = pkgSetting.appId;
pkg.mExtras = pkgSetting; //pkgSetting保存到pkg.mExtras中;
if (!verifySignaturesLP(pkgSetting, pkg)) { //④验证签名;
if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
return null;
}
// The signature has changed, but this package is in the system
// image... let's recover!
pkgSetting.signatures.mSignatures = pkg.mSignatures;
// However... if this package is part of a shared user, but it
// doesn't match the signature of the shared user, let's fail.
// What this means is that you can't change the signatures
// associated with an overall shared user, which doesn't seem all
// that unreasonable.
if (pkgSetting.sharedUser != null) {
if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
Log.w(TAG, "Signature mismatch for shared user : " + pkgSetting.sharedUser);
mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
return null;
}
}
// File a report about this.
String msg = "System package " + pkg.packageName
+ " signature changed; retaining data.";
reportSettingsProblem(Log.WARN, msg);
}
// Verify that this new package doesn't have any content providers
// that conflict with existing packages. Only do this if the
// package isn't already installed, since we don't want to break
// things that are installed.
if ((scanMode&SCAN_NEW_INSTALL) != 0) { //⑤验证正在安装的apk是否与已经安装的apk存在contentprovider冲突;
final int N = pkg.providers.size();
int i;
for (i=0; i<N; i++) {
PackageParser.Provider p = pkg.providers.get(i);
if (p.info.authority != null) {
String names[] = p.info.authority.split(";");
for (int j = 0; j < names.length; j++) {
if (mProvidersByAuthority.containsKey(names[j])) {
PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
Slog.w(TAG, "Can't install because provider name " + names[j] +
" (in package " + pkg.applicationInfo.packageName +
") is already used by "
+ ((other != null && other.getComponentName() != null)
? other.getComponentName().getPackageName() : "?"));
mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
return null;
}
}
}
}
}
if (pkg.mAdoptPermissions != null) { //⑤权限领养,《adopt-permissions》将该标签指定的 name 存入 package 的 mAdoptPermissions 这个 list 中。 Name 指定了这个 package 需要从 name 指定的 package 进行权限领养。在 system package 进行升级时使用。
// This package wants to adopt ownership of permissions from
// another package.
for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) {
final String origName = pkg.mAdoptPermissions.get(i);
final PackageSetting orig = mSettings.peekPackageLPr(origName);
if (orig != null) {
if (verifyPackageUpdateLPr(orig, pkg)) {
Slog.i(TAG, "Adopting permissions from " + origName + " to "
+ pkg.packageName);
mSettings.transferPermissionsLPw(origName, pkg.packageName);
}
}
}
}
}
final String pkgName = pkg.packageName;
final long scanFileTime = scanFile.lastModified();
final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
pkg.applicationInfo.processName = fixProcessName(
pkg.applicationInfo.packageName,
pkg.applicationInfo.processName,
pkg.applicationInfo.uid);
File dataPath;
if (mPlatformPackage == pkg) {
// The system package is special.
dataPath = new File (Environment.getDataDirectory(), "system");
pkg.applicationInfo.dataDir = dataPath.getPath();
} else {
// This is a normal package, need to make its data directory.
dataPath = getDataPathForPackage(pkg.packageName, 0); //⑥获取应用的/data/data/packageName目录;
boolean uidError = false;
if (dataPath.exists()) { //如果<span style="font-family: Arial, Helvetica, sans-serif;">/data/data/packageName目录存在;</span>
int currentUid = 0;
try {
StructStat stat = Libcore.os.stat(dataPath.getPath());
currentUid = stat.st_uid;
} catch (ErrnoException e) {
Slog.e(TAG, "Couldn't stat path " + dataPath.getPath(), e);
}
// If we have mismatched owners for the data path, we have a problem.
if (currentUid != pkg.applicationInfo.uid) { //如果/data/data/packageName的Uid与applicationInfo.uid有出入,那么以下逻辑会纠正;
boolean recovered = false;
if (currentUid == 0) {
// The directory somehow became owned by root. Wow.
// This is probably because the system was stopped while
// installd was in the middle of messing with its libs
// directory. Ask installd to fix that.
int ret = mInstaller.fixUid(pkgName, pkg.applicationInfo.uid,
pkg.applicationInfo.uid);
if (ret >= 0) {
recovered = true;
String msg = "Package " + pkg.packageName
+ " unexpectedly changed to uid 0; recovered to " +
+ pkg.applicationInfo.uid;
reportSettingsProblem(Log.WARN, msg);
}
}
if (!recovered && ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
|| (scanMode&SCAN_BOOTING) != 0)) {
// If this is a system app, we can at least delete its
// current data so the application will still work.
int ret = removeDataDirsLI(pkgName);
if (ret >= 0) {
// TODO: Kill the processes first
// Old data gone!
String prefix = (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0
? "System package " : "Third party package ";
String msg = prefix + pkg.packageName
+ " has changed from uid: "
+ currentUid + " to "
+ pkg.applicationInfo.uid + "; old data erased";
reportSettingsProblem(Log.WARN, msg);
recovered = true;
// And now re-install the app.
ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
pkg.applicationInfo.seinfo);
if (ret == -1) {
// Ack should not happen!
msg = prefix + pkg.packageName
+ " could not have data directory re-created after delete.";
reportSettingsProblem(Log.WARN, msg);
mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
return null;
}
}
if (!recovered) {
mHasSystemUidErrors = true;
}
} else if (!recovered) {
// If we allow this install to proceed, we will be broken.
// Abort, abort!
mLastScanError = PackageManager.INSTALL_FAILED_UID_CHANGED;
return null;
}
if (!recovered) {
pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
+ pkg.applicationInfo.uid + "/fs_"
+ currentUid;
pkg.applicationInfo.nativeLibraryDir = pkg.applicationInfo.dataDir;
String msg = "Package " + pkg.packageName
+ " has mismatched uid: "
+ currentUid + " on disk, "
+ pkg.applicationInfo.uid + " in settings";
// writer
synchronized (mPackages) {
mSettings.mReadMessages.append(msg);
mSettings.mReadMessages.append('\n');
uidError = true;
if (!pkgSetting.uidError) {
reportSettingsProblem(Log.ERROR, msg);
}
}
}
}
pkg.applicationInfo.dataDir = dataPath.getPath();
} else { <span style="font-family: Arial, Helvetica, sans-serif;">//如果</span><span style="font-family: Arial, Helvetica, sans-serif;">/data/data/packageName目录不存在,调用createDataDirsLI()进行创建/data/data/packagename目录;</span>
if (DEBUG_PACKAGE_SCANNING) {
if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
Log.v(TAG, "Want this data dir: " + dataPath);
}
//invoke installer to do the actual installation
int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
pkg.applicationInfo.seinfo);
if (ret < 0) {
// Error from installer
mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
return null;
}
if (dataPath.exists()) {
pkg.applicationInfo.dataDir = dataPath.getPath();
} else {
Slog.w(TAG, "Unable to create data directory: " + dataPath);
pkg.applicationInfo.dataDir = null;
}
}
/*
* Set the data dir to the default "/data/data/<package name>/lib"
* if we got here without anyone telling us different (e.g., apps
* stored on SD card have their native libraries stored in the ASEC
* container with the APK).
*
* This happens during an upgrade from a package settings file that
* doesn't have a native library path attribute at all.
*/
if (pkg.applicationInfo.nativeLibraryDir == null && pkg.applicationInfo.dataDir != null) { //⑥apk默认lib库目录为/data/data/packagename/lib,除非应用本身指定其他目录,对于存储在SD卡上apk,他们的native lib库保存在ASEC容器中;
if (pkgSetting.nativeLibraryPathString == null) {
setInternalAppNativeLibraryPath(pkg, pkgSetting);
} else {
pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString;
}
}
pkgSetting.uidError = uidError;
}
String path = scanFile.getPath(); //下面这段话的意思是,对于system apk,一般对本地二进制不进行解压,因为二进制文件已经存在/system/lib下,除非刚升级;对于安装在外置SD卡上的应用,也不进行解压,因为这些二进制文件已经存在于ASEC容器中;
/* Note: We don't want to unpack the native binaries for
* system applications, unless they have been updated
* (the binaries are already under /system/lib).
* Also, don't unpack libs for apps on the external card
* since they should have their libraries in the ASEC
* container already.
*
* In other words, we're going to unpack the binaries
* only for non-system apps and system app upgrades.
*/
if (pkg.applicationInfo.nativeLibraryDir != null) {
try {
File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
final String dataPathString = dataPath.getCanonicalPath();
if (isSystemApp(pkg) && !isUpdatedSystemApp(pkg)) {
/*
* Upgrading from a previous version of the OS sometimes
* leaves native libraries in the /data/data/<app>/lib
* directory for system apps even when they shouldn't be.
* Recent changes in the JNI library search path
* necessitates we remove those to match previous behavior.
*/
if (NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryDir)) {
Log.i(TAG, "removed obsolete native libraries for system package "
+ path);
}
} else {
if (!isForwardLocked(pkg) && !isExternal(pkg)) { //⑥安装在内置SD卡上的应用,创建native library目录;
/*
* Update native library dir if it starts with
* /data/data
*/
if (nativeLibraryDir.getPath().startsWith(dataPathString)) {
setInternalAppNativeLibraryPath(pkg, pkgSetting);
nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
}
try {
if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) {
Slog.e(TAG, "Unable to copy native libraries");
mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
return null;
}
} catch (IOException e) {
Slog.e(TAG, "Unable to copy native libraries", e);
mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
return null;
}
}
if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path);
final int[] userIds = sUserManager.getUserIds();
synchronized (mInstallLock) {
for (int userId : userIds) {
if (mInstaller.linkNativeLibraryDirectory(pkg.packageName,
pkg.applicationInfo.nativeLibraryDir, userId) < 0) { //⑥link native library;
Slog.w(TAG, "Failed linking native library dir (user=" + userId
+ ")");
mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
return null;
}
}
}
}
} catch (IOException ioe) {
Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
}
}
pkg.mScanPath = path;
if ((scanMode&SCAN_NO_DEX) == 0) { //⑥做Dex优化;
if (performDexOptLI(pkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false)
== DEX_OPT_FAILED) {
if ((scanMode & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
removeDataDirsLI(pkg.packageName);
}
mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
return null;
}
}
if (mFactoryTest && pkg.requestedPermissions.contains(
android.Manifest.permission.FACTORY_TEST)) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
}
ArrayList<PackageParser.Package> clientLibPkgs = null;
// writer
synchronized (mPackages) {
if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) { //⑥针对system apk 添加共享库;也只有system apk才能;
// Only system apps can add new shared libraries.
if (pkg.libraryNames != null) {
for (int i=0; i<pkg.libraryNames.size(); i++) {
String name = pkg.libraryNames.get(i);
boolean allowed = false;
if (isUpdatedSystemApp(pkg)) {
// New library entries can only be added through the
// system image. This is important to get rid of a lot
// of nasty edge cases: for example if we allowed a non-
// system update of the app to add a library, then uninstalling
// the update would make the library go away, and assumptions
// we made such as through app install filtering would now
// have allowed apps on the device which aren't compatible
// with it. Better to just have the restriction here, be
// conservative, and create many fewer cases that can negatively
// impact the user experience.
final PackageSetting sysPs = mSettings
.getDisabledSystemPkgLPr(pkg.packageName);
if (sysPs.pkg != null && sysPs.pkg.libraryNames != null) {
for (int j=0; j<sysPs.pkg.libraryNames.size(); j++) {
if (name.equals(sysPs.pkg.libraryNames.get(j))) {
allowed = true;
allowed = true;
break;
}
}
}
} else {
allowed = true;
}
if (allowed) {
if (!mSharedLibraries.containsKey(name)) {
mSharedLibraries.put(name, new SharedLibraryEntry(null,
pkg.packageName));
} else if (!name.equals(pkg.packageName)) {
Slog.w(TAG, "Package " + pkg.packageName + " library "
+ name + " already exists; skipping");
}
} else {
Slog.w(TAG, "Package " + pkg.packageName + " declares lib "
+ name + " that is not declared on system image; skipping");
}
}
if ((scanMode&SCAN_BOOTING) == 0) {
// If we are not booting, we need to update any applications
// that are clients of our shared library. If we are booting,
// this will all be done once the scan is complete.
clientLibPkgs = updateAllSharedLibrariesLPw(pkg);
}
}
}
}
// We also need to dexopt any apps that are dependent on this library. Note that
// if these fail, we should abort the install since installing the library will
// result in some apps being broken.
if (clientLibPkgs != null) { //⑥如果存在其他apk依赖正在安装的apk的库,那么也要对其他apk做dex优化;
if ((scanMode&SCAN_NO_DEX) == 0) {
for (int i=0; i<clientLibPkgs.size(); i++) {
PackageParser.Package clientPkg = clientLibPkgs.get(i);
if (performDexOptLI(clientPkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0, false)
== DEX_OPT_FAILED) {
if ((scanMode & SCAN_DELETE_DATA_ON_FAILURES) != 0) {
removeDataDirsLI(pkg.packageName);
}
mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
return null;
}
}
}
}
// Request the ActivityManager to kill the process(only for existing packages)
// so that we do not end up in a confused state while the user is still using the older
// version of the application while the new one gets installed.
if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { //⑥如果是替换安装,那么先请求AMS将进程干掉;
// If the package lives in an asec, tell everyone that the container is going
// away so they can clean up any references to its resources (which would prevent
// vold from being able to unmount the asec)
if (isForwardLocked(pkg) || isExternal(pkg)) {
if (DEBUG_INSTALL) {
Slog.i(TAG, "upgrading pkg " + pkg + " is ASEC-hosted -> UNAVAILABLE");
}
final int[] uidArray = new int[] { pkg.applicationInfo.uid };
final ArrayList<String> pkgList = new ArrayList<String>(1);
pkgList.add(pkg.applicationInfo.packageName);
sendResourcesChangedBroadcast(false, true, pkgList, uidArray, null);
}
// Post the request that it be killed now that the going-away broadcast is en route
killApplication(pkg.applicationInfo.packageName,
pkg.applicationInfo.uid, "update pkg");
}
// Also need to kill any apps that are dependent on the library.
if (clientLibPkgs != null) { //⑥对于依赖library库的应用也要干掉;
for (int i=0; i<clientLibPkgs.size(); i++) {
PackageParser.Package clientPkg = clientLibPkgs.get(i);
killApplication(clientPkg.applicationInfo.packageName,
clientPkg.applicationInfo.uid, "update lib");
}
}
// writer
synchronized (mPackages) {
// We don't expect installation to fail beyond this point,
if ((scanMode&SCAN_MONITOR) != 0) {
mAppDirs.put(pkg.mPath, pkg);
}
// Add the new setting to mSettings
mSettings.insertPackageSettingLPw(pkgSetting, pkg); //⑥将pkgSetting保存到mSettings.mPackages中去;
// Add the new setting to mPackages
mPackages.put(pkg.applicationInfo.packageName, pkg); //⑦将pkg添加到mPackages中去;
// Make sure we don't accidentally delete its data.
final Iterator<PackageCleanItem> iter = mSettings.mPackagesToBeCleaned.iterator();
while (iter.hasNext()) {
PackageCleanItem item = iter.next();
if (pkgName.equals(item.packageName)) {
iter.remove();
}
}
// Take care of first install / last update times.
if (currentTime != 0) {
if (pkgSetting.firstInstallTime == 0) {
pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
} else if ((scanMode&SCAN_UPDATE_TIME) != 0) {
pkgSetting.lastUpdateTime = currentTime;
}
} else if (pkgSetting.firstInstallTime == 0) {
// We need *something*. Take time time stamp of the file.
pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
} else if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
if (scanFileTime != pkgSetting.timeStamp) {
// A package on the system image has changed; consider this
// to be an update.
pkgSetting.lastUpdateTime = scanFileTime;
}
}
// Add the package's KeySets to the global KeySetManager
KeySetManager ksm = mSettings.mKeySetManager; //⑦KeySetManager是一个签名管理类;签名跟包名对应起来保存在这个类中;
try {
ksm.addSigningKeySetToPackage(pkg.packageName, pkg.mSigningKeys);
if (pkg.mKeySetMapping != null) {
for (Map.Entry<String, Set<PublicKey>> entry : pkg.mKeySetMapping.entrySet()) {
if (entry.getValue() != null) {
ksm.addDefinedKeySetToPackage(pkg.packageName,
entry.getValue(), entry.getKey());
}
}
}
} 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<N; i++) { //⑦对该apk所有的Provider保存到mProviders中,
PackageParser.Provider p = pkg.providers.get(i);
p.info.processName = fixProcessName(pkg.applicationInfo.processName,
p.info.processName, pkg.applicationInfo.uid);
mProviders.addProvider(p);
p.syncable = p.info.isSyncable;
if (p.info.authority != null) {
String names[] = p.info.authority.split(";");
p.info.authority = null;
for (int j = 0; j < names.length; j++) {
if (j == 1 && p.syncable) {
// We only want the first authority for a provider to possibly be
// syncable, so if we already added this provider using a different
// authority clear the syncable flag. We copy the provider before
// changing it because the mProviders object contains a reference
// to a provider that we don't want to change.
// Only do this for the second authority since the resulting provider
// object can be the same for all future authorities for this provider.
p = new PackageParser.Provider(p);
p.syncable = false;
}
if (!mProvidersByAuthority.containsKey(names[j])) { //⑧对provider中的所有authority保存与Provider 组成键值对保存在mProvidersByAuthority;还可以看出只要authority名已经存在过,那么就不会再保存,会skip这个authority值;
mProvidersByAuthority.put(names[j], p);
if (p.info.authority == null) {
p.info.authority = names[j];
} else {
p.info.authority = p.info.authority + ";" + names[j];
}
if (DEBUG_PACKAGE_SCANNING) {
if ((parseFlags & PackageParser.PARSE_CHATTY) != 0)
Log.d(TAG, "Registered content provider: " + names[j]
+ ", className = " + p.info.name + ", isSyncable = "
+ p.info.isSyncable);
}
} else {
PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
Slog.w(TAG, "Skipping provider name " + names[j] +
" (in package " + pkg.applicationInfo.packageName +
"): name already used by "
+ ((other != null && other.getComponentName() != null)
? other.getComponentName().getPackageName() : "?"));
}
}
}
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(p.info.name);
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Providers: " + r);
}
N = pkg.services.size();
r = null;
for (i=0; i<N; i++) { //⑦开始保存service,该apk的service会保存在mServices中,
PackageParser.Service s = pkg.services.get(i);
s.info.processName = fixProcessName(pkg.applicationInfo.processName,
s.info.processName, pkg.applicationInfo.uid);
mServices.addService(s);
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(s.info.name);
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Services: " + r);
}
N = pkg.receivers.size(); //⑧对于广播接收器receiver,会保存在mReceivers中;
r = null;
for (i=0; i<N; i++) {
PackageParser.Activity a = pkg.receivers.get(i);
a.info.processName = fixProcessName(pkg.applicationInfo.processName,
a.info.processName, pkg.applicationInfo.uid);
mReceivers.addActivity(a, "receiver");
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(a.info.name);
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Receivers: " + r);
}
N = pkg.activities.size(); //⑧对于activity,会保存在mActivities中;
r = null;
for (i=0; i<N; i++) {
PackageParser.Activity a = pkg.activities.get(i);
a.info.processName = fixProcessName(pkg.applicationInfo.processName,
a.info.processName, pkg.applicationInfo.uid);
mActivities.addActivity(a, "activity");
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(a.info.name);
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Activities: " + r);
}
N = pkg.permissionGroups.size(); //⑧对于apk的权限组,添加到mPermissionGroups中;一般没啥用;permission-group> tag
r = null;
for (i=0; i<N; i++) {
PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
if (cur == null) {
mPermissionGroups.put(pg.info.name, pg);
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(pg.info.name);
}
} else {
Slog.w(TAG, "Permission group " + pg.info.name + " from package "
+ pg.info.packageName + " ignored: original from "
+ cur.info.packageName);
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append("DUP:");
r.append(pg.info.name);
}
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permission Groups: " + r);
}
N = pkg.permissions.size(); //⑧<permission>tag中解析出来的;会保存到permissionMap中去;
r = null;
for (i=0; i<N; i++) {
PackageParser.Permission p = pkg.permissions.get(i);
HashMap<String, BasePermission> permissionMap =
p.tree ? mSettings.mPermissionTrees
: mSettings.mPermissions;
p.group = mPermissionGroups.get(p.info.group);
if (p.info.group == null || p.group != null) {
BasePermission bp = permissionMap.get(p.info.name);
if (bp == null) {
bp = new BasePermission(p.info.name, p.info.packageName,
BasePermission.TYPE_NORMAL);
permissionMap.put(p.info.name, bp);
}
if (bp.perm == null) {
if (bp.sourcePackage != null
&& !bp.sourcePackage.equals(p.info.packageName)) {
// If this is a permission that was formerly defined by a non-system
// app, but is now defined by a system app (following an upgrade),
// discard the previous declaration and consider the system's to be
// canonical.
if (isSystemApp(p.owner)) {
Slog.i(TAG, "New decl " + p.owner + " of permission "
+ p.info.name + " is system");
bp.sourcePackage = null;
}
}
if (bp.sourcePackage == null
|| bp.sourcePackage.equals(p.info.packageName)) {
BasePermission tree = findPermissionTreeLP(p.info.name);
if (tree == null
|| tree.sourcePackage.equals(p.info.packageName)) {
bp.packageSetting = pkgSetting;
bp.perm = p;
bp.uid = pkg.applicationInfo.uid;
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(p.info.name);
}
} else {
Slog.w(TAG, "Permission " + p.info.name + " from package "
+ p.info.packageName + " ignored: base tree "
+ tree.name + " is from package "
+ tree.sourcePackage);
}
} else {
Slog.w(TAG, "Permission " + p.info.name + " from package "
+ p.info.packageName + " ignored: original from "
+ bp.sourcePackage);
}
} else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append("DUP:");
r.append(p.info.name);
}
if (bp.perm == p) {
bp.protectionLevel = p.info.protectionLevel;
}
} else {
Slog.w(TAG, "Permission " + p.info.name + " from package "
+ p.info.packageName + " ignored: no group "
+ p.group);
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Permissions: " + r);
}
N = pkg.instrumentation.size(); //⑧<instrumentation>tag中解析出来的;保存在mInstrumentation中;
r = null;
for (i=0; i<N; i++) {
PackageParser.Instrumentation a = pkg.instrumentation.get(i);
a.info.packageName = pkg.applicationInfo.packageName;
a.info.sourceDir = pkg.applicationInfo.sourceDir;
a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
a.info.dataDir = pkg.applicationInfo.dataDir;
a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir;
mInstrumentation.put(a.getComponentName(), a);
if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
r.append(a.info.name);
}
}
if (r != null) {
if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Instrumentation: " + r);
}
if (pkg.protectedBroadcasts != null) {
N = pkg.protectedBroadcasts.size();
for (i=0; i<N; i++) {
mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
}
}
pkgSetting.setTimeStamp(scanFileTime); //保存时间戳;
}
return pkg;
}
总结:这个函数主要干了这么几件事:1、将packagename、PackageParser.Package键值对保存到mPackages中;2、为每个安装的apk创建一个PackageSetting对象;3、验证签名,验证 content providers是否与已经安装的apk存在冲突;5、为每个apk创建/data/data/packagename目录,为native library进行链接;6、对apk做odex优化;7、如果是替换安装,干掉已经存在的进程;8、对apk的签名、provide、receiver、service、activity、permissions、instrumentation进行保存,方便其他进程进行查询;
上面这个函数调用后会接着调用updateSettingsLI()将一些必要的信息写到/data/system/packages.xml中去进行保存。
9、 deletePackageX()--卸载apk
/**
* This method is an internal method that could be get invoked either
* to delete an installed package or to clean up a failed installation.
* After deleting an installed package, a broadcast is sent to notify any
* listeners that the package has been installed. For cleaning up a failed
* installation, the broadcast is not necessary since the package's
* installation wouldn't have sent the initial broadcast either
* The key steps in deleting a package are
* deleting the package information in internal structures like mPackages,
* deleting the packages base directories through installd
* updating mSettings to reflect current status
* persisting settings for later use
* sending a broadcast if necessary //①deletePackageX()函数既可以用来卸载一个已安装的apk,也可以用来清除安装失败的apk;卸载已安装的apk后会发送一个广播;卸载apk关键步骤是删除package信息,像mPackages、通过installd删除apk目录、更新mSettings;
*/
private int deletePackageX(String packageName, int userId, int flags) {
final PackageRemovedInfo info = new PackageRemovedInfo();
final boolean res;
if (isPackageDeviceAdmin(packageName, userId)) {
Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
}
boolean removedForAllUsers = false;
boolean systemUpdate = false;
// for the uninstall-updates case and restricted profiles, remember the per-
// userhandle installed state
int[] allUsers;
boolean[] perUserInstalled;
synchronized (mPackages) {
PackageSetting ps = mSettings.mPackages.get(packageName);
allUsers = sUserManager.getUserIds();
perUserInstalled = new boolean[allUsers.length];
for (int i = 0; i < allUsers.length; i++) {
perUserInstalled[i] = ps != null ? ps.getInstalled(allUsers[i]) : false;
}
}
synchronized (mInstallLock) {
if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageX: pkg=" + packageName + " user=" + userId);
res = deletePackageLI(packageName, //②调用这个函数进行卸载apk,这个将在下面详细分析;
(flags & PackageManager.DELETE_ALL_USERS) != 0
? UserHandle.ALL : new UserHandle(userId),
true, allUsers, perUserInstalled,
flags | REMOVE_CHATTY, info, true);
systemUpdate = info.isRemovedPackageSystemUpdate;
if (res && !systemUpdate && mPackages.get(packageName) == null) {
removedForAllUsers = true;
}
if (DEBUG_REMOVE) Slog.d(TAG, "delete res: systemUpdate=" + systemUpdate
+ " removedForAllUsers=" + removedForAllUsers);
}
if (res) { //③发送卸载广播;
info.sendBroadcast(true, systemUpdate, removedForAllUsers);
// If the removed package was a system update, the old system package
// was re-enabled; we need to broadcast this information
if (systemUpdate) {
Bundle extras = new Bundle(1);
extras.putInt(Intent.EXTRA_UID, info.removedAppId >= 0
? info.removedAppId : info.uid);
extras.putBoolean(Intent.EXTRA_REPLACING, true);
sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, null, null, null);
sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
extras, null, null, null);
sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null,
null, packageName, null, null);
}
}
// Force a gc here.
Runtime.getRuntime().gc();
// Delete the resources here after sending the broadcast to let
// other processes clean up before deleting resources.
if (info.args != null) {
synchronized (mInstallLock) {
info.args.doPostDeleteLI(true);
}
}
return res ? PackageManager.DELETE_SUCCEEDED : PackageManager.DELETE_FAILED_INTERNAL_ERROR;
}
10、deletePackageLI()
private boolean deletePackageLI(String packageName, UserHandle user,
boolean deleteCodeAndResources, int[] allUserHandles, boolean[] perUserInstalled,
int flags, PackageRemovedInfo outInfo,
boolean writeSettings) {
if (packageName == null) {
Slog.w(TAG, "Attempt to delete null packageName.");
return false;
}
if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageLI: " + packageName + " user " + user);
PackageSetting ps;
boolean dataOnly = false;
int removeUser = -1;
int appId = -1;
synchronized (mPackages) {
ps = mSettings.mPackages.get(packageName);
if (ps == null) {
Slog.w(TAG, "Package named '" + packageName + "' doesn't exist.");
return false;
}
if ((!isSystemApp(ps) || (flags&PackageManager.DELETE_SYSTEM_APP) != 0) && user != null
&& user.getIdentifier() != UserHandle.USER_ALL) { //①如果卸载systemAPP,那么必须设置DELETE_SYSTEM_APP flag;
// The caller is asking that the package only be deleted for a single
// user. To do this, we just mark its uninstalled state and delete
// its data. If this is a system app, we only allow this to happen if
// they have set the special DELETE_SYSTEM_APP which requests different
// semantics than normal for uninstalling system apps.
if (DEBUG_REMOVE) Slog.d(TAG, "Only deleting for single user");
ps.setUserState(user.getIdentifier(), //②设置PackageUserState状态;
COMPONENT_ENABLED_STATE_DEFAULT,
false, //installed
true, //stopped
true, //notLaunched
false, //blocked
null, null, null);
if (!isSystemApp(ps)) {
if (ps.isAnyInstalled(sUserManager.getUserIds())) {
// Other user still have this package installed, so all
// we need to do is clear this user's data and save that
// it is uninstalled.
if (DEBUG_REMOVE) Slog.d(TAG, "Still installed by other users");
removeUser = user.getIdentifier();
appId = ps.appId;
mSettings.writePackageRestrictionsLPr(removeUser);
} else {
// We need to set it back to 'installed' so the uninstall
// broadcasts will be sent correctly.
if (DEBUG_REMOVE) Slog.d(TAG, "Not installed by other users, full delete");
ps.setInstalled(true, user.getIdentifier()); //③对于非systemAPP,将状态先设回installed状态,方便广播接收;
}
} else {
// This is a system app, so we assume that the
// other users still have this package installed, so all
// we need to do is clear this user's data and save that
// it is uninstalled.
if (DEBUG_REMOVE) Slog.d(TAG, "Deleting system app");
removeUser = user.getIdentifier();
appId = ps.appId;
mSettings.writePackageRestrictionsLPr(removeUser);
}
}
}
if (removeUser >= 0) {
// From above, we determined that we are deleting this only
// for a single user. Continue the work here.
if (DEBUG_REMOVE) Slog.d(TAG, "Updating install state for user: " + removeUser);
if (outInfo != null) {
outInfo.removedPackage = packageName;
outInfo.removedAppId = appId;
outInfo.removedUsers = new int[] {removeUser};
}
mInstaller.clearUserData(packageName, removeUser);
removeKeystoreDataIfNeeded(removeUser, appId);
schedulePackageCleaning(packageName, removeUser, false);
return true;
}
if (dataOnly) {
// Delete application data first
if (DEBUG_REMOVE) Slog.d(TAG, "Removing package data only");
removePackageDataLI(ps, null, null, outInfo, flags, writeSettings);
return true;
}
boolean ret = false;
mSettings.mKeySetManager.removeAppKeySetData(packageName); //③移除签名信息;
if (isSystemApp(ps)) {
if (DEBUG_REMOVE) Slog.d(TAG, "Removing system package:" + ps.name);
// When an updated system application is deleted we delete the existing resources as well and
// fall back to existing code in system partition
ret = deleteSystemPackageLI(ps, allUserHandles, perUserInstalled,
flags, outInfo, writeSettings); //④如果是systemapp,调用deleteSystemPackageLI()进行卸载;
} else {
if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package:" + ps.name);
// Kill application pre-emptively especially for apps on sd.
killApplication(packageName, ps.appId, "uninstall pkg");
ret = deleteInstalledPackageLI(ps, deleteCodeAndResources, flags, //⑤如果是普通app,调用deleteInstalledPackageLI()进行卸载,卸载之前先调用killApplication()将app进程干掉;
allUserHandles, perUserInstalled,
outInfo, writeSettings);
}
return ret;
}
总结:这个函数主要设置apk状态,然后再调用deleteInstalledPackageLI()或deleteSystemPackageLI()进行卸载,deleteInstalledPackageLI()函数主要调用removePackageDataLI()将属于该apk的信息进行移除,下面详细分析这个函数:removePackageDataLI()
* This method deletes the package from internal data structures. If the DONT_DELETE_DATA
* flag is not set, the data directory is removed as well.
* make sure this flag is set for partially installed apps. If not its meaningless to
* delete a partially installed application.
*/
private void removePackageDataLI(PackageSetting ps,
int[] allUserHandles, boolean[] perUserInstalled,
PackageRemovedInfo outInfo, int flags, boolean writeSettings) {
String packageName = ps.name;
if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + ps);
removePackageLI(ps, (flags&REMOVE_CHATTY) != 0); //①调用该函数将app数据结构进行移除;removePackageLI()-->cleanPackageDataStructuresLILPw(),会删除
// Retrieve object to delete permissions for shared user later on
final PackageSetting deletedPs;
// reader
synchronized (mPackages) {
deletedPs = mSettings.mPackages.get(packageName);
if (outInfo != null) {
outInfo.removedPackage = packageName;
outInfo.removedUsers = deletedPs != null
? deletedPs.queryInstalledUsers(sUserManager.getUserIds(), true)
: null;
}
}
if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) { //②如果没有设置DELETE_KEEP_DATA属性,那么调用removeDataDirsLI()将data目录删掉;
removeDataDirsLI(packageName);
schedulePackageCleaning(packageName, UserHandle.USER_ALL, true);
}
// writer
synchronized (mPackages) {
if (deletedPs != null) {
if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
if (outInfo != null) {
outInfo.removedAppId = mSettings.removePackageLPw(packageName); //③从mSettings.mPackages中将app移除,并从mSharedUsers中将app移除;
}
if (deletedPs != null) {
updatePermissionsLPw(deletedPs.name, null, 0); //④从mSettings.mPermissionTrees移除属于该app的权限树;
if (deletedPs.sharedUser != null) {
// remove permissions associated with package
mSettings.updateSharedUserPermsLPw(deletedPs, mGlobalGids);
}
}
clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL);
}
// make sure to preserve per-user disabled state if this removal was just
// a downgrade of a system app to the factory package
if (allUserHandles != null && perUserInstalled != null) {
if (DEBUG_REMOVE) {
Slog.d(TAG, "Propagating install state across downgrade");
}
for (int i = 0; i < allUserHandles.length; i++) {
if (DEBUG_REMOVE) {
Slog.d(TAG, " user " + allUserHandles[i]
+ " => " + perUserInstalled[i]);
}
ps.setInstalled(perUserInstalled[i], allUserHandles[i]);
}
}
}
// can downgrade to reader
if (writeSettings) {
// Save settings now
mSettings.writeLPr(); //⑤更细/data/system/packages.xml
}
}
if (outInfo != null) {
// A user ID was deleted here. Go through all users and remove it
// from KeyStore.
removeKeystoreDataIfNeeded(UserHandle.USER_ALL, outInfo.removedAppId); //⑥移除签名信息;
}
}
总结:该方法主要讲app的数据结构从PMS中进行移除,如果设置了DONT_DELETE_DATA属性,那么就不会讲data删除;数据结构删除主要从mPackages、mAppDirs、mProviders、mProvidersByAuthority、mServices、mReceivers、mActivities、mSettings.mPermissions、mInstrumentation、mSharedLibraries(systemAPP)、mSettings.mPackages、mSettings.mPermissionTrees等list中进行移除。
7、PackageParser.PARSE_IS_SYSTEM
当调用scanDirLI()扫描安装某个目录下安装包时,传入的参数带PackageParser.PARSE_IS_SYSTEM表示该目录下的安装包是系统核心apk.
private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags,
int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
.........
if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
} else {
// Only allow system apps to be flagged as core apps.
pkg.coreApp = false;
}
...........
}
private static boolean isSystemApp(PackageParser.Package pkg) {
return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}
8、PackageManagerService.mPackages和Settings.mPackages
搞懂这两个变量对理解PMS很重要。PackageManagerService.mPackages中保存着<PackageName, PackageParser.Package>键值对,所有已经安装的包全部保存在这里;Settings.mPackages保存着<PackageName, PackageSetting>键值对,每次开机PMS初始化时会从/data/system/packages.xml中恢复出package到Settings.mPackages中,开机后安装的package也会更新到Settings.mPackages中。开机安装apk判断安装的apk是否是new package便是通过从.apk解析的信息跟Settings.mPackages的信息对比。
9、mPlatformPackage:指向/system/framework/framework-res.apk包。
mDisabledSysPackages:正在被替换的system apk会暂时保存在mDisabledSysPackages列表中,待安装完成便从mDisabledSysPackages中删除。
PackageParser.Package.usesLibraries:保存着AndroidManifest中<uses-library>标签中 android:required=true的库(当前模块依赖的 Java 共享库);
PackageParser.Package.usesOptionalLibraries:保存着AndroidManifest中<uses-library>标签中 android:required=false的库(当前模块依赖的 Java 共享库);