相关文章 Android包管理机制系列html
PMS的建立过程分为两个部分进行讲解,分别是SyetemServer处理部分和PMS构造方法。其中SyetemServer处理部分和AMS和WMS的建立过程是相似的,能够将它们进行对比,这样能够更好的理解和记忆这一知识点。前端
PMS是在SyetemServer进程中被建立的,SyetemServer进程用来建立系统服务,不了解它的能够查看Android系统启动流程(三)解析SyetemServer进程启动过程这篇文章。 从SyetemServer的入口方法main方法开始讲起,以下所示。 frameworks/base/services/java/com/android/server/SystemServer.javajava
public static void main(String[] args) {
new SystemServer().run();
}
复制代码
main方法中只调用了SystemServer的run方法,以下所示。 frameworks/base/services/java/com/android/server/SystemServer.javaandroid
private void run() {
try {
...
//建立消息Looper
Looper.prepareMainLooper();
//加载了动态库libandroid_servers.so
System.loadLibrary("android_servers");//1
performPendingShutdown();
// 建立系统的Context
createSystemContext();
// 建立SystemServiceManager
mSystemServiceManager = new SystemServiceManager(mSystemContext);//2
mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
SystemServerInitThreadPool.get();
} finally {
traceEnd();
}
try {
traceBeginAndSlog("StartServices");
//启动引导服务
startBootstrapServices();//3
//启动核心服务
startCoreServices();//4
//启动其余服务
startOtherServices();//5
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
traceEnd();
}
...
}
复制代码
在注释1处加载了动态库libandroid_servers.so。接下来在注释2处建立SystemServiceManager,它会对系统的服务进行建立、启动和生命周期管理。在注释3中的startBootstrapServices方法中用SystemServiceManager启动了ActivityManagerService、PowerManagerService、PackageManagerService等服务。在注释4处的startCoreServices方法中则启动了DropBoxManagerService、BatteryService、UsageStatsService和WebViewUpdateService。注释5处的startOtherServices方法中启动了CameraService、AlarmManagerService、VrManagerService等服务。这些服务的父类均为SystemService。从注释三、四、5的方法能够看出,官方把系统服务分为了三种类型,分别是引导服务、核心服务和其余服务,其中其余服务是一些非紧要和一些不须要当即启动的服务。这些系统服务总共有100多个,咱们熟知的AMS属于引导服务,WMS属于其余服务, 本文要讲的PMS属于引导服务,所以这里列出引导服务以及它们的做用,见下表。git
引导服务 | 做用 |
---|---|
Installer | 系统安装apk时的一个服务类,启动完成Installer服务以后才能启动其余的系统服务 |
ActivityManagerService | 负责四大组件的启动、切换、调度。 |
PowerManagerService | 计算系统中和Power相关的计算,而后决策系统应该如何反应 |
LightsService | 管理和显示背光LED |
DisplayManagerService | 用来管理全部显示设备 |
UserManagerService | 多用户模式管理 |
SensorService | 为系统提供各类感应器服务 |
PackageManagerService | 用来对apk进行安装、解析、删除、卸载等等操做 |
查看启动引导服务的注释3处的startBootstrapServices方法。 frameworks/base/services/java/com/android/server/SystemServer.javagithub
private void startBootstrapServices() {
...
traceBeginAndSlog("StartPackageManagerService");
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);//1
mFirstBoot = mPackageManagerService.isFirstBoot();//2
mPackageManager = mSystemContext.getPackageManager();
traceEnd();
...
}
复制代码
注释1处的PMS的main方法主要用来建立PMS,其中最后一个参数mOnlyCore表明是否只扫描系统的目录,它在本篇文章中会出现屡次,通常状况下它的值为false。注释2处获取boolean类型的变量mFirstBoot,它用于表示PMS是否首次被启动。mFirstBoot是后续WMS建立时所须要的参数,从这里就能够看出系统服务之间是有依赖关系的,它们的启动顺序不能随意被更改。缓存
PMS的main方法以下所示。 frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java架构
public static PackageManagerService main(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {
PackageManagerServiceCompilerMapping.checkProperties();
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
m.enableSystemUserPackages();
ServiceManager.addService("package", m);
return m;
}
复制代码
main方法主要作了两件事,一个是建立PMS对象,另外一个是将PMS注册到ServiceManager中。 PMS的构造方法大概有600多行,分为5个阶段,每一个阶段会打印出相应的EventLog,EventLog用于打印Android系统的事件日志。app
PMS的构造方法中会获取一些包管理须要属性,以下所示。 frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java框架
public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {
LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "create package manager");
//打印开始阶段日志
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
SystemClock.uptimeMillis())
...
//用于存储屏幕的相关信息
mMetrics = new DisplayMetrics();
//Settings用于保存全部包的动态设置
mSettings = new Settings(mPackages);
//在Settings中添加多个默认的sharedUserId
mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);//1
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);
...
mInstaller = installer;
//建立Dex优化工具类
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();
//获取全局的groupId
mGlobalGids = systemConfig.getGlobalGids();
//获取系统权限
mSystemPermissions = systemConfig.getSystemPermissions();
mAvailableFeatures = systemConfig.getAvailableFeatures();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
mProtectedPackages = new ProtectedPackages(mContext);
//安装APK时须要的锁,保护全部对installd的访问。
synchronized (mInstallLock) {//1
//更新APK时须要的锁,保护内存中已经解析的包信息等内容
synchronized (mPackages) {//2
//建立后台线程ServiceThread
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
mHandlerThread.start();
//建立PackageHandler绑定到ServiceThread的消息队列
mHandler = new PackageHandler(mHandlerThread.getLooper());//3
mProcessLoggingHandler = new ProcessLoggingHandler();
//将PackageHandler添加到Watchdog的检测集中
Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);//4
mDefaultPermissionPolicy = new DefaultPermissionGrantPolicy(this);
mInstantAppRegistry = new InstantAppRegistry(this);
//在Data分区建立一些目录
File dataDir = Environment.getDataDirectory();//5
mAppInstallDir = new File(dataDir, "app");
mAppLib32InstallDir = new File(dataDir, "app-lib");
mAsecInternalPath = new File(dataDir, "app-asec").getPath();
mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
//建立多用户管理服务
sUserManager = new UserManagerService(context, this,
new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
...
mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false))//6
...
}
复制代码
在开始阶段中建立了不少PMS中的关键对象并赋值给PMS中的成员变量,下面简单介绍这些成员变量。
除了建立这些关键对象,在开始阶段还有一些关键代码须要去讲解:
...
public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {
...
//打印扫描系统阶段日志
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
startTime);
...
//在/system中建立framework目录
File frameworkDir = new File(Environment.getRootDirectory(), "framework");
...
//扫描/vendor/overlay目录下的文件
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);
mParallelPackageParserCallback.findStaticOverlayPackages();
//扫描/system/framework 目录下的文件
scanDirTracedLI(frameworkDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED,
scanFlags | SCAN_NO_DEX, 0);
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
//扫描 /system/priv-app 目录下的文件
scanDirTracedLI(privilegedAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
//扫描/system/app 目录下的文件
scanDirTracedLI(systemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
File vendorAppDir = new File("/vendor/app");
try {
vendorAppDir = vendorAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
//扫描 /vendor/app 目录下的文件
scanDirTracedLI(vendorAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
//扫描/oem/app 目录下的文件
final File oemAppDir = new File(Environment.getOemDirectory(), "app");
scanDirTracedLI(oemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
//这个列表表明有可能有升级包的系统App
final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();//1
if (!mOnlyCore) {
Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
while (psit.hasNext()) {
PackageSetting ps = psit.next();
if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
continue;
}
//这里的mPackages的是PMS的成员变量,表明scanDirTracedLI方法扫描上面那些目录获得的
final PackageParser.Package scannedPkg = mPackages.get(ps.name);
if (scannedPkg != null) {
if (mSettings.isDisabledSystemPackageLPr(ps.name)) {//2
...
//将这个系统App的PackageSetting从PMS的mPackages中移除
removePackageLI(scannedPkg, true);
//将升级包的路径添加到mExpectingBetter列表中
mExpectingBetter.put(ps.name, ps.codePath);
}
continue;
}
if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
...
} else {
final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
//这个系统App升级包信息在mDisabledSysPackages中,可是没有发现这个升级包存在
if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {//5
possiblyDeletedUpdatedSystemApps.add(ps.name);//
}
}
}
}
...
}
复制代码
/system能够称做为System分区,里面主要存储谷歌和其余厂商提供的Android系统相关文件和框架。Android系统架构分为应用层、应用框架层、系统运行库层(Native 层)、硬件抽象层(HAL层)和Linux内核层,除了Linux内核层在Boot分区,其余层的代码都在System分区。下面列出 System分区的部分子目录。
目录 | 含义 |
---|---|
app | 存放系统App,包括了谷歌内置的App也有厂商或者运营商提供的App |
framework | 存放应用框架层的jar包 |
priv-app | 存放特权App |
lib | 存放so文件 |
fonts | 存放系统字体文件 |
media | 存放系统的各类声音,好比铃声、提示音,以及系统启动播放的动画 |
上面的代码还涉及到/vendor 目录,它用来存储厂商对Android系统的定制部分。
系统扫描阶段的主要工做有如下3点:
主要来讲第3点,一次OTA升级对于一个系统App会有三种状况:
当系统App升级,PMS会将该系统App的升级包设置数据(PackageSetting)存储到Settings的mDisabledSysPackages列表中(具体见PMS的replaceSystemPackageLIF方法),mDisabledSysPackages的类型为ArrayMap<String, PackageSetting>
。mDisabledSysPackages中的信息会被PMS保存到packages.xml中的<updated-package>
标签下(具体见Settings的writeDisabledSysPackageLPr方法)。 注释2处说明这个系统App有升级包,那么就将该系统App的PackageSetting从mDisabledSysPackages列表中移除,并将系统App的升级包的路径添加到mExpectingBetter列表中,mExpectingBetter的类型为ArrayMap<String, File>
等待后续处理。 注释5处若是这个系统App的升级包信息存储在mDisabledSysPackages列表中,可是没有发现这个升级包存在,则将它加入到possiblyDeletedUpdatedSystemApps列表中,意为“系统App的升级包可能被删除”,之因此是“可能”,是由于系统尚未扫描Data分区,只能暂放到possiblyDeletedUpdatedSystemApps列表中,等到扫描完Data分区后再作处理。
public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) {
...
mSettings.pruneSharedUsersLPw();
//若是不是只扫描系统的目录,那么就开始扫描Data分区。
if (!mOnlyCore) {
//打印扫描Data分区阶段日志
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
SystemClock.uptimeMillis());
//扫描/data/app目录下的文件
scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
//扫描/data/app-private目录下的文件
scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
| PackageParser.PARSE_FORWARD_LOCK,
scanFlags | SCAN_REQUIRE_KNOWN, 0);
//扫描完Data分区后,处理possiblyDeletedUpdatedSystemApps列表
for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
// 从mSettings.mDisabledSysPackages变量中移除去此应用
mSettings.removeDisabledSystemPackageLPw(deletedAppName);
String msg;
//1:若是这个系统App的包信息不在PMS的变量mPackages中,说明是残留的App信息,后续会删除它的数据。
if (deletedPkg == null) {
msg = "Updated system package " + deletedAppName
+ " no longer exists; it's data will be wiped";
// Actual deletion of code and data will be handled by later
// reconciliation step
} else {
//2:若是这个系统App在mPackages中,说明是存在于Data分区,不属于系统App,那么移除其系统权限。
msg = "Updated system app + " + deletedAppName
+ " no longer present; removing system privileges for "
+ deletedAppName;
deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
}
logCriticalInfo(Log.WARN, msg);
}
//遍历mExpectingBetter列表
for (int i = 0; i < mExpectingBetter.size(); i++) {
final String packageName = mExpectingBetter.keyAt(i);
if (!mPackages.containsKey(packageName)) {
//获得系统App的升级包路径
final File scanFile = mExpectingBetter.valueAt(i);
logCriticalInfo(Log.WARN, "Expected better " + packageName
+ " but never showed up; reverting to system");
int reparseFlags = mDefParseFlags;
//3:根据系统App所在的目录设置扫描的解析参数
if (FileUtils.contains(privilegedAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED;
}
...
//将packageName对应的包设置数据(PackageSetting)添加到mSettings的mPackages中
mSettings.enableSystemPackageLPw(packageName);//4
try {
//扫描系统App的升级包
scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 0, null);//5
} catch (PackageManagerException e) {
Slog.e(TAG, "Failed to parse original system package: "
+ e.getMessage());
}
}
}
}
//清除mExpectingBetter列表
mExpectingBetter.clear();
...
}
复制代码
/data能够称为Data分区,它用来存储全部用户的我的数据和配置文件。下面列出Data分区部分子目录:
目录 | 含义 |
---|---|
app | 存储用户本身安装的App |
data | 存储全部已安装的App数据的目录,每一个App都有本身单独的子目录 |
app-private | App的私有存储空间 |
app-lib | 存储全部App的Jni库 |
system | 存放系统配置文件 |
anr | 用于存储ANR发生时系统生成的traces.txt文件 |
扫描Data分区阶段主要作了如下几件事:
//打印扫描结束阶段日志
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
SystemClock.uptimeMillis());
Slog.i(TAG, "Time to scan packages: "
+ ((SystemClock.uptimeMillis()-startTime)/1000f)
+ " seconds");
int updateFlags = UPDATE_PERMISSIONS_ALL;
// 若是当前平台SDK版本和上次启动时的SDK版本不一样,从新更新APK的受权
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;
//若是是第一次启动或者是Android M升级后的第一次启动,须要初始化全部用户定义的默认首选App
if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) {
for (UserInfo user : sUserManager.getUsers(true)) {
mSettings.applyDefaultPreferredAppsLPw(this, user.id);
applyFactoryDefaultBrowserLPw(user.id);
primeDomainVerificationsLPw(user.id);
}
}
...
//OTA后的第一次启动,会清除代码缓存目录。
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)) {
clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
| Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
}
ver.fingerprint = Build.FINGERPRINT;
}
...
// 把Settings的内容保存到packages.xml中
mSettings.writeLPr();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
复制代码
扫描结束结束阶段主要作了如下几件事:
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());
...
mInstallerService = new PackageInstallerService(context, this);//1
...
Runtime.getRuntime().gc();//2
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "loadFallbacks");
FallbackCategoryProvider.loadFallbacks();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
mInstaller.setWarnIfHeld(mPackages);
LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());//3
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
复制代码
注释1处建立PackageInstallerService,PackageInstallerService是用于管理安装会话的服务,它会为每次安装过程分配一个SessionId,在Android包管理机制(二)PackageInstaller安装APK这篇文章中提到过PackageInstallerService。 注释2处进行一次垃圾收集。注释3处将PackageManagerInternalImpl(PackageManager的本地服务)添加到LocalServices中, LocalServices用于存储运行在当前的进程中的本地服务。
本篇文章介绍了PMS的建立过程,分为两个部分,分别是SyetemServer处理部分和PMS构造方法,PMS构造方法又分为5个部分,分别是开始阶段、扫描系统阶段、扫描Data分区阶段、扫描结束阶段和准备阶段。
参考资料
Android包管理机制
源码分析 — PackageManagerService(一)之启动流程
Android-6.0之PMS解析下篇
APK安装流程详解6——PackageManagerService启动前奏
这里不只分享Android、Java和移动前端相关技术,还有行业动态、技术资讯、面经和我的感悟。