美文网首页
Android 10.0 PackageManagerServi

Android 10.0 PackageManagerServi

作者: 竖起大拇指 | 来源:发表于2020-11-02 10:53 被阅读0次

    概述

    PackageManagerService是android系统核心服务之一,在Android中非常重要,主要负责的功能如下:

    • 解析AndroidManifest.xml 主要包括AndoridManifest中节点的信息。

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

    • 管理本地apk,主要包括安装和删除等。

    启动过程

    PKMS服务由SystemServer进行启动,在SystemServer中startBootstrapServices()启动PKMS服务,在调用startOtherServices进行dex优化,磁盘管理等功能,并让PKMS进入systemReady状态。

    SystemServer.java#startBootstrapServices()

    startBootstrapServices首先启动Installer服务,也就是安装器,随后判断当前的设备是否处于加密状态,如果是则只解析核心应用,接着调用PKMS的静态方法main来创建pkms对象

     
    private void startBootstrapServices() {
        ...
            // Wait for installd to finish starting up so that it has a chance to
            // create critical directories such as /data/user with the appropriate
            // permissions.  We need this to complete before we initialize other services.
        //(1)启动Installer
        //阻塞等待installd完成启动,以便有机会创建具有适当权限的关键目录,如/data/user。
        //我们需要在初始化其他服务之前完成此任务。
        Installer installer = mSystemServiceManager.startService(Installer.class);
        mActivityManagerService.setInstaller(installer);
    
        ...
    
      // Only run "core" apps if we're encrypting the device.
        //(2)获取设别是否加密(手机设置密码),如果设备加密了,则只解析"core"应用,mOnlyCore = true,后面会频繁使用该变量进行条件判断
        String cryptState = VoldProperties.decrypt().orElse("");
        if (ENCRYPTING_STATE.equals(cryptState)) {
            Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
            mOnlyCore = true;
        } else if (ENCRYPTED_STATE.equals(cryptState)) {
            Slog.w(TAG, "Device encrypted - only parsing core apps");
            mOnlyCore = true;
        }
        
        //(3)调用main方法初始化PackageManagerService。
        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
     
        //PKMS是否是第一次启动
        mFirstBoot = mPackageManagerService.isFirstBoot();
        
        //(4)如果设备没有加密,操作它。管理A/B OTA dexopting。
        if (!mOnlyCore) {
            boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
                    false);
            OtaDexoptService.main(mSystemContext, mPackageManagerService);
        }
        ...
    }
    
    startOtherServices
    • 执行updatePackagesIfNeeded,完成dex优化
    • 执行performFstrimIfNeeded 完成磁盘维护
    • 调用systemReady 准备就绪
     
    private void startOtherServices() {
        ...
        if (!mOnlyCore) {
            ...
            //(5)如果设备没有加密,执行performDexOptUpgrade,完成dex优化;
            mPackageManagerService.updatePackagesIfNeeded();
        }
        ...
        //(6) 最终执行performFstrim,完成磁盘维护
        mPackageManagerService.performFstrimIfNeeded();
        ...
        //(7)PKMS准备就绪
        mPackageManagerService.systemReady();
        ...
    }
    
    PackageManagerService.java#main()

    main函数主要工作:

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

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

    PKMS构造函数分析

    主要有两个重要的锁(mInstallLock,mPackages)和五个阶段构成。
    mPackages:用来解析内存中所有apk的package信息以及相关状态。
    五个阶段:

    • 阶段1:BOOT_PROGRESS_PMS_START

    • 阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START

    • 阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START

    • 阶段4:BOOT_PROGRESS_PMS_SCAN_END

    • 阶段5:BOOT_PROGRESS_PMS_READY
      PKMS服务也是通过binder进行通信,IPackageManager.aidl由工具转换后自动生成binder的服务端IPackageManager.Stub和客户端IPackageManager.Stub.Proxy。

    • Binder服务端:PackageManagerService继承于IPackageManager.Stub

    • Binder客户端:ApplicationPackageManager的成员变量mPM继承于IPackageManager.Stub.Proxy;本身APM继承于PackageManager对象。

    PackageManagerService.java

    IPacakgeManager.Stub 是IPackageManager.aidl自动生成的,正好也说明PKMS是service端,通过Binder交互

    public class PackageManagerService extends IPackageManager.Stub
            implements PackageSender
    
    PackageManagerService()构造函数
    public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
            ...
            //阶段1:BOOT_PROGRESS_PMS_START
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
                    SystemClock.uptimeMillis());
     
            //阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START 
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
                        startTime);
            ...
            
            //阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START 
            if (!mOnlyCore) {
                    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                            SystemClock.uptimeMillis());
            }
            ...
            //阶段4:BOOT_PROGRESS_PMS_SCAN_END 
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
                        SystemClock.uptimeMillis());
            ...
            //阶段5:BOOT_PROGRESS_PMS_READY
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                        SystemClock.uptimeMillis());
    }
    
    阶段1:BOOT_PROGRESS_PMS_START

    主要工作:

    • 构造DisplayMetrics,保存分辨率等相关信息

    • 创建Installer对象 与InstallId交互

    • 创建mPermissionManager对象,进行权限管理

    • 构造Settings类,保存安装包信息,清除路径不存在的孤立应用,主要涉及/data/system目录下的packages.xml,package-backup.xml,packages.list,packages-stopped.xml,packages-stopped-backup.xml等文件。

    • 构造PackageDexOptimizer及DexManager类,处理dex优化;

    • 创建SystemConfig实例,获取系统配置信息,配置共享lib库

    • 创建PackageManager的handler线程,循环处理外部安装相关消息。

    public PackageManagerService(...) {
        LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES);
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
                    SystemClock.uptimeMillis());
        mContext = context;
     
        mFactoryTest = factoryTest; // 一般为false,即非工厂生产模式
        mOnlyCore = onlyCore; //标记是否只加载核心服务
        mMetrics = new DisplayMetrics(); // 分辨率配置
        mInstaller = installer; //保存installer对象
     
    // Create sub-components that provide services / data. Order here is important.
        //创建提供服务/数据的子组件。这里的顺序很重要,使用到了两个重要的同步锁:mInstallLock、mPackages
        synchronized (mInstallLock) {
        synchronized (mPackages) {
        // Expose private service for system components to use.
            // 公开系统组件使用的私有服务
            // 本地服务
            LocalServices.addService(
                    PackageManagerInternal.class, new PackageManagerInternalImpl());
            // 多用户管理服务
            sUserManager = new UserManagerService(context, this,
                    new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
            mComponentResolver = new ComponentResolver(sUserManager,
                    LocalServices.getService(PackageManagerInternal.class),
                    mPackages);
            // 权限管理服务
            mPermissionManager = PermissionManagerService.create(context,
                    mPackages /*externalLock*/);
            mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();
            
            //创建Settings对象
            mSettings = new Settings(Environment.getDataDirectory(),
                    mPermissionManager.getPermissionSettings(), mPackages);
        }
        }
        
        // 添加system, phone, log, nfc, bluetooth, shell,se,networkstack 这8种shareUserId到mSettings;
        mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.se", SE_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        mSettings.addSharedUserLPw("android.uid.networkstack", NETWORKSTACK_UID,
                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
        ...
        // DexOpt优化
        mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
                    "*dexopt*");
        mDexManager = new DexManager(mContext, this, mPackageDexOptimizer, installer, mInstallLock);
        // ART虚拟机管理服务
        mArtManagerService = new ArtManagerService(mContext, this, installer, mInstallLock);
        mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
     
        mViewCompiler = new ViewCompiler(mInstallLock, mInstaller);
        // 权限变化监听器
        mOnPermissionChangeListeners = new OnPermissionChangeListeners(
                FgThread.get().getLooper());
        mProtectedPackages = new ProtectedPackages(mContext);
        mApexManager = new ApexManager(context);
        
        // 获取默认分辨率
        getDefaultDisplayMetrics(context, mMetrics);
        //拿到SystemConfig()的对象,其中会调用SystemConfig的readPermissions()完成权限的读取
        SystemConfig systemConfig = SystemConfig.getInstance();
        synchronized (mInstallLock) {
                // writer
                synchronized (mPackages) {
                    // 启动"PackageManager"线程,负责apk的安装、卸载
                    mHandlerThread = new ServiceThread(TAG,
                            Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
                    mHandlerThread.start();
                    // 应用handler
                    mHandler = new PackageHandler(mHandlerThread.getLooper());
                    // 进程记录handler
                    mProcessLoggingHandler = new ProcessLoggingHandler();
                    // Watchdog监听ServiceThread是否超时:10分钟
                    Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
                    // Instant应用注册
                    mInstantAppRegistry = new InstantAppRegistry(this);
                     // 共享lib库配置
                    ArrayMap<String, SystemConfig.SharedLibraryEntry> libConfig
                            = systemConfig.getSharedLibraries();
                    final int builtInLibCount = libConfig.size();
                    for (int i = 0; i < builtInLibCount; i++) {
                        String name = libConfig.keyAt(i);
                        SystemConfig.SharedLibraryEntry entry = libConfig.valueAt(i);
                        addBuiltInSharedLibraryLocked(entry.filename, name);
                    }
                    ...
                    // 读取安装相关SELinux策略
                    SELinuxMMAC.readInstallPolicy();
     
                    // 返回栈加载
                    FallbackCategoryProvider.loadFallbacks();
                    //读取并解析/data/system下的XML文件
                    mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
     
                    // 清理代码路径不存在的孤立软件包
                    final int packageSettingCount = mSettings.mPackages.size();
                    for (int i = packageSettingCount - 1; i >= 0; i--) {
                        PackageSetting ps = mSettings.mPackages.valueAt(i);
                        if (!isExternal(ps) && (ps.codePath == null || !ps.codePath.exists())
                                && mSettings.getDisabledSystemPkgLPr(ps.name) != null) {
                            mSettings.mPackages.removeAt(i);
                            mSettings.enableSystemPackageLPw(ps.name);
                        }
                    }
     
                    // 如果不是首次启动,也不是CORE应用,则拷贝预编译的DEX文件
                    if (!mOnlyCore && mFirstBoot) {
                        requestCopyPreoptedFiles();
                    }
                    ...
                } // synchronized (mPackages)
            }
    }
    

    readLPW()会扫描下面5个文件

    1. /data/system/packages.xml
    2. /data/system/packages-backup.xml
    3. /data/system/packages.list
    4. /data/system/packages-stopped.xml
    5. /data/system/packages-stopped-backup.xml

    文件共分为三组,简单的作用描述如下:

    • packages.xml:PKMS 扫描完目标文件夹后会创建该文件。当系统进行程序安装、卸载和更新等操作时,均会更新该文件。该文件保存了系统中与 package 相关的一些信息。

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

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

    这些目录的指向,都在Settings中的构造函数完成, 如下所示,得到目录后调用readLPw()进行扫描

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

    解析上面这几个xml的文件内容,建立对应的数据结构

    [Settings.java]
    boolean readLPw(@NonNull List<UserInfo> users) {
        FileInputStream str = null;
        ...
        if (str == null) {
            str = new FileInputStream(mSettingsFilename);
        }
        //解析"/data/system/packages.xml"
        XmlPullParser parser = Xml.newPullParser();
        parser.setInput(str, StandardCharsets.UTF_8.name());
     
        int type;
        while ((type = parser.next()) != XmlPullParser.START_TAG
                && type != XmlPullParser.END_DOCUMENT) {
            ;
        }
        int outerDepth = parser.getDepth();
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
                continue;
            }
            //根据XML的各个节点进行各种操作,例如读取权限、shared-user等
            String tagName = parser.getName();
            if (tagName.equals("package")) {
                readPackageLPw(parser);
            } else if (tagName.equals("permissions")) {
                mPermissions.readPermissions(parser);
            } else if (tagName.equals("permission-trees")) {
                mPermissions.readPermissionTrees(parser);
            } else if (tagName.equals("shared-user")) {
                readSharedUserLPw(parser);
            }...
        }
        str.close();
        ...
        return true;
    }
    
    

    创建SharedUserSetting对象并添加到Settings的成员变量mSharedUsers中,在Android系统中,多个package通过设置shareUserid属性可以运行在同一进程,共享同一个UID。

    mSettings.addSharedUserLPw("android.uid.system", //字符串
                               Process.SYSTEM_UID, //系统进程使用的用户id,值为1000
                               ApplicationInfo.FLAG_SYSTEM, //标志系统 Package
                               ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); //特权系统应用
     
    SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
        //mSharedUsers 是一个 HashMap,key 为字符串,值为 SharedUserSetting 对象
        SharedUserSetting s = mSharedUsers.get(name);
        if (s != null) {
            if (s.userId == uid) {
                return s;
            }
            PackageManagerService.reportSettingsProblem(Log.ERROR,
                    "Adding duplicate shared user, keeping first: " + name);
            return null;
        }
        //创建一个新的 SharedUserSetting 对象,并设置的 userId 为 uid
        s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
        s.userId = uid;
        if (registerExistingAppIdLPw(uid, s, name)) {
            mSharedUsers.put(name, s);//将name与s键值对添加到mSharedUsers中保存
            return s;
        }
        return null;
    }
    
    阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START

    主要工作:

    • 从init.rc中获取环境变量BOOTCLASSPATH和SYSTEMSERVERCLASSPATH;
    • 对于旧版本升级的情况,将安装时获取权限变更为运行时申请权限
    • 扫描system/vendor/product/odem/oem 等目录的priv-app ,app ,overlay包
    • 清除安装时临时文件以及其他不必要的信息。
    public PackageManagerService(Context context, Installer installer,
                boolean factoryTest, boolean onlyCore) {
        synchronized (mInstallLock) {
            synchronized (mPackages) {
                // 记录扫描开始时间
                long startTime = SystemClock.uptimeMillis();
                EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
                        startTime);
                
                //获取环境变量,init.rc
                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();
                // 判断fingerprint是否有更新
                mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
                ...
                // 对于Android M之前版本升级上来的情况,需将系统应用程序权限从安装升级到运行时
                mPromoteSystemApps =
                        mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;
                // 对于Android N之前版本升级上来的情况,需像首次启动一样处理package
                mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;
                mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;
                mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q;
                // 在扫描之前保存预先存在的系统package的名称,不希望自动为新系统应用授予运行时权限
                if (mPromoteSystemApps) {
                    Iterator<PackageSetting> pkgSettingIter = mSettings.mPackages.values().iterator();
                    while (pkgSettingIter.hasNext()) {
                        PackageSetting ps = pkgSettingIter.next();
                        if (isSystemApp(ps)) {
                            mExistingSystemPackages.add(ps.name);
                        }
                    }
                }
                // 准备解析package的缓存
                mCacheDir = preparePackageParserCache();
                // 设置flag,而不在扫描安装时更改文件路径
                int scanFlags = SCAN_BOOTING | SCAN_INITIAL;
                ...
                //扫描以下路径:
                /vendor/overlay、/product/overlay、/product_services/overlay、/odm/overlay、/oem/overlay、/system/framework
                /system/priv-app、/system/app、/vendor/priv-app、/vendor/app、/odm/priv-app、/odm/app、/oem/app、/oem/priv-app、
                /product/priv-app、/product/app、/product_services/priv-app、/product_services/app、/product_services/priv-app
        
                scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),...);
                scanDirTracedLI(new File(PRODUCT_OVERLAY_DIR),...);
                scanDirTracedLI(new File(PRODUCT_SERVICES_OVERLAY_DIR),...);
                scanDirTracedLI(new File(ODM_OVERLAY_DIR),...);
                scanDirTracedLI(new File(OEM_OVERLAY_DIR),...);
                ...
                final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
                final List<String> stubSystemApps = new ArrayList<>();
                // 删掉不存在的package
                if (!mOnlyCore) {
                    final Iterator<PackageParser.Package> pkgIterator = mPackages.values().iterator();
                    while (pkgIterator.hasNext()) {
                        final PackageParser.Package pkg = pkgIterator.next();
                        if (pkg.isStub) {
                            stubSystemApps.add(pkg.packageName);
                        }
                    }
                    final Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
                    while (psit.hasNext()) {
                        PackageSetting ps = psit.next();
                        // 如果不是系统应用,则不被允许disable
                        if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                            continue;
                        }
                        
                        // 如果应用被扫描,则不允许被擦除
                        final PackageParser.Package scannedPkg = mPackages.get(ps.name);
                        if (scannedPkg != null) {
                            // 如果系统应用被扫描且存在disable应用列表中,则只能通过OTA升级添加
                            if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
                                ...
                                removePackageLI(scannedPkg, true);
                                mExpectingBetter.put(ps.name, ps.codePath);
                            }
                            continue;
                        }
                        ...
                    }
                }
                // 删除临时文件
                deleteTempPackageFiles();
                // 删除没有关联应用的共享UID标识
                mSettings.pruneSharedUsersLPw();
                ...
            }
            ...
        }
        ...
    }
    

    说明下:[system/app/与system/priv-app/的区别] 在system/priv-app目录主要是存放手机厂商定制的系统的系统级应用,比如phone app,settings app,systemui app等,这些应用需要系统及权限,而又不能被用户卸载掉。这个目录是在Android KitKat新增加的分区。在KitKat之前版本在系统分区的所有apks都可以使用系统权限,这个更改使手机厂商能够更好的控制捆绑软件对敏感权限的访问。手机厂商在定制一些系统软件的时候软件也会需要专门给priv-app添加selinux policy。当然应用需要获取系统权限还有其他的办法,在AndroidManifest.xml文件中添加 android:sharedUserId="android.uid.sysytem",同时给该apk添加系统签名,比如小米手机就需要给apk添加小米的系统权限。

    阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START

    主要工作:解析核心应用,处理data目录下的应用信息,更新,删除不必要的数据。

    public PackageManagerService(Context context, Installer installer,
                boolean factoryTest, boolean onlyCore) {
        synchronized (mInstallLock) {
            synchronized (mPackages) {
                ...
                if (!mOnlyCore) {
                    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                            SystemClock.uptimeMillis());
                    //扫描/data/app 目录
                    scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
                    ...
                     // Remove disable package settings for updated system apps that were
                    // removed via an OTA. If the update is no longer present, remove the
                    // app completely. Otherwise, revoke their system privileges.
                    // 移除通过OTA删除的更新系统应用程序的禁用package设置
                    // 如果更新不再存在,则完全删除该应用。否则,撤消其系统权限
                    for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) {
                        final String packageName = possiblyDeletedUpdatedSystemApps.get(i);
                        final PackageParser.Package pkg = mPackages.get(packageName);
                        final String msg;
     
                         // remove from the disabled system list; do this first so any future
                        // scans of this package are performed without this state
                          mSettings.removeDisabledSystemPackageLPw(packageName);
                        ...
                    }
          
    
    /*   Make sure all system apps that we expected to appear on the userdata partition actually showed up. If they never
                      appeared, crawl back and revive the system version.
                     */
                    // 确保期望在userdata分区上显示的所有系统应用程序实际显示
                    // 如果从未出现过,需要回滚以恢复系统版本
                    for (int i = 0; i < mExpectingBetter.size(); i++) {
                        final String packageName = mExpectingBetter.keyAt(i);
                        if (!mPackages.containsKey(packageName)) {
                            final File scanFile = mExpectingBetter.valueAt(i);
                            ...
                            mSettings.enableSystemPackageLPw(packageName);
                            try {
                                  //扫描APK
                                scanPackageTracedLI(scanFile, reparseFlags, rescanFlags, 0, null);
                            } catch (PackageManagerException e) {
                                Slog.e(TAG, "Failed to parse original system package: "
                                        + e.getMessage());
                            }
                        }
                    }
                     // Uncompress and install any stubbed system applications.
                    // This must be done last to ensure all stubs are replaced or disabled.
                    // 解压缩并安装任何存根系统应用程序。必须最后执行此操作以确保替换或禁用所有存根
                    installSystemStubPackages(stubSystemApps, scanFlags);
                    ...
                    // 获取storage manager包名
                    mStorageManagerPackage = getStorageManagerPackageName();
    
                   // Resolve protected action filters. Only the setup wizard is allowed to
                // have a high priority filter for these actions.
                    // 解决受保护的action过滤器。只允许setup wizard(开机向导)为这些action设置高优先级过滤器
                    mSetupWizardPackage = getSetupWizardPackageName();
                    ...
    
                 // Now that we know all of the shared libraries, update all clients to have
                // the correct library paths.
                    // 更新客户端以确保持有正确的共享库路径
                    updateAllSharedLibrariesLocked(null, Collections.unmodifiableMap(mPackages));
                    ...
                    // 读取并更新要保留的package的上次使用时间
                    mPackageUsage.read(mPackages);
                    mCompilerStats.read();
                }
            }
        }
    }
    
    阶段四:BOOT_PROGRESS_PMS_SCAN_END

    主要工作:

    • sdk版本变更,更新权限
    • OTA升级后首次启动,清除不必要的缓存数据
    • 权限等默认更新后,清理相关数据
    • 更新package.xml
     
    public PackageManagerService(Context context, Installer installer,
                boolean factoryTest, boolean onlyCore) {
        synchronized (mInstallLock) {
            synchronized (mPackages) {
                ...
                EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
                        SystemClock.uptimeMillis());
                // If the platform SDK has changed since the last time we booted,
                // we need to re-grant app permission to catch any new ones that
                // appear.  This is really a hack, and means that apps can in some
                // cases get permissions that the user didn't initially explicitly
                // allow...  it would be nice to have some better way to handle
                // this situation.
                // 如果自上次启动以来,平台SDK已改变,则需要重新授予应用程序权限以捕获出现的任何新权限
                final boolean sdkUpdated = (ver.sdkVersion != mSdkVersion);
                mPermissionManager.updateAllPermissions(
                        StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated, mPackages.values(),
                        mPermissionCallback);
                ...
    
                // If this is the first boot or an update from pre-M, and it is a normal
                // boot, then we need to initialize the default preferred apps across
                // all defined users.
                // 如果这是第一次启动或来自Android M之前的版本的升级,并且它是正常启动,那需要在所有已定义的用户中初始化默认的首选应用程序
                if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) {
                    for (UserInfo user : sUserManager.getUsers(true)) {
                        mSettings.applyDefaultPreferredAppsLPw(user.id);
                        primeDomainVerificationsLPw(user.id);
                    }
                }
    
    
                // Prepare storage for system user really early during boot,
                // since core system apps like SettingsProvider and SystemUI
                // can't wait for user to start
                // 在启动期间为系统用户准备存储,因为像SettingsProvider和SystemUI这样的核心系统应用程序无法等待用户启动
                final int storageFlags;
                if (StorageManager.isFileEncryptedNativeOrEmulated()) {
                    storageFlags = StorageManager.FLAG_STORAGE_DE;
                } else {
                    storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
                }
                ...
    
    
                 // If this is first boot after an OTA, and a normal boot, then
                // we need to clear code cache directories.
                // Note that we do *not* clear the application profiles. These remain valid
                // across OTAs and are used to drive profile verification (post OTA) and
                // profile compilation (without waiting to collect a fresh set of profiles).
                // 如果是在OTA之后首次启动,并且正常启动,那需要清除代码缓存目录,但不清除应用程序配置文件
                if (mIsUpgrade && !onlyCore) {
                    Slog.i(TAG, "Build fingerprint changed; clearing code caches");
                    for (int i = 0; i < mSettings.mPackages.size(); i++) {
                        final PackageSetting ps = mSettings.mPackages.valueAt(i);
                        if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
                            // No apps are running this early, so no need to freeze
                            clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
                                    FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
                                            | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
                        }
                    }
                    ver.fingerprint = Build.FINGERPRINT;
                }
                
                 // Grandfather existing (installed before Q) non-system apps to hide
                // their icons in launcher.
                //安装Android-Q前的非系统应用程序在Launcher中隐藏他们的图标
                if (!onlyCore && mIsPreQUpgrade) {
                    Slog.i(TAG, "Whitelisting all existing apps to hide their icons");
                    int size = mSettings.mPackages.size();
                    for (int i = 0; i < size; i++) {
                        final PackageSetting ps = mSettings.mPackages.valueAt(i);
                        if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                            continue;
                        }
                        ps.disableComponentLPw(PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME,
                                UserHandle.USER_SYSTEM);
                    }
                }
     
                // clear only after permissions and other defaults have been updated
                // 仅在权限或其它默认配置更新后清除
                mExistingSystemPackages.clear();
                mPromoteSystemApps = false;
                ...
              
                 // All the changes are done during package scanning.
                 // 所有变更均在扫描过程中完成
                ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;
    
                  // can downgrade to reader
                //降级去读取
                mSettings.writeLPr();
            }
        }
    }
    
    阶段五:BOOT_PROGRESS_PMS_READY

    主要工作有:

    • 创建PackageInstallerService对
    • GC回收内存
     
    public PackageManagerService(Context context, Installer installer,
                boolean factoryTest, boolean onlyCore) {
        synchronized (mInstallLock) {
            synchronized (mPackages) {
                ...
                EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                        SystemClock.uptimeMillis());
                ...
    
                // PermissionController hosts default permission granting and role management, so it's a critical part of the core system.
    
                //PermissionController 持有默认的权限授予和角色管理,所以这是核心系统的一个关键部分。
                mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr();
                ...
                updateInstantAppInstallerLocked(null);
    
                // Read and update the usage of dex files.
                // Do this at the end of PM init so that all the packages have their data directory reconciled.
                // At this point we know the code paths of the packages, so we can validate
                // the disk file and build the internal cache.
                // The usage file is expected to be small so loading and verifying it should take a fairly small time compare to the other activities (e.g. package scanning).
                // 阅读并更新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) {
                    MetricsLogger.histogram(null, "ota_package_manager_init_time",
                            (int) (SystemClock.uptimeMillis() - startTime));
                }
            }
        }
        ...
    
         // Now after opening every single application zip, make sure they are all flushed.  Not really needed, but keeps things nice and  tidy.
        // 打开应用之后,及时回收处理
        Runtime.getRuntime().gc();
    
              // The initial scanning above does many calls into installd while
            // holding the mPackages lock, but we're mostly interested in yelling
            // once we have a booted system.
            // 上面的初始扫描在持有mPackage锁的同时对installd进行了多次调用
        mInstaller.setWarnIfHeld(mPackages);
        ...
    }
    

    DEX优化

    检查是否需要去更新Packages并进行dex优化,如果没有OTA升级,没有大版本升级,没有清除dalvik虚拟机缓存,可以去更新packages。最终调用的是Installer的dexopt进行优化

    PKMS.java#updatePackagesIfNeeded()

    更新packages的优先级:core app> system app > other app,调用performDexOptUpgrade()进行系统更新

    public void updatePackagesIfNeeded() {
         //只有system或是root用户才有权限请求 package update
        enforceSystemOrRoot("Only the system can request package update");
     
        //(1)判断有没有进行OTA升级,我们需要在OTA后重新提取。
        boolean causeUpgrade = isDeviceUpgrading();
     
        //(2)是否是第一次启动或是系统大版本升级
        boolean causeFirstBoot = isFirstBoot() || mIsPreNUpgrade;
     
        // We need to re-extract after a pruned cache, as AoT-ed files will be out of date.
        //(3)判断是否有清除过dalvik虚拟机的缓存
        boolean causePrunedCache = VMRuntime.didPruneDalvikCache();
     
        //(4)如果上面的三个都没有,那么就不进行任何操作
        if (!causeUpgrade && !causeFirstBoot && !causePrunedCache) {
            return;
        }
     
        List<PackageParser.Package> pkgs;
        synchronized (mPackages) {
            //(5)按照package的优先级进行排序,core app >system app > other app
            pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this);
        }
     
        final long startTime = System.nanoTime(); //记录开始时间
        
        //进行dex优化,
        final int[] stats = performDexOptUpgrade(pkgs, mIsPreNUpgrade /* showDialog */,
                    causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT,
                    false /* bootComplete */);
        ...
    }
    
    PackageManagerService.java#performDexOptUpgrade()

    判断是否需要对package进行更新,如果需要那么更新会按照优先级完成dex优化,最终调用Install的dexopt进行dex优化。

     
    private int[] performDexOptUpgrade(List<PackageParser.Package> pkgs, boolean showDialog,
            final int compilationReason, boolean bootComplete) {
        ...
        //循环取出packages,进行优化
        for (PackageParser.Package pkg : pkgs) {
            numberOfPackagesVisited++;
     
            boolean useProfileForDexopt = false;
     
            //第一次启动或是ota升级之后并且是系统应用才会进行odex
            if ((isFirstBoot() || isDeviceUpgrading()) && isSystemApp(pkg)) {
                ...
            }
            ...
            //最终是调用 mInstaller.dexopt 完成优化的,installd守护进程,installer安装器和Installd通信
            int primaryDexOptStaus = performDexOptTraced(new DexoptOptions(
                    pkg.packageName,
                    pkgCompilationReason,
                    dexoptFlags));
     
            switch (primaryDexOptStaus) {
                case PackageDexOptimizer.DEX_OPT_PERFORMED:
                    numberOfPackagesOptimized++; //odex优化完成的应用
                    break;
                case PackageDexOptimizer.DEX_OPT_SKIPPED:
                    numberOfPackagesSkipped++; //跳过的应用
                    break;
                case PackageDexOptimizer.DEX_OPT_FAILED:
                    numberOfPackagesFailed++; //失败的应用
                    break;
                default:
                    Log.e(TAG, "Unexpected dexopt return code " + primaryDexOptStaus);
                    break;
            }
        }
        return new int[] { numberOfPackagesOptimized, numberOfPackagesSkipped,
                numberOfPackagesFailed };
    }
    

    磁盘维护

    磁盘维护最终调用的是vold进行的fstrim进行清理操作

    PackageManagerService.java#performFstrimIfNeeded()

    主要执行磁盘清理工作,释放磁盘空间

    public void performFstrimIfNeeded() {
       //只有system或是root用户才有权限请求fstrim
       enforceSystemOrRoot("Only the system can request fstrim");
     
    // Before everything else, see whether we need to fstrim.
       //在其他事情之前,看看我们是否需要fstrim
       try {
            //获取StorageManager对象
           IStorageManager sm = PackageHelper.getStorageManager();
           if (sm != null) {
               boolean doTrim = false;
               //获取执行FTRIM间隔,默认是3天,可以通过setting provider更改这个时间
               long interval = android.provider.Settings.Global.getLong(
                       mContext.getContentResolver(),
                       android.provider.Settings.Global.FSTRIM_MANDATORY_INTERVAL,
                       DEFAULT_MANDATORY_FSTRIM_INTERVAL);
     
               if (interval > 0) {
                   final long timeSinceLast = System.currentTimeMillis() - sm.lastMaintenance();
                   if (timeSinceLast > interval) {
                       doTrim = true; //如果超过了三天就进行磁盘清理
                       Slog.w(TAG, "No disk maintenance in " + timeSinceLast
                               + "; running immediately");
                   }
               }
               if (doTrim) {
                   final boolean dexOptDialogShown;
                   synchronized (mPackages) {
                       dexOptDialogShown = mDexOptDialogShown;
                   }
                   //如果不是第一次启动,显示一个提示框
                   if (!isFirstBoot() && dexOptDialogShown) {
                       try {
                           ActivityManager.getService().showBootMessage(
                                   mContext.getResources().getString(
                                           R.string.android_upgrading_fstrim), true);
                       } catch (RemoteException e) {
                       }
                   }
                   // 这里的sm是 StorageManagerService,发送消息H_FSTRIM给handler,然后再向vold发送fstrim命
                   sm.runMaintenance();
               }
           } else {
               Slog.e(TAG, "storageManager service unavailable!");
           }
       } catch (RemoteException e) {
           // Can't happen; StorageManagerService is local
       }
    }
    

    PKMS准备就绪

    PackageManagerService.java#systemReady()

    systemReady主要完成默认授权和更新package的信息,通知等待pms的一些组件。

     
    public void systemReady() {
        //只有system或是root用户才有权限 声称system已经ready
        enforceSystemOrRoot("Only the system can claim the system is ready");
     
        ContentObserver co = new ContentObserver(mHandler) {
            ...
        };
        co.onChange(true); //注册一个监听
        ...
        synchronized (mPackages) {
     
            ArrayList<PreferredActivity> removed = new ArrayList<>();
            for (int i=0; i<mSettings.mPreferredActivities.size(); i++) {
                PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
                removed.clear();
                for (PreferredActivity pa : pir.filterSet()) {
                    if (!mComponentResolver.isActivityDefined(pa.mPref.mComponent)) {
                        removed.add(pa);
                    }
                }//移除不存在的先前用户设置保存的优先选择的activity组件
                if (removed.size() > 0) {
                    for (int r=0; r<removed.size(); r++) {
                        PreferredActivity pa = removed.get(r);
                        Slog.w(TAG, "Removing dangling preferred activity: "
                                + pa.mPref.mComponent);
                        pir.removeFilter(pa);
                    }
                    mSettings.writePackageRestrictionsLPr(
                            mSettings.mPreferredActivities.keyAt(i)); //写入到文件中
                }
            }
     
            for (int userId : UserManagerService.getInstance().getUserIds()) {
                if (!mSettings.areDefaultRuntimePermissionsGrantedLPr(userId)) {
                    grantPermissionsUserIds = ArrayUtils.appendInt(
                            grantPermissionsUserIds, userId);
                }
            }
        }
     
        sUserManager.systemReady(); //多用户服务 systemReady
        //升级所有已获取的默认权限
        for (int userId : grantPermissionsUserIds) {
            mDefaultPermissionPolicy.grantDefaultPermissions(userId); //默认授权操作
        }
        ...
     
        // Now that we've scanned all packages, and granted any default
        // permissions, ensure permissions are updated. Beware of dragons if you
        // try optimizing this.
        synchronized (mPackages) {
            mPermissionManager.updateAllPermissions(
                    StorageManager.UUID_PRIVATE_INTERNAL, false, mPackages.values(),
                    mPermissionCallback); //更新权限信息
            ...
            });
        }
     
        //注意随时间变化的外部存储设备
        final StorageManager storage = mContext.getSystemService(StorageManager.class);
        storage.registerListener(mStorageListener);
     
        mInstallerService.systemReady();
        mApexManager.systemReady();
        mPackageDexOptimizer.systemReady();
        ...
    
     // Now that we're mostly running, clean up stale users and apps
        //清除过期的userid和app
        sUserManager.reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);
        reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL);
     
        mPermissionManager.systemReady();
     
        if (mInstantAppResolverConnection != null) {
            mContext.registerReceiver(new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    mInstantAppResolverConnection.optimisticBind();
                    mContext.unregisterReceiver(this);
                }
            }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
        }
     
        if (!isFirstBoot()) {
            Slog.i(TAG, "enablePackageStoppedPolicy");
            synchronized (mPackages) {
                PackageManagerServiceUtilsZTE.enablePackageStoppedPolicy(mPackages.values(), this);
            }
        }
     
        mModuleInfoProvider.systemReady();
     
        // Installer service might attempt to install some packages that have been staged for
        // installation on reboot. Make sure this is the last component to be call since the
        // installation might require other components to be ready.
        mInstallerService.restoreAndApplyStagedSessionIfNeeded();
     
        //update partner app
        new Thread(() -> {
            updatePartnerAppInFota();
        }).start();
    }
    

    大概流程就是这样,完。

    相关文章

      网友评论

          本文标题:Android 10.0 PackageManagerServi

          本文链接:https://www.haomeiwen.com/subject/bsudvktx.html