Android 8.1 源码_核心篇 — 深入研究 PackageManagerService 系列(3)

47次阅读

共计 40036 个字符,预计需要花费 101 分钟才能阅读完成。

开篇
核心源码

关键类
路径

SystemServer.java
frameworks/base/services/java/com/android/server/SystemServer.java

PackageManagerService.java
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

Process.java
frameworks/base/core/java/android/os/Process.java

SystemConfig.java
frameworks/base/core/java/com/android/server/SystemConfig.java

Settings.java
frameworks/base/services/core/java/com/android/server/pm/Settings.java

简介
PackageManagerService(PMS)是 SystemServer 启动后的第一个核心服务,也是 Android 系统中最常用的服务之一。它负责系统中 Package 的管理,应用程序的安装、卸载、信息查询等。如果你是面向 Android 系统开发的工程师,基础概念我也不需要再多赘述,我们直接跟源码。
PackageParser
parseMonolithicPackageLite
private static PackageLite parseMonolithicPackageLite(File packageFile, int flags)
throws PackageParserException {
final ApkLite baseApk = parseApkLite(packageFile, flags);
final String packagePath = packageFile.getAbsolutePath();
return new PackageLite(packagePath, baseApk, null, null, null, null, null, null);
}
这个方法就是调用 parseApkLite() 方法来获取一个 ApkLite 对象,然后用这个 ApkLite 对象构造一个 PackageLite 对象。
parseApkLite-01
/**
* Utility method that retrieves lightweight details about a single APK
* file, including package name, split name, and install location.
*
* @param apkFile path to a single APK
* @param flags optional parse flags, such as
* {@link #PARSE_COLLECT_CERTIFICATES}
*/
public static ApkLite parseApkLite(File apkFile, int flags)
throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();

// 创建 AssetManager 对象
AssetManager assets = null;
XmlResourceParser parser = null;
try {
assets = newConfiguredAssetManager();
int cookie = assets.addAssetPath(apkPath);
if (cookie == 0) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
“Failed to parse ” + apkPath);
}

final DisplayMetrics metrics = new DisplayMetrics();
metrics.setToDefaults();

parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);

final Signature[] signatures;
final Certificate[][] certificates;
// 设置签名
if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
// TODO: factor signature related items out of Package object
final Package tempPkg = new Package((String) null);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, “collectCertificates”);
try {
collectCertificates(tempPkg, apkFile, flags);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
signatures = tempPkg.mSignatures;
certificates = tempPkg.mCertificates;
} else {
signatures = null;
certificates = null;
}

final AttributeSet attrs = parser;
return parseApkLite(apkPath, parser, attrs, signatures, certificates);

} catch (XmlPullParserException | IOException | RuntimeException e) {
Slog.w(TAG, “Failed to parse ” + apkPath, e);
throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
“Failed to parse ” + apkPath, e);
} finally {
// 关闭资源管理器与解析器
IoUtils.closeQuietly(parser);
IoUtils.closeQuietly(assets);
}
}
parseApkLite-02
private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs,
Signature[] signatures, Certificate[][] certificates)
throws IOException, XmlPullParserException, PackageParserException {
// 调用了 parsePackageSplitNames() 方法来获取 packageSplit
final Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs);

int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
int versionCode = 0;
int revisionCode = 0;
boolean coreApp = false;
boolean debuggable = false;
boolean multiArch = false;
boolean use32bitAbi = false;
boolean extractNativeLibs = true;
boolean isolatedSplits = false;
boolean isFeatureSplit = false;
String configForSplit = null;
String usesSplitName = null;

// 遍历属性,并获取相应的值
for (int i = 0; i < attrs.getAttributeCount(); i++) {
final String attr = attrs.getAttributeName(i);
if (attr.equals(“installLocation”)) {
installLocation = attrs.getAttributeIntValue(i,
PARSE_DEFAULT_INSTALL_LOCATION);
} else if (attr.equals(“versionCode”)) {
versionCode = attrs.getAttributeIntValue(i, 0);
} else if (attr.equals(“revisionCode”)) {
revisionCode = attrs.getAttributeIntValue(i, 0);
} else if (attr.equals(“coreApp”)) {
coreApp = attrs.getAttributeBooleanValue(i, false);
} else if (attr.equals(“isolatedSplits”)) {
isolatedSplits = attrs.getAttributeBooleanValue(i, false);
} else if (attr.equals(“configForSplit”)) {
configForSplit = attrs.getAttributeValue(i);
} else if (attr.equals(“isFeatureSplit”)) {
isFeatureSplit = attrs.getAttributeBooleanValue(i, false);
}
}

