Android系統啓動流程分析之安裝應用

跟隨上一篇博客Android系統的啓動流程簡要分析繼續分析android系統的啓動.上一篇文章裏講了,SystemServer在main方法裏創建了一個線程ServerThread,並調用
initAndLoop方法.
ServerThread thr = new ServerThread();
thr.initAndLoop();
在initAndLoop方法裏加載各種服務,比如WindowManagerService(Wms)、ActivityManagerService(Ams)、PackageManagerService(Pms)等.
看下啓動PackageManagerServer的代碼
pm = PackageManagerService.main(context, installer, factoryTest != SystemServer.FACTORY_TEST_OFF, onlyCore);
這個pm是IPackageManager的實例,IPackageManager是由IPackageManager.aidl文件編譯生成的.
PackageManagerService繼承自IPackageManager.Stub
public class PackageManagerService extends IPackageManager.Stub {
PackageManagerService調用main方法,傳入四個參數
context 上下文
installer 安裝器
factoryTest != SystemServer.FACTORY_TEST_OFF 是否爲正常的工廠模式
onlyCore 爲true表示在加密的設備只啓動核心的程序

那麼查看PackageManagerService的main方法.

PackageManagerService定義在frameworks/base/services/java/com/android/server/PackageManagerService.java文件中.

main方法是這樣的

public static final IPackageManager main(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {
		PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore);
		ServiceManager.addService("package", m);
		return m;
	}

根據傳入的四個參數創建PackageManagerService的實例,
然後通過ServiceManager添加這個PackageManagerService實例.
既然創建了這個實例,那麼就調用了它的有參構造函數
1.在構造函數裏會掃描制定目錄的apk文件
// 掃描基礎框架(沒有代碼的資源包)。				
				mFrameworkInstallObserver = new AppDirObserver(frameworkDir.getPath(), OBSERVER_EVENTS, true, false, false);
				mFrameworkInstallObserver.startWatching();
				scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_IS_PRIVILEGED, scanMode | SCAN_NO_DEX, 0);
				
				// 掃描system/priv-app目錄			 
				File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
				mPrivilegedInstallObserver = new AppDirObserver(privilegedAppDir.getPath(), OBSERVER_EVENTS, true, true, false);
				mPrivilegedInstallObserver.startWatching();
				scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_IS_PRIVILEGED, scanMode, 0);

				// 掃描system/app目錄				 
				File systemAppDir = new File(Environment.getRootDirectory(), "app");
				mSystemInstallObserver = new AppDirObserver(systemAppDir.getPath(), OBSERVER_EVENTS, true, false, false);
				mSystemInstallObserver.startWatching();
				scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);

				// 掃描映射目錄
				File vendorAppDir = new File("/vendor/app");
				mVendorInstallObserver = new AppDirObserver(vendorAppDir.getPath(), OBSERVER_EVENTS, true, false, false);
				mVendorInstallObserver.startWatching();
				scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
掃描調用的方法是scanDirLI,傳入四個參數,context(上下文),flag(標誌),scanMode(掃描模式),currentTime(當前時間).
2.在scanDirLI方法內部會調用
PackageParser.Package pkg = scanPackageLI(file, flags | PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);
3.scanPackageLI通過解析安裝包parsePackage獲取到安裝包的信息結構
PackageParser pp = new PackageParser(scanPath)
		pp.setSeparateProcesses(mSeparateProcesses);
		pp.setOnlyCoreApps(mOnlyCore);
		final PackageParser.Package pkg = pp.parsePackage(scanFile, scanPath, mMetrics, parseFlags);
4.之後調用parsePackage的重載方法解析,將應用信息保存在PackageManagerService,比如VersionCode、VersionName等
 try {
            // XXXX todo: need to figure out correct configuration.
            pkg = parsePackage(res, parser, flags, errorText);
        } catch (Exception e) {
            errorException = e;
            mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
        }
5.回到第3步,調用scanPackageLI的重載方法
PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE, currentTime, user);6.
6.然後調用createDataDirsLI方法
// And now re-install the app.
ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid, pkg.applicationInfo.seinfo);
7.在createDataDirsLI方法裏調用mInstaller的install方法進行安裝.
int res = mInstaller.install(packageName, uid, uid, seinfo);



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章