浅谈PackageManagerService启动流程以及安装app流程

1,296 阅读3分钟

本文源码都是android29,10.0 代码

一 概述

PackageManagerService 也是一个比较核心的系统服务,他管理着apk安装,卸载,以及信息查询和权限管理等等。管理着跟 package 相关的,主要功能有:

  • 解析AndroidNanifest.xml清单文件
  • 扫描.apk文件,安装系统应用,安装本地应用等
  • 管理本地应用,主要有, 安装,卸载,应用信息查询(比如权限) 等

二 启动

在系统启动,也就是开机的时候。在SystemServer启动,也就是SystemServer的main方法中调用startBootstrapServices中,启动了PackageManagerService的main方法,

private void startBootstrapServices() {
	//省略代码
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
}
private void startOtherServices() {
   //省略代码
   
   //dex 优化
   mPackageManagerService.updatePackagesIfNeeded();
   //磁盘维护
   mPackageManagerService.performFstrimIfNeeded();
   // 当准备好之后,需要处理的东西,比如处理所有等待系统准备就绪的消息
   mPackageManagerService.systemReady();
}

三 启动总结

  1. 通过Zygote分裂出来的SystemServer进程,初始化的时候创建了PMS
  2. 扫描pacages.xml,就想window的注册表似的,里面有包名,权限等等信息,随着apk的卸载和安装,都会更新里面的东西
  3. 扫描所有的apk,system/app (系统),data/app(用户),用户装的程序越多,扫描时间越长,开机一般耗费这里了(还有就是在SystemServer中启动各种各样的服务)。PackageParser解析APK文件中的AndroidManifest.xml 保存下来,手机桌面就是从这里拿到数据

安装apk

  1. 当我们点击一个apk的时候其实打开了packages/app/PackageInstaller.PackageInstallerActivity
  2. 然后当我们点击确定的时候,打开 InstallAppProgress 这个Activity,也就是转菊花的页面, , 注册了PackageInstallObserver监听安装完成的回调,之后调用到PackageInstallerService,
  3. 拷贝apk到data/app下面,之后才开始正式安装
  4. 解析apk信息,将apk的权限、应用包名,创建data/data/包名下的路径,so库的lib,file,cache,数据库等文件夹,更新Settings信息,里面有packages.xml,类似于注册表的东西
  5. 当app安装完成 给laucher发送一个广播Intent.ACTION_PACKAGE_ADDED,完成

PackageManagerService的main

main()方法的作用:

  • 检查系统属性
  • 初始化 PackageManagerService
  • 初始化部分应用服务,主要用于多用户场景
  • 将 package 服务注册到 ServiceManager
  • 将 package_native 服务注册到 ServiceManager, 主要是给native代码调用的
public static PackageManagerService main(Context context, Installer installer,
        boolean factoryTest, boolean onlyCore) {
    // 检查系统属性
    PackageManagerServiceCompilerMapping.checkProperties();

	//初始化 PackageManagerService
    PackageManagerService m = new PackageManagerService(context, installer,
            factoryTest, onlyCore);
    //启用部分应用服务于多用户场景       
    m.enableSystemUserPackages();
    //将 package 服务注册到 ServiceManager
    ServiceManager.addService("package", m);
    final PackageManagerNative pmn = m.new PackageManagerNative();
     //将 package_native 服务注册到 ServiceManager,  主要是给native代码调用的
    ServiceManager.addService("package_native", pmn);
    return m;
}

PackageManagerService构造函数

中间我会省略不必要的代码

