系統(tǒng)應(yīng)用的AndroidManifest.xml是在什么時(shí)候被解析的

調(diào)試應(yīng)用悼潭,一般兩種方式把a(bǔ)pk通過(guò)adb push到指定目錄或者通過(guò)adb install 蔚袍。
做系統(tǒng)應(yīng)用開(kāi)發(fā)一般使用adb push到 指定目錄進(jìn)行調(diào)試愿汰,然后kill進(jìn)程彬碱,等待應(yīng)用再被拉起窃诉,但是會(huì)遇到一個(gè)問(wèn)題杨耙,把APK通過(guò)adb push到設(shè)備后重啟之前AndroidManifest.xml的修改不生效赤套。

為什么會(huì)出現(xiàn)這個(gè)現(xiàn)象,就需要了解AndroidManifest.xml啥時(shí)候被加載的珊膜。
APK的安裝容握,離不開(kāi)PMS (PackageManagerService)
先上圖


解析AndroidManifest流程.png

首先分析PMS的啟動(dòng)

PMS (PackageManagerService)啟動(dòng)過(guò)程

  • SystemServer --> main() --> startBootstrapServices() --> PackageManagerService.main()
    /**
     * The main entry point from zygote.<--源頭
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }
....
....
    private void run() {
    ...
    ...
    // Start services.
        try {
            t.traceBegin("StartServices");
            startBootstrapServices(t);
            startCoreServices(t);
            startOtherServices(t);
            startApexServices(t);
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            t.traceEnd(); // StartServices
        }
    }
    ...
    
    private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
      ...
      ...
       //啟動(dòng)installer服務(wù),從名字可以看出此服務(wù)與安裝apk相關(guān)车柠,里面主要是管理apk的各種信息剔氏,AMS和PMS啟動(dòng)時(shí)都需要這個(gè)參數(shù)
       t.traceBegin("StartInstaller");
       Installer installer = mSystemServiceManager.startService(Installer.class);
       t.traceEnd();
      //這里是啟動(dòng)AMS
        // Activity manager runs the show.
        t.traceBegin("StartActivityManager");
        //這里有備注可能以后會(huì)換地方
        // TODO: Might need to move after migration to WM.
        ActivityTaskManagerService atm = mSystemServiceManager.startService(
                ActivityTaskManagerService.Lifecycle.class).getService();
        mActivityManagerService = ActivityManagerService.Lifecycle.startService(
                mSystemServiceManager, atm);
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        mWindowManagerGlobalLock = atm.getGlobalLock();
        t.traceEnd();
      ...
      ...
        // Only run "core" apps if we're encrypting the device.
        //啟動(dòng)min-framework 顯示密碼輸入界面,僅啟動(dòng) coreApp竹祷, 在AndroidManifest.xml中聲明谈跛。
        //此時(shí)啟動(dòng)的 APP 在 tmpfs 臨時(shí)分區(qū),所以塑陵,所有app都是原始安裝狀態(tài)感憾,不包含任何用戶(hù)使用產(chǎn)生的數(shù)據(jù)。
        String cryptState = VoldProperties.decrypt().orElse("");
        if (ENCRYPTING_STATE.equals(cryptState)) {
            Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
            mOnlyCore = true;
        } else if (ENCRYPTED_STATE.equals(cryptState)) {
            Slog.w(TAG, "Device encrypted - only parsing core apps");
            mOnlyCore = true;
        }
        ....
        ....
        t.traceBegin("StartDomainVerificationService");
        //這個(gè)服務(wù)作為參數(shù)傳進(jìn)PMS令花,主要是為了做一些校驗(yàn)工作
        DomainVerificationService domainVerificationService = new DomainVerificationService(
                mSystemContext, SystemConfig.getInstance(), platformCompat);
        mSystemServiceManager.startService(domainVerificationService);
        t.traceEnd();
      ...
      ...
      //啟動(dòng)PMS
       t.traceBegin("StartPackageManagerService");
        try {
            Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain");
            Pair<PackageManagerService, IPackageManager> pmsPair = PackageManagerService.main(
                    mSystemContext, installer, domainVerificationService,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
            mPackageManagerService = pmsPair.first;
            iPackageManager = pmsPair.second;
        } finally {
            Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");
        }
    ...
    ...
    }
......
.....
    private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
        ...
        ...
        WindowManagerService wm = null;
        ...
        ...
            //啟動(dòng)WMS
            t.traceBegin("StartWindowManagerService");
            // WMS needs sensor service ready
            mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_SENSOR_SERVICE);
            wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
                    new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
            ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
                    DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
            ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
                    /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
            t.traceEnd();

            t.traceBegin("SetWindowManagerService");
            mActivityManagerService.setWindowManager(wm);
            t.traceEnd();

            t.traceBegin("WindowManagerServiceOnInitReady");
            wm.onInitReady();
            t.traceEnd();
      .....
      .....
    }

注意此處開(kāi)始Android的10到13版本各有變化阻桅,其中11到13屬于重構(gòu)逐漸迭代過(guò)程

Android T(13) SDK32版本的過(guò)程以后分析

PackageManagerService --> main()

Android Q(10) SDK29版本的過(guò)程
  • PackageManagerService -> main() --> new PackageManagerService()
    在這個(gè)巨大無(wú)比的構(gòu)造方法中摘出我們需要關(guān)心的兩個(gè)方法
    -->scanDirTracedLI()
    -->installSystemStubPackages()
    public static PackageManagerService main(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
        // Self-check for initial settings.
        PackageManagerServiceCompilerMapping.checkProperties();

        PackageManagerService m = new PackageManagerService(context, installer,
                factoryTest, onlyCore);
        m.enableSystemUserPackages();
        ServiceManager.addService("package", m);
        final PackageManagerNative pmn = m.new PackageManagerNative();
        ServiceManager.addService("package_native", pmn);
        return m;
    }
    public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
            ....
            ....
             scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_VENDOR,
                    0);
          /**省略了很多目錄 PRODUCT_OVERLAY_DIR,PRODUCT_SERVICES_OVERLAY_DIR 等等*/
          ....
          ....
            // Find base frameworks (resource packages without code).
            //掃描安裝“system\framework”目錄下的jar包
            scanDirTracedLI(frameworkDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_NO_DEX
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_PRIVILEGED,
                    0);
          ....
          ....
           // Collect privileged system packages. /system/priv-app
            final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
            scanDirTracedLI(privilegedAppDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_PRIVILEGED,
                    0);
           /**省略了很多目錄 Environment.getRootDirectory()+"app" == /system/app兼都,
            Environment.getVendorDirectory()+"priv-app"== /vendor/piv-app 
            Environment.getVendorDirectory()+"app"== /vendor/app
            Environment.getOdmDirectory()+"priv-app"== /omd/piv-app 
            Environment.getOdmDirectory()+"app"== /omd/app 
            Environment.getOemDirectory()+"app"== /oed/piv-app 
            Environment.getProductDirectory()+"priv-app"== /product/piv-app
            Environment.getProductDirectory()+"app"== /product/app
            Environment.getProductServicesDirectory()+"priv-app"== //product_services/priv-app 
            Environment.getProductServicesDirectory()+"app"== //product_services/app **/
          ....
          ....
           // Stub packages must either be replaced with full versions in the /data
            // partition or be disabled.
            final List<String> stubSystemApps = new ArrayList<>();
            if (!mOnlyCore) {
                // do this first before mucking with mPackages for the "expecting better" case
                //mPackages是在方法scanDirTracedLI中賦值的
                final Iterator<PackageParser.Package> pkgIterator = mPackages.values().iterator();
                while (pkgIterator.hasNext()) {
                    final PackageParser.Package pkg = pkgIterator.next();
                    if (pkg.isStub) {
                        stubSystemApps.add(pkg.packageName);
                    }
                }
            ....
            ....
            }
           ....
           ....
           if (!mOnlyCore) {
                EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                        SystemClock.uptimeMillis());
                //sAppInstallDir這個(gè)目錄是 Environment.getDataDirectory()+ "app" == /data/app
                //掃描三方安裝目錄
                scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
                ....
                ....
                // Uncompress and install any stubbed system applications.
                // This must be done last to ensure all stubs are replaced or disabled.
                //安裝系統(tǒng)應(yīng)用
                installSystemStubPackages(stubSystemApps, scanFlags); 
            }
            ....
            ....
            // Now that we know all of the shared libraries, update all clients to have
            // the correct library paths.
            //更新所有應(yīng)用庫(kù)的路徑
            updateAllSharedLibrariesLocked(null, Collections.unmodifiableMap(mPackages));
            ....
            ...
            for (String pkgName : deferPackages) {
            ....
                  //最后會(huì)調(diào)到 mInstaller.createAppData嫂沉, 
                  //通過(guò)Binder調(diào)用到 進(jìn)程installd,最終調(diào)用installd的createAppData()
                  prepareAppDataAndMigrateLIF(pkg, UserHandle.USER_SYSTEM, storageFlags, true /* maybeMigrateAppData */);
            ....
            }
    }

