privatevoidrun(){try{// 省略部分代碼,只列出關(guān)鍵部分的代碼// The system server should never make non-oneway callsBinder.setWarnOnBlocking(true);// Initialize native services.System.loadLibrary("android_servers");// Create the system service manager.// SystemServiceManager是整個Service的大管家mSystemServiceManager =newSystemServiceManager(mSystemContext);mSystemServiceManager.setStartInfo(mRuntimeRestart,mRuntimeStartElapsedTime, mRuntimeStartUptime);LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);}finally{t.traceEnd();// InitBeforeStartServices}// Start services.try{t.traceBegin("StartServices");// start critical services, include PMS/AMSstartBootstrapServices(t);// start essential servicesstartCoreServices(t);// start other servicestartOtherServices(t);}catch(Throwable ex){Slog.e("System","******************************************");Slog.e("System","************ Failure starting system services", ex);throw ex;}finally{t.traceEnd();// StartServices}}
/*** Starts the small tangle of critical services that are needed to get the system off the* ground. These services have complex mutual dependencies which is why we initialize them all* in one place here. Unless your service is also entwined in these dependencies, it should be* initialized in one of the other functions.*/privatevoidstartBootstrapServices(@NonNullTimingsTraceAndSlog t){// 省略部分代碼t.traceBegin("StartPackageManagerService");try{Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain");mPackageManagerService =PackageManagerService.main(mSystemContext, installer,mFactoryTestMode !=FactoryTest.FACTORY_TEST_OFF, mOnlyCore);}finally{Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");}// Now that the package manager has started, register the dex load reporter to capture any// dex files loaded by system server.// These dex files will be optimized by the BackgroundDexOptService.SystemServerDexLoadReporter.configureSystemServerDexReporter(mPackageManagerService);mFirstBoot = mPackageManagerService.isFirstBoot();mPackageManager = mSystemContext.getPackageManager();// 省略部分代碼}
privatevoidscanDirLI(File scanDir,int parseFlags,int scanFlags,long currentTime,PackageParser2 packageParser,ExecutorService executorService){ParallelPackageParser parallelPackageParser =newParallelPackageParser(packageParser, executorService);// Submit files for parsing in parallelint fileCount =0;for(File file : files){finalboolean isPackage =(isApkFile(file)|| file.isDirectory())&&!PackageInstallerService.isStageName(file.getName());if(!isPackage){// Ignore entries which are not packagescontinue;}// 繼續(xù)往下調(diào)用了parallelPackageParser.submit()parallelPackageParser.submit(file, parseFlags);fileCount++;}}
ParallelPackageParser.submit(File scanFile, int parseFlags)
/*** Submits the file for parsing* @param scanFile file to scan* @param parseFlags parse flags*/publicvoidsubmit(File scanFile,int parseFlags){mExecutorService.submit(()->{ParseResult pr =newParseResult();Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER,"parallel parsePackage ["+ scanFile +"]");try{pr.scanFile = scanFile;// 繼續(xù)往下調(diào)用了parserPackage()pr.parsedPackage =parsePackage(scanFile, parseFlags);}catch(Throwable e){pr.throwable = e;}finally{Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);}try{mQueue.put(pr);}catch(InterruptedException e){Thread.currentThread().interrupt();// Propagate result to callers of take().// This is helpful to prevent main thread from getting stuck waiting on// ParallelPackageParser to finish in case of interruptionmInterruptedInThread =Thread.currentThread().getName();}});}
ParallelPackageParser.parsePackage(File scanFile, int parseFlags)
Single APK:安裝文件為一個完整的APK,即base APK。Android稱其為Monolithic。
Mutiple APK:安裝文件在一個文件目錄中,其內(nèi)部有多個被拆分的APK,這些APK由一個 base APK和一個或多個split APK組成。Android稱其為Cluster。
??????我們直接看解析Single APK文件的邏輯
ParsingPackageUtils.parseMonolithicPackage(ParseInput input, File apkFile, int flags)
/*** Parse the given APK file, treating it as as a single monolithic package.* <p>* Note that this <em>does not</em> perform signature verification; that* must be done separately in {@link #getSigningDetails(ParsingPackageRead, boolean)}.*/privateParseResult<ParsingPackage>parseMonolithicPackage(ParseInput input,File apkFile,int flags)throwsPackageParserException{// 省略部分代碼finalSplitAssetLoader assetLoader =newDefaultSplitAssetLoader(lite, flags);try{// 真正開始解析apk信息ParseResult<ParsingPackage> result =parseBaseApk(input,apkFile,apkFile.getCanonicalPath(),assetLoader.getBaseAssetManager(), flags);if(result.isError()){return input.error(result);}return input.success(result.getResult().setUse32BitAbi(lite.use32bitAbi));}catch(IOException e){return input.error(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,"Failed to get path: "+ apkFile, e);}finally{IoUtils.closeQuietly(assetLoader);}}
parsingPackageUtils.parseBaseApk(ParseInput input, File apkFile, String codePath, AssetManager assets, int flags)
/*** Parse the manifest of a <em>base APK</em>. When adding new features you* need to consider whether they should be supported by split APKs and child* packages.** @param apkPath The package apk file path* @param res The resources from which to resolve values* @param parser The manifest parser* @param flags Flags how to parse* @return Parsed package or null on error.*/privateParseResult<ParsingPackage>parseBaseApk(ParseInput input,String apkPath,String codePath,Resources res,XmlResourceParser parser,int flags)throwsXmlPullParserException,IOException,PackageParserException{// 省略部分代碼finalTypedArray manifestArray = res.obtainAttributes(parser,R.styleable.AndroidManifest);try{finalboolean isCoreApp =parser.getAttributeBooleanValue(null,"coreApp",false);finalParsingPackage pkg = mCallback.startParsingPackage(pkgName, apkPath, codePath, manifestArray, isCoreApp);// 繼續(xù)往下調(diào)用了parseBaseApkTags()finalParseResult<ParsingPackage> result =parseBaseApkTags(input, pkg, manifestArray, res, parser, flags);if(result.isError()){return result;}return input.success(pkg);}finally{manifestArray.recycle();}}
parsingPackageUtils.parseBaseApkTags(ParseInput input, ParsingPackage pkg, TypedArray sa, Resources res, XmlResourceParser parser, int flags)
privateParseResult<ParsingPackage>parseBaseApkTags(ParseInput input,ParsingPackage pkg,TypedArray sa,Resources res,XmlResourceParser parser,int flags)throwsXmlPullParserException,IOException{//省略部分代碼while((type = parser.next())!=XmlPullParser.END_DOCUMENT&&(type !=XmlPullParser.END_TAG|| parser.getDepth()> depth)){if(type !=XmlPullParser.START_TAG){continue;}String tagName = parser.getName();finalParseResult result;if(PackageParser.TAG_APPLICATION.equals(tagName)){// 找到<applicaton>標簽,四大組件的聲明都在里面if(foundApp){if(PackageParser.RIGID_PARSER){result = input.error("<manifest> has more than one <application>");}else{Slog.w(TAG,"<manifest> has more than one <application>");result = input.success(null);}}else{foundApp =true;// 關(guān)鍵在這里result =parseBaseApplication(input, pkg, res, parser, flags);}}else{// 解析除<application>外的其他標簽result =parseBaseApkTag(tagName, input, pkg, res, parser, flags);}if(result.isError()){return input.error(result);}}// 省略部分代碼return input.success(pkg);}
parsingPackageUtils.parseBaseApplication(ParseInput input, ParsingPackage pkg, Resources res, XmlResourceParser parser, int flags)