PackageManagerService 啟動流程源碼解析

weizhenggen 9年前發布 | 11K 次閱讀 技術 Android開發 移動開發

概述

PackageManagerService,是Android系統中核心服務之一,管理著所有跟package相關的工作,常見的比如安裝、卸載應用。 PKMS服務也是通過binder進行通信,IPackageManager.aidl由工具轉換后自動生成binder的服務端IPackageManager.Stub和客戶端IPackageManager.Stub.Proxy,具體關系如下:

Binder服務端:PackageManagerService繼承于IPackageManager.Stub;

Binder客戶端:ApplicationPackageManager(簡稱APM)的成員變量mPM繼承于IPackageManager.Stub.Proxy; 本身APM是繼承于PackageManager對象。

Android系統啟動過程中,一路啟動到SystemServer后,便可以啟動framework的各大服務,本篇博客將介紹PKMS的啟動過程(基于安卓7.0源碼)。

PackageManagerService的啟動

SystemServer啟動過程中涉及到的PKMS代碼如下:

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);
//PKMS是否首次啟動
mFirstBoot = mPackageManagerService.isFirstBoot();


mPackageManager = mSystemContext.getPackageManager();
...

}</code></pre>

PackageManagerService與其他所有的服務一樣,也是由SystemServer啟動,它也是java層服務之一,PKMS.main()過程主要是創建PKMS服務,并注冊到ServiceManager。

整個system_server進程啟動過程,涉及PKMS服務的主要幾個動作如下,接下來分別講解每個過程

PKMS.main()

PKMS.performBootDexOpt

PKMS.systemReady

PKMS.main()

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();
    // Disable any carrier apps. We do this very early in boot to prevent the apps from being
    // disabled after already being started.
    CarrierAppUtils.disableCarrierAppsUntilPrivileged(context.getOpPackageName(), m,
            UserHandle.USER_SYSTEM);
    //將包管理服務對象添加到ServiceManager
    ServiceManager.addService("package", m);
    return m;
}

該方法的主要功能創建PKMS對象,并將其注冊到ServiceManager。 關于PKMS對象的構造方法很長,分為以下幾個階段,每個階段會輸出相應的EventLog: 除了階段1的開頭部分代碼,后續代碼都是同時持有同步鎖mPackages和mInstallLock的過程中執行的。

階段1:BOOT_PROGRESS_PMS_START

階段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START

階段3:BOOT_PROGRESS_PMS_DATA_SCAN_START

階段4:BOOT_PROGRESS_PMS_SCAN_END

階段5:BOOT_PROGRESS_PMS_READY

階段1:BOOT_PROGRESS_PMS_START

階段1 PMS_START有兩部分組成,由無需加鎖的前部分和同時持有兩個鎖的后半部分,先來說說前半部分:

前半部分

//向事件日志寫入事件,標識PackageManagerService啟動
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
        SystemClock.uptimeMillis());
//SDK版本檢查
if (mSdkVersion <= 0) {
    Slog.w(TAG, "** ro.build.version.sdk not set!");
}

mContext = context; //開機模式是否為工廠模式 mFactoryTest = factoryTest; //是否僅啟動內核 mOnlyCore = onlyCore; //構造DisplayMetrics對象以便獲取尺寸數據 mMetrics = new DisplayMetrics(); //構造Settings對象存儲運行時的設置信息 mSettings = new Settings(mPackages); //添加一些用戶uid 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); //判斷是否在不同的進程 String separateProcesses = SystemProperties.get("debug.separate_processes"); if (separateProcesses != null && separateProcesses.length() > 0) { if ("".equals(separateProcesses)) { mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES; mSeparateProcesses = null; Slog.w(TAG, "Running with debug.separate_processes: (ALL)"); } else { mDefParseFlags = 0; mSeparateProcesses = separateProcesses.split(","); Slog.w(TAG, "Running with debug.separate_processes: "

            + separateProcesses);
}

} else { mDefParseFlags = 0; mSeparateProcesses = null; } //installer由SystemServer構造,這里通過該對象與底層進行通信,進行具體安裝與卸載的操作 mInstaller = installer; //創建PackageDexOptimizer,該類用于輔助進行dex優化 mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context, "dexopt"); mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());

mOnPermissionChangeListeners = new OnPermissionChangeListeners( FgThread.get().getLooper());

getDefaultDisplayMetrics(context, mMetrics); //獲取系統配置信息 SystemConfig systemConfig = SystemConfig.getInstance(); mGlobalGids = systemConfig.getGlobalGids(); mSystemPermissions = systemConfig.getSystemPermissions(); mAvailableFeatures = systemConfig.getAvailableFeatures();</code></pre>

接下來,再來看看后半部分:

