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);
    
    ...
}
加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。