会介绍 PackageInstaller
PackageManager
PackageManagerService
之间的联系及 PackageManagerService
的启动过程
- 涉及文件
packages\apps\PackageInstaller\
frameworks/base/core/java/android/content/pm/PackageManager.java
frameworks/base/core/java/android/content/pm/IPackageManager.aidl
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
PackageInstaller
系统默认内置应用,主要提供安装、升级、卸载应用等功能。既支持完整安装包也支持拆分包。
任何应用都可以通过创建 PackageInstaller.Session
来安装应用;首先创建会话,然后安装程序把一个或多个安装包流式传输到位并决定是进行安装还是销毁会话。安装过程需要用户参与进行交互。
会话能够安装全新的应用、升级已安装的应用或把拆分包添加到现有的应用。
相关 API 具体可参考 Android 官方文档:PackageInstaller、PackageInstaller.Session
PackageInstaller
其实主要是处理用户交互的,向用户展示即将安装或卸载的应用的基本信息:图标、名称和需要的权限等,以及安装或卸载进度和结果。
应用安装
调用安装程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
private void installApp(String filePath) { File apkFile = new File(filePath); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); Uri contentUri = FileProvider.getUriForFile( mContext , "{USER.PACKAGE.NAME}.fileprovider" , apkFile); intent.setDataAndType(contentUri, "application/vnd.android.package-archive"); } else { intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive"); } startActivity(intent); }
Intent
匹配1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
<activity android:name=".InstallStart" android:exported="true" android:excludeFromRecents="true"> <intent-filter android:priority="1"> <action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.INSTALL_PACKAGE" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="file" /> <data android:scheme="content" /> <data android:mimeType="application/vnd.android.package-archive" /> </intent-filter> <intent-filter android:priority="1"> <action android:name="android.intent.action.INSTALL_PACKAGE" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="file" /> <data android:scheme="package" /> <data android:scheme="content" /> </intent-filter> <intent-filter android:priority="1"> <action android:name="android.content.pm.action.CONFIRM_PERMISSIONS" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
应用卸载
调用卸载程序:
1 2 3 4 5 6 7
public static void unstallApp(Context context, String packageName){ Intent uninstall_intent = new Intent(); uninstall_intent.setAction(Intent.ACTION_DELETE); uninstall_intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); uninstall_intent.setData(Uri.parse("package:"+packageName)); context.startActivity(uninstall_intent); }
Intent
匹配1 2 3 4 5 6 7 8 9 10 11
<activity android:name=".UninstallerActivity" android:configChanges="orientation|keyboardHidden|screenSize" android:excludeFromRecents="true" android:theme="@style/AlertDialogActivity"> <intent-filter android:priority="1"> <action android:name="android.intent.action.DELETE" /> <action android:name="android.intent.action.UNINSTALL_PACKAGE" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="package" /> </intent-filter> </activity>
PackageManager
该类主要用于检索已经安装应用的信息,可以通过 Context.getPackageManager()
获取。相关 API 具体可以参考 Android 官方文档:PackageManager
获取 PackageManager
Context
类的抽象方法一般都由 ContextImpl
子类实现。
Context.getPackageManager()
1 2 3 4 5 6 7 8 9 10 11 12 13 14
public PackageManager getPackageManager() { if (mPackageManager != null) { return mPackageManager; } IPackageManager pm = ActivityThread.getPackageManager(); if (pm != null) { // Doesn't matter if we make more than one instance. // 没有使用同步,可能会有多个实例 return (mPackageManager = new ApplicationPackageManager(this, pm)); } return null; }
ActivityThread.getPackageManager()
1 2 3 4 5 6 7 8 9 10 11
public static IPackageManager getPackageManager() { if (sPackageManager != null) { return sPackageManager; } // 这个就不往下分析了,获取到其实是 BinderProxy IBinder b = ServiceManager.getService("package"); // 这个获取到是 IPackageManager.Stub.Proxy; // 既是 PackageManagerService 服务端 Binder 的远程代理 sPackageManager = IPackageManager.Stub.asInterface(b); return sPackageManager; }
ApplicationPackageManager()
1 2 3 4 5 6
protected ApplicationPackageManager(ContextImpl context, IPackageManager pm) { mContext = context; // 所有需要 Binder 通讯都交由 mPM 处理 mPM = pm; }
PackageManager
其实现类是:ApplicationPackageManager
。持有IPackageManager
对象是PackageManagerService
的代理。
PackageManagerService
类图
略。和 PowerManagerService
类似,与 PackageManager
的通讯是基于 AIDL
的,最终通过 Binder
实现。
启动
SystemServer
部分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 run() { // Start services. startBootstrapServices(); startCoreServices(); startOtherServices(); } private void startBootstrapServices() { // Start the package manager. // 启动 PackageManagerService 服务 <2.> mPackageManagerService = PackageManagerService.main(mSystemContext, installer, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); mFirstBoot = mPackageManagerService.isFirstBoot(); mPackageManager = mSystemContext.getPackageManager(); // Manages A/B OTA dexopting. This is a bootstrap service as we need it to rename // A/B artifacts after boot, before anything else might touch/need them. // Note: this isn't needed during decryption (we don't have /data anyways). if (!mOnlyCore) { boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt", false); if (!disableOtaDexopt) { OtaDexoptService.main(mSystemContext, mPackageManagerService); } } } private void startOtherServices() { if (!mOnlyCore) { // 是否要更新应用,像 OTA 升级后应用可能会有变动 <3.> mPackageManagerService.updatePackagesIfNeeded(); } // 执行 fstrim mPackageManagerService.performFstrimIfNeeded(); // 系统已经准备好了,做相应的收尾工作 <4.> mPackageManagerService.systemReady(); mActivityManagerService.systemReady(() -> { // Wait for all packages to be prepared mPackageManagerService.waitForAppDataPrepared(); }, BOOT_TIMINGS_TRACE_LOG); }
main()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
public static PackageManagerService main(Context context, Installer installer, boolean factoryTest, boolean onlyCore) { // Self-check for initial settings. // 检查系统设置,存储在 *.prop 文件中的值 PackageManagerServiceCompilerMapping.checkProperties(); // 构建 PackageManagerService,factoryTest 标记是否是测试模式,onlyCore 标记是否只加载核心应用 PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore); // 支持多用户时不加载黑名单中的应用 m.enableSystemUserPackages(); // 注册到 ServiceManager ServiceManager.addService("package", m); // Native 层的 PackagerManagerNative,这里是服务端不是代理 final PackageManagerNative pmn = m.new PackageManagerNative(); ServiceManager.addService("package_native", pmn); return m; }
updatePackagesIfNeeded()
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
public void updatePackagesIfNeeded() { enforceSystemOrRoot("Only the system can request package update"); // We need to re-extract after an OTA. // 判断系统是否是 OTA 升级后开机 boolean causeUpgrade = isUpgrade(); // First boot or factory reset. // Note: we also handle devices that are upgrading to N right now as if it is their // first boot, as they do not have profile data. // 系统是首次启动或恢复出厂设置之后启动;或者升级到 N 的首次启动,有生成配置文件 boolean causeFirstBoot = isFirstBoot() || mIsPreNUpgrade; // We need to re-extract after a pruned cache, as AoT-ed files will be out of date. // 如果虚拟机缓存文件有剪裁,比如 ota 之后 boolean causePrunedCache = VMRuntime.didPruneDalvikCache(); if (!causeUpgrade && !causeFirstBoot && !causePrunedCache) { return; } List<PackageParser.Package> pkgs; synchronized (mPackages) { pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this); } final long startTime = System.nanoTime(); // 有时会显示:系统正在升级的弹窗 final int[] stats = performDexOptUpgrade(pkgs, mIsPreNUpgrade /* showDialog */, causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT, false /* bootComplete */); final int elapsedTimeSeconds = (int) TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - startTime); }
systemReady()
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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
public void systemReady() { enforceSystemOrRoot("Only the system can claim the system is ready"); mSystemReady = true; // 监听是否允许网络及时应用 final ContentResolver resolver = mContext.getContentResolver(); ContentObserver co = new ContentObserver(mHandler) { @Override public void onChange(boolean selfChange) { mWebInstantAppsDisabled = (Global.getInt(resolver, Global.ENABLE_EPHEMERAL_FEATURE, 1) == 0) || (Secure.getInt(resolver, Secure.INSTANT_APPS_ENABLED, 1) == 0); } }; mContext.getContentResolver().registerContentObserver(android.provider.Settings.Global .getUriFor(Global.ENABLE_EPHEMERAL_FEATURE), false, co, UserHandle.USER_SYSTEM); mContext.getContentResolver().registerContentObserver(android.provider.Settings.Secure .getUriFor(Secure.INSTANT_APPS_ENABLED), false, co, UserHandle.USER_SYSTEM); co.onChange(true); // Disable any carrier apps. We do this very early in boot to prevent the apps from being // disabled after already being started. // 禁止运营商应用,直到相匹配的 SIM 插入 CarrierAppUtils.disableCarrierAppsUntilPrivileged(mContext.getOpPackageName(), this, mContext.getContentResolver(), UserHandle.USER_SYSTEM); // Read the compatibilty setting when the system is ready. // 阅读兼容性设置 boolean compatibilityModeEnabled = android.provider.Settings.Global.getInt( mContext.getContentResolver(), android.provider.Settings.Global.COMPATIBILITY_MODE, 1) == 1; PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled); if (DEBUG_SETTINGS) { Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled); } int[] grantPermissionsUserIds = EMPTY_INT_ARRAY; synchronized (mPackages) { // Verify that all of the preferred activity components actually // exist. It is possible for applications to be updated and at // that point remove a previously declared activity component that // had been set as a preferred activity. We try to clean this up // the next time we encounter that preferred activity, but it is // possible for the user flow to never be able to return to that // situation so here we do a sanity check to make sure we haven't // left any junk around. // 清理首选应用,比如:设置中默认 Chrome 为首选浏览器但 Chrome 已被移除,需要清理该默认浏览器选项 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); } if (grantPermissionsUserIds == EMPTY_INT_ARRAY) { // If we did not grant default permissions, we preload from this the // default permission exceptions lazily to ensure we don't hit the // disk on a new user creation. mDefaultPermissionPolicy.scheduleReadDefaultPermissionExceptions(); } // Now that we've scanned all packages, and granted any default // permissions, ensure permissions are updated. Beware of dragons if you // try optimizing this. // 扫描所有包并更新默认权限 synchronized (mPackages) { mPermissionManager.updateAllPermissions( StorageManager.UUID_PRIVATE_INTERNAL, false, mPackages.values(), mPermissionCallback); } // 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(); mDexManager.systemReady(); mPackageDexOptimizer.systemReady(); // 外部卷挂载方式 StorageManagerInternal StorageManagerInternal = LocalServices.getService( StorageManagerInternal.class); StorageManagerInternal.addExternalStoragePolicy( new StorageManagerInternal.ExternalStorageMountPolicy() { @Override public int getMountMode(int uid, String packageName) { if (Process.isIsolated(uid)) { return Zygote.MOUNT_EXTERNAL_NONE; } if (checkUidPermission(READ_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) { return Zygote.MOUNT_EXTERNAL_DEFAULT; } if (checkUidPermission(WRITE_EXTERNAL_STORAGE, uid) == PERMISSION_DENIED) { return Zygote.MOUNT_EXTERNAL_READ; } return Zygote.MOUNT_EXTERNAL_WRITE; } @Override public boolean hasExternalStorage(int uid, String packageName) { return true; } }); // Now that we're mostly running, clean up stale users and apps // 清理工作 sUserManager.reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL); reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL); mPermissionManager.systemReady(); if (mInstantAppResolverConnection != null) { mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { mInstantAppResolverConnection.optimisticBind(); mContext.unregisterReceiver(this); } }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED)); } }
构造 PackageManagerService()
|
|
Settings.class
建立 Android 体系与 Linux 内核的用户权限对应关系Settings()
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
Settings(PermissionSettings permissions, Object lock) { this(Environment.getDataDirectory(), permissions, lock); } Settings(File dataDir, PermissionSettings permission, Object lock) { mLock = lock; mPermissions = permission; mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock); // /data/system 目录 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); // 记录应用相关信息:permission、package、shared-user、keyset-settings mSettingsFilename = new File(mSystemDir, "packages.xml"); // package-backup.xml 是 package.xml 的备份文件, // package.xml 写入成功后再写入到备份文件,写入失败时可恢复到上次状态 mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml"); // 记录安装包相关信息:包名、userid、debugable、应用数据存放路径、seinfo、gid mPackageListFilename = new File(mSystemDir, "packages.list"); FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID); // sdcardfs 的作用与 fuse 相同,也是用于控制文件访问的权限。 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"); }
addSharedUserLPw()
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
SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) { SharedUserSetting s = mSharedUsers.get(name); if (s != null) { if (s.userId == uid) { // 相应的 SharedUserSetting 存在并且 userId 相同直接返回该对象 return s; } // userId 不同则抱一个错误 PackageManagerService.reportSettingsProblem(Log.ERROR, "Adding duplicate shared user, keeping first: " + name); return null; } // 不存在新建存入到 mShsredUsers 并返回新建的对象 s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags); s.userId = uid; if (addUserIdLPw(uid, s, name)) { mSharedUsers.put(name, s); return s; } return null; } private boolean addUserIdLPw(int uid, Object obj, Object name) { if (uid > Process.LAST_APPLICATION_UID) { // userId 没有对应的应用,不合法 return false; } if (uid >= Process.FIRST_APPLICATION_UID) { // 非系统应用 // 存入到 mUserIds 中 userId 对应的下标位置;中间空白部分用 null 填充 int N = mUserIds.size(); final int index = uid - Process.FIRST_APPLICATION_UID; while (index >= N) { mUserIds.add(null); N++; } if (mUserIds.get(index) != null) { PackageManagerService.reportSettingsProblem(Log.ERROR, "Adding duplicate user id: " + uid + " name=" + name); return false; } mUserIds.set(index, obj); } else { // 系统内置的 userId if (mOtherUserIds.get(uid) != null) { PackageManagerService.reportSettingsProblem(Log.ERROR, "Adding duplicate shared id: " + uid + " name=" + name); return false; } // 存入到 mOtherUserIds 中 mOtherUserIds.put(uid, obj); } return true; }
在
Settings
中mSharedUsers
是一个map
对象,利用名称作为索引管理SharedUserSettings
对象。Settings
中的mOtherUserIds
和mUserIds
,均是利用userId
作为索引管理SharedUserSettings
对象。不同的是mOtherUserIds
是SparseArray
,以系统uid
作为键值;=mUserIds= 是ArrayList
,普通 APK 的uid
为ArrayList
的下标。SharedUserSettings
将持有一组PackageSetting
。AndroidManifest.xml
中android:sharedUserId
的属性就是应用的UserId
其与 Linux 的 UID 相关联,而 Linux 的权限是建立再用户的基础上的,从而建立应用的权限体系。
SystemConfig.class
从文件读取系统配置SystemConfig()
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
// 单例模式 public static SystemConfig getInstance() { synchronized (SystemConfig.class) { if (sInstance == null) { sInstance = new SystemConfig(); } return sInstance; } } SystemConfig() { // Read configuration from system // 从 /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); // Vendors are only allowed to customze libs, features and privapp permissions // 从 /vendor 目录读取权限配置信息,该目录下只能自定义:libs、features、privapp 权限 int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS; if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) { // For backward compatibility vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS); } readPermissions(Environment.buildPath( Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag); readPermissions(Environment.buildPath( Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag); // Allow ODM to customize system configs as much as Vendor, because /odm is another // vendor partition other than /vendor. // 从 /odm 目录读取权限配置信息,限制和 /vendor 一样 int odmPermissionFlag = vendorPermissionFlag; readPermissions(Environment.buildPath( Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag); readPermissions(Environment.buildPath( Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag); // Allow OEM to customize features and OEM permissions // 从 /oem 目录读取权限配置信息,只能自定义:features 和 OEM 权限 int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS; readPermissions(Environment.buildPath( Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag); readPermissions(Environment.buildPath( Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag); // Allow Product to customize system configs around libs, features, permissions and apps // 从产品目录读取配置信息,可以自定义:system configs、libs、features、permissions、apps int productPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS; readPermissions(Environment.buildPath( Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag); readPermissions(Environment.buildPath( Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag); }
readPermissions()
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
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) { // 解析 XML 文件并保存解析后的结果 readPermissionsFromXml(platformFile, permissionFlag); } }
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 77 78 79 80
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); } } 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; } try (ParallelPackageParser parallelPackageParser = new ParallelPackageParser( mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir, mParallelPackageParserCallback)) { // Submit files for parsing in parallel int fileCount = 0; for (File file : files) { // 过滤 apk、文件夹并排除临时文件 final boolean isPackage = (isApkFile(file) || file.isDirectory()) && !PackageInstallerService.isStageName(file.getName()); if (!isPackage) { // Ignore entries which are not packages continue; } // 提交符合条件的文件,用于并行解析 parallelPackageParser.submit(file, parseFlags); // 计数用于后面处理解析结果 fileCount++; } // Process results one by one // 逐个处理解析结果 for (; fileCount > 0; fileCount--) { ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take(); Throwable throwable = parseResult.throwable; int errorCode = PackageManager.INSTALL_SUCCEEDED; if (throwable == null) { // TODO(toddke): move lower in the scan chain // Static shared libraries have synthetic package names if (parseResult.pkg.applicationInfo.isStaticSharedLibrary()) { // 重命名静态共享库包:pkg.packageName + "_" + pkg.staticSharedLibVersion renameStaticSharedLibraryPackage(parseResult.pkg); } try { if (errorCode == PackageManager.INSTALL_SUCCEEDED) { // 继续解析其它信息 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); } // Delete invalid userdata apps if ((scanFlags & SCAN_AS_SYSTEM) == 0 && errorCode != PackageManager.INSTALL_SUCCEEDED) { logCriticalInfo(Log.WARN, "Deleting invalid package at " + parseResult.scanFile); // 移除无用的用户安装包 removeCodePathLI(parseResult.scanFile); } } } }
ParallelPackageParser.class
这是一个辅助类用于并行解析安装包```java static class ParseResult {
1 2 3
PackageParser.Package pkg; // Parsed package File scanFile; // File that was parsed Throwable throwable; // Set if an error occurs during parsing
}
/**
- Take the parsed package from the parsing queue, waiting if necessary until the element
- appears in the queue.
- @return parsed package */ // 取出解析结果 public ParseResult take() { try { if (mInterruptedInThread != null) { throw new InterruptedException(“Interrupted in ” + mInterruptedInThread); } return mQueue.take(); } catch (InterruptedException e) { // We cannot recover from interrupt here Thread.currentThread().interrupt(); throw new IllegalStateException(e); } }
/** * Submits the file for parsing * @param scanFile file to scan * @param parseFlags parse falgs */ 提交到线程池 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(); // debug.separate_processes 值 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(); // Propagate result to callers of take(). // This is helpful to prevent main thread from getting stuck waiting on // ParallelPackageParser to finish in case of interruption mInterruptedInThread = Thread.currentThread().getName(); } }); }
@VisibleForTesting protected PackageParser.Package parsePackage(PackageParser packageParser, File scanFile, int parseFlags) throws PackageParser.PackageParserException { // 交由 PackageParser 类进行解析 return packageParser.parsePackage(scanFile, parseFlags, true /* useCaches */); } ```
PackageParser.class
安装包解析类parsePackage()
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
public Package parsePackage(File packageFile, int flags) throws PackageParserException { return parsePackage(packageFile, flags, false /* useCaches */); } public Package parsePackage(File packageFile, int flags, boolean useCaches) throws PackageParserException { // 这次是 true,如果从缓存中找到直接返回该对象 Package parsed = useCaches ? getCachedResult(packageFile, flags) : null; if (parsed != null) { return parsed; } long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0; // 目录和单个文件调用的方法不同,但大同小异; // Android 目前默认都是文件夹;那我这里也就只分析解析文件夹的方法 if (packageFile.isDirectory()) { parsed = parseClusterPackage(packageFile, flags); } else { parsed = parseMonolithicPackage(packageFile, flags); } long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0; // 缓存解析结果 cacheResult(packageFile, flags, parsed); if (LOG_PARSE_TIMINGS) { parseTime = cacheTime - parseTime; cacheTime = SystemClock.uptimeMillis() - cacheTime; if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) { Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime + "ms, update_cache=" + cacheTime + " ms"); } } return parsed; }
parseClusterPackage()
解析文件夹```java /**
- Parse all APKs contained in the given directory, treating them as a
- single package. This also performs sanity checking, such as requiring
- identical package name and version codes, a single base APK, and unique
- split names.
- Note that this does not perform signature verification; that
must be done separately in {@link #collectCertificates(Package, int)}. */ private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException { // 解析出所有 apk 信息 <3> final PackageLite lite = parseClusterPackageLite(packageDir, 0); if (mOnlyCoreApps && !lite.coreApp) { throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, “Not a coreApp: “ + packageDir); }
// Build the split dependency tree. // 构建子包依赖树 SparseArray
splitDependencies = null; final SplitAssetLoader assetLoader; if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) { try { splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite); assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags); } catch (SplitAssetDependencyLoader.IllegalDependencyException e) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage()); } } else { assetLoader = new DefaultSplitAssetLoader(lite, flags); } try { // 解析母 apk <5> final AssetManager assets = assetLoader.getBaseAssetManager(); final File baseApk = new File(lite.baseCodePath); final Package pkg = parseBaseApk(baseApk, assets, flags); if (pkg == null) { throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, “Failed to parse base APK: “ + baseApk); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
if (!ArrayUtils.isEmpty(lite.splitNames)) { final int num = lite.splitNames.length; pkg.splitNames = lite.splitNames; pkg.splitCodePaths = lite.splitCodePaths; pkg.splitRevisionCodes = lite.splitRevisionCodes; pkg.splitFlags = new int[num]; pkg.splitPrivateFlags = new int[num]; pkg.applicationInfo.splitNames = pkg.splitNames; pkg.applicationInfo.splitDependencies = splitDependencies; pkg.applicationInfo.splitClassLoaderNames = new String[num]; for (int i = 0; i < num; i++) { // 解析子 apk,过程类似母 apk final AssetManager splitAssets = assetLoader.getSplitAssetManager(i); parseSplitApk(pkg, i, splitAssets, flags); } } pkg.setCodePath(packageDir.getCanonicalPath()); pkg.setUse32bitAbi(lite.use32bitAbi); return pkg;
} catch (IOException e) { throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, “Failed to get path: “ + lite.baseCodePath, e); } finally { IoUtils.closeQuietly(assetLoader); } } ```
parseClusterPackageLite()
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
// PackageLite 的构造方法,主要是保存应用的信息 public PackageLite(String codePath, ApkLite baseApk, String[] splitNames, boolean[] isFeatureSplits, String[] usesSplitNames, String[] configForSplit, String[] splitCodePaths, int[] splitRevisionCodes) { this.packageName = baseApk.packageName; this.versionCode = baseApk.versionCode; this.versionCodeMajor = baseApk.versionCodeMajor; this.installLocation = baseApk.installLocation; this.verifiers = baseApk.verifiers; this.splitNames = splitNames; this.isFeatureSplits = isFeatureSplits; this.usesSplitNames = usesSplitNames; this.configForSplit = configForSplit; this.codePath = codePath; this.baseCodePath = baseApk.codePath; this.splitCodePaths = splitCodePaths; this.baseRevisionCode = baseApk.revisionCode; this.splitRevisionCodes = splitRevisionCodes; this.coreApp = baseApk.coreApp; this.debuggable = baseApk.debuggable; this.multiArch = baseApk.multiArch; this.use32bitAbi = baseApk.use32bitAbi; this.extractNativeLibs = baseApk.extractNativeLibs; this.isolatedSplits = baseApk.isolatedSplits; } static PackageLite parseClusterPackageLite(File packageDir, int flags) throws PackageParserException { final File[] files = packageDir.listFiles(); if (ArrayUtils.isEmpty(files)) { throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, "No packages found in split"); } String packageName = null; int versionCode = 0; Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite"); final ArrayMap<String, ApkLite> apks = new ArrayMap<>(); for (File file : files) { if (isApkFile(file)) { // 解析单个 APK 文件 final ApkLite lite = parseApkLite(file, flags); // Assert that all package names and version codes are // consistent with the first one we encounter. if (packageName == null) { packageName = lite.packageName; versionCode = lite.versionCode; } else { // 检查包名是否一致 if (!packageName.equals(lite.packageName)) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Inconsistent package " + lite.packageName + " in " + file + "; expected " + packageName); } // 检查版本号是否一致 if (versionCode != lite.versionCode) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Inconsistent version " + lite.versionCode + " in " + file + "; expected " + versionCode); } } // 检查子包的唯一性 // Assert that each split is defined only once if (apks.put(lite.splitName, lite) != null) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Split name " + lite.splitName + " defined more than once; most recent was " + file); } } } Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); // 因为 baseApk.splitName=null,所以移除 null 返回 baseApk final ApkLite baseApk = apks.remove(null); if (baseApk == null) { throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, "Missing base APK in " + packageDir); } // Always apply deterministic ordering based on splitName final int size = apks.size(); String[] splitNames = null; boolean[] isFeatureSplits = null; String[] usesSplitNames = null; String[] configForSplits = null; String[] splitCodePaths = null; int[] splitRevisionCodes = null; String[] splitClassLoaderNames = null; if (size > 0) { splitNames = new String[size]; isFeatureSplits = new boolean[size]; usesSplitNames = new String[size]; configForSplits = new String[size]; splitCodePaths = new String[size]; splitRevisionCodes = new int[size]; // 子包排序储存 splitNames = apks.keySet().toArray(splitNames); Arrays.sort(splitNames, sSplitNameComparator); for (int i = 0; i < size; i++) { final ApkLite apk = apks.get(splitNames[i]); usesSplitNames[i] = apk.usesSplitName; isFeatureSplits[i] = apk.isFeatureSplit; configForSplits[i] = apk.configForSplit; splitCodePaths[i] = apk.codePath; splitRevisionCodes[i] = apk.revisionCode; } } final String codePath = packageDir.getAbsolutePath(); // 构建 PackageLite 对象并返回 return new PackageLite(codePath, baseApk, splitNames, isFeatureSplits, usesSplitNames, configForSplits, splitCodePaths, splitRevisionCodes); }
parseApkLite()
```java /**
- Utility method that retrieves lightweight details about a single APK
- file, including package name, split name, and install location. *
- @param apkFile path to a single APK
- @param flags optional parse flags, such as
- {@link #PARSE_COLLECT_CERTIFICATES} */ public static ApkLite parseApkLite(File apkFile, int flags) throws PackageParserException { return parseApkLiteInner(apkFile, null, null, flags); }
private static ApkLite parseApkLiteInner(File apkFile, FileDescriptor fd, String debugPathName, int flags) throws PackageParserException { // 这里 fd、debugPathName 都是 null // 这个获得 apk 绝对路径 final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath();
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
XmlResourceParser parser = null; try { final ApkAssets apkAssets; try { // 从 apk 中加载 AndroidManifest.xml 文件 apkAssets = fd != null ? ApkAssets.loadFromFd(fd, debugPathName, false, false) : ApkAssets.loadFromPath(apkPath); } catch (IOException e) { throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, "Failed to parse " + apkPath); } // 准备解析 AndroidManifest.xml 文件 parser = apkAssets.openXml(ANDROID_MANIFEST_FILENAME); final SigningDetails signingDetails; if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) { // TODO: factor signature related items out of Package object final Package tempPkg = new Package((String) null); // 系统签名 apk 跳过签名相关 final boolean skipVerify = (flags & PARSE_IS_SYSTEM_DIR) != 0; Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates"); try { // 获取签名信息 collectCertificates(tempPkg, apkFile, skipVerify); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } signingDetails = tempPkg.mSigningDetails; } else { signingDetails = SigningDetails.UNKNOWN; } //XmlResourceParser 是 AttributeSet 的子类 final AttributeSet attrs = parser; return parseApkLite(apkPath, parser, attrs, signingDetails); } catch (XmlPullParserException | IOException | RuntimeException e) { Slog.w(TAG, "Failed to parse " + apkPath, e); throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, "Failed to parse " + apkPath, e); } finally { IoUtils.closeQuietly(parser); // TODO(b/72056911): Implement and call close() on ApkAssets. }
} // 主要解析 AndroidManifest.xml 文件,并将结果保存到 ApkLite 对象中 private static ApkLite parseApkLite(String codePath, XmlPullParser parser, AttributeSet attrs, SigningDetails signingDetails) throws IOException, XmlPullParserException, PackageParserException { final Pair
packageSplit = parsePackageSplitNames(parser, attrs); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
int installLocation = PARSE_DEFAULT_INSTALL_LOCATION; int versionCode = 0; int versionCodeMajor = 0; int revisionCode = 0; boolean coreApp = false; boolean debuggable = false; boolean multiArch = false; boolean use32bitAbi = false; boolean extractNativeLibs = true; boolean isolatedSplits = false; boolean isFeatureSplit = false; String configForSplit = null; String usesSplitName = null; // 从 AndroidManifest.xml 中解析上述变量的值 // ...... // 构建 ApkLite 对象并返回 return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit, configForSplit, usesSplitName, versionCode, versionCodeMajor, revisionCode, installLocation, verifiers, signingDetails, coreApp, debuggable, multiArch, use32bitAbi, extractNativeLibs, isolatedSplits);
} ```
parseBaseApk()
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
private Package parseBaseApk(File apkFile, AssetManager assets, int flags) throws PackageParserException { final String apkPath = apkFile.getAbsolutePath(); String volumeUuid = null; if (apkPath.startsWith(MNT_EXPAND)) { final int end = apkPath.indexOf('/', MNT_EXPAND.length()); volumeUuid = apkPath.substring(MNT_EXPAND.length(), end); } mParseError = PackageManager.INSTALL_SUCCEEDED; mArchiveSourcePath = apkFile.getAbsolutePath(); if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath); XmlResourceParser parser = null; try { // 根据 apk 路径获取资源管理器中的 AndroidManifest.xml 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); if (pkg == null) { throw new PackageParserException(mParseError, apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]); } pkg.setVolumeUuid(volumeUuid); pkg.setApplicationVolumeUuid(volumeUuid); pkg.setBaseCodePath(apkPath); pkg.setSigningDetails(SigningDetails.UNKNOWN); return pkg; } catch (PackageParserException e) { throw e; } catch (Exception e) { throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, "Failed to read manifest from " + apkPath, e); } finally { IoUtils.closeQuietly(parser); } } private boolean parseBaseApkChild(Package parentPkg, Resources res, XmlResourceParser parser, int flags, String[] outError) throws XmlPullParserException, IOException { // Make sure we have a valid child package name // 包名 String childPackageName = parser.getAttributeValue(null, "package"); if (validateName(childPackageName, true, false) != null) { mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME; return false; } // Child packages must be unique // 包名唯一 if (childPackageName.equals(parentPkg.packageName)) { String message = "Child package name cannot be equal to parent package name: " + parentPkg.packageName; Slog.w(TAG, message); outError[0] = message; mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false; } // Child packages must be unique if (parentPkg.hasChildPackage(childPackageName)) { String message = "Duplicate child package:" + childPackageName; Slog.w(TAG, message); outError[0] = message; mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return false; } // Go ahead and parse the child Package childPkg = new Package(childPackageName); // Child package inherits parent version code/name/target SDK // 解析出:版本号、名称、SDK 版本等信息 childPkg.mVersionCode = parentPkg.mVersionCode; childPkg.baseRevisionCode = parentPkg.baseRevisionCode; childPkg.mVersionName = parentPkg.mVersionName; childPkg.applicationInfo.targetSdkVersion = parentPkg.applicationInfo.targetSdkVersion; childPkg.applicationInfo.minSdkVersion = parentPkg.applicationInfo.minSdkVersion; childPkg = parseBaseApkCommon(childPkg, CHILD_PACKAGE_TAGS, res, parser, flags, outError); if (childPkg == null) { // If we got null then error was set during child parsing return false; } // Set the parent-child relation if (parentPkg.childPackages == null) { parentPkg.childPackages = new ArrayList<>(); } parentPkg.childPackages.add(childPkg); childPkg.parentPackage = parentPkg; return true; }
scanPackageChildLI()
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 PackageParser.Package scanPackageChildLI(PackageParser.Package pkg, final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime, @Nullable UserHandle user) throws PackageManagerException { // If the package has children and this is the first dive in the function // we scan the package with the SCAN_CHECK_ONLY flag set to see whether all // packages (parent and children) would be successfully scanned before the // actual scan since scanning mutates internal state and we want to atomically // install the package and its children. // 如果有子包,第一次只确保扫描到所有子包但不解析,因为解析会改变包的状态 if ((scanFlags & SCAN_CHECK_ONLY) == 0) { if (pkg.childPackages != null && pkg.childPackages.size() > 0) { scanFlags |= SCAN_CHECK_ONLY; } } else { scanFlags &= ~SCAN_CHECK_ONLY; } // Scan the parent PackageParser.Package scannedPkg = addForInitLI(pkg, parseFlags, scanFlags, currentTime, user); // Scan the children final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; for (int i = 0; i < childCount; i++) { PackageParser.Package childPackage = pkg.childPackages.get(i); addForInitLI(childPackage, parseFlags, scanFlags, currentTime, user); } if ((scanFlags & SCAN_CHECK_ONLY) != 0) { // 第二次进入改方法,解析所有包 return scanPackageChildLI(pkg, parseFlags, scanFlags, currentTime, user); } return scannedPkg; }
addForInitLI()
这个方法比较长,主要作用是把扫描到的应用包信息存储到
PackageManagerService
,由于以后查询,Intent
行为主要依赖次信息库;在此过程中也会附加检查,如果包与先前已知的包相同,则发生基本验证[例如确保匹配签名,检查版本代码等]。 如果程序包未通过签名检查,则将删除/data
上安装的版本。 如果新软件包的版本小于或等于/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 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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
private PackageParser.Package addForInitLI(PackageParser.Package pkg, @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime, @Nullable UserHandle user) throws PackageManagerException { // 系统内置的即非 data 分区 final boolean scanSystemPartition = (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0; final String renamedPkgName; final PackageSetting disabledPkgSetting; final boolean isSystemPkgUpdated; final boolean pkgAlreadyExists; PackageSetting pkgSetting; // NOTE: installPackageLI() has the same code to setup the package's // application info. This probably should be done lower in the call // stack [such as scanPackageOnly()]. However, we verify the application // info prior to that [in scanPackageNew()] and thus have to setup // the application info early. pkg.setApplicationVolumeUuid(pkg.volumeUuid); pkg.setApplicationInfoCodePath(pkg.codePath); pkg.setApplicationInfoBaseCodePath(pkg.baseCodePath); pkg.setApplicationInfoSplitCodePaths(pkg.splitCodePaths); pkg.setApplicationInfoResourcePath(pkg.codePath); pkg.setApplicationInfoBaseResourcePath(pkg.baseCodePath); pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths); synchronized (mPackages) { // 获取自首次安装以来已重命名的软件包的原始包名。 键是包的新名称,值是原始名称。 renamedPkgName = mSettings.getRenamedPackageLPr(pkg.mRealPackage); final String realPkgName = getRealPackageName(pkg, renamedPkgName); if (realPkgName != null) { // 更改为原始包名 ensurePackageRenamed(pkg, renamedPkgName); } //获取原始包配置,原始包必须以相同的方式签名,且必须具有相同的名称和共享用户[如果有]。 final PackageSetting originalPkgSetting = getOriginalPackageLocked(pkg, renamedPkgName); // 获取当前包配置 final PackageSetting installedPkgSetting = mSettings.getPackageLPr(pkg.packageName); pkgSetting = originalPkgSetting == null ? installedPkgSetting : originalPkgSetting; // 判断当前应用包是否已经存在 pkgAlreadyExists = pkgSetting != null; final String disabledPkgName = pkgAlreadyExists ? pkgSetting.name : pkg.packageName; // 获取被当前应用包替换的系统应用包配置 disabledPkgSetting = mSettings.getDisabledSystemPkgLPr(disabledPkgName); // 是否是系统应用的升级包 isSystemPkgUpdated = disabledPkgSetting != null; final SharedUserSetting sharedUserSetting = (pkg.mSharedUserId != null) ? mSettings.getSharedUserLPw(pkg.mSharedUserId, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, true) : null; if (scanSystemPartition) { // Potentially prune child packages. If the application on the /system // partition has been updated via OTA, but, is still disabled by a // version on /data, cycle through all of its children packages and // remove children that are no longer defined. // 如果 /system 分区上的应用程序已通过 OTA 更新,但仍然被 /data 上的版本禁用,则循环遍历其所有子程序包并删除不再定义的子项。 if (isSystemPkgUpdated) { final int scannedChildCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; final int disabledChildCount = disabledPkgSetting.childPackageNames != null ? disabledPkgSetting.childPackageNames.size() : 0; for (int i = 0; i < disabledChildCount; i++) { String disabledChildPackageName = disabledPkgSetting.childPackageNames.get(i); boolean disabledPackageAvailable = false; for (int j = 0; j < scannedChildCount; j++) { PackageParser.Package childPkg = pkg.childPackages.get(j); if (childPkg.packageName.equals(disabledChildPackageName)) { disabledPackageAvailable = true; break; } } if (!disabledPackageAvailable) { mSettings.removeDisabledSystemPackageLPw(disabledChildPackageName); } } // we're updating the disabled package, so, scan it as the package setting final ScanRequest request = new ScanRequest(pkg, sharedUserSetting, null, disabledPkgSetting /* pkgSetting */, null /* disabledPkgSetting */, null /* originalPkgSetting */, null, parseFlags, scanFlags, (pkg == mPlatformPackage), user); applyPolicy(pkg, parseFlags, scanFlags, mPlatformPackage); scanPackageOnlyLI(request, mFactoryTest, -1L); } } } // 新包安装路径是否改变 final boolean newPkgChangedPaths = pkgAlreadyExists && !pkgSetting.codePathString.equals(pkg.codePath); // 新包版本是否升级 final boolean newPkgVersionGreater = pkgAlreadyExists && pkg.getLongVersionCode() > pkgSetting.versionCode; // 系统包是否有升级 final boolean isSystemPkgBetter = scanSystemPartition && isSystemPkgUpdated && newPkgChangedPaths && newPkgVersionGreater; if (isSystemPkgBetter) { // The version of the application on /system is greater than the version on // /data. Switch back to the application on /system. // It's safe to assume the application on /system will correctly scan. If not, // there won't be a working copy of the application. // /system 上的应用程序版本大于 /data 上的版本。 切换回 /system 上的应用程序。 synchronized (mPackages) { // just remove the loaded entries from package lists mPackages.remove(pkgSetting.name); } final InstallArgs args = createInstallArgsForExisting( packageFlagsToInstallFlags(pkgSetting), pkgSetting.codePathString, pkgSetting.resourcePathString, getAppDexInstructionSets(pkgSetting)); // 清理资源文件 args.cleanUpResourcesLI(); synchronized (mPackages) { // 重新启用系统分区上的应用包 mSettings.enableSystemPackageLPw(pkgSetting.name); } } if (scanSystemPartition && isSystemPkgUpdated && !isSystemPkgBetter) { // The version of the application on the /system partition is less than or // equal to the version on the /data partition. Even though the disabled system package // is likely to be replaced by a version on the /data partition, we make assumptions // that it's part of the mPackages collection during package manager initialization. So, // add it to mPackages if there isn't already a package in the collection and then throw // an exception to use the application already installed on the /data partition. // /system 分区上的应用程序版本小于或等于 /data 分区上的版本。仍然使用 /data 分区上的版本,但仍将改包加入到应用管理器 synchronized (mPackages) { if (!mPackages.containsKey(pkg.packageName)) { mPackages.put(pkg.packageName, pkg); } } } // Verify certificates against what was last scanned. If it is an updated priv app, we will // force re-collecting certificate. // 根据上次扫描的内容验证证书。 如果它是更新 priv-app 下的应用程序,我们将强制重新收集证书。 final boolean forceCollect = PackageManagerServiceUtils.isApkVerificationForced( disabledPkgSetting); // Full APK verification can be skipped during certificate collection, only if the file is // in verified partition, or can be verified on access (when apk verity is enabled). In both // cases, only data in Signing Block is verified instead of the whole file. // 只有当文件位于已验证的分区中,或者可以在访问时验证(apk 启用访问验证时), //才能在证书收集期间跳过完整的 APK 验证。 在这两种情况下,仅验证签名块中的数据而不是整个文件。 final boolean skipVerify = ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0) || (forceCollect && canSkipFullPackageVerification(pkg)); collectCertificatesLI(pkgSetting, pkg, forceCollect, skipVerify); // Reset profile if the application version is changed maybeClearProfilesForUpgradesLI(pkgSetting, pkg); /* * A new system app appeared, but we already had a non-system one of the * same name installed earlier. */ // 出现了一个新的系统应用程序,但我们之前已经安装了一个同名的非系统应用程序。 boolean shouldHideSystemApp = false; // A new application appeared on /system, but, we already have a copy of // the application installed on /data. if (scanSystemPartition && !isSystemPkgUpdated && pkgAlreadyExists && !pkgSetting.isSystem()) { if (!pkg.mSigningDetails.checkCapability(pkgSetting.signatures.mSigningDetails, PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA) && !pkgSetting.signatures.mSigningDetails.checkCapability( pkg.mSigningDetails, PackageParser.SigningDetails.CertCapabilities.ROLLBACK)) { // 签名不匹配,删除改包 try (PackageFreezer freezer = freezePackage(pkg.packageName, "scanPackageInternalLI")) { deletePackageLIF(pkg.packageName, null, true, null, 0, null, false, null); } pkgSetting = null; } else if (newPkgVersionGreater) { // The application on /system is newer than the application on /data. // Simply remove the application on /data [keeping application data] // and replace it with the version on /system. // 系统新包版本更高,移除 /data 上的应用包但保留应用数据 InstallArgs args = createInstallArgsForExisting( packageFlagsToInstallFlags(pkgSetting), pkgSetting.codePathString, pkgSetting.resourcePathString, getAppDexInstructionSets(pkgSetting)); synchronized (mInstallLock) { args.cleanUpResourcesLI(); } } else { // The application on /system is older than the application on /data. Hide // the application on /system and the version on /data will be scanned later // and re-added like an update. // /system 上的应用程序比 /data 上的应用程序旧。 隐藏 /system 上的应用程序,稍后将扫描 /data 上的版本,并像更新一样重新添加。 shouldHideSystemApp = true; } } // 下一步 <2> final PackageParser.Package scannedPkg = scanPackageNewLI(pkg, parseFlags, scanFlags | SCAN_UPDATE_SIGNATURE, currentTime, user); if (shouldHideSystemApp) { synchronized (mPackages) { // 停用需要隐藏的系统包 mSettings.disableSystemPackageLPw(pkg.packageName, true); } } return scannedPkg; }
scanPackageNewLI()
这个方法主要是有新应用包时(比如 ota 引入)确认是否要替换原应用包
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
@GuardedBy("mInstallLock") private PackageParser.Package scanPackageNewLI(@NonNull PackageParser.Package pkg, final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime, @Nullable UserHandle user) throws PackageManagerException { final String renamedPkgName = mSettings.getRenamedPackageLPr(pkg.mRealPackage); final String realPkgName = getRealPackageName(pkg, renamedPkgName); if (realPkgName != null) { ensurePackageRenamed(pkg, renamedPkgName); } final PackageSetting originalPkgSetting = getOriginalPackageLocked(pkg, renamedPkgName); final PackageSetting pkgSetting = mSettings.getPackageLPr(pkg.packageName); final PackageSetting disabledPkgSetting = mSettings.getDisabledSystemPkgLPr(pkg.packageName); // 调整扫描参数 scanFlags = adjustScanFlags(scanFlags, pkgSetting, disabledPkgSetting, user, pkg); synchronized (mPackages) { // 根据给定的策略标志将策略应用于已解析的包。 applyPolicy(pkg, parseFlags, scanFlags, mPlatformPackage); // 断言解析的包根据给定的策略有效。 如果包无效,无论出于何种原因,抛出 PackageManagerException。 assertPackageIsValid(pkg, parseFlags, scanFlags); SharedUserSetting sharedUserSetting = null; if (pkg.mSharedUserId != null) { // SIDE EFFECTS; may potentially allocate a new shared user // 如果不存在则新建 sharedUserSetting = mSettings.getSharedUserLPw( pkg.mSharedUserId, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, true /*create*/); } boolean scanSucceeded = false; try { final ScanRequest request = new ScanRequest(pkg, sharedUserSetting, pkgSetting == null ? null : pkgSetting.pkg, pkgSetting, disabledPkgSetting, originalPkgSetting, realPkgName, parseFlags, scanFlags, (pkg == mPlatformPackage), user); // 前面主要是解析 AndroidManifest.xm 获取应用的基本信息;同时确定应用使用的版本 // 这个方法将解析四大组件相关信息,并储存以供以后查询,比如 Intent 相关 <3> final ScanResult result = scanPackageOnlyLI(request, mFactoryTest, currentTime); if (result.success) { // 提交结果 <4> commitScanResultsLocked(request, result); } scanSucceeded = true; } finally { if (!scanSucceeded && (scanFlags & SCAN_DELETE_DATA_ON_FAILURES) != 0) { // DELETE_DATA_ON_FAILURES is only used by frozen paths // 失败则清理无效数据 destroyAppDataLIF(pkg, UserHandle.USER_ALL, StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE); destroyAppProfilesLIF(pkg, UserHandle.USER_ALL); } } } return pkg; }
scanPackageOnlyLI()
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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
@GuardedBy("mInstallLock") private static @NonNull ScanResult scanPackageOnlyLI(@NonNull ScanRequest request, boolean isUnderFactoryTest, long currentTime) throws PackageManagerException { final PackageParser.Package pkg = request.pkg; PackageSetting pkgSetting = request.pkgSetting; final PackageSetting disabledPkgSetting = request.disabledPkgSetting; final PackageSetting originalPkgSetting = request.originalPkgSetting; final @ParseFlags int parseFlags = request.parseFlags; final @ScanFlags int scanFlags = request.scanFlags; final String realPkgName = request.realPkgName; final SharedUserSetting sharedUserSetting = request.sharedUserSetting; final UserHandle user = request.user; final boolean isPlatformPackage = request.isPlatformPackage; List<String> changedAbiCodePath = null; DexManager.maybeLogUnexpectedPackageDetails(pkg); // Initialize package source and resource directories // 初始化资源、源码目录 final File scanFile = new File(pkg.codePath); final File destCodeFile = new File(pkg.applicationInfo.getCodePath()); final File destResourceFile = new File(pkg.applicationInfo.getResourcePath()); // We keep references to the derived CPU Abis from settings in oder to reuse // them in the case where we're not upgrading or booting for the first time. // 如果不是系统升级或首次开机可以使用以前保存的 CPU Abis 的引用 String primaryCpuAbiFromSettings = null; String secondaryCpuAbiFromSettings = null; // 需要生成 abi 引用 boolean needToDeriveAbi = (scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0; if (!needToDeriveAbi) { // 不需要生成 abi 引用时,确保是否有旧的存在,没有则要生成 if (pkgSetting != null) { primaryCpuAbiFromSettings = pkgSetting.primaryCpuAbiString; secondaryCpuAbiFromSettings = pkgSetting.secondaryCpuAbiString; } else { // Re-scanning a system package after uninstalling updates; need to derive ABI needToDeriveAbi = true; } } // sharedUser 不一致,需要重新生成 PackageSetting if (pkgSetting != null && pkgSetting.sharedUser != sharedUserSetting) { PackageManagerService.reportSettingsProblem(Log.WARN, "Package " + pkg.packageName + " shared user changed from " + (pkgSetting.sharedUser != null ? pkgSetting.sharedUser.name : "<nothing>") + " to " + (sharedUserSetting != null ? sharedUserSetting.name : "<nothing>") + "; replacing with new"); pkgSetting = null; } String[] usesStaticLibraries = null; if (pkg.usesStaticLibraries != null) { usesStaticLibraries = new String[pkg.usesStaticLibraries.size()]; pkg.usesStaticLibraries.toArray(usesStaticLibraries); } // 更新 PackageSetting 没有则要生成 final boolean createNewPackage = (pkgSetting == null); if (createNewPackage) { final String parentPackageName = (pkg.parentPackage != null) ? pkg.parentPackage.packageName : null; final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0; final boolean virtualPreload = (scanFlags & SCAN_AS_VIRTUAL_PRELOAD) != 0; // REMOVE SharedUserSetting from method; update in a separate call pkgSetting = Settings.createNewSetting(pkg.packageName, originalPkgSetting, disabledPkgSetting, realPkgName, sharedUserSetting, destCodeFile, destResourceFile, pkg.applicationInfo.nativeLibraryRootDir, pkg.applicationInfo.primaryCpuAbi, pkg.applicationInfo.secondaryCpuAbi, pkg.mVersionCode, pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags, user, true /*allowInstall*/, instantApp, virtualPreload, parentPackageName, pkg.getChildPackageNames(), UserManagerService.getInstance(), usesStaticLibraries, pkg.usesStaticLibrariesVersions); } else { // REMOVE SharedUserSetting from method; update in a separate call. // // TODO(narayan): This update is bogus. nativeLibraryDir & primaryCpuAbi, // secondaryCpuAbi are not known at this point so we always update them // to null here, only to reset them at a later point. Settings.updatePackageSetting(pkgSetting, disabledPkgSetting, sharedUserSetting, destCodeFile, destResourceFile, pkg.applicationInfo.nativeLibraryDir, pkg.applicationInfo.primaryCpuAbi, pkg.applicationInfo.secondaryCpuAbi, pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags, pkg.getChildPackageNames(), UserManagerService.getInstance(), usesStaticLibraries, pkg.usesStaticLibrariesVersions); } if (createNewPackage && originalPkgSetting != null) { // This is the initial transition from the original package, so, // fix up the new package's name now. We must do this after looking // up the package under its new name, so getPackageLP takes care of // fiddling things correctly. pkg.setPackageName(originalPkgSetting.name); // File a report about this. String msg = "New package " + pkgSetting.realName + " renamed to replace old package " + pkgSetting.name; reportSettingsProblem(Log.WARN, msg); } final int userId = (user == null ? UserHandle.USER_SYSTEM : user.getIdentifier()); // for existing packages, change the install state; but, only if it's explicitly specified // 更改已存在应用包的安装状态 if (!createNewPackage) { final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0; final boolean fullApp = (scanFlags & SCAN_AS_FULL_APP) != 0; setInstantAppForUser(pkgSetting, userId, instantApp, fullApp); } if (disabledPkgSetting != null) { pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; } // Apps which share a sharedUserId must be placed in the same selinux domain. If this // package is the first app installed as this shared user, set seInfoTargetSdkVersion to its // targetSdkVersion. These are later adjusted in PackageManagerService's constructor to be // the lowest targetSdkVersion of all apps within the shared user, which corresponds to the // least restrictive selinux domain. // NOTE: As new packages are installed / updated, the shared user's seinfoTargetSdkVersion // will NOT be modified until next boot, even if a lower targetSdkVersion is used. This // ensures that all packages continue to run in the same selinux domain. // 共享 sharedUserId 的应用必须放在同一个 selinux 域中。 如果此程序包是作为此共享用户安装的第一个应用程序, // 请将 seInfoTargetSdkVersion 设置为其 targetSdkVersion。 这些稍后在 PackageManagerService 的构造函 // 数中调整为共享用户中所有应用程序的最低 targetSdkVersion,这对应于限制性最小的 selinux 域。 // 注意:在安装/更新新软件包时,即使使用较低的 targetSdkVersion,共享用户的 seinfoTargetSdkVersion // 也不会被修改,直到下次引导。 这可确保所有包继续在同一 selinux 域中运行。 final int targetSdkVersion = ((sharedUserSetting != null) && (sharedUserSetting.packages.size() != 0)) ? sharedUserSetting.seInfoTargetSdkVersion : pkg.applicationInfo.targetSdkVersion; // TODO(b/71593002): isPrivileged for sharedUser and appInfo should never be out of sync. // They currently can be if the sharedUser apps are signed with the platform key. final boolean isPrivileged = (sharedUserSetting != null) ? sharedUserSetting.isPrivileged() | pkg.isPrivileged() : pkg.isPrivileged(); pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, isPrivileged, pkg.applicationInfo.targetSandboxVersion, targetSdkVersion); pkg.applicationInfo.seInfoUser = SELinuxUtil.assignSeinfoUser(pkgSetting.readUserState( userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId)); pkg.mExtras = pkgSetting; pkg.applicationInfo.processName = fixProcessName( pkg.applicationInfo.packageName, pkg.applicationInfo.processName); if (!isPlatformPackage) { // Get all of our default paths setup pkg.applicationInfo.initForUser(UserHandle.USER_SYSTEM); } // 更新 abi 引用 final String cpuAbiOverride = deriveAbiOverride(pkg.cpuAbiOverride, pkgSetting); if ((scanFlags & SCAN_NEW_INSTALL) == 0) { if (needToDeriveAbi) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi"); final boolean extractNativeLibs = !pkg.isLibrary(); derivePackageAbi(pkg, cpuAbiOverride, extractNativeLibs); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); // Some system apps still use directory structure for native libraries // in which case we might end up not detecting abi solely based on apk // structure. Try to detect abi based on directory structure. if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp() && pkg.applicationInfo.primaryCpuAbi == null) { setBundledAppAbisAndRoots(pkg, pkgSetting); setNativeLibraryPaths(pkg, sAppLib32InstallDir); } } else { // This is not a first boot or an upgrade, don't bother deriving the // ABI during the scan. Instead, trust the value that was stored in the // package setting. pkg.applicationInfo.primaryCpuAbi = primaryCpuAbiFromSettings; pkg.applicationInfo.secondaryCpuAbi = secondaryCpuAbiFromSettings; setNativeLibraryPaths(pkg, sAppLib32InstallDir); if (DEBUG_ABI_SELECTION) { Slog.i(TAG, "Using ABIS and native lib paths from settings : " + pkg.packageName + " " + pkg.applicationInfo.primaryCpuAbi + ", " + pkg.applicationInfo.secondaryCpuAbi); } } } else { if ((scanFlags & SCAN_MOVE) != 0) { // We haven't run dex-opt for this move (since we've moved the compiled output too) // but we already have this packages package info in the PackageSetting. We just // use that and derive the native library path based on the new codepath. pkg.applicationInfo.primaryCpuAbi = pkgSetting.primaryCpuAbiString; pkg.applicationInfo.secondaryCpuAbi = pkgSetting.secondaryCpuAbiString; } // Set native library paths again. For moves, the path will be updated based on the // ABIs we've determined above. For non-moves, the path will be updated based on the // ABIs we determined during compilation, but the path will depend on the final // package path (after the rename away from the stage path). setNativeLibraryPaths(pkg, sAppLib32InstallDir); } // This is a special case for the "system" package, where the ABI is // dictated by the zygote configuration (and init.rc). We should keep track // of this ABI so that we can deal with "normal" applications that run under // the same UID correctly. if (isPlatformPackage) { pkg.applicationInfo.primaryCpuAbi = VMRuntime.getRuntime().is64Bit() ? Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0]; } // If there's a mismatch between the abi-override in the package setting // and the abiOverride specified for the install. Warn about this because we // would've already compiled the app without taking the package setting into // account. if ((scanFlags & SCAN_NO_DEX) == 0 && (scanFlags & SCAN_NEW_INSTALL) != 0) { if (cpuAbiOverride == null && pkg.packageName != null) { Slog.w(TAG, "Ignoring persisted ABI override " + cpuAbiOverride + " for package " + pkg.packageName); } } pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi; pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi; pkgSetting.cpuAbiOverrideString = cpuAbiOverride; // Copy the derived override back to the parsed package, so that we can // update the package settings accordingly. pkg.cpuAbiOverride = cpuAbiOverride; // Push the derived path down into PackageSettings so we know what to // clean up at uninstall time. pkgSetting.legacyNativeLibraryPathString = pkg.applicationInfo.nativeLibraryRootDir; if ((scanFlags & SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) { // We don't do this here during boot because we can do it all // at once after scanning all existing packages. // // We also do this *before* we perform dexopt on this package, so that // we can avoid redundant dexopts, and also to make sure we've got the // code and package path correct. changedAbiCodePath = adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages, pkg); } if (isUnderFactoryTest && pkg.requestedPermissions.contains( android.Manifest.permission.FACTORY_TEST)) { pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST; } if (isSystemApp(pkg)) { pkgSetting.isOrphaned = true; } // Take care of first install / last update times. // 记录首次安装时间和最后更新时间 final long scanFileTime = getLastModifiedTime(pkg); if (currentTime != 0) { if (pkgSetting.firstInstallTime == 0) { pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime; } else if ((scanFlags & SCAN_UPDATE_TIME) != 0) { pkgSetting.lastUpdateTime = currentTime; } } else if (pkgSetting.firstInstallTime == 0) { // We need *something*. Take time time stamp of the file. pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime; } else if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0) { if (scanFileTime != pkgSetting.timeStamp) { // A package on the system image has changed; consider this // to be an update. pkgSetting.lastUpdateTime = scanFileTime; } } pkgSetting.setTimeStamp(scanFileTime); pkgSetting.pkg = pkg; pkgSetting.pkgFlags = pkg.applicationInfo.flags; if (pkg.getLongVersionCode() != pkgSetting.versionCode) { pkgSetting.versionCode = pkg.getLongVersionCode(); } // Update volume if needed final String volumeUuid = pkg.applicationInfo.volumeUuid; if (!Objects.equals(volumeUuid, pkgSetting.volumeUuid)) { Slog.i(PackageManagerService.TAG, "Update" + (pkgSetting.isSystem() ? " system" : "") + " package " + pkg.packageName + " volume from " + pkgSetting.volumeUuid + " to " + volumeUuid); pkgSetting.volumeUuid = volumeUuid; } return new ScanResult(true, pkgSetting, changedAbiCodePath); }
commitScanResultsLocked()
提交包扫描并修改系统状态。
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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
@GuardedBy("mPackages") private void commitScanResultsLocked(@NonNull ScanRequest request, @NonNull ScanResult result) throws PackageManagerException { final PackageParser.Package pkg = request.pkg; final PackageParser.Package oldPkg = request.oldPkg; final @ParseFlags int parseFlags = request.parseFlags; final @ScanFlags int scanFlags = request.scanFlags; final PackageSetting oldPkgSetting = request.oldPkgSetting; final PackageSetting originalPkgSetting = request.originalPkgSetting; final PackageSetting disabledPkgSetting = request.disabledPkgSetting; final UserHandle user = request.user; final String realPkgName = request.realPkgName; final PackageSetting pkgSetting = result.pkgSetting; final List<String> changedAbiCodePath = result.changedAbiCodePath; final boolean newPkgSettingCreated = (result.pkgSetting != request.pkgSetting); // 新旧包 sharedUser 不一致 if (newPkgSettingCreated) { if (originalPkgSetting != null) { mSettings.addRenamedPackageLPw(pkg.packageName, originalPkgSetting.name); } // 新建用户 mSettings.addUserToSettingLPw(pkgSetting); // 原应用包数据传给新包,原包数据将不会保留 if (originalPkgSetting != null && (scanFlags & SCAN_CHECK_ONLY) == 0) { mTransferedPackages.add(originalPkgSetting.name); } } pkg.applicationInfo.uid = pkgSetting.appId; // 更新用户状态 mSettings.writeUserRestrictionsLPw(pkgSetting, oldPkgSetting); if ((scanFlags & SCAN_CHECK_ONLY) == 0 && realPkgName != null) { mTransferedPackages.add(pkg.packageName); } if ((scanFlags & SCAN_BOOTING) == 0 && (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) { // Check all shared libraries and map to their actual file path. // We only do this here for apps not on a system dir, because those // are the only ones that can fail an install due to this. We // will take care of the system apps by updating all of their // library paths after the scan is done. Also during the initial // scan don't update any libs as we do this wholesale after all // apps are scanned to avoid dependency based scanning. // 检查所有非系统目录上的共享库并映射到它们的实际文件路径。 updateSharedLibrariesLPr(pkg, null); } // All versions of a static shared library are referenced with the same // package name. Internally, we use a synthetic package name to allow // multiple versions of the same shared library to be installed. So, // we need to generate the synthetic package name of the latest shared // library in order to compare signatures. // 使用相同的包名称引用静态共享库的所有版本。 在内部,我们使用合成包名称来允许安装同一共享库的多个版本。 // 因此,我们需要生成最新共享库的合成包名称,以便比较签名。 // 以下处理应用包的签名信息 PackageSetting signatureCheckPs = pkgSetting; if (pkg.applicationInfo.isStaticSharedLibrary()) { SharedLibraryEntry libraryEntry = getLatestSharedLibraVersionLPr(pkg); if (libraryEntry != null) { signatureCheckPs = mSettings.getPackageLPr(libraryEntry.apk); } } final KeySetManagerService ksms = mSettings.mKeySetManagerService; if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, scanFlags)) { if (ksms.checkUpgradeKeySetLocked(signatureCheckPs, pkg)) { // We just determined the app is signed correctly, so bring // over the latest parsed certs. pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails; } else { if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) { throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package " + pkg.packageName + " upgrade keys do not match the " + "previously installed version"); } else { pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails; String msg = "System package " + pkg.packageName + " signature changed; retaining data."; reportSettingsProblem(Log.WARN, msg); } } } else { try { final boolean compareCompat = isCompatSignatureUpdateNeeded(pkg); final boolean compareRecover = isRecoverSignatureUpdateNeeded(pkg); final boolean compatMatch = verifySignatures(signatureCheckPs, disabledPkgSetting, pkg.mSigningDetails, compareCompat, compareRecover); // The new KeySets will be re-added later in the scanning process. if (compatMatch) { synchronized (mPackages) { ksms.removeAppKeySetDataLPw(pkg.packageName); } } // We just determined the app is signed correctly, so bring // over the latest parsed certs. pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails; // if this is is a sharedUser, check to see if the new package is signed by a newer // signing certificate than the existing one, and if so, copy over the new details if (signatureCheckPs.sharedUser != null) { if (pkg.mSigningDetails.hasAncestor( signatureCheckPs.sharedUser.signatures.mSigningDetails)) { signatureCheckPs.sharedUser.signatures.mSigningDetails = pkg.mSigningDetails; } if (signatureCheckPs.sharedUser.signaturesChanged == null) { signatureCheckPs.sharedUser.signaturesChanged = Boolean.FALSE; } } } catch (PackageManagerException e) { if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) { throw e; } // The signature has changed, but this package is in the system // image... let's recover! pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails; // If the system app is part of a shared user we allow that shared user to change // signatures as well as part of an OTA. We still need to verify that the signatures // are consistent within the shared user for a given boot, so only allow updating // the signatures on the first package scanned for the shared user (i.e. if the // signaturesChanged state hasn't been initialized yet in SharedUserSetting). // OTA 更改了签名信息,更新签名信息 if (signatureCheckPs.sharedUser != null) { if (signatureCheckPs.sharedUser.signaturesChanged != null && compareSignatures( signatureCheckPs.sharedUser.signatures.mSigningDetails.signatures, pkg.mSigningDetails.signatures) != PackageManager.SIGNATURE_MATCH) { throw new PackageManagerException( INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, "Signature mismatch for shared user: " + pkgSetting.sharedUser); } signatureCheckPs.sharedUser.signatures.mSigningDetails = pkg.mSigningDetails; signatureCheckPs.sharedUser.signaturesChanged = Boolean.TRUE; } // File a report about this. String msg = "System package " + pkg.packageName + " signature changed; retaining data."; reportSettingsProblem(Log.WARN, msg); } catch (IllegalArgumentException e) { } } // 权限相关 if ((scanFlags & SCAN_CHECK_ONLY) == 0 && pkg.mAdoptPermissions != null) { // This package wants to adopt ownership of permissions from // another package. for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) { final String origName = pkg.mAdoptPermissions.get(i); final PackageSetting orig = mSettings.getPackageLPr(origName); if (orig != null) { if (verifyPackageUpdateLPr(orig, pkg)) { Slog.i(TAG, "Adopting permissions from " + origName + " to " + pkg.packageName); mSettings.mPermissions.transferPermissions(origName, pkg.packageName); } } } } // 处理 cpu abi if (changedAbiCodePath != null && changedAbiCodePath.size() > 0) { for (int i = changedAbiCodePath.size() - 1; i >= 0; --i) { final String codePathString = changedAbiCodePath.get(i); try { mInstaller.rmdex(codePathString, getDexCodeInstructionSet(getPreferredInstructionSet())); } catch (InstallerException ignored) { } } } if ((scanFlags & SCAN_CHECK_ONLY) != 0) { if (oldPkgSetting != null) { synchronized (mPackages) { mSettings.mPackages.put(oldPkgSetting.name, oldPkgSetting); } } } else { final int userId = user == null ? 0 : user.getIdentifier(); // Modify state for the given package setting // 提交扫描结果到 PackageManagerService commitPackageSettings(pkg, oldPkg, pkgSetting, user, scanFlags, (parseFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/); if (pkgSetting.getInstantApp(userId)) { mInstantAppRegistry.addInstantAppLPw(userId, pkgSetting.appId); } } }
commitPackageSettings()
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 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
private void commitPackageSettings(PackageParser.Package pkg, @Nullable PackageParser.Package oldPkg, PackageSetting pkgSetting, UserHandle user, final @ScanFlags int scanFlags, boolean chatty) { final String pkgName = pkg.packageName; // mCustomResolverComponentName 定义于:R.string.config_customResolverActivity if (mCustomResolverComponentName != null && mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) { // 用自定义的替换默认的 ResolverActivity;前面说过 ResolverActivity 的用处 // Intent 有多个匹配项时,展示这些匹配项供用户选择一个 setUpCustomResolverActivity(pkg); } // 处理特殊包名:android if (pkg.packageName.equals("android")) { synchronized (mPackages) { if ((scanFlags & SCAN_CHECK_ONLY) == 0) { // Set up information for our fall-back user intent resolution activity. // 系统应用包 mPlatformPackage = pkg; pkg.mVersionCode = mSdkVersion; pkg.mVersionCodeMajor = 0; mAndroidApplication = pkg.applicationInfo; // 没有自定义 ResolverActivity;初始化默认 ResolverActivity if (!mResolverReplaced) { mResolveActivity.applicationInfo = mAndroidApplication; mResolveActivity.name = ResolverActivity.class.getName(); mResolveActivity.packageName = mAndroidApplication.packageName; mResolveActivity.processName = "system:ui"; mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE; mResolveActivity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NEVER; mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS; mResolveActivity.theme = R.style.Theme_Material_Dialog_Alert; mResolveActivity.exported = true; mResolveActivity.enabled = true; mResolveActivity.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE; mResolveActivity.configChanges = ActivityInfo.CONFIG_SCREEN_SIZE | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ORIENTATION | ActivityInfo.CONFIG_KEYBOARD | ActivityInfo.CONFIG_KEYBOARD_HIDDEN; mResolveInfo.activityInfo = mResolveActivity; mResolveInfo.priority = 0; mResolveInfo.preferredOrder = 0; mResolveInfo.match = 0; mResolveComponentName = new ComponentName( mAndroidApplication.packageName, mResolveActivity.name); } } } } ArrayList<PackageParser.Package> clientLibPkgs = null; // writer synchronized (mPackages) { boolean hasStaticSharedLibs = false; // Any app can add new static shared libraries // 更新链接库信息 if (pkg.staticSharedLibName != null) { // Static shared libs don't allow renaming as they have synthetic package // names to allow install of multiple versions, so use name from manifest. if (addSharedLibraryLPw(null, pkg.packageName, pkg.staticSharedLibName, pkg.staticSharedLibVersion, SharedLibraryInfo.TYPE_STATIC, pkg.manifestPackageName, pkg.getLongVersionCode())) { hasStaticSharedLibs = true; } else { Slog.w(TAG, "Package " + pkg.packageName + " library " + pkg.staticSharedLibName + " already exists; skipping"); } // Static shared libs cannot be updated once installed since they // use synthetic package name which includes the version code, so // not need to update other packages's shared lib dependencies. } // 系统应用包更新时,链接库相关更新 if (!hasStaticSharedLibs && (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { // Only system apps can add new dynamic shared libraries. if (pkg.libraryNames != null) { for (int i = 0; i < pkg.libraryNames.size(); i++) { String name = pkg.libraryNames.get(i); boolean allowed = false; if (pkg.isUpdatedSystemApp()) { // New library entries can only be added through the // system image. This is important to get rid of a lot // of nasty edge cases: for example if we allowed a non- // system update of the app to add a library, then uninstalling // the update would make the library go away, and assumptions // we made such as through app install filtering would now // have allowed apps on the device which aren't compatible // with it. Better to just have the restriction here, be // conservative, and create many fewer cases that can negatively // impact the user experience. final PackageSetting sysPs = mSettings .getDisabledSystemPkgLPr(pkg.packageName); if (sysPs.pkg != null && sysPs.pkg.libraryNames != null) { for (int j = 0; j < sysPs.pkg.libraryNames.size(); j++) { if (name.equals(sysPs.pkg.libraryNames.get(j))) { allowed = true; break; } } } } else { allowed = true; } if ((scanFlags & SCAN_BOOTING) == 0) { // If we are not booting, we need to update any applications // that are clients of our shared library. If we are booting, // this will all be done once the scan is complete. clientLibPkgs = updateAllSharedLibrariesLPw(pkg); } } } } if ((scanFlags & SCAN_BOOTING) != 0) { // No apps can run during boot scan, so they don't need to be frozen } else if ((scanFlags & SCAN_DONT_KILL_APP) != 0) { // Caller asked to not kill app, so it's probably not frozen } else if ((scanFlags & SCAN_IGNORE_FROZEN) != 0) { // Caller asked us to ignore frozen check for some reason; they // probably didn't know the package name } else { // We're doing major surgery on this package, so it better be frozen // right now to keep it from launching checkPackageFrozen(pkgName); } // Also need to kill any apps that are dependent on the library. if (clientLibPkgs != null) { for (int i=0; i<clientLibPkgs.size(); i++) { PackageParser.Package clientPkg = clientLibPkgs.get(i); killApplication(clientPkg.applicationInfo.packageName, clientPkg.applicationInfo.uid, "update lib"); } } // writer Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings"); // PackageManagerService 存储四大组件信息 synchronized (mPackages) { // We don't expect installation to fail beyond this point // Add the new setting to mSettings mSettings.insertPackageSettingLPw(pkgSetting, pkg); // Add the new setting to mPackages mPackages.put(pkg.applicationInfo.packageName, pkg); // Make sure we don't accidentally delete its data. final Iterator<PackageCleanItem> iter = mSettings.mPackagesToBeCleaned.iterator(); while (iter.hasNext()) { PackageCleanItem item = iter.next(); if (pkgName.equals(item.packageName)) { iter.remove(); } } // Add the package's KeySets to the global KeySetManagerService KeySetManagerService ksms = mSettings.mKeySetManagerService; ksms.addScannedPackageLPw(pkg); // Provider int N = pkg.providers.size(); StringBuilder r = null; int i; for (i=0; i<N; i++) { PackageParser.Provider p = pkg.providers.get(i); // ...... } // Service N = pkg.services.size(); r = null; for (i=0; i<N; i++) { PackageParser.Service s = pkg.services.get(i); s.info.processName = fixProcessName(pkg.applicationInfo.processName, s.info.processName); mServices.addService(s); if (chatty) { if (r == null) { r = new StringBuilder(256); } else { r.append(' '); } r.append(s.info.name); } } // Receiver N = pkg.receivers.size(); r = null; for (i=0; i<N; i++) { PackageParser.Activity a = pkg.receivers.get(i); a.info.processName = fixProcessName(pkg.applicationInfo.processName, a.info.processName); mReceivers.addActivity(a, "receiver"); if (chatty) { if (r == null) { r = new StringBuilder(256); } else { r.append(' '); } r.append(a.info.name); } } // Activity N = pkg.activities.size(); r = null; for (i=0; i<N; i++) { PackageParser.Activity a = pkg.activities.get(i); a.info.processName = fixProcessName(pkg.applicationInfo.processName, a.info.processName); mActivities.addActivity(a, "activity"); if (chatty) { if (r == null) { r = new StringBuilder(256); } else { r.append(' '); } r.append(a.info.name); } } // Permission 不允许临时应用程序定义新权限和权限组。 // Don't allow ephemeral applications to define new permissions groups. if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) { } else { mPermissionManager.addAllPermissionGroups(pkg, chatty); } // Don't allow ephemeral applications to define new permissions. if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) { } else { mPermissionManager.addAllPermissions(pkg, chatty); } // Instrumentation N = pkg.instrumentation.size(); r = null; for (i=0; i<N; i++) { PackageParser.Instrumentation a = pkg.instrumentation.get(i); a.info.packageName = pkg.applicationInfo.packageName; a.info.sourceDir = pkg.applicationInfo.sourceDir; a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir; a.info.splitNames = pkg.splitNames; a.info.splitSourceDirs = pkg.applicationInfo.splitSourceDirs; a.info.splitPublicSourceDirs = pkg.applicationInfo.splitPublicSourceDirs; a.info.splitDependencies = pkg.applicationInfo.splitDependencies; a.info.dataDir = pkg.applicationInfo.dataDir; a.info.deviceProtectedDataDir = pkg.applicationInfo.deviceProtectedDataDir; a.info.credentialProtectedDataDir = pkg.applicationInfo.credentialProtectedDataDir; a.info.primaryCpuAbi = pkg.applicationInfo.primaryCpuAbi; a.info.secondaryCpuAbi = pkg.applicationInfo.secondaryCpuAbi; a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir; a.info.secondaryNativeLibraryDir = pkg.applicationInfo.secondaryNativeLibraryDir; mInstrumentation.put(a.getComponentName(), a); if (chatty) { if (r == null) { r = new StringBuilder(256); } else { r.append(' '); } r.append(a.info.name); } } // Protected Broadcast if (pkg.protectedBroadcasts != null) { N = pkg.protectedBroadcasts.size(); synchronized (mProtectedBroadcasts) { for (i = 0; i < N; i++) { mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i)); } } } }