synchronized (mInstallLock) {
// writer
synchronized (mPackages) {
    //啟動消息處理線程
    mHandlerThread = new ServiceThread(TAG,
            Process.THREAD_PRIORITY_BACKGROUND, true /allowIo/);
    mHandlerThread.start();
    //通過消息處理線程的Looper對象構造一個處理消息的Handler對象
    mHandler = new PackageHandler(mHandlerThread.getLooper());
    mProcessLoggingHandler = new ProcessLoggingHandler();
    //使用看門狗檢測當前消息處理線程
    Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
    //獲取當前的Data目錄
    File dataDir = Environment.getDataDirectory();
    mAppInstallDir = new File(dataDir, "app");
    mAppLib32InstallDir = new File(dataDir, "app-lib");
    mEphemeralInstallDir = new File(dataDir, "app-ephemeral");
    mAsecInternalPath = new File(dataDir, "app-asec").getPath();
    mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
    //構造UserManagerService對象,創建用戶管理服務
    sUserManager = new UserManagerService(context, this, mPackages);

// Propagate permission configuration in to package manager.
//讀取權限配置文件中的信息,保存到mPermissions這個ArrayMap中
ArrayMap<String, SystemConfig.PermissionEntry> permConfig
        = systemConfig.getPermissions();
for (int i=0; i<permConfig.size(); i++) {
    SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
    BasePermission bp = mSettings.mPermissions.get(perm.name);
    if (bp == null) {
        bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);
        mSettings.mPermissions.put(perm.name, bp);
    }
    if (perm.gids != null) {
        bp.setGids(perm.gids, perm.perUser);
    }
}
//獲取所有外部lib
ArrayMap<String, String> libConfig = systemConfig.getSharedLibraries();
for (int i=0; i<libConfig.size(); i++) {
    mSharedLibraries.put(libConfig.keyAt(i),
            new SharedLibraryEntry(libConfig.valueAt(i), null));
}
//嘗試讀取mac_permissions.xml并解析
mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();
//讀取并解析packages-backup.xml等文件
mRestoredSettings = mSettings.readLPw(sUserManager.getUsers(false));
//判斷是否自定義的解析界面
String customResolverActivity = Resources.getSystem().getString(
        R.string.config_customResolverActivity);
if (TextUtils.isEmpty(customResolverActivity)) {
    customResolverActivity = null;
} else {
    mCustomResolverComponentName = ComponentName.unflattenFromString(
            customResolverActivity);
}
................

}</code></pre>

這個過程涉及的幾個重要變量:

創建Settings

在階段1中創建了Settings對象,我們看看里面做了什么

Settings(File dataDir, Object lock) {
    mLock = lock;

mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);

mSystemDir = new File(dataDir, "system");
mSystemDir.mkdirs();//創建/data/system
FileUtils.setPermissions(mSystemDir.toString(),
        FileUtils.S_IRWXU|FileUtils.S_IRWXG
        |FileUtils.S_IROTH|FileUtils.S_IXOTH,
        -1, -1);
mSettingsFilename = new File(mSystemDir, "packages.xml");
mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
mPackageListFilename = new File(mSystemDir, "packages.list");
FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);

final File kernelDir = new File("/config/sdcardfs");
mKernelMappingFilename = kernelDir.exists() ? kernelDir : null;

// Deprecated: Needed for migration
mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");

}</code></pre>

此處mSystemDir是指目錄/data/system,在該目錄有以下5個文件:

SystemConfig階段1中還調用SystemConfig.getInstance()方法來獲取SystemConfig

