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)//安装apkmInstaller.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(); //有效activityfinal ActivityIntentResolver mReceivers = new ActivityIntentResolver(); //有效receiverfinal ServiceIntentResolver mServices = new ServiceIntentResolver();//有效servicefinal HashMap mProvidersByComponent = new HashMap();//有效ProvidersBy
当用户想查询apk的某些信息时(例如,查询包信息),就可以通过PMS查询到这些信息了。