Android PackageManagerService总结(二) PKMS启动过程

一. 概述

        PackageManagerService(简称PKMS),是Android系统中核心服务之一,管理着所有与package相关的工作,常见的比如安装、卸载应用, 信息查询等工作, 主要完成以下核心功能

1. 解析AndroidManifest.xml清单文件,解析清单文件中的所有节点信息

2. 扫描本地文件,主要针对apk,主要是系统应用、本地安装应用等。

3. 管理本地apk,主要包括安装、删除等等

4. 管理设备上安装的所有应用程序,并在系统启动时加载应用程序

5. 根据请求的Intent匹配到对应的Activity、Provider、Service,提供包含包名和Component的信息对象

6. 调用需要权限的系统函数时,检查程序是否具备相应权限从而保证系统安全

7. 提供应用程序的安装、卸载的接口

二. PKMS启动过程

        在Android系统启动过程中,程序会执行到SystemServer中,然后调用startBootstrapServices()方法启动核心服务,在startBootstrapServices()方法中完成PMS的启动:

private void startBootstrapServices() {
....
    //注释1
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    //注释2
    mPackageManager = mSystemContext.getPackageManager();
.....
}

注释1处:调用PackageManagerService.main()方法,在main()方法中创建PMS的对象,并向
ServiceManager注册Binder     

接下来看一下PKMS的main方法:

  public static PackageManagerService main(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
        // Self-check for initial settings.
        PackageManagerServiceCompilerMapping.checkProperties();
        // 1、创建PMS对象
        PackageManagerService m = new PackageManagerServiceEx(context, installer,
                factoryTest, onlyCore);
        m.enableSystemUserPackages();
        // 2、注册PMS对象到ServiceManager中
        ServiceManager.addService("package", m);
        //3、 创建 PMN对象
        final PackageManagerNative pmn = m.new PackageManagerNative();
        //4、注册PMN对象
        ServiceManager.addService("package_native", pmn);
        return m;
    }

注释2处: 初始化PackageManager对象.

通过调用ContextImpl.getPackageManager()获取PackageManager对象

@Override
    public PackageManager getPackageManager() {
        if (mPackageManager != null) {
            return mPackageManager;
        }

        IPackageManager pm = ActivityThread.getPackageManager();
        if (pm != null) {
            // Doesn't matter if we make more than one instance.
            return (mPackageManager = new ApplicationPackageManager(this, pm));
        }

        return null;
    }

getPackageManager方法中使用ActivityThread.getPackageManager()获取前面创建并注册的Binder对象,然后创建ApplicationPackageManager实例

frameworks/base/core/java/android/app/ActivityThread.java

 @UnsupportedAppUsage
    public static IPackageManager getPackageManager() {
        if (sPackageManager != null) {
            return sPackageManager;
        }
         // 获取注册Binder
        IBinder b = ServiceManager.getService("package");
        // sPackageManager就是服务端PKMS的代理proxy对象
        sPackageManager = IPackageManager.Stub.asInterface(b);
        return sPackageManager;
    }

上面的这段代码, sPackageManager 就是服务端PKMS的 代理proxy对象, 客户端拿到sPackageManager这个代理对象,就可以跨进程调用PKMS中的方法了.

先来小结一下, 从上面的3个过程可以得出以下结论:

1. PMS使用Binder通信机制,最终IPackageManager接口的实现类为PackageManagerService类 

2. 系统中获取的PackageManager对象具体实现的子类是ApplicationPackageManager对象

类图:

PKMS初始化时的核心部分为PackageManagerService()构造函数的内容,我们下面就来分析该流程

public static PackageManagerService main(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
        // Self-check for initial settings.
        //检查Package编译相关系统属性
        PackageManagerServiceCompilerMapping.checkProperties();
        // 调用PackageManagerService构造方法,
        PackageManagerService m = new PackageManagerServiceEx(context, installer,
                factoryTest, onlyCore);
        //启用部分应用服务于多用户场景
        m.enableSystemUserPackages(); 
        //往ServiceManager中注册”package”和”package_native”。
        ServiceManager.addService("package", m);
        final PackageManagerNative pmn = m.new PackageManagerNative();
        ServiceManager.addService("package_native", pmn);
        return m;
    }