public static SystemConfig getInstance() {
    synchronized (SystemConfig.class) {
        if (sInstance == null) {
            sInstance = new SystemConfig();
        }
        return sInstance;
    }
}
SystemConfig() {
    // Read configuration from system
    readPermissions(Environment.buildPath(
            Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
    // Read configuration from the old permissions dir
    readPermissions(Environment.buildPath(
            Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
    // Allow ODM to customize system configs around libs, features and apps
    int odmPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_APP_CONFIGS;
    readPermissions(Environment.buildPath(
            Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
    readPermissions(Environment.buildPath(
            Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
    // Only allow OEM to customize features
    readPermissions(Environment.buildPath(
            Environment.getOemDirectory(), "etc", "sysconfig"), ALLOW_FEATURES);
    readPermissions(Environment.buildPath(
            Environment.getOemDirectory(), "etc", "permissions"), ALLOW_FEATURES);
}

readPermissions()解析指定目錄下的所有xml文件,比如將標簽所指的動態庫保存到 PKMS的成員變量mSharedLibraries。可見,SystemConfig創建過程是對以下這六個目錄中的所有xml進行解析:

/system/etc/sysconfig

/system/etc/permissions

/odm/etc/sysconfig

/odm/etc/permissions

/oem/etc/sysconfig

/oem/etc/permissions

SystemConfig.readPermissions

void readPermissions(File libraryDir, int permissionFlag) {
    // Read permissions from given directory.
    if (!libraryDir.exists() || !libraryDir.isDirectory()) {
        if (permissionFlag == ALLOW_ALL) {
            Slog.w(TAG, "No directory " + libraryDir + ", skipping");
        }
        return;
    }
    if (!libraryDir.canRead()) {
        Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
        return;
    }

// Iterate over the files in the directory and scan .xml files
File platformFile = null;
for (File f : libraryDir.listFiles()) {
    // We'll read platform.xml last
    if (f.getPath().endsWith("etc/permissions/platform.xml")) {
        platformFile = f;
        continue;
    }

    if (!f.getPath().endsWith(".xml")) {
        Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
        continue;
    }
    if (!f.canRead()) {
        Slog.w(TAG, "Permissions library file " + f + " cannot be read");
        continue;
    }

    readPermissionsFromXml(f, permissionFlag);
}

// Read platform permissions last so it will take precedence
if (platformFile != null) {
    readPermissionsFromXml(platformFile, permissionFlag);
}

}</code></pre>

該方法是解析指定目錄下所有的具有可讀權限的,且以xml后綴文件。

階段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START

//標記掃描開始的時間
            long startTime = SystemClock.uptimeMillis();
            //將掃描開始的事件寫入日志
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
                    startTime);

        // Set flag to monitor and not change apk file paths when
        // scanning install directories.
        //設置掃描的模式
        final int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING | SCAN_INITIAL;
        //獲取java啟動類庫的路徑
        final String bootClassPath = System.getenv("BOOTCLASSPATH");
        //獲取systemServer的路徑
        final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");

        if (bootClassPath == null) {
            Slog.w(TAG, "No BOOTCLASSPATH found!");
        }

        if (systemServerClassPath == null) {
            Slog.w(TAG, "No SYSTEMSERVERCLASSPATH found!");
        }

        final List<String> allInstructionSets = InstructionSets.getAllInstructionSets();
        final String[] dexCodeInstructionSets =
                getDexCodeInstructionSets(
                        allInstructionSets.toArray(new String[allInstructionSets.size()]));

        /**
         * Ensure all external libraries have had dexopt run on them.
         */
        //確保所有的外部lib都被dexopt優化
        if (mSharedLibraries.size() > 0) {
            // NOTE: For now, we're compiling these system "shared libraries"
            // (and framework jars) into all available architectures. It's possible
            // to compile them only when we come across an app that uses them (there's
            // already logic for that in scanPackageLI) but that adds some complexity.
            for (String dexCodeInstructionSet : dexCodeInstructionSets) {
                for (SharedLibraryEntry libEntry : mSharedLibraries.values()) {
                    final String lib = libEntry.path;
                    if (lib == null) {
                        continue;
                    }

                    try {
                        // Shared libraries do not have profiles so we perform a full
                        // AOT compilation (if needed).
                        int dexoptNeeded = DexFile.getDexOptNeeded(
                                lib, dexCodeInstructionSet,
                                getCompilerFilterForReason(REASON_SHARED_APK),
                                false /* newProfile */);
                        if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
                            mInstaller.dexopt(lib, Process.SYSTEM_UID, dexCodeInstructionSet,
                                    dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/,
                                    getCompilerFilterForReason(REASON_SHARED_APK),
                                    StorageManager.UUID_PRIVATE_INTERNAL,
                                    SKIP_SHARED_LIBRARY_CHECK);
                        }
                    } catch (FileNotFoundException e) {
                        Slog.w(TAG, "Library not found: " + lib);
                    } catch (IOException | InstallerException e) {
                        Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
                                + e.getMessage());
                    }
                }
            }
        }

        File frameworkDir = new File(Environment.getRootDirectory(), "framework");

        final VersionInfo ver = mSettings.getInternalVersion();
        mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);

        // when upgrading from pre-M, promote system app permissions from install to runtime
        mPromoteSystemApps =
                mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;

        // When upgrading from pre-N, we need to handle package extraction like first boot,
        // as there is no profiling data available.
        mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;

        // save off the names of pre-existing system packages prior to scanning; we don't
        // want to automatically grant runtime permissions for new system apps
        if (mPromoteSystemApps) {
            Iterator<PackageSetting> pkgSettingIter = mSettings.mPackages.values().iterator();
            while (pkgSettingIter.hasNext()) {
                PackageSetting ps = pkgSettingIter.next();
                if (isSystemApp(ps)) {
                    mExistingSystemPackages.add(ps.name);
                }
            }
        }

        // Collect vendor overlay packages.
        // (Do this before scanning any apps.)
        // For security and version matching reason, only consider
        // overlay packages if they reside in VENDOR_OVERLAY_DIR.
        //收集供應商包名:/vendor/overlay
        File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
        scanDirTracedLI(vendorOverlayDir, mDefParseFlags
                | PackageParser.PARSE_IS_SYSTEM
                | PackageParser.PARSE_IS_SYSTEM_DIR
                | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);

        // Find base frameworks (resource packages without code).
        //掃描frameworkDir目錄下的apk進行安裝,掃描模式為非優化模式
        scanDirTracedLI(frameworkDir, mDefParseFlags
                | PackageParser.PARSE_IS_SYSTEM
                | PackageParser.PARSE_IS_SYSTEM_DIR
                | PackageParser.PARSE_IS_PRIVILEGED,
                scanFlags | SCAN_NO_DEX, 0);

        // Collected privileged system packages.
        final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
        scanDirTracedLI(privilegedAppDir, mDefParseFlags
                | PackageParser.PARSE_IS_SYSTEM
                | PackageParser.PARSE_IS_SYSTEM_DIR
                | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);

        // Collect ordinary system packages.
        final File systemAppDir = new File(Environment.getRootDirectory(), "app");
        scanDirTracedLI(systemAppDir, mDefParseFlags
                | PackageParser.PARSE_IS_SYSTEM
                | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

        // Collect all vendor packages.
        File vendorAppDir = new File("/vendor/app");
        try {
            vendorAppDir = vendorAppDir.getCanonicalFile();
        } catch (IOException e) {
            // failed to look up canonical path, continue with original one
        }
        scanDirTracedLI(vendorAppDir, mDefParseFlags
                | PackageParser.PARSE_IS_SYSTEM
                | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

        // Collect all OEM packages.
        final File oemAppDir = new File(Environment.getOemDirectory(), "app");
        scanDirTracedLI(oemAppDir, mDefParseFlags
                | PackageParser.PARSE_IS_SYSTEM
                | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

        // Prune any system packages that no longer exist.
        //構造一個List來存放不存在的packages路徑
        final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
        if (!mOnlyCore) {
            //遍歷mSettings.mPackages
            Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
            while (psit.hasNext()) {
                PackageSetting ps = psit.next();

                /*
                 * If this is not a system app, it can't be a
                 * disable system app.
                 */
                //如果不是系統app,不處理
                if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                    continue;
                }

                /*
                 * If the package is scanned, it's not erased.
                 */
                final PackageParser.Package scannedPkg = mPackages.get(ps.name);
                if (scannedPkg != null) {
                    /*
                     * If the system app is both scanned and in the
                     * disabled packages list, then it must have been
                     * added via OTA. Remove it from the currently
                     * scanned package so the previously user-installed
                     * application can be scanned.
                     */
                    //如果在disable列表中,那么,說明它是通過OTA方式進行升級更新添加的,因此,清楚相應數據
                    if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
                        logCriticalInfo(Log.WARN, "Expecting better updated system app for "
                                + ps.name + "; removing system app.  Last known codePath="
                                + ps.codePathString + ", installStatus=" + ps.installStatus
                                + ", versionCode=" + ps.versionCode + "; scanned versionCode="
                                + scannedPkg.mVersionCode);
                        //移除其信息
                        removePackageLI(scannedPkg, true);
                        mExpectingBetter.put(ps.name, ps.codePath);
                    }

                    continue;
                }
                //如果不在disable列表中,則直接清楚相應的數據
                if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
                    psit.remove();
                    logCriticalInfo(Log.WARN, "System package " + ps.name
                            + " no longer exists; it's data will be wiped");
                    // Actual deletion of code and data will be handled by later
                    // reconciliation step
                } else {
                    //否則,通過codePath判斷其是否有可能被更新或刪除
                    final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
                    if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
                        possiblyDeletedUpdatedSystemApps.add(ps.name);
                    }
                }
            }
        }

        //look for any incomplete package installations
        //獲取未完成安裝的apk包的PackageSetting列表
        ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
        //清除未安裝的安裝包
        for (int i = 0; i < deletePkgsList.size(); i++) {
            // Actual deletion of code and data will be handled by later
            // reconciliation step
            final String packageName = deletePkgsList.get(i).name;
            logCriticalInfo(Log.WARN, "Cleaning up incompletely installed app: " + packageName);
            synchronized (mPackages) {
                mSettings.removePackageLPw(packageName);
            }
        }

        //delete tmp files
        //清除臨時文件
        deleteTempPackageFiles();

        // Remove any shared userIDs that have no associated packages
        //清除在mSettings中沒有被使用的SharedUserSettings
        mSettings.pruneSharedUsersLPw();</code></pre> 

環境變量: 那可通過adb shell env來查看系統所有的環境變量及相應值。也可通過命令adb shell echo $SYSTEMSERVERCLASSPATH。

SYSTEMSERVERCLASSPATH:主要包括/system/framework目錄下services.jar,ethernet-service.jar,wifi-service.jar這3個文件。

BOOTCLASSPATH:該環境變量內容較多,不同ROM可能有所不同,常見內容包含/system/framework目錄下的framework.jar,ext.jar,core-libart.jar,telephony-common.jar,ims-common.jar,core-junit.jar等文件。

scanDirLI(): 掃描指定目錄下的apk文件,最終調用PackageParser.parseBaseApk來完成AndroidManifest.xml文件的解析,生成Application, activity,service,broadcast, provider等信息。

/vendor/overlay

/system/framework

/system/priv-app

/system/app

/vendor/priv-app

/vendor/app

/oem/app

階段3:BOOT_PROGRESS_PMS_DATA_SCAN_START

// Remove any shared userIDs that have no associated packages
//清除在mSettings中沒有被使用的SharedUserSettings
mSettings.pruneSharedUsersLPw();
//如果是普通模式,則需要進行一些額外處理
if (!mOnlyCore) {
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
            SystemClock.uptimeMillis());
    //掃描該目錄
    scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);

    scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
            | PackageParser.PARSE_FORWARD_LOCK,
            scanFlags | SCAN_REQUIRE_KNOWN, 0);

    scanDirLI(mEphemeralInstallDir, mDefParseFlags
            | PackageParser.PARSE_IS_EPHEMERAL,
            scanFlags | SCAN_REQUIRE_KNOWN, 0);

    /**
     * Remove disable package settings for any updated system
     * apps that were removed via an OTA. If they're not a
     * previously-updated app, remove them completely.
     * Otherwise, just revoke their system-level permissions.
     */
    //后面這部分代碼邏輯簡單,就是遍歷possiblyDeletedUpdatedSystemApps,處理通過OTA更新和刪除的APK文件
    for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
        PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
        mSettings.removeDisabledSystemPackageLPw(deletedAppName);

        String msg;
        if (deletedPkg == null) {
            msg = "Updated system package " + deletedAppName
                    + " no longer exists; it's data will be wiped";
            // Actual deletion of code and data will be handled by later
            // reconciliation step
        } else {
            msg = "Updated system app + " + deletedAppName
                    + " no longer present; removing system privileges for "
                    + deletedAppName;

            deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;

            PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
            deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
        }
        logCriticalInfo(Log.WARN, msg);
    }

    /**
     * Make sure all system apps that we expected to appear on
     * the userdata partition actually showed up. If they never
     * appeared, crawl back and revive the system version.
     */
    for (int i = 0; i < mExpectingBetter.size(); i++) {
        final String packageName = mExpectingBetter.keyAt(i);
        if (!mPackages.containsKey(packageName)) {
            final File scanFile = mExpectingBetter.valueAt(i);

            logCriticalInfo(Log.WARN, "Expected better " + packageName
                    + " but never showed up; reverting to system");

            int reparseFlags = mDefParseFlags;
            if (FileUtils.contains(privilegedAppDir, scanFile)) {
                reparseFlags = PackageParser.PARSE_IS_SYSTEM
                        | PackageParser.PARSE_IS_SYSTEM_DIR
                        | PackageParser.PARSE_IS_PRIVILEGED;
            } else if (FileUtils.contains(systemAppDir, scanFile)) {
                reparseFlags = PackageParser.PARSE_IS_SYSTEM
                        | PackageParser.PARSE_IS_SYSTEM_DIR;
            } else if (FileUtils.contains(vendorAppDir, scanFile)) {
                reparseFlags = PackageParser.PARSE_IS_SYSTEM
                        | PackageParser.PARSE_IS_SYSTEM_DIR;
            } else if (FileUtils.contains(oemAppDir, scanFile)) {
                reparseFlags = PackageParser.PARSE_IS_SYSTEM
                        | PackageParser.PARSE_IS_SYSTEM_DIR;
            } else {
                Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
                continue;
            }

            mSettings.enableSystemPackageLPw(packageName);

            try {
                scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 0, null);
            } catch (PackageManagerException e) {
                Slog.e(TAG, "Failed to parse original system package: "
                        + e.getMessage());
            }
        }
    }
}
mExpectingBetter.clear();

