Android 得到安装包的信息

得到安装包的所有的信息

  一个APK安装包它的相关信息都配置在AndroidManifest.xml中,将它解析出来之后,是存放在PackageInfo类对象中,而PackageInfo类对象的生成相关代码,实现在PackageUtil类的getPackageInfo()方法中,看一下它的实现:

    @Nullable
    public static PackageInfo getPackageInfo(Context context, File sourceFile, int flags) {
    
    
        try {
    
    
            return context.getPackageManager().getPackageArchiveInfo(sourceFile.getAbsolutePath(),
                    flags);
        } catch (Exception ignored) {
    
    
            return null;
        }
    }

  在这context一般是Activity实例,context.getPackageManager()得到的是ApplicationPackageManager实例。看一下它的getPackageArchiveInfo(sourceFile.getAbsolutePath(), flags)方法:

    @Nullable
    public PackageInfo getPackageArchiveInfo(@NonNull String archiveFilePath,
            @PackageInfoFlags int flags) {
    
    
        if ((flags & (PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                | PackageManager.MATCH_DIRECT_BOOT_AWARE)) == 0) {
    
    
            // Caller expressed no opinion about what encryption
            // aware/unaware components they want to see, so match both
            flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE
                    | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
        }

        boolean collectCertificates = (flags & PackageManager.GET_SIGNATURES) != 0
                || (flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0;

        ParseInput input = ParseTypeImpl.forParsingWithoutPlatformCompat().reset();
        ParseResult<ParsingPackage> result = ParsingPackageUtils.parseDefault(input,
                new File(archiveFilePath), 0, getPermissionManager().getSplitPermissions(),
                collectCertificates);
        if (result.isError()) {
    
    
            return null;
        }
        return PackageInfoWithoutStateUtils.generate(result.getResult(), null, flags, 0, 0, null,
                new PackageUserState(), UserHandle.getCallingUserId());
    }

  在这里,会将 flags 添加PackageManager.MATCH_DIRECT_BOOT_AWARE和PackageManager.MATCH_DIRECT_BOOT_UNAWARE。collectCertificates 会为false,代表不会收集签名。
  这里的input 实际是ParseTypeImpl对象。它用来保存解析的结果。
  这里首先通过ParsingPackageUtils.parseDefault()得到APK安装包的解析信息,然后调用PackageInfoWithoutStateUtils.generate()得到PackageInfo对象。
  看一下PackageInfoWithoutStateUtils.generate()方法,了解一下PackageInfo对象是怎么生成的。这里UserHandle.getCallingUserId()是Binder调用方的user id,它是通过调用方的uid得到的,如果当前没处在Binder调用中,则它是当前应用的user id。
  PackageInfoWithoutStateUtils.generate()方法会在内部调用PackageInfoWithoutStateUtils的静态方法generateWithComponents(ParsingPackageRead pkg, int[] gids, @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, Set grantedPermissions, PackageUserState state, int userId, @Nullable ApexInfo apexInfo),看一下它的实现:

    @Nullable
    private static PackageInfo generateWithComponents(ParsingPackageRead pkg, int[] gids,
            @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
            Set<String> grantedPermissions, PackageUserState state, int userId,
            @Nullable ApexInfo apexInfo) {
    
    
        ApplicationInfo applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
        if (applicationInfo == null) {
    
    
            return null;
        }
        PackageInfo info = generateWithoutComponents(pkg, gids, flags, firstInstallTime,
                lastUpdateTime, grantedPermissions, state, userId, apexInfo, applicationInfo);

        if (info == null) {
    
    
            return null;
        }

        if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
    
    
            final int N = pkg.getActivities().size();
            if (N > 0) {
    
    
                int num = 0;
                final ActivityInfo[] res = new ActivityInfo[N];
                for (int i = 0; i < N; i++) {
    
    
                    final ParsedActivity a = pkg.getActivities().get(i);
                    if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), a,
                            flags)) {
    
    
                        if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(
                                a.getName())) {
    
    
                            continue;
                        }
                        res[num++] = generateActivityInfo(pkg, a, flags, state,
                                applicationInfo, userId);
                    }
                }
                info.activities = ArrayUtils.trimToSize(res, num);
            }
        }
        if ((flags & PackageManager.GET_RECEIVERS) != 0) {
    
    
            final int size = pkg.getReceivers().size();
            if (size > 0) {
    
    
                int num = 0;
                final ActivityInfo[] res = new ActivityInfo[size];
                for (int i = 0; i < size; i++) {
    
    
                    final ParsedActivity a = pkg.getReceivers().get(i);
                    if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), a,
                            flags)) {
    
    
                        res[num++] = generateActivityInfo(pkg, a, flags, state,
                                applicationInfo, userId);
                    }
                }
                info.receivers = ArrayUtils.trimToSize(res, num);
            }
        }
        if ((flags & PackageManager.GET_SERVICES) != 0) {
    
    
            final int size = pkg.getServices().size();
            if (size > 0) {
    
    
                int num = 0;
                final ServiceInfo[] res = new ServiceInfo[size];
                for (int i = 0; i < size; i++) {
    
    
                    final ParsedService s = pkg.getServices().get(i);
                    if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), s,
                            flags)) {
    
    
                        res[num++] = generateServiceInfo(pkg, s, flags, state,
                                applicationInfo, userId);
                    }
                }
                info.services = ArrayUtils.trimToSize(res, num);
            }
        }
        if ((flags & PackageManager.GET_PROVIDERS) != 0) {
    
    
            final int size = pkg.getProviders().size();
            if (size > 0) {
    
    
                int num = 0;
                final ProviderInfo[] res = new ProviderInfo[size];
                for (int i = 0; i < size; i++) {
    
    
                    final ParsedProvider pr = pkg.getProviders()
                            .get(i);
                    if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), pr,
                            flags)) {
    
    
                        res[num++] = generateProviderInfo(pkg, pr, flags, state,
                                applicationInfo, userId);
                    }
                }
                info.providers = ArrayUtils.trimToSize(res, num);
            }
        }
        if ((flags & PackageManager.GET_INSTRUMENTATION) != 0) {
    
    
            int N = pkg.getInstrumentations().size();
            if (N > 0) {
    
    
                info.instrumentation = new InstrumentationInfo[N];
                for (int i = 0; i < N; i++) {
    
    
                    info.instrumentation[i] = generateInstrumentationInfo(
                            pkg.getInstrumentations().get(i), pkg, flags, userId,
                            true /* assignUserFields */);
                }
            }
        }

        return info;
    }

  该方法首先通过generateApplicationInfo()方法得到ApplicationInfo对象,然后通过该对象作为参数调用generateWithoutComponents()方法得到PackageInfo对象info。接下来,再根据flags标识判断是否得到四大组件Activity、Receiver、Service、Provider的信息。再通过PackageManager.GET_INSTRUMENTATION标识,得到Instrumentation信息。

生成ApplicationInfo对象

  它是由PackageInfoWithoutStateUtils类的generateApplicationInfo(ParsingPackageRead pkg, @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId)实现:

    @Nullable
    public static ApplicationInfo generateApplicationInfo(ParsingPackageRead pkg,
            @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId) {
    
    
        if (pkg == null) {
    
    
            return null;
        }

        if (!checkUseInstalled(pkg, state, flags)) {
    
    
            return null;
        }

        return generateApplicationInfoUnchecked(pkg, flags, state, userId,
                true /* assignUserFields */);
    }

  pkg 不问为null,它是解析APK文件得到的所有相关信息,它实际是ParsingPackageImpl对象。详细见Android 解析APK包
  接着调用checkUseInstalled(pkg, state, flags)检查包的状态,如果返回false,则返回结果null。PackageUserState类用来描述包的每用户状态信息。它最终是调用PackageUserState类对象的isAvailable(int flags)方法实现,代码PackageUserState类对象的isAvailable(int flags)代码如下:

    /**
     * Test if this package is installed.
     */
    public boolean isAvailable(int flags) {
    
    
        // True if it is installed for this user and it is not hidden. If it is hidden,
        // still return true if the caller requested MATCH_UNINSTALLED_PACKAGES
        final boolean matchAnyUser = (flags & PackageManager.MATCH_ANY_USER) != 0;
        final boolean matchUninstalled = (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0;
        return matchAnyUser
                || (this.installed
                        && (!this.hidden || matchUninstalled));
    }

  如果标签flags存在PackageManager.MATCH_ANY_USER标识,则代表满足任一用户。这种情况直接返回true。
  如果状态是installed并且不是隐藏,返回true。但是状态是installed并且是隐藏,这种情况下调用者如果带PackageManager.MATCH_UNINSTALLED_PACKAGES标识也返回true。
  在这里PackageUserState类对象是新建的,所以installed为true,hidden 为false。所以返回true。
  最后接着调用generateApplicationInfoUnchecked(pkg, flags, state, userId, true /* assignUserFields */),来生成ApplicationInfo对象,它的代码如下:

    @NonNull
    public static ApplicationInfo generateApplicationInfoUnchecked(@NonNull ParsingPackageRead pkg,
            @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId,
            boolean assignUserFields) {
    
    
        // Make shallow copy so we can store the metadata/libraries safely
        ApplicationInfo ai = pkg.toAppInfoWithoutState();

        if (assignUserFields) {
    
    
            assignUserFields(pkg, ai, userId);
        }

        if ((flags & PackageManager.GET_META_DATA) == 0) {
    
    
            ai.metaData = null;
        }
        if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) == 0) {
    
    
            ai.sharedLibraryFiles = null;
            ai.sharedLibraryInfos = null;
        }

        // CompatibilityMode is global state.
        if (!android.content.pm.PackageParser.sCompatibilityModeEnabled) {
    
    
            ai.disableCompatibilityMode();
        }

        ai.flags |= flag(state.stopped, ApplicationInfo.FLAG_STOPPED)
                | flag(state.installed, ApplicationInfo.FLAG_INSTALLED)
                | flag(state.suspended, ApplicationInfo.FLAG_SUSPENDED);
        ai.privateFlags |= flag(state.instantApp, ApplicationInfo.PRIVATE_FLAG_INSTANT)
                | flag(state.virtualPreload, ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD)
                | flag(state.hidden, ApplicationInfo.PRIVATE_FLAG_HIDDEN);

        if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
    
    
            ai.enabled = true;
        } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
    
    
            ai.enabled = (flags & PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
        } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
                || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
    
    
            ai.enabled = false;
        }
        ai.enabledSetting = state.enabled;
        if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
    
    
            ai.category = state.categoryHint;
        }
        if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
    
    
            ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
        }
        ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
        final OverlayPaths overlayPaths = state.getAllOverlayPaths();
        if (overlayPaths != null) {
    
    
            ai.resourceDirs = overlayPaths.getResourceDirs().toArray(new String[0]);
            ai.overlayPaths = overlayPaths.getOverlayPaths().toArray(new String[0]);
        }

        return ai;
    }

  这里通过ParsingPackageRead类对象pkg的toAppInfoWithoutState()得到ApplicationInfo对象。这里pkg是ParsingPackageImpl对象。所以这里调用的ParsingPackageImpl类的toAppInfoWithoutState()方法:

    @Deprecated
    @Override
    public ApplicationInfo toAppInfoWithoutState() {
    
    
        ApplicationInfo appInfo = toAppInfoWithoutStateWithoutFlags();
        appInfo.flags = PackageInfoWithoutStateUtils.appInfoFlags(this);
        appInfo.privateFlags = PackageInfoWithoutStateUtils.appInfoPrivateFlags(this);
        appInfo.privateFlagsExt = PackageInfoWithoutStateUtils.appInfoPrivateFlagsExt(this);
        return appInfo;
    }

    @Override
    public ApplicationInfo toAppInfoWithoutStateWithoutFlags() {
    
    
        ApplicationInfo appInfo = new ApplicationInfo();

        // Lines that are commented below are state related and should not be assigned here.
        // They are left in as placeholders, since there is no good backwards compatible way to
        // separate these.
        appInfo.appComponentFactory = appComponentFactory;
        appInfo.backupAgentName = backupAgentName;
        appInfo.banner = banner;
        appInfo.category = category;
        appInfo.classLoaderName = classLoaderName;
        appInfo.className = className;
        appInfo.compatibleWidthLimitDp = compatibleWidthLimitDp;
        appInfo.compileSdkVersion = compileSdkVersion;
        appInfo.compileSdkVersionCodename = compileSdkVersionCodeName;
//        appInfo.credentialProtectedDataDir
        appInfo.crossProfile = isCrossProfile();
//        appInfo.dataDir
        appInfo.descriptionRes = descriptionRes;
//        appInfo.deviceProtectedDataDir
        appInfo.enabled = getBoolean(Booleans.ENABLED);
//        appInfo.enabledSetting
        appInfo.fullBackupContent = fullBackupContent;
        appInfo.dataExtractionRulesRes = dataExtractionRules;
        // TODO(b/135203078): See ParsingPackageImpl#getHiddenApiEnforcementPolicy
//        appInfo.mHiddenApiPolicy
//        appInfo.hiddenUntilInstalled
        appInfo.icon =
                (ParsingPackageUtils.sUseRoundIcon && roundIconRes != 0) ? roundIconRes : iconRes;
        appInfo.iconRes = iconRes;
        appInfo.roundIconRes = roundIconRes;
        appInfo.installLocation = installLocation;
        appInfo.labelRes = labelRes;
        appInfo.largestWidthLimitDp = largestWidthLimitDp;
        appInfo.logo = logo;
        appInfo.manageSpaceActivityName = manageSpaceActivityName;
        appInfo.maxAspectRatio = maxAspectRatio;
        appInfo.metaData = metaData;
        appInfo.minAspectRatio = minAspectRatio;
        appInfo.minSdkVersion = minSdkVersion;
        appInfo.name = className;
//        appInfo.nativeLibraryDir
//        appInfo.nativeLibraryRootDir
//        appInfo.nativeLibraryRootRequiresIsa
        appInfo.networkSecurityConfigRes = networkSecurityConfigRes;
        appInfo.nonLocalizedLabel = nonLocalizedLabel;
        appInfo.packageName = packageName;
        appInfo.permission = permission;
//        appInfo.primaryCpuAbi
        appInfo.processName = getProcessName();
        appInfo.requiresSmallestWidthDp = requiresSmallestWidthDp;
//        appInfo.resourceDirs
//        appInfo.secondaryCpuAbi
//        appInfo.secondaryNativeLibraryDir
//        appInfo.seInfo
//        appInfo.seInfoUser
//        appInfo.sharedLibraryFiles
//        appInfo.sharedLibraryInfos
//        appInfo.showUserIcon
        appInfo.splitClassLoaderNames = splitClassLoaderNames;
        appInfo.splitDependencies = splitDependencies;
        appInfo.splitNames = splitNames;
        appInfo.storageUuid = mStorageUuid;
        appInfo.targetSandboxVersion = targetSandboxVersion;
        appInfo.targetSdkVersion = targetSdkVersion;
        appInfo.taskAffinity = taskAffinity;
        appInfo.theme = theme;
//        appInfo.uid
        appInfo.uiOptions = uiOptions;
        appInfo.volumeUuid = volumeUuid;
        appInfo.zygotePreloadName = zygotePreloadName;
        appInfo.setGwpAsanMode(gwpAsanMode);
        appInfo.setMemtagMode(memtagMode);
        appInfo.setNativeHeapZeroInitialized(nativeHeapZeroInitialized);
        appInfo.setRequestRawExternalStorageAccess(requestRawExternalStorageAccess);
        appInfo.setBaseCodePath(mBaseApkPath);
        appInfo.setBaseResourcePath(mBaseApkPath);
        appInfo.setCodePath(mPath);
        appInfo.setResourcePath(mPath);
        appInfo.setSplitCodePaths(splitCodePaths);
        appInfo.setSplitResourcePaths(splitCodePaths);
        appInfo.setVersionCode(mLongVersionCode);

        return appInfo;
    }

  从这里可以看到,主要是将ParsingPackageImpl对象的成员变量值赋给ApplicationInfo 类对象。
  再回到PackageInfoWithoutStateUtils类的generateApplicationInfoUnchecked(pkg, flags, state, userId, true /* assignUserFields */)方法里,接着assignUserFields如果为true,会调用assignUserFields(pkg, ai, userId),它主要是设置ApplicationInfo类对象的credentialProtectedDataDir、deviceProtectedDataDir、dataDir。
  接着会根据标识,判断是否设置ApplicationInfo类对象的metaData、sharedLibraryFiles、sharedLibraryInfos。
  下面主要是根据PackageUserState类对象state的值来设置一些对应的值。
  通过以上,我们明白了ApplicationInfo类对象的生成。

生成PackageInfo对象

  PackageInfo对象的生成主要是由PackageInfoWithoutStateUtils的generateWithoutComponents(ParsingPackageRead pkg, int[] gids, @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime, Set grantedPermissions, PackageUserState state, int userId, @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo)来生成,看一下它的代码:

    @Nullable
    public static PackageInfo generateWithoutComponents(ParsingPackageRead pkg, int[] gids,
            @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
            Set<String> grantedPermissions, PackageUserState state, int userId,
            @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo) {
    
    
        if (!checkUseInstalled(pkg, state, flags)) {
    
    
            return null;
        }

        return generateWithoutComponentsUnchecked(pkg, gids, flags, firstInstallTime,
                lastUpdateTime, grantedPermissions, state, userId, apexInfo, applicationInfo);
    }

  checkUseInstalled(pkg, state, flags)前面说过了,这里略了。接着看generateWithoutComponentsUnchecked()方法:

    @NonNull
    public static PackageInfo generateWithoutComponentsUnchecked(ParsingPackageRead pkg, int[] gids,
            @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
            Set<String> grantedPermissions, PackageUserState state, int userId,
            @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo) {
    
    
        PackageInfo pi = new PackageInfo();
        pi.packageName = pkg.getPackageName();
        pi.splitNames = pkg.getSplitNames();
        pi.versionCode = pkg.getVersionCode();
        pi.versionCodeMajor = pkg.getVersionCodeMajor();
        pi.baseRevisionCode = pkg.getBaseRevisionCode();
        pi.splitRevisionCodes = pkg.getSplitRevisionCodes();
        pi.versionName = pkg.getVersionName();
        pi.sharedUserId = pkg.getSharedUserId();
        pi.sharedUserLabel = pkg.getSharedUserLabel();
        pi.applicationInfo = applicationInfo;
        pi.installLocation = pkg.getInstallLocation();
        if ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
                || (pi.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
    
    
            pi.requiredForAllUsers = pkg.isRequiredForAllUsers();
        }
        pi.restrictedAccountType = pkg.getRestrictedAccountType();
        pi.requiredAccountType = pkg.getRequiredAccountType();
        pi.overlayTarget = pkg.getOverlayTarget();
        pi.targetOverlayableName = pkg.getOverlayTargetName();
        pi.overlayCategory = pkg.getOverlayCategory();
        pi.overlayPriority = pkg.getOverlayPriority();
        pi.mOverlayIsStatic = pkg.isOverlayIsStatic();
        pi.compileSdkVersion = pkg.getCompileSdkVersion();
        pi.compileSdkVersionCodename = pkg.getCompileSdkVersionCodeName();
        pi.firstInstallTime = firstInstallTime;
        pi.lastUpdateTime = lastUpdateTime;
        if ((flags & PackageManager.GET_GIDS) != 0) {
    
    
            pi.gids = gids;
        }
        if ((flags & PackageManager.GET_CONFIGURATIONS) != 0) {
    
    
            int size = pkg.getConfigPreferences().size();
            if (size > 0) {
    
    
                pi.configPreferences = new ConfigurationInfo[size];
                pkg.getConfigPreferences().toArray(pi.configPreferences);
            }
            size = pkg.getReqFeatures().size();
            if (size > 0) {
    
    
                pi.reqFeatures = new FeatureInfo[size];
                pkg.getReqFeatures().toArray(pi.reqFeatures);
            }
            size = pkg.getFeatureGroups().size();
            if (size > 0) {
    
    
                pi.featureGroups = new FeatureGroupInfo[size];
                pkg.getFeatureGroups().toArray(pi.featureGroups);
            }
        }
        if ((flags & PackageManager.GET_PERMISSIONS) != 0) {
    
    
            int size = ArrayUtils.size(pkg.getPermissions());
            if (size > 0) {
    
    
                pi.permissions = new PermissionInfo[size];
                for (int i = 0; i < size; i++) {
    
    
                    pi.permissions[i] = generatePermissionInfo(pkg.getPermissions().get(i),
                            flags);
                }
            }
            final List<ParsedUsesPermission> usesPermissions = pkg.getUsesPermissions();
            size = usesPermissions.size();
            if (size > 0) {
    
    
                pi.requestedPermissions = new String[size];
                pi.requestedPermissionsFlags = new int[size];
                for (int i = 0; i < size; i++) {
    
    
                    final ParsedUsesPermission usesPermission = usesPermissions.get(i);
                    pi.requestedPermissions[i] = usesPermission.name;
                    // The notion of required permissions is deprecated but for compatibility.
                    pi.requestedPermissionsFlags[i] |=
                            PackageInfo.REQUESTED_PERMISSION_REQUIRED;
                    if (grantedPermissions != null
                            && grantedPermissions.contains(usesPermission.name)) {
    
    
                        pi.requestedPermissionsFlags[i] |=
                                PackageInfo.REQUESTED_PERMISSION_GRANTED;
                    }
                    if ((usesPermission.usesPermissionFlags
                            & ParsedUsesPermission.FLAG_NEVER_FOR_LOCATION) != 0) {
    
    
                        pi.requestedPermissionsFlags[i] |=
                                PackageInfo.REQUESTED_PERMISSION_NEVER_FOR_LOCATION;
                    }
                }
            }
        }
        if ((flags & PackageManager.GET_ATTRIBUTIONS) != 0) {
    
    
            int size = ArrayUtils.size(pkg.getAttributions());
            if (size > 0) {
    
    
                pi.attributions = new Attribution[size];
                for (int i = 0; i < size; i++) {
    
    
                    pi.attributions[i] = generateAttribution(pkg.getAttributions().get(i));
                }
            }
            if (pkg.areAttributionsUserVisible()) {
    
    
                pi.applicationInfo.privateFlagsExt
                        |= ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE;
            } else {
    
    
                pi.applicationInfo.privateFlagsExt
                        &= ~ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE;
            }
        } else {
    
    
            pi.applicationInfo.privateFlagsExt
                    &= ~ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE;
        }

        if (apexInfo != null) {
    
    
            File apexFile = new File(apexInfo.modulePath);

            pi.applicationInfo.sourceDir = apexFile.getPath();
            pi.applicationInfo.publicSourceDir = apexFile.getPath();
            if (apexInfo.isFactory) {
    
    
                pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
                pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
            } else {
    
    
                pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
                pi.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
            }
            if (apexInfo.isActive) {
    
    
                pi.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
            } else {
    
    
                pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED;
            }
            pi.isApex = true;
        }

        PackageParser.SigningDetails signingDetails = pkg.getSigningDetails();
        // deprecated method of getting signing certificates
        if ((flags & PackageManager.GET_SIGNATURES) != 0) {
    
    
            if (signingDetails.hasPastSigningCertificates()) {
    
    
                // Package has included signing certificate rotation information.  Return the oldest
                // cert so that programmatic checks keep working even if unaware of key rotation.
                pi.signatures = new Signature[1];
                pi.signatures[0] = signingDetails.pastSigningCertificates[0];
            } else if (signingDetails.hasSignatures()) {
    
    
                // otherwise keep old behavior
                int numberOfSigs = signingDetails.signatures.length;
                pi.signatures = new Signature[numberOfSigs];
                System.arraycopy(signingDetails.signatures, 0, pi.signatures, 0,
                        numberOfSigs);
            }
        }

        // replacement for GET_SIGNATURES
        if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
    
    
            if (signingDetails != PackageParser.SigningDetails.UNKNOWN) {
    
    
                // only return a valid SigningInfo if there is signing information to report
                pi.signingInfo = new SigningInfo(signingDetails);
            } else {
    
    
                pi.signingInfo = null;
            }
        }

        return pi;
    }

  这些代码看着很长,其实主要是新生成PackageInfo对象,然后给它的成员变量赋值。
  这里我们看到,前面生成的ApplicationInfo类对象是放到PackageInfo类对象的applicationInfo成员变量中。并且PackageInfo类对象大部分成员变量的值都来自ParsingPackageImpl类对象的成员变量的值。
  而ApplicationInfo类对象的值,大部分也都来自ParsingPackageImpl类对象。而ParsingPackageImpl类对象的值,也是来自安装包里的“AndroidManifest.xml”文件,这样就将ParsingPackageImpl类对象的值都设置到PackageInfo类对象中。

总结

  APK安装包里的配置信息都在“AndroidManifest.xml”文件中,通过解析它之后,是放到了ParsingPackageImpl类对象中。ParsingPackageImpl类对象通过自己的toAppInfoWithoutState(),将自己的值生成到ApplicationInfo对象中,而PackageInfo类对象的applicationInfo正是ApplicationInfo对象,并且PackageInfo类对象的其他成员也来自ParsingPackageImpl类对象。这样PackageInfo类对象就包含了安装包的信息。

猜你喜欢

转载自blog.csdn.net/q1165328963/article/details/134023435