三. PKMS 构造函数分析

PKMS的构造方法代码比较长, 我们通过EventLog(事件日志)的打印,可以分为5个过程

1. BOOT_PROGRESS_PMS_START(开始阶段)
2. BOOT_PROGRESS_PMS_SYSTEM_SCAN_START(扫描系统阶段)
3. BOOT_PROGRESS_PMS_DATA_SCAN_START(扫描Data分区阶段)
4. BOOT_PROGRESS_PMS_SCAN_END(扫描结束阶段)
5. BOOT_PROGRESS_PMS_READY(准备阶段)

3.1  BOOT_PROGRESS_PMS_START 开始阶段

    public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
        LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES);
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "create package manager");
        //第一阶段BOOT_PROGRESS_PMS_START 开始
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
                SystemClock.uptimeMillis());

        if (mSdkVersion <= 0) {
            Slog.w(TAG, "**** ro.build.version.sdk not set!");
        }

        mContext = context;
        // 一般为false,即非工厂生产模式
        mFactoryTest = factoryTest;
        mOnlyCore = onlyCore; //标记是否只加载核心服务
        //1. 构造 DisplayMetrics ,保存分辨率等相关信息
        mMetrics = new DisplayMetrics();
        //2. 创建Installer对象,与installd交互;
        mInstaller = installer;

        // Create sub-components that provide services / data. Order here is important.
        //创建提供服务/数据的子组件。这里的顺序很重要,使用到了两个重要的同步锁
        synchronized (mInstallLock) {
        synchronized (mPackages) {
            // Expose private service for system components to use.
            // 公开系统组件使用的私有服务
            // 本地服务
            LocalServices.addService(
                    PackageManagerInternal.class, new PackageManagerInternalImpl());
            // 多用户管理服务
            sUserManager = new UserManagerService(context, this,
                    new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
            //解析所有Android组件类型对象[activities, services, providers and receivers]
            mComponentResolver = new ComponentResolver(sUserManager,
                    LocalServices.getService(PackageManagerInternal.class),
                    mPackages);
            //3. 创建mPermissionManager对象,进行权限管理;
            mPermissionManager = PermissionManagerService.create(context,
                    mPackages /*externalLock*/);
            mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();
            //创建Settings对象
            //构造Settings类,保存安装包信息,清除路径不存在的孤立应用,
            // 主要涉及 /data/system/目录的packages.xml,packages-backup.xml, packages.list, packages-stopped.xml,packages-stopped-backup.xml等文件。
            mSettings = new Settings(Environment.getDataDirectory(),
                    mPermissionManager.getPermissionSettings(), mPackages);
        }
        }
        // 添加system, phone, log, nfc, bluetooth, shell,se,networkstack 这8种 shareUserId 到 mSettings;
        mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.se", SE_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.networkstack", NETWORKSTACK_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;
        }
        //5. 构造PackageDexOptimizer及DexManager类,处理dex优化
        //DexOpt优化
        mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
                "*dexopt*");
        mDexManager = new DexManager(mContext, this, mPackageDexOptimizer, installer, mInstallLock);
        // ART虚拟机管理服务
        mArtManagerService = new ArtManagerService(mContext, this, installer, mInstallLock);
        mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());

        mViewCompiler = new ViewCompiler(mInstallLock, mInstaller);
        //权限变化监听器
        mOnPermissionChangeListeners = new OnPermissionChangeListeners(
                FgThread.get().getLooper());
        // 获取默认分辨率
        getDefaultDisplayMetrics(context, mMetrics);

        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "get system config");
        //6.创建SystemConfig实例,获取系统配置信息,配置共享lib库;
        // 拿到SystemConfig()的对象,其中会调用SystemConfig的readPermissions()完成权限的读取
        SystemConfig systemConfig = SystemConfig.getInstance();
        //获取该设备支持的功能,这些功能是从系统配置文件中读取的
        mAvailableFeatures = systemConfig.getAvailableFeatures();
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

        mProtectedPackages = new ProtectedPackages(mContext);

        mApexManager = new ApexManager(context);


            //启动"PackageManager"线程,负责apk的安装、卸载, 用HanderThread来实现
            mHandlerThread = new ServiceThread(TAG,
                    Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
            mHandlerThread.start();
            // 应用handler  PackageHandler是PKMS中的内部类
            mHandler = new PackageHandler(mHandlerThread.getLooper());
            // 进程记录handler
            mProcessLoggingHandler = new ProcessLoggingHandler();
            //Watchdog监听ServiceThread是否超时:10分钟
            Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
            // Instant应用注册
            mInstantAppRegistry = new InstantAppRegistry(this);
            // 共享lib库配置
            ArrayMap<String, SystemConfig.SharedLibraryEntry> libConfig
                    = systemConfig.getSharedLibraries();
            final int builtInLibCount = libConfig.size();
            for (int i = 0; i < builtInLibCount; i++) {
                String name = libConfig.keyAt(i);
                SystemConfig.SharedLibraryEntry entry = libConfig.valueAt(i);
                addBuiltInSharedLibraryLocked(entry.filename, name);
            }

            // Now that we have added all the libraries, iterate again to add dependency
            // information IFF their dependencies are added.
            long undefinedVersion = SharedLibraryInfo.VERSION_UNDEFINED;
            for (int i = 0; i < builtInLibCount; i++) {
                String name = libConfig.keyAt(i);
                SystemConfig.SharedLibraryEntry entry = libConfig.valueAt(i);
                final int dependencyCount = entry.dependencies.length;
                for (int j = 0; j < dependencyCount; j++) {
                    final SharedLibraryInfo dependency =
                        getSharedLibraryInfoLPr(entry.dependencies[j], undefinedVersion);
                    if (dependency != null) {
                        getSharedLibraryInfoLPr(name, undefinedVersion).addDependency(dependency);
                    }
                }
            }
            // 读取安装相关SELinux策略
            SELinuxMMAC.readInstallPolicy();

            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "loadFallbacks");
            // 返回栈加载
            FallbackCategoryProvider.loadFallbacks();
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "read user settings");
            //读取并解析/data/system下的XML文件
            //[这段代码 等下下面会分析]
            mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

            // Clean up orphaned packages for which the code path doesn't exist
            // and they are an update to a system app - caused by bug/32321269
            // 清理代码路径不存在的孤立软件包
            final int packageSettingCount = mSettings.mPackages.size();
            for (int i = packageSettingCount - 1; i >= 0; i--) {
                PackageSetting ps = mSettings.mPackages.valueAt(i);
                if (!isExternal(ps) && (ps.codePath == null || !ps.codePath.exists())
                        && mSettings.getDisabledSystemPkgLPr(ps.name) != null) {
                    mSettings.mPackages.removeAt(i);
                    mSettings.enableSystemPackageLPw(ps.name);
                }
            }
           // 如果不是首次启动,也不是CORE应用,则拷贝预编译的DEX文件
            if (!mOnlyCore && mFirstBoot) {
                requestCopyPreoptedFiles();
            }