// Resolve protected action filters. Only the setup wizard is allowed to
// have a high priority filter for these actions.
mSetupWizardPackage = getSetupWizardPackageName();
if (mProtectedFilters.size() > 0) {
    if (DEBUG_FILTERS && mSetupWizardPackage == null) {
        Slog.i(TAG, "No setup wizard;"
            + " All protected intents capped to priority 0");
    }
    for (ActivityIntentInfo filter : mProtectedFilters) {
        if (filter.activity.info.packageName.equals(mSetupWizardPackage)) {
            if (DEBUG_FILTERS) {
                Slog.i(TAG, "Found setup wizard;"
                    + " allow priority " + filter.getPriority() + ";"
                    + " package: " + filter.activity.info.packageName
                    + " activity: " + filter.activity.className
                    + " priority: " + filter.getPriority());
            }
            // skip setup wizard; allow it to keep the high priority filter
            continue;
        }
        Slog.w(TAG, "Protected action; cap priority to 0;"
                + " package: " + filter.activity.info.packageName
                + " activity: " + filter.activity.className
                + " origPrio: " + filter.getPriority());
        filter.setPriority(0);
    }
}
mDeferProtectedFilters = false;
mProtectedFilters.clear();

// Now that we know all of the shared libraries, update all clients to have
// the correct library paths.
//給需要使用shared libraries的package找到相應的路徑,并將其保存至package的usesLibraryFiles中
updateAllSharedLibrariesLPw();