// Only search the tree when the tag is directly below <manifest>
int type;
final int searchDepth = parser.getDepth() + 1;

final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
// private static final String TAG_PACKAGE_VERIFIER = “package-verifier”
// 继续解析 package-verifier 节点
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}

if (parser.getDepth() != searchDepth) {
continue;
}

if (TAG_PACKAGE_VERIFIER.equals(parser.getName())) {
final VerifierInfo verifier = parseVerifier(attrs);
if (verifier != null) {
verifiers.add(verifier);
}
} else if (TAG_APPLICATION.equals(parser.getName())) {
for (int i = 0; i < attrs.getAttributeCount(); ++i) {
final String attr = attrs.getAttributeName(i);
if (“debuggable”.equals(attr)) {
debuggable = attrs.getAttributeBooleanValue(i, false);
}
if (“multiArch”.equals(attr)) {
multiArch = attrs.getAttributeBooleanValue(i, false);
}
if (“use32bitAbi”.equals(attr)) {
use32bitAbi = attrs.getAttributeBooleanValue(i, false);
}
if (“extractNativeLibs”.equals(attr)) {
extractNativeLibs = attrs.getAttributeBooleanValue(i, true);
}
}
} else if (TAG_USES_SPLIT.equals(parser.getName())) {
if (usesSplitName != null) {
Slog.w(TAG, “Only one <uses-split> permitted. Ignoring others.”);
continue;
}

usesSplitName = attrs.getAttributeValue(ANDROID_RESOURCES, “name”);
if (usesSplitName == null) {
throw new PackageParserException(
PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
“<uses-split> tag requires ‘android:name’ attribute”);
}
}
}

// 利用解析出来的数据去构造一个 ApkLite 对象
return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
configForSplit, usesSplitName, versionCode, revisionCode, installLocation,
verifiers, signatures, certificates, coreApp, debuggable, multiArch, use32bitAbi,
extractNativeLibs, isolatedSplits);
}
parsePackageSplitNames
// 这个方法主要是解析 manifest
private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser,
AttributeSet attrs) throws IOException, XmlPullParserException,
PackageParserException {

int type;
while ((type = parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) {
}

if (type != XmlPullParser.START_TAG) {
throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
“No start tag found”);
}
if (!parser.getName().equals(TAG_MANIFEST)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
“No <manifest> tag”);
}

final String packageName = attrs.getAttributeValue(null, “package”);
if (!”android”.equals(packageName)) {
// 这个方法主要就是检测是否是数字、字母、下划线和点分隔符,这也是取包名的规则,
// 比如是字母数字下划线加点分隔符,否则都不是合法的应用包名。并且合法的包名至少包含一个点分隔符。
final String error = validateName(packageName, true, true);
if (error != null) {
throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
“Invalid manifest package: ” + error);
}
}

String splitName = attrs.getAttributeValue(null, “split”);
if (splitName != null) {
if (splitName.length() == 0) {
splitName = null;
} else {
final String error = validateName(splitName, false, false);
if (error != null) {
throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
“Invalid manifest split: ” + error);
}
}
}

return Pair.create(packageName.intern(),
(splitName != null) ? splitName.intern() : splitName);
}
parseBaseApk
private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
throws PackageParserException {
final String apkPath = apkFile.getAbsolutePath();

String volumeUuid = null;
if (apkPath.startsWith(MNT_EXPAND)) {
final int end = apkPath.indexOf(‘/’, MNT_EXPAND.length());
volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
}

mParseError = PackageManager.INSTALL_SUCCEEDED;
mArchiveSourcePath = apkFile.getAbsolutePath();

if (DEBUG_JAR) Slog.d(TAG, “Scanning base APK: ” + apkPath);

final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);

Resources res = null;
XmlResourceParser parser = null;
try {
res = new Resources(assets, mMetrics, null);
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);

final String[] outError = new String[1];
final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
if (pkg == null) {
throw new PackageParserException(mParseError,
apkPath + ” (at ” + parser.getPositionDescription() + “): ” + outError[0]);
}

pkg.setVolumeUuid(volumeUuid);
pkg.setApplicationVolumeUuid(volumeUuid);
pkg.setBaseCodePath(apkPath);
pkg.setSignatures(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);
}
}
parseBaseApk
private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
String[] outError) throws XmlPullParserException, IOException {
final String splitName;
final String pkgName;

try {
Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser);
pkgName = packageSplit.first;
splitName = packageSplit.second;

if (!TextUtils.isEmpty(splitName)) {
outError[0] = “Expected base APK, but found split ” + splitName;
mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
return null;
}
} catch (PackageParserException e) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
return null;
}