public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
    //屏幕的宽高,分辨率等信息           
    mMetrics = new DisplayMetrics();
    //installer对象,在SystemServer里面初始化的,apk的安装和卸载最终都是调用installd来实现的
    mInstaller = installer;   
    synchronized (mInstallLock) {
    synchronized (mPackages) {
        // Expose private service for system components to use.
        LocalServices.addService(
                PackageManagerInternal.class, new PackageManagerInternalImpl());
        //UserManager是Andorid 4.0新增的一个功能,也就是一个手机可以有多个用户,有多个配置,
        //至今好像也没发现他的应用落地
        sUserManager = new UserManagerService(context, this,
                new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
        // 解析 activities, services, providers and receivers
        mComponentResolver = new ComponentResolver(sUserManager,
                LocalServices.getService(PackageManagerInternal.class),
                mPackages);
         //权限管理
        mPermissionManager = PermissionManagerService.create(context,
                mPackages /*externalLock*/);
        mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();
        //创建Settings 对象,里面有很多重要的文件管理 比如packages.xml 和 packages.list
        mSettings = new Settings(Environment.getDataDirectory(),
                mPermissionManager.getPermissionSettings(), mPackages);
         
        // dex 的优化
       mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
                "*dexopt*");
        // dex 管理
        mDexManager = new DexManager(mContext, this, mPackageDexOptimizer, installer, mInstallLock);
        //ART虚拟机管理
        mArtManagerService = new ArtManagerService(mContext, this, installer, mInstallLock);
        
        // Permission 监听器
      mOnPermissionChangeListeners = new OnPermissionChangeListeners(
                FgThread.get().getLooper());

		// 得到默认的DisplayMetrics
        getDefaultDisplayMetrics(context, mMetrics);
		//
        SystemConfig systemConfig = SystemConfig.getInstance();
        
        synchronized (mPackages) {
        	// PMS中的线程,轮训,app的安装与卸载
            mHandlerThread = new ServiceThread(TAG,
                    Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
            mHandlerThread.start();
            mHandler = new PackageHandler(mHandlerThread.getLooper());
            mProcessLoggingHandler = new ProcessLoggingHandler();
            Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
            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);
            }

            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);
                    }
                }
            }

            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文件 
            // packages.xml 和 packages-backup.xml 包信息,以及权限当系统进行程序安装、
            //   卸载和更新等操作时,均会更新该文件。该文件保存了系统中与 package 相关的一些信息
            //   相当于注册表似的
            // packages.list 
            // packages-stopped.xml 和 packages-stopped-backup.xml
            mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
           //.....

			//准备解析 Package 
            mCacheDir = preparePackageParserCache();

            // Set flag to monitor and not change apk file paths when
            // scanning install directories.
            int scanFlags = SCAN_BOOTING | SCAN_INITIAL;

            if (mIsUpgrade || mFirstBoot) {
                scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
            }
			// 下面都是扫描对应目录下的包 ,解析成PackageParser实例类
			//扫描/vendor/overlay下的apk
            scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_VENDOR,
                    0);
            scanDirTracedLI(new File(PRODUCT_OVERLAY_DIR),
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_PRODUCT,
                    0);
            scanDirTracedLI(new File(PRODUCT_SERVICES_OVERLAY_DIR),
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_PRODUCT_SERVICES,
                    0);
            scanDirTracedLI(new File(ODM_OVERLAY_DIR),
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_ODM,
                    0);
            scanDirTracedLI(new File(OEM_OVERLAY_DIR),
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_OEM,
                    0);

            mParallelPackageParserCallback.findStaticOverlayPackages();

            // Find base frameworks (resource packages without code).
            scanDirTracedLI(frameworkDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_NO_DEX
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_PRIVILEGED,
                    0);
            if (!mPackages.containsKey("android")) {
                throw new IllegalStateException(
                        "Failed to load frameworks package; check log for warnings");
            }

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

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

            // Collect privileged vendor packages.
            File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
            try {
                privilegedVendorAppDir = privilegedVendorAppDir.getCanonicalFile();
            } catch (IOException e) {
                // failed to look up canonical path, continue with original one
            }
            scanDirTracedLI(privilegedVendorAppDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_VENDOR
                    | SCAN_AS_PRIVILEGED,
                    0);

            // Collect ordinary vendor packages.
            File vendorAppDir = new File(Environment.getVendorDirectory(), "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_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_VENDOR,
                    0);

            // Collect privileged odm packages. /odm is another vendor partition
            // other than /vendor.
            File privilegedOdmAppDir = new File(Environment.getOdmDirectory(),
                        "priv-app");
            try {
                privilegedOdmAppDir = privilegedOdmAppDir.getCanonicalFile();
            } catch (IOException e) {
                // failed to look up canonical path, continue with original one
            }
            scanDirTracedLI(privilegedOdmAppDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_VENDOR
                    | SCAN_AS_PRIVILEGED,
                    0);

            // Collect ordinary odm packages. /odm is another vendor partition
            // other than /vendor.
            File odmAppDir = new File(Environment.getOdmDirectory(), "app");
            try {
                odmAppDir = odmAppDir.getCanonicalFile();
            } catch (IOException e) {
                // failed to look up canonical path, continue with original one
            }
            scanDirTracedLI(odmAppDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_VENDOR,
                    0);

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

            // Collected privileged /product packages.
            File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
            try {
                privilegedProductAppDir = privilegedProductAppDir.getCanonicalFile();
            } catch (IOException e) {
                // failed to look up canonical path, continue with original one
            }
            scanDirTracedLI(privilegedProductAppDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_PRODUCT
                    | SCAN_AS_PRIVILEGED,
                    0);

            // Collect ordinary /product packages.
            File productAppDir = new File(Environment.getProductDirectory(), "app");
            try {
                productAppDir = productAppDir.getCanonicalFile();
            } catch (IOException e) {
                // failed to look up canonical path, continue with original one
            }
            scanDirTracedLI(productAppDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_PRODUCT,
                    0);

           // 后面整不动了
          
    
 }

参考

深入理解android卷2
Android 10.0 PackageManagerService(一)工作原理及启动流程-[Android取经之路]