PackageManagerService是android系统核心服务之一,它主要负责的工作如下: 一. 解析AndroidManifest.xml文件,解析清单文件中的所有节点信息。 二. 扫描.apk文件,安装系统应用,本地应用等。 三. 管理本地应用,主要有:安装、卸载、应用信息查询等。
概述 Android系统启动时,会启动(应用程序管理服务器PKMS),此服务负责扫描系统中特定的目录,寻找里面的APK格式的文件,并对这些文件进行解析,然后得到应用程序相关信息,最后完成应用程序的安装
PKMS在安装应用过程中, 会全面解析应用程序的AndroidManifest.xml文件, 来得到Activity, Service, BroadcastReceiver, ContextProvider 等信息, 在结合PKMS服务就可以在OS中正常的使用应用程序了
在Android系统中, 系统启动时由SystemServer启动PKMS服务, 启动该服务后会执行应用程序的安装过程
PKMS架构设计 类图关系
继承关系
注意: 客户端可通过Context.getPackageManager()获得ApplicationPackageManager对象, 而mPM指向的是Proxy代理,当调用到mPM.方法后,将会调用到IPackageManager的Proxy代理方法, 然后通过Binder机制中的mRemote与服务端PackageManagerService通信 并调用到PackageManagerService的方法; 自我总结:PKMS是属于Binder机制的服务端角色
PKMS启动过程
启动过程描述: SystemServer启动PKMS:先是在SystemServer.startBootstrapServices()函数中启动PKMS服务,再调用startOtherServices()函数中对dex优化,磁盘管理功能,让PKMS进入SystemReady状态。
SystemServer的启动 SystemServer七部曲
调用startBootstrapServices()服务
SystemServer启动Boot服务
1 (1 ) 启动Installer服务:mSystemServiceManager.startService(Installer.class);
1 2 (2 ) 获取设备是否加密(手机设置密码),如果设备加密了,则只解析"core" 应用 String cryptState = VoldProperties.decrypt().orElse("" );
1 2 3 4 5 6 (3 ) 调用PKMS.main()方法初始化PackageManagerService PackageManagerService.main(mSystemContext,installer,mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore); ServiceManager.addService("package" ,m); final PackageManagerNative pmn = m.new PackageManagerNative () ; ServiceManager.addService("package_native" , pmn);
1 2 (4 ) 如果设备没有加密,操作它。管理A/B OTA dexopting if (!mOnlyCore)
startBootstrapServices源码
SystemServer.java startBootstrapServices() 说明:startBootstrapServices()首先启动Installer服务,也就是安装器,随后判断当前的设备是否是出于加密状态。如果是出于加密状态则只是解析核心应用,接着调用PackageManagerService的静态方法main来创建PKMS对象。 (1) 启动Installer对象 (2) 获取设备是否加密(手机设置密码),如果设备加密了,则只解析”core”应用。 (3) 调用PKMS main方法初始化PackageManagerService,其中调用PackageManagerService()构造方法创建了PKMS对象。 (4) 如果设备没有加密,操作它。管理A/B OTA dexopting。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 private void startBootstrapServices (@NonNull TimingsTraceAndSlog t) { Installer installer = mSystemServiceManager.startService(Installer.class); mActivityManagerService = ActivityManagerService.Lifecycle.startService( mSystemServiceManager, atm); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); String cryptState = VoldProperties.decrypt().orElse("" ); if (ENCRYPTING_STATE.equals(cryptState)) { Slog.w(TAG, "Detected encryption in progress - only parsing core apps" ); mOnlyCore = true ; } else if (ENCRYPTED_STATE.equals(cryptState)) { Slog.w(TAG, "Device encrypted - only parsing core apps" ); mOnlyCore = true ; } mPackageManagerService = PackageManagerService.main(mSystemContext, installer, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); mFirstBoot = mPackageManagerService.isFirstBoot(); mPackageManager = mSystemContext.getPackageManager(); if (!mOnlyCore) { boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt" , false ); if (!disableOtaDexopt) { t.traceBegin("StartOtaDexOptService" ); try { Watchdog.getInstance().pauseWatchingCurrentThread("moveab" ); OtaDexoptService.main(mSystemContext, mPackageManagerService); } catch (Throwable e) { reportWtf("starting OtaDexOptService" , e); } finally { Watchdog.getInstance().resumeWatchingCurrentThread("moveab" ); t.traceEnd(); } } } }
调用startOtherServices()方法
SystemServer启动其他服务,并使一些核心服务处于ready状态
1 2 3 4 5 6 7 8 (5 ) mPackageManagerService.updatePackagesIfNeeded(); 该方法,作用:检查是否需要去更新Packages并进行dex优化。 条件:没有OTA升级,没有大版本升级, 没有清除过dalvik虚拟机的缓存,可以去更新Packages。 更新Packages的优先级:core app > system app > other app,调用performDexOptUpgrade()方法进行更新
1 2 (6 ) mPackageManagerService.performFstrimIfNeeded();
1 2 3 (7 ) mPackageManagerService.systemReady(mActivityManagerService.getAppOpsService()); DefaultPermissionPolicy.grantDefaultPermissions(userId);
startOtherServices源码
[SystemServer.java] startOtherServices() (5) 执行updatePackageIfNeeded,完成dex优化 (6) 执行performFstrimIfNeeded,完成磁盘维护 (7) 调用systemReady,准备就绪
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 private void startOtherServices (@NonNull TimingsTraceAndSlog t) { if (!mOnlyCore) { try { Watchdog.getInstance().pauseWatchingCurrentThread("dexopt" ); mPackageManagerService.updatePackagesIfNeeded(); } catch (Throwable e) { reportWtf("update packages" , e); } finally { Watchdog.getInstance().resumeWatchingCurrentThread("dexopt" ); } } try { mPackageManagerService.performFstrimIfNeeded(); } catch (Throwable e) { reportWtf("performing fstrim" , e); } mPackageManagerService.systemReady(); }
PKMS构造初始化 PKMS.main main函数主要工作: (1) 检查Package编译相关系统属性 (2) 调用PackageManagerService构造方法 (3) 启用部分应用服务于多用户场景 (4) 往ServiceManager中注册 “package” 和 “package_native’。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public static PackageManagerService main (Context context, Installer installer, boolean factoryTest, boolean onlyCore) { PackageManagerServiceCompilerMapping.checkProperties(); PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest); m.installWhitelistedSystemPackages(); ServiceManager.addService("package" , m); final PackageManagerNative pmn = m.new PackageManagerNative () ; ServiceManager.addService("package_native" , pmn); return m; }
【总结回顾】
1 2 3 创建PackageManagerService并向ServiceManager注册 创建PackageManagerNative并向ServiceManager注册
PKMS构造
PKMS 初始化时的核心部分为PackageManagerService的构造函数的内容,现在我们来看一下该函数。
此函数由两个重要的锁(mInstallLock和mLock)和五个阶段构成。在Android 11.0源码中是由(mInstallLock和mPackages)两个锁
mInstallLock、mLock:用来保护所有安装apk的访问权限,此操作通常涉及繁重的磁盘数据读写等操作。并且是单线程操作,所以有时候会处理很慢。此锁不会在已经持有了mLock锁的情况下加锁,反之,在已经持有mInstallLock锁的情况下,立即获得mLock是安全的。
mPackages(mLock):用来解析内存中所有apk的package信息及相关状态。
PKMS服务也是通过Binder进行通信,IPackageManager.aidl由工具转换后自动生成Binder的服务端IPackageManager.Stub和客户端IPackageManager.Stub.Proxy。
Binder服务端:PackageManagerService继承自IPackageManager.Stub
Binder客户端:ApplicationPackageManager(简称APM)的成员变量mPm继承于IPackageManager.Stub.Proxy。本身APM继承与PackageManager对象。
五个阶段
1 2 3 4 5 6 7 5个阶段构成,下面会详细的来分析这些内容。 阶段1:BOOT_PROGRESS_PMS_START 开始阶段 阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START 系统扫描阶段 阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_START Data扫描阶段 阶段4:BOOT_PROGRESS_PMS_SCAN_END 扫描结束 阶段5:BOOT_PROGRESS_PMS_READY 就绪阶段
阶段1,阶段2,阶段3,阶段4,阶段5 的 EventLog
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public PackageManagerService(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { ... // 阶段1:BOOT_PROGRESS_PMS_START EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START, SystemClock.uptimeMillis()); // 阶段2:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START, startTime); ... // 阶段3:BOOT_PROGRESS_PMS_DATA_SCAN_STAR if (!mOnlyCore) { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START, SystemClock.uptimeMillis()); } ... // 阶段4:BOOT_PROGRESS_PMS_SCAN_END EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END, SystemClock.uptimeMillis()); ... // 阶段5:BOOT_PROGRESS_PMS_READY EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY, SystemClock.uptimeMillis()); }
阶段一
BOOT_PROGRESS_PMS_START 开始阶段
主要工作: (1) 构造 DisplayMetrics,保存分辨率相关信息。 (2) 创建Installer对象,与installd交互 (3) 创建mPermissionManager对象,进行权限管理 (4) 构造Settings类,保存安装包信息,清除路径不存在的孤立应用,主要涉及/data/system/目录的packages.xml, packages-backup.xml,packages.list,packages-stopped.xml,packages-stopped-backup.xml等文件。 (5) 构造PackageDexOptimizer及DexManager类,处理dex优化; (6) 创建SystemConfig实例,获取系统配置信息,配置共享lib库; (7) 创建PackageManager的Handler线程,循环处理外部安装相关消息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 public PackageManagerService (Injector injector, boolean onlyCore, boolean factoryTest) { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START, SystemClock.uptimeMillis()); if (mSdkVersion <= 0 ) { Slog.w(TAG, "**** ro.build.version.sdk not set!" ); } mFactoryTest = factoryTest; mOnlyCore = onlyCore; mMetrics = new DisplayMetrics(); mInstaller = injector.getInstaller(); LocalServices.addService(PackageManagerInternal.class, mPmInternal); mUserManager = injector.getUserManagerService(); mComponentResolver = injector.getComponentResolver(); mPermissionManager = injector.getPermissionManagerServiceInternal(); mSettings = injector.getSettings(); 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); mSettings.addSharedUserLPw("android.uid.se" , SE_UID, ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); mSettings.addSharedUserLPw("android.uid.networkstack" , NETWORKSTACK_UID, ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); mPackageDexOptimizer = new PackageDexOptimizer(mInstaller, mInstallLock, mContext, "*dexopt*" ); mDexManager = new DexManager(mContext, this , mPackageDexOptimizer, mInstaller, mInstallLock); mArtManagerService = new ArtManagerService(mContext, this , mInstaller, mInstallLock); getDefaultDisplayMetrics(mInjector.getDisplayManager(), mMetrics); SystemConfig systemConfig = SystemConfig.getInstance(); synchronized (mInstallLock) { synchronized (mLock) { mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, true ); mHandlerThread.start(); mHandler = new PackageHandler(mHandlerThread.getLooper()); mProcessLoggingHandler = new ProcessLoggingHandler(); Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT); mInstantAppRegistry = new InstantAppRegistry(this ); ArrayMap<String, SystemConfig.SharedLibraryEntry> libConfig = systemConfig.getSharedLibraries(); final int builtInLibCount = libConfig.size(); for (int i = 0 ; i < builtInLibCount; i++) { String name = libConfig.keyAt(i); SystemConfig.SharedLibraryEntry entry = libConfig.valueAt(i); addBuiltInSharedLibraryLocked(entry.filename, name); } SELinuxMMAC.readInstallPolicy(); FallbackCategoryProvider.loadFallbacks(); mFirstBoot = !mSettings.readLPw(mInjector.getUserManagerInternal().getUsers(false )); final int packageSettingCount = mSettings.mPackages.size(); for (int i = packageSettingCount - 1 ; i >= 0 ; i--) { PackageSetting ps = mSettings.mPackages.valueAt(i); if (!isExternal(ps) && (ps.codePath == null || !ps.codePath.exists()) && mSettings.getDisabledSystemPkgLPr(ps.name) != null ) { mSettings.mPackages.removeAt(i); mSettings.enableSystemPackageLPw(ps.name); } } if (!mOnlyCore && mFirstBoot) { requestCopyPreoptedFiles(); } ...... } } }
【总结回顾】
1 2 3 这里主要是对一些属性和子服务进行了创建或赋值,其中比较重要的有mInstaller、mSettings、mPackageDexOptimizer等。 在之前的有些版本,mSettings等有些属性是在这里直接new的,而现在采用传入Injector的方式来获取。另外、这里还开启了工作线程。
readLPw()会扫描下面5个文件
“/data/system/packages.xml” // 所有安装app信息
“/data/system/packages-backup.xml” // 所有安装app信息的备份的信息记录
“/data/system/packages.list” // 所有安装app信息
“/data/system/packages-stopped.xml” // 所有强制停止app信息
“/data/system/packages-stopped-backup.xml” // 所以强制停止app信息的备份的信息记录
5个文件共分为三组,简单的作用描述如下:
packages.xml: PKMS扫描完成目标文件夹之后会创建该文件。当系统进行程序安装、卸载和更新等操作时,均会更新该文件。该文件保存了系统中与 package相关的一些信息。
packages.list: 描述系统中存在的所有非系统自带的apk的信息。当这些程序有变动时 PKMS 就会更新该文件。
packages-stopped.xml : 从系统自带的设置程序中进入应用程序页面,然后再选择强制停止(ForceStop) 某个应用时,系统会将该应用的相关信息记录到此文件中。也就是该文件保存系统中被用户强制停止的 package 的信息。
这些目录的指向,都在settings中的构造函数中完成,如下所示,得到目录后调用readLpw()进行扫描。
看一下settings的构造函数(package com.android.server.pm)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 private final File mSettingsFilename;private final File mBackupSettingsFilename;private final File mPackageListFilename;private final File mStoppedPackagesFilename;private final File mBackupStoppedPackagesFilename;private final File mKernelMappingFilename;final ArrayMap<String, PackageSetting> mPackages = new ArrayMap<>();Settings(File dataDir, PermissionSettings permission, Object lock) { mLock = lock; mPermissions = permission; mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock); mSystemDir = new File(dataDir, "system" ); mSystemDir.mkdirs(); FileUtils.setPermissions(mSystemDir.toString(), FileUtils.S_IRWXU|FileUtils.S_IRWXG |FileUtils.S_IROTH|FileUtils.S_IXOTH, -1 , -1 ); mSettingsFilename = new File(mSystemDir, "packages.xml" ); mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml" ); mPackageListFilename = new File(mSystemDir, "packages.list" ); FileUtils.setPermissions(mPackageListFilename, 0640 , SYSTEM_UID, PACKAGE_INFO_GID); final File kernelDir = new File("/config/sdcardfs" ); mKernelMappingFilename = kernelDir.exists() ? kernelDir : null ; mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml" ); mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml" ); }
解析上面这几个xml的内容,建立对应的数据结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 Setting.java boolean readLPw (@NonNull List<UserInfo> users) { FileInputStream str = null ; if (str == null ) { str = new FileInputStream(mSettingsFilename); } XmlPullParser parser = Xml.newPullParser(); parser.setInput(str, StandardCharsets.UTF_8.name()); int type; while ((type = parser.next()) != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { ; } if (type != XmlPullParser.START_TAG) { mReadMessages.append("No start tag found in settings file\n" ); PackageManagerService.reportSettingsProblem(Log.WARN, "No start tag found in package manager settings" ); Slog.wtf(PackageManagerService.TAG, "No start tag found in package manager settings" ); return false ; } int outerDepth = parser.getDepth(); while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { continue ; } String tagName = parser.getName(); if (tagName.equals("package" )) { readPackageLPw(parser); } else if (tagName.equals("permissions" )) { mPermissions.readPermissions(parser); } else if (tagName.equals("permission-trees" )) { mPermissions.readPermissionTrees(parser); } else if (tagName.equals("shared-user" )) { readSharedUserLPw(parser); } ..... str.close(); for (int i = 0 ; i < N; i++) { final PackageSetting p = mPendingPackages.get(i); final int sharedUserId = p.getSharedUserId(); final Object idObj = getSettingLPr(sharedUserId); if (idObj instanceof SharedUserSetting) { final SharedUserSetting sharedUser = (SharedUserSetting) idObj; p.sharedUser = sharedUser; p.appId = sharedUser.userId; addPackageSettingLPw(p, sharedUser); } return true ; }
说明:创建 SharedUserSetting 对象并添加到 Settings 的成员变量 mSharedUsers 中,在 Android 系统中, 多个 package 通过设置 sharedUserId 属性可以运行在同一个进程,共享同一个 UID。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 mSettings.addSharedUserLPw("android.uid.system" , Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); SharedUserSetting addSharedUserLPw (String name, int uid, int pkgFlags, int pkgPrivateFlags) { SharedUserSetting s = mSharedUsers.get(name); if (s != null ) { if (s.userId == uid) { return s; } PackageManagerService.reportSettingsProblem(Log.ERROR, "Adding duplicate shared user, keeping first: " + name); return null ; } s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags); s.userId = uid; if (registerExistingAppIdLPw(uid, s, name)) { mSharedUsers.put(name, s); return s; } return null ; }
【总结回顾】
1 2 3 4 初始化PMS的各个子组件/子服务以及相关属性 解析package.xml,获取已经安装的App信息,存储到Settings的mPackages中 创建了后台工作线程及其Handler
阶段二
BOOT_PROGRESS_PMS_SYSTEM_SCAN_START 系统扫描阶段
主要工作: (1) 从init.rc中获取环境变量BOOTCLASSPATH和SYSTEMSERVERCLASSPATH; (2) 对于旧版本升级的情况,将安装时获取权限变更为运行时申请权限; (3) 扫描system/vendor/product/odm/oem等目录的priv-app、app、overlay包; (4) 清除安装时临时文件以及其他不必要的信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 public PackageManagerService (Context context, Installer installer, boolean factoryTest, boolean onlyCore) { long startTime = SystemClock.uptimeMillis(); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SYSTEM_SCAN_START, startTime); final String bootClassPath = System.getenv("BOOTCLASSPATH" ); final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH" ); File frameworkDir = new File(Environment.getRootDirectory(), "framework" ); final VersionInfo ver = mSettings.getInternalVersion(); mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint); mPromoteSystemApps = mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1; mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N; mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1; mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q; if (isDeviceUpgrading()) { mExistingPackages = new ArraySet<>(mSettings.mPackages.size()); for (PackageSetting ps : mSettings.mPackages.values()) { mExistingPackages.add(ps.name); } } mCacheDir = preparePackageParserCache(); int scanFlags = SCAN_BOOTING | SCAN_INITIAL; for (int i = mDirsToScanAsSystem.size() - 1 ; i >= 0 ; i--) { final ScanPartition partition = mDirsToScanAsSystem.get(i); if (partition.getOverlayFolder() == null ) { continue ; } scanDirTracedLI(partition.getOverlayFolder(), systemParseFlags, systemScanFlags | partition.scanFlag, 0 , packageParser, executorService); } scanDirTracedLI(frameworkDir, systemParseFlags, systemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED, 0 , packageParser, executorService); if (!mPackages.containsKey("android" )) { throw new IllegalStateException( "Failed to load frameworks package; check log for warnings" ); } for (int i = 0 , size = mDirsToScanAsSystem.size(); i < size; i++) { final ScanPartition partition = mDirsToScanAsSystem.get(i); if (partition.getPrivAppFolder() != null ) { scanDirTracedLI(partition.getPrivAppFolder(), systemParseFlags, systemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, 0 , packageParser, executorService); } scanDirTracedLI(partition.getAppFolder(), systemParseFlags, systemScanFlags | partition.scanFlag, 0 , packageParser, executorService); } if (!mOnlyCore) { final Iterator<AndroidPackage> pkgIterator = mPackages.values().iterator(); while (pkgIterator.hasNext()) { final AndroidPackage pkg = pkgIterator.next(); if (pkg.isStub()) { stubSystemApps.add(pkg.getPackageName()); } } final Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator(); while (psit.hasNext()) { PackageSetting ps = psit.next(); if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0 ) { continue ; } final AndroidPackage scannedPkg = mPackages.get(ps.name); if (scannedPkg != null ) { if (mSettings.isDisabledSystemPackageLPr(ps.name)) { logCriticalInfo(Log.WARN, "Expecting better updated system app for " + ps.name + "; removing system app. Last known" + " codePath=" + ps.codePathString + ", versionCode=" + ps.versionCode + "; scanned versionCode=" + scannedPkg.getLongVersionCode()); removePackageLI(scannedPkg, true ); mExpectingBetter.put(ps.name, ps.codePath); } continue ; } mSettings.pruneSharedUsersLPw(); ...... }
分析上面调用的 scanDirTracedLI
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 private void scanDirTracedLI (File scanDir, final int parseFlags, int scanFlags, long currentTime, PackageParser2 packageParser, ExecutorService executorService) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]" ); try { scanDirLI(scanDir, parseFlags, scanFlags, currentTime, packageParser, executorService); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } private void scanDirLI (File scanDir, int parseFlags, int scanFlags, long currentTime, PackageParser2 packageParser, ExecutorService executorService) { final File[] files = scanDir.listFiles(); if (ArrayUtils.isEmpty(files)) { Log.d(TAG, "No files in app dir " + scanDir); return ; } if (DEBUG_PACKAGE_SCANNING) { Log.d(TAG, "Scanning app dir " + scanDir + " scanFlags=" + scanFlags + " flags=0x" + Integer.toHexString(parseFlags)); } ParallelPackageParser parallelPackageParser = new ParallelPackageParser(packageParser, executorService); int fileCount = 0 ; for (File file : files) { final boolean isPackage = (isApkFile(file) || file.isDirectory()) && !PackageInstallerService.isStageName(file.getName()); if (!isPackage) { continue ; } parallelPackageParser.submit(file, parseFlags); fileCount++; } for (; fileCount > 0 ; fileCount--) { ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take(); Throwable throwable = parseResult.throwable; int errorCode = PackageManager.INSTALL_SUCCEEDED; if (throwable == null ) { if (parseResult.parsedPackage.isStaticSharedLibrary()) { renameStaticSharedLibraryPackage(parseResult.parsedPackage); } try { addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags, currentTime, null ); } catch (PackageManagerException e) { ... } } else ... if ((scanFlags & SCAN_AS_SYSTEM) == 0 && errorCode != PackageManager.INSTALL_SUCCEEDED) { logCriticalInfo(Log.WARN, "Deleting invalid package at " + parseResult.scanFile); removeCodePathLI(parseResult.scanFile); } } }
以上函数的【总结回顾】
1 2 3 4 通过ParallelPackageParser解析扫描目录下的包 取出解析结果,执行addForInitLI 删除无效的用户App
【总结回顾】
1 2 3 4 扫描各个系统分区的的App 解析系统App信息 把解析结果存储起来,存储在PMS的相关属性和mSettings里
阶段三
BOOT_PROGRESS_PMS_DATA_SCAN_START Data扫描阶段 扫描/data/app下的App,也就是用户安装的App
主要工作 对于不仅仅解析核心应用的情况下,还处理data目录的应用信息,及时更新,去除不必要的数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 PackageManagerService.packageManagerService() if (!mOnlyCore) { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START, SystemClock.uptimeMillis()); scanDirTracedLI(sAppInstallDir, 0 , scanFlags | SCAN_REQUIRE_KNOWN, 0 , packageParser, executorService); for (int i = possiblyDeletedUpdatedSystemApps.size() - 1 ; i >= 0 ; --i) { final String packageName = possiblyDeletedUpdatedSystemApps.get(i); final AndroidPackage pkg = mPackages.get(packageName); final String msg; mSettings.removeDisabledSystemPackageLPw(packageName); ..... } for (int i = 0 ; i < mExpectingBetter.size(); i++) { final String packageName = mExpectingBetter.keyAt(i); if (!mPackages.containsKey(packageName)) { mSettings.enableSystemPackageLPw(packageName); try { scanPackageTracedLI(scanFile, reparseFlags, rescanFlags, 0 , null ); } catch (PackageManagerException e) { Slog.e(TAG, "Failed to parse original system package: " + e.getMessage()); } } } installSystemStubPackages(stubSystemApps, scanFlags); ...... mStorageManagerPackage = getStorageManagerPackageName(); mSetupWizardPackage = getSetupWizardPackageNameImpl(); updateAllSharedLibrariesLocked(null , null , Collections.unmodifiableMap(mPackages)); ...... mPackageUsage.read(mSettings.mPackages); mCompilerStats.read(); }
【总结回顾】
1 2 这里就是对/data/app进行了扫描,主要工作与扫描系统App目录是一样的,只是细节处理上有些不同。初次之外还做了一些扫尾工作
阶段四
BOOT_PROGRESS_PMS_SCAN_END 扫描结束
主要工作: (1) sdk版本变更,更新权限; (2) OTA升级后首次启动,清除不必要的缓存数据; (3) 权限等默认项更新完后,清理相关数据; (4) 更新package.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 PackageManagerService.packageManager() EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,SystemClock.uptimeMillis()); final boolean sdkUpdated = (ver.sdkVersion != mSdkVersion);if (sdkUpdated) { mPermissionManager.updateAllPermissions(StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated); ver.sdkVersion = mSdkVersion; if (!mOnlyCore && (mPromoteSystemApps || mFirstBoot)) { for (UserInfo user : mInjector.getUserManagerInternal().getUsers(true )) { mSettings.applyDefaultPreferredAppsLPw(user.id); primeDomainVerificationsLPw(user.id); } } final int storageFlags; if (StorageManager.isFileEncryptedNativeOrEmulated()) { storageFlags = StorageManager.FLAG_STORAGE_DE; } else { storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE; } if (mIsUpgrade && !mOnlyCore) { 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, FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES); } } ver.fingerprint = Build.FINGERPRINT; } if (!mOnlyCore && mIsPreQUpgrade) { Slog.i(TAG, "Whitelisting all existing apps to hide their icons" ); int size = mSettings.mPackages.size(); for (int i = 0 ; i < size; i++) { final PackageSetting ps = mSettings.mPackages.valueAt(i); if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0 ) { continue ; } ps.disableComponentLPw(PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME, UserHandle.USER_SYSTEM); } } mPromoteSystemApps = false ; ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION; mSettings.writeLPr();
【总结回顾】
1 2 3 4 5 如果SDK版本发生了变化(升级系统),重新对App进行授权 为系统核心服务准备存储空间 如果是升级后第一次正常启动,需要清除代码缓存,但不是会清除应用的配置文件 把更新后的信息写回对应的xml文件中
阶段五
BOOT_PROGRESS_PMS_READY 就绪阶段
主要工作: (1)创建PackageInstallerService对象 (2)GC回收内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY, SystemClock.uptimeMillis()); mRequiredPermissionControllerPackage = getRequiredPermissionControllerLPr(); ....... updateInstantAppInstallerLocked(null ); final Map<Integer, List<PackageInfo>> userPackages = new HashMap<>();for (int userId : userIds) { userPackages.put(userId, getInstalledPackages( 0 , userId).getList()); } mDexManager.load(userPackages); if (mIsUpgrade) { FrameworkStatsLog.write( FrameworkStatsLog.BOOT_TIME_EVENT_DURATION_REPORTED, BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_INIT_TIME, SystemClock.uptimeMillis() - startTime); } } } ...... Runtime.getRuntime().gc();
【总结回顾】
1 2 对一些属性进行了赋值,最重要的是初始化PackageInstallerService。
五阶段总结 阶段一:开始阶段:BOOT_PROGRESS_PMS_START。这个阶段的主要工作:
1 2 3 4 第一件事:初始化PMS的各个子组件/子服务以及相关属性 第二件事:解析package.xml,获取已经安装的App信息,存储到Settings的mPackages中 第三件事:创建了后台工作线程及其Handler
阶段二:系统扫描阶段:BOOT_PROGRESS_PMS_SYSTEM_SCAN_START。这个阶段的主要工作:
1 2 3 4 第一件事:扫描各个系统分区的的App 第二件事:解析系统App信息 第三件事:把解析结果存储起来,存储在PMS的相关属性和mSettings里
阶段三:Data扫描阶段:BOOT_PROGRESS_PMS_DATA_SCAN_START。
1 2 3 这个阶段对/data/app进行了扫描,主要工作与扫描系统App目录是一样的, 只是细节处理上有些不同。初次之外还做了一些扫尾工作。
阶段四:扫描结束:BOOT_PROGRESS_PMS_SCAN_END。这个阶段主要工作:
1 2 3 4 5 第一件事:如果SDK版本发生了变化(升级系统),重新对App进行授权 第二件事:为系统核心服务准备存储空间 第三件事:如果是升级后第一次正常启动,需要清除代码缓存,但不是会清除应用的配置文件 第四讲事:把更新后的信息写回对应的xml文件中
阶段五:就绪阶段:BOOT_PROGRESS_PMS_READY。
1 2 这个阶段又对一些属性进行了赋值,最重要的是初始化PackageInstallerService
PKMS构建成功之后 在SystemServer中,PMS构建完成之后,仍然后一些额外的操作(通过查找mPackageManagerService看它在哪些地方用到了)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 private void startOtherServices (@NonNull TimingsTraceAndSlog t) { t.traceBegin("startOtherServices" ); ... if (!mOnlyCore) { ... mPackageManagerService.updatePackagesIfNeeded(); ... } t.traceBegin("PerformFstrimIfNeeded" ); try { mPackageManagerService.performFstrimIfNeeded(); } catch (Throwable e) { reportWtf("performing fstrim" , e); } t.traceEnd(); ... t.traceBegin("MakePackageManagerServiceReady" ); mPackageManagerService.systemReady(); t.traceEnd(); ... mActivityManagerService.systemReady(() -> { ... mPackageManagerService.waitForAppDataPrepared(); ... }, t); t.traceEnd(); }
【总结回顾】
1 2 3 4 5 6 在startOtherServices中,PKMS做了几件事情: 在需要的情况下进行dex优化 在需要的情况下进行磁盘清理 通知PMS及其子组件系统已就绪 ActivityManagerService启动Launcher之前等待PMS中为App的启动做好准备工作
简述总结 总的来说,PMS在SystemServer里面创建,并向ServiceManager注册。 其创建过程分为五个阶段,在此过程中会从packages.xml等相关文件中读取上次保存的包列表和实时扫描的列表进行比较和更新, 处理升级事宜,最后把更新后的包列表重新持久化。 另外,创建完成之后还进行了一些dex优化、磁盘清理等等一些列额外操作。
APK的扫描 PKMS的构造函数中调用了 scanDirTracedLI 方法 来扫描某个目录的apk文件。
APK的扫描,整体描述图:
PKMS.scanDirTracedLi :首先加入了一些systtrace的日志追踪,然后调用scanDirLI()进行分析
1 2 3 4 5 6 7 8 9 private void scanDirTracedLI (File scanDir, final int parseFlags, int scanFlags, long currentTime) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]" ); try { scanDirLI(scanDir, parseFlags, scanFlags, currentTime); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } }
PKMS.scanDirLI : 使用了ParallelPackageParser的对象,ParallelPackageParser是一个队列,我们这里手机所有系统的apk,然后从这些队列里面取出apk,再调用PackageParser 解析进行解析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 private void scanDirLI (File scanDir, int parseFlags, int scanFlags, long currentTime) { final File[] files = scanDir.listFiles(); if (ArrayUtils.isEmpty(files)) { Log.d(TAG, "No files in app dir " + scanDir); return ; } if (DEBUG_PACKAGE_SCANNING) { Log.d(TAG, "Scanning app dir " + scanDir + " scanFlags=" + scanFlags + " flags=0x" + Integer.toHexString(parseFlags)); } try (ParallelPackageParser parallelPackageParser = new ParallelPackageParser( mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir, mParallelPackageParserCallback)) { int fileCount = 0 ; for (File file : files) { final boolean isPackage = (isApkFile(file) || file.isDirectory()) && !PackageInstallerService.isStageName(file.getName()); 过滤掉非 apk 文件,如果不是则跳过继续扫描 if (!isPackage) { continue ; } parallelPackageParser.submit(file, parseFlags); fileCount++; } for (; fileCount > 0 ; fileCount--) { ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take(); Throwable throwable = parseResult.throwable; int errorCode = PackageManager.INSTALL_SUCCEEDED; if (throwable == null ) { if (parseResult.pkg.applicationInfo.isStaticSharedLibrary()) { renameStaticSharedLibraryPackage(parseResult.pkg); } try { scanPackageChildLI(parseResult.pkg, parseFlags, scanFlags, currentTime, null ); } catch (PackageManagerException e) { errorCode = e.error; Slog.w(TAG, "Failed to scan " + parseResult.scanFile + ": " + e.getMessage()); } } else if (throwable instanceof PackageParser.PackageParserException) { PackageParser.PackageParserException e = (PackageParser.PackageParserException) throwable; errorCode = e.error; Slog.w(TAG, "Failed to parse " + parseResult.scanFile + ": " + e.getMessage()); } else { throw new IllegalStateException("Unexpected exception occurred while parsing " + parseResult.scanFile, throwable); } if ((scanFlags & SCAN_AS_SYSTEM) == 0 && errorCode != PackageManager.INSTALL_SUCCEEDED) { logCriticalInfo(Log.WARN, "Deleting invalid package at " + parseResult.scanFile); removeCodePathLI(parseResult.scanFile); } } } }
ParallelPackageParser.submit :
把扫描路径中的APK等内容,放入队列mQueue,
并把parsePackage() pp 赋给ParseResult,用于后面的调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public void submit (File scanFile, int parseFlags) { mService.submit(() -> { ParseResult pr = new ParseResult(); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parallel parsePackage [" + scanFile + "]" ); try { PackageParser pp = new PackageParser(); pp.setSeparateProcesses(mSeparateProcesses); pp.setOnlyCoreApps(mOnlyCore); pp.setDisplayMetrics(mMetrics); pp.setCacheDir(mCacheDir); pp.setCallback(mPackageParserCallback); pr.scanFile = scanFile; pr.pkg = parsePackage(pp, scanFile, parseFlags); } catch (Throwable e) { pr.throwable = e; } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } try { mQueue.put(pr); } catch (InterruptedException e) { Thread.currentThread().interrupt(); mInterruptedInThread = Thread.currentThread().getName(); } }); }
通过 PackageParser.parsePackage 进行apk解析:
如果传入的packageFile是目录, 调用parseClusterPackage()解析
如果传入的packageFile是APK文件, 调用parseMonolithicPackage()解析
1 2 3 4 5 6 7 8 9 10 11 12 13 public Package parsePackage (File packageFile, int flags, boolean useCaches) throws PackageParserException { ... if (packageFile.isDirectory()) { parsed = parseClusterPackage(packageFile, flags); } else { parsed = parseMonolithicPackage(packageFile, flags); } ... return parsed; }
PackageParser.parseMonolithicPackage (),它的作用是解析给定的APK文件,将其作为单个单块包处理,最终调用parseBaseApk()进行解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public Package parseMonolithicPackage (File apkFile, int flags) throws PackageParserException { final PackageLite lite = parseMonolithicPackageLite(apkFile, flags); if (mOnlyCoreApps) { if (!lite.coreApp) { throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, "Not a coreApp: " + apkFile); } } final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags); try { final Package pkg = parseBaseApk(apkFile, assetLoader.getBaseAssetManager(), flags); pkg.setCodePath(apkFile.getCanonicalPath()); pkg.setUse32bitAbi(lite.use32bitAbi); return pkg; } catch (IOException e) { throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, "Failed to get path: " + apkFile, e); } finally { IoUtils.closeQuietly(assetLoader); } }
PackageParser.parseBaseApk ()主要是对AndroidManifest.xml进行解析,解析后所有的信息放在Package对象中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 private Package parseBaseApk (File apkFile, AssetManager assets, int flags) throws PackageParserException { final String apkPath = apkFile.getAbsolutePath(); ... XmlResourceParser parser = null ; ... final int cookie = assets.findCookieForPath(apkPath); if (cookie == 0 ) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Failed adding asset path: " + apkPath); } parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME); final Resources res = new Resources(assets, mMetrics, null ); final String[] outError = new String[1 ]; final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError); ... pkg.setVolumeUuid(volumeUuid); pkg.setApplicationVolumeUuid(volumeUuid); pkg.setBaseCodePath(apkPath); pkg.setSigningDetails(SigningDetails.UNKNOWN); return pkg; ... }
parseBaseApk —–> parseBaseApkCommon , parseBaseApk省略了
PackageParser.parseBaseApkCommon 从AndroidManifest.xml中获取标签名,解析标签中的各个item的内容,存入Package对象中
例如:获取标签 “application”、”permission”、”package”、”manifest” ,太多了,省略了哈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 private Package parseBaseApkCommon (Package pkg, Set<String> acceptedTags, Resources res, XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, IOException { TypedArray sa = res.obtainAttributes(parser, com.android.internal.R.styleable.AndroidManifest); String str = sa.getNonConfigurationString( com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0 ); while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { String tagName = parser.getName(); if (tagName.equals(TAG_APPLICATION)) { if (foundApp) { ... } foundApp = true ; if (!parseBaseApplication(pkg, res, parser, flags, outError)) { return null ; } ... else if (tagName.equals(TAG_PERMISSION)) { if (!parsePermission(pkg, res, parser, outError)) { return null ; } .... } } }
上面解析AndroidManifest.xml,会得到 “application “、”overlay”、”permission”、”uses-permission” 等信息
我们下面就针对”application “进行展开分析一下,进入 PackageParser.parseBaseApplication ()函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 private boolean parseBaseApplication (Package owner, Resources res, XmlResourceParser parser, int flags, String[] outError) while ((type = parser.next() ) ! = XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) { String tagName = parser.getName(); if (tagName.equals("activity" )) { Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, false , owner.baseHardwareAccelerated); if (a == null ) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false ; } hasActivityOrder |= (a.order != 0 ); owner.activities.add(a); } else if (tagName.equals("receiver" )) { Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs, true , false ); if (a == null ) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false ; } hasReceiverOrder |= (a.order != 0 ); owner.receivers.add(a); }else if (tagName.equals("service" )) { Service s = parseService(owner, res, parser, flags, outError, cachedArgs); if (s == null ) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false ; } hasServiceOrder |= (s.order != 0 ); owner.services.add(s); }else if (tagName.equals("provider" )) { Provider p = parseProvider(owner, res, parser, flags, outError, cachedArgs); if (p == null ) { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false ; } owner.providers.add(p); } ... } }
在 PackageParser 扫描完一个 APK 后,此时系统已经根据该 APK 中 AndroidManifest.xml,创建了一个完整的 Package 对象
APK的扫描,自我总结:
第一步:扫描APK,解析AndroidManifest.xml文件,得到清单文件各个标签内容
第二步:解析清单文件到的信息由 Package 保存。从该类的成员变量可看出,和 Android 四大组件相关的信息分别由 activites、receivers、providers、services 保存,由于一个 APK 可声明多个组件,因此 activites 和 receivers等均声明为 ArrayList
APK的安装 安装步骤一: 把Apk的信息通过IO流的形式写入到PackageInstaller.Session中
安装步骤二: 调用PackageInstaller.Session的commit方法, 把Apk的信息交给PKMS处理
安装步骤三: 进行Apk的Copy操作, 进行安装
安装的三步走, 整体描述图:
用户点击 xxx.apk 文件进行安装, 从 开始安装 到 完成安装 流程如下:
APK的安装, 整体描述图:
点击一个apk后,会弹出安装界面,点击确定按钮后,会进入PackageInstallerActivity 的 bindUi () 中的mAlert点击事件, 弹出的安装界面底部显示的是一个diaglog,主要由bindUi构成,上面有 ”取消 “ 和 ”安装 “ 两个按钮,点击安装后 调用startInstall()进行安装:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 private void bindUi () { mAlert.setIcon(mAppSnippet.icon); mAlert.setTitle(mAppSnippet.label); mAlert.setView(R.layout.install_content_view); mAlert.setButton(DialogInterface.BUTTON_POSITIVE, getString(R.string.install), (ignored, ignored2) -> { if (mOk.isEnabled()) { if (mSessionId != -1 ) { mInstaller.setPermissionsResult(mSessionId, true ); finish(); } else { startInstall(); } } }, null ); mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel), (ignored, ignored2) -> { setResult(RESULT_CANCELED); if (mSessionId != -1 ) { mInstaller.setPermissionsResult(mSessionId, false ); } finish(); }, null ); setupAlert(); mOk = mAlert.getButton(DialogInterface.BUTTON_POSITIVE); mOk.setEnabled(false ); }
startInstall 方法组装了一个Intent,并跳转到 InstallInstalling 这个Activity,并关闭掉当前的PackageInstallerActivity。InstallInstalling主要用于向包管理器发送包的信息并处理包管理的回调:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 private void startInstall () { Intent newIntent = new Intent(); newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO, mPkgInfo.applicationInfo); newIntent.setData(mPackageURI); newIntent.setClass(this , InstallInstalling.class); String installerPackageName = getIntent().getStringExtra( Intent.EXTRA_INSTALLER_PACKAGE_NAME); if (mOriginatingURI != null ) { newIntent.putExtra(Intent.EXTRA_ORIGINATING_URI, mOriginatingURI); } if (mReferrerURI != null ) { newIntent.putExtra(Intent.EXTRA_REFERRER, mReferrerURI); } if (mOriginatingUid != PackageInstaller.SessionParams.UID_UNKNOWN) { newIntent.putExtra(Intent.EXTRA_ORIGINATING_UID, mOriginatingUid); } if (installerPackageName != null ) { newIntent.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, installerPackageName); } if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false )) { newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true ); } newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT); if (localLOGV) Log.i(TAG, "downloaded app uri=" +mPackageURI); startActivity(newIntent); finish(); }
启动 InstallInstalling ,进入onCreate, 重点是看onCreate函数中的六步 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 protected void onCreate (@Nullable Bundle savedInstanceState) { super .onCreate(savedInstanceState); ApplicationInfo appInfo = getIntent() .getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO); mPackageURI = getIntent().getData(); if ("package" .equals(mPackageURI.getScheme())) { try { getPackageManager().installExistingPackage(appInfo.packageName); launchSuccess(); } catch (PackageManager.NameNotFoundException e) { launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null ); } } else { final File sourceFile = new File(mPackageURI.getPath()); PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this , appInfo, sourceFile); mAlert.setIcon(as.icon); mAlert.setTitle(as.label); mAlert.setView(R.layout.install_content_view); mAlert.setButton(DialogInterface.BUTTON_NEGATIVE, getString(R.string.cancel), (ignored, ignored2) -> { if (mInstallingTask != null ) { mInstallingTask.cancel(true ); } if (mSessionId > 0 ) { getPackageManager().getPackageInstaller().abandonSession(mSessionId); mSessionId = 0 ; } setResult(RESULT_CANCELED); finish(); }, null ); setupAlert(); requireViewById(R.id.installing).setVisibility(View.VISIBLE); if (savedInstanceState != null ) { mSessionId = savedInstanceState.getInt(SESSION_ID); mInstallId = savedInstanceState.getInt(INSTALL_ID); try { InstallEventReceiver.addObserver(this , mInstallId, this ::launchFinishBasedOnResult); } catch (EventResultPersister.OutOfIdsException e) { } } else { PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( PackageInstaller.SessionParams.MODE_FULL_INSTALL); params.setInstallAsInstantApp(false ); params.setReferrerUri(getIntent().getParcelableExtra(Intent.EXTRA_REFERRER)); params.setOriginatingUri(getIntent() .getParcelableExtra(Intent.EXTRA_ORIGINATING_URI)); params.setOriginatingUid(getIntent().getIntExtra(Intent.EXTRA_ORIGINATING_UID, UID_UNKNOWN)); params.setInstallerPackageName(getIntent().getStringExtra( Intent.EXTRA_INSTALLER_PACKAGE_NAME)); params.setInstallReason(PackageManager.INSTALL_REASON_USER); File file = new File(mPackageURI.getPath()); try { PackageParser.PackageLite pkg = PackageParser.parsePackageLite(file, 0 ); params.setAppPackageName(pkg.packageName); params.setInstallLocation(pkg.installLocation); params.setSize( PackageHelper.calculateInstalledSize(pkg, false , params.abiOverride)); } catch (PackageParser.PackageParserException e) { Log.e(LOG_TAG, "Cannot parse package " + file + ". Assuming defaults." ); Log.e(LOG_TAG, "Cannot calculate installed size " + file + ". Try only apk size." ); params.setSize(file.length()); } catch (IOException e) { Log.e(LOG_TAG, "Cannot calculate installed size " + file + ". Try only apk size." ); params.setSize(file.length()); } try { mInstallId = InstallEventReceiver .addObserver(this , EventResultPersister.GENERATE_NEW_ID, this ::launchFinishBasedOnResult); } catch (EventResultPersister.OutOfIdsException e) { launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null ); } try { mSessionId = getPackageManager().getPackageInstaller().createSession(params); } catch (IOException e) { launchFailure(PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null ); } } mCancelButton = mAlert.getButton(DialogInterface.BUTTON_NEGATIVE); mSessionCallback = new InstallSessionCallback(); } }
注意: 以上第六步 是重点 PackageInstaller 的 createSession()内部会通过IPackageInstaller与PackageInstallerService进行进程间通信,最终调用的是PackageInstallerService的createSession方法来创建并返回mSessionId
InstallInstalling.onResume 方法中,调用onPostExecute()方法,将APK的信息通过IO流的形式写入到PackageInstaller.Session中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 protected void onResume () { super .onResume(); if (mInstallingTask == null ) { PackageInstaller installer = getPackageManager().getPackageInstaller(); PackageInstaller.SessionInfo sessionInfo = installer.getSessionInfo(mSessionId); if (sessionInfo != null && !sessionInfo.isActive()) { mInstallingTask = new InstallingAsyncTask(); mInstallingTask.execute(); } else { mCancelButton.setEnabled(false ); setFinishOnTouchOutside(false ); } } }
Installinstalling.InstallingAsyncTask: 关注 第一步 和 第二步
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 private final class InstallingAsyncTask extends AsyncTask <Void , Void , PackageInstaller .Session > { volatile boolean isDone; @Override protected PackageInstaller.Session doInBackground (Void... params) { PackageInstaller.Session session; try { session = getPackageManager().getPackageInstaller().openSession(mSessionId); } catch (IOException e) { return null ; } session.setStagingProgress(0 ); try { File file = new File(mPackageURI.getPath()); try (InputStream in = new FileInputStream(file)) { long sizeBytes = file.length(); try (OutputStream out = session .openWrite("PackageInstaller" , 0 , sizeBytes)) { byte [] buffer = new byte [1024 * 1024 ]; while (true ) { int numRead = in.read(buffer); if (numRead == -1 ) { session.fsync(out); break ; } if (isCancelled()) { session.close(); break ; } out.write(buffer, 0 , numRead); if (sizeBytes > 0 ) { float fraction = ((float ) numRead / (float ) sizeBytes); session.addProgress(fraction); } } } } return session; } catch (IOException | SecurityException e) { Log.e(LOG_TAG, "Could not write package" , e); session.close(); return null ; } finally { synchronized (this ) { isDone = true ; notifyAll(); } } } @Override protected void onPostExecute (PackageInstaller.Session session) { if (session != null ) { Intent broadcastIntent = new Intent(BROADCAST_ACTION); broadcastIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); broadcastIntent.setPackage(getPackageName()); broadcastIntent.putExtra(EventResultPersister.EXTRA_ID, mInstallId); PendingIntent pendingIntent = PendingIntent.getBroadcast( InstallInstalling.this , mInstallId, broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT); session.commit(pendingIntent.getIntentSender()); mCancelButton.setEnabled(false ); setFinishOnTouchOutside(false ); } else { getPackageManager().getPackageInstaller().abandonSession(mSessionId); if (!isCancelled()) { launchFailure(PackageManager.INSTALL_FAILED_INVALID_APK, null ); } } } }
PackageInstaller的commit ()
1 2 3 4 5 6 7 8 9 10 [PackageInstaller.java] commit public void commit (@NonNull IntentSender statusReceiver) { try { mSession.commit(statusReceiver, false ); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
PackageInstallerSession.**commit()**中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [PackageInstallerSession.java] commit() public void commit (@NonNull IntentSender statusReceiver, boolean forTransfer) { if (mIsPerfLockAcquired && mPerfBoostInstall != null ) { mPerfBoostInstall.perfLockRelease(); mIsPerfLockAcquired = false ; } ... if (!markAsCommitted(statusReceiver, forTransfer)) { return ; } ... mHandler.obtainMessage(MSG_COMMIT).sendToTarget(); }
MSG_COMMIT 在handler中进行处理,进入handleCommit()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public boolean handleMessage (Message msg) { switch (msg.what) { case MSG_COMMIT: handleCommit(); break ; } } private void handleCommit () { ... List<PackageInstallerSession> childSessions = getChildSessions(); try { synchronized (mLock) { commitNonStagedLocked(childSessions); } } catch (PackageManagerException e) { final String completeMsg = ExceptionUtils.getCompleteMessage(e); Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg); destroyInternal(); dispatchSessionFinished(e.error, completeMsg, null ); } }
最终调用 **mPm.installStage()**,进入PKMS 【经过千辛万苦,终于要进入PKMS了】
1 2 3 4 5 6 7 8 private void commitNonStagedLocked (...) throws PackageManagerException { if (isMultiPackage()) { ... mPm.installStage(activeChildSessions); } else { mPm.installStage(committingSession); } }
PKMS.installStage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 [PackageManagerService.java] void installStage (ActiveInstallSession activeInstallSession) { if (DEBUG_INSTANT) { if ((activeInstallSession.getSessionParams().installFlags & PackageManager.INSTALL_INSTANT_APP) != 0 ) { Slog.d(TAG, "Ephemeral install of " + activeInstallSession.getPackageName()); } } final Message msg = mHandler.obtainMessage(INIT_COPY); final InstallParams params = new InstallParams(activeInstallSession); params.setTraceMethod("installStage" ).setTraceCookie(System.identityHashCode(params)); msg.obj = params; Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installStage" , System.identityHashCode(msg.obj)); Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall" , System.identityHashCode(msg.obj)); mHandler.sendMessage(msg); } 对INIT_COPY的消息的处理 [PackageManagerService.java] void doHandleMessage (Message msg) { switch (msg.what) { case INIT_COPY: { HandlerParams params = (HandlerParams) msg.obj; if (params != null ) { if (DEBUG_INSTALL) Slog.i(TAG, "init_copy: " + params); Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "queueInstall" , System.identityHashCode(params)); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "startCopy" ); params.startCopy(); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } break ; } } } [PKMS.HandlerParams] final void startCopy () { if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this ); handleStartCopy(); handleReturnCode(); } [PKMS.MultiPackageInstallParams] void handleReturnCode () { if (mVerificationCompleted && mEnableRollbackCompleted) { ..... if (mRet == PackageManager.INSTALL_SUCCEEDED) { mRet = mArgs.copyApk(); } ..... } }
APK 拷贝 方法调用步骤如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 PKMS copyApk () doCopyApk () PackageManagerServiceUtils copyPacakge () copyFile () private static void copyFile (String sourcePath, File targetDir, String targetName) throws ErrnoException, IOException { if (!FileUtils.isValidExtFilename(targetName)) { throw new IllegalArgumentException("Invalid filename: " + targetName); } Slog.d(TAG, "Copying " + sourcePath + " to " + targetName); final File targetFile = new File(targetDir, targetName); final FileDescriptor targetFd = Os.open(targetFile.getAbsolutePath(), O_RDWR | O_CREAT, 0644 ); Os.chmod(targetFile.getAbsolutePath(), 0644 ); FileInputStream source = null ; try { source = new FileInputStream(sourcePath); FileUtils.copy(source.getFD(), targetFd); } finally { IoUtils.closeQuietly(source); } }
进入 Android 11.0 核心安装环节:
processPendingInstall:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 private void processPendingInstall (final InstallArgs args, final int currentStatus) { if (args.mMultiPackageInstallParams != null ) { args.mMultiPackageInstallParams.tryProcessInstallRequest(args, currentStatus); } else { PackageInstalledInfo res = createPackageInstalledInfo(currentStatus); processInstallRequestsAsync( res.returnCode == PackageManager.INSTALL_SUCCEEDED, Collections.singletonList(new InstallRequest(args, res))); } } private void processInstallRequestsAsync (boolean success, List<InstallRequest> installRequests) { mHandler.post(() -> { if (success) { for (InstallRequest request : installRequests) { request.args.doPreInstall(request.installResult.returnCode); } synchronized (mInstallLock) { installPackagesTracedLI(installRequests); } for (InstallRequest request : installRequests) { request.args.doPostInstall( request.installResult.returnCode, request.installResult.uid); } } for (InstallRequest request : installRequests) { restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult, new PostInstallData(request.args, request.installResult, null )); } }); }
installPackagesTracedLI
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 private void installPackagesLI (List<InstallRequest> requests) { ... prepareResult = preparePackageLI(request.args, request.installResult); ... final List<ScanResult> scanResults = scanPackageTracedLI( prepareResult.packageToScan, prepareResult.parseFlags, prepareResult.scanFlags, System.currentTimeMillis(), request.args.user); ... ReconcileRequest reconcileRequest = new ReconcileRequest(preparedScans, installArgs, installResults, prepareResults, mSharedLibraries, Collections.unmodifiableMap(mPackages), versionInfos, lastStaticSharedLibSettings); ... commitPackagesLocked(commitRequest); ... executePostCommitSteps(commitRequest); }
executePostCommitSteps 安装APK,并为新的代码路径准备应用程序配置文件,并再次检查是否需要dex优化
如果是直接安装新包,会为新的代码路径准备应用程序配置文件
如果是替换安装:其主要过程为更新设置,清除原有的某些APP数据,重新生成相关的app数据目录等步骤,同时要区分系统应用替换和非系统应用替换。而安装新包:则直接更新设置,生成APP数据即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 [PackageManagerService.java] executePostCommitSteps() private void executePostCommitSteps (CommitRequest commitRequest) { for (ReconciledPackage reconciledPkg : commitRequest.reconciledPackages.values()) { ... prepareAppDataAfterInstallLIF(pkg); if (reconciledPkg.prepareResult.clearCodeCache) { clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); } mArtManagerService.prepareAppProfiles( pkg, resolveUserIds(reconciledPkg.installArgs.user.getIdentifier()), true ); final boolean performDexopt = (!instantApp || Global.getInt(mContext.getContentResolver(), Global.INSTANT_APP_DEXOPT_ENABLED, 0 ) != 0 ) && ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0 ); if (performDexopt) { ... mPackageDexOptimizer.performDexOpt(pkg, null , getOrCreateCompilerPackageStats(pkg), mDexManager.getPackageUseInfoOrDefault(packageName), dexoptOptions); } BackgroundDexOptService.notifyPackageChanged(packageName); } }
prepareAppDataAfterInstallLIF:
1 2 3 4 5 6 7 8 9 10 11 通过一系列的调用,最终会调用到[Installer.java] createAppData()进行安装,交给installed进程进行APK的安装 调用栈如下: prepareAppDataAfterInstallLIF() | prepareAppDataLIF() | prepareAppDataLeafLIF() | [Installer.java] createAppData()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 private void prepareAppDataAfterInstallLIF (PackageParser.Package pkg) { ... for (UserInfo user : um.getUsers()) { ... if (ps.getInstalled(user.id)) { prepareAppDataLIF(pkg, user.id, flags); } } } private void prepareAppDataLIF (PackageParser.Package pkg, int userId, int flags) { if (pkg == null ) { Slog.wtf(TAG, "Package was null!" , new Throwable()); return ; } prepareAppDataLeafLIF(pkg, userId, flags); final int childCount = (pkg.childPackages != null ) ? pkg.childPackages.size() : 0 ; for (int i = 0 ; i < childCount; i++) { prepareAppDataLeafLIF(pkg.childPackages.get(i), userId, flags); } } private void prepareAppDataLeafLIF (PackageParser.Package pkg, int userId, int flags) { ... try { ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags, appId, seInfo, app.targetSdkVersion); } catch (InstallerException e) { if (app.isSystemApp()) { destroyAppDataLeafLIF(pkg, userId, flags); try { ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags, appId, seInfo, app.targetSdkVersion); } catch (InstallerException e2) { ... } } } }
Installer.createAppData 收尾工作,安装完成后,更新设置,更新安装锁等:
1 2 3 4 5 6 7 8 9 10 11 12 13 [Installer.java] public long createAppData (String uuid, String packageName, int userId, int flags, int appId, String seInfo, int targetSdkVersion) throws InstallerException { if (!checkBeforeRemote()) return -1 ; try { return mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo, targetSdkVersion); } catch (Exception e) { throw InstallerException.from(e); } }
总结:安装的原理:
权限扫描 PackageManagerService中执行systemReady()后,需求对 /system/etc/permissions中的各种xml进行扫描,进行相应的权限存储,让以后可以使用.
PackageManagerService执行systemReady()时,通过SystemConfig的readPermissionsFromXml()来扫描读取/system/etc/permissions中的xml文件,包括platform.xml和系统支持的各种硬件模块的feature主要工作:
整体图:
SystemConfig 的 readPermissions函数:
此函数目的:(扫描/system/etc/permissions中文件,调用readPermissionsFromXml()进行解析,存入SsytemConfig相应的成员数组变量中)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 void readPermissions (File libraryDir, int permissionFlag) { ... File platformFile = null ; for (File f : libraryDir.listFiles()) { if (!f.isFile()) { continue ; } if (f.getPath().endsWith("etc/permissions/platform.xml" )) { platformFile = f; continue ; } ... readPermissionsFromXml(f, permissionFlag); } if (platformFile != null ) { readPermissionsFromXml(platformFile, permissionFlag); } }
解析xml的标签节点,存入mGlobalGids、mPermissions、mSystemPermissions等成员变量中,供其他进行调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 private void readPermissionsFromXml (File permFile, int permissionFlag) { FileReader permReader = null ; permReader = new FileReader(permFile); ... XmlPullParser parser = Xml.newPullParser(); parser.setInput(permReader); while (true ) { ... String name = parser.getName(); switch (name) { case "group" : { String gidStr = parser.getAttributeValue(null , "gid" ); if (gidStr != null ) { int gid = android.os.Process.getGidForName(gidStr); mGlobalGids = appendInt(mGlobalGids, gid); } else { Slog.w(TAG, "<" + name + "> without gid in " + permFile + " at " + parser.getPositionDescription()); } ... } break ; case "permission" : { if (allowPermissions) { String perm = parser.getAttributeValue(null , "name" ); if (perm == null ) { Slog.w(TAG, "<" + name + "> without name in " + permFile + " at " + parser.getPositionDescription()); XmlUtils.skipCurrentTag(parser); break ; } perm = perm.intern(); readPermission(parser, perm); } else { logNotAllowedInPartition(name, permFile, parser); XmlUtils.skipCurrentTag(parser); } } break ; } } }
查看 XML文件:
adb devices
adb shell
然后在导出去:
1 adb pull /system/etc/permissions
/system/etc/permissions中会存在很多的xml文件,例如我们看下 android.software.webview.xml的文件,内容如下:
里面只只有一个feature “android.software.webview”,大部分的xml都是类似的定义方式
1 2 3 4 <?xml version="1.0" encoding="utf-8"?> <permissions > <feature name ="android.software.webview" /> </permissions >
让我们来简单的看下/system/etc/permissions/platform.xml的内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 <?xml version="1.0" encoding="utf-8"?> <permissions > <permission name ="android.permission.BLUETOOTH_ADMIN" > <group gid ="net_bt_admin" /> </permission > <permission name ="android.permission.INTERNET" > <group gid ="inet" /> </permission > <permission name ="android.permission.READ_LOGS" > <group gid ="log" /> </permission > ... <assign-permission name ="android.permission.MODIFY_AUDIO_SETTINGS" uid ="media" /> <assign-permission name ="android.permission.ACCESS_SURFACE_FLINGER" uid ="media" /> <assign-permission name ="android.permission.WAKE_LOCK" uid ="media" /> ... <split-permission name ="android.permission.ACCESS_FINE_LOCATION" > <new-permission name ="android.permission.ACCESS_COARSE_LOCATION" /> </split-permission > <split-permission name ="android.permission.WRITE_EXTERNAL_STORAGE" > <new-permission name ="android.permission.READ_EXTERNAL_STORAGE" /> </split-permission > <split-permission name ="android.permission.READ_CONTACTS" targetSdk ="16" > <new-permission name ="android.permission.READ_CALL_LOG" /> </split-permission > ... <library name ="android.test.base" file ="/system/framework/android.test.base.jar" /> <library name ="android.test.mock" file ="/system/framework/android.test.mock.jar" dependency ="android.test.base" /> <library name ="android.test.runner" file ="/system/framework/android.test.runner.jar" dependency ="android.test.base:android.test.mock" /> <library name ="android.hidl.base-V1.0-java" file ="/system/framework/android.hidl.base-V1.0-java.jar" /> <library name ="android.hidl.manager-V1.0-java" file ="/system/framework/android.hidl.manager-V1.0-java.jar" dependency ="android.hidl.base-V1.0-java" /> ... </permissions >
以上platform.xml中出现的标签种类则较为多样,它们的含义分别是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 platform.xml中出现的标签种类则较为多样,它们的含义分别是: <group > :根据name获取gid<permission > 标签:把属性name所描述的权限赋予给<group > 标签中属性gid所表示的用户组,一个权限可以有一个或多个group对象,当一个APK授权于这个这个权限时,它同时属于这几个组<assign-permission > 标签:把属性name所描述的权限赋予给uid属性所表示的用户<split-permission > 标签:一个权限可以扩展出一个新的权限<library > 标签:除framework中动态库以外的,所有系统会自动加载的动态库<feature > 标签:硬件支持的一些feature<oem-permission > 标签:oem厂商自己定义的一些权限<privapp-permission > 标签:来自system、vendor、product、system_ext的privapp权限分别存储,这是防止供应商分区中的xml授权于系统分区中的私有应用权限 最后将上面xml解析出来的数据做如下存储: <group > 标签gid属性的值会存放在mGlobalGids数组中;<permission > 标签,解析得到的值会存放在mPermissions集合中;<assign-permission > 标签解析得到的值会存放在mSystemPermissions中;<split-permission > 存储在mSplitPermissions<library > 标签解析得到的值会存放在mSharedLibraries中;<feature > 存储在mAvaliableFeatures<oem-permission > 存储在mOemPermissions<privapp-permission > 会根据不同的存储路径,分别存储在mVendorPrivAppPermissions、mProductPrivAppPermissions、mSystemExtPrivAppPermissions、mPrivAppPermissions
总结:权限扫描,扫描/system/etc/permissions中的xml,存入相应的结构体中,供之后权限管理使用