for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
    // NOTE: We ignore potential failures here during a system scan (like
    // the rest of the commands above) because there's precious little we
    // can do about it. A settings error is reported, though.
    adjustCpuAbisForSharedUserLPw(setting.packages, null /* scanned package */,
            false /* boot complete */);
}

// Now that we know all the packages we are keeping,
// read and update their last usage times.
mPackageUsage.readLP();

當mOnlyCore = false時,則scanDirLI()還會收集如下目錄中的apk

/data/app

/data/app-private

階段4:BOOT_PROGRESS_PMS_SCAN_END

EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
                    SystemClock.uptimeMillis());
            Slog.i(TAG, "Time to scan packages: "
                    + ((SystemClock.uptimeMillis()-startTime)/1000f)
                    + " seconds");

            // If the platform SDK has changed since the last time we booted,
            // we need to re-grant app permission to catch any new ones that
            // appear.  This is really a hack, and means that apps can in some
            // cases get permissions that the user didn't initially explicitly
            // allow...  it would be nice to have some better way to handle
            // this situation.
            int updateFlags = UPDATE_PERMISSIONS_ALL;
            if (ver.sdkVersion != mSdkVersion) {
                Slog.i(TAG, "Platform changed from " + ver.sdkVersion + " to "
                        + mSdkVersion + "; regranting permissions for internal storage");
                updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL;
            }
            //當sdk版本不一致時,,更新相關信息,并給需要使用權限的apk分配相應的權限
            updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
            ver.sdkVersion = mSdkVersion;

            // If this is the first boot or an update from pre-M, and it is a normal
            // boot, then we need to initialize the default preferred apps across
            // all defined users.
            //當這是ota后的首次啟動,正常啟動則需要清除目錄的緩存代碼
            if (!onlyCore && (mPromoteSystemApps || !mRestoredSettings)) {
                for (UserInfo user : sUserManager.getUsers(true)) {
                    mSettings.applyDefaultPreferredAppsLPw(this, user.id);
                    applyFactoryDefaultBrowserLPw(user.id);
                    primeDomainVerificationsLPw(user.id);
                }
            }

            // Prepare storage for system user really early during boot,
            // since core system apps like SettingsProvider and SystemUI
            // can't wait for user to start
            final int storageFlags;
            if (StorageManager.isFileEncryptedNativeOrEmulated()) {
                storageFlags = StorageManager.FLAG_STORAGE_DE;
            } else {
                storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
            }
            reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL, UserHandle.USER_SYSTEM,
                    storageFlags);

            // If this is first boot after an OTA, and a normal boot, then
            // we need to clear code cache directories.
            // Note that we do *not* clear the application profiles. These remain valid
            // across OTAs and are used to drive profile verification (post OTA) and
            // profile compilation (without waiting to collect a fresh set of profiles).
            if (mIsUpgrade && !onlyCore) {
                Slog.i(TAG, "Build fingerprint changed; clearing code caches");
                for (int i = 0; i < mSettings.mPackages.size(); i++) {
                    final PackageSetting ps = mSettings.mPackages.valueAt(i);
                    if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
                        // No apps are running this early, so no need to freeze
                        clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
                                StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
                                        | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
                    }
                }
                ver.fingerprint = Build.FINGERPRINT;
            }

            checkDefaultBrowser();

            // clear only after permissions and other defaults have been updated
            //當權限和其他默認項都完成更新,則清理相關信息
            mExistingSystemPackages.clear();
            mPromoteSystemApps = false;

            // All the changes are done during package scanning.
            ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;

            // can downgrade to reader
            //信息寫回packages.xml文件
            mSettings.writeLPr();

            // Perform dexopt on all apps that mark themselves as coreApps. We do this pretty
            // early on (before the package manager declares itself as early) because other
            // components in the system server might ask for package contexts for these apps.
            //
            // Note that "onlyCore" in this context means the system is encrypted or encrypting
            // (i.e, that the data partition is unavailable).
            if ((isFirstBoot() || isUpgrade() || VMRuntime.didPruneDalvikCache()) && !onlyCore) {
                long start = System.nanoTime();
                List<PackageParser.Package> coreApps = new ArrayList<>();
                for (PackageParser.Package pkg : mPackages.values()) {
                    if (pkg.coreApp) {
                        coreApps.add(pkg);
                    }
                }

                int[] stats = performDexOpt(coreApps, false,
                        getCompilerFilterForReason(REASON_CORE_APP));

                final int elapsedTimeSeconds =
                        (int) TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start);
                MetricsLogger.histogram(mContext, "opt_coreapps_time_s", elapsedTimeSeconds);

                if (DEBUG_DEXOPT) {
                    Slog.i(TAG, "Dex-opt core apps took : " + elapsedTimeSeconds + " seconds (" +
                            stats[0] + ", " + stats[1] + ", " + stats[2] + ")");
                }


                // TODO: Should we log these stats to tron too ?
                // MetricsLogger.histogram(mContext, "opt_coreapps_num_dexopted", stats[0]);
                // MetricsLogger.histogram(mContext, "opt_coreapps_num_skipped", stats[1]);
                // MetricsLogger.histogram(mContext, "opt_coreapps_num_failed", stats[2]);
                // MetricsLogger.histogram(mContext, "opt_coreapps_num_total", coreApps.size());
            }