if (mCallback != null) {
String[] overlayPaths = mCallback.getOverlayPaths(pkgName, apkPath);
if (overlayPaths != null && overlayPaths.length > 0) {
for (String overlayPath : overlayPaths) {
res.getAssets().addOverlayPath(overlayPath);
}
}
}

// 用包名构造一个 Package
final Package pkg = new Package(pkgName);

// 获取资源数组
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifest);

// 初始化 pkg 的属性 mVersionCode、baseRevisionCode 和 mVersionName
pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
pkg.baseRevisionCode = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_revisionCode, 0);
pkg.mVersionName = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifest_versionName, 0);
if (pkg.mVersionName != null) {
pkg.mVersionName = pkg.mVersionName.intern();
}

// 判断是不是核心 app
pkg.coreApp = parser.getAttributeBooleanValue(null, “coreApp”, false);

sa.recycle();

// 解析 AndroidManifest 下面的每一个节点
return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
}
parseBaseApkCommon
private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
IOException {

… …

/* Set the global “forward lock” flag */
if ((flags & PARSE_FORWARD_LOCK) != 0) {
pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK;
}

/* Set the global “on SD card” flag */
// 是否要安装在 SD 卡上
if ((flags & PARSE_EXTERNAL_STORAGE) != 0) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
}

// Resource boolean are -1, so 1 means we don’t know the value.
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;
}

… …

// 解析 <application> 标签
if (tagName.equals(TAG_APPLICATION)) {
if (foundApp) {
if (RIGID_PARSER) {
outError[0] = “<manifest> has more than one <application>”;
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return null;
} else {
Slog.w(TAG, “<manifest> has more than one <application>”);
XmlUtils.skipCurrentTag(parser);
continue;
}
}

foundApp = true;
if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
return null;
}
// 解析 <overlay> 标签
} else if (tagName.equals(TAG_OVERLAY)) {
sa = res.obtainAttributes(parser,
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,
0);
pkg.mIsStaticOverlay = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestResourceOverlay_isStatic,
false);
final String propName = sa.getString(
com.android.internal.R.styleable
.AndroidManifestResourceOverlay_requiredSystemPropertyName);
final String propValue = sa.getString(
com.android.internal.R.styleable
.AndroidManifestResourceOverlay_requiredSystemPropertyValue);
sa.recycle();

if (pkg.mOverlayTarget == null) {
outError[0] = “<overlay> does not specify a target package”;
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return null;
}

if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
outError[0] = “<overlay> priority must be between 0 and 9999”;
mParseError =
PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return null;
}

// check to see if overlay should be excluded based on system property condition
if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
Slog.i(TAG, “Skipping target and overlay pair ” + pkg.mOverlayTarget + ” and ”
+ pkg.baseCodePath+ “: overlay ignored due to required system property: ”
+ propName + ” with value: ” + propValue);
return null;
}

XmlUtils.skipCurrentTag(parser);
// 解析 <key-sets> 标签
} else if (tagName.equals(TAG_KEY_SETS)) {
if (!parseKeySets(pkg, res, parser, outError)) {
return null;
}
// 解析 <permission-group> 标签
} else if (tagName.equals(TAG_PERMISSION_GROUP)) {
if (!parsePermissionGroup(pkg, flags, res, parser, outError)) {
return null;
}
// 解析 <permission> 标签
} else if (tagName.equals(TAG_PERMISSION)) {
if (!parsePermission(pkg, res, parser, outError)) {
return null;
}
// 解析 <permission-tree> 标签
} else if (tagName.equals(TAG_PERMISSION_TREE)) {
if (!parsePermissionTree(pkg, res, parser, outError)) {
return null;
}
// 解析 <uses-permission> 标签
} else if (tagName.equals(TAG_USES_PERMISSION)) {
if (!parseUsesPermission(pkg, res, parser)) {
return null;
}
// 解析 <uses-permission-sdk-m> 标签或者 <uses-permission-sdk-23> 标签
} else if (tagName.equals(TAG_USES_PERMISSION_SDK_M)
|| tagName.equals(TAG_USES_PERMISSION_SDK_23)) {
if (!parseUsesPermission(pkg, res, parser)) {
return null;
}
// 解析 <uses-configuration> 标签
} else if (tagName.equals(TAG_USES_CONFIGURATION)) {
ConfigurationInfo cPref = new ConfigurationInfo();
sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
cPref.reqTouchScreen = sa.getInt(
com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
Configuration.TOUCHSCREEN_UNDEFINED);
cPref.reqKeyboardType = sa.getInt(
com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
Configuration.KEYBOARD_UNDEFINED);
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
false)) {
cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
}
cPref.reqNavigation = sa.getInt(
com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
Configuration.NAVIGATION_UNDEFINED);
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
false)) {
cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
}
sa.recycle();
pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);

