Android 系统服务 - PMS 的启动过程
相關文章鏈接:
1. Android Framework - 學習啟動篇
2. Android 系統服務 - PMS 的啟動過程
相關源碼文件:
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java frameworks/base/services/core/java/com/android/server/pm/Settings.java frameworks/base/services/core/java/com/android/server/SystemConfig frameworks/base/core/java/android/content/pm/PackageManager.javaframeworks/base/core/android/java/content/pm/IPackageManager.aidl frameworks/base/core/java/android/content/pm/PackageParser.java frameworks/base/cmds/pm/src/com/android/commands/pm/Pm.javaframeworks/base/services/core/java/com/android/server/pm/Installer.java frameworks/base/core/java/com/android/internal/os/InstallerConnection.javaPackageManagerService 也是 Android 應用開發者需要重點熟悉的一個服務,也是由 SystemService 進程創建的,管理著所有跟 package 相關的工作,常見的比如安裝、卸載應用。我們先找到其啟動創建的源代碼:
private void startBootstrapServices() {// 啟動 installer 服務Installer installer = mSystemServiceManager.startService(Installer.class);...// 處于加密狀態則僅僅解析核心應用String cryptState = SystemProperties.get("vold.decrypt");if (ENCRYPTING_STATE.equals(cryptState)) {mOnlyCore = true; // ENCRYPTING_STATE = "trigger_restart_min_framework"} else if (ENCRYPTED_STATE.equals(cryptState)) {mOnlyCore = true; // ENCRYPTED_STATE = "1"}// 創建 PKMS 對象 mPackageManagerService = PackageManagerService.main(mSystemContext, installer,mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);mPackageManager = mSystemContext.getPackageManager(); }SystemService 進程啟動過程中跟 PKMS 相關的有 installer 服務和 PackageManager 對象,我們主要分析他的創建過程也就是 PackageManagerService.main() 方法
public static PackageManagerService main(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {// 創建 PackageManagerService 對象PackageManagerService m = new PackageManagerService(context, installer,factoryTest, onlyCore);// 將 PKMS 添加到 ServiceManager 進程去管理ServiceManager.addService("package", m);return m;} public PackageManagerService(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {// 保存一些基本變量mContext = context;mFactoryTest = factoryTest;mOnlyCore = onlyCore;// 創建 Settings 對象mSettings = new Settings(mPackages);// 添加 system, phone, log, nfc, bluetooth, shell 這六種shareUserId到mSettings;mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);mSettings.addSharedUserLPw("android.uid.log", LOG_UID,ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);mInstaller = installer;// 用來優化 dexmPackageDexOptimizer = new PackageDexOptimizer(this);synchronized (mInstallLock) {synchronized (mPackages) {// 創建名為 “PackageManager” 的 handler 線程mHandlerThread = new ServiceThread(TAG,Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);mHandlerThread.start();mHandler = new PackageHandler(mHandlerThread.getLooper());Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);// 創建各種目錄File dataDir = Environment.getDataDirectory();mAppDataDir = new File(dataDir, "data");mAppInstallDir = new File(dataDir, "app");mAppLib32InstallDir = new File(dataDir, "app-lib");mAsecInternalPath = new File(dataDir, "app-asec").getPath();mUserAppDataDir = new File(dataDir, "user");mDrmAppPrivateInstallDir = new File(dataDir, "app-private");// 創建用戶管理服務sUserManager = new UserManagerService(context, this,mInstallLock, mPackages);// 這個目錄為 /system/frameworkFile frameworkDir = new File(Environment.getRootDirectory(), "framework");// 獲取到 frameworkDir 下面的所有文件String[] frameworkFiles = frameworkDir.list();if (frameworkFiles != null) {for (String dexCodeInstructionSet : dexCodeInstructionSets) {for (int i=0; i<frameworkFiles.length; i++) {File libPath = new File(frameworkDir, frameworkFiles[i]);String path = libPath.getPath();// alreadyDexOpted 列表是否包含該文件if (alreadyDexOpted.contains(path)) {continue;}// 過濾掉不是 apk 和 jar 的文件if (!path.endsWith(".apk") && !path.endsWith(".jar")) {continue;}try {int dexoptNeeded = DexFile.getDexOptNeeded(path, null, dexCodeInstructionSet, false);if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {// 執行 dexopt 優化操作 mInstaller.dexopt(path, Process.SYSTEM_UID, true, dexCodeInstructionSet, dexoptNeeded);}} catch (FileNotFoundException e) {Slog.w(TAG, "Jar not found: " + path);} catch (IOException e) {Slog.w(TAG, "Exception reading jar: " + path, e);}}}}// 搜集解析系統各種 app 包信息...// 移除文件mInstaller.moveFiles();// 清理所有安裝不完整的包ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();for(int i = 0; i < deletePkgsList.size(); i++) {cleanupInstallFailedPackage(deletePkgsList.get(i));}// 刪除臨時文件deleteTempPackageFiles();// 處理解析非系統的 app if (!mOnlyCore) {// 掃描解析 /data/app 目錄scanDirLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);// 掃描解析 /data/app-private 目錄scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,scanFlags | SCAN_REQUIRE_KNOWN, 0);...}// 將所有解析的包信息寫到 packages.xml 文件mSettings.writeLPr();} // synchronized (mPackages)} // synchronized (mInstallLock)// 調用 gc Runtime.getRuntime().gc();}PKMS 的創建和啟動過程比 AMS 復雜太多,我刪減了很多不是核心的代碼,總得來說 PKMS 在創建的過程中會去解析所有 apk 的安裝信息,其中包括系統應用和非系統的安裝應用,對于應用開發者來說,我們只需要關注非系統應用就足夠了。我們平時安裝的手機應用主要放在 mAppInstallDir(data/app) 目錄下。總的來說 PKMS 在啟動的時候會去解析我們手機所有的應用的 apk 包信息,并會將其所解析的內容全部保存在 mPackages 變量中,最后我們來看下 PKMS 到底是掃描解析保存了 apk 的哪些信息。
private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) {...for (File file : files) {// 是不是 apk 文件final boolean isPackage = (isApkFile(file) || file.isDirectory())&& !PackageInstallerService.isStageName(file.getName());if (!isPackage) {// Ignore entries which are not packagescontinue;}try {// 掃描解析 apk 文件scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK,scanFlags, currentTime, null);} catch (PackageManagerException e) {// 如果有異常,把這個文件或者文件夾刪除if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 &&e.error == PackageManager.INSTALL_FAILED_INVALID_APK) {logCriticalInfo(Log.WARN, "Deleting invalid package at " + file);if (file.isDirectory()) {mInstaller.rmPackageDir(file.getAbsolutePath());} else {file.delete();}}}}}private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,long currentTime, UserHandle user) throws PackageManagerException {// 創建一個解析對象PackageParser pp = new PackageParser();pp.setSeparateProcesses(mSeparateProcesses);pp.setOnlyCoreApps(mOnlyCore);pp.setDisplayMetrics(mMetrics);final PackageParser.Package pkg;try {// 解析 apk 參數,返回 PackageParser.Packagepkg = pp.parsePackage(scanFile, parseFlags);} catch (PackageParserException e) {throw PackageManagerException.from(e);}// 搜集證書信息collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags);...return scannedPkg;}public Package parsePackage(File packageFile, int flags) throws PackageParserException {if (packageFile.isDirectory()) {...} else {return parseMonolithicPackage(packageFile, flags);}}public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {final AssetManager assets = new AssetManager();try {final Package pkg = parseBaseApk(apkFile, assets, flags);pkg.codePath = apkFile.getAbsolutePath();return pkg;} finally {IoUtils.closeQuietly(assets);}}private Package parseBaseApk(File apkFile, AssetManager assets, int flags)throws PackageParserException {final String apkPath = apkFile.getAbsolutePath();final int cookie = loadApkIntoAssetManager(assets, apkPath, flags);Resources res = null;XmlResourceParser parser = null;try {res = new Resources(assets, mMetrics, null);assets.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,Build.VERSION.RESOURCES_SDK_INT);// 打開解析 AndroidManifest.xml 文件parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);final String[] outError = new String[1];final Package pkg = parseBaseApk(res, parser, flags, outError);if (pkg == null) {throw new PackageParserException(mParseError,apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);}return pkg;} catch (PackageParserException e) {throw e;} catch (Exception e) {throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,"Failed to read manifest from " + apkPath, e);} finally {IoUtils.closeQuietly(parser);}}private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,String[] outError) throws XmlPullParserException, IOException {AttributeSet attrs = parser;// 解析包名try {Pair<String, String> packageSplit = parsePackageSplitNames(parser, attrs, flags);pkgName = packageSplit.first;splitName = packageSplit.second;} catch (PackageParserException e) {mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;return null;}// 構建一個 Package 對象final Package pkg = new Package(pkgName);boolean foundApp = false;// 獲取 VersionCode 和 VersionNameTypedArray sa = res.obtainAttributes(attrs,com.android.internal.R.styleable.AndroidManifest);pkg.mVersionCode = pkg.applicationInfo.versionCode = sa.getInteger(com.android.internal.R.styleable.AndroidManifest_versionCode, 0);pkg.mVersionName = sa.getNonConfigurationString(com.android.internal.R.styleable.AndroidManifest_versionName, 0);if (pkg.mVersionName != null) {pkg.mVersionName = pkg.mVersionName.intern();}// 解析所有可能出現的屬性,application ,uses-permission,permission,等等int outerDepth = parser.getDepth();while ((type = parser.next()) != XmlPullParser.END_DOCUMENT&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {continue;}String tagName = parser.getName();if (tagName.equals("application")) {if (foundApp) {if (RIGID_PARSER) {outError[0] = "<manifest> has more than one <application>";mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return null;} else {Slog.w(TAG, "<manifest> has more than one <application>");XmlUtils.skipCurrentTag(parser);continue;}}foundApp = true;if (!parseBaseApplication(pkg, res, parser, attrs, flags, outError)) {return null;}} else if (tagName.equals("permission")) {if (parsePermission(pkg, res, parser, attrs, outError) == null) {return null;}} else if (tagName.equals("uses-permission")) {if (!parseUsesPermission(pkg, res, parser, attrs)) {return null;}} else if (RIGID_PARSER) {outError[0] = "Bad element under <manifest>: "+ parser.getName();mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return null;} else {Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()+ " at " + mArchiveSourcePath + " "+ parser.getPositionDescription());XmlUtils.skipCurrentTag(parser);continue;}}...return pkg;}private boolean parseBaseApplication(Package owner, Resources res,XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)throws XmlPullParserException, IOException {final ApplicationInfo ai = owner.applicationInfo;final String pkgName = owner.applicationInfo.packageName;TypedArray sa = res.obtainAttributes(attrs,com.android.internal.R.styleable.AndroidManifestApplication);// 解析 applicationString name = sa.getNonConfigurationString(com.android.internal.R.styleable.AndroidManifestApplication_name, 0);if (name != null) {ai.className = buildClassName(pkgName, name, outError);if (ai.className == null) {sa.recycle();mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return false;}}// 解析 allowBackupboolean allowBackup = sa.getBoolean(com.android.internal.R.styleable.AndroidManifestApplication_allowBackup, true);if (allowBackup) {...}// 解析 label 也就是 app 的名字TypedValue v = sa.peekValue(com.android.internal.R.styleable.AndroidManifestApplication_label);if (v != null && (ai.labelRes=v.resourceId) == 0) {ai.nonLocalizedLabel = v.coerceToString();}// 解析 icon ,logo,theme 等等ai.icon = sa.getResourceId(com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);ai.logo = sa.getResourceId(com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);ai.banner = sa.getResourceId(com.android.internal.R.styleable.AndroidManifestApplication_banner, 0);ai.theme = sa.getResourceId(com.android.internal.R.styleable.AndroidManifestApplication_theme, 0); // 開始解析四大組件final int innerDepth = parser.getDepth();int type;while ((type = parser.next()) != XmlPullParser.END_DOCUMENT&& (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {continue;}String tagName = parser.getName();if (tagName.equals("activity")) {Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,owner.baseHardwareAccelerated);if (a == null) {mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return false;}owner.activities.add(a);} else if (tagName.equals("receiver")) {Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);if (a == null) {mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return false;}owner.receivers.add(a);} else if (tagName.equals("service")) {Service s = parseService(owner, res, parser, attrs, flags, outError);if (s == null) {mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return false;}owner.services.add(s);} else if (tagName.equals("provider")) {Provider p = parseProvider(owner, res, parser, attrs, flags, outError);if (p == null) {mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return false;}owner.providers.add(p);} else if (tagName.equals("activity-alias")) {Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);if (a == null) {mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return false;}owner.activities.add(a);} else if (parser.getName().equals("meta-data")) {// note: application meta-data is stored off to the side, so it can// remain null in the primary copy (we like to avoid extra copies because// it can be large)if ((owner.mAppMetaData = parseMetaData(res, parser, attrs, owner.mAppMetaData,outError)) == null) {mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return false;}} else if (tagName.equals("library")) {sa = res.obtainAttributes(attrs,com.android.internal.R.styleable.AndroidManifestLibrary);// Note: don't allow this value to be a reference to a resource// that may change.String lname = sa.getNonResourceString(com.android.internal.R.styleable.AndroidManifestLibrary_name);sa.recycle();if (lname != null) {lname = lname.intern();if (!ArrayUtils.contains(owner.libraryNames, lname)) {owner.libraryNames = ArrayUtils.add(owner.libraryNames, lname);}}XmlUtils.skipCurrentTag(parser);} else if (tagName.equals("uses-library")) {sa = res.obtainAttributes(attrs,com.android.internal.R.styleable.AndroidManifestUsesLibrary);// Note: don't allow this value to be a reference to a resource// that may change.String lname = sa.getNonResourceString(com.android.internal.R.styleable.AndroidManifestUsesLibrary_name);boolean req = sa.getBoolean(com.android.internal.R.styleable.AndroidManifestUsesLibrary_required,true);sa.recycle();if (lname != null) {lname = lname.intern();if (req) {owner.usesLibraries = ArrayUtils.add(owner.usesLibraries, lname);} else {owner.usesOptionalLibraries = ArrayUtils.add(owner.usesOptionalLibraries, lname);}}XmlUtils.skipCurrentTag(parser);} else if (tagName.equals("uses-package")) {// Dependencies for app installers; we don't currently try to// enforce this.XmlUtils.skipCurrentTag(parser);} else {if (!RIGID_PARSER) {Slog.w(TAG, "Unknown element under <application>: " + tagName+ " at " + mArchiveSourcePath + " "+ parser.getPositionDescription());XmlUtils.skipCurrentTag(parser);continue;} else {outError[0] = "Bad element under <application>: " + tagName;mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;return false;}}}return true;}視頻地址:https://pan.baidu.com/s/1dM3K9bPRuepFUJIASIDeQg
視頻密碼:af97
總結
以上是生活随笔為你收集整理的Android 系统服务 - PMS 的启动过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Error creating bean
- 下一篇: leetcode 825. Friend