階段5:BOOT_PROGRESS_PMS_READY

EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                    SystemClock.uptimeMillis());

            if (!mOnlyCore) {
                mRequiredVerifierPackage = getRequiredButNotReallyRequiredVerifierLPr();
                mRequiredInstallerPackage = getRequiredInstallerLPr();
                mIntentFilterVerifierComponent = getIntentFilterVerifierComponentNameLPr();
                mIntentFilterVerifier = new IntentVerifierProxy(mContext,
                        mIntentFilterVerifierComponent);
                mServicesSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
                        PackageManager.SYSTEM_SHARED_LIBRARY_SERVICES);
                mSharedSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
                        PackageManager.SYSTEM_SHARED_LIBRARY_SHARED);
            } else {
                mRequiredVerifierPackage = null;
                mRequiredInstallerPackage = null;
                mIntentFilterVerifierComponent = null;
                mIntentFilterVerifier = null;
                mServicesSystemSharedLibraryPackageName = null;
                mSharedSystemSharedLibraryPackageName = null;
            }

            mInstallerService = new PackageInstallerService(context, this);

            final ComponentName ephemeralResolverComponent = getEphemeralResolverLPr();
            final ComponentName ephemeralInstallerComponent = getEphemeralInstallerLPr();
            // both the installer and resolver must be present to enable ephemeral
            if (ephemeralInstallerComponent != null && ephemeralResolverComponent != null) {
                if (DEBUG_EPHEMERAL) {
                    Slog.i(TAG, "Ephemeral activated; resolver: " + ephemeralResolverComponent
                            + " installer:" + ephemeralInstallerComponent);
                }
                mEphemeralResolverComponent = ephemeralResolverComponent;
                mEphemeralInstallerComponent = ephemeralInstallerComponent;
                setUpEphemeralInstallerActivityLP(mEphemeralInstallerComponent);
                mEphemeralResolverConnection =
                        new EphemeralResolverConnection(mContext, mEphemeralResolverComponent);
            } else {
                if (DEBUG_EPHEMERAL) {
                    final String missingComponent =
                            (ephemeralResolverComponent == null)
                            ? (ephemeralInstallerComponent == null)
                                    ? "resolver and installer"
                                    : "resolver"
                            : "installer";
                    Slog.i(TAG, "Ephemeral deactivated; missing " + missingComponent);
                }
                mEphemeralResolverComponent = null;
                mEphemeralInstallerComponent = null;
                mEphemeralResolverConnection = null;
            }

            mEphemeralApplicationRegistry = new EphemeralApplicationRegistry(this);
        } // synchronized (mPackages)
        } // synchronized (mInstallLock)

        // Now after opening every single application zip, make sure they
        // are all flushed.  Not really needed, but keeps things nice and
        // tidy.
        Runtime.getRuntime().gc();

        // The initial scanning above does many calls into installd while
        // holding the mPackages lock, but we're mostly interested in yelling
        // once we have a booted system.
        mInstaller.setWarnIfHeld(mPackages);

        // Expose private service for system components to use.
        LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());

