調(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)
先上圖
首先分析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)后完成解析就是安裝完成了