从APK安装过程来认识PMS

Posted 丶笑看退场

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从APK安装过程来认识PMS相关的知识,希望对你有一定的参考价值。

在涉及到一个包的安装过程的时候,往往都绕不开PackageManagerService,它是android系统中最常用的服务之一。主要负责系统中Package的管理,应用程序的安装、卸载、信息查询等工作。

开始前想先了解下什么是PMS(Android 11):

一、 PMS的启动过程

PMS也是在systemServer中创建的,涉及到PMS的创建部分:

//SystemServer

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) 
        ......
  
          //创建PMS对象
 try 
            Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain");
            mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
         finally 
            Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");
        
  
    	//PMS是不是首次启动	
  mFirstBoot = mPackageManagerService.isFirstBoot();
  mPackageManager = mSystemContext.getPackageManager();

  
  private void startOtherServices(@NonNull TimingsTraceAndSlog t) 
    ......
     //完成dex优化
  mPackageManagerService.updatePackagesIfNeeded();
  //完成磁盘维护
  mPackageManagerService.performFstrimIfNeeded();
  //通知系统进入就绪状态
  mPackageManagerService.systemReady();
  

在这个启动过程中,PMS的main函数是整个的核心,现在我们就继续进行分析:

public static PackageManagerService main(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) 
  
  //对PMS对象
  PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest);
        t.traceEnd(); // "create package manager"
  
  //将 package 服务注册到 ServiceManager,这是 binder 服务的常规注册流程
    ServiceManager.addService("package", m);
  final PackageManagerNative pmn = m.new PackageManagerNative();
        ServiceManager.addService("package_native", pmn);
    return m;
  

main方法的代码不多,主要是调用到了PMS的构造函数,而由于PMS中做了很多工作,这也就是Android启动速度慢的主要原因之一。

在其构造方法中,主要的工作是扫描Android系统中几个目标文件夹中的apk,之后建立合适的数据结构和管理如Package信息,四大组件信息,权限信息等各种信息。PKMS的工作流程可以分为五个阶段来分析:

 public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest) 
   ......
   EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
                SystemClock.uptimeMillis());
   ......
   EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
                    startTime);
   ......
   EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                        SystemClock.uptimeMillis());
   ......
   EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
                    SystemClock.uptimeMillis());
   ......
   EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                    SystemClock.uptimeMillis());
 

可以看到系统根据EventLog将PKMS的初始化分为以下几个阶段:

  • BOOT_PROGRESS_PMS_START 启动阶段
  • BOOT_PROGRESS_PMS_SYSTEM_SCAN_START启动阶段
  • BOOT_PROGRESS_PMS_DATA_SCAN_START启动阶段
  • BOOT_PROGRESS_PMS_SCAN_END启动阶段
  • BOOT_PROGRESS_PMS_READY启动阶段

1.1 BOOT_PROGRESS_PMS_START 阶段

PackageManager.disableApplicationInfoCache();
        PackageManager.disablePackageInfoCache();

        PackageManager.corkPackageInfoCache();

        final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing",
                Trace.TRACE_TAG_PACKAGE_MANAGER);
        mPendingBroadcasts = new PendingPackageBroadcasts();

        mInjector = injector;
        mInjector.bootstrap(this);
        mLock = injector.getLock();
        mInstallLock = injector.getInstallLock();
        LockGuard.installLock(mLock, LockGuard.INDEX_PACKAGES);
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
                SystemClock.uptimeMillis());

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

        mContext = injector.getContext();
        mFactoryTest = factoryTest;  //开机模式
        mOnlyCore = onlyCore;   //是否对包做dex优化
        mMetrics = new DisplayMetrics();  //分辨率的配置
        mInstaller = injector.getInstaller(); //保存installer对象

        // Create sub-components that provide services / data. Order here is important.
        t.traceBegin("createSubComponents");

        // Expose private service for system components to use.
        mPmInternal = new PackageManagerInternalImpl();
        LocalServices.addService(PackageManagerInternal.class, mPmInternal);
        mUserManager = injector.getUserManagerService();
        mComponentResolver = injector.getComponentResolver();
        mPermissionManager = injector.getPermissionManagerServiceInternal();
