System进程在启动时,会调用PackageManagerService类的静态成员函数main将系统的Package管理服务PackageManagerService启动起来。由于PMS在apk的解析,安装过程中发挥在及其重要的作用,我们结合Android8.0.0-r4的源代码,对其进行详细介绍。
此过程共分为10个步骤,下面我们一一结合具体代码进行说明:
1.在SystemServer中启动PMS服务
代码路径:/frameworks/base/services/java/com/android/server/SystemServer.java
(http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/java/com/android/server/SystemServer.java)
259 public static void main(String[] args) { 260 new SystemServer().run(); 261 }
在main中创建一个SystemServer的匿名对象并调用它的run函数
263 public SystemServer() { 264 // Check for factory test mode. 265 mFactoryTestMode = FactoryTest.getMode(); 266 // Remember if it's runtime restart(when sys.boot_completed is already set) or reboot 267 mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed")); 268 }
创建匿名对象,在构造函数中得到启动模式和sys.boot_completed的属性。用来判断是否为正常模式启动和boot启动是否完成。
在run函数中会对系统属性进行初始化设置,并启动一些关键的服务:
391 // Start services. 392 try { 393 traceBeginAndSlog("StartServices"); 394 startBootstrapServices(); 395 startCoreServices(); 396 startOtherServices(); 397 SystemServerInitThreadPool.shutdown();
例如此次要说明的PMS服务就在startBootstrapServices()函数中
575 } 576 traceBeginAndSlog("StartPackageManagerService"); 577 mPackageManagerService = PackageManagerService.main(mSystemContext, installer, 578 mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); 579 mFirstBoot = mPackageManagerService.isFirstBoot(); 580 mPackageManager = mSystemContext.getPackageManager(); 581 traceEnd();
除过PMS服务外还会对AMS,PowerManagerService等进行初始化启动
2.PackageManagerService.main
代码路径:/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java (http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java)
2279 public static PackageManagerService main(Context context, Installer installer, 2280 boolean factoryTest, boolean onlyCore) { 2281 // Self-check for initial settings. 2282 PackageManagerServiceCompilerMapping.checkProperties();//属性检查 2283 2284 PackageManagerService m = new PackageManagerService(context, installer, 2285 factoryTest, onlyCore);//创建PMS对象 2286 m.enableSystemUserPackages();//执行成员函数enableSystemUserPackages 2287 ServiceManager.addService("package", m);//添加到系统服务中,这样系统中的其他组件就可以通过Service Manager来获得它的访问接口 2288 return m; 2289 }
3.PackageManagerService的构造函数:
代码路径:/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java (http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java)
2374 public PackageManagerService(Context context, Installer installer, 2375 boolean factoryTest, boolean onlyCore) { 2376 LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES);
使用类型为Settings的成员变量mSettings来管理应用程序的安装信息,调用mSettings的成员函数调用addSharedUserLPw()来添加共享用户
2393 mSettings = new Settings(mPackages); 2394 mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID, 2395 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); 2396 mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, 2397 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); 2398 mSettings.addSharedUserLPw("android.uid.log", LOG_UID, 2399 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); 2400 mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID, 2401 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); 2402 mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID, 2403 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); 2404 mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID, 2405 ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
调用Environment类的静态成员函数getDataDirectory来获得系统的数据目录/data,并且保存在变量dataDir中
2445 // writer 2446 synchronized (mPackages) { 2447 mHandlerThread = new ServiceThread(TAG, 2448 Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/); 2449 mHandlerThread.start(); 2450 mHandler = new PackageHandler(mHandlerThread.getLooper()); 2451 mProcessLoggingHandler = new ProcessLoggingHandler(); 2452 Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT); 2453 2454 mDefaultPermissionPolicy = new DefaultPermissionGrantPolicy(this); 2455 mInstantAppRegistry = new InstantAppRegistry(this); 2456 2457 File dataDir = Environment.getDataDirectory();
//调用Environment类的静态成员函数getDataDirectory来获得系统的数据目录/data,并且保存在变量dataDir中 2458 mAppInstallDir = new File(dataDir, "app");// data/app目录保存的是由用户自己安装的应用程序 2459 mAppLib32InstallDir = new File(dataDir, "app-lib"); 2460 mAsecInternalPath = new File(dataDir, "app-asec").getPath(); 2461 mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
// data/app-private目录保存的是受ORM保护的私有应用程序
调用Environment类的静态成员函数getRootDirectory来获得 Android系统目录/system,接下来再通过这个目录来获得另外一个目录mFrameworkDir,它对应的系统路径为/system/ framework,里面保存的应用程序是资源型的。 资源型的应用程序是用来打包资源文件的,它们不包含有执行代码
2536 File frameworkDir = new File(Environment.getRootDirectory(), "framework");调用Environment类的静态成员函数getRootDirectory来获得系统目录/system,接着再通过这个目录来获得另外一个目录mSystemAppDir,它对应的系统路径为/system/app,里面保存的是系统自带的应用程序。调用scanDirTracedLI来安装此目录下的应用程序
2602 final File systemAppDir = new File(Environment.getRootDirectory(), "app"); 2603 scanDirTracedLI(systemAppDir, mDefParseFlags 2604 | PackageParser.PARSE_IS_SYSTEM 2605 | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0); 2606
类似的Package管理服务PackageManagerService就得到了六个目录, 它们分别是/system/framework、/system/app、/system/priv-app、/vendor/app、/data/app和/data/app-private
调用PackageManagerService类的成员函数updatePermissionsLPw来为申请了特定的资源访问权限的应用程序分配相应的Linux用户组ID
2849 updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
调用PackageManagerService的成员变量mSettings的成员函数writeLP将前面所获到得的应用程序安装信息保存在本地的一个配置文件中,以便下一次再安装这些应用程序时,可以将需要保持一致的应用程序信息恢复回来
2939 2940 // can downgrade to reader 2941 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "write settings"); 2942 mSettings.writeLPr(); 2943 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
接下来分析一下分析一下Settings类的成员函数readLPw的实现,然后分析PackageManagerService类的成员函数scanDirLI和updatePermissionsLPw的实现,最后分析Settings类的成员函数writeLPr的实现
4.Settings.readLPw
代码路径:frameworks/base/services/core/java/com/android/server/pm/Settings.java (http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/pm/Settings.java)
在初始化Settings对象时会调用Settings的构造函数,利用成员变量mSettingsFilename和mBackupSettingsFilename分别指向了系统中的文件/data/system/packages.xml(上一次应用程序安装信息)和 /data/system/packages-backup.xml(备份的)
423 Settings(Object lock) { 424 this(Environment.getDataDirectory(), lock); 425 } 426 427 Settings(File dataDir, Object lock) { 428 mLock = lock; 429 430 mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock); 431 432 mSystemDir = new File(dataDir, "system"); 433 mSystemDir.mkdirs(); 434 FileUtils.setPermissions(mSystemDir.toString(), 435 FileUtils.S_IRWXU|FileUtils.S_IRWXG 436 |FileUtils.S_IROTH|FileUtils.S_IXOTH, 437 -1, -1); 438 mSettingsFilename = new File(mSystemDir, "packages.xml"); 439 mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml"); 440 mPackageListFilename = new File(mSystemDir, "packages.list"); 441 FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID); 442 443 final File kernelDir = new File("/config/sdcardfs"); 444 mKernelMappingFilename = kernelDir.exists() ? kernelDir : null; 445 446 // Deprecated: Needed for migration 447 mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml"); 448 mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml"); 449 }
检查文件/data/system/packages-backup.xml是否存在。 如果存在,那么接下来会以它作为上一次的应用程序安装信息;否则,代码就会以文件/data/system/packages.xml的内容作为上一次的应用程序安装信息。
3011 boolean readLPw(@NonNull List<UserInfo> users) { 3012 FileInputStream str = null; 3013 if (mBackupSettingsFilename.exists()) { 3014 try { 3015 str = new FileInputStream(mBackupSettingsFilename); 3016 mReadMessages.append("Reading from backup settings file\n"); 3017 PackageManagerService.reportSettingsProblem(Log.INFO, 3018 "Need to read from backup settings file"); 3019 if (mSettingsFilename.exists()) { 3020 // If both the backup and settings file exist, we 3021 // ignore the settings since it might have been 3022 // corrupted. 3023 Slog.w(PackageManagerService.TAG, "Cleaning up settings file " 3024 + mSettingsFilename); 3025 mSettingsFilename.delete();//删除 settings file 3026 } 3027 } catch (java.io.IOException e) { 3028 // We'll try for the normal settings file. 3029 } 3030 }
接下来在try-catch中利用创建的XmlPullParser parser = Xml.newPullParser()对象对pacakages.xml文件进行解析
String tagName = parser.getName(); 3077 if (tagName.equals("package")) { 3078 readPackageLPw(parser); 3079 } else if (tagName.equals("permissions")) { 3080 readPermissionsLPw(mPermissions, parser); 3081 } else if (tagName.equals("permission-trees")) { 3082 readPermissionsLPw(mPermissionTrees, parser); 3083 } else if (tagName.equals("shared-user")) { 3084 readSharedUserLPw(parser); 3085 } else if (tagName.equals("preferred-packages")) { 3086 // no longer used. 3087 } else if (tagName.equals("preferred-activities")) { 3088 // Upgrading from old single-user implementation; 3089 // these are the preferred activities for user 0. 3090 readPreferredActivitiesLPw(parser, 0); 3091 } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) { 3092 // TODO: check whether this is okay! as it is very 3093 // similar to how preferred-activities are treated 3094 readPersistentPreferredActivitiesLPw(parser, 0); 3095 } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) { 3096 // TODO: check whether this is okay! as it is very
name:APK的包名codePath:安装路径。有/system/app系统APK和/data/app两种。/system/app存放系统出厂时预置的一些APK,/data/app存放用户安装的第三方APK。system:如果APK被安装在/system/app下,system的值为true;安装在/data/app下面的话,值为true。ts:时间戳version:APK的版本号
以package节点为示例,对此节点的解析函数readPackageLPw进行详细讲解。
3765 private void readPackageLPw(XmlPullParser parser) throws XmlPullParserException, IOException {
这个Linux用户ID可能是一个无效的Linux用户ID。接下来首先会创建一个PendingPackage对象,
3933 } else if (userId > 0) { 3934 packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr), 3935 new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiString, 3936 secondaryCpuAbiString, cpuAbiOverrideString, userId, versionCode, pkgFlags, 3937 pkgPrivateFlags, parentPackageName, null /*childPackageNames*/, 3938 null /*usesStaticLibraries*/, null /*usesStaticLibraryVersions*/); 3939 if (PackageManagerService.DEBUG_SETTINGS) 3940 Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId=" 3941 + userId + " pkg=" + packageSetting); 3942 if (packageSetting == null) { 3943 PackageManagerService.reportSettingsProblem(Log.ERROR, "Failure adding uid " 3944 + userId + " while parsing settings at " 3945 + parser.getPositionDescription()); 3946 } else { 3947 packageSetting.setTimeStamp(timeStamp); 3948 packageSetting.firstInstallTime = firstInstallTime; 3949 packageSetting.lastUpdateTime = lastUpdateTime; 3950 }
PendingPackage对象保存在Settings类的成员变量mPendingPackag会在此调用Settings类的成员函数
readPackageLPw, addPackageLPw, readSharedUserLPw, addSharedUserLPw等来完成完成用户id的分配
5.PackageManagerService.scanDirLI
代码路径:/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
(http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java)
PackageManagerService类的构造函数中, 这时候Package管理服务PackageManagerService就将上一次的应用程序安装信息恢复完成了。
接下来就会继续调用PackageManagerService类的成员函数scanDirTracedLI来安装保存在目录/system/framework、/system/app、/system/priv-app、
/vendor/app、/data/app和/data/app-private中的应用程序
2603 scanDirTracedLI(systemAppDir, mDefParseFlags 2604 | PackageParser.PARSE_IS_SYSTEM 2605 | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
在PMS的成员函数scanDirTracedLI中会调用PMS的成员函数scanDirLI函数继续来进行安装工作 2606
8628 private void scanDirTracedLI(File dir, final int parseFlags, int scanFlags, long currentTime) { 8629 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + dir.getAbsolutePath() + "]"); 8630 try { 8631 scanDirLI(dir, parseFlags, scanFlags, currentTime); 8632 } finally { 8633 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 8634 } 8635 }
下面我们来具体分析scanDirLI函数是如何来进行安装apk的工作
8637 private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) { 8638 final File[] files = dir.listFiles();//文件夹中的文件列表 8639 if (ArrayUtils.isEmpty(files)) {//判断是否为空 8640 Log.d(TAG, "No files in app dir " + dir); 8641 return; 8642 } 8643 8644 if (DEBUG_PACKAGE_SCANNING) { 8645 Log.d(TAG, "Scanning app dir " + dir + " scanFlags=" + scanFlags 8646 + " flags=0x" + Integer.toHexString(parseFlags)); 8647 } 8648 ParallelPackageParser parallelPackageParser = new ParallelPackageParser( 8649 mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir, 8650 mParallelPackageParserCallback);//创建 ParallelPackageParser对象 8651
//对是否为apk文件进行判断,如果是apk文件,会调用parallelPackageParser.submit去执行解析工作 8652 // Submit files for parsing in parallel 8653 int fileCount = 0; 8654 for (File file : files) { 8655 final boolean isPackage = (isApkFile(file) || file.isDirectory()) 8656 && !PackageInstallerService.isStageName(file.getName()); 8657 if (!isPackage) { 8658 // Ignore entries which are not packages 8659 continue; 8660 } 8661 parallelPackageParser.submit(file, parseFlags); 8662 fileCount++; 8663 } 8664 8665 // Process results one by one 8666 for (; fileCount > 0; fileCount--) { 8667 ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take(); 8668 Throwable throwable = parseResult.throwable; 8669 int errorCode = PackageManager.INSTALL_SUCCEEDED; 8670 8671 if (throwable == null) { 8672 // Static shared libraries have synthetic package names 8673 if (parseResult.pkg.applicationInfo.isStaticSharedLibrary()) { 8674 renameStaticSharedLibraryPackage(parseResult.pkg); 8675 } 8676 try { 8677 if (errorCode == PackageManager.INSTALL_SUCCEEDED) { 8678 scanPackageLI(parseResult.pkg, parseResult.scanFile, parseFlags, scanFlags, 8679 currentTime, null); 8680 } 8681 } catch (PackageManagerException e) { 8682 errorCode = e.error; 8683 Slog.w(TAG, "Failed to scan " + parseResult.scanFile + ": " + e.getMessage()); 8684 } 8685 } else if (throwable instanceof PackageParser.PackageParserException) { 8686 PackageParser.PackageParserException e = (PackageParser.PackageParserException) 8687 throwable; 8688 errorCode = e.error; 8689 Slog.w(TAG, "Failed to parse " + parseResult.scanFile + ": " + e.getMessage()); 8690 } else { 8691 throw new IllegalStateException("Unexpected exception occurred while parsing " 8692 + parseResult.scanFile, throwable); 8693 } 8694 8695 // Delete invalid userdata apps 8696 if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 && 8697 errorCode == PackageManager.INSTALL_FAILED_INVALID_APK) { 8698 logCriticalInfo(Log.WARN, 8699 "Deleting invalid package at " + parseResult.scanFile); 8700 removeCodePathLI(parseResult.scanFile); 8701 } 8702 } 8703 parallelPackageParser.close(); 8704 }
6. ParallelPackageParser.submit
代码路径:frameworks/base/services/core/java/com/android/server/pm/ParallelPackageParser.java
(http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/pm/ParallelPackageParser.java)
在PMS的成员函数scanDirLI是否为apk文件进行判断,如果是apk文件,会调用parallelPackageParser.submit去执行解析工作
105 public void submit(File scanFile, int parseFlags) { 106 mService.submit(() -> { 107 ParseResult pr = new ParseResult(); 108 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parallel parsePackage [" + scanFile + "]"); 109 try { 110 PackageParser pp = new PackageParser(); 111 pp.setSeparateProcesses(mSeparateProcesses); 112 pp.setOnlyCoreApps(mOnlyCore); 113 pp.setDisplayMetrics(mMetrics); 114 pp.setCacheDir(mCacheDir); 115 pp.setCallback(mPackageParserCallback); 116 pr.scanFile = scanFile; 117 pr.pkg = parsePackage(pp, scanFile, parseFlags); 118 } catch (Throwable e) { 119 pr.throwable = e; 120 } finally { 121 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 122 } 123 try { 124 mQueue.put(pr); 125 } catch (InterruptedException e) { 126 Thread.currentThread().interrupt(); 127 // Propagate result to callers of take(). 128 // This is helpful to prevent main thread from getting stuck waiting on 129 // ParallelPackageParser to finish in case of interruption 130 mInterruptedInThread = Thread.currentThread().getName(); 131 } 132
7.PackageParser.parsePackage
代码路径:frameworks/base/core/java/android/content/pm/PackageParser.java
(http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/content/pm/PackageParser.java)
parallelPackageParser.submit会调用PackageParser.parsePackage去解析apk的AndroidManifest.xml文件
959 public Package parsePackage(File packageFile, int flags, boolean useCaches) 960 throws PackageParserException { 961 Package parsed = useCaches ? getCachedResult(packageFile, flags) : null; 962 if (parsed != null) { 963 return parsed; 964 } 965 966 if (packageFile.isDirectory()) { 967 parsed = parseClusterPackage(packageFile, flags);//判断是否为文件夹 968 } else { 969 parsed = parseMonolithicPackage(packageFile, flags);//非文件夹 970 } 971 972 cacheResult(packageFile, flags, parsed); 973 974 return parsed; 975 } 976 977 /** 978 * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}. 979 */ 980 public Package parsePackage(File packageFile, int flags) throws PackageParserException { 981 return parsePackage(packageFile, flags, false /* useCaches */); 982 }
不论是parseClusterPackage还是parseMonolithicPackage函数,进入文件夹或直接对xml文件进行解析,都会调用parseBaseApk这个函数来对apk解析归档文件进行解析。
1973 private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags, 1974 String[] outError) throws XmlPullParserException, IOException { 1975 final String splitName; 1976 final String pkgName; 1977 1978 try { 1979 Pair<String, String> packageSplit = parsePackageSplitNames(parser, parser); 1980 pkgName = packageSplit.first; 1981 splitName = packageSplit.second; 1982 1983 if (!TextUtils.isEmpty(splitName)) { 1984 outError[0] = "Expected base APK, but found split " + splitName; 1985 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME; 1986 return null; 1987 } 1988 } catch (PackageParserException e) { 1989 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME; 1990 return null; 1991 } 1992 1993 if (mCallback != null) { 1994 String[] overlayPaths = mCallback.getOverlayPaths(pkgName, apkPath); 1995 if (overlayPaths != null && overlayPaths.length > 0) { 1996 for (String overlayPath : overlayPaths) { 1997 res.getAssets().addOverlayPath(overlayPath); 1998 } 1999 } 2000 } 2001 2002 final Package pkg = new Package(pkgName); 2003 2004 TypedArray sa = res.obtainAttributes(parser, 2005 com.android.internal.R.styleable.AndroidManifest); 2006 2007 pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger( 2008 com.android.internal.R.styleable.AndroidManifest_versionCode, 0); 2009 pkg.baseRevisionCode = sa.getInteger( 2010 com.android.internal.R.styleable.AndroidManifest_revisionCode, 0); 2011 pkg.mVersionName = sa.getNonConfigurationString( 2012 com.android.internal.R.styleable.AndroidManifest_versionName, 0); 2013 if (pkg.mVersionName != null) { 2014 pkg.mVersionName = pkg.mVersionName.intern(); 2015 } 2016 2017 pkg.coreApp = parser.getAttributeBooleanValue(null, "coreApp", false); 2018 2019 sa.recycle(); 2020 2021 return parseBaseApkCommon(pkg, null, res, parser, flags, outError); 2022 }
parseBaseApkCommon才是解析的主力函数,通过此函数对res目录和AndroidManifest.xml的xml文件进行解析,从而把解析后的信息存储在Package 这个变量中
private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res, 2044 XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, 2045 IOException { 2046 mParseInstrumentationArgs = null; 2047 mParseActivityArgs = null; 2048 mParseServiceArgs = null; 2049 mParseProviderArgs = null; 2050 2051 int type; 2052 boolean foundApp = false; 2053 2054 TypedArray sa = res.obtainAttributes(parser, 2055 com.android.internal.R.styleable.AndroidManifest); 2056 2057 String str = sa.getNonConfigurationString( 2058 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0); 2059 if (str != null && str.length() > 0) { 2060 if ((flags & PARSE_IS_EPHEMERAL) != 0) { 2061 outError[0] = "sharedUserId not allowed in ephemeral application"; 2062 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID; 2063 return null; 2064 } 2065 String nameError = validateName(str, true, false); 2066 if (nameError != null && !"android".equals(pkg.packageName)) { 2067 outError[0] = "<manifest> specifies bad sharedUserId name \"" 2068 + str + "\": " + nameError; 2069 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID; 2070 return null; 2071 } 2072 pkg.mSharedUserId = str.intern(); 2073 pkg.mSharedUserLabel = sa.getResourceId( 2074 com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0); 2075 } 2076 2077 pkg.installLocation = sa.getInteger( 2078 com.android.internal.R.styleable.AndroidManifest_installLocation, 2079 PARSE_DEFAULT_INSTALL_LOCATION); 2080 pkg.applicationInfo.installLocation = pkg.installLocation; 2081 2082 final int targetSandboxVersion = sa.getInteger( 2083 com.android.internal.R.styleable.AndroidManifest_targetSandboxVersion, 2084 PARSE_DEFAULT_TARGET_SANDBOX); 2085 pkg.applicationInfo.targetSandboxVersion = targetSandboxVersion; 2086 2087 /* Set the global "forward lock" flag */ 2088 if ((flags & PARSE_FORWARD_LOCK) != 0) { 2089 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK; 2090 } 2091 2092 /* Set the global "on SD card" flag */ 2093 if ((flags & PARSE_EXTERNAL_STORAGE) != 0) { 2094 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE; 2095 } 2096 2097 if (sa.getBoolean(com.android.internal.R.styleable.AndroidManifest_isolatedSplits, false)) { 2098 pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING; 2099 } 2100 2101 // Resource boolean are -1, so 1 means we don't know the value. 2102 int supportsSmallScreens = 1; 2103 int supportsNormalScreens = 1; 2104 int supportsLargeScreens = 1; 2105 int supportsXLargeScreens = 1; 2106 int resizeable = 1; 2107 int anyDensity = 1; 2108 2109 int outerDepth = parser.getDepth(); 2110 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 2111 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 2112 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2113 continue; 2114 } 2115 2116 String tagName = parser.getName(); 2117 2118 if (acceptedTags != null && !acceptedTags.contains(tagName)) { 2119 Slog.w(TAG, "Skipping unsupported element under <manifest>: " 2120 + tagName + " at " + mArchiveSourcePath + " " 2121 + parser.getPositionDescription()); 2122 XmlUtils.skipCurrentTag(parser); 2123 continue; 2124 } 2125
循环分别对activity 、 receiver 、 service和provider,标签进行解析,以便可以获得正在解析的应用程序的Activity、
Broadcast Receiver、 Service和Content Provider组件的配置信息,调用parseBaseApplication来解析application节点,其他节点类似。 2126 if (tagName.equals(TAG_APPLICATION)) { 2127 if (foundApp) { 2128 if (RIGID_PARSER) { 2129 outError[0] = "<manifest> has more than one <application>"; 2130 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 2131 return null; 2132 } else { 2133 Slog.w(TAG, "<manifest> has more than one <application>"); 2134 XmlUtils.skipCurrentTag(parser); 2135 continue; 2136 } 2137 } 2138
2139 foundApp = true; 2140 if (!parseBaseApplication(pkg, res, parser, flags, outError)) { 2141 return null; 2142 } 2143 } else if (tagName.equals(TAG_OVERLAY)) { 2144 sa = res.obtainAttributes(parser, 2145 com.android.internal.R.styleable.AndroidManifestResourceOverlay); 2146 pkg.mOverlayTarget = sa.getString( 2147 com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage); 2148 pkg.mOverlayPriority = sa.getInt( 2149 com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority, 2150 0); 2151 pkg.mIsStaticOverlay = sa.getBoolean( 2152 com.android.internal.R.styleable.AndroidManifestResourceOverlay_isStatic, 2153 false); 2154 final String propName = sa.getString( 2155 com.android.internal.R.styleable 2156 .AndroidManifestResourceOverlay_requiredSystemPropertyName); 2157 final String propValue = sa.getString( 2158 com.android.internal.R.styleable 2159 .AndroidManifestResourceOverlay_requiredSystemPropertyValue); 2160 sa.recycle(); 2161 2162 if (pkg.mOverlayTarget == null) { 2163 outError[0] = "<overlay> does not specify a target package"; 2164 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 2165 return null; 2166 } 2167 2168 if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) { 2169 outError[0] = "<overlay> priority must be between 0 and 9999"; 2170 mParseError = 2171 PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 2172 return null; 2173 } 2174 2175 // check to see if overlay should be excluded based on system property condition 2176 if (!checkOverlayRequiredSystemProperty(propName, propValue)) { 2177 Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and " 2178 + pkg.baseCodePath+ ": overlay ignored due to required system property: " 2179 + propName + " with value: " + propValue); 2180 return null; 2181 } 2182 2183 XmlUtils.skipCurrentTag(parser); 2184 2185 } else if (tagName.equals(TAG_KEY_SETS)) { 2186 if (!parseKeySets(pkg, res, parser, outError)) { 2187 return null; 2188 } 2189 } else if (tagName.equals(TAG_PERMISSION_GROUP)) { 2190 if (!parsePermissionGroup(pkg, flags, res, parser, outError)) { 2191 return null; 2192 } 2193 } else if (tagName.equals(TAG_PERMISSION)) { 2194 if (!parsePermission(pkg, res, parser, outError)) { 2195 return null; 2196 } 2197 } else if (tagName.equals(TAG_PERMISSION_TREE)) { 2198 if (!parsePermissionTree(pkg, res, parser, outError)) { 2199 return null; 2200 } 2201 } else if (tagName.equals(TAG_USES_PERMISSION)) { 2202 if (!parseUsesPermission(pkg, res, parser)) { 2203 return null; 2204 } 2205 } else if (tagName.equals(TAG_USES_PERMISSION_SDK_M) 2206 || tagName.equals(TAG_USES_PERMISSION_SDK_23)) { 2207 if (!parseUsesPermission(pkg, res, parser)) { 2208 return null; 2209 } 2210 } else if (tagName.equals(TAG_USES_CONFIGURATION)) { 2211 ConfigurationInfo cPref = new ConfigurationInfo(); 2212 sa = res.obtainAttributes(parser, 2213 com.android.internal.R.styleable.AndroidManifestUsesConfiguration); 2214 cPref.reqTouchScreen = sa.getInt( 2215 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen, 2216 Configuration.TOUCHSCREEN_UNDEFINED); 2217 cPref.reqKeyboardType = sa.getInt( 2218 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType, 2219 Configuration.KEYBOARD_UNDEFINED); 2220 if (sa.getBoolean( 2221 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard, 2222 false)) { 2223 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD; 2224 } 2225 cPref.reqNavigation = sa.getInt( 2226 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation, 2227 Configuration.NAVIGATION_UNDEFINED); 2228 if (sa.getBoolean( 2229 com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav, 2230 false)) { 2231 cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV; 2232 } 2233 sa.recycle(); 2234 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref); 2235 2236 XmlUtils.skipCurrentTag(parser); 2237 2238 } else if (tagName.equals(TAG_USES_FEATURE)) { 2239 FeatureInfo fi = parseUsesFeature(res, parser); 2240 pkg.reqFeatures = ArrayUtils.add(pkg.reqFeatures, fi); 2241 2242 if (fi.name == null) { 2243 ConfigurationInfo cPref = new ConfigurationInfo(); 2244 cPref.reqGlEsVersion = fi.reqGlEsVersion; 2245 pkg.configPreferences = ArrayUtils.add(pkg.configPreferences, cPref); 2246 } 2247 2248 XmlUtils.skipCurrentTag(parser); 2249 2250 } else if (tagName.equals(TAG_FEATURE_GROUP)) { 2251 FeatureGroupInfo group = new FeatureGroupInfo(); 2252 ArrayList<FeatureInfo> features = null; 2253 final int innerDepth = parser.getDepth(); 2254 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 2255 && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) { 2256 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 2257 continue; 2258 } 2259 2260 final String innerTagName = parser.getName(); 2261 if (innerTagName.equals("uses-feature")) { 2262 FeatureInfo featureInfo = parseUsesFeature(res, parser); 2263 // FeatureGroups are stricter and mandate that 2264 // any <uses-feature> declared are mandatory. 2265 featureInfo.flags |= FeatureInfo.FLAG_REQUIRED; 2266 features = ArrayUtils.add(features, featureInfo); 2267 } else { 2268 Slog.w(TAG, "Unknown element under <feature-group>: " + innerTagName + 2269 " at " + mArchiveSourcePath + " " + 2270 parser.getPositionDescription()); 2271 } 2272 XmlUtils.skipCurrentTag(parser); 2273 } 2274 2275 if (features != null) { 2276 group.features = new FeatureInfo[features.size()]; 2277 group.features = features.toArray(group.features); 2278 } 2279 pkg.featureGroups = ArrayUtils.add(pkg.featureGroups, group); 2280 2281 } else if (tagName.equals(TAG_USES_SDK)) { 2282 if (SDK_VERSION > 0) { 2283 sa = res.obtainAttributes(parser, 2284 com.android.internal.R.styleable.AndroidManifestUsesSdk); 2285 2286 int minVers = 1; 2287 String minCode = null; 2288 int targetVers = 0; 2289 String targetCode = null; 2290 2291 TypedValue val = sa.peekValue( 2292 com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion); 2293 if (val != null) { 2294 if (val.type == TypedValue.TYPE_STRING && val.string != null) { 2295 targetCode = minCode = val.string.toString(); 2296 } else { 2297 // If it's not a string, it's an integer. 2298 targetVers = minVers = val.data; 2299 } 2300 } 2301 2302 val = sa.peekValue( 2303 com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion); 2304 if (val != null) { 2305 if (val.type == TypedValue.TYPE_STRING && val.string != null) { 2306 targetCode = val.string.toString(); 2307 if (minCode == null) { 2308 minCode = targetCode; 2309 } 2310 } else { 2311 // If it's not a string, it's an integer. 2312 targetVers = val.data; 2313 } 2314 } 2315 2316 sa.recycle(); 2317 2318 final int minSdkVersion = PackageParser.computeMinSdkVersion(minVers, minCode, 2319 SDK_VERSION, SDK_CODENAMES, outError); 2320 if (minSdkVersion < 0) { 2321 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK; 2322 return null; 2323 } 2324 2325 final int targetSdkVersion = PackageParser.computeTargetSdkVersion(targetVers, 2326 targetCode, SDK_VERSION, SDK_CODENAMES, outError); 2327 if (targetSdkVersion < 0) { 2328 mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK; 2329 return null; 2330 } 2331 2332 pkg.applicationInfo.minSdkVersion = minSdkVersion; 2333 pkg.applicationInfo.targetSdkVersion = targetSdkVersion; 2334 } 2335 2336 XmlUtils.skipCurrentTag(parser); 2337 2338 } else if (tagName.equals(TAG_SUPPORT_SCREENS)) { 2339 sa = res.obtainAttributes(parser, 2340 com.android.internal.R.styleable.AndroidManifestSupportsScreens); 2341 2342 pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger( 2343 com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp, 2344 0); 2345 pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger( 2346 com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp, 2347 0); 2348 pkg.applicationInfo.largestWidthLimitDp = sa.getInteger( 2349 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp, 2350 0); 2351 2352 // This is a trick to get a boolean and still able to detect 2353 // if a value was actually set. 2354 supportsSmallScreens = sa.getInteger( 2355 com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens, 2356 supportsSmallScreens); 2357 supportsNormalScreens = sa.getInteger( 2358 com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens, 2359 supportsNormalScreens); 2360 supportsLargeScreens = sa.getInteger( 2361 com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens, 2362 supportsLargeScreens); 2363 supportsXLargeScreens = sa.getInteger( 2364 com.android.internal.R.styleable.AndroidManifestSupportsScreens_xlargeScreens, 2365 supportsXLargeScreens); 2366 resizeable = sa.getInteger( 2367 com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable, 2368 resizeable); 2369 anyDensity = sa.getInteger( 2370 com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity, 2371 anyDensity); 2372 2373 sa.recycle(); 2374 2375 XmlUtils.skipCurrentTag(parser); 2376 2377 } else if (tagName.equals(TAG_PROTECTED_BROADCAST)) { 2378 sa = res.obtainAttributes(parser, 2379 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast); 2380 2381 // Note: don't allow this value to be a reference to a resource 2382 // that may change. 2383 String name = sa.getNonResourceString( 2384 com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name); 2385 2386 sa.recycle(); 2387 2388 if (name != null && (flags&PARSE_IS_SYSTEM) != 0) { 2389 if (pkg.protectedBroadcasts == null) { 2390 pkg.protectedBroadcasts = new ArrayList<String>(); 2391 } 2392 if (!pkg.protectedBroadcasts.contains(name)) { 2393 pkg.protectedBroadcasts.add(name.intern()); 2394 } 2395 } 2396 2397 XmlUtils.skipCurrentTag(parser); 2398 2399 } else if (tagName.equals(TAG_INSTRUMENTATION)) { 2400 if (parseInstrumentation(pkg, res, parser, outError) == null) { 2401 return null; 2402 } 2403 } else if (tagName.equals(TAG_ORIGINAL_PACKAGE)) { 2404 sa = res.obtainAttributes(parser, 2405 com.android.internal.R.styleable.AndroidManifestOriginalPackage); 2406 2407 String orig =sa.getNonConfigurationString( 2408 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0); 2409 if (!pkg.packageName.equals(orig)) { 2410 if (pkg.mOriginalPackages == null) { 2411 pkg.mOriginalPackages = new ArrayList<String>(); 2412 pkg.mRealPackage = pkg.packageName; 2413 } 2414 pkg.mOriginalPackages.add(orig); 2415 } 2416 2417 sa.recycle(); 2418 2419 XmlUtils.skipCurrentTag(parser); 2420 2421 } else if (tagName.equals(TAG_ADOPT_PERMISSIONS)) { 2422 sa = res.obtainAttributes(parser, 2423 com.android.internal.R.styleable.AndroidManifestOriginalPackage); 2424 2425 String name = sa.getNonConfigurationString( 2426 com.android.internal.R.styleable.AndroidManifestOriginalPackage_name, 0); 2427 2428 sa.recycle(); 2429 2430 if (name != null) { 2431 if (pkg.mAdoptPermissions == null) { 2432 pkg.mAdoptPermissions = new ArrayList<String>(); 2433 } 2434 pkg.mAdoptPermissions.add(name); 2435 } 2436 2437 XmlUtils.skipCurrentTag(parser); 2438 2439 } else if (tagName.equals(TAG_USES_GL_TEXTURE)) { 2440 // Just skip this tag 2441 XmlUtils.skipCurrentTag(parser); 2442 continue; 2443 2444 } else if (tagName.equals(TAG_COMPATIBLE_SCREENS)) { 2445 // Just skip this tag 2446 XmlUtils.skipCurrentTag(parser); 2447 continue; 2448 } else if (tagName.equals(TAG_SUPPORTS_INPUT)) {// 2449 XmlUtils.skipCurrentTag(parser); 2450 continue; 2451 2452 } else if (tagName.equals(TAG_EAT_COMMENT)) { 2453 // Just skip this tag 2454 XmlUtils.skipCurrentTag(parser); 2455 continue; 2456 2457 } else if (tagName.equals(TAG_PACKAGE)) { 2458 if (!MULTI_PACKAGE_APK_ENABLED) { 2459 XmlUtils.skipCurrentTag(parser); 2460 continue; 2461 } 2462 if (!parseBaseApkChild(pkg, res, parser, flags, outError)) { 2463 // If parsing a child failed the error is already set 2464 return null; 2465 } 2466 2467 } else if (tagName.equals(TAG_RESTRICT_UPDATE)) { 2468 if ((flags & PARSE_IS_SYSTEM_DIR) != 0) { 2469 sa = res.obtainAttributes(parser, 2470 com.android.internal.R.styleable.AndroidManifestRestrictUpdate); 2471 final String hash = sa.getNonConfigurationString( 2472 com.android.internal.R.styleable.AndroidManifestRestrictUpdate_hash, 0); 2473 sa.recycle(); 2474 2475 pkg.restrictUpdateHash = null; 2476 if (hash != null) { 2477 final int hashLength = hash.length(); 2478 final byte[] hashBytes = new byte[hashLength / 2]; 2479 for (int i = 0; i < hashLength; i += 2){ 2480 hashBytes[i/2] = (byte) ((Character.digit(hash.charAt(i), 16) << 4) 2481 + Character.digit(hash.charAt(i + 1), 16)); 2482 } 2483 pkg.restrictUpdateHash = hashBytes; 2484 } 2485 } 2486 2487 XmlUtils.skipCurrentTag(parser); 2488 2489 } else if (RIGID_PARSER) { 2490 outError[0] = "Bad element under <manifest>: " 2491 + parser.getName(); 2492 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; 2493 return null; 2494 2495 } else { 2496 Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName() 2497 + " at " + mArchiveSourcePath + " " 2498 + parser.getPositionDescription()); 2499 XmlUtils.skipCurrentTag(parser); 2500 continue; 2501 } 2502 } 2503 2504 if (!foundApp && pkg.instrumentation.size() == 0) { 2505 outError[0] = "<manifest> does not contain an <application> or <instrumentation>"; 2506 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY; 2507 } 2508 2509 final int NP = PackageParser.NEW_PERMISSIONS.length; 2510 StringBuilder implicitPerms = null; 2511 for (int ip=0; ip<NP; ip++) { 2512 final PackageParser.NewPermissionInfo npi 2513 = PackageParser.NEW_PERMISSIONS[ip]; 2514 if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) { 2515 break; 2516 } 2517 if (!pkg.requestedPermissions.contains(npi.name)) { 2518 if (implicitPerms == null) { 2519 implicitPerms = new StringBuilder(128); 2520 implicitPerms.append(pkg.packageName); 2521 implicitPerms.append(": compat added "); 2522 } else { 2523 implicitPerms.append(' '); 2524 } 2525 implicitPerms.append(npi.name); 2526 pkg.requestedPermissions.add(npi.name); 2527 } 2528 } 2529 if (implicitPerms != null) { 2530 Slog.i(TAG, implicitPerms.toString()); 2531 } 2532 2533 final int NS = PackageParser.SPLIT_PERMISSIONS.length; 2534 for (int is=0; is<NS; is++) { 2535 final PackageParser.SplitPermissionInfo spi 2536 = PackageParser.SPLIT_PERMISSIONS[is]; 2537 if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk 2538 || !pkg.requestedPermissions.contains(spi.rootPerm)) { 2539 continue; 2540 } 2541 for (int in=0; in<spi.newPerms.length; in++) { 2542 final String perm = spi.newPerms[in]; 2543 if (!pkg.requestedPermissions.contains(perm)) { 2544 pkg.requestedPermissions.add(perm); 2545 } 2546 } 2547 } 2548 2549 if (supportsSmallScreens < 0 || (supportsSmallScreens > 0 2550 && pkg.applicationInfo.targetSdkVersion 2551 >= android.os.Build.VERSION_CODES.DONUT)) { 2552 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS; 2553 } 2554 if (supportsNormalScreens != 0) { 2555 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS; 2556 } 2557 if (supportsLargeScreens < 0 || (supportsLargeScreens > 0 2558 && pkg.applicationInfo.targetSdkVersion 2559 >= android.os.Build.VERSION_CODES.DONUT)) { 2560 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS; 2561 } 2562 if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0 2563 && pkg.applicationInfo.targetSdkVersion 2564 >= android.os.Build.VERSION_CODES.GINGERBREAD)) { 2565 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS; 2566 } 2567 if (resizeable < 0 || (resizeable > 0 2568 && pkg.applicationInfo.targetSdkVersion 2569 >= android.os.Build.VERSION_CODES.DONUT)) { 2570 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS; 2571 } 2572 if (anyDensity < 0 || (anyDensity > 0 2573 && pkg.applicationInfo.targetSdkVersion 2574 >= android.os.Build.VERSION_CODES.DONUT)) { 2575 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES; 2576 } 2577 2578 // At this point we can check if an application is not supporting densities and hence 2579 // cannot be windowed / resized. Note that an SDK version of 0 is common for 2580 // pre-Doughnut applications. 2581 if (pkg.applicationInfo.usesCompatibilityMode()) { 2582 adjustPackageToBeUnresizeableAndUnpipable(pkg); 2583 } 2584 return pkg; 2585 } 2586
8.PackageManagerService.scanPackageLI
代码路径:/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
(http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java)
上面对AndroidManifest.xml解析完成保存在Package的HashMap中
调用PackageManagerService.scanPackageLI解析后的数据进行使用
8665 // Process results one by one 8666 for (; fileCount > 0; fileCount--) { 8667 ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take(); 8668 Throwable throwable = parseResult.throwable; 8669 int errorCode = PackageManager.INSTALL_SUCCEEDED; 8670 8671 if (throwable == null) { 8672 // Static shared libraries have synthetic package names 8673 if (parseResult.pkg.applicationInfo.isStaticSharedLibrary()) { 8674 renameStaticSharedLibraryPackage(parseResult.pkg); 8675 } 8676 try { 8677 if (errorCode == PackageManager.INSTALL_SUCCEEDED) { 8678 scanPackageLI(parseResult.pkg, parseResult.scanFile, parseFlags, scanFlags, 8679 currentTime, null); 8680 } 8681 } catch (PackageManagerException e) { 8682 errorCode = e.error; 8683 Slog.w(TAG, "Failed to scan " + parseResult.scanFile + ": " + e.getMessage()); 8684 }
最终会调用scanPackageInternalLI函数来调用其他成员函数来对activity,service等解析结果进行保存
( 1 )为参数pkg所描述的一个应用程序分配Linux用户ID
( 2)将参数pkg所指向的一个Package对象保存在PackageManagerService类的成员变量mPackages中
( 3)将参数pkg所描述的一个应用程序的ContentProvider组件配置信息保存在PackageManagerService 类的成员变量rnProvidersByComponent中
(4)将参数pkg所描述的一个应用程序的Service组件配置信息、保存在PackageManagerService类的成员变量mServices中
( 5)将参数pkg所描述的一个应用程序的Broadcast Receiver组件配置信息保存在Packa在eManagerService 类的成员变量mReceivers中
( 6)将参数pkg所描述的一个应用程序的Activity组件配置信息保存在PackageManagerService类的 成员变量mActivities中
8.PackageManagerService.scanPackageLI
代码路径:/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
(http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java)
2847 updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL; 2848 } 2849 updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags); 2850 ver.sdkVersion = mSdkVersion;
12270 private void updatePermissionsLPw(String changingPkg, 12271 PackageParser.Package pkgInfo, String replaceVolumeUuid, int flags) { 12272 // Make sure there are no dangling permission trees. 12273 Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator(); 12274 while (it.hasNext()) { 12275 final BasePermission bp = it.next(); 12276 if (bp.packageSetting == null) { 12277 // We may not yet have parsed the package, so just see if ........................... 12325 } else if (changingPkg != null && changingPkg.equals(bp.sourcePackage)) { 12326 if (pkgInfo == null || !hasPermission(pkgInfo, bp.name)) { 12327 Slog.i(TAG, "Removing old permission: " + bp.name 12328 + " from package " + bp.sourcePackage); 12329 flags |= UPDATE_PERMISSIONS_ALL; 12330 it.remove(); 12331 } 12332 } 12333 } 12334 12335 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "grantPermissions"); 12336 // Now update the permissions for all packages, in particular 12337 // replace the granted permissions of the system packages. 12338 if ((flags&UPDATE_PERMISSIONS_ALL) != 0) { 12339 for (PackageParser.Package pkg : mPackages.values()) { 12340 if (pkg != pkgInfo) { 12341 // Only replace for packages on requested volume 12342 final String volumeUuid = getVolumeUuidForPackage(pkg); 12343 final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_ALL) != 0) 12344 && Objects.equals(replaceVolumeUuid, volumeUuid); 12345 grantPermissionsLPw(pkg, replace, changingPkg); 12346 } 12347 } 12348 } 12349 12350 if (pkgInfo != null) { 12351 // Only replace for packages on requested volume 12352 final String volumeUuid = getVolumeUuidForPackage(pkgInfo); 12353 final boolean replace = ((flags & UPDATE_PERMISSIONS_REPLACE_PKG) != 0) 12354 && Objects.equals(replaceVolumeUuid, volumeUuid); 12355 grantPermissionsLPw(pkgInfo, replace, changingPkg); 12356 } 12357 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 12358 }
所有已经安装了的应用程序都保存在PackageManagerService类的成员变量mPackages中当参数 grantPermissions的值等于true时, 就会依次调用PackageManagerService类的成员函数grantPermissionsLP来为它们分配Linux用户组ID, 以便它们可以获得所申请的资源访问权限。
调用pms的成员函数grantPermissionsLPw对apk的uses-permission的权限进行检查,以确定apk是否申请了相关权限。
12360 private void grantPermissionsLPw(PackageParser.Package pkg, boolean replace, 12361 String packageOfInterest) {
..................
12695 // write synchronously to avoid losing runtime permissions state. 12696 for (int userId : changedRuntimePermissionUserIds) { 12697 mSettings.writeRuntimePermissionsForUserLPr(userId, runtimePermissionsRevoked); 12698 } 12699 }
9.Settings.writeLPr
代码路径:frameworks/base/services/core/java/com/android/server/pm/Settings.java (http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/pm/Settings.java)
调用Settings类的成员函数writeLP将这些应用程序的安装信息保存在本地文件(/data/system/packages.xml)
2940 // can downgrade to reader 2941 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "write settings"); 2942 mSettings.writeLPr(); 2943 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
10.PackageManagerService.userPackages
代码路径:/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
(http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java)
最后会更新系统的dex文件,并对解析过程完成后的内存使用进行手动回收
2991 updateInstantAppInstallerLocked(null); 2992 2993 // Read and update the usage of dex files. 2994 // Do this at the end of PM init so that all the packages have their 2995 // data directory reconciled. 2996 // At this point we know the code paths of the packages, so we can validate 2997 // the disk file and build the internal cache. 2998 // The usage file is expected to be small so loading and verifying it 2999 // should take a fairly small time compare to the other activities (e.g. package 3000 // scanning). 3001 final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>(); 3002 final int[] currentUserIds = UserManagerService.getInstance().getUserIds(); 3003 for (int userId : currentUserIds) { 3004 userPackages.put(userId, getInstalledPackages(/*flags*/ 0, userId).getList()); 3005 } 3006 mDexManager.load(userPackages); 3007 } // synchronized (mPackages) 3008 } // synchronized (mInstallLock) 3009 3010 // Now after opening every single application zip, make sure they 3011 // are all flushed. Not really needed, but keeps things nice and 3012 // tidy. 3013 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "GC"); 3014 Runtime.getRuntime().gc(); 3015 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 3016 3017 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "loadFallbacks"); 3018 FallbackCategoryProvider.loadFallbacks(); 3019 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 3020 3021 // The initial scanning above does many calls into installd while 3022 // holding the mPackages lock, but we're mostly interested in yelling 3023 // once we have a booted system. 3024 mInstaller.setWarnIfHeld(mPackages); 3025 3026 // Expose private service for system components to use. 3027 LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl()); 3028 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
总结一下:
对于apk安装包而已,实质上是一个zipalign工具来打包,经过签名工具签名的zip压缩包。
安装APP应用程序的主要方式有:
1.系统启动时安装
2.adb命令安装
3.应用商店安装
4.通过PackageInstaller安装
其中所有的安装方法的核心都是通过PMS的成员函数scanPackageLI()
上面讲解的是系统启动时安装的主要过程主要分4部分
1.读取安装信息2.扫描安装
3.写回安装信息
4.更新dex,odex文件,手动回收扫描过程使用的内存