Jimmy Chen

A Programmer

(原创)PackageManagerService启动流程分析(上)

略久没有写自己写博客了,现在要重新抓起来。最近对Android Framework的内容感兴趣,所以接下来可能会阅读下Framework部分的代码,Android系统部分的代码有机会也会分析分析。今天就先来看看PackageManager和PackageManagerService好了。

一. 简述

  PackageManagerService(PKMS)和PackageManger(PKM)的关系如下图,PKMS是Android系统中核心服务之一,负责package的相关工作,例如安装,卸载以及查询等。

《(原创)PackageManagerService启动流程分析(上)》

  根据博主之前关于Binder部分的博客和上面的图片可以看出,PackageManger继承于IPackageManager.Stub.Porxy,而PackageManagerService则继承于IPackageManager.Stub。相关的父类则是有IPackageManager.aidl编译生成。下面来看PackageManagerService的启动过程。

二. Android启动过程中PKMS所完成的动作

  在之前讲述Android启动流程时有提到,在启动Android过程中会先启动一些重要的service,这里面就包括PKMS,下面我们来看看PKMS启动的代码。

private void startBootstrapServices() {
    ...............
    // 启动Installer
    traceBeginAndSlog("StartInstaller");
    Installer installer = mSystemServiceManager.startService(Installer.class);
    traceEnd();
    ............
    // 下面的代码判断是否只启动系统的核心进程,只在加密data的时候才会将mOnlyCore设置为true
    String cryptState = SystemProperties.get("vold.decrypt");
    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;
    }
    
    ....................
    traceBeginAndSlog("StartPackageManagerService");
    // 初始化PKMS
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
            mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    // 判断PKMS是否是第一次启动
    mFirstBoot = mPackageManagerService.isFirstBoot();
    // 获取PackageManager
    mPackageManager = mSystemContext.getPackageManager();
    traceEnd();
    ..............
}

private void startOtherServices() {
    ...............
    // 如果是首次开机或者升级的话,判断是否需要对Packages的信息进行更新
    if (!mOnlyCore) {
        traceBeginAndSlog("UpdatePackagesIfNeeded");
        try {
            mPackageManagerService.updatePackagesIfNeeded();
        } catch (Throwable e) {
            reportWtf("update packages", e);
        }
        traceEnd();
    }
    
    // 执行类似磁盘STRIM的技术
    traceBeginAndSlog("PerformFstrimIfNeeded");
    try {
        mPackageManagerService.performFstrimIfNeeded();
    } catch (Throwable e) {
        reportWtf("performing fstrim", e);
    }
    traceEnd();
    .............
    // 执行PKMS的systemReady,通知系统进入就绪状态
    traceBeginAndSlog("MakePackageManagerServiceReady");
    try {
        mPackageManagerService.systemReady();
    } catch (Throwable e) {
        reportWtf("making Package Manager Service ready", e);
    }
    traceEnd();
    ..............
    // Wait for all packages to be prepared
    // 等待所有的Packages准备就绪
    mPackageManagerService.waitForAppDataPrepared();
}

  从上面的代码总结Android启动过程,PKMS所执行的主要操作如下:

  • PackageManagerService.main
  • mPackageManagerService.updatePackagesIfNeeded
  • mPackageManagerService.performFstrimIfNeeded
  • mPackageManagerService.systemReady
  • mPackageManagerService.waitForAppDataPrepared

所以按照上面的执行过程一步一步看代码分析。

2.1 PackageManagerService.main

public static PackageManagerService main(Context context, Installer installer,
        boolean factoryTest, boolean onlyCore) {
    // 检查一些系统属性,貌似和编译相关,这里暂时不分析
    PackageManagerServiceCompilerMapping.checkProperties();

    // 重点分析的对象,调用PackageManagerService的构造函数
    PackageManagerService m = new PackageManagerService(context, installer,
            factoryTest, onlyCore);
    // enable系统用户的APP
    m.enableSystemUserPackages();
    // 将PackageManagerService添加到ServiceManager中,service名为package
    ServiceManager.addService("package", m);
    final PackageManagerNative pmn = m.new PackageManagerNative();
    // 添加package_native service到ServiceManager
    ServiceManager.addService("package_native", pmn);
    return m;
}

  main方法的主要动作就是调用PackageManagerService的构造函数,进行初始化并将其添加到ServiceManager中

