本文源代码基于 Android 7.0。
- /base/services/java/com/android/server/SystemServer.java
- /base/services/core/java/com/android/server/pm/PackageManagerService.java
- /base/services/core/java/com/android/server/pm/Settings.java
- /base/core/java/com/android/server/SystemConfig.java
- /system/core/rootdir/init.rc
- /base/cmds/installd/installd.cpp
- /base/cmds/installd/commands.cpp
- /base/cmds/installd/utils.cpp
- /base/services/core/java/com/android/server/pm/Installer.java
- /base/core/java/com/android/internal/os/InstallerConnection.java
PackageManagerService(PKMS),是 Android 系统中核心服务之一,管理着所有跟 package 相关的工作,常见的比如安装、卸载应用。
目录:
- PKMS 的启动过程
- Installd 守护进程
- Installer
1. PMS 的启动过程
- 1.1 SystemServer.startBootstrapServices()
PKMS 也是运行在 system_server 进程的,看看 SystemServer 的 startBootstrapServices():
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
- 1.2 PKMS.main()
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
PackageManagerServiceCompilerMapping.checkProperties();
// 构造一个包管理服务对象,new PackageManagerService
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
m.enableSystemUserPackages();
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.3 阶段1:BOOT_PROGRESS_PMS_START
阶段1 PMS_START 有两部分组成,由无需加锁的前部分和同时持有两个锁的后半部分,先来说说前半部分:
//向事件日志写入事件,标识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();
接下来,再来看看后半部分:
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);
}
................
}
这个过程涉及的几个重要变量:
- mAppDataDir: /data/data
- mAppLib32InstallDir: /data/app-lib
- mAsecInternalPath: /data/app-asec
- mUserAppDataDir: /data/user
- mAppInstallDir: /data/app
- mDrmAppPrivateInstallDir: /data/app-private
在阶段1中创建了 Settings 对象,来看看里面做了什么:
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个文件:
- packages.xml: 记录所有安装的 app 信息
- packages-backup.xml: 备份文件
- packages-stopped.xml: 记录系统被强制停止的文件
- packages-stopped-backup.xml: 备份文件
- packages.list: 记录应用的数据信息
阶段1中还调用 SystemConfig.getInstance() 方法来获取 SystemConfig:
public static SystemConfig getInstance() {
synchronized (SystemConfig.class) {
if (sInstance == null) {
sInstance = new SystemConfig();
}
return sInstance;
}
}
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
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 为后缀文件。
- 1.4 阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START
//标记扫描开始的时间
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
- 1.5 阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START
/ 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
- 1.6 阶段4:BOOT_PROGRESS_PMS_SCAN_END
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());
}
- 1.7 阶段5:BOOT_PROGRESS_PMS_READY
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());
- 1.8 PackageInstaller 服务
PKMS 初始化完成阶段,还会创建一个 PackageInstaller 服务。
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;
- 1.9 PKMS.systemReady
@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) {
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;
}
});
reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);
reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL);
}
至此,PackageManagerService 启动流程分析完毕。
2. Installd 守护进程
PKMS 服务负责应用的安装、卸载等相关工作,而真正干活的还是 installd。其中 PKMS 执行权限为 system,而进程 installd 的执行权限为 root。
- 2.1 简介
installd 是由 Android 系统的 init 进程 (pid=1),在解析 init.rc 文件的如下代码块时,通过 fork 创建的用户空间的守护进程 installd。
service installd /system/bin/installd
class main
socket installd stream 600 system system
installd 是随着系统启动过程中 main class 而启动的,并且会创建一个 socket 套接字,用于跟上层的 PKMS 进行交互。
installd 的启动入口 /base/cmds/installd/installd.c 的 main() 方法,接下来从这里开始说起。
- 2.2 installd 启动
installd.cpp
int main(const int argc __unused, char *argv[]) {
char buf[BUFFER_MAX]; //buffer大小为1024Byte
struct sockaddr addr;
socklen_t alen;
int lsocket, s;
...
//初始化全局信息
if (initialize_globals() < 0) {
exit(1);
}
//初始化相关目录
if (initialize_directories() < 0) {
exit(1);
}
//获取套接字"installd"
lsocket = android_get_control_socket(SOCKET_PATH);
if (listen(lsocket, 5)) { //监听socket消息
exit(1);
}
fcntl(lsocket, F_SETFD, FD_CLOEXEC);
for (;;) {
alen = sizeof(addr);
s = accept(lsocket, &addr, &alen); //接受socket消息
if (s < 0) {
continue;
}
fcntl(s, F_SETFD, FD_CLOEXEC);
for (;;) {
unsigned short count;
//读取指令的长度
if (readx(s, &count, sizeof(count))) {
break;
}
if ((count < 1) || (count >= BUFFER_MAX)) {
break;
}
//读取指令的内容
if (readx(s, buf, count)) {
break;
}
buf[count] = 0;
...
//执行指令
if (execute(s, buf)) break;
}
close(s);
}
return 0;
}
installd 进程,通过监听套接字 "installd",当接收到 socket 消息则执行相应的指令。
int initialize_globals() {
// 数据目录/data/
if (get_path_from_env(&android_data_dir, "ANDROID_DATA") < 0) {
return -1;
}
// app目录/data/app/
if (copy_and_append(&android_app_dir, &android_data_dir, APP_SUBDIR) < 0) {
return -1;
}
// 受保护的app目录/data/priv-app/
if (copy_and_append(&android_app_private_dir, &android_data_dir, PRIVATE_APP_SUBDIR) < 0) {
return -1;
}
// app本地库目录/data/app-lib/
if (copy_and_append(&android_app_lib_dir, &android_data_dir, APP_LIB_SUBDIR) < 0) {
return -1;
}
// sdcard挂载点/mnt/asec
if (get_path_from_env(&android_asec_dir, "ASEC_MOUNTPOINT") < 0) {
return -1;
}
// 多媒体目录/data/media
if (copy_and_append(&android_media_dir, &android_data_dir, MEDIA_SUBDIR) < 0) {
return -1;
}
// 外部app目录/mnt/expand
if (get_path_from_string(&android_mnt_expand_dir, "/mnt/expand/") < 0) {
return -1;
}
// 系统和厂商目录
android_system_dirs.count = 4;
android_system_dirs.dirs = (dir_rec_t*) calloc(android_system_dirs.count, sizeof(dir_rec_t));
...
dir_rec_t android_root_dir;
// 目录/system
if (get_path_from_env(&android_root_dir, "ANDROID_ROOT") < 0) {
return -1;
}
// 目录/system/app
android_system_dirs.dirs[0].path = build_string2(android_root_dir.path, APP_SUBDIR);
android_system_dirs.dirs[0].len = strlen(android_system_dirs.dirs[0].path);
// 目录/system/app-lib
android_system_dirs.dirs[1].path = build_string2(android_root_dir.path, PRIV_APP_SUBDIR);
android_system_dirs.dirs[1].len = strlen(android_system_dirs.dirs[1].path);
// 目录/vendor/app/
android_system_dirs.dirs[2].path = strdup("/vendor/app/");
android_system_dirs.dirs[2].len = strlen(android_system_dirs.dirs[2].path);
// 目录/oem/app/
android_system_dirs.dirs[3].path = strdup("/oem/app/");
android_system_dirs.dirs[3].len = strlen(android_system_dirs.dirs[3].path);
return 0;
}
int initialize_directories() {
int res = -1;
//读取当前文件系统版本
char version_path[PATH_MAX];
snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path);
int oldVersion;
if (fs_read_atomic_int(version_path, &oldVersion) == -1) {
oldVersion = 0;
}
int version = oldVersion;
// 目录/data/user
char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX);
// 目录/data/data
char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX);
// 目录/data/user/0
char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, "0");
...
//将/data/user/0链接到/data/data
if (access(primary_data_dir, R_OK) < 0) {
if (symlink(legacy_data_dir, primary_data_dir)) {
goto fail;
}
}
... //处理data/media 相关
return res;
}
static int execute(int s, char cmd[BUFFER_MAX]) {
char reply[REPLY_MAX];
char *arg[TOKEN_MAX+1];
unsigned i;
unsigned n = 0;
unsigned short count;
int ret = -1;
reply[0] = 0;
arg[0] = cmd;
while (*cmd) {
if (isspace(*cmd)) {
*cmd++ = 0;
n++;
arg[n] = cmd;
if (n == TOKEN_MAX) {
goto done;
}
}
if (*cmd) {
cmd++; //计算参数个数
}
}
for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
if (!strcmp(cmds[i].name,arg[0])) {
if (n != cmds[i].numargs) {
//参数个数不匹配,直接返回
ALOGE("%s requires %d arguments (%d given)\n",
cmds[i].name, cmds[i].numargs, n);
} else {
//执行相应的命令
ret = cmds[i].func(arg + 1, reply);
}
goto done;
}
}
done:
if (reply[0]) {
n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply);
} else {
n = snprintf(cmd, BUFFER_MAX, "%d", ret);
}
if (n > BUFFER_MAX) n = BUFFER_MAX;
count = n;
//将命令执行后的返回值写入socket套接字
if (writex(s, &count, sizeof(count))) return -1;
if (writex(s, cmd, count)) return -1;
return 0;
}
- 2.3 命令表
struct cmdinfo cmds[] = {
{ "ping", 0, do_ping },
{ "install", 5, do_install }, //安装app
{ "dexopt", 9, do_dexopt }, //dex优化
{ "markbootcomplete", 1, do_mark_boot_complete },
{ "movedex", 3, do_move_dex },
{ "rmdex", 2, do_rm_dex },
{ "remove", 3, do_remove },
{ "rename", 2, do_rename },
{ "fixuid", 4, do_fixuid },
{ "freecache", 2, do_free_cache },
{ "rmcache", 3, do_rm_cache },
{ "rmcodecache", 3, do_rm_code_cache },
{ "getsize", 8, do_get_size },
{ "rmuserdata", 3, do_rm_user_data },
{ "cpcompleteapp", 6, do_cp_complete_app },
{ "movefiles", 0, do_movefiles },
{ "linklib", 4, do_linklib },
{ "mkuserdata", 5, do_mk_user_data },
{ "mkuserconfig", 1, do_mk_user_config },
{ "rmuser", 2, do_rm_user },
{ "idmap", 3, do_idmap },
{ "restorecondata", 4, do_restorecon_data },
{ "createoatdir", 2, do_create_oat_dir },
{ "rmpackagedir", 1, do_rm_package_dir },
{ "linkfile", 3, do_link_file }
};
此命令表总共有25的命令,该表中第二列是指命令所需的参数个数,第三列是指命令所指向的函数。不同的 Android 版本该表格都会有所不同。
3. Installer
当守护进程 installd 启动完成后,上层 framework 便可以通过 socket 跟该守护进程进行通信。 在 SystemServer 启动服务的过程中创建 Installer 对象,便会有一次跟 installd 通信的过程。
SystemServer.java
private void startBootstrapServices() {
//启动installer服务
Installer installer = mSystemServiceManager.startService(Installer.class);
...
}
Installer.java
public Installer(Context context) {
super(context);
// 创建InstallerConnection对象
mInstaller = new InstallerConnection();
}
public void onStart() {
Slog.i(TAG, "Waiting for installd to be ready.");
mInstaller.waitForConnection();
}
先创建 Installer 对象,再调用 onStart() 方法,该方法中主要工作是等待 socket 通道建立完成。
InstallerConnection.java
public void waitForConnection() {
for (;;) {
try {
execute("ping");
return;
} catch (InstallerException ignored) {
}
Slog.w(TAG, "installd not ready");
SystemClock.sleep(1000);
}
}
public String[] execute(String cmd, Object... args) throws InstallerException {
final StringBuilder builder = new StringBuilder(cmd);
for (Object arg : args) {
String escaped;
if (arg == null) {
escaped = "";
} else {
escaped = String.valueOf(arg);
}
if (escaped.indexOf('\0') != -1 || escaped.indexOf(' ') != -1 || "!".equals(escaped)) {
throw new InstallerException(
"Invalid argument while executing " + cmd + " " + Arrays.toString(args));
}
if (TextUtils.isEmpty(escaped)) {
escaped = "!";
}
builder.append(' ').append(escaped);
}
// 执行transact函数
final String[] resRaw = transact(builder.toString()).split(" ");
int res = -1;
try {
res = Integer.parseInt(resRaw[0]);
} catch (ArrayIndexOutOfBoundsException | NumberFormatException ignored) {
}
if (res != 0) {
throw new InstallerException(
"Failed to execute " + cmd + " " + Arrays.toString(args) + ": " + res);
}
return resRaw;
}
/**
* 可见,一次transact过程为先connect()来判断是否建立socket连接,如果已连接则通过writeCommand() 将命令写入socket的mOut管道,
* 等待从管道的mIn中readFully()读取应答消息。
*
* 上层PackageManagerService收集完相应信息,通过socket交给守护进程installd,该进程才是真正干活的进程。
*/
public synchronized String transact(String cmd) {
if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) {
Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x"
+ Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable());
}
if (!connect()) {
Slog.e(TAG, "connection failed");
return "-1";
}
if (!writeCommand(cmd)) {
/*
* If installd died and restarted in the background (unlikely but
* possible) we'll fail on the next write (this one). Try to
* reconnect and write the command one more time before giving up.
*/
Slog.e(TAG, "write command failed? reconnect!");
if (!connect() || !writeCommand(cmd)) {
return "-1";
}
}
if (LOCAL_DEBUG) {
Slog.i(TAG, "send: '" + cmd + "'");
}
final int replyLength = readReply();
if (replyLength > 0) {
String s = new String(buf, 0, replyLength);
if (LOCAL_DEBUG) {
Slog.i(TAG, "recv: '" + s + "'");
}
return s;
} else {
if (LOCAL_DEBUG) {
Slog.i(TAG, "fail");
}
return "-1";
}
}
private boolean connect() {
if (mSocket != null) {
return true;
}
Slog.i(TAG, "connecting...");
try {
mSocket = new LocalSocket();
LocalSocketAddress address = new LocalSocketAddress("installd",
LocalSocketAddress.Namespace.RESERVED);
mSocket.connect(address);
mIn = mSocket.getInputStream();
mOut = mSocket.getOutputStream();
} catch (IOException ex) {
disconnect();
return false;
}
return true;
}
public void disconnect() {
Slog.i(TAG, "disconnecting...");
IoUtils.closeQuietly(mSocket);
IoUtils.closeQuietly(mIn);
IoUtils.closeQuietly(mOut);
mSocket = null;
mIn = null;
mOut = null;
}
private boolean readFully(byte[] buffer, int len) {
try {
Streams.readFully(mIn, buffer, 0, len);
} catch (IOException ioe) {
Slog.e(TAG, "read exception");
disconnect();
return false;
}
if (LOCAL_DEBUG) {
Slog.i(TAG, "read " + len + " bytes");
}
return true;
}
private int readReply() {
if (!readFully(buf, 2)) {
return -1;
}
final int len = (((int) buf[0]) & 0xff) | ((((int) buf[1]) & 0xff) << 8);
if ((len < 1) || (len > buf.length)) {
Slog.e(TAG, "invalid reply length (" + len + ")");
disconnect();
return -1;
}
if (!readFully(buf, len)) {
return -1;
}
return len;
}
可见,一次 transact 过程为先 connect() 来判断是否建立 socket 连接,如果已连接则通过 writeCommand() 将命令写入 socket的 mOut 管道,等待从管道的 mIn 中 readFully() 读取应答消息。
上层 PKMS 收集完相应信息,通过 socket 交给守护进程 installd,该进程才是真正干活的进程。