当前位置: 首页 > news >正文

网站建设哪家好就推 鹏博资讯如何做 行业社交类网站

网站建设哪家好就推 鹏博资讯,如何做 行业社交类网站,企业文化案例,扬中网站建设多少钱经过前面准备、浏览、协调这些步骤#xff0c;马上要进入提交阶段了。所谓提交#xff0c;就是把这些安装应用的相关信息和状态都放到系统中。对于已安装普通应用#xff0c;它其实分为两个步骤#xff0c;先卸载旧包#xff0c;再安装新包。当然#xff0c;如果是新安装…  经过前面准备、浏览、协调这些步骤马上要进入提交阶段了。所谓提交就是把这些安装应用的相关信息和状态都放到系统中。对于已安装普通应用它其实分为两个步骤先卸载旧包再安装新包。当然如果是新安装的应用包只涉及安装新包这个步骤。   它实现在commitPackagesLocked(final CommitRequest request)中 GuardedBy(mLock)private void commitPackagesLocked(final CommitRequest request) {// TODO: remove any expected failures from this method; this should only be able to fail due// to unavoidable errors (I/O, etc.)for (ReconciledPackage reconciledPkg : request.reconciledPackages.values()) {final ScanResult scanResult reconciledPkg.scanResult;final ScanRequest scanRequest scanResult.request;final ParsedPackage parsedPackage scanRequest.parsedPackage;final String packageName parsedPackage.getPackageName();final PackageInstalledInfo res reconciledPkg.installResult;if (reconciledPkg.prepareResult.replace) {AndroidPackage oldPackage mPackages.get(packageName);// Set the update and install timesPackageSetting deletedPkgSetting getPackageSetting(oldPackage.getPackageName());reconciledPkg.pkgSetting.firstInstallTime deletedPkgSetting.firstInstallTime;reconciledPkg.pkgSetting.lastUpdateTime System.currentTimeMillis();res.removedInfo.broadcastAllowList mAppsFilter.getVisibilityAllowList(reconciledPkg.pkgSetting, request.mAllUsers, mSettings.getPackagesLocked());if (reconciledPkg.prepareResult.system) {// Remove existing system packageremovePackageLI(oldPackage, true);if (!disableSystemPackageLPw(oldPackage)) {// We didnt need to disable the .apk as a current system package,// which means we are replacing another update that is already// installed. We need to make sure to delete the older ones .apk.res.removedInfo.args createInstallArgsForExisting(oldPackage.getPath(),getAppDexInstructionSets(AndroidPackageUtils.getPrimaryCpuAbi(oldPackage,deletedPkgSetting),AndroidPackageUtils.getSecondaryCpuAbi(oldPackage,deletedPkgSetting)));} else {res.removedInfo.args null;}} else {try {// Settings will be written during the call to updateSettingsLI().executeDeletePackageLIF(reconciledPkg.deletePackageAction, packageName,true, request.mAllUsers, false, parsedPackage);} catch (SystemDeleteException e) {if (mIsEngBuild) {throw new RuntimeException(Unexpected failure, e);// ignore; not possible for non-system app}}// Successfully deleted the old package; proceed with replace.// If deleted package lived in a container, give users a chance to// relinquish resources before killing.if (oldPackage.isExternalStorage()) {if (DEBUG_INSTALL) {Slog.i(TAG, upgrading pkg oldPackage is ASEC-hosted - UNAVAILABLE);}final int[] uidArray new int[]{oldPackage.getUid()};final ArrayListString pkgList new ArrayList(1);pkgList.add(oldPackage.getPackageName());sendResourcesChangedBroadcast(false, true, pkgList, uidArray, null);}// Update the in-memory copy of the previous code paths.PackageSetting ps1 mSettings.getPackageLPr(reconciledPkg.prepareResult.existingPackage.getPackageName());if ((reconciledPkg.installArgs.installFlags PackageManager.DONT_KILL_APP) 0) {if (ps1.mOldCodePaths null) {ps1.mOldCodePaths new ArraySet();}Collections.addAll(ps1.mOldCodePaths, oldPackage.getBaseApkPath());if (oldPackage.getSplitCodePaths() ! null) {Collections.addAll(ps1.mOldCodePaths, oldPackage.getSplitCodePaths());}} else {ps1.mOldCodePaths null;}if (reconciledPkg.installResult.returnCode PackageManager.INSTALL_SUCCEEDED) {PackageSetting ps2 mSettings.getPackageLPr(parsedPackage.getPackageName());if (ps2 ! null) {res.removedInfo.removedForAllUsers mPackages.get(ps2.name) null;}}}}AndroidPackage pkg commitReconciledScanResultLocked(reconciledPkg, request.mAllUsers);updateSettingsLI(pkg, reconciledPkg.installArgs, request.mAllUsers, res);final PackageSetting ps mSettings.getPackageLPr(packageName);if (ps ! null) {res.newUsers ps.queryInstalledUsers(mUserManager.getUserIds(), true);ps.setUpdateAvailable(false /*updateAvailable*/);}if (res.returnCode PackageManager.INSTALL_SUCCEEDED) {updateSequenceNumberLP(ps, res.newUsers);updateInstantAppInstallerLocked(packageName);}}ApplicationPackageManager.invalidateGetPackagesForUidCache();}CommitRequest对象request的成员reconciledPackages是MapString, ReconciledPackage对象它里面是对应每一个安装应用key值是包名。该方法就是对每一个安装应用循环接着看它的处理。   ScanResult对象scanResult、ScanRequest对象scanRequest是在 Android 安装应用-浏览阶段 中生成的对象。ParsedPackage对象parsedPackage是解析对象包parsedPackage是安装应用的包名PackageInstalledInfo对象res 是对应的应用的安装信息。   reconciledPkg.prepareResult.replace为true代表是需要替换旧包进行更新。   在替换更新的情况下先得到旧的解析包对象。mPackages是WatchedArrayMapString, AndroidPackage它维持着所有的解析包对象key值是包名。在替换之前mPackages中的解析包对象就是旧包对象oldPackage最后它需要被parsedPackage替换掉。deletedPkgSetting则是即将删除的PackageSetting对象reconciledPkg.pkgSetting则是之前Android 安装应用-浏览阶段生成的新的PackageSetting对象下面是更新新生成的PackageSetting对象的首次安装时间和最后更新时间当前时间。res.removedInfo.broadcastAllowList是SparseArrayint[]类型它的key值是用户UserIdvalue则是所有的应用的app Ids。request.mAllUsers在这里是所有的用户UserId数组mAppsFilter.getVisibilityAllowList()得到所有的能看到该安装应用的应用res.removedInfo.broadcastAllowList就是是存放的这些能看到它的应用的app Ids。   如果被替换的包是系统包调用removePackageLI(oldPackage, true)。该方法主要是将包名对应的解析包对象从mPackages中删除然后将旧包的声明的组件删除声明的权限删除所有定义的属性删除定义的instrumentation删除如果是系统包还会将它引用的共享库去除。如果它声明了静态共享库也会将它去除。   如果被替换的包是系统包它接着会检查当前旧包使用的系统预安装的还是后续已经升级过的包。它是通过disableSystemPackageLPw(oldPackage)来判断的如果它为true代表当前旧包使用的系统预安装的包是不能删除的。所以这里将删除信息的参数args null。如果它为false则代表后续已经升级过新的安装包后面需要将它删除。所以创建新的删除参数包括旧包的安装路径和主、副ABI并将它设置为res.removedInfo.args。 如果被替换包不是系统包它会执行executeDeletePackageLIF方法删除应用包。删除应用包见下面分析。   删除包之后继续往下执行如果旧包在外部空间它会发送一个资源改变的广播通知用户们。它还会更新PackageSetting对象的旧包的安装路径。   executeDeletePackageLIF方法上面都是用来清除应用的接下来就是要安装新的应用了。   它是首先调用commitReconciledScanResultLocked(reconciledPkg, request.mAllUsers) 提交修改系统中对应的状态然后调用updateSettingsLI(pkg, reconciledPkg.installArgs, request.mAllUsers, res)用来更新PackageSetting对象的状态。   接下来res.newUsers则是新应用提交并更新PackageSetting对象之后得到的installed状态为true的用户id数组。还会将PackageSetting对象的updateAvailable设置为false。   目前安装成功的话它会调用updateSequenceNumberLP()来更新对应包的更新序号这个更新序列号就是每次更新会加1。调用updateInstantAppInstallerLocked(packageName)来更新用来安装instant应用的Activity。   最后调用ApplicationPackageManager.invalidateGetPackagesForUidCache()是使CACHE_KEY_PACKAGES_FOR_UID_PROPERTY属性缓存无效。这个属性值存储的是对应用户的安装应用包名。   下面先看看删除应用包然后再看提交修改包应用的系统的状态、更新PackageSetting对象的状态。 删除应用包 删除应用包是由executeDeletePackageLIF方法实现的看一下它的代码 /** Deletes a package. Only throws when install of a disabled package fails. */private void executeDeletePackageLIF(DeletePackageAction action,String packageName, boolean deleteCodeAndResources,NonNull int[] allUserHandles, boolean writeSettings,ParsedPackage replacingPackage) throws SystemDeleteException {final PackageSetting ps action.deletingPs;final PackageRemovedInfo outInfo action.outInfo;final UserHandle user action.user;final int flags action.flags;final boolean systemApp isSystemApp(ps);// We need to get the permission state before package state is (potentially) destroyed.final SparseBooleanArray hadSuspendAppsPermission new SparseBooleanArray();for (int userId : allUserHandles) {hadSuspendAppsPermission.put(userId, checkPermission(Manifest.permission.SUSPEND_APPS,packageName, userId) PERMISSION_GRANTED);}final int userId user null ? UserHandle.USER_ALL : user.getIdentifier();if ((!systemApp || (flags PackageManager.DELETE_SYSTEM_APP) ! 0) userId ! UserHandle.USER_ALL) {// The caller is asking that the package only be deleted for a single// user. To do this, we just mark its uninstalled state and delete// its data. If this is a system app, we only allow this to happen if// they have set the special DELETE_SYSTEM_APP which requests different// semantics than normal for uninstalling system apps.final boolean clearPackageStateAndReturn;synchronized (mLock) {markPackageUninstalledForUserLPw(ps, user);if (!systemApp) {// Do not uninstall the APK if an app should be cachedboolean keepUninstalledPackage shouldKeepUninstalledPackageLPr(packageName);if (ps.isAnyInstalled(mUserManager.getUserIds()) || keepUninstalledPackage) {// Other users still have this package installed, so all// we need to do is clear this users data and save that// it is uninstalled.if (DEBUG_REMOVE) Slog.d(TAG, Still installed by other users);clearPackageStateAndReturn true;} else {// We need to set it back to installed so the uninstall// broadcasts will be sent correctly.if (DEBUG_REMOVE) Slog.d(TAG, Not installed by other users, full delete);ps.setInstalled(true, userId);mSettings.writeKernelMappingLPr(ps);clearPackageStateAndReturn false;}} else {// This is a system app, so we assume that the// other users still have this package installed, so all// we need to do is clear this users data and save that// it is uninstalled.if (DEBUG_REMOVE) Slog.d(TAG, Deleting system app);clearPackageStateAndReturn true;}}if (clearPackageStateAndReturn) {clearPackageStateForUserLIF(ps, userId, outInfo, flags);synchronized (mLock) {scheduleWritePackageRestrictionsLocked(user);}return;}}// TODO(b/109941548): break reasons for ret false out into mayDelete methodif (systemApp) {if (DEBUG_REMOVE) Slog.d(TAG, Removing system package: ps.name);// When an updated system application is deleted we delete the existing resources// as well and fall back to existing code in system partitiondeleteSystemPackageLIF(action, ps, allUserHandles, flags, outInfo, writeSettings);} else {if (DEBUG_REMOVE) Slog.d(TAG, Removing non-system package: ps.name);deleteInstalledPackageLIF(ps, deleteCodeAndResources, flags, allUserHandles,outInfo, writeSettings);}// If the package removed had SUSPEND_APPS, unset any restrictions that might have been in// place for all affected users.int[] affectedUserIds (outInfo ! null) ? outInfo.removedUsers : null;if (affectedUserIds null) {affectedUserIds resolveUserIds(userId);}for (final int affectedUserId : affectedUserIds) {if (hadSuspendAppsPermission.get(affectedUserId)) {unsuspendForSuspendingPackage(packageName, affectedUserId);removeAllDistractingPackageRestrictions(affectedUserId);}}// Take a note whether we deleted the package for all usersif (outInfo ! null) {outInfo.removedForAllUsers mPackages.get(ps.name) null;}}DeletePackageAction类型对象action是关于要删除包行为的action.deletingPs就是要删除的PackageSetting对象action.outInfo是删除的信息action.user是用户action.flags是删除标识变量systemApp代表是系统APP。   hadSuspendAppsPermission里面存储每个用户对应的包名packageName的应用是否已经授权过SUSPEND_APPS权限。   action.user是需要删除的应用的用户在我们的例子中这里是null可以参考 Android 应用安装-协调阶段也就是代表所有用户。   接下来这段代码是是处理某个用户删除的情况userId ! UserHandle.USER_ALL还要满足不是系统APP或者设置了删除系统app标识PackageManager.DELETE_SYSTEM_APP。   变量clearPackageStateAndReturn代表清除包的对应的这个单独用户的数据之后就返回不继续向下执行。   markPackageUninstalledForUserLPw(ps, user)用来标记用户的卸载状态PackageSetting对象会维护每个用户的用户状态这个用户状态是用PackageUserState对象来表示的。这里主要将PackageUserState对象的installed状态设置为false。   接着对非系统APP进行处理。   变量keepUninstalledPackage代表保持卸载包。它是由shouldKeepUninstalledPackageLPr(packageName)来决定的而该方法是由成员变量mKeepUninstalledPackages来判断的如果包名在它里面即为true。像这种情况会将变量clearPackageStateAndReturn true。还有一种情况其他用户还有这个包的installed状态即ps.isAnyInstalled(mUserManager.getUserIds())为true上面通过markPackageUninstalledForUserLPw(ps, user)将user的installed设置为false也会clearPackageStateAndReturn true代表需要将该用户的数据清除就返回其他用户的数据是不能清除的。如果上面两个情况不满足调用ps.setInstalled(true, userId)将该用户对应的installed设置为true因为刚才通过markPackageUninstalledForUserLPw(ps, user)将用户对应的installed设置为false并且也判断过ps.isAnyInstalled(mUserManager.getUserIds())了所以在这里是将它的值还原。mSettings.writeKernelMappingLPr(ps)则是处理Settings对象中维持的KernelPackageState对象它包含着应用的appId和installed状态已经是false的用户维持在PackageSetting对象中。最后将clearPackageStateAndReturn false。   接着对系统APP进行处理。直接是将clearPackageStateAndReturn true它是假定其他用户有这个系统应用的installed状态所以只清理该单独用户的。   上面处理之后变量clearPackageStateAndReturn为true代表只需要清理这个userId这个单独用户的数据就行它是由clearPackageStateForUserLIF()实现见下面。   之后调用scheduleWritePackageRestrictionsLocked(user)它首先执行invalidatePackageInfoCache()让一些缓存无效包信息的缓存包含PackageManagerService对象的Computer缓存,接着向PackageManagerService对象的后台ServiceThread发送一个延迟(10s)消息WRITE_PACKAGE_RESTRICTIONS而在ServiceThread中处理该消息时会调用Settings对象的writePackageRestrictionsLPr(userId)方法来处理它和/data/system/users/ userId “/package-restrictions.xml” 及 “/data/system/users/” userId “/package-restrictions-backup.xml两个文件有关后面这个文件是前一个文件的备份。writePackageRestrictionsLPr(userId)方法主要是将用户对应的各个应用包状态、较好的Activity信息、持久较好的Activity信息、intent配置信息、默认的浏览器包名等相关信息写入”/package-restrictions.xml文件。这些处理完毕就直接return不再继续向下执行。   再接下来如果clearPackageStateAndReturn为false或者参数user null的情况下它会继续向下执行代码还是分系统APP还是非系统APP的情况。   系统APP会执行deleteSystemPackageLIF(action, ps, allUserHandles, flags, outInfo, writeSettings)非系统APP会执行deleteInstalledPackageLIF(ps, deleteCodeAndResources, flags, allUserHandles, outInfo, writeSettings)。这俩方法的区别是删除系统应用包时它会继续使用系统分区中的安装包所以在它删除了更新包之后会执行安装系统分区中的安装包。deleteInstalledPackageLIF(ps, deleteCodeAndResources, flags, allUserHandles, outInfo, writeSettings)的实现见下面。   接下来executeDeletePackageLIF方法会继续检查被删除应用如果被授予Manifest.permission.SUSPEND_APPS权限这里会去除它对别的应用暂停的影响。   这样executeDeletePackageLIF方法就看完了。   下面看下clearPackageStateForUserLIF(ps, userId, outInfo, flags)它是用来清理userId的数据。看下实现的代码 删除包对应用户的数据 private void clearPackageStateForUserLIF(PackageSetting ps, int userId,PackageRemovedInfo outInfo, int flags) {final AndroidPackage pkg;synchronized (mLock) {pkg mPackages.get(ps.name);}destroyAppProfilesLIF(pkg);final SharedUserSetting sus ps.getSharedUser();ListAndroidPackage sharedUserPkgs sus ! null ? sus.getPackages() : null;if (sharedUserPkgs null) {sharedUserPkgs Collections.emptyList();}final int[] userIds (userId UserHandle.USER_ALL) ? mUserManager.getUserIds(): new int[] {userId};for (int nextUserId : userIds) {if (DEBUG_REMOVE) {Slog.d(TAG, Updating package: ps.name install state for user: nextUserId);}if ((flags PackageManager.DELETE_KEEP_DATA) 0) {destroyAppDataLIF(pkg, nextUserId,FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL);}removeKeystoreDataIfNeeded(mInjector.getUserManagerInternal(), nextUserId, ps.appId);clearPackagePreferredActivities(ps.name, nextUserId);mDomainVerificationManager.clearPackageForUser(ps.name, nextUserId);}mPermissionManager.onPackageUninstalled(ps.name, ps.appId, pkg, sharedUserPkgs, userId);if (outInfo ! null) {if ((flags PackageManager.DELETE_KEEP_DATA) 0) {outInfo.dataRemoved true;}outInfo.removedPackage ps.name;outInfo.installerPackageName ps.installSource.installerPackageName;outInfo.isStaticSharedLib pkg ! null pkg.getStaticSharedLibName() ! null;outInfo.removedAppId ps.appId;outInfo.removedUsers userIds;outInfo.broadcastUsers userIds;}}在这里得到mPackages中对应的包名的安装包信息。   接着调用destroyAppProfilesLIF(pkg)将包对应的配置文件删除。因为它要与installd 进程通信实现在InstalldNativeService.cpp中的destroyAppProfiles(const std::string packageName)中跳转代码太多直接说实现的内容了对/data/user/“目录下面的用户遍历userid删除 “/data/misc/profiles/cur/” userid “/” package_name 目录及其里面的文件如果没在”/data/user/“目录下面找到userid就只找寻userid为0的用户也就是删除”/data/misc/profiles/cur/0/ package_name 目录及其中的文件接着删除/data/misc/profiles/ref/ package_name 目录及其里面的文件。   接着向下如果userId UserHandle.USER_ALL即-1代表所有用户所以取出来所有用户id如果是单个用户id则将单个用户放在数组中赋值给数组userIds。   遍历用户数组userIds开始   遍历用户数组userIds如果标识没有PackageManager.DELETE_KEEP_DATA会调用destroyAppDataLIF方法它是清除所有的APP数据。它根据标识做了以下三件事   1、如果设置了FLAG_STORAGE_CE标识它会清除用户的包数据。用户的数据存放位置和存储卷UUID、包名、用户ID有关的。如果存储卷UUID为null则代表内部存储那它的根目录为/data如果不为null根目录为/mnt/expand/ volume_uuid。如果特定用户userid则路径为 根目录 “/user/” userid “/” 包名。还有一种常见情况为内部存储用户userid为0如果 “/data/data存在并且是目录则路径为”/data/data/ 包名。所以这里会将这个用户目录包括其中的数据都清除掉。   2、如果设置了FLAG_STORAGE_DE标识它会清除用户的设备加密的数据。它的路径文件路径和上面有些像不过它的路径中的/user/“换成了”/user_de/“。即为根目录 “/user_de/” userid “/” 包名。还以内部存储用户userid为例则它的路径为”/data/user_de/0/ 包名。这里会将该目录及里面文件都删除掉。如果标识没有设置FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES它还会删除应用和用户对应的配置文件这和前面destroyAppProfilesLIF(pkg)不一样的是它是删除某个用户id的。   3、如果设置了FLAG_STORAGE_EXTERNAL标识它需要清除外部存储上该应用的存储数据。外部存储空间和用户相关的路径目录有哪些呢它也是和用户id和包名相关。外部空间根目录是从/proc/mounts中读取出来的外部空间根目录 “/” userId即是和用户相关的目录暂称外部空间用户根目录extUserDir。具体删除的路径有以下几个extUserDir “/Android/data/” 包名、extUserDir “/Android/media/” 包名、extUserDir “/Android/obb/” 包名。   继续看clearPackageStateForUserLIF方法中的执行方法调用removeKeystoreDataIfNeeded方法它是在APP卸载时通知Keystore 2.0并且对应的命名空间被删除。   接着是调用clearPackagePreferredActivities(ps.name, nextUserId)清除这个nextUserId用户包名等于ps.name的较好的Activity。它们是维护在Settings对象中的成员变量mPreferredActivities中。所以这块就是把符合要求的对应用户的Activity从它里面去除。如果确实有需要删除的对应用户的Activity它接下来会调用updateDefaultHomeNotLocked(changedUsers)来更新对应用户默认的Home默认的Home的包名是PackageManagerService对象的成员变量DefaultAppProvider mDefaultAppProvider维持的如果mDefaultAppProvider维持的Home包名和查询得到的nextUserId的当前较好的Activity不同会更新Home包名并且发送nextUserId用户Intent.ACTION_PREFERRED_ACTIVITY_CHANGED广播。   如果确实有需要删除的对应用户的ActivityclearPackagePreferredActivities(ps.name, nextUserId)还会执行scheduleWritePackageRestrictionsLocked(userId)方法它首先执行invalidatePackageInfoCache()让一些缓存无效包信息的缓存包含PackageManagerService对象的Computer缓存。接着向PackageManagerService对象的后台ServiceThread发送一个延迟(10s)消息WRITE_PACKAGE_RESTRICTIONS而在ServiceThread中处理该消息时会调用Settings对象的writePackageRestrictionsLPr(userId)方法来处理它和/data/system/users/ userId “/package-restrictions.xml” 及 “/data/system/users/” userId “/package-restrictions-backup.xml两个文件有关后面这个文件是前一个文件的备份。writePackageRestrictionsLPr(userId)方法主要是将用户对应的各个应用包状态、较好的Activity信息、持久较好的Activity信息、intent配置信息、默认的浏览器包名等相关信息写入”/package-restrictions.xml文件。   回到clearPackageStateForUserLIF方法中还是在循环遍历中它接着执行mDomainVerificationManager.clearPackageForUser(ps.name, nextUserId)。mDomainVerificationManager在这里是DomainVerificationService对象在这里它是用来清除对应应用和对应用户的域名验证状态。   遍历用户数组userIds结束   上面是遍历用户的循环看完了下面是调用mPermissionManager.onPackageUninstalled(ps.name, ps.appId, pkg, sharedUserPkgs, userId)。mPermissionManager实际是PermissionManagerServiceInternalImpl对象这块是包要卸载了需要对相应权限进行处理。   下面outInfo对象则是对清理状况的一种描述信息。包括删除的包名删除包名的安装应用数据是否删除是否调用了destroyAppDataLIF方法、是否是静态库、去除了哪个用户的包信息。 删除安装包 它是由deleteInstalledPackageLIF()实现的看下它实现的代码 private void deleteInstalledPackageLIF(PackageSetting ps,boolean deleteCodeAndResources, int flags, NonNull int[] allUserHandles,PackageRemovedInfo outInfo, boolean writeSettings) {synchronized (mLock) {if (outInfo ! null) {outInfo.uid ps.appId;outInfo.broadcastAllowList mAppsFilter.getVisibilityAllowList(ps,allUserHandles, mSettings.getPackagesLocked());}}// Delete package data from internal structures and also remove data if flag is setremovePackageDataLIF(ps, allUserHandles, outInfo, flags, writeSettings);// Delete application code and resources only for parent packagesif (deleteCodeAndResources (outInfo ! null)) {outInfo.args createInstallArgsForExisting(ps.getPathString(), getAppDexInstructionSets(ps.primaryCpuAbiString, ps.secondaryCpuAbiString));if (DEBUG_SD_INSTALL) Slog.i(TAG, args outInfo.args);}}deleteInstalledPackageLIF()方法会给PackageRemovedInfo对象outInfo中的相关字段赋值主要就是调用removePackageDataLIF(ps, allUserHandles, outInfo, flags, writeSettings)方法。如果参数deleteCodeAndResources为true代表需要删除代码和资源包。所以构造outInfo.args对象它是FileInstallArgs对象包含安装包路径和指令集。   removePackageDataLIF()会做如下工作会给PackageRemovedInfo对象outInfo中的相关字段赋值包括removedUsers。接着会调用removePackageLI()方法它会去除包相关的数据。如果参数标识flags没有PackageManager.DELETE_KEEP_DATA它还会调用destroyAppDataLIF()见上面、destroyAppProfilesLIF(),见上面来删除对应应用包的相关文件。   如果参数标识flags没有PackageManager.DELETE_KEEP_DATA它还会用来清除对应应用的域名验证状态应用的keySet它还会调用mSettings.removePackageLPw(packageName)清除成员变量mSettings中的PackageSetting对象并将与其相关的内容一并清除。如果不是系统包它也会调用mPermissionManager.onPackageUninstalled(packageName, deletedPs.appId, deletedPs.pkg, sharedUserPkgs, UserHandle.USER_ALL)把它的权限状态给去除。接着会调用clearPackagePreferredActivitiesLPw(deletedPs.name, changedUsers, UserHandle.USER_ALL)清除这个nextUserId用户包名等于ps.name的较好的Activity。它们是维护在Settings对象中的成员变量mPreferredActivities中。所以这块就是把符合要求的Activity从它里面去除。如果在清除了用户的较好的Activity时那接着就需要更新这个用户的默认home。然后发送较好Activity发生变化的广播(Intent.ACTION_PREFERRED_ACTIVITY_CHANGED)。   removePackageDataLIF()还会根据boolean型参数writeSettings是否保存Settings类型对象中的状态。还会从密钥库删除对应应用的密钥。 提交修改包应用的系统的状态 commitReconciledScanResultLocked(reconciledPkg, request.mAllUsers)的代码如下 /*** Commits the package scan and modifies system state.* pemWARNING:/em The method may throw an excpetion in the middle* of committing the package, leaving the system in an inconsistent state.* This needs to be fixed so, once we get to this point, no errors are* possible and the system is not left in an inconsistent state.*/GuardedBy({mLock, mInstallLock})private AndroidPackage commitReconciledScanResultLocked(NonNull ReconciledPackage reconciledPkg, int[] allUsers) {final ScanResult result reconciledPkg.scanResult;final ScanRequest request result.request;// TODO(b/135203078): Move this even further awayParsedPackage parsedPackage request.parsedPackage;if (android.equals(parsedPackage.getPackageName())) {// TODO(b/135203078): Move this to initial parseparsedPackage.setVersionCode(mSdkVersion).setVersionCodeMajor(0);}final AndroidPackage 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 UserHandle user request.user;final String realPkgName request.realPkgName;final ListString changedAbiCodePath result.changedAbiCodePath;final PackageSetting pkgSetting;if (request.pkgSetting ! null request.pkgSetting.sharedUser ! null request.pkgSetting.sharedUser ! result.pkgSetting.sharedUser) {// shared user changed, remove from old shared userrequest.pkgSetting.sharedUser.removePackage(request.pkgSetting);}if (result.existingSettingCopied) {pkgSetting request.pkgSetting;pkgSetting.updateFrom(result.pkgSetting);} else {pkgSetting result.pkgSetting;if (originalPkgSetting ! null) {mSettings.addRenamedPackageLPw(parsedPackage.getRealPackage(),originalPkgSetting.name);mTransferredPackages.add(originalPkgSetting.name);} else {mSettings.removeRenamedPackageLPw(parsedPackage.getPackageName());}}if (pkgSetting.sharedUser ! null) {pkgSetting.sharedUser.addPackage(pkgSetting);}if (reconciledPkg.installArgs ! null reconciledPkg.installArgs.forceQueryableOverride) {pkgSetting.forceQueryableOverride true;}// If this is part of a standard install, set the initiating package name, else rely on// previous device state.if (reconciledPkg.installArgs ! null) {InstallSource installSource reconciledPkg.installArgs.installSource;if (installSource.initiatingPackageName ! null) {final PackageSetting ips mSettings.getPackageLPr(installSource.initiatingPackageName);if (ips ! null) {installSource installSource.setInitiatingPackageSignatures(ips.signatures);}}pkgSetting.setInstallSource(installSource);}// TODO(toddke): Consider a method specifically for modifying the Package object// post scan; or, moving this stuff out of the Package object since it has nothing// to do with the package on disk.// We need to have this here because addUserToSettingLPw() is sometimes responsible// for creating the application ID. If we did this earlier, we would be saving the// correct ID.parsedPackage.setUid(pkgSetting.appId);final AndroidPackage pkg parsedPackage.hideAsFinal();mSettings.writeUserRestrictionsLPw(pkgSetting, oldPkgSetting);if (realPkgName ! null) {mTransferredPackages.add(pkg.getPackageName());}if (reconciledPkg.collectedSharedLibraryInfos ! null) {executeSharedLibrariesUpdateLPr(pkg, pkgSetting, null, null,reconciledPkg.collectedSharedLibraryInfos, allUsers);}final KeySetManagerService ksms mSettings.getKeySetManagerService();if (reconciledPkg.removeAppKeySetData) {ksms.removeAppKeySetDataLPw(pkg.getPackageName());}if (reconciledPkg.sharedUserSignaturesChanged) {pkgSetting.sharedUser.signaturesChanged Boolean.TRUE;pkgSetting.sharedUser.signatures.mSigningDetails reconciledPkg.signingDetails;}pkgSetting.signatures.mSigningDetails reconciledPkg.signingDetails;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) {}}}final int userId user null ? 0 : user.getIdentifier();// Modify state for the given package settingcommitPackageSettings(pkg, oldPkg, pkgSetting, oldPkgSetting, scanFlags,(parseFlags ParsingPackageUtils.PARSE_CHATTY) ! 0 /*chatty*/, reconciledPkg);if (pkgSetting.getInstantApp(userId)) {mInstantAppRegistry.addInstantAppLPw(userId, pkgSetting.appId);}pkgSetting.setStatesOnCommit();return pkg;}所需要的数据都封装在参数reconciledPkg对象中ScanResult对象、ScanRequest对象都是前面文章 Android 安装应用-浏览阶段 中生成的现在通过reconciledPkg对象取出来。其中parsedPackage是解析出来的包对象oldPkgSetting是包的旧设置信息对象。originalPkgSetting是原来的包设置对象realPkgName是包的真名字这俩变量是和改包名相关的如果没有改包名这俩变量为null如果originalPkgSetting不为null代表是首次安装更改包名的应用。changedAbiCodePath是包共享应用中改变了abi的应用的路径。   接着如果包共享用户发生了变化需要从原来的共享应用包中去除之前的应用。   如果result.existingSettingCopied为true则result.pkgSetting是通过深copy request.pkgSetting创建的对象并且它里面的值有些可能发生了变化所以这里通过updateFrom方法来更新它的值。如果result.existingSettingCopied为false则result.pkgSetting是通过new新创建的对象这里直接将result.pkgSetting赋值给变量pkgSetting。接着如果originalPkgSetting ! null代表包名进行了更改所以这里通过mSettings.addRenamedPackageLPw(parsedPackage.getRealPackage(), originalPkgSetting.name)将现在的包名和之前的旧包名建立对应关系是通过mSettings的成员mRenamedPackages实现还会将旧包名放入变量mTransferredPackages中代表它的包名发生了变更。如果originalPkgSetting为null代表没有变更所以这里将包名从mSettings的成员mRenamedPackages中去除。   如果应用是共享用户这里会将包设置对象添加到共享用户中。   如果安装参数中forceQueryableOverride为true这里会将包设置对象属性forceQueryableOverride设置为true。   接着设置包设置对象的安装源信息。这里是处理了一下安装者应用的签名信息。   再接下来给解析包对象设置应用UId。   在这里会调用解析包对象parsedPackage的hideAsFinal()方法这里parsedPackage实际是PackageImpl对象   接着调用mSettings.writeUserRestrictionsLPw(pkgSetting, oldPkgSetting) 它是用来持久化应用的一些状态的不过在这里普通的应用安装应该不会去更新因为现在包已经从mSettings中去除了还没有加入其中。   接着如果realPkgName不为null将包名加入mTransferredPackages中。前面的文章 Android 安装应用-浏览阶段如果realPkgName不为null则pkg.getPackageName()为旧包名这里将它加入mTransferredPackages中代表它有新包名。   如果reconciledPkg.collectedSharedLibraryInfos ! null代表应用声明了库更新信息所以这里执行库的更新。   reconciledPkg.removeAppKeySetData为true代表需要更新应用的签名key。所以这里先将它们删除后续再更新新的签名key。   reconciledPkg.sharedUserSignaturesChanged为true代表共享用户的签名发生了变化这里更新对应的包设置对象的共享用户签名。   还会更新包设置对象的签名。   changedAbiCodePath.size() 0代表共享用户中有些用的ABI发生了变化这里会将对应的dex文件删除。   接着会根据变量user的值来设置局部变量userId的值如果为null将userId设置为0也即System用户。   解下来就是调用commitPackageSettings()方法来修改对应包的状态了详细见下面。   如果应用是InstantApp则会将应用的安装信息添加到mInstantAppRegistry中。   最后调用包设置对象的setStatesOnCommit()方法提交这个包的安装状态。最后将解析包对象返回。 修改对应包的状态 看一下commitPackageSettings()方法的实现 /*** Adds a scanned package to the system. When this method is finished, the package will* be available for query, resolution, etc...*/private void commitPackageSettings(NonNull AndroidPackage pkg, Nullable AndroidPackage oldPkg,NonNull PackageSetting pkgSetting, Nullable PackageSetting oldPkgSetting,final ScanFlags int scanFlags, boolean chatty, ReconciledPackage reconciledPkg) {final String pkgName pkg.getPackageName();if (mCustomResolverComponentName ! null mCustomResolverComponentName.getPackageName().equals(pkg.getPackageName())) {setUpCustomResolverActivity(pkg, pkgSetting);}if (pkg.getPackageName().equals(android)) {synchronized (mLock) {// Set up information for our fall-back user intent resolution activity.mPlatformPackage pkg;// The instance stored in PackageManagerService is special cased to be non-user// specific, so initialize all the needed fields here.mAndroidApplication pkg.toAppInfoWithoutState();mAndroidApplication.flags PackageInfoUtils.appInfoFlags(pkg, pkgSetting);mAndroidApplication.privateFlags PackageInfoUtils.appInfoPrivateFlags(pkg, pkgSetting);mAndroidApplication.initForUser(UserHandle.USER_SYSTEM);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);}onChanged();}}ArrayListAndroidPackage clientLibPkgs null;// writersynchronized (mLock) {if (!ArrayUtils.isEmpty(reconciledPkg.allowedSharedLibraryInfos)) {for (SharedLibraryInfo info : reconciledPkg.allowedSharedLibraryInfos) {commitSharedLibraryInfoLocked(info);}final MapString, AndroidPackage combinedSigningDetails reconciledPkg.getCombinedAvailablePackages();try {// Shared libraries for the package need to be updated.updateSharedLibrariesLocked(pkg, pkgSetting, null, null,combinedSigningDetails);} catch (PackageManagerException e) {Slog.e(TAG, updateSharedLibrariesLPr failed: , e);}// Update all applications that use this library. Skip when booting// since this will be done after all packages are scaned.if ((scanFlags SCAN_BOOTING) 0) {clientLibPkgs updateAllSharedLibrariesLocked(pkg, pkgSetting,combinedSigningDetails);}}}if (reconciledPkg.installResult ! null) {reconciledPkg.installResult.libraryConsumers clientLibPkgs;}if ((scanFlags SCAN_BOOTING) ! 0) {// No apps can run during boot scan, so they dont need to be frozen} else if ((scanFlags SCAN_DONT_KILL_APP) ! 0) {// Caller asked to not kill app, so its probably not frozen} else if ((scanFlags SCAN_IGNORE_FROZEN) ! 0) {// Caller asked us to ignore frozen check for some reason; they// probably didnt know the package name} else {// Were doing major surgery on this package, so it better be frozen// right now to keep it from launchingcheckPackageFrozen(pkgName);}// Also need to kill any apps that are dependent on the library.if (clientLibPkgs ! null) {for (int i0; iclientLibPkgs.size(); i) {AndroidPackage clientPkg clientLibPkgs.get(i);killApplication(clientPkg.getPackageName(),clientPkg.getUid(), update lib);}}// writerTrace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, updateSettings);synchronized (mLock) {// We dont expect installation to fail beyond this point// Add the new setting to mSettingsmSettings.insertPackageSettingLPw(pkgSetting, pkg);// Add the new setting to mPackagesmPackages.put(pkg.getPackageName(), pkg);if ((scanFlags SCAN_AS_APK_IN_APEX) ! 0) {mApexManager.registerApkInApex(pkg);}// Add the packages KeySets to the global KeySetManagerServiceKeySetManagerService ksms mSettings.getKeySetManagerService();ksms.addScannedPackageLPw(pkg);mComponentResolver.addAllComponents(pkg, chatty);final boolean isReplace reconciledPkg.prepareResult ! null reconciledPkg.prepareResult.replace;mAppsFilter.addPackage(pkgSetting, isReplace);mPackageProperty.addAllProperties(pkg);if (oldPkgSetting null || oldPkgSetting.getPkg() null) {mDomainVerificationManager.addPackage(pkgSetting);} else {mDomainVerificationManager.migrateState(oldPkgSetting, pkgSetting);}int collectionSize ArrayUtils.size(pkg.getInstrumentations());StringBuilder r null;int i;for (i 0; i collectionSize; i) {ParsedInstrumentation a pkg.getInstrumentations().get(i);a.setPackageName(pkg.getPackageName());mInstrumentation.put(a.getComponentName(), a);if (chatty) {if (r null) {r new StringBuilder(256);} else {r.append( );}r.append(a.getName());}}if (r ! null) {if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, Instrumentation: r);}final ListString protectedBroadcasts pkg.getProtectedBroadcasts();if (!protectedBroadcasts.isEmpty()) {synchronized (mProtectedBroadcasts) {mProtectedBroadcasts.addAll(protectedBroadcasts);}}mPermissionManager.onPackageAdded(pkg, (scanFlags SCAN_AS_INSTANT_APP) ! 0, oldPkg);}Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);}前面这两段代码主要是处理mResolveActivity、mResolveInfo成员变量的。可见平台的包名应用是android并且会将mPlatformPackage指向应用包对象。   我们主要看下面的代码它是处理共享库的代码。   reconciledPkg.allowedSharedLibraryInfos是应用声明的库。它不为空的情况下遍历它调用commitSharedLibraryInfoLocked(info)是将库信息加入成员mSharedLibraries中如果是静态库还会加入成员mStaticLibsByDeclaringPackage中。   接着调用updateSharedLibrariesLocked(pkg, pkgSetting, null, null, combinedSigningDetails) 会将它使用的类库添加到它声明的库中。   接着如果不是系统启动中的情况它会调用updateAllSharedLibrariesLocked(pkg, pkgSetting, combinedSigningDetails)更新所有使用该库的应用。并且返回值clientLibPkgs为所有使用该类库的应用包。   下面还会将clientLibPkgs赋值给reconciledPkg.installResult.libraryConsumers。   接着在系统启动中或scanFlags有SCAN_DONT_KILL_APP或SCAN_IGNORE_FROZEN标签的情况下不检查应用的冻结状态其他情况需要调用checkPackageFrozen(pkgName)来检查。   接下来如果存在使用更新库的应用需要将这些应用杀掉。它调用的是killApplication(clientPkg.getPackageName(), clientPkg.getUid(), “update lib”)方法。   接下来就是调用mSettings.insertPackageSettingLPw(pkgSetting, pkg)将包设置对象pkgSetting加入mSettings中。它还会处理如果pkgSetting中的签名信息不在需要从pkg.getSigningDetails()取得赋值到pkgSetting中的签名信息。最主要的是将pkgSetting对象添加到mSettings中的成员变量mPackages中它是WatchedArrayMapString, PackageSetting类型key是包名value是PackageSetting对象。如果是共享用户在这里会将PackageSetting对象添加到共享SharedUserSetting对象中。   调用mPackages.put(pkg.getPackageName(), pkg)将包解析对象加入mPackages中。   下面就是将包的KeySet添加到KeySetManagerService对象中。它调用的是ksms.addScannedPackageLPw(pkg)方法。   再下面就是调用mComponentResolver.addAllComponents(pkg, chatty)添加包应用的组件信息包含Activity、BroadCastReceiver、Service、Provider。   mAppsFilter.addPackage(pkgSetting, isReplace)是用来处理APP之间可见性的。   mPackageProperty.addAllProperties(pkg)添加包定义的所有属性值。   接下来是处理包名配置的域名验证。它主要是处理配置的Action为Intent.ACTION_VIEW、Category为Intent.CATEGORY_BROWSABLE的Activity其中的域名验证。   下面是将包声明的Instrumentation添加到成员mInstrumentation中。   将包中的受保护的广播添加到成员mProtectedBroadcasts中。   最后调用mPermissionManager.onPackageAdded(pkg, (scanFlags SCAN_AS_INSTANT_APP) ! 0, oldPkg)通知应用权限的添加。 更新PackageSetting对象的状态 updateSettingsInternalLI()方法是用来更新PackageSetting对象的相关数据的接下来看看updateSettingsInternalLI()方法 private void updateSettingsInternalLI(AndroidPackage pkg, InstallArgs installArgs,int[] allUsers, PackageInstalledInfo res) {Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, updateSettings);final String pkgName pkg.getPackageName();final int[] installedForUsers res.origUsers;final int installReason installArgs.installReason;InstallSource installSource installArgs.installSource;final String installerPackageName installSource.installerPackageName;if (DEBUG_INSTALL) Slog.d(TAG, New package installed in pkg.getPath());synchronized (mLock) {// For system-bundled packages, we assume that installing an upgraded version// of the package implies that the user actually wants to run that new code,// so we enable the package.final PackageSetting ps mSettings.getPackageLPr(pkgName);final int userId installArgs.user.getIdentifier();if (ps ! null) {if (pkg.isSystem()) {if (DEBUG_INSTALL) {Slog.d(TAG, Implicitly enabling system package on upgrade: pkgName);}// Enable system package for requested usersif (res.origUsers ! null) {for (int origUserId : res.origUsers) {if (userId UserHandle.USER_ALL || userId origUserId) {ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT,origUserId, installerPackageName);}}}// Also convey the prior install/uninstall stateif (allUsers ! null installedForUsers ! null) {for (int currentUserId : allUsers) {final boolean installed ArrayUtils.contains(installedForUsers, currentUserId);if (DEBUG_INSTALL) {Slog.d(TAG, user currentUserId installed);}ps.setInstalled(installed, currentUserId);}// these install state changes will be persisted in the// upcoming call to mSettings.writeLPr().}if (allUsers ! null) {for (int currentUserId : allUsers) {ps.resetOverrideComponentLabelIcon(currentUserId);}}}// Retrieve the overlays for shared libraries of the package.if (!ps.getPkgState().getUsesLibraryInfos().isEmpty()) {for (SharedLibraryInfo sharedLib : ps.getPkgState().getUsesLibraryInfos()) {for (int currentUserId : UserManagerService.getInstance().getUserIds()) {if (!sharedLib.isDynamic()) {// TODO(146804378): Support overlaying static shared librariescontinue;}final PackageSetting libPs mSettings.getPackageLPr(sharedLib.getPackageName());if (libPs null) {continue;}ps.setOverlayPathsForLibrary(sharedLib.getName(),libPs.getOverlayPaths(currentUserId), currentUserId);}}}// Its implied that when a user requests installation, they want the app to be// installed and enabled. (This does not apply to USER_ALL, which here means only// install on users for which the app is already installed).if (userId ! UserHandle.USER_ALL) {ps.setInstalled(true, userId);ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userId, installerPackageName);}mSettings.addInstallerPackageNames(ps.installSource);// When replacing an existing package, preserve the original install reason for all// users that had the package installed before. Similarly for uninstall reasons.final SetInteger previousUserIds new ArraySet();if (res.removedInfo ! null res.removedInfo.installReasons ! null) {final int installReasonCount res.removedInfo.installReasons.size();for (int i 0; i installReasonCount; i) {final int previousUserId res.removedInfo.installReasons.keyAt(i);final int previousInstallReason res.removedInfo.installReasons.valueAt(i);ps.setInstallReason(previousInstallReason, previousUserId);previousUserIds.add(previousUserId);}}if (res.removedInfo ! null res.removedInfo.uninstallReasons ! null) {for (int i 0; i res.removedInfo.uninstallReasons.size(); i) {final int previousUserId res.removedInfo.uninstallReasons.keyAt(i);final int previousReason res.removedInfo.uninstallReasons.valueAt(i);ps.setUninstallReason(previousReason, previousUserId);}}// Set install reason for users that are having the package newly installed.final int[] allUsersList mUserManager.getUserIds();if (userId UserHandle.USER_ALL) {// TODO(b/152629990): It appears that the package doesnt actually get newly// installed in this case, so the installReason shouldnt get modified?for (int currentUserId : allUsersList) {if (!previousUserIds.contains(currentUserId)) {ps.setInstallReason(installReason, currentUserId);}}} else if (!previousUserIds.contains(userId)) {ps.setInstallReason(installReason, userId);}// TODO(b/169721400): generalize Incremental States and create a Callback object// that can be used for all the packages.final String codePath ps.getPathString();if (IncrementalManager.isIncrementalPath(codePath) mIncrementalManager ! null) {final IncrementalStatesCallback incrementalStatesCallback new IncrementalStatesCallback(ps.name,UserHandle.getUid(userId, ps.appId),getInstalledUsers(ps, userId));ps.setIncrementalStatesCallback(incrementalStatesCallback);mIncrementalManager.registerLoadingProgressCallback(codePath,new IncrementalProgressListener(ps.name));}// Ensure that the uninstall reason is UNKNOWN for users with the package installed.for (int currentUserId : allUsersList) {if (ps.getInstalled(currentUserId)) {ps.setUninstallReason(UNINSTALL_REASON_UNKNOWN, currentUserId);}}mSettings.writeKernelMappingLPr(ps);final PermissionManagerServiceInternal.PackageInstalledParams.BuilderpermissionParamsBuilder new PermissionManagerServiceInternal.PackageInstalledParams.Builder();final boolean grantPermissions (installArgs.installFlags PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) ! 0;if (grantPermissions) {final ListString grantedPermissions installArgs.installGrantPermissions ! null? Arrays.asList(installArgs.installGrantPermissions): pkg.getRequestedPermissions();permissionParamsBuilder.setGrantedPermissions(grantedPermissions);}final boolean allowlistAllRestrictedPermissions (installArgs.installFlags PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) ! 0;final ListString allowlistedRestrictedPermissions allowlistAllRestrictedPermissions ? pkg.getRequestedPermissions(): installArgs.whitelistedRestrictedPermissions;if (allowlistedRestrictedPermissions ! null) {permissionParamsBuilder.setAllowlistedRestrictedPermissions(allowlistedRestrictedPermissions);}final int autoRevokePermissionsMode installArgs.autoRevokePermissionsMode;permissionParamsBuilder.setAutoRevokePermissionsMode(autoRevokePermissionsMode);mPermissionManager.onPackageInstalled(pkg, permissionParamsBuilder.build(), userId);}res.name pkgName;res.uid pkg.getUid();res.pkg pkg;res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);//to update install statusTrace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, writeSettings);writeSettingsLPrTEMP();Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);}Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);}res.origUsers是在 Android 安装应用-准备阶段 赋值的它是PackageSetting对象中 installe状态为true的用户这里赋值给installedForUsers变量。   局部变量userId是安装参数中的用户id。   从mSettings中取得PackageSetting对象ps。   如果安装包pkg是系统安装包会设定原来的installe状态为true的用户的enabled状态为COMPONENT_ENABLED_STATE_DEFAULT。还会把原来的installe状态为true的用户的installe状态继续为true其他的用户设置为false。还会调用PackageSetting对象的resetOverrideComponentLabelIcon(currentUserId)重设组件的label和icon。   如果ps.getPkgState().getUsesLibraryInfos()不为null并且它的库位动态的则会调用ps.setOverlayPathsForLibrary(sharedLib.getName(), libPs.getOverlayPaths(currentUserId), currentUserId)将动态库的遮罩路径设置到它里面   如果安装用户是一个固定用户不是指所有用户则将它的installe状态为trueenabled状态为COMPONENT_ENABLED_STATE_DEFAULT。   ps.installSource是和安装源相关的对象这里调用mSettings.addInstallerPackageNames(ps.installSource)将安装者包名添加到mSettings中。   接着就是处理用户的安装原因、卸载原因。可以看到它先恢复之前的安装原因、卸载原因。对于那些installe状态为true的用户则设置它的卸载原因为UNINSTALL_REASON_UNKNOWN。   下面是处理权限相关的。后面通过mPermissionManager.onPackageInstalled(pkg, permissionParamsBuilder.build(), userId)通知应用包安装了。   最后设置res的name、uid、解析包对象。ReturnCode是安装结果。PackageSetting对象更新了之后调用writeSettingsLPrTEMP()来持久化相应的状态。 总结 在安装过程中有两个类AndroidPackage和PackageSettingAndroidPackage类对象实际是PackageImpl对象它是通过解析应用安装包得到的包含安装包的所有配置对应Manifest配置文件中的内容。PackageSetting对象则是包数据设置对象主要是后续设置的一些状态像应用对每个用户的状态例安装、停止状态主要、次要CPU ABI另外PackageSetting对象的成员pkg是指向PackageImpl对象的。   PackageManagerService对象中成员mPackages是WatchedArrayMapString, AndroidPackage它的key是包名value则是AndroidPackage对象安装成功之后PackageImpl对象是要添加到mPackages中的。   PackageManagerService对象中成员mSettings是Settings类。Settings类有成员变量mPackages它是WatchedArrayMapString, PackageSetting它的key是包名value则是PackageSetting对象安装成功之后PackageSetting对象是要添加到Settings类的成员变量mPackages中的。   这两个类对象的处理可以从文章中找到。   当然安装中还会将各大组件添加到系统中这个和PackageManagerService对象中成员mComponentResolver相关后续查找组件也会通过该成员变量。   其实挺复杂的是权限的处理这个等待后面再整理该篇文章也是疏通了流程精细的地方还待仔细琢磨。
http://www.hkea.cn/news/14594523/

