fwrite

fwrite

twitter
github
email

PackageManagerServervice

PackageManagerServervice 通过 SystemServer 进程启动,该服务会 扫描系统中特定的目录,寻找里面的 APK 格式文件,并对这些文件进行解析(得到 AppInfo 相关讯息),最后完成安装。
PKMS 会在安装应用的过程中解析 APK 中的 AndroidManifest.xml 文件(解析出 Android 四大组件),这些解析完的信息会保存在 Android 系统中,方便系统随时取用。

主要功能#

  • 扫描 .apk 文件,安装 系统应用本地应用
  • Parser AndroidManifest.xml 清单文件,分析出四大零组件、权限… 等等信息,并储存在 PKMS 方便查询
  • 管理本地应用,其中包括 安装卸载查询 APK 信息 … 等等功能
  • 分配应用程序的 UID、GID

透过 GID(Group 群组 ID)来管理权限管理,在某个群组中才能使用某些功能

使用#

我们可以通过Context#getPackageManager()方法 来取得 PKMS 服务,PackageManager 是抽象类,实际上是 ApplicationPackageManager。

		
@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
		  
    PackageManager packageManager = this.getBaseContext().getPackageManager();
}

ServiceManager 取得 PKMS#

ActivityThread 通过 ServiceManager 取得 PKMS 的 IBinder,这里的
IPackageManager 是透过 AIDL 自动产生的类,IPackageManager 通过 asInterface 来取得 Java 代理类,透过该代理类来与 PKMS 通信

// ActivityThread.java
	  
@UnsupportedAppUsage
public static IPackageManager getPackageManager() {
    if (sPackageManager != null) {
        return sPackageManager;
    }
	          
    // 1.取得ServiceManager的代理
    // 2.透过代理传入“package”来取得PKMS的句柄(handle)
    // 3.返回PKMS的代理
    final IBinder b = ServiceManager.getService("package");
	          
    // 创建 AIDL 的代理类
    sPackageManager = IPackageManager.Stub.asInterface(b);
	          
    return sPackageManager;
}

SystemServer  初始化 PKMS#

SystemServer 启动引导服务(startBootstrapServices):PKMS 就是在这里启动

// SystemServer.java

public static void main(String[] args) {
    new SystemServer().run();
}
	  
	  
private void run() {
    ... 省略部分

    try {
        startBootstrapServices(t);
        startCoreServices(t);
        startOtherServices(t);
    } /* 省略 catch */

    ... 省略部分

    // Loop forever.
    Looper.loop();
	  
    throw new RuntimeException("Main thread loop unexpectedly exited");
}
	  
	  
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) 
    ... 

    // 安装服务
    Installer installer = mSystemServiceManager.startService(Installer.class);

    mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
	  
	... 
	  
    try {
        ... watch dog

        // 呼叫 PackageManagerService 的静态 main 方法
        // @ 分析 main
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                domainVerificationService, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF,
                mOnlyCore);
    } ... watch dog
	  
    ... 
}

startBootstrapServices#

启动 Installer 服务,之后会用这个服务来安装所有应用

// SystemServer.java

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
    ... 省略部分

    Installer installer = mSystemServiceManager.startService(Installer.class);

    ... 省略部分
}

VoldProperties#decrypt 判断手机装置是否加密(读取 init.rc 档的设定),mOnlyCore = true 代表只运行核心程序。

// SystemServer.java

private static final String ENCRYPTING_STATE = "trigger_restart_min_framework";

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
    ...

    // Only run "core" apps if we're encrypting the device.
    String cryptState = VoldProperties.decrypt().orElse("");

    if (ENCRYPTING_STATE.equals(cryptState)) {
        // 只运行核心程序
        ... log msg

        mOnlyCore = true;
    } else if (ENCRYPTED_STATE.equals(cryptState)) {
        ... log msg

        mOnlyCore = true;
    }

    ...
}

调用PKMS#main方法,创建 PKMS 对象

// SystemServer.java

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
    ... 省略部分

    try {
        ...

        PackageManagerService.main(mSystemContext, installer,
                domainVerificationService, 
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF,
                mOnlyCore);    // 假设传入 false
    } /* 省略 finally */
  
    ... 省略部分
}

如果设备没有加密,就执行 A/B OTA dexopting,OtaDexoptService#main方法

// SystemServer.java

private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
    ... 

    if (!mOnlyCore) {
        boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
                false);

        if (!disableOtaDexopt) {
            ... trace log
            try {
                ... watch dog
                    
                OtaDexoptService.main(mSystemContext, mPackageManagerService);
            } /*  catch、finally */
        }
    }

    ...
}

PKMS 在 SystemServer#startBootstrapServices函数 完成初始化操作后,会在 startOtherServices 做后续的操作(完成 Dex 优化、systemReady)
透过PKMS#performFstrimIfNeeded完成 dex 优化

// SystemServer.java

private void startOtherServices(@NonNull TimingsTraceAndSlog t) {

    ... 省略部分

    try {
        mPackageManagerService.performFstrimIfNeeded();
    } ...

    ... 省略部分
}

PKMS 准备就绪调用 systemReady加载预设权限

PKMS  分析#

PKMS main#

透过PackageManagerService#main方法就可以创建 PackageManagerService 物件,并且将 PKMS 透过 packagepackage_native 添加到 ServiceManager 中

// PackageManagerService.java