XmlUtils.skipCurrentTag(parser);
// 解析 <uses-feature> 标签
} else if (tagName.equals(TAG_USES_FEATURE)) {
FeatureInfo fi = parseUsesFeature(res, parser);
pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi);

if (fi.name == null) {
ConfigurationInfo cPref = new ConfigurationInfo();
cPref.reqGlEsVersion = fi.reqGlEsVersion;
pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref);
}

XmlUtils.skipCurrentTag(parser);
// 解析 <feature-group> 标签
} else if (tagName.equals(TAG_FEATURE_GROUP)) {
FeatureGroupInfo group = new FeatureGroupInfo();
ArrayList<FeatureInfo> features = null;
final int innerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}

final String innerTagName = parser.getName();
if (innerTagName.equals(“uses-feature”)) {
FeatureInfo featureInfo = parseUsesFeature(res, parser);
// FeatureGroups are stricter and mandate that
// any <uses-feature> declared are mandatory.
featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
features = ArrayUtils.add(features, featureInfo);
} else {
Slog.w(TAG, “Unknown element under <feature-group>: ” + innerTagName +
” at ” + mArchiveSourcePath + ” ” +
parser.getPositionDescription());
}
XmlUtils.skipCurrentTag(parser);
}

if (features != null) {
group.features = new FeatureInfo[features.size()];
group.features = features.toArray(group.features);
}
pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group);
// 解析 <uses-sdk> 标签
} else if (tagName.equals(TAG_USES_SDK)) {
if (SDK_VERSION > 0) {
sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestUsesSdk);

int minVers = 1;
String minCode = null;
int targetVers = 0;
String targetCode = null;

TypedValue val = sa.peekValue(
com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
if (val != null) {
if (val.type == TypedValue.TYPE_STRING && val.string != null) {
targetCode = minCode = val.string.toString();
} else {
// If it’s not a string, it’s an integer.
targetVers = minVers = val.data;
}
}

val = sa.peekValue(
com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
if (val != null) {
if (val.type == TypedValue.TYPE_STRING && val.string != null) {
targetCode = val.string.toString();
if (minCode == null) {
minCode = targetCode;
}
} else {
// If it’s not a string, it’s an integer.
targetVers = val.data;
}
}

sa.recycle();

final int minSdkVersion = PackageParser.computeMinSdkVersion(minVers, minCode,
SDK_VERSION, SDK_CODENAMES, outError);
if (minSdkVersion < 0) {
mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
return null;
}

final int targetSdkVersion = PackageParser.computeTargetSdkVersion(targetVers,
targetCode, SDK_VERSION, SDK_CODENAMES, outError);
if (targetSdkVersion < 0) {
mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
return null;
}

pkg.applicationInfo.minSdkVersion = minSdkVersion;
pkg.applicationInfo.targetSdkVersion = targetSdkVersion;
}

XmlUtils.skipCurrentTag(parser);
// 解析 <supports-screens> 标签
} else if (tagName.equals(TAG_SUPPORT_SCREENS)) {
sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestSupportsScreens);

pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
0);
pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
0);
pkg.applicationInfo.largestWidthLimitDp = sa.getInteger(
com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
0);

// This is a trick to get a boolean and still able to detect
// if a value was actually set.
supportsSmallScreens = sa.getInteger(
com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
supportsSmallScreens);
supportsNormalScreens = sa.getInteger(
com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
supportsNormalScreens);
supportsLargeScreens = sa.getInteger(
com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
supportsLargeScreens);
supportsXLargeScreens = sa.getInteger(
com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens,
supportsXLargeScreens);
resizeable = sa.getInteger(
com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
resizeable);
anyDensity = sa.getInteger(
com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
anyDensity);

sa.recycle();

XmlUtils.skipCurrentTag(parser);
// 解析 <protected-broadcast> 标签
} else if (tagName.equals(TAG_PROTECTED_BROADCAST)) {
sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);

// Note: don’t allow this value to be a reference to a resource
// that may change.
String name = sa.getNonResourceString(
com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);

sa.recycle();

if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
if (pkg.protectedBroadcasts == null) {
pkg.protectedBroadcasts = new ArrayList<String>();
}
if (!pkg.protectedBroadcasts.contains(name)) {
pkg.protectedBroadcasts.add(name.intern());
}
}

XmlUtils.skipCurrentTag(parser);
// 解析 <instrumentation> 标签
} else if (tagName.equals(TAG_INSTRUMENTATION)) {
if (parseInstrumentation(pkg, res, parser, outError) == null) {
return null;
}
// 解析 <original-package> 标签
} else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) {
sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestOriginalPackage);

String orig =sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);
if (!pkg.packageName.equals(orig)) {
if (pkg.mOriginalPackages == null) {
pkg.mOriginalPackages = new ArrayList<String>();
pkg.mRealPackage = pkg.packageName;
}
pkg.mOriginalPackages.add(orig);
}

sa.recycle();

XmlUtils.skipCurrentTag(parser);
// 解析 <adopt-permissions> 标签
} else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) {
sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestOriginalPackage);

String name = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0);

sa.recycle();

if (name != null) {
if (pkg.mAdoptPermissions == null) {
pkg.mAdoptPermissions = new ArrayList<String>();
}
pkg.mAdoptPermissions.add(name);
}

XmlUtils.skipCurrentTag(parser);
// 解析 <uses-gl-texture> 标签
} else if (tagName.equals(TAG_USES_GL_TEXTURE)) {
// Just skip this tag
XmlUtils.skipCurrentTag(parser);
continue;
// 解析 <compatible-screens> 标签
} else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) {
// Just skip this tag
XmlUtils.skipCurrentTag(parser);
continue;
// 解析 <supports-input> 标签
} else if (tagName.equals(TAG_SUPPORTS_INPUT)) {//
XmlUtils.skipCurrentTag(parser);
continue;
// 解析 <eat-comment> 标签
} else if (tagName.equals(TAG_EAT_COMMENT)) {
// Just skip this tag
XmlUtils.skipCurrentTag(parser);
continue;

} else if (tagName.equals(TAG_PACKAGE)) {
if (!MULTI_PACKAGE_APK_ENABLED) {
XmlUtils.skipCurrentTag(parser);
continue;
}
if (!parseBaseApkChild(pkg, res, parser, flags, outError)) {
// If parsing a child failed the error is already set
return null;
}

} else if (tagName.equals(TAG_RESTRICT_UPDATE)) {
if ((flags & PARSE_IS_SYSTEM_DIR) != 0) {
sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestRestrictUpdate);
final String hash = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestRestrictUpdate_hash, 0);
sa.recycle();

pkg.restrictUpdateHash = null;
if (hash != null) {
final int hashLength = hash.length();
final byte[] hashBytes = new byte[hashLength / 2];
for (int i = 0; i < hashLength; i += 2){
hashBytes[i/2] = (byte) ((Character.digit(hash.charAt(i), 16) << 4)
+ Character.digit(hash.charAt(i + 1), 16));
}
pkg.restrictUpdateHash = hashBytes;
}
}

XmlUtils.skipCurrentTag(parser);

} else if (RIGID_PARSER) {
outError[0] = “Bad element under <manifest>: ”
+ parser.getName();
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return null;

} else {
Slog.w(TAG, “Unknown element under <manifest>: ” + parser.getName()
+ ” at ” + mArchiveSourcePath + ” ”
+ parser.getPositionDescription());
XmlUtils.skipCurrentTag(parser);
continue;
}
}
parseBaseApplication
private boolean parseBaseApplication(Package owner, Resources res,
XmlResourceParser parser, int flags, String[] outError)
throws XmlPullParserException, IOException {
// 获取 ApplicationInfo 对象 ai
final ApplicationInfo ai = owner.applicationInfo;
// 获取包名
final String pkgName = owner.applicationInfo.packageName;

// 从资源里面获取 AndroidManifest 的数组
TypedArray sa = res.obtainAttributes(parser,
com.android.internal.R.styleable.AndroidManifestApplication);

if (!parsePackageItemInfo(owner, ai, outError,
“<application>”, sa, false /*nameRequired*/,
com.android.internal.R.styleable.AndroidManifestApplication_name,
com.android.internal.R.styleable.AndroidManifestApplication_label,
com.android.internal.R.styleable.AndroidManifestApplication_icon,
com.android.internal.R.styleable.AndroidManifestApplication_roundIcon,
com.android.internal.R.styleable.AndroidManifestApplication_logo,
com.android.internal.R.styleable.AndroidManifestApplication_banner)) {
sa.recycle();
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}

if (ai.name != null) {
ai.className = ai.name;
}

// 在 AndroidManifest 里面是否设置了 android:manageSpaceActivity 属性,
// 如果设置了则 manageSpaceActivity 不为空,没有设置 manageSpaceActivity 为空
String manageSpaceActivity = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_manageSpaceActivity,
Configuration.NATIVE_CONFIG_VERSION);
if (manageSpaceActivity != null) {
// 如果设置了,则添加类名
ai.manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity,
outError);
}

