PackageManagerService分析

一.概述

PackageManagerService(PKMS)是android系统中的核心服务,也是安卓常用的服务之一;它负责系统中Package的管理,应用的安装,卸载,信息查询等。

二 PKMS的启动分析

2.1 SystemService.startBootstrapServices

与ams一样pkms的启动在”system_service”进程中开启的

[—>SystemService.java]

private void startBootstrapServices() {
    //启动installer服务
    Installer installer = mSystemServiceManager.startService(Installer.class);
    ...
    //创建PKMS对象【见2.2】
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    //PKMS是否首次启动
    mFirstBoot = mPackageManagerService.isFirstBoot();

    //【见3.1】
    mPackageManager = mSystemContext.getPackageManager();
    ...
}

2.2 PKMS.main

public static PackageManagerService main(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {
    //初始化PKMS对象[见2.3]
    PackageManagerService m = new PackageManagerService(context, installer,
            factoryTest, onlyCore);
    //将package服务注册到ServiceManager
    ServiceManager.addService("package", m);
    return m;
}

这个方法主要功能是创建PKMS对象,并将其注册到服务大管家ServiceManager中去

2.3 PackageManagerService

public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
                SystemClock.uptimeMillis());
        ...
        mMetrics = new DisplayMetrics();
        //用于存储系统运行中的一些设置 [见2.4]
        mSettings = new Settings(mPackages);
        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);
        ...
        synchronized (mInstallLock) {
        synchronized (mPackages) {
            //创建一个"package"的线程,用于处理后面apk的安装与卸载等操作
            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);
           //创建各种目录
            File dataDir = Environment.getDataDirectory();
            mAppInstallDir = new File(dataDir, "app");
            mAppLib32InstallDir = new File(dataDir, "app-lib");
            mEphemeralInstallDir = new File(dataDir, "app-ephemeral");
            mAsecInternalPath = new File(dataDir, "app-asec").getPath();
            mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
           //创建用户管理服务
            sUserManager = new UserManagerService(context, this, mPackages);
            ...
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
                    startTime);
            ...
            //扫描供应商包名:/vendor/overlay
            File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
            scanDirTracedLI(vendorOverlayDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR
                    | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
            //扫描系统包名 /system/framework
            scanDirTracedLI(frameworkDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR
                    | PackageParser.PARSE_IS_PRIVILEGED,
                    scanFlags | SCAN_NO_DEX, 0);
            //扫描私有的系统包名:/system/priv-app
            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
            final File systemAppDir = new File(Environment.getRootDirectory(), "app");
            scanDirTracedLI(systemAppDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

            // 扫描所有的供应商包名:/vendor/app
            File vendorAppDir = new File("/vendor/app");
            ...
            scanDirTracedLI(vendorAppDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

            //扫描所有OEM包名 /oem/app
            final File oemAppDir = new File(Environment.getOemDirectory(), "app");
            scanDirTracedLI(oemAppDir, mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
           ...
            //将收集到的信息保存到文件中去,package.xml,package.list,package-stopped.xml
            mSettings.writeLPr();
            ...

    }

/system/frameworks:该目录中的文件都是系统库,例如,framework.jar,services.jar,framework-res.apk,不过在这里只扫描apk文件,所以framework-res.apk是这次扫描的结果

/system/app:该目录下全是默认的系统应用,例如Browser.apk,SettingProvider.apk等

/vendor/app:该目录中的文件是全部厂商提供的

scanDirLi(…):这个方法用来扫描指定目录下的apk文件,最终调用PackageParser.parseBaseApk来完成AndroidManifest.xml文件的解析,生成Application,activity,service,broadcast,provider等信息

在这个过程中PKMS的任务比较重,要创建比较多的对象,是一个比较耗时费时候的过程;这也是为什么安卓系统启动比较慢的原因之一。

2.4 Settings

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

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

        mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);

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

Setting这个类是用来保存运行过程中一些设置信息,例如扫描后的apk信息就存储在这些目录中

文件 功能
packages.xml 记录所有安装app的信息
packages-backup.xml 备份文件
packages-stopped.xml 记录系统被强制停止的文件
packages-stopped-backup.xml 备份文件
packages.list 记录应用的数据信息

三 pkms的使用

3.1 ContextImpl.getPackageManager

public PackageManager getPackageManager() {
        if (mPackageManager != null) {
            return mPackageManager;
        }
        //[见3.2]
        IPackageManager pm = ActivityThread.getPackageManager();
        if (pm != null) {
            //创建ApplicationPackageManager对象
            return (mPackageManager = new ApplicationPackageManager(this, pm));
        }

        return null;
    }

在这里通过ActivityThread这个类拿到了一个PackageManger对象,其实这是通过Binder拿到的PackageManagerService中的IPackageManage.Stub对象,ApplicationPackageManager相当于一个代理它内部的操作都是通过PackageManagerService来完成的。

3.2 ActivityThread.getPackageManager

public static IPackageManager getPackageManager() {
        if (sPackageManager != null) {
            return sPackageManager;
        }
        //从服务大管家中取出package服务
        IBinder b = ServiceManager.getService("package");
        sPackageManager = IPackageManager.Stub.asInterface(b);
        return sPackageManager;
    }

你可能感兴趣的:(android)