Android源码分析-PackageManagerService(PMS)源码分析(一)PMS的初始化以及PackageManager的使用

一,PackageManagerService(PMS)服务简介:

PackageManagerService(简称PMS),顾名思义,用于进行Android包的管理。利用PackageManagerService服务,可以查询应用程序等信息,以及安装包(package)信息,以及该应用activity,service,权限等组件的信息。PackageManagerService是Android系统中的一个系统服务。

Android系统中,提供了PackageManager类来对外(应用程序)提供API接口,对内(Android系统)与PMS进行IPC通信,最终通过PMS来实现真正的功能。

Android系统对PackageManager定义成了抽象类,而其真正的具体功能是在ApplicationPackageManager类中(ApplicationPackageManager是PackageManager的派生类)实现的。

二,PackageManagerService架构图:

PackageManagerService架构图(相关类图):

 

三,PackageManager的常用数据成员和常用方法:

列出了3个常用的方法:

public abstract PackageInfo getPackageInfo(String packageName, int flags) throws NameNotFoundException; //获取包的信息

public abstract PermissionInfo getPermissionInfo(String name, int flags)
        throws NameNotFoundException; //获取权限信息
public abstract ActivityInfo getActivityInfo(ComponentName component,
        int flags) throws NameNotFoundException; //获取activity信息

 更多的方法,如下图:

四,ApplicationPackageManager的常用数据成员和常用方法:

ApplicationPackageManager继承自PackageManager,PackageManager的很多abstract方法都是ApplicationPackageManager来实现的。

常用方法,如下图:

五,PackageManagerService的初始化代码分析:

5.1 PMS的初始化:

和其它Framework组件一样,PMS是在SystemServer中进行的初始化,代码如下:

SystemServer.java中,PackageManagerService的初始化:

pm = PackageManagerService.main(context,
                    factoryTest != SystemServer.FACTORY_TEST_OFF,
                    onlyCore);
            boolean firstBoot = false;
            try {
                firstBoot = pm.isFirstBoot();
            } catch (RemoteException e) {
            }

。。。。。。


try {
            pm.performBootDexOpt();
        } catch (Throwable e) {
            reportWtf("performing boot dexopt", e);
        }

。。。。。。

try {
            pm.systemReady();
        } catch (Throwable e) {
            reportWtf("making Package Manager Service ready", e);
        }

在PackageManagerService.java中, 有:

public static final IPackageManager main(Context context, boolean factoryTest,
            boolean onlyCore) {
        PackageManagerService m = new PackageManagerService(context, factoryTest, onlyCore);
        ServiceManager.addService("package", m);
        return m;
    }

说明:

返回的是IPackageManager类型,其真正的实例其实是:

PackageManagerService

将其加入ServerManager中,以便进行管理。

5.2 PackageManagerService的构造函数分析:

5.2.1 创建Installer实例, 获取pi屏幕大小:

        //创建Installer实例
        mInstaller = new Installer();

        //屏幕大小相关
        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
        Display d = wm.getDefaultDisplay();
        d.getMetrics(mMetrics);

5.2.2  获取app安装相关目录:

            //获取app安装相关目录
            File dataDir = Environment.getDataDirectory();
            mAppDataDir = new File(dataDir, "data");
            mAsecInternalPath = new File(dataDir, "app-asec").getPath();
            mUserAppDataDir = new File(dataDir, "user");

            //2. app安装目录: “/data/data/app-private”目录
            mDrmAppPrivateInstallDir = new File(dataDir, "app-private");

 5.2.3  读取权限:

            readPermissions();

  5.2.4  获取framework目录和虚拟机缓存目录:

            //framework目录
            mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
            //虚拟机缓存目录
            mDalvikCacheDir = new File(dataDir, "dalvik-cache");

  5.2.5  加载框架层资源:framework-res和核心包:

            libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
            
            String[] frameworkFiles = mFrameworkDir.list();
            if (frameworkFiles != null) {
                for (int i=0; i<frameworkFiles.length; i++) {
                    File libPath = new File(mFrameworkDir, frameworkFiles[i]);
                    String path = libPath.getPath();
                    // Skip the file if we alrady did it.
                    if (libFiles.contains(path)) {
                        continue;
                    }
                    // Skip the file if it is not a type we want to dexopt.
                    if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
                        continue;
                    }
                    try {
                        if (dalvik.system.DexFile.isDexOptNeeded(path)) {
                            mInstaller.dexopt(path, Process.SYSTEM_UID, true);
                            didDexOpt = true;
                        }
                    } catch (FileNotFoundException e) {
                        Slog.w(TAG, "Jar not found: " + path);
                    } catch (IOException e) {
                        Slog.w(TAG, "Exception reading jar: " + path, e);
                    }
                }
            }

  5.2.6  获取系统app,wendor app的包信息: 

            // Collect all system packages.
            mSystemAppDir = new File(Environment.getRootDirectory(), "app");
            mSystemInstallObserver = new AppDirObserver(
                mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
            mSystemInstallObserver.startWatching();
            scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);

            // Collect all vendor packages.
            mVendorAppDir = new File("/vendor/app");
            mVendorInstallObserver = new AppDirObserver(
                mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
            mVendorInstallObserver.startWatching();
            scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);