.....
.....
//好了到这里第一阶段就分析完了

注释1处, PKMS的构造函数中由两个重要的锁(mInstallLock、mPackages)
mInstallLock :用来保护所有安装apk的访问权限,此操作通常涉及繁重的磁盘数据读写等操作,并且是单线程操作,故有时候会处理很慢.

mPackages:  用来解析内存中所有apk的package信息及相关状态。

重点看看 mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false)) 这句代码

mSettings.readLPw

readLPw()会扫描下面5个文件 
1. "/data/system/packages.xml" 所有安装app信息 
2. "/data/system/packages-backup.xml" 所有安装app信息之备份的信息记录 
3. "/data/system/packages.list" 所有安装app信息 
4. "/data/system/packages-stopped.xml" 所有强制停止app信息 
5. "/data/system/packages-stopped-backup.xml" 所有强制停止app信息之备份的信息记录

5个文件共分为三组,简单的作用描述如下: 
packages.xml:PKMS扫描完目标文件夹后会创建该文件。当系统进行程序安装、卸载和更新等操作时,均会更新该文件。该文件保存了系统中与package 相关的一些信息。


packages.list:描述系统中存在的所有APK的信息。当这些程序有变动时,PKMS就会更新该文件。

packages-stopped.xml:从系统自带的设置程序中进入应用程序页面,然后在选择强制停止 (ForceStop)某个应用时,系统会将该应用的相关信息记录到此文件中。也就是该文件保存系统中被用户强制停止的Package的信息。