PackageManagerService构造函数

  PackageManagerService的构造函数可以分成5个阶段进行分析,分阶段的过程主要是按照写EventLog的时间进行区分。PKMS的构造函数

  • EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,SystemClock.uptimeMillis());
  • EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,startTime);
  • EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,SystemClock.uptimeMillis());
  • EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,SystemClock.uptimeMillis());
  • EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,SystemClock.uptimeMillis());

2.1.1. BOOT_PROGRESS_PMS_START

public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
    ..............
    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
            SystemClock.uptimeMillis());

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

    mContext = context;

    mPermissionReviewRequired = context.getResources().getBoolean(
            R.bool.config_permissionReviewRequired);

    mFactoryTest = factoryTest;
    mOnlyCore = onlyCore;
    // 创建DisplayMetrics获取显示屏相关信息
    mMetrics = new DisplayMetrics();
    // 创建settings对象,下面解析该对象
    mSettings = new Settings(mPackages);
    // 将一些shared uid添加到settings对象中
    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);

    ...............

    mInstaller = installer;
    // 初始化一些对象
    mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
            "*dexopt*");
    mDexManager = new DexManager(this, mPackageDexOptimizer, installer, mInstallLock);
    mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());

    mOnPermissionChangeListeners = new OnPermissionChangeListeners(
            FgThread.get().getLooper());

    getDefaultDisplayMetrics(context, mMetrics);

    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "get system config");
    // 获取系统的配置信息,后面会解析
    SystemConfig systemConfig = SystemConfig.getInstance();
    mGlobalGids = systemConfig.getGlobalGids();
    mSystemPermissions = systemConfig.getSystemPermissions();
    mAvailableFeatures = systemConfig.getAvailableFeatures();
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

    mProtectedPackages = new ProtectedPackages(mContext);

    synchronized (mInstallLock) {
    // writer
    synchronized (mPackages) {
        // 创建名为“PackageManager”的handler线程
        mHandlerThread = new ServiceThread(TAG,
                Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
        mHandlerThread.start();
        mHandler = new PackageHandler(mHandlerThread.getLooper());
        mProcessLoggingHandler = new ProcessLoggingHandler();
        Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);

        mDefaultPermissionPolicy = new DefaultPermissionGrantPolicy(this);
        mInstantAppRegistry = new InstantAppRegistry(this);
        
        // 创建/data下的各个目录
        File dataDir = Environment.getDataDirectory();
        mAppInstallDir = new File(dataDir, "app");
        mAppLib32InstallDir = new File(dataDir, "app-lib");
        mAsecInternalPath = new File(dataDir, "app-asec").getPath();
        mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
        mRegionalizationAppInstallDir = new File(dataDir, "app-regional");
        sUserManager = new UserManagerService(context, this,
                new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);

        // 将系统配置的permission添加到settings中
        ArrayMap<String, SystemConfig.PermissionEntry> permConfig
                = systemConfig.getPermissions();
        for (int i=0; i < permConfig.size(); i++) {
            SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
            BasePermission bp = mSettings.mPermissions.get(perm.name);
            if (bp == null) {
                bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);
                mSettings.mPermissions.put(perm.name, bp);
            }
            if (perm.gids != null) {
                bp.setGids(perm.gids, perm.perUser);
            }
        }

        // 配置共享库
        ArrayMap<String, String> libConfig = systemConfig.getSharedLibraries();
        final int builtInLibCount = libConfig.size();
        for (int i = 0; i < builtInLibCount; i++) {
            String name = libConfig.keyAt(i);
            String path = libConfig.valueAt(i);
            addSharedLibraryLPw(path, null, name, SharedLibraryInfo.VERSION_UNDEFINED,
                    SharedLibraryInfo.TYPE_BUILTIN, PLATFORM_PACKAGE_NAME, 0);
        }

        // 读取SELinux所需的platform permission xml文件
        mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();

        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "read user settings");
        mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

        // 清理因系统升级而导致的孤立程序包
        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);
            }
        }

        if (mFirstBoot) {
            requestCopyPreoptedFiles();
        }

        String customResolverActivity = Resources.getSystem().getString(
                R.string.config_customResolverActivity);
        if (TextUtils.isEmpty(customResolverActivity)) {
            customResolverActivity = null;
        } else {
            mCustomResolverComponentName = ComponentName.unflattenFromString(
                    customResolverActivity);
        }

        long startTime = SystemClock.uptimeMillis();
}

  上面的内容我们主要分析其中的两部分,一是创建配置settings的对象,二是创建配置systemConfig对象。

创建settings对象

  接下来直接看settings对象创建的相关内容。