5.2.7 非核心app的扫描:

            if (!mOnlyCore) {
                EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                        SystemClock.uptimeMillis());
                mAppInstallObserver = new AppDirObserver(
                    mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
                mAppInstallObserver.startWatching();
                //13.扫描安装目录,最重要的步骤
                scanDirLI(mAppInstallDir, 0, scanMode, 0);
    
                mDrmAppInstallObserver = new AppDirObserver(
                    mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
                mDrmAppInstallObserver.startWatching();

                //13.扫描安装目录,最重要的步骤
                scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
                        scanMode, 0);

                ......
                }
            } 

5.2.8 更新权限: 

            updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
                    | (regrantPermissions
                            ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
                            : 0));

 其中,最主要是scanDirLI方法,即扫描目录下的apk文件。下面主要分析这个方法(5.3)。

5.3 scanDirLI方法代码分析:

(1)scanDirLI的定义:

private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
...
//扫描dir目录下的文件,如果是apk文件,就继续执行“scanPackageLI”方法。
PackageParser.Package pkg = scanPackageLI(file,
        flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime);

}

(2)scanPackageLI(重点):

private PackageParser.Package scanPackageLI(File scanFile,
            int parseFlags, int scanMode, long currentTime) {
        mLastScanError = PackageManager.INSTALL_SUCCEEDED;
        String scanPath = scanFile.getPath();
        parseFlags |= mDefParseFlags;

        PackageParser pp = new PackageParser(scanPath);

......
//
//1.创建参数
createInstallArgs


//2.身份认证
collectCertificatesLI

//3.调用另外一个重载函数
scanPackageLI

(3)主要分析scanPackageLI这个重载函数:

//初始化source和资源文件目录
File destCodeFile = new File(pkg.applicationInfo.sourceDir);
File destResourceFile = new File(pkg.applicationInfo.publicSourceDir);

......

//签名校验
verifySignaturesLP(pkgSetting, pkg)

//安装apk
mInstaller.install(pkgName, pkg.applicationInfo.uid,
                        pkg.applicationInfo.uid);

//创建用户目录
sUserManager.installPackageForAllUsers(pkgName, pkg.applicationInfo.uid);

//native 目录的处理

//providers的处理

//servuce的处理

//receivers的处理

//permissions(权限)的处理

六,总结:

PMS中将各个app进行解析,并且保存在内存中,即PMS类的数据成员,典型的有:

PackageManagerService.java的数据成员:

final File mAppDataDir; //应用数据目录
final File mFrameworkDir; //framework目录
final File mSystemAppDir; //系统目录
final File mVendorAppDir; //vendor目录
final File mAppInstallDir; //应用安装目录
final File mDalvikCacheDir;//虚拟机缓存目录

final ActivityIntentResolver mActivities =
        new ActivityIntentResolver(); //有效activity
final ActivityIntentResolver mReceivers =
        new ActivityIntentResolver(); //有效receiver
final ServiceIntentResolver mServices = new ServiceIntentResolver();//有效service

final HashMap<ComponentName, PackageParser.Provider> mProvidersByComponent =
        new HashMap<ComponentName, PackageParser.Provider>();//有效ProvidersBy

当用户想查询apk的某些信息时(例如,查询包信息),就可以通过PMS查询到这些信息了。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liranke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值