方法scanDirTracedLI()

--> scanDirLI()此方法中又有兩個(gè)值得關(guān)注的方法
-->parallelPackageParser.submit(file, parseFlags)
-->scanPackageChildLI()

 private void scanDirTracedLI(File scanDir, final int parseFlags, int scanFlags, long currentTime) {
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]");
        try {
            scanDirLI(scanDir, parseFlags, scanFlags, currentTime);
        } finally {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }
    }
 private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime) {
        ....
        ....
       try (ParallelPackageParser parallelPackageParser = new ParallelPackageParser(
                mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir,
                mParallelPackageParserCallback)) {
            // Submit files for parsing in parallel
            int fileCount = 0;
            for (File file : files) {
                final boolean isPackage = (isApkFile(file) || file.isDirectory())
                        && !PackageInstallerService.isStageName(file.getName());
                if (!isPackage) {
                    // Ignore entries which are not packages
                    continue;
                }
                //解析apk文件俯抖,主要是對(duì)AndroidManifest.xml進(jìn)行解析输瓜,解析后所有的信息放在Package對(duì)象中
                parallelPackageParser.submit(file, parseFlags);
                fileCount++;
            }
            // Process results one by one
            for (; fileCount > 0; fileCount--) {
                ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
                ....
                ....
                        scanPackageChildLI(parseResult.pkg, parseFlags, scanFlags,currentTime, null);
            ....
            }
       }
          

        ....
 }
  • 首先看parallelPackageParser.submit方法
    ParallelPackageParser --> parallelPackageParser.submit(file, parseFlags) --> parsePackage()
    /**
     * Submits the file for parsing
     * @param scanFile file to scan
     * @param parseFlags parse falgs
     */
    public void submit(File scanFile, int parseFlags) {
        mService.submit(() -> {
            ParseResult pr = new ParseResult();
            ...
            try {
                ....
                ....
                pr.pkg = parsePackage(pp, scanFile, parseFlags);
            } catch (Throwable e) {
                pr.throwable = e;
            } finally {
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }
            try {
                mQueue.put(pr);
            } catch (InterruptedException e) {
                ....
            }
        });
    }
    @VisibleForTesting
    protected PackageParser.Package parsePackage(PackageParser packageParser, File scanFile,
            int parseFlags) throws PackageParser.PackageParserException {
        return packageParser.parsePackage(scanFile, parseFlags, true /* useCaches */);
    }

