概述
PackageManagerService,是Android系统中核心服务之一,管理着所有跟package相关的工作,常见的比如安装、卸载应用。 PKMS服务也是通过binder进行通信,IPackageManager.aidl由工具转换后自动生成binder的服务端IPackageManager.Stub和客户端IPackageManager.Stub.Proxy,具体关系如下:
Binder服务端:PackageManagerService继承于IPackageManager.Stub; Binder客户端:ApplicationPackageManager(简称APM)的成员变量mPM继承于IPackageManager.Stub.Proxy; 本身APM是继承于PackageManager对象。
Android系统启动过程中,一路启动到SystemServer后,便可以启动framework的各大服务,本篇博客将介绍PKMS的启动过程(基于安卓7.0源码)。
PackageManagerService的启动
SystemServer启动过程中涉及到的PKMS代码如下:
代码语言:javascript复制private void startBootstrapServices() {
//启动installer服务
Installer installer = mSystemServiceManager.startService(Installer.class);
...
//处于加密状态则仅仅解析核心应用
String cryptState = SystemProperties.get("vold.decrypt");
if (ENCRYPTING_STATE.equals(cryptState)) {
mOnlyCore = true; // ENCRYPTING_STATE = "trigger_restart_min_framework"
} else if (ENCRYPTED_STATE.equals(cryptState)) {
mOnlyCore = true; // ENCRYPTED_STATE = "1"
}
//创建PKMS对象
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
//PKMS是否首次启动
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
...
}
PackageManagerService与其他所有的服务一样,也是由SystemServer启动,它也是java层服务之一,PKMS.main()过程主要是创建PKMS服务,并注册到ServiceManager。
整个system_server进程启动过程,涉及PKMS服务的主要几个动作如下,接下来分别讲解每个过程 PKMS.main() PKMS.performBootDexOpt PKMS.systemReady
PKMS.main()
代码语言:javascript复制public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
// Self-check for initial settings.
PackageManagerServiceCompilerMapping.checkProperties();
//构造一个包管理服务对象
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
m.enableSystemUserPackages();
// Disable any carrier apps. We do this very early in boot to prevent the apps from being
// disabled after already being started.
CarrierAppUtils.disableCarrierAppsUntilPrivileged(context.getOpPackageName(), m,
UserHandle.USER_SYSTEM);
//将包管理服务对象添加到ServiceManager
ServiceManager.addService("package", m);
return m;
}
该方法的主要功能创建PKMS对象,并将其注册到ServiceManager。 关于PKMS对象的构造方法很长,分为以下几个阶段,每个阶段会输出相应的EventLog: 除了阶段1的开头部分代码,后续代码都是同时持有同步锁mPackages和mInstallLock的过程中执行的。
阶段1:BOOT_PROGRESS_PMS_START 阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START 阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START 阶段4:BOOT_PROGRESS_PMS_SCAN_END 阶段5:BOOT_PROGRESS_PMS_READY
阶段1:BOOT_PROGRESS_PMS_START
阶段1 PMS_START有两部分组成,由无需加锁的前部分和同时持有两个锁的后半部分,先来说说前半部分: 前半部分
代码语言:javascript复制//向事件日志写入事件,标识PackageManagerService启动
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
SystemClock.uptimeMillis());
//SDK版本检查
if (mSdkVersion <= 0) {
Slog.w(TAG, "**** ro.build.version.sdk not set!");
}
mContext = context;
//开机模式是否为工厂模式
mFactoryTest = factoryTest;
//是否仅启动内核
mOnlyCore = onlyCore;
//构造DisplayMetrics对象以便获取尺寸数据
mMetrics = new DisplayMetrics();
//构造Settings对象存储运行时的设置信息
mSettings = new Settings(mPackages);
//添加一些用户uid
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);
//判断是否在不同的进程
String separateProcesses = SystemProperties.get("debug.separate_processes");
if (separateProcesses != null && separateProcesses.length() > 0) {
if ("*".equals(separateProcesses)) {
mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
mSeparateProcesses = null;
Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");
} else {
mDefParseFlags = 0;
mSeparateProcesses = separateProcesses.split(",");
Slog.w(TAG, "Running with debug.separate_processes: "
separateProcesses);
}
} else {
mDefParseFlags = 0;
mSeparateProcesses = null;
}
//installer由SystemServer构造,这里通过该对象与底层进行通信,进行具体安装与卸载的操作
mInstaller = installer;
//创建PackageDexOptimizer,该类用于辅助进行dex优化
mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
"*dexopt*");
mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());
mOnPermissionChangeListeners = new OnPermissionChangeListeners(
FgThread.get().getLooper());
getDefaultDisplayMetrics(context, mMetrics);
//获取系统配置信息
SystemConfig systemConfig = SystemConfig.getInstance();
mGlobalGids = systemConfig.getGlobalGids();
mSystemPermissions = systemConfig.getSystemPermissions();
mAvailableFeatures = systemConfig.getAvailableFeatures();
接下来,再来看看后半部分:
代码语言:javascript复制synchronized (mInstallLock) {
// writer
synchronized (mPackages) {
//启动消息处理线程
mHandlerThread = new ServiceThread(TAG,
Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
mHandlerThread.start();
//通过消息处理线程的Looper对象构造一个处理消息的Handler对象
mHandler = new PackageHandler(mHandlerThread.getLooper());
mProcessLoggingHandler = new ProcessLoggingHandler();
//使用看门狗检测当前消息处理线程
Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
//获取当前的Data目录
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");
//构造UserManagerService对象,创建用户管理服务
sUserManager = new UserManagerService(context, this, mPackages);
// Propagate permission configuration in to package manager.
//读取权限配置文件中的信息,保存到mPermissions这个ArrayMap中
ArrayMap<String, SystemConfig.PermissionEntry> permConfig
= systemConfig.getPermissions();
for (int i=0; i<permConfig.size(); i ) {
SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
BasePermission bp = mSettings.mPermissions.get(perm.name);
if (bp == null) {
bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);
mSettings.mPermissions.put(perm.name, bp);
}
if (perm.gids != null) {
bp.setGids(perm.gids, perm.perUser);
}
}
//获取所有外部lib
ArrayMap<String, String> libConfig = systemConfig.getSharedLibraries();
for (int i=0; i<libConfig.size(); i ) {
mSharedLibraries.put(libConfig.keyAt(i),
new SharedLibraryEntry(libConfig.valueAt(i), null));
}
//尝试读取mac_permissions.xml并解析
mFoundPolicyFile = SELinuxMMAC.readInstallPolicy();
//读取并解析packages-backup.xml等文件
mRestoredSettings = mSettings.readLPw(sUserManager.getUsers(false));
//判断是否自定义的解析界面
String customResolverActivity = Resources.getSystem().getString(
R.string.config_customResolverActivity);
if (TextUtils.isEmpty(customResolverActivity)) {
customResolverActivity = null;
} else {
mCustomResolverComponentName = ComponentName.unflattenFromString(
customResolverActivity);
}
................
}
这个过程涉及的几个重要变量:
创建Settings
在阶段1中创建了Settings对象,我们看看里面做了什么
代码语言:javascript复制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;
// Deprecated: Needed for migration
mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
}
此处mSystemDir是指目录/data/system,在该目录有以下5个文件:
SystemConfig 阶段1中还调用SystemConfig.getInstance()方法来获取SystemConfig
代码语言:javascript复制public static SystemConfig getInstance() {
synchronized (SystemConfig.class) {
if (sInstance == null) {
sInstance = new SystemConfig();
}
return sInstance;
}
}
代码语言:javascript复制SystemConfig() {
// Read configuration from system
readPermissions(Environment.buildPath(
Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
// Read configuration from the old permissions dir
readPermissions(Environment.buildPath(
Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
// Allow ODM to customize system configs around libs, features and apps
int odmPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_APP_CONFIGS;
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
readPermissions(Environment.buildPath(
Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
// Only allow OEM to customize features
readPermissions(Environment.buildPath(
Environment.getOemDirectory(), "etc", "sysconfig"), ALLOW_FEATURES);
readPermissions(Environment.buildPath(
Environment.getOemDirectory(), "etc", "permissions"), ALLOW_FEATURES);
}
readPermissions()解析指定目录下的所有xml文件,比如将标签所指的动态库保存到 PKMS的成员变量mSharedLibraries。可见,SystemConfig创建过程是对以下这六个目录中的所有xml进行解析: /system/etc/sysconfig /system/etc/permissions /odm/etc/sysconfig /odm/etc/permissions /oem/etc/sysconfig /oem/etc/permissions
SystemConfig.readPermissions
代码语言:javascript复制void readPermissions(File libraryDir, int permissionFlag) {
// Read permissions from given directory.
if (!libraryDir.exists() || !libraryDir.isDirectory()) {
if (permissionFlag == ALLOW_ALL) {
Slog.w(TAG, "No directory " libraryDir ", skipping");
}
return;
}
if (!libraryDir.canRead()) {
Slog.w(TAG, "Directory " libraryDir " cannot be read");
return;
}
// Iterate over the files in the directory and scan .xml files
File platformFile = null;
for (File f : libraryDir.listFiles()) {
// We'll read platform.xml last
if (f.getPath().endsWith("etc/permissions/platform.xml")) {
platformFile = f;
continue;
}
if (!f.getPath().endsWith(".xml")) {
Slog.i(TAG, "Non-xml file " f " in " libraryDir " directory, ignoring");
continue;
}
if (!f.canRead()) {
Slog.w(TAG, "Permissions library file " f " cannot be read");
continue;
}
readPermissionsFromXml(f, permissionFlag);
}
// Read platform permissions last so it will take precedence
if (platformFile != null) {
readPermissionsFromXml(platformFile, permissionFlag);
}
}
该方法是解析指定目录下所有的具有可读权限的,且以xml后缀文件。
阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START
代码语言:javascript复制 //标记扫描开始的时间
long startTime = SystemClock.uptimeMillis();
//将扫描开始的事件写入日志
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
startTime);
// Set flag to monitor and not change apk file paths when
// scanning install directories.
//设置扫描的模式
final int scanFlags = SCAN_NO_PATHS | SCAN_DEFER_DEX | SCAN_BOOTING | SCAN_INITIAL;
//获取java启动类库的路径
final String bootClassPath = System.getenv("BOOTCLASSPATH");
//获取systemServer的路径
final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");
if (bootClassPath == null) {
Slog.w(TAG, "No BOOTCLASSPATH found!");
}
if (systemServerClassPath == null) {
Slog.w(TAG, "No SYSTEMSERVERCLASSPATH found!");
}
final List<String> allInstructionSets = InstructionSets.getAllInstructionSets();
final String[] dexCodeInstructionSets =
getDexCodeInstructionSets(
allInstructionSets.toArray(new String[allInstructionSets.size()]));
/**
* Ensure all external libraries have had dexopt run on them.
*/
//确保所有的外部lib都被dexopt优化
if (mSharedLibraries.size() > 0) {
// NOTE: For now, we're compiling these system "shared libraries"
// (and framework jars) into all available architectures. It's possible
// to compile them only when we come across an app that uses them (there's
// already logic for that in scanPackageLI) but that adds some complexity.
for (String dexCodeInstructionSet : dexCodeInstructionSets) {
for (SharedLibraryEntry libEntry : mSharedLibraries.values()) {
final String lib = libEntry.path;
if (lib == null) {
continue;
}
try {
// Shared libraries do not have profiles so we perform a full
// AOT compilation (if needed).
int dexoptNeeded = DexFile.getDexOptNeeded(
lib, dexCodeInstructionSet,
getCompilerFilterForReason(REASON_SHARED_APK),
false /* newProfile */);
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
mInstaller.dexopt(lib, Process.SYSTEM_UID, dexCodeInstructionSet,
dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/,
getCompilerFilterForReason(REASON_SHARED_APK),
StorageManager.UUID_PRIVATE_INTERNAL,
SKIP_SHARED_LIBRARY_CHECK);
}
} catch (FileNotFoundException e) {
Slog.w(TAG, "Library not found: " lib);
} catch (IOException | InstallerException e) {
Slog.w(TAG, "Cannot dexopt " lib "; is it an APK or JAR? "
e.getMessage());
}
}
}
}
File frameworkDir = new File(Environment.getRootDirectory(), "framework");
final VersionInfo ver = mSettings.getInternalVersion();
mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
// when upgrading from pre-M, promote system app permissions from install to runtime
mPromoteSystemApps =
mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;
// When upgrading from pre-N, we need to handle package extraction like first boot,
// as there is no profiling data available.
mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;
// save off the names of pre-existing system packages prior to scanning; we don't
// want to automatically grant runtime permissions for new system apps
if (mPromoteSystemApps) {
Iterator<PackageSetting> pkgSettingIter = mSettings.mPackages.values().iterator();
while (pkgSettingIter.hasNext()) {
PackageSetting ps = pkgSettingIter.next();
if (isSystemApp(ps)) {
mExistingSystemPackages.add(ps.name);
}
}
}
// Collect vendor overlay packages.
// (Do this before scanning any apps.)
// For security and version matching reason, only consider
// overlay packages if they reside in VENDOR_OVERLAY_DIR.
//收集供应商包名:/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);
// Find base frameworks (resource packages without code).
//扫描frameworkDir目录下的apk进行安装,扫描模式为非优化模式
scanDirTracedLI(frameworkDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED,
scanFlags | SCAN_NO_DEX, 0);
// Collected privileged system packages.
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);
// Collect ordinary system packages.
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirTracedLI(systemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
// Collect all vendor packages.
File vendorAppDir = new File("/vendor/app");
try {
vendorAppDir = vendorAppDir.getCanonicalFile();
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
scanDirTracedLI(vendorAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
// Collect all OEM packages.
final File oemAppDir = new File(Environment.getOemDirectory(), "app");
scanDirTracedLI(oemAppDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);
// Prune any system packages that no longer exist.
//构造一个List来存放不存在的packages路径
final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
if (!mOnlyCore) {
//遍历mSettings.mPackages
Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
while (psit.hasNext()) {
PackageSetting ps = psit.next();
/*
* If this is not a system app, it can't be a
* disable system app.
*/
//如果不是系统app,不处理
if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) {
continue;
}
/*
* If the package is scanned, it's not erased.
*/
final PackageParser.Package scannedPkg = mPackages.get(ps.name);
if (scannedPkg != null) {
/*
* If the system app is both scanned and in the
* disabled packages list, then it must have been
* added via OTA. Remove it from the currently
* scanned package so the previously user-installed
* application can be scanned.
*/
//如果在disable列表中,那么,说明它是通过OTA方式进行升级更新添加的,因此,清楚相应数据
if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
logCriticalInfo(Log.WARN, "Expecting better updated system app for "
ps.name "; removing system app. Last known codePath="
ps.codePathString ", installStatus=" ps.installStatus
", versionCode=" ps.versionCode "; scanned versionCode="
scannedPkg.mVersionCode);
//移除其信息
removePackageLI(scannedPkg, true);
mExpectingBetter.put(ps.name, ps.codePath);
}
continue;
}
//如果不在disable列表中,则直接清楚相应的数据
if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
psit.remove();
logCriticalInfo(Log.WARN, "System package " ps.name
" no longer exists; it's data will be wiped");
// Actual deletion of code and data will be handled by later
// reconciliation step
} else {
//否则,通过codePath判断其是否有可能被更新或删除
final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name);
if (disabledPs.codePath == null || !disabledPs.codePath.exists()) {
possiblyDeletedUpdatedSystemApps.add(ps.name);
}
}
}
}
//look for any incomplete package installations
//获取未完成安装的apk包的PackageSetting列表
ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
//清除未安装的安装包
for (int i = 0; i < deletePkgsList.size(); i ) {
// Actual deletion of code and data will be handled by later
// reconciliation step
final String packageName = deletePkgsList.get(i).name;
logCriticalInfo(Log.WARN, "Cleaning up incompletely installed app: " packageName);
synchronized (mPackages) {
mSettings.removePackageLPw(packageName);
}
}
//delete tmp files
//清除临时文件
deleteTempPackageFiles();
// Remove any shared userIDs that have no associated packages
//清除在mSettings中没有被使用的SharedUserSettings
mSettings.pruneSharedUsersLPw();
环境变量: 那可通过adb shell env来查看系统所有的环境变量及相应值。也可通过命令adb shell echo $SYSTEMSERVERCLASSPATH。 SYSTEMSERVERCLASSPATH:主要包括/system/framework目录下services.jar,ethernet-service.jar,wifi-service.jar这3个文件。 BOOTCLASSPATH:该环境变量内容较多,不同ROM可能有所不同,常见内容包含/system/framework目录下的framework.jar,ext.jar,core-libart.jar,telephony-common.jar,ims-common.jar,core-junit.jar等文件。
scanDirLI(): 扫描指定目录下的apk文件,最终调用PackageParser.parseBaseApk来完成AndroidManifest.xml文件的解析,生成Application, activity,service,broadcast, provider等信息。 /vendor/overlay /system/framework /system/priv-app /system/app /vendor/priv-app /vendor/app /oem/app
阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START
代码语言:javascript复制// Remove any shared userIDs that have no associated packages
//清除在mSettings中没有被使用的SharedUserSettings
mSettings.pruneSharedUsersLPw();
//如果是普通模式,则需要进行一些额外处理
if (!mOnlyCore) {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
SystemClock.uptimeMillis());
//扫描该目录
scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
| PackageParser.PARSE_FORWARD_LOCK,
scanFlags | SCAN_REQUIRE_KNOWN, 0);
scanDirLI(mEphemeralInstallDir, mDefParseFlags
| PackageParser.PARSE_IS_EPHEMERAL,
scanFlags | SCAN_REQUIRE_KNOWN, 0);
/**
* Remove disable package settings for any updated system
* apps that were removed via an OTA. If they're not a
* previously-updated app, remove them completely.
* Otherwise, just revoke their system-level permissions.
*/
//后面这部分代码逻辑简单,就是遍历possiblyDeletedUpdatedSystemApps,处理通过OTA更新和删除的APK文件
for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
mSettings.removeDisabledSystemPackageLPw(deletedAppName);
String msg;
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 {
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);
}
/**
* Make sure all system apps that we expected to appear on
* the userdata partition actually showed up. If they never
* appeared, crawl back and revive the system version.
*/
for (int i = 0; i < mExpectingBetter.size(); i ) {
final String packageName = mExpectingBetter.keyAt(i);
if (!mPackages.containsKey(packageName)) {
final File scanFile = mExpectingBetter.valueAt(i);
logCriticalInfo(Log.WARN, "Expected better " packageName
" but never showed up; reverting to system");
int reparseFlags = mDefParseFlags;
if (FileUtils.contains(privilegedAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED;
} else if (FileUtils.contains(systemAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR;
} else if (FileUtils.contains(vendorAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR;
} else if (FileUtils.contains(oemAppDir, scanFile)) {
reparseFlags = PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR;
} else {
Slog.e(TAG, "Ignoring unexpected fallback path " scanFile);
continue;
}
mSettings.enableSystemPackageLPw(packageName);
try {
scanPackageTracedLI(scanFile, reparseFlags, scanFlags, 0, null);
} catch (PackageManagerException e) {
Slog.e(TAG, "Failed to parse original system package: "
e.getMessage());
}
}
}
}
mExpectingBetter.clear();
// Resolve protected action filters. Only the setup wizard is allowed to
// have a high priority filter for these actions.
mSetupWizardPackage = getSetupWizardPackageName();
if (mProtectedFilters.size() > 0) {
if (DEBUG_FILTERS && mSetupWizardPackage == null) {
Slog.i(TAG, "No setup wizard;"
" All protected intents capped to priority 0");
}
for (ActivityIntentInfo filter : mProtectedFilters) {
if (filter.activity.info.packageName.equals(mSetupWizardPackage)) {
if (DEBUG_FILTERS) {
Slog.i(TAG, "Found setup wizard;"
" allow priority " filter.getPriority() ";"
" package: " filter.activity.info.packageName
" activity: " filter.activity.className
" priority: " filter.getPriority());
}
// skip setup wizard; allow it to keep the high priority filter
continue;
}
Slog.w(TAG, "Protected action; cap priority to 0;"
" package: " filter.activity.info.packageName
" activity: " filter.activity.className
" origPrio: " filter.getPriority());
filter.setPriority(0);
}
}
mDeferProtectedFilters = false;
mProtectedFilters.clear();
// Now that we know all of the shared libraries, update all clients to have
// the correct library paths.
//给需要使用shared libraries的package找到相应的路径,并将其保存至package的usesLibraryFiles中
updateAllSharedLibrariesLPw();
for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
// NOTE: We ignore potential failures here during a system scan (like
// the rest of the commands above) because there's precious little we
// can do about it. A settings error is reported, though.
adjustCpuAbisForSharedUserLPw(setting.packages, null /* scanned package */,
false /* boot complete */);
}
// Now that we know all the packages we are keeping,
// read and update their last usage times.
mPackageUsage.readLP();
当mOnlyCore = false时,则scanDirLI()还会收集如下目录中的apk /data/app /data/app-private
阶段4:BOOT_PROGRESS_PMS_SCAN_END
代码语言:javascript复制EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
SystemClock.uptimeMillis());
Slog.i(TAG, "Time to scan packages: "
((SystemClock.uptimeMillis()-startTime)/1000f)
" seconds");
// If the platform SDK has changed since the last time we booted,
// we need to re-grant app permission to catch any new ones that
// appear. This is really a hack, and means that apps can in some
// cases get permissions that the user didn't initially explicitly
// allow... it would be nice to have some better way to handle
// this situation.
int updateFlags = UPDATE_PERMISSIONS_ALL;
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;
}
//当sdk版本不一致时,,更新相关信息,并给需要使用权限的apk分配相应的权限
updatePermissionsLPw(null, null, StorageManager.UUID_PRIVATE_INTERNAL, updateFlags);
ver.sdkVersion = mSdkVersion;
// If this is the first boot or an update from pre-M, and it is a normal
// boot, then we need to initialize the default preferred apps across
// all defined users.
//当这是ota后的首次启动,正常启动则需要清除目录的缓存代码
if (!onlyCore && (mPromoteSystemApps || !mRestoredSettings)) {
for (UserInfo user : sUserManager.getUsers(true)) {
mSettings.applyDefaultPreferredAppsLPw(this, user.id);
applyFactoryDefaultBrowserLPw(user.id);
primeDomainVerificationsLPw(user.id);
}
}
// Prepare storage for system user really early during boot,
// since core system apps like SettingsProvider and SystemUI
// can't wait for user to start
final int storageFlags;
if (StorageManager.isFileEncryptedNativeOrEmulated()) {
storageFlags = StorageManager.FLAG_STORAGE_DE;
} else {
storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
}
reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL, UserHandle.USER_SYSTEM,
storageFlags);
// If this is first boot after an OTA, and a normal boot, then
// we need to clear code cache directories.
// Note that we do *not* clear the application profiles. These remain valid
// across OTAs and are used to drive profile verification (post OTA) and
// profile compilation (without waiting to collect a fresh set of profiles).
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)) {
// No apps are running this early, so no need to freeze
clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
| Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
}
}
ver.fingerprint = Build.FINGERPRINT;
}
checkDefaultBrowser();
// clear only after permissions and other defaults have been updated
//当权限和其他默认项都完成更新,则清理相关信息
mExistingSystemPackages.clear();
mPromoteSystemApps = false;
// All the changes are done during package scanning.
ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;
// can downgrade to reader
//信息写回packages.xml文件
mSettings.writeLPr();
// Perform dexopt on all apps that mark themselves as coreApps. We do this pretty
// early on (before the package manager declares itself as early) because other
// components in the system server might ask for package contexts for these apps.
//
// Note that "onlyCore" in this context means the system is encrypted or encrypting
// (i.e, that the data partition is unavailable).
if ((isFirstBoot() || isUpgrade() || VMRuntime.didPruneDalvikCache()) && !onlyCore) {
long start = System.nanoTime();
List<PackageParser.Package> coreApps = new ArrayList<>();
for (PackageParser.Package pkg : mPackages.values()) {
if (pkg.coreApp) {
coreApps.add(pkg);
}
}
int[] stats = performDexOpt(coreApps, false,
getCompilerFilterForReason(REASON_CORE_APP));
final int elapsedTimeSeconds =
(int) TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - start);
MetricsLogger.histogram(mContext, "opt_coreapps_time_s", elapsedTimeSeconds);
if (DEBUG_DEXOPT) {
Slog.i(TAG, "Dex-opt core apps took : " elapsedTimeSeconds " seconds ("
stats[0] ", " stats[1] ", " stats[2] ")");
}
// TODO: Should we log these stats to tron too ?
// MetricsLogger.histogram(mContext, "opt_coreapps_num_dexopted", stats[0]);
// MetricsLogger.histogram(mContext, "opt_coreapps_num_skipped", stats[1]);
// MetricsLogger.histogram(mContext, "opt_coreapps_num_failed", stats[2]);
// MetricsLogger.histogram(mContext, "opt_coreapps_num_total", coreApps.size());
}
阶段5:BOOT_PROGRESS_PMS_READY
代码语言:javascript复制EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());
if (!mOnlyCore) {
mRequiredVerifierPackage = getRequiredButNotReallyRequiredVerifierLPr();
mRequiredInstallerPackage = getRequiredInstallerLPr();
mIntentFilterVerifierComponent = getIntentFilterVerifierComponentNameLPr();
mIntentFilterVerifier = new IntentVerifierProxy(mContext,
mIntentFilterVerifierComponent);
mServicesSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
PackageManager.SYSTEM_SHARED_LIBRARY_SERVICES);
mSharedSystemSharedLibraryPackageName = getRequiredSharedLibraryLPr(
PackageManager.SYSTEM_SHARED_LIBRARY_SHARED);
} else {
mRequiredVerifierPackage = null;
mRequiredInstallerPackage = null;
mIntentFilterVerifierComponent = null;
mIntentFilterVerifier = null;
mServicesSystemSharedLibraryPackageName = null;
mSharedSystemSharedLibraryPackageName = null;
}
mInstallerService = new PackageInstallerService(context, this);
final ComponentName ephemeralResolverComponent = getEphemeralResolverLPr();
final ComponentName ephemeralInstallerComponent = getEphemeralInstallerLPr();
// both the installer and resolver must be present to enable ephemeral
if (ephemeralInstallerComponent != null && ephemeralResolverComponent != null) {
if (DEBUG_EPHEMERAL) {
Slog.i(TAG, "Ephemeral activated; resolver: " ephemeralResolverComponent
" installer:" ephemeralInstallerComponent);
}
mEphemeralResolverComponent = ephemeralResolverComponent;
mEphemeralInstallerComponent = ephemeralInstallerComponent;
setUpEphemeralInstallerActivityLP(mEphemeralInstallerComponent);
mEphemeralResolverConnection =
new EphemeralResolverConnection(mContext, mEphemeralResolverComponent);
} else {
if (DEBUG_EPHEMERAL) {
final String missingComponent =
(ephemeralResolverComponent == null)
? (ephemeralInstallerComponent == null)
? "resolver and installer"
: "resolver"
: "installer";
Slog.i(TAG, "Ephemeral deactivated; missing " missingComponent);
}
mEphemeralResolverComponent = null;
mEphemeralInstallerComponent = null;
mEphemeralResolverConnection = null;
}
mEphemeralApplicationRegistry = new EphemeralApplicationRegistry(this);
} // synchronized (mPackages)
} // synchronized (mInstallLock)
// Now after opening every single application zip, make sure they
// are all flushed. Not really needed, but keeps things nice and
// tidy.
Runtime.getRuntime().gc();
// The initial scanning above does many calls into installd while
// holding the mPackages lock, but we're mostly interested in yelling
// once we have a booted system.
mInstaller.setWarnIfHeld(mPackages);
// Expose private service for system components to use.
LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());
PKMS初始化完成阶段,还会创建一个PackageInstaller服务。
代码语言:javascript复制public PackageInstallerService(Context context, PackageManagerService pm) {
mContext = context;
mPm = pm;
//创建名为”PackageInstaller“的Handler线程
mInstallThread = new HandlerThread(TAG);
mInstallThread.start();
mInstallHandler = new Handler(mInstallThread.getLooper());
mCallbacks = new Callbacks(mInstallThread.getLooper());
mSessionsFile = new AtomicFile(
new File(Environment.getSystemSecureDirectory(), "install_sessions.xml"));
mSessionsDir = new File(Environment.getSystemSecureDirectory(), "install_sessions");
mSessionsDir.mkdirs();
synchronized (mSessions) {
readSessionsLocked();
reconcileStagesLocked(StorageManager.UUID_PRIVATE_INTERNAL);
final ArraySet<File> unclaimedIcons = newArraySet(
mSessionsDir.listFiles());
for (int i = 0; i < mSessions.size(); i ) {
final PackageInstallerSession session = mSessions.valueAt(i);
unclaimedIcons.remove(buildAppIconFile(session.sessionId));
}
for (File icon : unclaimedIcons) {
icon.delete();
}
}
}
PKMS初始化过程,分为5个阶段: PMS_START阶段: 创建Settings对象; 将6类shareUserId到mSettings; 初始化SystemConfig; 创建名为“PackageManager”的handler线程mHandlerThread; 创建UserManagerService多用户管理服务; 通过解析4大目录中的xmL文件构造共享mSharedLibraries; PMS_SYSTEM_SCAN_START阶段: 扫描系统apk; PMS_DATA_SCAN_START阶段: 扫描/data/app目录下的apk; 扫描/data/app-private目录下的apk; PMS_SCAN_END阶段: 将上述信息写回/data/system/packages.xml; PMS_READY阶段: 创建服务PackageInstallerService;
PKMS.systemReady
代码语言:javascript复制@Override
public void systemReady() {
mSystemReady = true;
// Read the compatibilty setting when the system is ready.
boolean compatibilityModeEnabled = android.provider.Settings.Global.getInt(
mContext.getContentResolver(),
android.provider.Settings.Global.COMPATIBILITY_MODE, 1) == 1;
PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
if (DEBUG_SETTINGS) {
Log.d(TAG, "compatibility mode:" compatibilityModeEnabled);
}
int[] grantPermissionsUserIds = EMPTY_INT_ARRAY;
synchronized (mPackages) {
// Verify that all of the preferred activity components actually
// exist. It is possible for applications to be updated and at
// that point remove a previously declared activity component that
// had been set as a preferred activity. We try to clean this up
// the next time we encounter that preferred activity, but it is
// possible for the user flow to never be able to return to that
// situation so here we do a sanity check to make sure we haven't
// left any junk around.
ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
for (int i=0; i<mSettings.mPreferredActivities.size(); i ) {
PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
removed.clear();
for (PreferredActivity pa : pir.filterSet()) {
if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
removed.add(pa);
}
}
if (removed.size() > 0) {
for (int r=0; r<removed.size(); r ) {
PreferredActivity pa = removed.get(r);
Slog.w(TAG, "Removing dangling preferred activity: "
pa.mPref.mComponent);
pir.removeFilter(pa);
}
mSettings.writePackageRestrictionsLPr(
mSettings.mPreferredActivities.keyAt(i));
}
}
for (int userId : UserManagerService.getInstance().getUserIds()) {
if (!mSettings.areDefaultRuntimePermissionsGrantedLPr(userId)) {
grantPermissionsUserIds = ArrayUtils.appendInt(
grantPermissionsUserIds, userId);
}
}
}
sUserManager.systemReady();//多用户服务
// If we upgraded grant all default permissions before kicking off.
//升级所有已获取的默认权限
for (int userId : grantPermissionsUserIds) {
mDefaultPermissionPolicy.grantDefaultPermissions(userId);
}
// Kick off any messages waiting for system ready
//处理所有等待系统准备就绪的消息
if (mPostSystemReadyMessages != null) {
for (Message msg : mPostSystemReadyMessages) {
msg.sendToTarget();
}
mPostSystemReadyMessages = null;
}
// Watch for external volumes that come and go over time
//观察外部存储设备
final StorageManager storage = mContext.getSystemService(StorageManager.class);
storage.registerListener(mStorageListener);
mInstallerService.systemReady();
mPackageDexOptimizer.systemReady();
MountServiceInternal mountServiceInternal = LocalServices.getService(
MountServiceInternal.class);
mountServiceInternal.addExternalStoragePolicy(
new MountServiceInternal.ExternalStorageMountPolicy() {
@Override
public int getMountMode(int uid, String packageName) {
if (Process.isIsolated(uid)) {
return Zygote.MOUNT_EXTERNAL_NONE;
}
if (checkUidPermission(WRITE_MEDIA_STORAGE, uid) == PERMISSION_GRANTED) {
return Zygote.MOUNT_EXTERNAL_DEFAULT;
}
if (checkUidPermission(READ_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) {
return Zygote.MOUNT_EXTERNAL_DEFAULT;
}
if (checkUidPermission(WRITE_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) {
return Zygote.MOUNT_EXTERNAL_READ;
}
return Zygote.MOUNT_EXTERNAL_WRITE;
}
@Override
public boolean hasExternalStorage(int uid, String packageName) {
return true;
}
});
// Now that we're mostly running, clean up stale users and apps
reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);
reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL);
}
至此,PackageManagerService启动流程分析完毕,如有错误之处,欢迎留言指正。