这些目录的指向,都是在Settings中的构造函数完成;

 Settings(File dataDir, PermissionSettings permission,
            Object lock) {
        mLock = lock;
        mPermissions = permission;
        mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);
        //mSystemDir指向目录"/data/system"
        mSystemDir = new File(dataDir, "system");
        //创建 "/data/system"
        mSystemDir.mkdirs();
        //设置权限
        FileUtils.setPermissions(mSystemDir.toString(),
                FileUtils.S_IRWXU|FileUtils.S_IRWXG
                |FileUtils.S_IROTH|FileUtils.S_IXOTH,
                -1, -1);
        //(1)指向目录"/data/system/packages.xml"
        mSettingsFilename = new File(mSystemDir, "packages.xml");
        //(2)指向目录"/data/system/packages-backup.xml
        mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
        //(3)指向目录"/data/system/packages.list"
        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
        //(4)指向目录"/data/system/packages-stopped.xml"
        mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
        //(5) 指 向 目 录 "/data/system/packages-stopped-backup.xml"
        mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
    }

好了,到这里 第一阶段的代码分析完成, 我们接下来分析第二阶段

3.2 BOOT_PROGRESS_PMS_SYSTEM_SCAN_START 扫描系统阶段

还在直接在源码中注释

 public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
......
 //第二阶段,扫描系统阶段
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
                    startTime);
            // 从init.rc中获取环境变量BOOTCLASSPATH和 SYSTEMSERVERCLASSPATH;
            //获取环境变量,init.rc
            final String bootClassPath = System.getenv("BOOTCLASSPATH");
            final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");

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

            if (systemServerClassPath == null) {
                Slog.w(TAG, "No SYSTEMSERVERCLASSPATH found!");
            }
            // 获取system/framework目录
            File frameworkDir = new File(Environment.getRootDirectory(), "framework");
            // 获取内部版本
            final VersionInfo ver = mSettings.getInternalVersion();
            // 判断fingerprint是否有更新
            mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
            if (mIsUpgrade) {
                logCriticalInfo(Log.INFO,
                        "Upgrading from " + ver.fingerprint + " to " + Build.FINGERPRINT);
            }

            // when upgrading from pre-M, promote system app permissions from install to runtime
        //对于旧版本升级的情况,将安装时获取权限变更为运行时申请权限;
        // 对于Android M之前版本升级上来的情况,需将系统应用程序权限从安装升级到运行时
            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.
        // 对于Android N之前版本升级上来的情况,需像首次启动一样处理package
            mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;

            mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;
            mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q;

            int preUpgradeSdkVersion = ver.sdkVersion;

            // 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
        // 在扫描之前保存预先存在的系统package的名称,不希望自动为新系统应用授予运行时权限
            if (mPromoteSystemApps) {
                Iterator<PackageSetting> pkgSettingIter = mSettings.mPackages.values().iterator();
                while (pkgSettingIter.hasNext()) {
                    PackageSetting ps = pkgSettingIter.next();
                    if (isSystemApp(ps)) {
                        mExistingSystemPackages.add(ps.name);
                    }
                }
            }
            // 准备解析package的缓存
            mCacheDir = preparePackageParserCache();

            // Set flag to monitor and not change apk file paths when
            // scanning install directories.
            // 设置flag,而不在扫描安装时更改文件路径
            int scanFlags = SCAN_BOOTING | SCAN_INITIAL;

            if (mIsUpgrade || mFirstBoot) {
                scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
            }

            // Collect vendor/product/product_services overlay packages. (Do this before scanning
            // any apps.)
            // For security and version matching reason, only consider overlay packages if they
            // reside in the right directory.

        //扫描以下路径:
        // /vendor/overlay、/product/overlay、/product_services/overlay、/odm/overlay、/oem/ overlay、
        // /system/framework /system/priv-app、/system/app、/vendor/priv- app、
        // /vendor/app、/odm/priv-app、/odm/app、/oem/app、/oem/priv-app、 /product/priv-app、
        // /product/app、/product_services/priv- app、 /product_services/app、/product_services/priv-app
            scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_VENDOR,
                    0);

..... //省略相同的scanDirTracedLI方法


            //delete tmp files
            //(4)清除安装时临时文件以及其他不必要的信息。
            deleteTempPackageFiles();

            final int cachedSystemApps = PackageParser.sCachedPackageReadCount.get();

            // Remove any shared userIDs that have no associated packages
            //删除没有关联应用的共享UID标识
            mSettings.pruneSharedUsersLPw();

...
...
//好了,到这里第二扫描系统阶段分析完成
}

第二阶段的工作内容:

1 从init.rc中获取环境变量BOOTCLASSPATH和SYSTEMSERVERCLASSPATH; 
2 对于旧版本升级的情况,将安装时获取权限变更为运行时申请权限; 
3 扫描system/vendor/product/odm/oem等目录的priv-app、app、overlay包;
4 清除安装时临时文件以及其他不必要的信息。

3.3 BOOT_PROGRESS_PMS_DATA_SCAN_START(扫描Data分区阶段)

对于不仅仅解析核心应用的情况下,还处理data目录的应用信息,及时更新, 去除不必要的数据。

 public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
.....
 //对于不仅仅解析核心应用的情况下,还处理data目录的应用信息,及时更新,去除不必要的数据。
            if (!mOnlyCore) {
                //第三阶段 开始扫描data分区
                EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                        SystemClock.uptimeMillis());

 // 如果更新不再存在,则完全删除该应用。否则,撤消其系统权限
                for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) {
                    final String packageName = possiblyDeletedUpdatedSystemApps.get(i);
                    final PackageParser.Package pkg = mPackages.get(packageName);
                    final String msg;
....

              try {
                            //扫描apk
                            scanPackageTracedLI(scanFile, reparseFlags, rescanFlags, 0, null);
                        } catch (PackageManagerException e) {
                            Slog.e(TAG, "Failed to parse original system package: "
                                    + e.getMessage());
                        }

 ....
    }

 // Uncompress and install any stubbed system applications.
                // This must be done last to ensure all stubs are replaced or disabled.
                // 解压缩并安装任何存根系统应用程序。必须最后执行此操作以确保替换或禁用所有存根
                installSystemStubPackages(stubSystemApps, scanFlags);


     // Resolve the storage manager.
            // 获取storage manager包名
            mStorageManagerPackage = getStorageManagerPackageName();

// 解决受保护的action过滤器。只允许setup wizard(开机向导)为这些action 设置高优先级过滤器
            mSetupWizardPackage = getSetupWizardPackageName();


                // 更新客户端以确保持有正确的共享库路径
            updateAllSharedLibrariesLocked(null, Collections.unmodifiableMap(mPackages));



            // Now that we know all the packages we are keeping,
            // read and update their last usage times.
        // 读取并更新要保留的package的上次使用时间
            mPackageUsage.read(mPackages);
            mCompilerStats.read();


....//到这里第三  扫描data分区阶段完毕

}

再来总结一下:

/data可以称为Data分区,它用来存储所有用户的个人数据和配置文件。下面列出Data分区部分子目录:

目录    含义
app   存储用户自己安装的App
data  存储所有已安装的App数据的目录,每个App都有自己单独的子目录
app-private App的私有存储空间
app-lib   存储所有App的Jni库
system  存放系统配置文件
anr   用于存储ANR发生时系统生成的traces.txt文件

