一.概述
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;
}