// 是否设置了 androidMannifest.xml 文件中 android:allowBackup 属性;
boolean allowBackup = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);
// 如果设置了允许备份
if (allowBackup) {
ai.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;

// backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
// and restoreAnyVersion are only relevant if backup is possible for the
// given application.
// 获取 backupAgent,如果在 AndroidManifest 里面设置了 android:backupAgent 属性,
// 则 backupAgent 不为空,否则 backupAgent 为空
String backupAgent = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_backupAgent,
Configuration.NATIVE_CONFIG_VERSION);
// 设置了 backupAgent,这构建类名
if (backupAgent != null) {
ai.backupAgentName = buildClassName(pkgName, backupAgent, outError);
if (DEBUG_BACKUP) {
Slog.v(TAG, “android:backupAgent = ” + ai.backupAgentName
+ ” from ” + pkgName + “+” + backupAgent);
}

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;
}
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_backupInForeground,
false)) {
ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
}
}

TypedValue v = sa.peekValue(
com.android.internal.R.styleable.AndroidManifestApplication_fullBackupContent);
if (v != null && (ai.fullBackupContent = v.resourceId) == 0) {
if (DEBUG_BACKUP) {
Slog.v(TAG, “fullBackupContent specified as boolean=” +
(v.data == 0 ? “false” : “true”));
}
// “false” => -1, “true” => 0
ai.fullBackupContent = (v.data == 0 ? -1 : 0);
}
if (DEBUG_BACKUP) {
Slog.v(TAG, “fullBackupContent=” + ai.fullBackupContent + ” for ” + pkgName);
}
}

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)) {
// Check if persistence is based on a feature being present
final String requiredFeature = sa.getNonResourceString(
com.android.internal.R.styleable.
AndroidManifestApplication_persistentWhenFeatureAvailable);
if (requiredFeature == null || mCallback.hasFeature(requiredFeature)) {
ai.flags |= ApplicationInfo.FLAG_PERSISTENT;
}
}
}

if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_requiredForAllUsers,
false)) {
owner.mRequiredForAllUsers = true;
}

String restrictedAccountType = sa.getString(com.android.internal.R.styleable
.AndroidManifestApplication_restrictedAccountType);
if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
owner.mRestrictedAccountType = restrictedAccountType;
}

String requiredAccountType = sa.getString(com.android.internal.R.styleable
.AndroidManifestApplication_requiredAccountType);
if (requiredAccountType != null && requiredAccountType.length() > 0) {
owner.mRequiredAccountType = requiredAccountType;
}

if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_debuggable,
false)) {
ai.flags |= ApplicationInfo.FLAG_DEBUGGABLE;
}

if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_vmSafeMode,
false)) {
ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
}

owner.baseHardwareAccelerated = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
if (owner.baseHardwareAccelerated) {
ai.flags |= ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
}

if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
true)) {
ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
}

if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_allowTaskReparenting,
false)) {
ai.flags |= ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
}

if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_allowClearUserData,
true)) {
ai.flags |= ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
}

// The parent package controls installation, hence specify test only installs.
if (owner.parentPackage == null) {
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
false)) {
ai.flags |= ApplicationInfo.FLAG_TEST_ONLY;
}
}

if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_largeHeap,
false)) {
ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
}

if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_usesCleartextTraffic,
true)) {
ai.flags |= ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
}

if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
false /* default is no RTL support*/)) {
ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
}

if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_multiArch,
false)) {
ai.flags |= ApplicationInfo.FLAG_MULTIARCH;
}

if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
true)) {
ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
}

if (sa.getBoolean(
R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
false)) {
ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
}
if (sa.getBoolean(
R.styleable.AndroidManifestApplication_directBootAware,
false)) {
ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
}

if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
if (sa.getBoolean(R.styleable.AndroidManifestApplication_resizeableActivity, true)) {
ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
} else {
ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
}
} else if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.N) {
ai.privateFlags |= PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
}

ai.maxAspectRatio = sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0);

ai.networkSecurityConfigRes = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifestApplication_networkSecurityConfig,
0);
ai.category = sa.getInt(
com.android.internal.R.styleable.AndroidManifestApplication_appCategory,
ApplicationInfo.CATEGORY_UNDEFINED);

String str;
str = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
ai.permission = (str != null && str.length() > 0) ? str.intern() : null;

if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
str = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity,
Configuration.NATIVE_CONFIG_VERSION);
} else {
// Some older apps have been seen to use a resource reference
// here that on older builds was ignored (with a warning). We
// need to continue to do this for them so they don’t break.
str = sa.getNonResourceString(
com.android.internal.R.styleable.AndroidManifestApplication_taskAffinity);
}
ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName,
str, outError);