public static PackageManagerService main(Context context, Installer installer,
        @NonNull DomainVerificationService domainVerificationService, boolean factoryTest,
        boolean onlyCore) {

    // 检查 package 编译相关系统属性
    PackageManagerServiceCompilerMapping.checkProperties();

    ...

    Injector injector = new Injector(
            context, lock, installer, installLock, 
            new PackageAbiHelperImpl(),
            backgroundHandler,
            SYSTEM_PARTITIONS,
            (i, pm) -> new ComponentResolver(i.getUserManagerService(), pm.mPmInternal, lock),
            (i, pm) -> PermissionManagerService.create(context,
                    i.getSystemConfig().getAvailableFeatures()),
            (i, pm) -> new UserManagerService(context, pm,
                    new UserDataPreparer(installer, installLock, context, onlyCore),
                    lock),
            (i, pm) -> new Settings(Environment.getDataDirectory(),
                    RuntimePermissionsPersistence.createInstance(),
                    i.getPermissionManagerServiceInternal(),
                    domainVerificationService, lock),
            (i, pm) -> AppsFilter.create(pm.mPmInternal, i),
            (i, pm) -> (PlatformCompat) ServiceManager.getService("platform_compat"),
            (i, pm) -> SystemConfig.getInstance(),
            (i, pm) -> new PackageDexOptimizer(i.getInstaller(), i.getInstallLock(),
                    i.getContext(), "*dexopt*"),
            (i, pm) -> new DexManager(i.getContext(), pm, i.getPackageDexOptimizer(),
                    i.getInstaller(), i.getInstallLock()),
            (i, pm) -> new ArtManagerService(i.getContext(), pm, i.getInstaller(),
                    i.getInstallLock()),
            (i, pm) -> ApexManager.getInstance(),
            (i, pm) -> new ViewCompiler(i.getInstallLock(), i.getInstaller()),
            (i, pm) -> (IncrementalManager)
                    i.getContext().getSystemService(Context.INCREMENTAL_SERVICE),
            (i, pm) -> new DefaultAppProvider(() -> context.getSystemService(RoleManager.class),
                    () -> LocalServices.getService(UserManagerInternal.class)),
            (i, pm) -> new DisplayMetrics(),
            (i, pm) -> new PackageParser2(pm.mSeparateProcesses, pm.mOnlyCore,
                    i.getDisplayMetrics(), pm.mCacheDir,
                    pm.mPackageParserCallback) /* scanningCachingPackageParserProducer */,
            (i, pm) -> new PackageParser2(pm.mSeparateProcesses, pm.mOnlyCore,
                    i.getDisplayMetrics(), null,
                    pm.mPackageParserCallback) /* scanningPackageParserProducer */,
            (i, pm) -> new PackageParser2(pm.mSeparateProcesses, false, i.getDisplayMetrics(),
                    null, pm.mPackageParserCallback) /* preparingPackageParserProducer */,
            // Prepare a supplier of package parser for the staging manager to parse apex file
            // during the staging installation.
            (i, pm) -> new PackageInstallerService(
                    i.getContext(), pm, i::getScanningPackageParser),
            (i, pm, cn) -> new InstantAppResolverConnection(
                    i.getContext(), cn, Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE),
            (i, pm) -> new ModuleInfoProvider(i.getContext(), pm),
            (i, pm) -> LegacyPermissionManagerService.create(i.getContext()),
            (i, pm) -> domainVerificationService,
            (i, pm) -> {
                // 负责 apk 安装、卸载
                HandlerThread thread = new ServiceThread(TAG,
                        Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
                thread.start();
                return pm.new PackageHandler(thread.getLooper());
            },
            new DefaultSystemWrapper(),
            LocalServices::getService,
            context::getSystemService);

    // 调用 PackageMangerService 的构造函数
    PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest,
            Build.FINGERPRINT, Build.IS_ENG, Build.IS_USERDEBUG, Build.VERSION.SDK_INT,
            Build.VERSION.INCREMENTAL);

    ...

    // 通过 package、package_native 添加到 ServiceManager中
    ServiceManager.addService("package", m);
    final PackageManagerNative pmn = m.new PackageManagerNative();
    ServiceManager.addService("package_native", pmn);
    return m;
}
// PackageManagerService.java

public static class Injector {

    @VisibleForTesting(visibility = Visibility.PRIVATE)
    interface Producer<T> {
        /** Produce an instance of type {@link T} */
        T produce(Injector injector, PackageManagerService packageManager);
    }

    ... 

    @VisibleForTesting(visibility = Visibility.PRIVATE)
    static class Singleton<T> {
        private final Producer<T> mProducer;
        private volatile T mInstance = null;

        Singleton(Producer<T> producer) {
            this.mProducer = producer;
        }

        T get(Injector injector, PackageManagerService packageManagerService) {
            if (mInstance == null) {
                mInstance = mProducer.produce(injector, packageManagerService);
            }
            return mInstance;
        }
    }

    private final Singleton<PermissionManagerServiceInternal> mPermissionManagerServiceProducer;
    private final Singleton<UserManagerService> mUserManagerProducer;
    private final Singleton<Settings> mSettingsProducer;
    private final Singleton<AppsFilter> mAppsFilterProducer;
    ...
    private final Singleton<DisplayMetrics> mDisplayMetricsProducer;

    Injector(Context context, PackageManagerTracedLock lock, Installer installer,
            Object installLock, PackageAbiHelper abiHelper,
            Handler backgroundHandler,
            List<ScanPartition> systemPartitions, 
            ...
            Producer<PermissionManagerServiceInternal> permissionManagerServiceProducer,
            Producer<UserManagerService> userManagerProducer,
            Producer<Settings> settingsProducer,
            Producer<DisplayMetrics> displayMetricsProducer,
            ) {

        ...

        mPermissionManagerServiceProducer = new Singleton<>(permissionManagerServiceProducer);
        mUserManagerProducer = new Singleton<>(userManagerProducer);
        mSettingsProducer = new Singleton<>(settingsProducer);

        ...

        mDisplayMetricsProducer = new Singleton<>(displayMetricsProducer);
    }

    public PermissionManagerServiceInternal getPermissionManagerServiceInternal() {
        return mPermissionManagerServiceProducer.get(this, mPackageManager);
    }

    public Context getContext() {
        return mContext;
    }

    public Settings getSettings() {
        return mSettingsProducer.get(this, mPackageManager);
    }

    public DisplayMetrics getDisplayMetrics() {
        return mDisplayMetricsProducer.get(this, mPackageManager);
    }

    ...

}

PKMS  构造方法#

PackageManagerService 的构造函数中可以发现 PKMS 构造有 5 个阶段 (写在 EventLog 中)

阶段标志说明其他
BOOT_PROGRESS_PMS_START初始阶段,透过 Inject 内部类来取得 单例 的各种服务、对象DisplayMetrics、Installer、mPermissionManager、mSettings、mPackageDexOptimizer
BOOT_PROGRESS_PMS_SYSTEM_SCAN_START扫描系统
BOOT_PROGRESS_PMS_DATA_SCAN_START扫描 data 区块
BOOT_PROGRESS_PMS_SCAN_END扫描结束
BOOT_PROGRESS_PMS_READY准备阶段

PKMS 有使用到多 Thread,而里面有两个重要的 需要注意

锁名称说明补充
mPackages(小锁)用于保护所有内存中解析 Package 的细节、状态、更新在持有 mInstallLock 的时候,获取 mPackages 是安全的
mInstallLock(大锁)用于保护所有安装 APK 时的锁,通常是有关到应用 APP 的重载(单线程、涉及繁重的 IO 操作在获取 mPackages 时,不该再获取此锁

第一阶段 - BOOT_PROGRESS_PMS_START#

第一阶段的重点是 Settings#readLPw 方法,读取 /data/system 目录下的文件

BOOT_PROGRESS_PMS_START:取得 DisplayMetrics(分辨率)、Installer(安装)、PermissionManager (权限管理)、mSettings(保存安装信息、清除不存在的应用)、PackageDexOptimizer(Dex 优化)… 详细请看注释

// PackageManagerService.java

public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,final String buildFingerprint, final boolean isEngBuild,final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {

    ...

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


    mOnlyCore = onlyCore;
    mMetrics = injector.getDisplayMetrics();
    mInstaller = injector.getInstaller();
    mUserManager = injector.getUserManagerService(); // 多用戶管理
    // 权限管理服务
    mPermissionManager = injector.getPermissionManagerServiceInternal();

    // 涉及 'data/system/' packages.xml
    // packages-backup.xml
    // packages.list
    // packages-stopped.xml
    // packages-stopped-backup.xml 文件
    mSettings = injector.getSettings();

    ...

    // 添加 system、phone、log、nfc、bluetooth、shell、se、
    // networkstack、uwb 这几个 sharedUserLPw 到 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);
    mSettings.addSharedUserLPw("android.uid.uwb", UWB_UID,
            ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);

    ...

    // 处理 dex 优化(DexOpt 优化)
    mPackageDexOptimizer = injector.getPackageDexOptimizer();
    mDexManager = injector.getDexManager();
    // Art 虚拟机管理
    mArtManagerService = injector.getArtManagerService();

    ...

    // 创建 /data/app 文件夹
    mAppInstallDir = new File(Environment.getDataDirectory(), "app");

    // 安装 APK 时需要的锁,保护所有对 installed 的访问
    // CHECKSTYLE:OFF IndentationCheck
    synchronized (mInstallLock) {
    // writer
    synchronized (mLock) {
        // 启动 PackageManager Thread,负责 apk 安装、卸载
        mHandler = injector.getHandler();
        // 进程纪录 Handler
        mProcessLoggingHandler = new ProcessLoggingHandler();
        
        // 监听 PackageManager Thread 是否超时10分钟
        Watchdog.getInstance().addThread(mHandler, 
                                 // WATCHDOG_TIMEOUT => 10 分鐘
                                 WATCHDOG_TIMEOUT);
    
        ...
            
        // 读取安装相关的 SELinux 策略
        SELinuxMMAC.readInstallPolicy();
        
        // 读取并解析 /data/system 中的 xml 文件
        mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
        
        t.traceEnd();
    }
    
    }
}

其中 mSettings.addSharedUserLPw 方法是将 SharedUserId 添加到 Setting 中;一般来讲进程间数据不可共享,但 有共同 SharedUserId 就可以共享数据

  • mPackageDexOptimizer 是 Dex 的优化工具
  • mHandler 绑定后台 ServiceThread 的消息队列,PKMS 通过它来驱动 APK 复制&安装,并且该 Handler 会由 WatchDog 来监看(防止花费过多时间)

PKMD 会访问几个重要的文件夹

访问资料夾
File(Environment.getDataDirectory(), “app”)/data/app
File(Environment.getDataDirectory(), “app-lib”)/data/app-lib

Settings 创建#

先复习 Settings 对象由来:PKMS 的 Settings 对象会由PKMS#Inject类提供

// PackageManager

public static class Injector {

    private final Singleton<Settings> mSettingsProducer;

    Injector(/* 省略参数 */) {
        ...
        mSettingsProducer = new Singleton<>(settingsProducer);
    }

    public Settings getSettings() {
        return mSettingsProducer.get(this, mPackageManager);
    }

}

public static PackageManagerService main(Context context, Installer installer,
        @NonNull DomainVerificationService domainVerificationService, boolean factoryTest,
        boolean onlyCore) {
    
    Injector injector = new Injector(
            context, lock, installer, installLock, new PackageAbiHelperImpl(),
            backgroundHandler,
            SYSTEM_PARTITIONS,
        ...
      
        (i, pm) -> new Settings(Environment.getDataDirectory(),  
                    RuntimePermissionsPersistence.createInstance(),
                    i.getPermissionManagerServiceInternal(),
                    domainVerificationService, 
                    lock),
    );
}

Settings 类 的构造函数会创建所需文件 & 文件夹,并设定它们的权限

// Settings.java

Settings(File dataDir,    //带入的 dataDir 是 /data
         RuntimePermissionsPersistence runtimePermissionsPersistence,
        LegacyPermissionDataProvider permissionDataProvider,
        @NonNull DomainVerificationManagerInternal domainVerificationManager,
        @NonNull PackageManagerTracedLock lock)  {

    ...

    // 创建 /data/system 目录
    mSystemDir = new File(dataDir, "system");//'/data/system'
    mSystemDir.mkdirs(); // 创建 /data/system
    // 文件夹权限 775
    FileUtils.setPermissions(mSystemDir.toString(),
            FileUtils.S_IRWXU|FileUtils.S_IRWXG
            |FileUtils.S_IROTH|FileUtils.S_IXOTH,
            -1, -1);

    // 创建 /data/system/packages.xml
    mSettingsFilename = new File(mSystemDir, "packages.xml");
    // 创建 /data/system/packages-backup.xml 
    mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
    // 创建 data/system/packages.list
    mPackageListFilename = new File(mSystemDir, "packages.list");

    // 设定 chmod 0640
    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
    // 创建 data/system/packages-stopped.list
    mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
    // 创建 data/system/packages-stopped-backup.list
    mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");

    ...

}

Settings  - readLPw 读取 package 文件#

mSettings#readLPw () 函数:读取 /data/system 目录下的文件,并保存到 Setting 对象中,而文件又分为以下几种(提出较为重要的几个)

文件名说明其他
packages.xml安装 app 信息PKMS 扫描完目录文件后会创建该文件,当系统执行 安装、卸载、更新 等操作时都会更新这个文件
packages-backup.xml安装 app 的备份信息避免在安装时关机,产生意外
packages.list所有安装的 app 信息(非系统 APP)描述所有非系统 APK 信息,当有第三方 APP 变更时就会修改该文件
packages-stopped.xml强制停止 app 信息强制停止某个应用时(用户操作),系统会将该应用的相关讯息记录到该文件中
packages-stopped-backup.xml强制停止 app 的备份信息
mSettings#readLPw() 功能:首先扫描 packages.xmlpackages-backup.xml 文件,其中与 Linux 使用 UID 有关的函数如下
“package” 标签:使用 readPackageLPw 函数,读取上一次分配的 Linux UID
“shared-user” 标签:使用 readSharedUserLPw 函数,读取上一次应用共享的 shared ID
// Settings.java

boolean readLPw(@NonNull List<UserInfo> users) {
    FileInputStream str = null;

    // 如果有 packages-backup.xml的话取得backup IO流
    if (mBackupSettingsFilename.exists()) {
        try {
            str = new FileInputStream(mBackupSettingsFilename);
            ...
        } /* 省略 catch */
    }

    try {
        if (str == null) {
            ...

            // 没有 backup 就使用 packages.xml
            str = new FileInputStream(mSettingsFilename);
        }

        // 解析 xml
        final TypedXmlPullParser parser = Xml.resolvePullParser(str);
        int type;
        // 调整 xml 指标位置
        while ((type = parser.next()) != XmlPullParser.START_TAG
                && type != XmlPullParser.END_DOCUMENT) {
            ;
        }
        // 解析格式,判断 xml 格式是否正确
        if (type != XmlPullParser.START_TAG) {
            ... err log
            return false;
        }


        int outerDepth = parser.getDepth();
        // 开始分析 xml
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                continue;
            }

            // 解析节点名称
            String tagName = parser.getName();
            if (tagName.equals("package")) {
                // 读取上一次分配的 Linux UID
                readPackageLPw(parser, users);

            } else if (tagName.equals("permissions")) {
                mPermissions.readPermissions(parser);

            } else if (tagName.equals("permission-trees")) {
                mPermissions.readPermissionTrees(parser);

            } else if (tagName.equals("shared-user")) {
                // 读取上一次应用共享的 GID
                readSharedUserLPw(parser, users);

            } ... 省略部分 else if

            else {
                ... log

                XmlUtils.skipCurrentTag(parser);
            }
        }
        str.close();
    } /* 省略 catch、finally */ 

    ...

    return true;
}

readPackageLPw 应用分配独立 Linux ID#

接下来我们主要关注 “package” 标签中的 3 元素

元素名功能补充
name应用包名必须要有 package 包名
userIdLinux 上次为该应用分配的 独立 UID
sharedUserId该应用 没有独立 UID,与其它应用共享 UID将该应用添加进 mPendingPackages 列表之后判断
// Setting.java

public static final String ATTR_NAME = "name";

private final WatchedArrayList<PackageSetting> mPendingPackages = new WatchedArrayList<>();

private void readPackageLPw(TypedXmlPullParser parser, List<UserInfo> users,
        ArrayMap<String, Long> originalFirstInstallTimes)
        throws XmlPullParserException, IOException {

    String name = null;
    int userId = 0;
    int sharedUserAppId = 0;

    try {
        // App package name
        name = parser.getAttributeValue(null, ATTR_NAME);

        ...

        userId = parser.getAttributeInt(null, "userId", 0);
        sharedUserAppId = parser.getAttributeInt(null, "sharedUserId", 0);

        if (name == null) {
            PackageManagerService.reportSettingsProblem(Log.WARN,
                    "Error in package manager settings: <package> has no name at "
                            + parser.getPositionDescription());
        } else if (codePathStr == null) {
            ...

        } else if (userId > 0) {    // 已分配到独立 ID
            packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
                    legacyNativeLibraryPathStr, primaryCpuAbiString, secondaryCpuAbiString,
                    cpuAbiOverrideString, userId, versionCode, pkgFlags, pkgPrivateFlags,
                    null /* usesSdkLibraries */, null /* usesSdkLibraryVersions */,
                    null /* usesStaticLibraries */, null /* usesStaticLibraryVersions */,
                    null /* mimeGroups */, domainSetId);

            ...

        } else if (sharedUserAppId != 0) {    // 未分配独立 ID
            if (sharedUserAppId > 0) {

                // 保存该应用信息
                packageSetting = new PackageSetting(name.intern(), realName,
                        new File(codePathStr), legacyNativeLibraryPathStr,
                        primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
                        versionCode, pkgFlags, pkgPrivateFlags, sharedUserAppId,
                        null /* usesSdkLibraries */,
                        null /* usesSdkLibrariesVersions */,
                        null /* usesStaticLibraries */,
                        null /* usesStaticLibraryVersions */,
                        null /* mimeGroups */, domainSetId);
                ...

                // 添加到 `mPendingPackages` 列表
                mPendingPackages.add(packageSetting);
                ...
            } else {
                ...
            }
        } else {
            ...
        }
    } /* 省略 catch */
}

addPackageLPw 函数:在 PKMS 中 每个应用都是以 PackageSetting 对象存在,并将其储存在以 package name 为 Key 的 HashMap 中

// Setting.java

// 储存全部应用的信息
final WatchedArrayMap<String, PackageSetting> mPackages;

private final AppIdSettingMap mAppIds;

PackageSetting addPackageLPw(String name, String realName, File codePath,
        String legacyNativeLibraryPathString, String primaryCpuAbiString,
        String secondaryCpuAbiString, String cpuAbiOverrideString, int uid, 
        ... /* 省略部分 */) {

    // 以 name 来取得 PackageSetting
    PackageSetting p = mPackages.get(name);
    if (p != null) {
        // 判断 uid 
        if (p.getAppId() == uid) {
            // 相等代表已分配独立 UID
            return p;
        }
        PackageManagerService.reportSettingsProblem(Log.ERROR,
                "Adding duplicate package, keeping first: " + name);
        return null;
    }
    p = new PackageSetting(name, realName, codePath, legacyNativeLibraryPathString,
            primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString, 
            ... /* 省略部分 */);

    // 设定 UID 给该 PackageSetting
    p.setAppId(uid);

    // 注册该 ID 至系统
    if (mAppIds.registerExistingAppId(uid, p, name)) {
        mPackages.put(name, p);
        return p;
    }
    return null;
}

registerExistingAppId函数:已分配的应用会从 mNonSystemSettings 取出 null

// Process.java

public static final int FIRST_APPLICATION_UID = 10000;

// ------------------------------------------------------------
// AppIdSettingMap.java

private final WatchedArrayList<SettingBase> mNonSystemSettings;

public boolean registerExistingAppId(int appId, SettingBase setting, Object name) {

    // 大于 FIRST_APPLICATION_UID 代表是独立应用
    if (appId >= Process.FIRST_APPLICATION_UID) {
        int size = mNonSystemSettings.size();
        final int index = appId - Process.FIRST_APPLICATION_UID;
        // fill the array until our index becomes valid
        while (index >= size) {
            mNonSystemSettings.add(null);
            size++;
        }
        // 已分配会取出 null
        if (mNonSystemSettings.get(index) != null) {
            // 重复 UID
           
            ...err msg
            return false;
        }
        mNonSystemSettings.set(index, setting);
    } else {
        // 小于 FIRST_APPLICATION_UID 代表是共享应用
        ...
    }
    return true;
}

readPackageLPw 应用分配共享 Linux ID#

接下来我们主要关注 “shared-user” 标签中的 3 元素

元素名功能补充
name用来描述一个共享 Linux 使用者的名称
userId用来描述一个共享 Linux 使用者的 ID
system描述该 ID 是系统型态、使用者型态
// Setting.java

private void readSharedUserLPw(TypedXmlPullParser parser, List<UserInfo> users)
        throws XmlPullParserException, IOException {
    String name = null;
    int pkgFlags = 0;
    int pkgPrivateFlags = 0;
    SharedUserSetting su = null;
    {
        name = parser.getAttributeValue(null, ATTR_NAME);    
        int userId = parser.getAttributeInt(null, "userId", 0);
        if (parser.getAttributeBoolean(null, "system", false)) {
            pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
        }
        
        if (name == null) {
            ...
        } else if (userId == 0) {
            ...
        } else {
            if ((su = addSharedUserLPw(name.intern(), userId, pkgFlags, pkgPrivateFlags))
                    == null) 
                ...
            }
        }
    }

    ...
}

Setting#addSharedUserLPw 函数:使用 SharedUserSetting 来描述一个共享应用;比对 ID 确认没问题后,就可以加入 mSharedUsers 列表

// Setting.java

final WatchedArrayMap<String, SharedUserSetting> mSharedUsers 
            = new WatchedArrayMap<>();

SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
    SharedUserSetting s = mSharedUsers.get(name);
    if (s != null) {
        if (s.mAppId == uid) {
            return s;
        }
        ...err

        return null;
    }
    // 创建对应对象
    s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
    // 设定 ID
    s.mAppId = uid;
    
    // 尝试注册
    if (mAppIds.registerExistingAppId(uid, s, name)) {
        mSharedUsers.put(name, s);
        return s;
    }
    return null;
}

registerExistingAppId 函数:已分配的应用会从 mNonSystemSettings 取出 null

// Process.java

public static final int FIRST_APPLICATION_UID = 10000;

// ------------------------------------------------------------
// AppIdSettingMap.java

private final WatchedArrayList<SettingBase> mNonSystemSettings;

public boolean registerExistingAppId(int appId, SettingBase setting, Object name) {

    // 大于 FIRST_APPLICATION_UID 代表是独立应用
    if (appId >= Process.FIRST_APPLICATION_UID) {
        ...
    } else {
        // 小于 FIRST_APPLICATION_UID 代表是共享应用
        if (mSystemSettings.get(appId) != null) {
            ...err

            return false;
        }
        mSystemSettings.put(appId, setting);
    }
    return true;
}

回到 readLPw 函数:经过上面分析 “shared-user”“package” 后可以得到共享、独立应用的相关讯息,接着就是要处理共享应用的 ID

// Settings.java

private final AppIdSettingMap mAppIds;

boolean readLPw(@NonNull List<UserInfo> users) {

    ...

    final int N = mPendingPackages.size();

    for (int i = 0; i < N; i++) {
        final PackageSetting p = mPendingPackages.get(i);
        final int sharedUserAppId = p.getSharedUserAppId();
        
        // 共享 ID 一定大于 0
        if (sharedUserAppId <= 0) {
            continue;
        }
        final Object idObj = getSettingLPr(sharedUserAppId);
        if (idObj instanceof SharedUserSetting) {
            final SharedUserSetting sharedUser = (SharedUserSetting) idObj;
            addPackageSettingLPw(p, sharedUser);
        } else if (idObj != null) {
            ...
        } else {
            ...
        }
    }
    mPendingPackages.clear();

    return true;
}


public SettingBase getSettingLPr(int appId) {
    return mAppIds.getSetting(appId);
}

void addPackageSettingLPw(PackageSetting p, SharedUserSetting sharedUser) {
    mPackages.put(p.getPackageName(), p);
    
    // 如果是共享应用还要再判断
    if (sharedUser != null) {
        SharedUserSetting existingSharedUserSetting = getSharedUserSettingLPr(p);

        if (existingSharedUserSetting != null && existingSharedUserSetting != sharedUser) {
            ...err msg

            sharedUser.removePackage(p);
        } else if (p.getAppId() != sharedUser.mAppId) {
            ...err msg

        }

        sharedUser.addPackage(p);
        p.setSharedUserAppId(sharedUser.mAppId);
        // 决定最终 ID
        p.setAppId(sharedUser.mAppId);
    }

    Object userIdPs = getSettingLPr(p.getAppId());
    if (sharedUser == null) {
        if (userIdPs != null && userIdPs != p) {
            mAppIds.replaceSetting(p.getAppId(), p);
        }
    } else {
        if (userIdPs != null && userIdPs != sharedUser) {
            mAppIds.replaceSetting(p.getAppId(), sharedUser);
        }
    }
}

第二阶段 - BOOT_PROGRESS_PMS_SYSTEM_SCAN_START#