Settings(Object lock) {
    this(Environment.getDataDirectory(), lock);
}

// dataDir为/data
Settings(File dataDir, Object lock) {
    mLock = lock;

    mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);

    // 创建data/system目录
    mSystemDir = new File(dataDir, "system");
    mSystemDir.mkdirs();
    FileUtils.setPermissions(mSystemDir.toString(),
            FileUtils.S_IRWXU|FileUtils.S_IRWXG
            |FileUtils.S_IROTH|FileUtils.S_IXOTH,
            -1, -1);
    // 读取data/system下的xml文件
    mSettingsFilename = new File(mSystemDir, "packages.xml");
    mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
    mPackageListFilename = new File(mSystemDir, "packages.list");
    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
    mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
    mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
}

  上面读取的5个文件所包含的内容如下表

《(原创)PackageManagerService启动流程分析(上)》

SystemConfig对象

// SystemConfig的单例模式
public static SystemConfig getInstance() {
    synchronized (SystemConfig.class) {
        if (sInstance == null) {
            sInstance = new SystemConfig();
        }
        return sInstance;
    }
}

SystemConfig() {
    // 读取系统信息配置文件
    readPermissions(Environment.buildPath(
            Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
    readPermissions(Environment.buildPath(
            Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
    // 允许Vendor供应商配置libs、features、permissions和apps
    int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
            ALLOW_APP_CONFIGS;
    readPermissions(Environment.buildPath(
            Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
    readPermissions(Environment.buildPath(
            Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
    // 允许ODM供应商配置libs、features、permissions和apps
    int odmPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_APP_CONFIGS;
    readPermissions(Environment.buildPath(
            Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
    readPermissions(Environment.buildPath(
            Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
    // 仅允许OEM对features进行配置
    readPermissions(Environment.buildPath(
            Environment.getOemDirectory(), "etc", "sysconfig"), ALLOW_FEATURES);
    readPermissions(Environment.buildPath(
            Environment.getOemDirectory(), "etc", "permissions"), ALLOW_FEATURES);
    //Remove vulkan specific features
    if (SystemProperties.getBoolean("persist.graphics.vulkan.disable", false)) {
        removeFeature(PackageManager.FEATURE_VULKAN_HARDWARE_LEVEL);
        removeFeature(PackageManager.FEATURE_VULKAN_HARDWARE_VERSION);
    }
    // Remove android extension pack for opengles version 3.0
    int value = SystemProperties.getInt("ro.opengles.version", 0);
    if (value > 0 && (value == 196608)) {
       if (mAvailableFeatures.remove("android.hardware.opengles.aep") != null) {
           Slog.d(TAG, "Removed android.hardware.opengles.aep feature for opengles 3.0");
       }
    }
}

  readPermissions会读取对应目录下所有的xml文件,根据xml文件对应的节点对libs、features和apps等内容进行配置。查找读取的xml文件路径如下:

  • /system/etc/sysconfig
  • /system/etc/permissions
  • /vendor/etc/sysconfig
  • /vendor/etc/permissions
  • /odm/etc/sysconfig
  • /odm/etc/permissions
  • /oem/etc/sysconfig
  • /oem/etc/permissions

  readPermissions代码如下所示:

void readPermissions(File libraryDir, int permissionFlag) {
    // 判断目录存在
    if (!libraryDir.exists() || !libraryDir.isDirectory()) {
        if (permissionFlag == ALLOW_ALL) {
            Slog.w(TAG, "No directory " + libraryDir + ", skipping");
        }
        return;
    }
    // 判断目录可读
    if (!libraryDir.canRead()) {
        Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
        return;
    }

    // Iterate over the files in the directory and scan .xml files
    File platformFile = null;
    for (File f : libraryDir.listFiles()) {
        // 如果存在platform.xml先记录下来,最后再解析
        if (f.getPath().endsWith("etc/permissions/platform.xml")) {
            platformFile = f;
            continue;
        }

        // 只解析xml文件
        if (!f.getPath().endsWith(".xml")) {
            Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
            continue;
        }
        // 判断文件是否可读
        if (!f.canRead()) {
            Slog.w(TAG, "Permissions library file " + f + " cannot be read");
            continue;
        }

        // 解析该目录下所有可读取的xml文件
        readPermissionsFromXml(f, permissionFlag);
    }

    // 最后读取解析platform.xml文件
    if (platformFile != null) {
        readPermissionsFromXml(platformFile, permissionFlag);
    }
}

  上面的代码比较好理解,这里不做过多解释了。

2.1.2 BOOT_PROGRESS_PMS_SYSTEM_SCAN_START

  接下来看第二个Eventlog前的内容

    EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
            startTime);

    // 获取环境变量中BOOTCLASSPATH和SYSTEMSERVERCLASSPATH的值,这两个值可以通过adb shell env进行查看
    final String bootClassPath = System.getenv("BOOTCLASSPATH");
    final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");

    if (bootClassPath == null) {
        Slog.w(TAG, "No BOOTCLASSPATH found!");
    }

    if (systemServerClassPath == null) {
        Slog.w(TAG, "No SYSTEMSERVERCLASSPATH found!");
    }

    // frameworkDir的路径为/system/framework
    File frameworkDir = new File(Environment.getRootDirectory(), "framework");

    final VersionInfo ver = mSettings.getInternalVersion();
    mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
    if (mIsUpgrade) {
        logCriticalInfo(Log.INFO,
                "Upgrading from " + ver.fingerprint + " to " + Build.FINGERPRINT);
    }

    // 下面是从不同版本上级上来时需要做的处理
    // when upgrading from pre-M, promote system app permissions from install to runtime
    mPromoteSystemApps =
            mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;

    // When upgrading from pre-N, we need to handle package extraction like first boot,
    // as there is no profiling data available.
    mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;

    mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;

    // save off the names of pre-existing system packages prior to scanning; we don't
    // want to automatically grant runtime permissions for new system apps
    if (mPromoteSystemApps) {
        Iterator<PackageSetting> pkgSettingIter = mSettings.mPackages.values().iterator();
        while (pkgSettingIter.hasNext()) {
            PackageSetting ps = pkgSettingIter.next();
            if (isSystemApp(ps)) {
                mExistingSystemPackages.add(ps.name);
            }
        }
    }

    // 准备packages parser的cache空间
    mCacheDir = preparePackageParserCache(mIsUpgrade);

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

    if (mIsUpgrade || mFirstBoot) {
        scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
    }

    // 扫描/vendor/overlay目录下的package
    scanDirTracedLI(new File(VENDOR_OVERLAY_DIR), mDefParseFlags
            | PackageParser.PARSE_IS_SYSTEM
            | PackageParser.PARSE_IS_SYSTEM_DIR
            | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);

    // 扫描静态overlay的packages
    mParallelPackageParserCallback.findStaticOverlayPackages();

    // 扫描/system/framework目录下的package
    scanDirTracedLI(frameworkDir, mDefParseFlags
            | PackageParser.PARSE_IS_SYSTEM
            | PackageParser.PARSE_IS_SYSTEM_DIR
            | PackageParser.PARSE_IS_PRIVILEGED,
            scanFlags | SCAN_NO_DEX, 0);

    // 扫描/system/priv-app目录下的系统package
    final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
    scanDirTracedLI(privilegedAppDir, mDefParseFlags
            | PackageParser.PARSE_IS_SYSTEM
            | PackageParser.PARSE_IS_SYSTEM_DIR
            | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);

    // 扫描/system/app目录下的普通package
    final File systemAppDir = new File(Environment.getRootDirectory(), "app");
    scanDirTracedLI(systemAppDir, mDefParseFlags
            | PackageParser.PARSE_IS_SYSTEM
            | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

    // 扫描/vendor/app目录下的vendor供应商package
    File vendorAppDir = new File("/vendor/app");
    try {
        vendorAppDir = vendorAppDir.getCanonicalFile();
    } catch (IOException e) {
        // failed to look up canonical path, continue with original one
    }
    scanDirTracedLI(vendorAppDir, mDefParseFlags
            | PackageParser.PARSE_IS_SYSTEM
            | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

    // 扫描/oem/app目录下的oem制造商的package
    final File oemAppDir = new File(Environment.getOemDirectory(), "app");
    scanDirTracedLI(oemAppDir, mDefParseFlags
            | PackageParser.PARSE_IS_SYSTEM
            | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

    // 如果支持运营商/区域化,则扫描加载运营商的package
    if (RegionalizationEnvironment.isSupported()) {
        Log.d(TAG, "Load Regionalization vendor apks");
        final List<File> RegionalizationDirs =
                RegionalizationEnvironment.getAllPackageDirectories();
        for (File f : RegionalizationDirs) {
            File RegionalizationSystemDir = new File(f, "system");
            // Collect packages in <Package>/system/priv-app
            scanDirLI(new File(RegionalizationSystemDir, "priv-app"),
                    PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR
                    | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
            // Collect packages in <Package>/system/app
            scanDirLI(new File(RegionalizationSystemDir, "app"),
                    PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags, 0);
            // Collect overlay in <Package>/system/vendor
            scanDirLI(new File(RegionalizationSystemDir, "vendor/overlay"),
                    PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR
                    | PackageParser.PARSE_TRUSTED_OVERLAY,
                    scanFlags | SCAN_TRUSTED_OVERLAY, 0);
        }
    }

    // 删除不再存在的系统package
    final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
    // stub package估计只是一个小的apk,用来下载正式版的package并安装
    final List<String> stubSystemApps = new ArrayList<>();
    if (!mOnlyCore) {
        // do this first before mucking with mPackages for the "expecting better" case
        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();

            // 如果不是系统package,则可设置为disabled的,这里先跳过
            if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                continue;
            }

            /*
             * If the package is scanned, it's not erased.
             */
            final PackageParser.Package scannedPkg = mPackages.get(ps.name);
            if (scannedPkg != null) {
                /*
                 * If the system app is both scanned and in the
                 * disabled packages list, then it must have been
                 * added via OTA. Remove it from the currently
                 * scanned package so the previously user-installed
                 * application can be scanned.
                 */
                if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
                    logCriticalInfo(Log.WARN, "Expecting better updated system app for "
                            + ps.name + "; removing system app.  Last known codePath="
                            + ps.codePathString + ", installStatus=" + ps.installStatus
                            + ", versionCode=" + ps.versionCode + "; scanned versionCode="
                            + scannedPkg.mVersionCode);
                    removePackageLI(scannedPkg, true);
                    mExpectingBetter.put(ps.name, ps.codePath);
                }

                continue;
            }

            if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
                psit.remove();
                logCriticalInfo(Log.WARN, "System package " + ps.name
                        + " no longer exists; it's data will be wiped");
                // Actual deletion of code and data will be handled by later
                // reconciliation step
            } 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.codePath == null || !disabledPs.codePath.exists()
                        || disabledPs.pkg == null) {
                    possiblyDeletedUpdatedSystemApps.add(ps.name);
                }
            }
        }
    }

    // 查找那些安装不完整的package,并将其删除
    ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
    for (int i = 0; i < deletePkgsList.size(); i++) {
        // Actual deletion of code and data will be handled by later
        // reconciliation step
        final String packageName = deletePkgsList.get(i).name;
        logCriticalInfo(Log.WARN, "Cleaning up incompletely installed app: " + packageName);
        synchronized (mPackages) {
            mSettings.removePackageLPw(packageName);
        }
    }

    //删除临时package
    deleteTempPackageFiles();

    final int cachedSystemApps = PackageParser.sCachedPackageReadCount.get();

    // 删除那些没有对应package的shared uid
    mSettings.pruneSharedUsersLPw();
    final long systemScanTime = SystemClock.uptimeMillis() - startTime;
    final int systemPackagesCount = mPackages.size();
    Slog.i(TAG, "Finished scanning system apps. Time: " + systemScanTime
            + " ms, packageCount: " + systemPackagesCount
            + " , timePerPackage: "
            + (systemPackagesCount == 0 ? 0 : systemScanTime / systemPackagesCount)
            + " , cached: " + cachedSystemApps);
    if (mIsUpgrade && systemPackagesCount > 0) {
        MetricsLogger.histogram(null, "ota_package_manager_system_app_avg_scan_time",
                ((int) systemScanTime) / systemPackagesCount);
    }

  BOOTCLASSPATH和SYSTEMSERVERCLASSPATH的值可以通过adb shell env进行查看,查看的结果如下图所示:

《(原创)PackageManagerService启动流程分析(上)》

《(原创)PackageManagerService启动流程分析(上)》

scanDirTracedLI会扫描指定目录下的package,最终调用PackageParser.parseBaseApk来完成AndroidManifest.xml文件的解析,生成Application, activity,service,broadcast, provider等信息。

2.1.3 BOOT_PROGRESS_PMS_SCAN_END

    // 处理非系统package
    if (!mOnlyCore) {
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                SystemClock.uptimeMillis());
        // 扫描/data/app目录下的package
        scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);

        // 扫描/data/app-private目录下的package
        scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
                | PackageParser.PARSE_FORWARD_LOCK,
                scanFlags | SCAN_REQUIRE_KNOWN, 0);

        // 扫描运营商第三方package
        if (RegionalizationEnvironment.isSupported()) {
            Log.d(TAG, "Load Regionalization 3rd apks from res packages.");
            final List<String> packages = RegionalizationEnvironment.getAllPackageNames();
            for (String pack : packages) {
                File appFolder = new File(mRegionalizationAppInstallDir, pack);
                Log.d(TAG, "Load Regionalization 3rd apks of path " + appFolder.getPath());
                scanDirLI(appFolder, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
            }
        }

        // 删除通过OTA升级禁用的Package
        for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
            PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
            mSettings.removeDisabledSystemPackageLPw(deletedAppName);

            final String msg;
            if (deletedPkg == null) {
                // should have found an update, but, we didn't; remove everything
                msg = "Updated system package " + deletedAppName
                        + " no longer exists; removing its data";
                // Actual deletion of code and data will be handled by later
                // reconciliation step
            } else {
                // found an update; revoke system privileges
                msg = "Updated system package + " + deletedAppName
                        + " no longer exists; revoking system privileges";

                // Don't do anything if a stub is removed from the system image. If
                // we were to remove the uncompressed version from the /data partition,
                // this is where it'd be done.

                final PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
                deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
                deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
            }
            logCriticalInfo(Log.WARN, msg);
        }

        // 确保所有系统package正确显示
        for (int i = 0; i < mExpectingBetter.size(); i++) {
            final String packageName = mExpectingBetter.keyAt(i);
            if (!mPackages.containsKey(packageName)) {
                final File scanFile = mExpectingBetter.valueAt(i);

                logCriticalInfo(Log.WARN, "Expected better " + packageName
                        + " but never showed up; reverting to system");

                int reparseFlags = mDefParseFlags;
                if (FileUtils.contains(privilegedAppDir, scanFile)) {
                    reparseFlags = PackageParser.PARSE_IS_SYSTEM
                            | PackageParser.PARSE_IS_SYSTEM_DIR
                            | PackageParser.PARSE_IS_PRIVILEGED;
                } else if (FileUtils.contains(systemAppDir, scanFile)) {
                    reparseFlags = PackageParser.PARSE_IS_SYSTEM
                            | PackageParser.PARSE_IS_SYSTEM_DIR;
                } else if (FileUtils.contains(vendorAppDir, scanFile)) {
                    reparseFlags = PackageParser.PARSE_IS_SYSTEM
                            | PackageParser.PARSE_IS_SYSTEM_DIR;
                } else if (FileUtils.contains(oemAppDir, scanFile)) {
                    reparseFlags = PackageParser.PARSE_IS_SYSTEM
                            | PackageParser.PARSE_IS_SYSTEM_DIR;
                } else {
                    Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
                    continue;
                }

                mSettings.enableSystemPackageLPw(packageName);

                try {
                    scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 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.
        decompressSystemApplications(stubSystemApps, scanFlags);

        final int cachedNonSystemApps = PackageParser.sCachedPackageReadCount.get()
                        - cachedSystemApps;

        final long dataScanTime = SystemClock.uptimeMillis() - systemScanTime - startTime;
        final int dataPackagesCount = mPackages.size() - systemPackagesCount;
        Slog.i(TAG, "Finished scanning non-system apps. Time: " + dataScanTime
                + " ms, packageCount: " + dataPackagesCount
                + " , timePerPackage: "
                + (dataPackagesCount == 0 ? 0 : dataScanTime / dataPackagesCount)
                + " , cached: " + cachedNonSystemApps);
        if (mIsUpgrade && dataPackagesCount > 0) {
            MetricsLogger.histogram(null, "ota_package_manager_data_app_avg_scan_time",
                    ((int) dataScanTime) / dataPackagesCount);
        }
    }
    mExpectingBetter.clear();

    // 解析存储管理器
    mStorageManagerPackage = getStorageManagerPackageName();

    // 解析受保护action过滤,仅setupwizard拥有最高优先级处理这个过滤
    mSetupWizardPackage = getSetupWizardPackageName();
    if (mProtectedFilters.size() > 0) {
        if (DEBUG_FILTERS && mSetupWizardPackage == null) {
            Slog.i(TAG, "No setup wizard;"
                + " All protected intents capped to priority 0");
        }
        for (ActivityIntentInfo filter : mProtectedFilters) {
            if (filter.activity.info.packageName.equals(mSetupWizardPackage)) {
                if (DEBUG_FILTERS) {
                    Slog.i(TAG, "Found setup wizard;"
                        + " allow priority " + filter.getPriority() + ";"
                        + " package: " + filter.activity.info.packageName
                        + " activity: " + filter.activity.className
                        + " priority: " + filter.getPriority());
                }
                // skip setup wizard; allow it to keep the high priority filter
                continue;
            }
            if (DEBUG_FILTERS) {
                Slog.i(TAG, "Protected action; cap priority to 0;"
                        + " package: " + filter.activity.info.packageName
                        + " activity: " + filter.activity.className
                        + " origPrio: " + filter.getPriority());
            }
            filter.setPriority(0);
        }
    }
    mDeferProtectedFilters = false;
    mProtectedFilters.clear();

    // 已经获取到所有共享库的路径,这里需要为各个package更新路径
    updateAllSharedLibrariesLPw(null);

    for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
        // NOTE: We ignore potential failures here during a system scan (like
        // the rest of the commands above) because there's precious little we
        // can do about it. A settings error is reported, though.
        adjustCpuAbisForSharedUserLPw(setting.packages, null /*scannedPackage*/);
    }

    // 更新上一次使用时间
    mPackageUsage.read(mPackages);
    mCompilerStats.read();

  这里主要是更新非系统package的信息,主要处在/data/app和/data/priv-app路径下面,下面继续往下看

2.1.4 BOOT_PROGRESS_PMS_READY

    // 如果系统SDK版本有升级,这里需要让所有的apk重新获取运行时权限
    int updateFlags = UPDATE_PERMISSIONS_ALL;
    if (ver.sdkVersion != mSdkVersion) {
        Slog.i(TAG, "Platform changed from " + ver.sdkVersion + " to "
                + mSdkVersion + "; regranting permissions for internal storage");
        updateFlags |= UPDATE_PERMISSIONS_REPLACE_PKG | UPDATE_PERMISSIONS_REPLACE_ALL;
    }
    updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
    ver.sdkVersion = mSdkVersion;

    // 如果是第一次开机或者是从pre-M版本升级上来的,我们需要为用户定义某些默认使用的package
    if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) {
        for (UserInfo user : sUserManager.getUsers(true)) {
            mSettings.applyDefaultPreferredAppsLPw(this, user.id);
            applyFactoryDefaultBrowserLPw(user.id);
            primeDomainVerificationsLPw(user.id);
        }
    }

    // 为系统用户准备内存空间
    final int storageFlags;
    if (StorageManager.isFileEncryptedNativeOrEmulated()) {
        storageFlags = StorageManager.FLAG_STORAGE_DE;
    } else {
        storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
    }
    List<String> deferPackages = reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL,
            UserHandle.USER_SYSTEM, storageFlags, true /* migrateAppData */,
            true /* onlyCoreApps */);
    mPrepareAppDataFuture = SystemServerInitThreadPool.get().submit(() -> {
        TimingsTraceLog traceLog = new TimingsTraceLog("SystemServerTimingAsync",
                Trace.TRACE_TAG_PACKAGE_MANAGER);
        traceLog.traceBegin("AppDataFixup");
        try {
            mInstaller.fixupAppData(StorageManager.UUID_PRIVATE_INTERNAL,
                    StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
        } catch (InstallerException e) {
            Slog.w(TAG, "Trouble fixing GIDs", e);
        }
        traceLog.traceEnd();

        traceLog.traceBegin("AppDataPrepare");
        if (deferPackages == null || deferPackages.isEmpty()) {
            return;
        }
        int count = 0;
        for (String pkgName : deferPackages) {
            PackageParser.Package pkg = null;
            synchronized (mPackages) {
                PackageSetting ps = mSettings.getPackageLPr(pkgName);
                if (ps != null && ps.getInstalled(UserHandle.USER_SYSTEM)) {
                    pkg = ps.pkg;
                }
            }
            if (pkg != null) {
                synchronized (mInstallLock) {
                    prepareAppDataAndMigrateLIF(pkg, UserHandle.USER_SYSTEM, storageFlags,
                            true /* maybeMigrateAppData */);
                }
                count++;
            }
        }
        traceLog.traceEnd();
        Slog.i(TAG, "Deferred reconcileAppsData finished " + count + " packages");
    }, "prepareAppData");

    // 如果是OTA后第一次正常开机,我们需要清楚code cache
    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,
                        StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
                                | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
            }
        }
        ver.fingerprint = Build.FINGERPRINT;
    }

    checkDefaultBrowser();

    // //当权限和其他默认项都完成更新,则清理相关信息
    mExistingSystemPackages.clear();
    mPromoteSystemApps = false;

    // All the changes are done during package scanning.
    ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;

    // can downgrade to reader
    Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "write settings");
    // 信息写回packages.xml文件
    mSettings.writeLPr();
    Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

2.1.5 BOOT_PROGRESS_PMS_READY

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

    if (!mOnlyCore) {
        // 估计是对扫描的Package做一些校验吧,水平有限,具体情况暂时没看出来
        mRequiredVerifierPackage = getRequiredButNotReallyRequiredVerifierLPr();
        mOptionalVerifierPackage = getOptionalVerifierLPr();
        mRequiredInstallerPackage = getRequiredInstallerLPr();
        mRequiredUninstallerPackage = getRequiredUninstallerLPr();
        mIntentFilterVerifierComponent = getIntentFilterVerifierComponentNameLPr();
        if (mIntentFilterVerifierComponent != null) {
            mIntentFilterVerifier = new IntentVerifierProxy(mContext,
                    mIntentFilterVerifierComponent);
        } else {
            mIntentFilterVerifier = null;
        }
        mServicesSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
                PackageManager.SYSTEM_SHARED_LIBRARY_SERVICES,
                SharedLibraryInfo.VERSION_UNDEFINED);
        mSharedSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
                PackageManager.SYSTEM_SHARED_LIBRARY_SHARED,
                SharedLibraryInfo.VERSION_UNDEFINED);
    } else {
        mRequiredVerifierPackage = null;
        mOptionalVerifierPackage = null;
        mRequiredInstallerPackage = null;
        mRequiredUninstallerPackage = null;
        mIntentFilterVerifierComponent = null;
        mIntentFilterVerifier = null;
        mServicesSystemSharedLibraryPackageName = null;
        mSharedSystemSharedLibraryPackageName = null;
    }

    // 创建PackageInstallerService
    mInstallerService = new PackageInstallerService(context, this);
    final Pair<ComponentName, String> instantAppResolverComponent =
            getInstantAppResolverLPr();
    if (instantAppResolverComponent != null) {
        if (DEBUG_EPHEMERAL) {
            Slog.d(TAG, "Set ephemeral resolver: " + instantAppResolverComponent);
        }
        mInstantAppResolverConnection = new EphemeralResolverConnection(
                mContext, instantAppResolverComponent.first,
                instantAppResolverComponent.second);
        mInstantAppResolverSettingsComponent =
                getInstantAppResolverSettingsLPr(instantAppResolverComponent.first);
    } else {
        mInstantAppResolverConnection = null;
        mInstantAppResolverSettingsComponent = null;
    }
    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).
    final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>();
    final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
    for (int userId : currentUserIds) {
        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));
    }
} // synchronized (mPackages)
} // synchronized (mInstallLock)