if (outError[0] == null) {
CharSequence pname;
if (owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.FROYO) {
pname = sa.getNonConfigurationString(
com.android.internal.R.styleable.AndroidManifestApplication_process,
Configuration.NATIVE_CONFIG_VERSION);
} else {
// Some older apps have been seen to use a resource reference
// here that on older builds was ignored (with a warning). We
// need to continue to do this for them so they don’t break.
pname = sa.getNonResourceString(
com.android.internal.R.styleable.AndroidManifestApplication_process);
}
ai.processName = buildProcessName(ai.packageName, null, pname,
flags, mSeparateProcesses, outError);

ai.enabled = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_enabled, true);

if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_isGame, false)) {
ai.flags |= ApplicationInfo.FLAG_IS_GAME;
}

if (false) {
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_cantSaveState,
false)) {
ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;

// A heavy-weight application can not be in a custom process.
// We can do direct compare because we intern all strings.
if (ai.processName != null && ai.processName != ai.packageName) {
outError[0] = “cantSaveState applications can not use custom processes”;
}
}
}
}

ai.uiOptions = sa.getInt(
com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);

ai.classLoaderName = sa.getString(
com.android.internal.R.styleable.AndroidManifestApplication_classLoader);
if (ai.classLoaderName != null
&& !ClassLoaderFactory.isValidClassLoaderName(ai.classLoaderName)) {
outError[0] = “Invalid class loader name: ” + ai.classLoaderName;
}

sa.recycle();

if (outError[0] != null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}

final int innerDepth = parser.getDepth();
// IMPORTANT: These must only be cached for a single <application> to avoid components
// getting added to the wrong package.
final CachedComponentArgs cachedArgs = new CachedComponentArgs();
int type;

// 开始解析
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();
// 解析 activity
if (tagName.equals(“activity”)) {
Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
owner.baseHardwareAccelerated);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}

owner.activities.add(a);

// 解析 receiver
} else if (tagName.equals(“receiver”)) {
Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
true, false);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}

owner.receivers.add(a);
// 解析 service
} else if (tagName.equals(“service”)) {
Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
if (s == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}

owner.services.add(s);
// 解析 provider
} else if (tagName.equals(“provider”)) {
Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
if (p == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}

owner.providers.add(p);

… …

} else {
if (!RIGID_PARSER) {
Slog.w(TAG, “Unknown element under <application>: ” + tagName
+ ” at ” + mArchiveSourcePath + ” ”
+ parser.getPositionDescription());
XmlUtils.skipCurrentTag(parser);
continue;
} else {
outError[0] = “Bad element under <application>: ” + tagName;
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}
}
}

// Must be ran after the entire {@link ApplicationInfo} has been fully processed and after
// every activity info has had a chance to set it from its attributes.
setMaxAspectRatio(owner);

PackageBackwardCompatibility.modifySharedLibraries(owner);

// 检查 IntentFilter 之一是否包含 DEFAULT / VIEW 和 HTTP / HTTPS 数据 URI
if (hasDomainURLs(owner)) {
owner.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
} else {
owner.applicationInfo.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
}

return true;
}
其实这个方法就是解析了 application 节点下的所有信息,比如 activity、service、receiver、provider、library、users-librayry 等信息,同时将解析后的每一个属性生成相应的对象,添加到传入的 package 里面,这些信息最后都会在 PackageManagerService 中用到。
扫描非系统 Package
if (!mOnlyCore) {// mOnlyCore 用于控制是否扫描非系统 Package
// do this first before mucking with mPackages for the “expecting better” case
final Iterator<PackageParser.Package> pkgIterator = mPackages.values().iterator();
while (pkgIterator.hasNext()) {
final PackageParser.Package pkg = pkgIterator.next();
if (pkg.isStub) {
stubSystemApps.add(pkg.packageName);
}
}

final Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
while (psit.hasNext()) {
PackageSetting ps = psit.next();

/*
* If this is not a system app, it can’t be a
* disable system app.
*/
if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
/// M: Operator apps are belong to system domain, therefore, need prune.
/// We should also consider OTA from old version without mtkFlag
if (sPmsExt.isNotOperatorApp(ps))
continue;
}

/*
* If the package is scanned, it’s not erased.
*/
final PackageParser.Package scannedPkg = mPackages.get(ps.name);
if (scannedPkg != null) {
/*
* If the system app is both scanned and in the
* disabled packages list, then it must have been
* added via OTA. Remove it from the currently
* scanned package so the previously user-installed
* application can be scanned.
*/
if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
logCriticalInfo(Log.WARN, “Expecting better updated system app for ”
+ ps.name + “; removing system app. Last known codePath=”
+ ps.codePathString + “, installStatus=” + ps.installStatus
+ “, versionCode=” + ps.versionCode + “; scanned versionCode=”
+ scannedPkg.mVersionCode);
removePackageLI(scannedPkg, true);
mExpectingBetter.put(ps.name, ps.codePath);
}

continue;
}