繼續(xù)跟進(jìn),這個(gè)過(guò)程中注意是對(duì)apk資源的加載和AndroidManifest.xml的解析
PackageParser -> parsePackage() 其中兩個(gè)方法最終都會(huì)調(diào)用到 parseBaseApk()
-->parseBaseApk()-->parseBaseApkCommon() 中包括解析四大組件芬萍,權(quán)限等等方法
-->parseBaseApplication() 具體往里跟進(jìn)一下
--->parsePermission()
....

       public Package parsePackage(File packageFile, int flags, boolean useCaches)
            throws PackageParserException {
        if (packageFile.isDirectory()) {
            return parseClusterPackage(packageFile, flags);
        } else {
            return parseMonolithicPackage(packageFile, flags);
        }
    }
    private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
        //因?yàn)锳ndroidManifest.xml 文件解析節(jié)點(diǎn)很多很龐大,這一步是對(duì)其進(jìn)行一個(gè)初步解析搔啊,
        //獲取應(yīng)用目錄的PackageLite對(duì)象柬祠,這個(gè)對(duì)象分開(kāi)保存了目錄下的核心應(yīng)用以及非核心應(yīng)用
        //主要用于對(duì)apk資源的加載
        final PackageLite lite = parseClusterPackageLite(packageDir, 0);
    ....
    ....
            //對(duì)apk資源的加載
            final AssetManager assets = assetLoader.getBaseAssetManager();
    ....
                //對(duì)核心應(yīng)用解析 parseBaseApk
            final Package pkg = parseBaseApk(baseApk, assets, flags);
    ....
    ....
                for (int i = 0; i < num; i++) {
                    //對(duì)非核心apk資源的加載
                    final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
                    //對(duì)非核心應(yīng)用的處理
                    parseSplitApk(pkg, i, splitAssets, flags);
                }
    }

    public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
        //對(duì)AndroidManifest.xml 文件進(jìn)行初步解析,主要用于對(duì)apk資源的加載
        final PackageLite lite = parseMonolithicPackageLite(apkFile, flags);
        ....
         final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
        ....
            //對(duì)核心應(yīng)用解析 负芋,assetLoader.getBaseAssetManager()是對(duì)apk資源的加載
            final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags);
    }
    
    private Package parseBaseApk(File apkFile, AssetManager assets, int flags)
            throws PackageParserException {
        ....
        ....
        //獲得一個(gè) XML 資源解析對(duì)象漫蛔,該對(duì)象解析的是 APK 中的 AndroidManifest.xml 文件。
        parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
        final Resources res = new Resources(assets, mMetrics, null);
 
        final String[] outError = new String[1];
        //再調(diào)用重載函數(shù)parseBaseApk()最終到parseBaseApkCommon()旧蛾,解析AndroidManifest.xml 后得到一個(gè)Package對(duì)象
        final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
        ....
        ....
    }
    private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
            String[] outError) throws XmlPullParserException, IOException {
    ....
    ....
    return parseBaseApkCommon(pkg, null, res, parser, flags, outError);
    }
    private Package parseBaseApkCommon(Package pkg, Set<String> acceptedTags, Resources res,
            XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException,
            IOException {
            .....
            ....
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
                  //從AndroidManifest.xml中獲取標(biāo)簽名
                  String tagName = parser.getName();
                  ....
                  //如果讀到AndroidManifest.xml中的tag是"application",執(zhí)行parseBaseApplication()進(jìn)行解析
                  if (tagName.equals(TAG_APPLICATION)) {
                  ....
                  ....
                      if (!parseBaseApplication(pkg, res, parser, flags, outError)) {
                          return null;
                      }
                  } 
                  .....
                  .....
                  // //如果標(biāo)簽是"permission"
                  else if (tagName.equals(TAG_PERMISSION)) {
                      if (!parsePermission(pkg, res, parser, outError)) {
                          return null;
                      }
            }
            }
    .....
    ....
    }
    //在該方法中可以看出四大組件的解析過(guò)程
    private boolean parseBaseApplication(Package owner, Resources res,
            XmlResourceParser parser, int flags, String[] outError)
        throws XmlPullParserException, IOException {
    ....
    ....
        if (tagName.equals("activity")) {
                Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false,
                        owner.baseHardwareAccelerated);
                ....
                }

                ....

            } else if (tagName.equals("receiver")) {
                Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
                        true, false);
                .....
                ....

            } else if (tagName.equals("service")) {
                Service s = parseService(owner, res, parser, flags, outError, cachedArgs);
                .....

            } else if (tagName.equals("provider")) {
                Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs);
                .....

            }
    }
  • 在 PackageParser 掃描完一個(gè) APK 后莽龟,此時(shí)系統(tǒng)已經(jīng)根據(jù)該 APK 中 AndroidManifest.xml,創(chuàng)建了一個(gè)完整的 Package 對(duì)象锨天,下一步就是將該 Package 加入到系統(tǒng)中毯盈,接下來(lái)是方法scanPackageChildLI()
    scanPackageChildLI() --> addForInitLI()
    主要進(jìn)行安裝包校驗(yàn)、簽名檢查病袄、apk更新等操作
