您的位置:首页 > 移动开发 > Android开发

PackageManagerService分析之二

2017-03-12 08:49 281 查看

3, 扫描Package

第二个阶段的工作主要是扫描系统中的APK,由于需要逐个扫描apk文件,因此手机上安装的程序越多,

PKM的工作量越大,系统启动速度越慢,也就是开机时间越长

3.1 系统库的dex优化

以下的代码主要是对系统库BOOTCLASSPATH指定,或platform.xml定义,

或者/system/frameworks目录下的jar和apk包进行一次检查,该dex优化的优化.dex优化后会在相应的目录生成.odex文件.

这里扫描所有的/system/framework下面除framework-res以外的apk和jar包(因为framework-res只有 resource文件),

然后依次对它们做Dex优化。在上面如果有对文件做过Dex优化,就要去删除dalvi-cache下面所有的dex文件,

以防 止cache文件和现在的文件不相符。

File frameworkDir = new File(Environment.getRootDirectory(), "framework");

// Gross hack for now: we know this file doesn't contain any
// code, so don't dexopt it to avoid the resulting log spew.
alreadyDexOpted.add(frameworkDir.getPath() + "/framework-res.apk");

// Gross hack for now: we know this file is only part of
// the boot class path for art, so don't dexopt it to
// avoid the resulting log spew.
alreadyDexOpted.add(frameworkDir.getPath() + "/core-libart.jar");

/**
* There are a number of commands implemented in Java, which
* we currently need to do the dexopt on so that they can be
* run from a non-root shell.
*/
String[] frameworkFiles = frameworkDir.list();

3.2 扫描apk

调用scanDirLI去扫描文件夹

/vendor/overlay

/system/priv-app  /system/app 

/vendor/app

File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
scanDirLI(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags | SCAN_TRUSTED_OVERLAY, 0);

// Find base frameworks (resource packages without code).
scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED,
scanFlags | SCAN_NO_DEX, 0);

// Collected privileged system packages.
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);

// Collect ordinary system packages.
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

// Collect all vendor packages.
File vendorAppDir = new File("/vendor/app");
try {
vendorAppDir = vendorAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

// Collect all OEM packages.
final File oemAppDir = new File(Environment.getOemDirectory(), "app");
scanDirLI(oemAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

// Collect all Regionalization packages form Carrier's res packages.
if (RegionalizationEnvironment.isSupported()) {
Log.d(TAG, "Load Regionalization vendor apks");
final List<File> RegionalizationDirs =
RegionalizationEnvironment.getAllPackageDirectories();
for (File f : RegionalizationDirs) {
File RegionalizationSystemDir = new File(f, "system");
// Collect packages in <Package>/system/priv-app
scanDirLI(new File(RegionalizationSystemDir, "priv-app"),
PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
// Collect packages in <Package>/system/app
scanDirLI(new File(RegionalizationSystemDir, "app"),
PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags, 0);
// Collect overlay in <Package>/system/vendor
scanDirLI(new File(RegionalizationSystemDir, "vendor/overlay"),
PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR,
scanFlags | SCAN_TRUSTED_OVERLAY, 0);
}
}

3.2.1 parsePackage

scanPackageLI首先调用PackageParser的parsePackage去解析扫描的文件,

注意这里有两个parsePackage函数,但它们的参数不同. 流程图如下,



PackageParser pp = new PackageParser();
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
pp.setDisplayMetrics(mMetrics);

if ((scanFlags & SCAN_TRUSTED_OVERLAY) != 0) {
parseFlags |= PackageParser.PARSE_TRUSTED_OVERLAY;
}

final PackageParser.Package pkg;
try {
pkg = pp.parsePackage(scanFile, parseFlags);
} catch (PackageParserException e) {
throw PackageManagerException.from(e);
}

parseBaseApk方法虽然很长,但是逻辑很简单,解析apk的AndroidManifest文件,

int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
continue;
}

String tagName = parser.getName();
if (tagName.equals("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, attrs, flags, outError)) {
return null;
}
} else if (tagName.equals("overlay")) {
pkg.mTrustedOverlay = trustedOverlay;

sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AndroidManifestResourceOverlay);
pkg.mOverlayTarget = sa.getString(
com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
pkg.mOverlayPriority = sa.getInt(
com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
-1);
sa.recycle();

if (pkg.mOverlayTarget == null) {
outError[0] = "<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;
}
XmlUtils.skipCurrentTag(parser);

} else if (tagName.equals("key-sets")) {
if (!parseKeySets(pkg, res, parser, attrs, outError)) {
return null;
}
} else if (tagName.equals("permission-group")) {
if (parsePermissionGroup(pkg, flags, res, parser, attrs, outError) == null) {
return null;
}
} else if (tagName.equals("permission")) {
if (parsePermission(pkg, res, parser, attrs, outError) == null) {
return null;
}
} else if (tagName.equals("permission-tree")) {
if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
return null;
}
} else if (tagName.equals("uses-permission")) {
if (!parseUsesPermission(pkg, res, parser, attrs)) {
return null;
}
} else if (tagName.equals("uses-permission-sdk-m")
|| tagName.equals("uses-permission-sdk-23")) {
if (!parseUsesPermission(pkg, res, parser, attrs)) {
return null;
}
}
•••

parseBaseApplication方法会解析Application中的内容,包括四大组件,并且receiver被当成activity来解析

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();
if (tagName.equals("activity")) {
Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
owner.baseHardwareAccelerated);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}

