Android8.0.0-r4的APK的安装

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文件,手动回收扫描过程使用的内存
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值