/**
     *  Scans a package and returns the newly parsed package.
     *  @throws PackageManagerException on a parse error.
     */
    @GuardedBy({"mInstallLock", "mPackages"})
    private PackageParser.Package scanPackageChildLI(PackageParser.Package pkg,
            final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime,
            @Nullable UserHandle user){
        if ((scanFlags & SCAN_CHECK_ONLY) == 0) {
            if (pkg.childPackages != null && pkg.childPackages.size() > 0) {
                scanFlags |= SCAN_CHECK_ONLY;
            }
        } else {
            scanFlags &= ~SCAN_CHECK_ONLY;
        }

        //在addForInitLI()中搂赋,進(jìn)行安裝包校驗(yàn)赘阀、簽名檢查、apk更新等操作脑奠,把Package加入系統(tǒng)
        // Scan the parent
        PackageParser.Package scannedPkg = addForInitLI(pkg, parseFlags,
                scanFlags, currentTime, user);
        // Scan the children
        final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
        for (int i = 0; i < childCount; i++) {
            PackageParser.Package childPackage = pkg.childPackages.get(i);
            addForInitLI(childPackage, parseFlags, scanFlags,
                    currentTime, user);
        }


        if ((scanFlags & SCAN_CHECK_ONLY) != 0) {
            return scanPackageChildLI(pkg, parseFlags, scanFlags, currentTime, user);
        }

        return scannedPkg;
    }