BOOT_PROGRESS_PMS_SYSTEM_SCAN_START:扫描系统阶段,其中目录包括(systemvendorproductodmoem … 等等目录中的 priv-appappoverlay)并且该步骤 仍在两个锁内执行
scanDirTracedLI 方法:该方法扫描 APK 包,会针对传入的路径扫描内部的 APK 档案,之后会再针对 scanDirTracedLI 进行分析

	  // PackageManagerService.java
	  
	  // Key 是应用包名,Value 是应用包
	  final ArrayMap<String, PackageParser.Package> mPackages =
	          new ArrayMap<String, PackageParser.Package>();
	  
	  public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
	          final String buildFingerprint, final boolean isEngBuild,
	          final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {
	  
	      ...
	  
	      // CHECKSTYLE:OFF IndentationCheck
	      synchronized (mInstallLock) {
	      // writer
	      synchronized (mLock) {
	  
	          ...
	  
	          // 记录开始时间
	          long startTime = SystemClock.uptimeMillis();
	          EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
	              startTime);
	  
	          // 从 init.rc 中获取环境变量 BOOTCLASSPATH、
	          //                        SYSTEMSERVERCLASSPATH
	          final String bootClassPath = 
	              System.getenv("BOOTCLASSPATH");
	  
	          final String systemServerClassPath = 
	              System.getenv("SYSTEMSERVERCLASSPATH");
	  
	  
	          // 获取 /system/framework 目录
	          File frameworkDir = new File(Environment.getRootDirectory(), "framework");
	  
	          // 获取内部版本
	          final VersionInfo ver = mSettings.getInternalVersion();
	  
	          // 判断是否需要更新
	          mIsUpgrade =
	              !buildFingerprint.equals(ver.fingerprint);
	  
	          // Android M 升级上来的版本,须将系统应用权限从安装时申请,改为运行时申请
	          mPromoteSystemApps =
	              mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;
	  
	          // Android N升级上来的版本,需要像首次启动一样处理包提取,因为没有可用的分析数据
	          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;
	  
	          ...
	  
	          // 准备解析 package 的缓存
	          mCacheDir = preparePackageParserCache(mIsEngBuild);
	  
	          // 设定 flag,当扫描安装文件夹时不改变 apk 路径
	          int scanFlags = SCAN_BOOTING | SCAN_INITIAL;
	  
	          // 收集 vendor/product/system_ext overlay packages.
	          for (int i = mDirsToScanAsSystem.size() - 1; i >= 0; i--) {
	              final ScanPartition partition = mDirsToScanAsSystem.get(i);
	              if (partition.getOverlayFolder() == null) {
	                  continue;
	              }
	              // 扫描 overlay… 等等文件夹内的 apk
	              scanDirTracedLI(partition.getOverlayFolder(), systemParseFlags,
	                      systemScanFlags | partition.scanFlag, 0,
	                      packageParser, executorService);
	          }
	  
	          // 扫描 framework 文件夹内的 apk
	          scanDirTracedLI(frameworkDir, systemParseFlags,
	              systemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED, 0,
	              packageParser, executorService);
	  
	          // 判断安装包是否是 android
	          if (!mPackages.containsKey("android")) {
	              throw new IllegalStateException(
	                      "Failed to load frameworks package; check log for warnings");
	          }
	  
	          for (int i = 0, size = mDirsToScanAsSystem.size(); i < size; i++) {
	              final ScanPartition partition = mDirsToScanAsSystem.get(i);
	              if (partition.getPrivAppFolder() != null) {
	                  // 扫描 priv-app 文件夹
	                  scanDirTracedLI(partition.getPrivAppFolder(), systemParseFlags,
	                          systemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, 0,
	                          packageParser, executorService);
	              }
	              // 扫描 /system/app 文件夹
	              scanDirTracedLI(partition.getAppFolder(), systemParseFlags,
	                      systemScanFlags | partition.scanFlag, 0,
	                      packageParser, executorService);
	          }
	  
	          ...
	  
	          if (!mOnlyCore) {
	              // do this first before mucking with mPackages for the "expecting better" case
	              final int numPackages = mPackages.size();
	              for (int index = 0; index < numPackages; index++) {
	                  final AndroidPackage pkg = mPackages.valueAt(index);
	                  if (pkg.isStub()) {
	                      stubSystemApps.add(pkg.getPackageName());
	                  }
	              }
	  
	              // 倒序扫描所有应用
	              for (int index = packageSettings.size() - 1; index >= 0; index--) {
	                  final PackageSetting ps = packageSettings.valueAt(index);
	  
	                  // 如果包有 FLAG_SYSTEM 忽略
	                  if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
	                      continue;
	                  }
	                  /*
	                   * If the package is scanned, it's not erased.
	                   */
	                  final AndroidPackage scannedPkg = mPackages.get(ps.name);
	                  if (scannedPkg != null) {
	  					//若在disabled packages list,添加进
	  					// via OTA,再将其移除
	                      if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
	                          ...
	                          //将系统 App 的 PackageSetting 从 PKMS 中 mPackage 移除
	                          removePackageLI(scannedPkg, true);
	  
	                          // 将升级包的路径添加到 mExpectingBetter 列表中
	                          mExpectingBetter.put(ps.name, ps.getPath());
	                      }
	                      continue;
	                  }
	  
	                  if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
	                      logCriticalInfo(Log.WARN, "System package " + ps.name
	                              + " no longer exists; it's data will be wiped");
	                      // 系统 APP 将不存在,移除该 APP 的数据
	                      removePackageDataLIF(ps, userIds, null, 0, false);
	                  } else {
	                      // we still have a disabled system package, but, it still might have
	                      // been removed. check the code path still exists and check there's
	                      // still a package. the latter can happen if an OTA keeps the same
	                      // code path, but, changes the package name.
	                      final PackageSetting disabledPs =
	                              mSettings.getDisabledSystemPkgLPr(ps.name);
	  
	                      if (disabledPs.getPath() == null || !disabledPs.getPath().exists()
	                              || disabledPs.pkg == null) {
	                          // 该系统 APP 在 isDisabledSystemPackage 中,并且没有发现升级包
	                          possiblyDeletedUpdatedSystemApps.add(ps.name);
	                      } else {
	                          // We're expecting that the system app should remain disabled, but add
	                          // it to expecting better to recover in case the data version cannot
	                          // be scanned.
	                          mExpectingBetter.put(disabledPs.name, disabledPs.getPath());
	                      }
	                  }
	              }
	          }
	  
	          ...
	  
	      }
	  
	      }
	  
	  }

扫描升级系统 APP - system 文件夹#

