blob: 7b329ebc5b832a46c82a2fae312fb9bea809ce2e [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.content.pm.parsing;
import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED;
import android.annotation.Nullable;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.ConfigurationInfo;
import android.content.pm.FallbackCategoryProvider;
import android.content.pm.FeatureGroupInfo;
import android.content.pm.FeatureInfo;
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.PackageUserState;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.content.pm.ProviderInfo;
import android.content.pm.SELinuxUtil;
import android.content.pm.ServiceInfo;
import android.content.pm.Signature;
import android.content.pm.SigningInfo;
import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation;
import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
import android.content.pm.parsing.ComponentParseUtils.ParsedPermissionGroup;
import android.os.Bundle;
import android.os.UserHandle;
import com.android.internal.util.ArrayUtils;
import java.util.Set;
/** @hide */
public class PackageInfoUtils {
private static final String TAG = ApkParseUtils.TAG;
/**
* Returns true if the package is installed and not hidden, or if the caller
* explicitly wanted all uninstalled and hidden packages as well.
*/
private static boolean checkUseInstalledOrHidden(AndroidPackage pkg, PackageUserState state,
@PackageManager.PackageInfoFlags int flags) {
// Returns false if the package is hidden system app until installed.
if ((flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) == 0
&& !state.installed
&& pkg.isHiddenUntilInstalled()) {
return false;
}
// If available for the target user, or trying to match uninstalled packages and it's
// a system app.
return state.isAvailable(flags)
|| (pkg.isSystemApp()
&& ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0
|| (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0));
}
public static PackageInfo generate(AndroidPackage pkg, int[] gids,
@PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
Set<String> grantedPermissions, PackageUserState state, int userId) {
if (!checkUseInstalledOrHidden(pkg, state, flags) || !pkg.isMatch(flags)) {
return null;
}
ApplicationInfo applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
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();
pi.isStub = pkg.isStub();
pi.coreApp = pkg.isCoreApp();
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() != null ? pkg.getConfigPreferences().size() : 0;
if (size > 0) {
pi.configPreferences = new ConfigurationInfo[size];
pkg.getConfigPreferences().toArray(pi.configPreferences);
}
size = pkg.getReqFeatures() != null ? pkg.getReqFeatures().size() : 0;
if (size > 0) {
pi.reqFeatures = new FeatureInfo[size];
pkg.getReqFeatures().toArray(pi.reqFeatures);
}
size = pkg.getFeatureGroups() != null ? pkg.getFeatureGroups().size() : 0;
if (size > 0) {
pi.featureGroups = new FeatureGroupInfo[size];
pkg.getFeatureGroups().toArray(pi.featureGroups);
}
}
if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
if (pkg.getActivities() != null) {
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 (state.isMatch(pkg.isSystem(), pkg.isEnabled(), a, flags)) {
if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(
a.className)) {
continue;
}
res[num++] = generateActivityInfo(pkg, a, flags, state, applicationInfo,
userId);
}
}
pi.activities = ArrayUtils.trimToSize(res, num);
}
}
}
if ((flags & PackageManager.GET_RECEIVERS) != 0) {
if (pkg.getReceivers() != null) {
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 (state.isMatch(pkg.isSystem(), pkg.isEnabled(), a, flags)) {
res[num++] = generateActivityInfo(pkg, a, flags, state, applicationInfo,
userId);
}
}
pi.receivers = ArrayUtils.trimToSize(res, num);
}
}
}
if ((flags & PackageManager.GET_SERVICES) != 0) {
if (pkg.getServices() != null) {
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 ComponentParseUtils.ParsedService s = pkg.getServices().get(i);
if (state.isMatch(pkg.isSystem(), pkg.isEnabled(), s, flags)) {
res[num++] = generateServiceInfo(pkg, s, flags, state, applicationInfo,
userId);
}
}
pi.services = ArrayUtils.trimToSize(res, num);
}
}
}
if ((flags & PackageManager.GET_PROVIDERS) != 0) {
if (pkg.getProviders() != null) {
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 ComponentParseUtils.ParsedProvider pr = pkg.getProviders()
.get(i);
if (state.isMatch(pkg.isSystem(), pkg.isEnabled(), pr, flags)) {
res[num++] = generateProviderInfo(pkg, pr, flags, state,
applicationInfo, userId);
}
}
pi.providers = ArrayUtils.trimToSize(res, num);
}
}
}
if ((flags & PackageManager.GET_INSTRUMENTATION) != 0) {
if (pkg.getInstrumentations() != null) {
int N = pkg.getInstrumentations().size();
if (N > 0) {
pi.instrumentation = new InstrumentationInfo[N];
for (int i = 0; i < N; i++) {
pi.instrumentation[i] = generateInstrumentationInfo(
pkg.getInstrumentations().get(i), flags);
}
}
}
}
if ((flags & PackageManager.GET_PERMISSIONS) != 0) {
if (pkg.getPermissions() != null) {
int N = ArrayUtils.size(pkg.getPermissions());
if (N > 0) {
pi.permissions = new PermissionInfo[N];
for (int i = 0; i < N; i++) {
pi.permissions[i] = generatePermissionInfo(
pkg.getPermissions().get(i),
flags
);
}
}
}
if (pkg.getRequestedPermissions() != null) {
int N = pkg.getRequestedPermissions().size();
if (N > 0) {
pi.requestedPermissions = new String[N];
pi.requestedPermissionsFlags = new int[N];
for (int i = 0; i < N; i++) {
final String perm = pkg.getRequestedPermissions().get(i);
pi.requestedPermissions[i] = perm;
// The notion of required permissions is deprecated but for compatibility.
pi.requestedPermissionsFlags[i] |=
PackageInfo.REQUESTED_PERMISSION_REQUIRED;
if (grantedPermissions != null && grantedPermissions.contains(perm)) {
pi.requestedPermissionsFlags[i] |=
PackageInfo.REQUESTED_PERMISSION_GRANTED;
}
}
}
}
}
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;
}
// TODO(b/135203078): Remove this in favor of AndroidPackage.toAppInfo()
private static ApplicationInfo appInfoFromFinalPackage(AndroidPackage pkg) {
ApplicationInfo appInfo = new ApplicationInfo();
appInfo.name = pkg.getName();
if (appInfo.name != null) appInfo.name = appInfo.name.trim();
appInfo.packageName = pkg.getPackageName();
appInfo.labelRes = pkg.getLabelRes();
appInfo.nonLocalizedLabel = pkg.getNonLocalizedLabel();
if (appInfo.nonLocalizedLabel != null) {
appInfo.nonLocalizedLabel = appInfo.nonLocalizedLabel.toString().trim();
}
appInfo.icon = pkg.getIcon();
appInfo.banner = pkg.getBanner();
appInfo.logo = pkg.getLogo();
appInfo.metaData = pkg.getMetaData();
// TODO(b/135203078): Can this be removed? Looks only used in ActivityInfo.
// appInfo.showUserIcon = pkg.getShowUserIcon();
appInfo.taskAffinity = pkg.getTaskAffinity();
appInfo.permission = pkg.getPermission();
appInfo.processName = pkg.getProcessName();
appInfo.className = pkg.getClassName();
appInfo.theme = pkg.getTheme();
appInfo.flags = pkg.getFlags();
appInfo.privateFlags = pkg.getPrivateFlags();
appInfo.requiresSmallestWidthDp = pkg.getRequiresSmallestWidthDp();
appInfo.compatibleWidthLimitDp = pkg.getCompatibleWidthLimitDp();
appInfo.largestWidthLimitDp = pkg.getLargestWidthLimitDp();
appInfo.volumeUuid = pkg.getVolumeUuid();
appInfo.storageUuid = pkg.getStorageUuid();
appInfo.scanSourceDir = pkg.getScanSourceDir();
appInfo.scanPublicSourceDir = pkg.getScanPublicSourceDir();
appInfo.sourceDir = pkg.getBaseCodePath();
appInfo.publicSourceDir = pkg.getPublicSourceDir();
appInfo.splitNames = pkg.getSplitNames();
appInfo.splitSourceDirs = pkg.getSplitCodePaths();
appInfo.splitPublicSourceDirs = pkg.getSplitPublicSourceDirs();
appInfo.splitDependencies = pkg.getSplitDependencies();
appInfo.nativeLibraryDir = pkg.getNativeLibraryDir();
appInfo.secondaryNativeLibraryDir = pkg.getSecondaryNativeLibraryDir();
appInfo.nativeLibraryRootDir = pkg.getNativeLibraryRootDir();
appInfo.nativeLibraryRootRequiresIsa = pkg.isNativeLibraryRootRequiresIsa();
appInfo.primaryCpuAbi = pkg.getPrimaryCpuAbi();
appInfo.secondaryCpuAbi = pkg.getSecondaryCpuAbi();
// TODO(b/135203078): Unused?
// appInfo.resourceDirs = pkg.getResourceDirs();
appInfo.seInfo = pkg.getSeInfo();
appInfo.seInfoUser = pkg.getSeInfoUser();
appInfo.sharedLibraryFiles = pkg.getUsesLibraryFiles();
appInfo.sharedLibraryInfos = pkg.getUsesLibraryInfos();
appInfo.dataDir = pkg.getDataDir();
appInfo.deviceProtectedDataDir = pkg.getDeviceProtectedDataDir();
appInfo.credentialProtectedDataDir = pkg.getCredentialProtectedDataDir();
appInfo.uid = pkg.getUid();
appInfo.minSdkVersion = pkg.getMinSdkVersion();
appInfo.targetSdkVersion = pkg.getTargetSdkVersion();
appInfo.setVersionCode(pkg.getLongVersionCode());
appInfo.enabled = pkg.isEnabled();
// TODO(b/135203078): Unused?
// appInfo.enabledSetting = pkg.getEnabledSetting();
appInfo.installLocation = pkg.getInstallLocation();
appInfo.manageSpaceActivityName = pkg.getManageSpaceActivityName();
appInfo.descriptionRes = pkg.getDescriptionRes();
appInfo.uiOptions = pkg.getUiOptions();
appInfo.backupAgentName = pkg.getBackupAgentName();
appInfo.fullBackupContent = pkg.getFullBackupContent();
appInfo.networkSecurityConfigRes = pkg.getNetworkSecurityConfigRes();
appInfo.category = pkg.getCategory();
appInfo.targetSandboxVersion = pkg.getTargetSandboxVersion();
appInfo.classLoaderName = pkg.getClassLoaderName();
appInfo.splitClassLoaderNames = pkg.getSplitClassLoaderNames();
appInfo.appComponentFactory = pkg.getAppComponentFactory();
appInfo.iconRes = pkg.getIconRes();
appInfo.roundIconRes = pkg.getRoundIconRes();
appInfo.compileSdkVersion = pkg.getCompileSdkVersion();
appInfo.compileSdkVersionCodename = pkg.getCompileSdkVersionCodeName();
// TODO(b/135203078): See PackageImpl#getHiddenApiEnforcementPolicy
// appInfo.mHiddenApiPolicy = pkg.getHiddenApiPolicy();
appInfo.hiddenUntilInstalled = pkg.isHiddenUntilInstalled();
appInfo.zygotePreloadName = pkg.getZygotePreloadName();
return appInfo;
}
public static ApplicationInfo generateApplicationInfo(AndroidPackage pkg,
@PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId) {
if (pkg == null) return null;
if (!checkUseInstalledOrHidden(pkg, state, flags) || !pkg.isMatch(flags)) {
return null;
}
if (!copyNeeded(flags, pkg, state, null, userId)
&& ((flags & PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) == 0
|| state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED)) {
// TODO(b/135203078): This isn't applicable anymore, as AppInfo isn't cached and
// always built new in toAppInfo(). Remove entire copyNeeded flow? Or find a way to
// transiently cache AppInfo, since multiple calls in quick secession probably need
// the same AppInfo.
// In this case it is safe to directly modify the internal ApplicationInfo state:
// - CompatibilityMode is global state, so will be the same for every call.
// - We only come in to here if the app should reported as installed; this is the
// default state, and we will do a copy otherwise.
// - The enable state will always be reported the same for the application across
// calls; the only exception is for the UNTIL_USED mode, and in that case we will
// be doing a copy.
ApplicationInfo applicationInfo = pkg.toAppInfo();
updateApplicationInfo(applicationInfo, flags, state);
return applicationInfo;
}
// Make shallow copy so we can store the metadata/libraries safely
ApplicationInfo ai = appInfoFromFinalPackage(pkg);
ai.initForUser(userId);
if ((flags & PackageManager.GET_META_DATA) != 0) {
ai.metaData = pkg.getAppMetaData();
}
if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0) {
ai.sharedLibraryFiles = pkg.getUsesLibraryFiles();
ai.sharedLibraryInfos = pkg.getUsesLibraryInfos();
}
if (state.stopped) {
ai.flags |= ApplicationInfo.FLAG_STOPPED;
} else {
ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
}
updateApplicationInfo(ai, flags, state);
return ai;
}
private static ActivityInfo generateActivityInfo(AndroidPackage pkg, ParsedActivity a,
@PackageManager.ComponentInfoFlags int flags, PackageUserState state,
@Nullable ApplicationInfo applicationInfo, int userId) {
if (a == null) return null;
if (!checkUseInstalledOrHidden(pkg, state, flags)) {
return null;
}
if (applicationInfo == null) {
applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
}
if (!copyNeeded(flags, pkg, state, a.metaData, userId)) {
updateApplicationInfo(applicationInfo, flags, state);
}
// Make shallow copies so we can store the metadata safely
ActivityInfo ai = new ActivityInfo();
assignSharedFieldsForComponentInfo(ai, a);
ai.targetActivity = a.targetActivity;
ai.processName = a.getProcessName();
ai.exported = a.exported;
ai.theme = a.theme;
ai.uiOptions = a.uiOptions;
ai.parentActivityName = a.parentActivityName;
ai.permission = a.getPermission();
ai.taskAffinity = a.taskAffinity;
ai.flags = a.flags;
ai.privateFlags = a.privateFlags;
ai.launchMode = a.launchMode;
ai.documentLaunchMode = a.documentLaunchMode;
ai.maxRecents = a.maxRecents;
ai.configChanges = a.configChanges;
ai.softInputMode = a.softInputMode;
ai.persistableMode = a.persistableMode;
ai.lockTaskLaunchMode = a.lockTaskLaunchMode;
ai.screenOrientation = a.screenOrientation;
ai.resizeMode = a.resizeMode;
ai.maxAspectRatio = a.maxAspectRatio;
ai.minAspectRatio = a.minAspectRatio;
ai.requestedVrComponent = a.requestedVrComponent;
ai.rotationAnimation = a.rotationAnimation;
ai.colorMode = a.colorMode;
ai.windowLayout = a.windowLayout;
ai.metaData = a.metaData;
ai.applicationInfo = applicationInfo;
return ai;
}
public static ActivityInfo generateActivityInfo(AndroidPackage pkg, ParsedActivity a,
@PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId) {
return generateActivityInfo(pkg, a, flags, state, null, userId);
}
private static ServiceInfo generateServiceInfo(AndroidPackage pkg,
ComponentParseUtils.ParsedService s, @PackageManager.ComponentInfoFlags int flags,
PackageUserState state, @Nullable ApplicationInfo applicationInfo, int userId) {
if (s == null) return null;
if (!checkUseInstalledOrHidden(pkg, state, flags)) {
return null;
}
if (applicationInfo == null) {
applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
}
if (!copyNeeded(flags, pkg, state, s.metaData, userId)) {
updateApplicationInfo(applicationInfo, flags, state);
}
// Make shallow copies so we can store the metadata safely
ServiceInfo si = new ServiceInfo();
assignSharedFieldsForComponentInfo(si, s);
si.exported = s.exported;
si.flags = s.flags;
si.metaData = s.metaData;
si.permission = s.getPermission();
si.processName = s.getProcessName();
si.mForegroundServiceType = s.foregroundServiceType;
si.metaData = s.metaData;
si.applicationInfo = applicationInfo;
return si;
}
public static ServiceInfo generateServiceInfo(AndroidPackage pkg,
ComponentParseUtils.ParsedService s, @PackageManager.ComponentInfoFlags int flags,
PackageUserState state, int userId) {
return generateServiceInfo(pkg, s, flags, state, null, userId);
}
private static ProviderInfo generateProviderInfo(AndroidPackage pkg,
ComponentParseUtils.ParsedProvider p, @PackageManager.ComponentInfoFlags int flags,
PackageUserState state, @Nullable ApplicationInfo applicationInfo, int userId) {
if (p == null) return null;
if (!checkUseInstalledOrHidden(pkg, state, flags)) {
return null;
}
if (applicationInfo == null) {
applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
}
if (!copyNeeded(flags, pkg, state, p.metaData, userId)
&& ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
|| p.uriPermissionPatterns == null)) {
updateApplicationInfo(applicationInfo, flags, state);
}
// Make shallow copies so we can store the metadata safely
ProviderInfo pi = new ProviderInfo();
assignSharedFieldsForComponentInfo(pi, p);
pi.exported = p.exported;
pi.flags = p.flags;
pi.processName = p.getProcessName();
pi.authority = p.getAuthority();
pi.isSyncable = p.isSyncable;
pi.readPermission = p.getReadPermission();
pi.writePermission = p.getWritePermission();
pi.grantUriPermissions = p.grantUriPermissions;
pi.forceUriPermissions = p.forceUriPermissions;
pi.multiprocess = p.multiProcess;
pi.initOrder = p.initOrder;
pi.uriPermissionPatterns = p.uriPermissionPatterns;
pi.pathPermissions = p.pathPermissions;
pi.metaData = p.metaData;
if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
pi.uriPermissionPatterns = null;
}
pi.applicationInfo = applicationInfo;
return pi;
}
public static ProviderInfo generateProviderInfo(AndroidPackage pkg,
ComponentParseUtils.ParsedProvider p, @PackageManager.ComponentInfoFlags int flags,
PackageUserState state, int userId) {
return generateProviderInfo(pkg, p, flags, state, null, userId);
}
public static InstrumentationInfo generateInstrumentationInfo(ParsedInstrumentation i,
@PackageManager.ComponentInfoFlags int flags) {
if (i == null) return null;
InstrumentationInfo ii = new InstrumentationInfo();
assignSharedFieldsForPackageItemInfo(ii, i);
ii.targetPackage = i.getTargetPackage();
ii.targetProcesses = i.getTargetProcesses();
ii.handleProfiling = i.handleProfiling;
ii.functionalTest = i.functionalTest;
ii.sourceDir = i.sourceDir;
ii.publicSourceDir = i.publicSourceDir;
ii.splitNames = i.splitNames;
ii.splitSourceDirs = i.splitSourceDirs;
ii.splitPublicSourceDirs = i.splitPublicSourceDirs;
ii.splitDependencies = i.splitDependencies;
ii.dataDir = i.dataDir;
ii.deviceProtectedDataDir = i.deviceProtectedDataDir;
ii.credentialProtectedDataDir = i.credentialProtectedDataDir;
ii.primaryCpuAbi = i.primaryCpuAbi;
ii.secondaryCpuAbi = i.secondaryCpuAbi;
ii.nativeLibraryDir = i.nativeLibraryDir;
ii.secondaryNativeLibraryDir = i.secondaryNativeLibraryDir;
if ((flags & PackageManager.GET_META_DATA) == 0) {
return ii;
}
ii.metaData = i.metaData;
return ii;
}
public static PermissionInfo generatePermissionInfo(ParsedPermission p,
@PackageManager.ComponentInfoFlags int flags) {
if (p == null) return null;
PermissionInfo pi = new PermissionInfo(p.backgroundPermission);
assignSharedFieldsForPackageItemInfo(pi, p);
pi.group = p.getGroup();
pi.requestRes = p.requestRes;
pi.protectionLevel = p.protectionLevel;
pi.descriptionRes = p.descriptionRes;
pi.flags = p.flags;
if ((flags & PackageManager.GET_META_DATA) == 0) {
return pi;
}
pi.metaData = p.metaData;
return pi;
}
public static PermissionGroupInfo generatePermissionGroupInfo(ParsedPermissionGroup pg,
@PackageManager.ComponentInfoFlags int flags) {
if (pg == null) return null;
PermissionGroupInfo pgi = new PermissionGroupInfo(
pg.requestDetailResourceId,
pg.backgroundRequestResourceId,
pg.backgroundRequestDetailResourceId
);
assignSharedFieldsForPackageItemInfo(pgi, pg);
pgi.priority = pg.priority;
pgi.requestRes = pg.requestRes;
pgi.flags = pg.flags;
if ((flags & PackageManager.GET_META_DATA) == 0) {
return pgi;
}
pgi.metaData = pg.metaData;
return pgi;
}
private static boolean copyNeeded(@PackageManager.ComponentInfoFlags int flags,
AndroidPackage pkg, PackageUserState state, Bundle metaData, int userId) {
if (userId != UserHandle.USER_SYSTEM) {
// We always need to copy for other users, since we need
// to fix up the uid.
return true;
}
if (state.enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
boolean enabled = state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
if (pkg.isEnabled() != enabled) {
return true;
}
}
boolean suspended = (pkg.getFlags() & FLAG_SUSPENDED) != 0;
if (state.suspended != suspended) {
return true;
}
if (!state.installed || state.hidden) {
return true;
}
if (state.stopped) {
return true;
}
if (state.instantApp != pkg.isInstantApp()) {
return true;
}
if ((flags & PackageManager.GET_META_DATA) != 0
&& (metaData != null || pkg.getAppMetaData() != null)) {
return true;
}
if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
&& pkg.getUsesLibraryFiles() != null) {
return true;
}
if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) != 0
&& pkg.getUsesLibraryInfos() != null) {
return true;
}
return pkg.getStaticSharedLibName() != null;
}
private static void updateApplicationInfo(ApplicationInfo ai,
@PackageManager.ApplicationInfoFlags int flags,
PackageUserState state) {
// CompatibilityMode is global state.
if (!PackageParser.sCompatibilityModeEnabled) {
ai.disableCompatibilityMode();
}
if (state.installed) {
ai.flags |= ApplicationInfo.FLAG_INSTALLED;
} else {
ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
}
if (state.suspended) {
ai.flags |= ApplicationInfo.FLAG_SUSPENDED;
} else {
ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
}
if (state.instantApp) {
ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_INSTANT;
} else {
ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_INSTANT;
}
if (state.virtualPreload) {
ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
} else {
ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
}
if (state.hidden) {
ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
} else {
ai.privateFlags &= ~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);
ai.resourceDirs = state.overlayPaths;
ai.icon = (PackageParser.sUseRoundIcon && ai.roundIconRes != 0)
? ai.roundIconRes : ai.iconRes;
}
private static void assignSharedFieldsForPackageItemInfo(PackageItemInfo packageItemInfo,
ComponentParseUtils.ParsedComponent parsedComponent) {
packageItemInfo.banner = parsedComponent.banner;
packageItemInfo.icon = parsedComponent.icon;
packageItemInfo.labelRes = parsedComponent.labelRes;
packageItemInfo.logo = parsedComponent.logo;
packageItemInfo.name = parsedComponent.className;
packageItemInfo.nonLocalizedLabel = parsedComponent.nonLocalizedLabel;
packageItemInfo.packageName = parsedComponent.getPackageName();
}
private static void assignSharedFieldsForComponentInfo(ComponentInfo componentInfo,
ComponentParseUtils.ParsedComponent parsedComponent) {
assignSharedFieldsForPackageItemInfo(componentInfo, parsedComponent);
componentInfo.descriptionRes = parsedComponent.descriptionRes;
componentInfo.directBootAware = parsedComponent.directBootAware;
componentInfo.enabled = parsedComponent.enabled;
componentInfo.splitName = parsedComponent.getSplitName();
}
}