第三扫描Data分区阶段主要做了以下几件事:

扫描/data/app和/data/app-private目录下的文件。
遍历possiblyDeletedUpdatedSystemApps列表,如果这个系统App的包信息不在PMS的变量mPackages中,说明是残留的App信息,后续会删除它的数据。如果这个系统App的包信息在mPackages中,说明是存在于Data分区,不属于系统App,那么移除其系统权限。

3.4 BOOT_PROGRESS_PMS_SCAN_END 扫描结束阶段

 public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
.....

            //第四阶段 扫描结束阶段
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
                    SystemClock.uptimeMillis());
....
       // 如果这是第一次启动或来自Android M之前的版本的升级,并且它是正常启动,
        // 那需要在所有已定义的用户中初始化默认的首选应用程序
            if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) {
                for (UserInfo user : sUserManager.getUsers(true)) {
                    mSettings.applyDefaultPreferredAppsLPw(user.id);
                    primeDomainVerificationsLPw(user.id);
                }
            }

// 在启动期间确实为系统用户准备存储,因为像SettingsProvider和SystemUI这样的核心系统应用程序无法等待用户启动
            final int storageFlags;
            if (StorageManager.isFileEncryptedNativeOrEmulated()) {
                storageFlags = StorageManager.FLAG_STORAGE_DE;
            } else {
                storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
            }

....
 // 如果是在OTA之后首次启动,并且正常启动,那需要清除代码缓存目录,但不清除应用程序配置文件
            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,
                                FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
                                        | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
                    }
                }
                ver.fingerprint = Build.FINGERPRINT;
            }
....
  //安装Android-Q前的非系统应用程序在Launcher中隐藏他们的图标
            if (!onlyCore && mIsPreQUpgrade) {
                Slog.i(TAG, "Whitelisting all existing apps to hide their icons");
                int size = mSettings.mPackages.size();
                for (int i = 0; i < size; i++) {
                    final PackageSetting ps = mSettings.mPackages.valueAt(i);
                    if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                        continue;
                    }
                    ps.disableComponentLPw(PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME,
                            UserHandle.USER_SYSTEM);
                }
            }

            // 仅在权限或其它默认配置更新后清除
            mExistingSystemPackages.clear();
            mPromoteSystemApps = false;

            // All the changes are done during package scanning.
            //所有变更均在扫描过程中完成
            ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;

            // can downgrade to reader
            //把Settings的内容保存到packages.xml中
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "write settings");
            mSettings.writeLPr();
....
// 好了,第四阶段的源码分析完毕

}

第4阶段主要工作:
1. sdk版本变更,更新权限;
2. OTA升级后首次启动,清除不必要的缓存数据;
3. 权限等默认项更新完后,清理相关数据;
4. 把Settings的内容保存到packages.xml中,这样此后PMS再次创建时会读到此前保存的Settings的内容。

3.5 BOOT_PROGRESS_PMS_READY 准备阶段

public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
.....
     //第五  准备阶段
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                    SystemClock.uptimeMillis());

....
    //创建PackageInstallerService对象
    mInstallerService = new PackageInstallerService(context, this, mApexManager);
...



   // 打开应用之后,及时回收处理
        Runtime.getRuntime().gc();    

.....//第5阶段完毕

}

第五阶段主要工作有:

1. 创建PackageInstallerService对象, PackageInstallerService是用于管理安装会话的服务,它会为每次安装过程分配一个SessionId
2. GC回收内存

四. 总结

        本文大体内容分为 PKMS启动过程 和  PKMS构造方法分析, PKMS得构造方法中分为5个阶段:开始阶段, 扫描系统,扫描data分区,扫描介绍和准备阶段, 只是梳理了一下主线流程, 每个方法的细节没有一一再分析,  工作中再定位问题的时候可以再去细跟每个方法的逻辑. 后续有新理解加入本文中来.

五. 待更新

有新的理解会更新到这里

        

猜你喜欢

转载自blog.csdn.net/u012514113/article/details/129714268