前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PackageManagerService启动流程源码解析

PackageManagerService启动流程源码解析

作者头像
老马的编程之旅
发布2022-06-22 10:41:01
1.1K0
发布2022-06-22 10:41:01
举报
文章被收录于专栏:深入理解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代码如下:

代码语言:javascript
复制
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();
    ...
}

PackageManagerService与其他所有的服务一样,也是由SystemServer启动,它也是java层服务之一,PKMS.main()过程主要是创建PKMS服务,并注册到ServiceManager。

整个system_server进程启动过程,涉及PKMS服务的主要几个动作如下,接下来分别讲解每个过程 PKMS.main() PKMS.performBootDexOpt PKMS.systemReady

PKMS.main()

代码语言:javascript
复制
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有两部分组成,由无需加锁的前部分和同时持有两个锁的后半部分,先来说说前半部分: 前半部分

代码语言:javascript
复制
//向事件日志写入事件,标识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();

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

代码语言:javascript
复制
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);
    }
    ................
}

这个过程涉及的几个重要变量:

这里写图片描述
这里写图片描述

创建Settings

在阶段1中创建了Settings对象,我们看看里面做了什么

代码语言:javascript
复制
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");
}

此处mSystemDir是指目录/data/system,在该目录有以下5个文件:

这里写图片描述
这里写图片描述

SystemConfig 阶段1中还调用SystemConfig.getInstance()方法来获取SystemConfig

代码语言:javascript
复制
public static SystemConfig getInstance() {
    synchronized (SystemConfig.class) {
        if (sInstance == null) {
            sInstance = new SystemConfig();
        }
        return sInstance;
    }
}
代码语言:javascript
复制
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

代码语言:javascript
复制
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);
    }
}

该方法是解析指定目录下所有的具有可读权限的,且以xml后缀文件。

阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START

代码语言:javascript
复制
 //标记扫描开始的时间
            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();

环境变量: 那可通过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

代码语言:javascript
复制
// 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

代码语言:javascript
复制
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

代码语言:javascript
复制
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服务。

代码语言:javascript
复制
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

代码语言:javascript
复制
@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启动流程分析完毕,如有错误之处,欢迎留言指正。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-02-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • PackageManagerService的启动
  • PKMS.main()
  • 阶段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
  • PKMS.systemReady
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档