目前阶段(BOOT_PROGRESS_PMS_SYSTEM_SCAN_START)主要是扫描 /system 文件夹:这个目录下文件夹都如何规划放置
Android 系统架构有分为应用层、应用框架层、系统运行层、硬件抽象层、内核层

system 内文件夹放置内容补充
app系统 app包括 google 内置、手机厂商 app
framework应用框架 jar 包主要放 jar 包、vdex
priv-app特权 app
lib放置动态 so 文件
fonts系统字体多是 ttf 档
media系统音效像是铃声、提示音、系统启动动画

第二个目的是扫描系统文件并处理,处理的 重点是 ==OTA 升级 ==系统会将可升级的系统应用标记为 DisabledSystemPackage,并且有 3 种状况
系统 APP 有更新:透过 removePackageLI 将系统 App 的 PackageSetting 从 PKMS 中 mPackage 移除,并 添加到 mExpectingBetter 列表
系统 APP 被移除:透过 removePackageDataLIF 移除系统 APP 数据
没有升级包:系统应用为 DisabledSystemPackage,但没有发现升级包,代表代表系统升级包 可能 被删除

第三阶段 - BOOT_PROGRESS_PMS_DATA_SCAN_START#

BOOT_PROGRESS_PMS_DATA_SCAN_START:主要会 扫描 /data 文件夹
扫描处理、更新 /data 目录的应用信息(也会及时移除不需要的数据)
处理上一步遗留的 possiblyDeletedUpdatedSystemApps 列表

  • 如果无法从 mPackage 中取得 Package 则会删除该 APP
  • 如果可以取得 Package 但不是系统 APP,并且会做以下这些事情
    • 移除 System 权限
    • 移除 Package
    • 重新扫描 Package 路径的 APK
      扫描 mExpectingBetter 列表
    • 取得系统 APP 升级包的路径,并且会做以下这些事情
    • 根据系统 APP 所在的目录设定扫描的解析参数
    • 将 PackageName 设定给mSetting#mPackages中(removeDisabledSystemPackageLPw 方法)
    • 清除 mExpectingBetter 列表
// PackageManagerService.java

private final File mAppInstallDir;

public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
        final String buildFingerprint, final boolean isEngBuild,
        final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {

    ...
   
    // 取得 /data/app 资料夾
    mAppInstallDir = new File(Environment.getDataDirectory(), "app");
    
     // CHECKSTYLE:OFF IndentationCheck
    synchronized (mInstallLock) {
    // writer
    synchronized (mLock) {
        
        ...
            
        if (!mOnlyCore) {
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                    SystemClock.uptimeMillis());
            
            // 扫描 /data/app文件夹
            scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0,
                    packageParser, executorService);
        }
        
        // 关闭 Parser 流(解析 Package xml 的流)
        packageParser.close();
        
        // 关闭 Executor 的全部任务
        List<Runnable> unfinishedTasks = executorService.shutdownNow();
        if (!unfinishedTasks.isEmpty()) {
            throw new IllegalStateException("Not all tasks finished before calling close: "
                    + unfinishedTasks);
        }
        
        
        if (!mOnlyCore) {    
            // 2. 扫描上一步所遗留的 APP 包(倒序)

            for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) {
                final String packageName = possiblyDeletedUpdatedSystemApps.get(i);
                final AndroidPackage pkg = mPackages.get(packageName);
                final String msg;
                
                // 从禁用系统列表(mDisabledSystemPackage)中移除
                mSettings.removeDisabledSystemPackageLPw(packageName);
                
                if (pkg == null) {
                    // 应该要找到升级包,但没找到(移除该APP)
                    msg = "Updated system package " + packageName
                            + " no longer exists; removing its data";
                    // (实际上并非马上移除)
                } else {
                    
                    // 如果有取到pkg,代表该APP存在Data区中,
                    // 不属于System app,移除系统权限
                    msg = "Updated system package " + packageName
                            + " no longer exists; rescanning package on data";
                    // 以下,删除并重新扫描数据包
                    removePackageLI(pkg, true);    // 删除
                    try {
                        final File codePath = new File(pkg.getPath());
                        // 重新扫描
                        scanPackageTracedLI(codePath, 0, scanFlags, 0, null);
                    } catch (PackageManagerException e) {
                        Slog.e(TAG, "Failed to parse updated, ex-system package: "
                                + e.getMessage());
                    }
                }
               
                // 如果我们还有一个包设置[ie.它是以前扫描并为系统所知]
                // 但是,我们没有该Pkg [即。从/data扫描它时出错
                // partition],彻底删除包数据。
                final PackageSetting ps = mSettings.getPackageLPr(packageName);
                if (ps != null && mPackages.get(packageName) == null) {
                    // 移除 data 内出错的数据包
                    removePackageDataLIF(ps, userIds, null, 0, false);
                }
                logCriticalInfo(Log.WARN, msg);

            }

            // 3. 遍历 mExpectingBetter 列表
            for (int i = 0; i < mExpectingBetter.size(); i++) {
                final String packageName = mExpectingBetter.keyAt(i);
                if (!mPackages.containsKey(packageName)) {
                    // 取得系统 APP 升级包的路径
                    final File scanFile = mExpectingBetter.valueAt(i);

                    for (int i1 = mDirsToScanAsSystem.size() - 1; i1 >= 0; i1--) {
                        final ScanPartition partition = mDirsToScanAsSystem.get(i1);
                        // 根据系统 APP 所在的目录设定扫描的解析参数
                        if (partition.containsPrivApp(scanFile)) {
                            reparseFlags = systemParseFlags;
                            // 设定扫描参数
                            rescanFlags = systemScanFlags | SCAN_AS_PRIVILEGED
                                    | partition.scanFlag;
                            break;
                        }
                        if (partition.containsApp(scanFile)) {
                            reparseFlags = systemParseFlags;
                            rescanFlags = systemScanFlags | partition.scanFlag;
                            break;
                        }
                    }
                    if (rescanFlags == 0) {
                        Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
                        continue;
                    }

                  //将PackageName对应的包设置数据(PackagesSetting)
                  //添加到mSetting的mPackages中
                    mSettings.enableSystemPackageLPw(packageName);

                    try {
                        // 扫描系统 APP 的升级包
                        final AndroidPackage newPkg = scanPackageTracedLI(
                                scanFile, reparseFlags, rescanFlags, 0, null);
                        // We rescanned a stub, add it to the list of stubbed system packages
                        if (newPkg.isStub()) {
                            stubSystemApps.add(packageName);
                        }
                    } /* 省略 catch */
                }
            }

          //解压&安装根系统应用
          //该操做要确保最后执行,来确保所有存根被替代or禁用
          // Stub(存根)
            installSystemStubPackages(stubSystemApps, scanFlags);

            ...
        }
        
        
        // 清除升级列表
        mExpectingBetter.clear();
        
        // 取得 Storage manage 包名
        mStorageManagerPackage = getStorageManagerPackageName();
        
        // 解决保护 action 过滤器,只允许 setup wizard 为这些 action 有最高权限的过滤
        mSetupWizardPackage = getSetupWizardPackageNameImpl();
        
        ...
        
        // 读取并更新要保留的 package 的上次使用时间
        mPackageUsage.read(packageSettings);
        mCompilerStats.read();

    }
}

scanDirTracedLI - 分析 data 目录內容#

/data 文件夹可成为 Data 分区,它个主用公用有两个
储存所有用户的 个人数据
储存所有用户的 配置文件
接着来看 /data 目录下的子目录都放那些数据

/data 底下目录含意
app储存该收机装置,自己安装的 APP 应用
data储存所有已安装的 APP 数据,其中也包括 System APP 数据
app-privateAPP 的私有儲存空間
app-lib储存所有 APP 的 JNI Lib
system存放系统配置文件
anr用于存放 ANR 发生时,系统生成的 traces.text 文件

第四階段 - BOOT_PROGRESS_PMS_SCAN_END#

BOOT_PROGRESS_PMS_SCAN_END 阶段 升级后首次启动,要清除不必要的缓存数据、权限,更新 package.xml 档案 (packages.xml 用来储存所有 APP 的信息)
SDK 版本更变,重新更新权限
OTA 升级后首次启动,清除不要要缓存
OTA 英文全称是 Over-the-Air Technology ,即空间下载技术,是手机通过行动网络对手机系统,应用程序进行管理的技术
权限更新完成后清理相关数据
透过 mSetting 的内容保存并更新 package.xml 文件,这样以后 PKMS 创建时就会读取到新的 Setting

// PackageManagerService.java

public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
        final String buildFingerprint, final boolean isEngBuild,
        final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {

    ... 
  
     // CHECKSTYLE:OFF IndentationCheck
    synchronized (mInstallLock) {
    // writer
    synchronized (mLock) {
        
        ...

        // 进入第四阶段
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
                SystemClock.uptimeMillis());

        // 权限重制
        mPermissionManager.onStorageVolumeMounted(
                StorageManager.UUID_PRIVATE_INTERNAL, mIsUpgrade);
        ver.sdkVersion = mSdkVersion;

        // 如果是第一次启动或从pre-M升级上来,并且是正常启动,那我们需要初始化User定义的首选预设应用
        if (!mOnlyCore && (mPromoteSystemApps || mFirstBoot)) {
            for (UserInfo user : mInjector.getUserManagerInternal().getUsers(true)) {
                mSettings.applyDefaultPreferredAppsLPw(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 && !mOnlyCore) {
            Slog.i(TAG, "Build fingerprint changed; clearing code caches");
            for (int i = 0; i < packageSettings.size(); i++) {
                final PackageSetting ps = packageSettings.valueAt(i);
                if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
                    // 没有应用会在这时启动,所以不必冻结
                    clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
                            FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
                                    | Installer.FLAG_CLEAR_CODE_CACHE_ONLY
                                    | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES);
                }
            }
            ver.fingerprint = Build.FINGERPRINT;
        }
        
        // 在Launcher中隐藏他们的icon(Android-Q之前的非系统应用)
        if (!mOnlyCore && mIsPreQUpgrade) {
            Slog.i(TAG, "Whitelisting all existing apps to hide their icons");
            int size = packageSettings.size();
            for (int i = 0; i < size; i++) {
                final PackageSetting ps = packageSettings.valueAt(i);
                if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                    continue;
                }
                ps.disableComponentLPw(PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME,
                        UserHandle.USER_SYSTEM);
            }
        }
        // clear only after permissions and other defaults have been updated
        mPromoteSystemApps = false;
        
        // 所有的改变都在扫描中完成
        ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;
        
        // 更新 package.xml
        t.traceBegin("write settings");
        writeSettingsLPrTEMP();
        t.traceEnd();

        ...

    }
        
    }
}

第五阶段 - BOOT_PROGRESS_PMS_READY#

BOOT_PROGRESS_PMS_READY:PKMS 最后阶段
PackageInstallerService 用于管理安装 Session 服务,每次安装过程都会分配一个 SessionId
要求触发 GC 回收内存

// PackageManagerService.java
public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
        final String buildFingerprint, final boolean isEngBuild,
        final boolean isUserDebugBuild, final int sdkVersion, final String incrementalVersion) {

    ...
    
     // CHECKSTYLE:OFF IndentationCheck
    synchronized (mInstallLock) {
    // writer
    synchronized (mLock) {
        
        ...
             
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                SystemClock.uptimeMillis());
        
        ... 
        
        // PermissionController 是一个系统核心,预设同意&管理权限
        mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr();
        
        ... 省略部分
        
        // 取得安装器服务
        mInstallerService = mInjector.getPackageInstallerService();
        
        ...
        
      // 读取&更新dex档案的用法
      // 在PM init结束时执行这个操作,以便所有包都协调其数据目录
      // 建构可以验证的文件并建构内存缓存
      // 使用文件预计很小,因此与其它活动相比,加载&验证它都满花费时间的
        final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>();
        for (int userId : userIds) {
            userPackages.put(userId, getInstalledPackages(/*flags*/ 0, userId).getList());
        }
        mDexManager.load(userPackages);
        if (mIsUpgrade) {
            FrameworkStatsLog.write(
                    FrameworkStatsLog.BOOT_TIME_EVENT_DURATION_REPORTED,
                    BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_INIT_TIME,
                    SystemClock.uptimeMillis() - startTime);
        }

        // 属性被重构后,重构 live computer
        mLiveComputer = createLiveComputer();

    }
        
    }
    
    ...
    
    // 在打开应用 zip 后,确保他们都刷新,并进行 GC 回收
    VMRuntime.getRuntime().requestConcurrentGC();
    
    mInstaller.setWarnIfHeld(mLock);
    
    ...
}
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.