以上是scanDirTracedLI()方法的流程基公,簡(jiǎn)單總結(jié)一下就是掃描系統(tǒng)存放apk目錄解析AndroidManifest.xml文件生成Package,然后進(jìn)行校驗(yàn)宋欺、簽名檢查轰豆、apk更新等操作,把Package加入系統(tǒng)齿诞;

接下來(lái)是方法 installSystemStubPackages()酸休,

主要功能是對(duì)壓縮編譯后的apk.gz進(jìn)行解壓安裝,為了優(yōu)化system分區(qū)空間掌挚,對(duì)app進(jìn)行壓縮編譯
installSystemStubPackages()--> installStubPackageLI(pkg, 0, scanFlags) 中有兩個(gè)關(guān)鍵方法
-->decompressPackage()
-->scanPackageTracedLI()

    private void installSystemStubPackages(@NonNull List<String> systemStubPackageNames,
            @ScanFlags int scanFlags) {
        ....
        ....
        installStubPackageLI(pkg, 0, scanFlags);
    }

    private PackageParser.Package installStubPackageLI(PackageParser.Package stubPkg,
            @ParseFlags int parseFlags, @ScanFlags int scanFlags)
                    throws PackageManagerException {
        ....
        // uncompress the binary to its eventual destination on /data
        //解壓到data目錄
        final File scanFile = decompressPackage(stubPkg.packageName, stubPkg.codePath);
        ...
        ...
         try {
            return scanPackageTracedLI(scanFile, parseFlags, scanFlags, 0, null);
        } 
    ....
    }
  • 首先看方法decompressPackage() --> PackageManagerServiceUtils -->decompressFile()
    private File decompressPackage(String packageName, String codePath) {
        //過(guò)濾是否有壓縮編譯的,gz文件
        final File[] compressedFiles = getCompressedFiles(codePath);
        if (compressedFiles == null || compressedFiles.length == 0) {
            .....
            return null;
        }
        //這個(gè)Environment.getDataAppDirectory是/data/app目錄,也就是說(shuō)解壓安裝壓縮編譯后的路徑是和通過(guò)install安裝的分區(qū)目錄是一樣的
        final File dstCodePath =
                getNextCodePath(Environment.getDataAppDirectory(null), packageName);
        int ret = PackageManager.INSTALL_SUCCEEDED;
        try {
            Os.mkdir(dstCodePath.getAbsolutePath(), 0755);
            Os.chmod(dstCodePath.getAbsolutePath(), 0755);
            for (File srcFile : compressedFiles) {
                final String srcFileName = srcFile.getName();
                final String dstFileName = srcFileName.substring(
                        0, srcFileName.length() - COMPRESSED_EXTENSION.length());
                final File dstFile = new File(dstCodePath, dstFileName);
                ret = decompressFile(srcFile, dstFile);
                .....
            }
        }
        .....
        .....
        if (ret == PackageManager.INSTALL_SUCCEEDED) {
            final File libraryRoot = new File(dstCodePath, LIB_DIR_NAME);
            NativeLibraryHelper.Handle handle = null;
            try {
                handle = NativeLibraryHelper.Handle.create(dstCodePath);
                //釋放apk中的so文件到本地目錄
                ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
                        null /*abiOverride*/);
            }
            .....
        }
        ....
        return dstCodePath;
    }