PKMS初始化完成階段,還會創建一個PackageInstaller服務。

public PackageInstallerService(Context context, PackageManagerService pm) {
    mContext = context;
    mPm = pm;
    //創建名為”PackageInstaller“的Handler線程
    mInstallThread = new HandlerThread(TAG);
    mInstallThread.start();

    mInstallHandler = new Handler(mInstallThread.getLooper());

    mCallbacks = new Callbacks(mInstallThread.getLooper());

    mSessionsFile = new AtomicFile(
            new File(Environment.getSystemSecureDirectory(), "install_sessions.xml"));
    mSessionsDir = new File(Environment.getSystemSecureDirectory(), "install_sessions");
    mSessionsDir.mkdirs();

    synchronized (mSessions) {
        readSessionsLocked();

        reconcileStagesLocked(StorageManager.UUID_PRIVATE_INTERNAL);

        final ArraySet<File> unclaimedIcons = newArraySet(
                mSessionsDir.listFiles());

        for (int i = 0; i < mSessions.size(); i++) {
            final PackageInstallerSession session = mSessions.valueAt(i);
            unclaimedIcons.remove(buildAppIconFile(session.sessionId));
        }

        for (File icon : unclaimedIcons) {
            icon.delete();
        }
    }
}

PKMS初始化過程,分為5個階段:

PMS_START階段:

創建Settings對象;

將6類shareUserId到mSettings;

初始化SystemConfig;

創建名為“PackageManager”的handler線程mHandlerThread;

創建UserManagerService多用戶管理服務;

通過解析4大目錄中的xmL文件構造共享mSharedLibraries;

PMS_SYSTEM_SCAN_START階段:

掃描系統apk;

PMS_DATA_SCAN_START階段:

掃描/data/app目錄下的apk;

掃描/data/app-private目錄下的apk;

PMS_SCAN_END階段:

將上述信息寫回/data/system/packages.xml;

PMS_READY階段:創建服務PackageInstallerService;

PKMS.systemReady

@Override
    public void systemReady() {
        mSystemReady = true;

        // Read the compatibilty setting when the system is ready.
        boolean compatibilityModeEnabled = android.provider.Settings.Global.getInt(
                mContext.getContentResolver(),
                android.provider.Settings.Global.COMPATIBILITY_MODE, 1) == 1;
        PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
        if (DEBUG_SETTINGS) {
            Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
        }

        int[] grantPermissionsUserIds = EMPTY_INT_ARRAY;

        synchronized (mPackages) {
            // Verify that all of the preferred activity components actually
            // exist.  It is possible for applications to be updated and at
            // that point remove a previously declared activity component that
            // had been set as a preferred activity.  We try to clean this up
            // the next time we encounter that preferred activity, but it is
            // possible for the user flow to never be able to return to that
            // situation so here we do a sanity check to make sure we haven't
            // left any junk around.
            ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
            for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
                PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
                removed.clear();
                for (PreferredActivity pa : pir.filterSet()) {
                    if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
                        removed.add(pa);
                    }
                }
                if (removed.size() > 0) {
                    for (int r=0; r<removed.size(); r++) {
                        PreferredActivity pa = removed.get(r);
                        Slog.w(TAG, "Removing dangling preferred activity: "
                                + pa.mPref.mComponent);
                        pir.removeFilter(pa);
                    }
                    mSettings.writePackageRestrictionsLPr(
                            mSettings.mPreferredActivities.keyAt(i));
                }
            }

            for (int userId : UserManagerService.getInstance().getUserIds()) {
                if (!mSettings.areDefaultRuntimePermissionsGrantedLPr(userId)) {
                    grantPermissionsUserIds = ArrayUtils.appendInt(
                            grantPermissionsUserIds, userId);
                }
            }
        }
        sUserManager.systemReady();//多用戶服務

        // If we upgraded grant all default permissions before kicking off.
        //升級所有已獲取的默認權限
        for (int userId : grantPermissionsUserIds) {
            mDefaultPermissionPolicy.grantDefaultPermissions(userId);
        }

        // Kick off any messages waiting for system ready
        //處理所有等待系統準備就緒的消息
        if (mPostSystemReadyMessages != null) {
            for (Message msg : mPostSystemReadyMessages) {
                msg.sendToTarget();
            }
            mPostSystemReadyMessages = null;
        }

        // Watch for external volumes that come and go over time
        //觀察外部存儲設備
        final StorageManager storage = mContext.getSystemService(StorageManager.class);
        storage.registerListener(mStorageListener);

        mInstallerService.systemReady();
        mPackageDexOptimizer.systemReady();

        MountServiceInternal mountServiceInternal = LocalServices.getService(
                MountServiceInternal.class);
        mountServiceInternal.addExternalStoragePolicy(
                new MountServiceInternal.ExternalStorageMountPolicy() {
            @Override
            public int getMountMode(int uid, String packageName) {
                if (Process.isIsolated(uid)) {
                    return Zygote.MOUNT_EXTERNAL_NONE;
                }
                if (checkUidPermission(WRITE_MEDIA_STORAGE, uid) == PERMISSION_GRANTED) {
                    return Zygote.MOUNT_EXTERNAL_DEFAULT;
                }
                if (checkUidPermission(READ_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) {
                    return Zygote.MOUNT_EXTERNAL_DEFAULT;
                }
                if (checkUidPermission(WRITE_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) {
                    return Zygote.MOUNT_EXTERNAL_READ;
                }
                return Zygote.MOUNT_EXTERNAL_WRITE;
            }

            @Override
            public boolean hasExternalStorage(int uid, String packageName) {
                return true;
            }
        });

        // Now that we're mostly running, clean up stale users and apps
        reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);
        reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL);
    }

至此,PackageManagerService啟動流程分析完畢,如有錯誤之處,歡迎留言指正。

 

來自:http://blog.csdn.net/u012124438/article/details/54882771

 

 本文由用戶 weizhenggen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!