相关文章:

  • 卫浴响应式外贸网站建设旅游网站建设合同
  • iis部署网站提示建设中门票预订网站建设
  • 工信部信息备案网站查询未来做哪些网站能致富
  • 手机网站 收录wordpress 数据库搜索功能
  • 网络营销网站建设ppt黄骅市邮编
  • 整个网站都在下雪特效怎么做手机端h5网站模板下载
  • 网站办公室比较厉害的网站制作公司
  • 地方网站优势邯郸网站制作哪里做
  • 网站推广策划方案书手机网站模板 源码
  • 套模板建设网站多少钱徐州网络推广公司排名
  • 网站伪静态怎么做公司做网站需准备资料
  • php能区别电脑网站和手机网站吗怎么嵌入到phpcms深圳招聘网站前十排名
  • 网站建设的常见技术有哪些知名网站建设推荐
  • 用什么软件做楼盘微网站厦门微信商城网站建设
  • 智能做网站西宁做网站哪家公司好
  • 网站建设 ppt网站建设维护网页设计
  • 国内网站做得好的公司做网站一般做几个尺寸
  • 哪个平台做网站好天津建设工程信息网招标文件澄清
  • 营销型网站价格实惠wordpress商城购物表单
  • 做网站大概要花多少钱房屋租赁网站建设如何给客户定位
  • 做统计的网站吗网站开发 外包 哪家
  • 广州市公司网站建设品牌免费的网络电视app
  • 南宁网站建站公司ps如何做网页
  • 怎样制作网站后台建站程序的价钱
  • 网站开发多语言切换思路公司内部管理软件叫什么
  • 个人的网站怎么备案在上海做钟点工的网站
  • 建站软件免费试用wordpress 不能选择数据库
  • 网站模板flash网站备案 种类
  • 网站建设企业资质蔬菜水果网站建设
  • 网站建设的需求目前网站开发怎么兼顾手机