PackageManagerServiceUtils -->decompressFile()
解壓壓縮文件

    public static int decompressFile(File srcFile, File dstFile) throws ErrnoException {
        if (DEBUG_COMPRESSION) {
            Slog.i(TAG, "Decompress file"
                    + "; src: " + srcFile.getAbsolutePath()
                    + ", dst: " + dstFile.getAbsolutePath());
        }
        try (
                InputStream fileIn = new GZIPInputStream(new FileInputStream(srcFile));
                OutputStream fileOut = new FileOutputStream(dstFile, false /*append*/);
        ) {
            FileUtils.copy(fileIn, fileOut);
            Os.chmod(dstFile.getAbsolutePath(), 0644);
            return PackageManager.INSTALL_SUCCEEDED;
        } catch (IOException e) {
            logCriticalInfo(Log.ERROR, "Failed to decompress file"
                    + "; src: " + srcFile.getAbsolutePath()
                    + ", dst: " + dstFile.getAbsolutePath());
        }
        return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
    }
  • 再看installStubPackageLI() --> scanPackageTracedLI()--> scanPackageLI()
    接下來(lái)跟上面分析的掃描系統(tǒng)指定目錄對(duì)apk的處理是一樣的
    -->PackageParser-->pp.parsePackage()先解析
    -->scanPackageChildLI()再進(jìn)行校驗(yàn)雨席、簽名檢查、apk更新等操作吠式,把Package加入系統(tǒng)陡厘;
    private PackageParser.Package scanPackageTracedLI(File scanFile, final int parseFlags,
            int scanFlags, long currentTime, UserHandle user) throws PackageManagerException {
      .....
      return scanPackageLI(scanFile, parseFlags, scanFlags, currentTime, user);
      .....
    }
    private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
            long currentTime, UserHandle user) throws PackageManagerException {
        ....
        PackageParser pp = new PackageParser();
        ....
        pkg = pp.parsePackage(scanFile, parseFlags);
        ....
        return scanPackageChildLI(pkg, parseFlags, scanFlags, currentTime, user);
    }

到這里已經(jīng)我們已經(jīng)分析到了系統(tǒng)應(yīng)用AndroidManifest.xml被解析過(guò)程,這些都是再PMS的構(gòu)造方法中執(zhí)行的特占,而PMS是再SystemServer中被啟動(dòng)的糙置,所以想要在系統(tǒng)目錄下/system、//vendor等等目錄下的apk的AndroidManifest.xml生效是目,需要重啟系統(tǒng)谤饭,或者重啟SystemServer進(jìn)程。

另外關(guān)于系統(tǒng)應(yīng)用安裝懊纳?
安裝的原理就是把通過(guò)進(jìn)程間通信通過(guò)PMS完成對(duì)apk復(fù)制到指定目錄/data/app揉抵、/system/app、/system/priv-app等嗤疯,對(duì)齊進(jìn)行解析冤今,的操作,系統(tǒng)應(yīng)用本身就在指定目錄茂缚,所以在PMS啟動(dòng)后完成解析就是安裝完成了

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末戏罢,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子脚囊,更是在濱河造成了極大的恐慌龟糕,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悔耘,死亡現(xiàn)場(chǎng)離奇詭異讲岁,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén)催首,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)扶踊,“玉大人,你說(shuō)我怎么就攤上這事郎任⊙砗模” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵舶治,是天一觀的道長(zhǎng)分井。 經(jīng)常有香客問(wèn)我,道長(zhǎng)霉猛,這世上最難降的妖魔是什么尺锚? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮惜浅,結(jié)果婚禮上瘫辩,老公的妹妹穿的比我還像新娘。我一直安慰自己坛悉,他們只是感情好伐厌,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著裸影,像睡著了一般挣轨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上轩猩,一...
    開(kāi)封第一講書(shū)人閱讀 52,156評(píng)論 1 308
  • 那天卷扮,我揣著相機(jī)與錄音,去河邊找鬼均践。 笑死晤锹,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的彤委。 我是一名探鬼主播抖甘,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼葫慎!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起薇宠,我...
    開(kāi)封第一講書(shū)人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤偷办,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后澄港,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體椒涯,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年回梧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了废岂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片祖搓。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖湖苞,靈堂內(nèi)的尸體忽然破棺而出拯欧,到底是詐尸還是另有隱情,我是刑警寧澤财骨,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布镐作,位于F島的核電站,受9級(jí)特大地震影響隆箩,放射性物質(zhì)發(fā)生泄漏该贾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一捌臊、第九天 我趴在偏房一處隱蔽的房頂上張望杨蛋。 院中可真熱鬧,春花似錦理澎、人聲如沸逞力。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)掏击。三九已至,卻和暖如春秩铆,著一層夾襖步出監(jiān)牢的瞬間砚亭,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工殴玛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留捅膘,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓滚粟,卻偏偏與公主長(zhǎng)得像寻仗,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子凡壤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容