赞
踩
如果了解过android的启动流程,我们知道android在启动的时候会去解析/data/system和/data/app下已经存在的apk。
那么是从哪里开始对这些包进行解析的呢?
1.
- public static final IPackageManager main(Context context, Installer installer,
- boolean factoryTest, boolean onlyCore) {
- PackageManagerService m = new PackageManagerService(context, installer,
- factoryTest, onlyCore);
- ServiceManager.addService("package", m);
- return m;
- }
android在启动的时候,会根据init.rc配置文件去执行PackageManagerService中的main方法。
该方法的操作很简单,就是生成一个PackageManagerService的对象,然后加载到ServiceManager进程中进行管理。
从这里我们就可以看出,ServiceManager进程就是用来管理android中Framework层的一些系统Service。
2.
main方法中代码很少,那么PackageManagerService是在哪里解析包的呢?
实际上在new一个PackageManagerService对象的时候,就对已存在的apk进行了解析。
下面我们对/data/app/下的apk解析过程做一个分析。
- synchronized (mPackages) {
- mHandlerThread.start();
- mHandler = new PackageHandler(mHandlerThread.getLooper());
-
- File dataDir = Environment.getDataDirectory();
- mAppDataDir = new File(dataDir, "data");
- mAppInstallDir = new File(dataDir, "app");
- mAppLibInstallDir = new File(dataDir, "app-lib");
- mAsecInternalPath = new File(dataDir, "app-asec").getPath();
- mUserAppDataDir = new File(dataDir, "user");
- mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
-
- sUserManager = new UserManagerService(context, this,
- mInstallLock, mPackages);
在这里对android的一些路径进行了获取,这里我们就看到android默认的用户安装路径mAppInstallDir就是/data/app/。
知道用户的apk所在路径,下面就可以去遍历该路径下的所有apk,然后进行解析。
- if (!mOnlyCore) {
- EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
- SystemClock.uptimeMillis());
- mAppInstallObserver = new AppDirObserver(
- mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
- mAppInstallObserver.startWatching();
- scanDirLI(mAppInstallDir, 0, scanMode, 0);
-
- mDrmAppInstallObserver = new AppDirObserver(
- mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
- mDrmAppInstallObserver.startWatching();
- scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
- scanMode, 0);
- private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
- String[] files = dir.list();
- if (files == null) {
- Log.d(TAG, "No files in app dir " + dir);
- return;
- }
-
- if (DEBUG_PACKAGE_SCANNING) {
- Log.d(TAG, "Scanning app dir " + dir);
- }
-
- int i;
- for (i=0; i<files.length; i++) {
- File file = new File(dir, files[i]);
- if (!isPackageFilename(files[i])) {
- // Ignore entries which are not apk's
- continue;
- }
- PackageParser.Package pkg = scanPackageLI(file,
- flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);
- // Don't mess around with apps in system partition.
- if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
- mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
- // Delete the apk
- Slog.w(TAG, "Cleaning up failed install of " + file);
- file.delete();
- }
- }
- }
通过dir.list()我们得到/data/app/下所有的文件名,然后在后面的for循环中逐个判断是否是*.apk文件,如果是,就调用scanPackageLI进行解析;
如果不是,就继续循环,寻找下一个apk文件。
下面进入scanPackageLI
- private PackageParser.Package scanPackageLI(File scanFile,
- int parseFlags, int scanMode, long currentTime, UserHandle user) {
- mLastScanError = PackageManager.INSTALL_SUCCEEDED;
- String scanPath = scanFile.getPath();
- parseFlags |= mDefParseFlags;
- PackageParser pp = new PackageParser(scanPath);
- pp.setSeparateProcesses(mSeparateProcesses);
- pp.setOnlyCoreApps(mOnlyCore);
- final PackageParser.Package pkg = pp.parsePackage(scanFile,
- scanPath, mMetrics, parseFlags);
- if (pkg == null) {
- mLastScanError = pp.getParseError();
- return null;
- }
- PackageSetting ps = null;
- PackageSetting updatedPkg;
- final PackageParser.Package pkg = pp.parsePackage(scanFile,
- scanPath, mMetrics, parseFlags);
这里就是去解析apk文件,从scanpackageLI的代码看出pp实际是一个PackageParser对象。
3. PackageParser.java
上面的pp.parsePackage会调用如下:
- try {
- // XXXX todo: need to figure out correct configuration.
- pkg = parsePackage(res, parser, flags, errorText);
- } catch (Exception e) {
- errorException = e;
- mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
- }
在这里面回去分析AndroidManifest.xml文件,当获取到application标签时,回去解析下面存在的控件。
- 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 (!parseApplication(pkg, res, parser, attrs, flags, outError)) {
- return null;
- }
parseApplication就是去解析标签<application>中的资源。
下面我们来看一下parseApplication是怎么解析provider的。
- 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,
- hardwareAccelerated);
- 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);
-
- }
当我们的标签是provider时,就会调用parseProvider去解析。解析完成后就会把得到的Provider加入到owner.provider中。
- private Provider parseProvider(Package owner, Resources res,
- XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
- throws XmlPullParserException, IOException {
- TypedArray sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestProvider);
-
- if (mParseProviderArgs == null) {
- mParseProviderArgs = new ParseComponentArgs(owner, outError,
- com.android.internal.R.styleable.AndroidManifestProvider_name,
- com.android.internal.R.styleable.AndroidManifestProvider_label,
- com.android.internal.R.styleable.AndroidManifestProvider_icon,
- com.android.internal.R.styleable.AndroidManifestProvider_logo,
- mSeparateProcesses,
- com.android.internal.R.styleable.AndroidManifestProvider_process,
- com.android.internal.R.styleable.AndroidManifestProvider_description,
- com.android.internal.R.styleable.AndroidManifestProvider_enabled);
- mParseProviderArgs.tag = "<provider>";
- }
-
- mParseProviderArgs.sa = sa;
- mParseProviderArgs.flags = flags;
-
- Provider p = new Provider(mParseProviderArgs, new ProviderInfo());
- if (outError[0] != null) {
- sa.recycle();
- return null;
- }
-
- boolean providerExportedDefault = false;
-
- if (owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
- // For compatibility, applications targeting API level 16 or lower
- // should have their content providers exported by default, unless they
- // specify otherwise.
- providerExportedDefault = true;
- }
-
- p.info.exported = sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestProvider_exported,
- providerExportedDefault);
-
- String cpname = sa.getNonConfigurationString(
- com.android.internal.R.styleable.AndroidManifestProvider_authorities, 0);
-
- p.info.isSyncable = sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestProvider_syncable,
- false);
-
- String permission = sa.getNonConfigurationString(
- com.android.internal.R.styleable.AndroidManifestProvider_permission, 0);
- String str = sa.getNonConfigurationString(
- com.android.internal.R.styleable.AndroidManifestProvider_readPermission, 0);
- if (str == null) {
- str = permission;
- }
- if (str == null) {
- p.info.readPermission = owner.applicationInfo.permission;
- } else {
- p.info.readPermission =
- str.length() > 0 ? str.toString().intern() : null;
- }
- str = sa.getNonConfigurationString(
- com.android.internal.R.styleable.AndroidManifestProvider_writePermission, 0);
- if (str == null) {
- str = permission;
- }
- if (str == null) {
- p.info.writePermission = owner.applicationInfo.permission;
- } else {
- p.info.writePermission =
- str.length() > 0 ? str.toString().intern() : null;
- }
-
- p.info.grantUriPermissions = sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestProvider_grantUriPermissions,
- false);
-
- p.info.multiprocess = sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestProvider_multiprocess,
- false);
-
- p.info.initOrder = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestProvider_initOrder,
- 0);
-
- p.info.flags = 0;
-
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestProvider_singleUser,
- false)) {
- p.info.flags |= ProviderInfo.FLAG_SINGLE_USER;
- if (p.info.exported) {
- Slog.w(TAG, "Provider exported request ignored due to singleUser: "
- + p.className + " at " + mArchiveSourcePath + " "
- + parser.getPositionDescription());
- p.info.exported = false;
- }
- }
-
- sa.recycle();
-
- if ((owner.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
- // A heavy-weight application can not have providers in its main process
- // We can do direct compare because we intern all strings.
- if (p.info.processName == owner.packageName) {
- outError[0] = "Heavy-weight applications can not have providers in main process";
- return null;
- }
- }
-
- if (cpname == null) {
- outError[0] = "<provider> does not include authorities attribute";
- return null;
- }
- p.info.authority = cpname.intern();
-
- if (!parseProviderTags(res, parser, attrs, p, outError)) {
- return null;
- }
-
- return p;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。