if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
psit.remove();
logCriticalInfo(Log.WARN, “System package ” + ps.name
+ ” no longer exists; it’s data will be wiped”);
// Actual deletion of code and data will be handled by later
// reconciliation step
} else {
// we still have a disabled system package, but, it still might have
// been removed. check the code path still exists and check there’s
// still a package. the latter can happen if an OTA keeps the same
// code path, but, changes the package name.
final PackageSetting disabledPs =
mSettings.getDisabledSystemPkgLPr(ps.name);
if (disabledPs.codePath == null || !disabledPs.codePath.exists()
|| disabledPs.pkg == null) {
possiblyDeletedUpdatedSystemApps.add(ps.name);
}
}
}
}

if (!mOnlyCore) {
scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);

scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
| PackageParser.PARSE_FORWARD_LOCK,
scanFlags | SCAN_REQUIRE_KNOWN, 0);

// Remove disable package settings for updated system apps that were
// removed via an OTA. If the update is no longer present, remove the
// app completely. Otherwise, revoke their system privileges.
for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
mSettings.removeDisabledSystemPackageLPw(deletedAppName);

final String msg;
if (deletedPkg == null) {
// should have found an update, but, we didn’t; remove everything
msg = “Updated system package ” + deletedAppName
+ ” no longer exists; removing its data”;
// Actual deletion of code and data will be handled by later
// reconciliation step
} else {
// found an update; revoke system privileges
msg = “Updated system package + ” + deletedAppName
+ ” no longer exists; revoking system privileges”;

// Don’t do anything if a stub is removed from the system image. If
// we were to remove the uncompressed version from the /data partition,
// this is where it’d be done.

final PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
/// M: [Operator] Revoke operator permissions for the original operator
sPmsExt.clearExtFlags(deletedPkg, deletedPs);
}
logCriticalInfo(Log.WARN, msg);
}

/*
* Make sure all system apps that we expected to appear on
* the userdata partition actually showed up. If they never
* appeared, crawl back and revive the system version.
*/
for (int i = 0; i < mExpectingBetter.size(); i++) {
final String packageName = mExpectingBetter.keyAt(i);
if (!mPackages.containsKey(packageName)) {
final File scanFile = mExpectingBetter.valueAt(i);

logCriticalInfo(Log.WARN, “Expected better ” + packageName
+ ” but never showed up; reverting to system”);

int reparseFlags = mDefParseFlags;
if (FileUtils.contains(privilegedAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED;
} else if (FileUtils.contains(systemAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR;
} else if (FileUtils.contains(vendorAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR;
} else if (FileUtils.contains(oemAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR;
} else {
Slog.e(TAG, “Ignoring unexpected fallback path ” + scanFile);
continue;
}

mSettings.enableSystemPackageLPw(packageName);

try {
scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 0, null);
} catch (PackageManagerException e) {
Slog.e(TAG, “Failed to parse original system package: ”
+ e.getMessage());
}
}
}

// Uncompress and install any stubbed system applications.
// This must be done last to ensure all stubs are replaced or disabled.
decompressSystemApplications(stubSystemApps, scanFlags);

final int cachedNonSystemApps = PackageParser.sCachedPackageReadCount.get()
– cachedSystemApps;

final long dataScanTime = SystemClock.uptimeMillis() – systemScanTime – startTime;
final int dataPackagesCount = mPackages.size() – systemPackagesCount;
Slog.i(TAG, “Finished scanning non-system apps. Time: ” + dataScanTime
+ ” ms, packageCount: ” + dataPackagesCount
+ ” , timePerPackage: ”
+ (dataPackagesCount == 0 ? 0 : dataScanTime / dataPackagesCount)
+ ” , cached: ” + cachedNonSystemApps);
if (mIsUpgrade && dataPackagesCount > 0) {
MetricsLogger.histogram(null, “ota_package_manager_data_app_avg_scan_time”,
((int) dataScanTime) / dataPackagesCount);
}
}
构造函数分析 – 扫尾工作
这部分任务比较简单,就是将第二阶段手机的信息再集中整理一次,可自行研究。
总结
第二阶段分析就此结束!

正文完
 0