owner.activities.add(a);

} else if (tagName.equals("receiver")) {
Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}

owner.receivers.add(a);

} else if (tagName.equals("service")) {
Service s = parseService(owner, res, parser, attrs, flags, outError);
if (s == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}

owner.services.add(s);

} else if (tagName.equals("provider")) {
Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
if (p == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}

owner.providers.add(p);

} else if (tagName.equals("activity-alias")) {
Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);
if (a == null) {
mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
return false;
}

owner.activities.add(a);

}
•••

最后解析的相关参数的都存放在PackageParser的内部类Package的数组中,

public final ApplicationInfo applicationInfo = new ApplicationInfo();

public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
public final ArrayList<Service> services = new ArrayList<Service>(0);
public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);

3.2.2 scanPackageLI

scanPackageLI调用流程图如下,



scanPackageDirtyLI会取出PackageParser四大组件,然后分别调用其内部类完成添加到数组。

这四个内部类都继承自IntentResolver。添加activity的方法如下,

N = pkg.activities.size();
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);
}
}

ActivityIntentResolver的addActivity方法如下,

public final void addActivity(PackageParser.Activity a, String type) {
final boolean systemApp = a.info.applicationInfo.isSystemApp();
mActivities.put(a.getComponentName(), a);
if (DEBUG_SHOW_INFO)
Log.v(
TAG, "  " + type + " " +
(a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
if (DEBUG_SHOW_INFO)
Log.v(TAG, "    Class=" + a.info.name);
final int NI = a.intents.size();
for (int j=0; j<NI; j++) {
PackageParser.ActivityIntentInfo intent = a.intents.get(j);
if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) {
intent.setPriority(0);
Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity "
+ a.className + " with priority > 0, forcing to 0");
}
if (DEBUG_SHOW_INFO) {
Log.v(TAG, "    IntentFilter:");
intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
}
if (!intent.debugCheck()) {
Log.w(TAG, "==> For Activity " + a.info.name);
}
addFilter(intent);
}
}

addFilter方法以后启动activity的时候再详细论述。

4, 扫描Package

PMS将前面收集的信息再整理一次,将已安装的apk信息写到package.xml、pacakage.list和package-stopped.xml中

updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
ver.sdkVersion = mSdkVersion;

// If this is the first boot or an update from pre-M, and it is a normal
// boot, then we need to initialize the default preferred apps across
// all defined users.
if (!onlyCore && (mPromoteSystemApps || !mRestoredSettings)) {
for (UserInfo user : sUserManager.getUsers(true)) {
mSettings.applyDefaultPreferredAppsLPw(this, user.id);
applyFactoryDefaultBrowserLPw(user.id);
primeDomainVerificationsLPw(user.id);
}
}

// If this is first boot after an OTA, and a normal boot, then
// we need to clear code cache directories.
if (mIsUpgrade && !onlyCore) {
Slog.i(TAG, "Build fingerprint changed; clearing code caches");
for (int i = 0; i < mSettings.mPackages.size(); i++) {
final PackageSetting ps = mSettings.mPackages.valueAt(i);
if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
deleteCodeCacheDirsLI(ps.volumeUuid, ps.name);
}
}
ver.fingerprint = Build.FINGERPRINT;
}

checkDefaultBrowser();

// clear only after permissions and other defaults have been updated
mExistingSystemPackages.clear();
mPromoteSystemApps = false;

// All the changes are done during package scanning.
ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;

// can downgrade to reader
mSettings.writeLPr();

EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());

mRequiredVerifierPackage = getRequiredVerifierLPr();
mRequiredInstallerPackage = getRequiredInstallerLPr();

mInstallerService = new PackageInstallerService(context, this);

mIntentFilterVerifierComponent = getIntentFilterVerifierComponentNameLPr();
mIntentFilterVerifier = new IntentVerifierProxy(mContext,
mIntentFilterVerifierComponent);

packages.xml:系统对程序安装,卸载和更新等操作时会更新该文件,PMS扫描完目标文件夹后创建该文件,保存了Package相关的信息。
packages.list:保存着系统中所有的非系统自带的APK信息,程序安装,卸载和更新会更新该文件。
packages-stoped.xml:保存系统中被用户强制停止的Package的信息。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息