//创建setting对象
        mSettings = injector.getSettings();
			//权限管理服务
        mPermissionManagerService = (IPermissionManager) ServiceManager.getService("permissionmgr");
        mIncrementalManager =
                (IncrementalManager) mContext.getSystemService(Context.INCREMENTAL_SERVICE);
        PlatformCompat platformCompat = mInjector.getCompatibility();
        mPackageParserCallback = new PackageParser2.Callback() 
            @Override
            public boolean isChangeEnabled(long changeId, @NonNull ApplicationInfo appInfo) 
                return platformCompat.isChangeEnabled(changeId, appInfo);
            

            @Override
            public boolean hasFeature(String feature) 
                return PackageManagerService.this.hasSystemFeature(feature, 0);
            
        ;

        // CHECKSTYLE:ON IndentationCheck
        t.traceEnd();

        t.traceBegin("addSharedUsers");
//添加system phone log nfc bluetooth shell se net networkstack这8种shareUserId带mSetting
        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);
        t.traceEnd();

        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;
        
//DexOpt的优化
        mPackageDexOptimizer = new PackageDexOptimizer(mInstaller, mInstallLock, mContext,
                "*dexopt*");
        mDexManager =
                new DexManager(mContext, this, mPackageDexOptimizer, mInstaller, mInstallLock);
        //mArt虚拟机管理服务
				mArtManagerService = new ArtManagerService(mContext, this, mInstaller, mInstallLock);
        mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());

        mViewCompiler = new ViewCompiler(mInstallLock, mInstaller);

        getDefaultDisplayMetrics(mInjector.getDisplayManager(), mMetrics);

        t.traceBegin("get system config");
        SystemConfig systemConfig = SystemConfig.getInstance();
        mAvailableFeatures = systemConfig.getAvailableFeatures();
        ApplicationPackageManager.invalidateHasSystemFeatureCache();
        t.traceEnd();

        mProtectedPackages = new ProtectedPackages(mContext);

        mApexManager = ApexManager.getInstance();
        mAppsFilter = mInjector.getAppsFilter();

        final List<ScanPartition> scanPartitions = new ArrayList<>();
        final List<ApexManager.ActiveApexInfo> activeApexInfos = mApexManager.getActiveApexInfos();
        for (int i = 0; i < activeApexInfos.size(); i++) 
            final ScanPartition scanPartition = resolveApexToScanPartition(activeApexInfos.get(i));
            if (scanPartition != null) 
                scanPartitions.add(scanPartition);
            
        

        mDirsToScanAsSystem = new ArrayList<>();
        mDirsToScanAsSystem.addAll(SYSTEM_PARTITIONS);
        mDirsToScanAsSystem.addAll(scanPartitions);
        Slog.d(TAG, "Directories scanned as system partitions: " + mDirsToScanAsSystem);

        // CHECKSTYLE:OFF IndentationCheck
        synchronized (mInstallLock) 
        // writer
        synchronized (mLock) 
          //启动packageManger线程,负责apk的安装、卸载
            mHandlerThread = new ServiceThread(TAG,
                    Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
            mHandlerThread.start();
            mHandler = new PackageHandler(mHandlerThread.getLooper());
          //进程记录handler
            mProcessLoggingHandler = new ProcessLoggingHandler();
          //watchdog监听ServiceThread是否超时, 
            Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
          //mInstant应用注册
            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();

            t.traceBegin("loadFallbacks");
            FallbackCategoryProvider.loadFallbacks();
            t.traceEnd();

            t.traceBegin("read user settings");
          //读取并解析/data/system下的XML文件
            mFirstBoot = !mSettings.readLPw(mInjector.getUserManagerInternal().getUsers(false));
            t.traceEnd();

            //清理代码路径不存在的孤立软件包
            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();
            
					
          //获取资配置
            String customResolverActivityName = Resources.getSystem().getString(
                    R.string.config_customResolverActivity);
            if (!TextUtils.isEmpty(customResolverActivityName)) 
                mCustomResolverComponentName = ComponentName.unflattenFromString(
                        customResolverActivityName);
            
				//获取扫描开始的时间
            long startTime = SystemClock.uptimeMillis();

在第一阶段主要做了初始化的工作,为后续做扫描工作的准备。这里面你可能会发现一个复杂的数据结构Settings以及它的addShareUserLPw函数。而Settiing在里面又起了什么作用?

1.1.1 Setting

首先我们先分析addShareUserLPw函数:

//使用了系统进程使用的用户id
mSettings.addSharedUserLPw("android.uid.system"以上是关于从APK安装过程来认识PMS的主要内容,如果未能解决你的问题,请参考以下文章

从APK安装过程来认识PMS

APK安装(一)—— PMS原理分析

PMS服务启动原理详解

PMS启动 APK 安装流程详解

Launcher启动过程详解

Launcher启动过程详解