// Now after opening every single application zip, make sure they
// are all flushed.  Not really needed, but keeps things nice and
// tidy.
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "GC");
Runtime.getRuntime().gc();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "loadFallbacks");
FallbackCategoryProvider.loadFallbacks();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

// 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.
mInstaller.setWarnIfHeld(mPackages);

// 创建并添加PackageManagerInternalImpl服务到ServiceManager
LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

上面这最后的部分有点难啊,看不出来做了什么操作,先留着,以后再分析吧。现在主要看的是上面会创建一个PackageInstallerService服务,我们接下来分析这个服务

2.1.6 创建PackageInstallerService

public PackageInstallerService(Context context, PackageManagerService pm) {
    mContext = context;
    mPm = pm;

    // 创建名为“PackageInstaller”的Handler线程
    mInstallThread = new HandlerThread(TAG);
    mInstallThread.start();

    mInstallHandler = new Handler(mInstallThread.getLooper());

    mCallbacks = new Callbacks(mInstallThread.getLooper());

    // 打开/data/system/install_sessions.xml文件
    mSessionsFile = new AtomicFile(
            new File(Environment.getDataSystemDirectory(), "install_sessions.xml"));
    // 创建/data/system/install_sessions文件夹
    mSessionsDir = new File(Environment.getDataSystemDirectory(), "install_sessions");
    mSessionsDir.mkdirs();
}

  真不容易,这PackageManagerService的第一部分就先分析到这里,到现在我们才主要分析了PKMS启动的第一个部分:PackageManagerService.main,下面列出的部分我们再下一篇再做分析。

  • mPackageManagerService.updatePackagesIfNeeded
  • mPackageManagerService.performFstrimIfNeeded
  • mPackageManagerService.systemReady
  • mPackageManagerService.waitForAppDataPrepared

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d 博主赞过: