diff options
107 files changed, 16874 insertions, 5832 deletions
diff --git a/Android.bp b/Android.bp index 9426a9c503ed..661b1ccf988e 100644 --- a/Android.bp +++ b/Android.bp @@ -372,7 +372,7 @@ java_defaults { exclude_srcs: [ // See comment on framework-atb-backward-compatibility module below - "core/java/android/content/pm/AndroidTestBaseUpdater.java", + "core/java/android/content/pm/parsing/library/AndroidTestBaseUpdater.java", ], sdk_version: "core_platform", @@ -536,7 +536,7 @@ java_library { installable: true, libs: ["app-compat-annotations"], srcs: [ - "core/java/android/content/pm/AndroidTestBaseUpdater.java", + "core/java/android/content/pm/parsing/library/AndroidTestBaseUpdater.java", ], } diff --git a/config/preloaded-classes b/config/preloaded-classes index 0394a7a489ba..97f009c09217 100644 --- a/config/preloaded-classes +++ b/config/preloaded-classes @@ -878,7 +878,7 @@ android.content.pm.-$$Lambda$jpya2qgMDDEok2GAoKRDqPM5lIE android.content.pm.ActivityInfo$1 android.content.pm.ActivityInfo$WindowLayout android.content.pm.ActivityInfo -android.content.pm.AndroidHidlUpdater +android.content.pm.parsing.library.AndroidHidlUpdater android.content.pm.ApplicationInfo$1 android.content.pm.ApplicationInfo android.content.pm.BaseParceledListSlice @@ -922,10 +922,10 @@ android.content.pm.LauncherApps$1 android.content.pm.LauncherApps android.content.pm.ModuleInfo$1 android.content.pm.ModuleInfo -android.content.pm.OrgApacheHttpLegacyUpdater -android.content.pm.PackageBackwardCompatibility$AndroidTestRunnerSplitUpdater -android.content.pm.PackageBackwardCompatibility$RemoveUnnecessaryAndroidTestBaseLibrary -android.content.pm.PackageBackwardCompatibility +android.content.pm.parsing.library.OrgApacheHttpLegacyUpdater +android.content.pm.parsing.library.PackageBackwardCompatibility$AndroidTestRunnerSplitUpdater +android.content.pm.parsing.library.PackageBackwardCompatibility$RemoveUnnecessaryAndroidTestBaseLibrary +android.content.pm.parsing.library.PackageBackwardCompatibility android.content.pm.PackageInfo$1 android.content.pm.PackageInfo android.content.pm.PackageInstaller$Session @@ -960,7 +960,7 @@ android.content.pm.PackageParser$SigningDetails$1 android.content.pm.PackageParser$SigningDetails android.content.pm.PackageParser$SplitNameComparator android.content.pm.PackageParser -android.content.pm.PackageSharedLibraryUpdater +android.content.pm.parsing.library.PackageSharedLibraryUpdater android.content.pm.PackageStats$1 android.content.pm.PackageStats android.content.pm.PackageUserState diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index e72444399dd0..26193f6ebb3d 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -1376,7 +1376,8 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { this.minHeight = minHeight; } - WindowLayout(Parcel source) { + /** @hide */ + public WindowLayout(Parcel source) { width = source.readInt(); widthFraction = source.readFloat(); height = source.readInt(); diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java index d6fb28f694fd..aa0002df2c3a 100644 --- a/core/java/android/content/pm/PackageInfo.java +++ b/core/java/android/content/pm/PackageInfo.java @@ -373,8 +373,9 @@ public class PackageInfo implements Parcelable { /** * Whether the overlay is static, meaning it cannot be enabled/disabled at runtime. + * @hide */ - boolean mOverlayIsStatic; + public boolean mOverlayIsStatic; /** * The user-visible SDK version (ex. 26) of the framework against which the application claims diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index cf21e9665c71..65ee1e5f0370 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -57,6 +57,12 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageParserCacheHelper.ReadHelper; import android.content.pm.PackageParserCacheHelper.WriteHelper; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.ApkParseUtils; +import android.content.pm.parsing.ComponentParseUtils; +import android.content.pm.parsing.PackageImpl; +import android.content.pm.parsing.PackageInfoUtils; +import android.content.pm.parsing.ParsedPackage; import android.content.pm.permission.SplitPermissionInfoParcelable; import android.content.pm.split.DefaultSplitAssetLoader; import android.content.pm.split.SplitAssetDependencyLoader; @@ -67,7 +73,6 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; -import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.FileUtils; @@ -156,21 +161,22 @@ import java.util.concurrent.atomic.AtomicInteger; * @hide */ public class PackageParser { - private static final boolean DEBUG_JAR = false; - private static final boolean DEBUG_PARSER = false; - private static final boolean DEBUG_BACKUP = false; - private static final boolean LOG_PARSE_TIMINGS = Build.IS_DEBUGGABLE; - private static final int LOG_PARSE_TIMINGS_THRESHOLD_MS = 100; + + public static final boolean DEBUG_JAR = false; + public static final boolean DEBUG_PARSER = false; + public static final boolean DEBUG_BACKUP = false; + public static final boolean LOG_PARSE_TIMINGS = Build.IS_DEBUGGABLE; + public static final int LOG_PARSE_TIMINGS_THRESHOLD_MS = 100; private static final String PROPERTY_CHILD_PACKAGES_ENABLED = "persist.sys.child_packages_enabled"; - private static final boolean MULTI_PACKAGE_APK_ENABLED = Build.IS_DEBUGGABLE && + public static final boolean MULTI_PACKAGE_APK_ENABLED = Build.IS_DEBUGGABLE && SystemProperties.getBoolean(PROPERTY_CHILD_PACKAGES_ENABLED, false); - private static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f; - private static final float DEFAULT_PRE_Q_MIN_ASPECT_RATIO = 1.333f; - private static final float DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH = 1f; + public static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f; + public static final float DEFAULT_PRE_Q_MIN_ASPECT_RATIO = 1.333f; + public static final float DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH = 1f; private static final int DEFAULT_MIN_SDK_VERSION = 1; private static final int DEFAULT_TARGET_SDK_VERSION = 0; @@ -182,37 +188,38 @@ public class PackageParser { public static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml"; /** Path prefix for apps on expanded storage */ - private static final String MNT_EXPAND = "/mnt/expand/"; - - private static final String TAG_MANIFEST = "manifest"; - private static final String TAG_APPLICATION = "application"; - private static final String TAG_PACKAGE_VERIFIER = "package-verifier"; - private static final String TAG_OVERLAY = "overlay"; - private static final String TAG_KEY_SETS = "key-sets"; - private static final String TAG_PERMISSION_GROUP = "permission-group"; - private static final String TAG_PERMISSION = "permission"; - private static final String TAG_PERMISSION_TREE = "permission-tree"; - private static final String TAG_USES_PERMISSION = "uses-permission"; - private static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m"; - private static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23"; - private static final String TAG_USES_CONFIGURATION = "uses-configuration"; - private static final String TAG_USES_FEATURE = "uses-feature"; - private static final String TAG_FEATURE_GROUP = "feature-group"; - private static final String TAG_USES_SDK = "uses-sdk"; - private static final String TAG_SUPPORT_SCREENS = "supports-screens"; - private static final String TAG_PROTECTED_BROADCAST = "protected-broadcast"; - private static final String TAG_INSTRUMENTATION = "instrumentation"; - private static final String TAG_ORIGINAL_PACKAGE = "original-package"; - private static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions"; - private static final String TAG_USES_GL_TEXTURE = "uses-gl-texture"; - private static final String TAG_COMPATIBLE_SCREENS = "compatible-screens"; - private static final String TAG_SUPPORTS_INPUT = "supports-input"; - private static final String TAG_EAT_COMMENT = "eat-comment"; - private static final String TAG_PACKAGE = "package"; - private static final String TAG_RESTRICT_UPDATE = "restrict-update"; - private static final String TAG_USES_SPLIT = "uses-split"; - - private static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect"; + public static final String MNT_EXPAND = "/mnt/expand/"; + + public static final String TAG_ADOPT_PERMISSIONS = "adopt-permissions"; + public static final String TAG_APPLICATION = "application"; + public static final String TAG_COMPATIBLE_SCREENS = "compatible-screens"; + public static final String TAG_EAT_COMMENT = "eat-comment"; + public static final String TAG_FEATURE_GROUP = "feature-group"; + public static final String TAG_INSTRUMENTATION = "instrumentation"; + public static final String TAG_KEY_SETS = "key-sets"; + public static final String TAG_MANIFEST = "manifest"; + public static final String TAG_ORIGINAL_PACKAGE = "original-package"; + public static final String TAG_OVERLAY = "overlay"; + public static final String TAG_PACKAGE = "package"; + public static final String TAG_PACKAGE_VERIFIER = "package-verifier"; + public static final String TAG_PERMISSION = "permission"; + public static final String TAG_PERMISSION_GROUP = "permission-group"; + public static final String TAG_PERMISSION_TREE = "permission-tree"; + public static final String TAG_PROTECTED_BROADCAST = "protected-broadcast"; + public static final String TAG_QUERIES = "queries"; + public static final String TAG_RESTRICT_UPDATE = "restrict-update"; + public static final String TAG_SUPPORT_SCREENS = "supports-screens"; + public static final String TAG_SUPPORTS_INPUT = "supports-input"; + public static final String TAG_USES_CONFIGURATION = "uses-configuration"; + public static final String TAG_USES_FEATURE = "uses-feature"; + public static final String TAG_USES_GL_TEXTURE = "uses-gl-texture"; + public static final String TAG_USES_PERMISSION = "uses-permission"; + public static final String TAG_USES_PERMISSION_SDK_23 = "uses-permission-sdk-23"; + public static final String TAG_USES_PERMISSION_SDK_M = "uses-permission-sdk-m"; + public static final String TAG_USES_SDK = "uses-sdk"; + public static final String TAG_USES_SPLIT = "uses-split"; + + public static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect"; /** * Bit mask of all the valid bits that can be set in recreateOnConfigChanges. @@ -222,25 +229,25 @@ public class PackageParser { ActivityInfo.CONFIG_MCC | ActivityInfo.CONFIG_MNC; // These are the tags supported by child packages - private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>(); + public static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>(); static { CHILD_PACKAGE_TAGS.add(TAG_APPLICATION); - CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION); - CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_M); - CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_23); - CHILD_PACKAGE_TAGS.add(TAG_USES_CONFIGURATION); - CHILD_PACKAGE_TAGS.add(TAG_USES_FEATURE); + CHILD_PACKAGE_TAGS.add(TAG_COMPATIBLE_SCREENS); + CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT); CHILD_PACKAGE_TAGS.add(TAG_FEATURE_GROUP); - CHILD_PACKAGE_TAGS.add(TAG_USES_SDK); - CHILD_PACKAGE_TAGS.add(TAG_SUPPORT_SCREENS); CHILD_PACKAGE_TAGS.add(TAG_INSTRUMENTATION); - CHILD_PACKAGE_TAGS.add(TAG_USES_GL_TEXTURE); - CHILD_PACKAGE_TAGS.add(TAG_COMPATIBLE_SCREENS); + CHILD_PACKAGE_TAGS.add(TAG_SUPPORT_SCREENS); CHILD_PACKAGE_TAGS.add(TAG_SUPPORTS_INPUT); - CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT); + CHILD_PACKAGE_TAGS.add(TAG_USES_CONFIGURATION); + CHILD_PACKAGE_TAGS.add(TAG_USES_FEATURE); + CHILD_PACKAGE_TAGS.add(TAG_USES_GL_TEXTURE); + CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION); + CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_23); + CHILD_PACKAGE_TAGS.add(TAG_USES_PERMISSION_SDK_M); + CHILD_PACKAGE_TAGS.add(TAG_USES_SDK); } - private static final boolean LOG_UNSAFE_BROADCASTS = false; + public static final boolean LOG_UNSAFE_BROADCASTS = false; /** * Total number of packages that were read from the cache. We use it only for logging. @@ -248,7 +255,7 @@ public class PackageParser { public static final AtomicInteger sCachedPackageReadCount = new AtomicInteger(); // Set of broadcast actions that are safe for manifest receivers - private static final Set<String> SAFE_BROADCASTS = new ArraySet<>(); + public static final Set<String> SAFE_BROADCASTS = new ArraySet<>(); static { SAFE_BROADCASTS.add(Intent.ACTION_BOOT_COMPLETED); } @@ -295,26 +302,29 @@ public class PackageParser { * @deprecated callers should move to explicitly passing around source path. */ @Deprecated - private String mArchiveSourcePath; + public String mArchiveSourcePath; - private String[] mSeparateProcesses; + public String[] mSeparateProcesses; private boolean mOnlyCoreApps; private DisplayMetrics mMetrics; @UnsupportedAppUsage - private Callback mCallback; + public Callback mCallback; private File mCacheDir; - private static final int SDK_VERSION = Build.VERSION.SDK_INT; - private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES; + public static final int SDK_VERSION = Build.VERSION.SDK_INT; + public static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES; + + public int mParseError = PackageManager.INSTALL_SUCCEEDED; - private int mParseError = PackageManager.INSTALL_SUCCEEDED; + public ThreadLocal<ApkParseUtils.ParseResult> mSharedResult + = ThreadLocal.withInitial(ApkParseUtils.ParseResult::new); - private static boolean sCompatibilityModeEnabled = true; - private static boolean sUseRoundIcon = false; + public static boolean sCompatibilityModeEnabled = true; + public static boolean sUseRoundIcon = false; - private static final int PARSE_DEFAULT_INSTALL_LOCATION = + public static final int PARSE_DEFAULT_INSTALL_LOCATION = PackageInfo.INSTALL_LOCATION_UNSPECIFIED; - private static final int PARSE_DEFAULT_TARGET_SANDBOX = 1; + public static final int PARSE_DEFAULT_TARGET_SANDBOX = 1; static class ParsePackageItemArgs { final Package owner; @@ -536,7 +546,7 @@ public class PackageParser { * the DTD. Otherwise, we try to get as much from the package as we * can without failing. This should normally be set to false, to * support extensions to the DTD in future versions. */ - private static final boolean RIGID_PARSER = false; + public static final boolean RIGID_PARSER = false; private static final String TAG = "PackageParser"; @@ -887,7 +897,7 @@ public class PackageParser { @Retention(RetentionPolicy.SOURCE) public @interface ParseFlags {} - private static final Comparator<String> sSplitNameComparator = new SplitNameComparator(); + public static final Comparator<String> sSplitNameComparator = new SplitNameComparator(); /** * Used to sort a set of APKs based on their split names, always placing the @@ -1033,7 +1043,7 @@ public class PackageParser { * and unique split names. * <p> * Note that this <em>does not</em> perform signature verification; that - * must be done separately in {@link #collectCertificates(Package, int)}. + * must be done separately in {@link ApkParseUtils#collectCertificates(AndroidPackage, boolean)}. * * If {@code useCaches} is true, the package parser might return a cached * result from a previous parse of the same {@code packageFile} with the same @@ -1041,21 +1051,54 @@ public class PackageParser { * has changed since the last parse, it's up to callers to do so. * * @see #parsePackageLite(File, int) + * @deprecated use {@link #parseParsedPackage(File, int, boolean)} */ @UnsupportedAppUsage + @Deprecated public Package parsePackage(File packageFile, int flags, boolean useCaches) throws PackageParserException { - Package parsed = useCaches ? getCachedResult(packageFile, flags) : null; + if (packageFile.isDirectory()) { + return parseClusterPackage(packageFile, flags); + } else { + return parseMonolithicPackage(packageFile, flags); + } + } + + /** + * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}. + * @deprecated use {@link #parseParsedPackage(File, int, boolean)} + */ + @UnsupportedAppUsage + @Deprecated + public Package parsePackage(File packageFile, int flags) throws PackageParserException { + return parsePackage(packageFile, flags, false /* useCaches */); + } + + /** + * Updated method which returns {@link ParsedPackage}, the current representation of a + * package parsed from disk. + * + * @see #parsePackage(File, int, boolean) + */ + public ParsedPackage parseParsedPackage(File packageFile, int flags, boolean useCaches) + throws PackageParserException { + ParsedPackage parsed = useCaches ? getCachedResult(packageFile, flags) : null; if (parsed != null) { return parsed; } long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0; - if (packageFile.isDirectory()) { - parsed = parseClusterPackage(packageFile, flags); - } else { - parsed = parseMonolithicPackage(packageFile, flags); - } + ApkParseUtils.ParseInput parseInput = mSharedResult.get().reset(); + parsed = ApkParseUtils.parsePackage( + parseInput, + mSeparateProcesses, + mCallback, + mMetrics, + mOnlyCoreApps, + packageFile, + flags + ) + .hideAsParsed(); long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0; cacheResult(packageFile, flags, parsed); @@ -1067,19 +1110,12 @@ public class PackageParser { + "ms, update_cache=" + cacheTime + " ms"); } } - return parsed; - } - /** - * Equivalent to {@link #parsePackage(File, int, boolean)} with {@code useCaches == false}. - */ - @UnsupportedAppUsage - public Package parsePackage(File packageFile, int flags) throws PackageParserException { - return parsePackage(packageFile, flags, false /* useCaches */); + return parsed; } /** - * Returns the cache key for a specificied {@code packageFile} and {@code flags}. + * Returns the cache key for a specified {@code packageFile} and {@code flags}. */ private String getCacheKey(File packageFile, int flags) { StringBuilder sb = new StringBuilder(packageFile.getName()); @@ -1090,13 +1126,13 @@ public class PackageParser { } @VisibleForTesting - protected Package fromCacheEntry(byte[] bytes) { + protected ParsedPackage fromCacheEntry(byte[] bytes) { return fromCacheEntryStatic(bytes); } /** static version of {@link #fromCacheEntry} for unit tests. */ @VisibleForTesting - public static Package fromCacheEntryStatic(byte[] bytes) { + public static ParsedPackage fromCacheEntryStatic(byte[] bytes) { final Parcel p = Parcel.obtain(); p.unmarshall(bytes, 0, bytes.length); p.setDataPosition(0); @@ -1104,7 +1140,8 @@ public class PackageParser { final ReadHelper helper = new ReadHelper(p); helper.startAndInstall(); - PackageParser.Package pkg = new PackageParser.Package(p); + // TODO(b/135203078): Hide PackageImpl constructor? + ParsedPackage pkg = new PackageImpl(p); p.recycle(); @@ -1114,14 +1151,14 @@ public class PackageParser { } @VisibleForTesting - protected byte[] toCacheEntry(Package pkg) { + protected byte[] toCacheEntry(ParsedPackage pkg) { return toCacheEntryStatic(pkg); } /** static version of {@link #toCacheEntry} for unit tests. */ @VisibleForTesting - public static byte[] toCacheEntryStatic(Package pkg) { + public static byte[] toCacheEntryStatic(ParsedPackage pkg) { final Parcel p = Parcel.obtain(); final WriteHelper helper = new WriteHelper(p); @@ -1170,7 +1207,7 @@ public class PackageParser { * Returns the cached parse result for {@code packageFile} for parse flags {@code flags}, * or {@code null} if no cached result exists. */ - private Package getCachedResult(File packageFile, int flags) { + public ParsedPackage getCachedResult(File packageFile, int flags) { if (mCacheDir == null) { return null; } @@ -1199,7 +1236,7 @@ public class PackageParser { /** * Caches the parse result for {@code packageFile} with flags {@code flags}. */ - private void cacheResult(File packageFile, int flags, Package parsed) { + public void cacheResult(File packageFile, int flags, ParsedPackage parsed) { if (mCacheDir == null) { return; } @@ -1238,7 +1275,8 @@ public class PackageParser { * split names. * <p> * Note that this <em>does not</em> perform signature verification; that - * must be done separately in {@link #collectCertificates(Package, int)}. + * must be done separately in + * {@link ApkParseUtils#collectCertificates(AndroidPackage, boolean)}. */ private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException { final PackageLite lite = parseClusterPackageLite(packageDir, 0); @@ -1302,10 +1340,11 @@ public class PackageParser { * Parse the given APK file, treating it as as a single monolithic package. * <p> * Note that this <em>does not</em> perform signature verification; that - * must be done separately in {@link #collectCertificates(Package, int)}. + * must be done separately in + * {@link ApkParseUtils#collectCertificates(AndroidPackage, boolean)}. * * @deprecated external callers should move to - * {@link #parsePackage(File, int)}. Eventually this method will + * {@link #parseParsedPackage(File, int, boolean)}. Eventually this method will * be marked private. */ @Deprecated @@ -1505,8 +1544,11 @@ public class PackageParser { * Collect certificates from all the APKs described in the given package, * populating {@link Package#mSigningDetails}. Also asserts that all APK * contents are signed correctly and consistently. + * + * @deprecated use {@link ApkParseUtils#collectCertificates(AndroidPackage, boolean)} */ @UnsupportedAppUsage + @Deprecated public static void collectCertificates(Package pkg, boolean skipVerify) throws PackageParserException { collectCertificatesInternal(pkg, skipVerify); @@ -1685,7 +1727,7 @@ public class PackageParser { ? null : "must have at least one '.' separator"; } - private static Pair<String, String> parsePackageSplitNames(XmlPullParser parser, + public static Pair<String, String> parsePackageSplitNames(XmlPullParser parser, AttributeSet attrs) throws IOException, XmlPullParserException, PackageParserException { @@ -2454,8 +2496,6 @@ public class PackageParser { mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; return null; - } else if (tagName.equals("queries")) { - parseQueries(pkg, res, parser, flags, outError); } else { Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName() + " at " + mArchiveSourcePath + " " @@ -2925,7 +2965,7 @@ public class PackageParser { return true; } - private static String buildClassName(String pkg, CharSequence clsSeq, + public static String buildClassName(String pkg, CharSequence clsSeq, String[] outError) { if (clsSeq == null || clsSeq.length() <= 0) { outError[0] = "Empty class name in package " + pkg; @@ -2973,7 +3013,7 @@ public class PackageParser { return proc; } - private static String buildProcessName(String pkg, String defProc, + public static String buildProcessName(String pkg, String defProc, CharSequence procSeq, int flags, String[] separateProcesses, String[] outError) { if ((flags&PARSE_IGNORE_PROCESSES) != 0 && !"system".equals(procSeq)) { @@ -2993,7 +3033,7 @@ public class PackageParser { return TextUtils.safeIntern(buildCompoundName(pkg, procSeq, "process", outError)); } - private static String buildTaskAffinityName(String pkg, String defProc, + public static String buildTaskAffinityName(String pkg, String defProc, CharSequence procSeq, String[] outError) { if (procSeq == null) { return defProc; @@ -3555,9 +3595,6 @@ public class PackageParser { owner.mRequiredAccountType = requiredAccountType; } - owner.mForceQueryable = - sa.getBoolean(R.styleable.AndroidManifestApplication_forceQueryable, false); - if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestApplication_debuggable, false)) { @@ -4019,89 +4056,6 @@ public class PackageParser { return true; } - private boolean parseQueries(Package owner, Resources res, XmlResourceParser parser, int flags, - String[] outError) - throws IOException, XmlPullParserException { - - final int outerDepth = parser.getDepth(); - int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG - || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { - continue; - } - if (parser.getName().equals("intent")) { - QueriesIntentInfo intentInfo = new QueriesIntentInfo(); - if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/, - intentInfo, outError)) { - return false; - } - - Uri data = null; - String dataType = null; - String host = ""; - final int numActions = intentInfo.countActions(); - final int numSchemes = intentInfo.countDataSchemes(); - final int numTypes = intentInfo.countDataTypes(); - final int numHosts = intentInfo.getHosts().length; - if ((numSchemes == 0 && numTypes == 0 && numActions == 0)) { - outError[0] = "intent tags must contain either an action or data."; - return false; - } - if (numActions > 1) { - outError[0] = "intent tag may have at most one action."; - return false; - } - if (numTypes > 1) { - outError[0] = "intent tag may have at most one data type."; - return false; - } - if (numSchemes > 1) { - outError[0] = "intent tag may have at most one data scheme."; - return false; - } - if (numHosts > 1) { - outError[0] = "intent tag may have at most one data host."; - return false; - } - Intent intent = new Intent(); - for (int i = 0, max = intentInfo.countCategories(); i < max; i++) { - intent.addCategory(intentInfo.getCategory(i)); - } - if (numHosts == 1) { - host = intentInfo.getHosts()[0]; - } - if (numSchemes == 1) { - data = new Uri.Builder() - .scheme(intentInfo.getDataScheme(0)) - .authority(host) - .build(); - } - if (numTypes == 1) { - dataType = intentInfo.getDataType(0); - } - intent.setDataAndType(data, dataType); - if (numActions == 1) { - intent.setAction(intentInfo.getAction(0)); - } - owner.mQueriesIntents = ArrayUtils.add(owner.mQueriesIntents, intent); - } else if (parser.getName().equals("package")) { - final TypedArray sa = res.obtainAttributes(parser, - com.android.internal.R.styleable.AndroidManifestQueriesPackage); - final String packageName = - sa.getString(R.styleable.AndroidManifestQueriesPackage_name); - if (TextUtils.isEmpty(packageName)) { - outError[0] = "Package name is missing from package tag."; - return false; - } - owner.mQueriesPackages = - ArrayUtils.add(owner.mQueriesPackages, packageName.intern()); - } - } - return true; - } - /** * Check if one of the IntentFilter as both actions DEFAULT / VIEW and a HTTP/HTTPS data URI */ @@ -5813,7 +5767,7 @@ public class PackageParser { return null; } - private static final String ANDROID_RESOURCES + public static final String ANDROID_RESOURCES = "http://schemas.android.com/apk/res/android"; private boolean parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs, @@ -6508,7 +6462,10 @@ public class PackageParser { /** * Representation of a full package parsed from APK files on disk. A package * consists of a single base APK, and zero or more split APKs. + * + * @deprecated use an {@link AndroidPackage} */ + @Deprecated public final static class Package implements Parcelable { @UnsupportedAppUsage @@ -6616,9 +6573,6 @@ public class PackageParser { // The major version code declared for this package. public int mVersionCodeMajor; - // Whether the package declares that it should be queryable by all normal apps on device. - public boolean mForceQueryable; - // Return long containing mVersionCode and mVersionCodeMajor. public long getLongVersionCode() { return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode); @@ -6724,9 +6678,6 @@ public class PackageParser { /** Whether or not the package is a stub and must be replaced by the full version. */ public boolean isStub; - public ArrayList<String> mQueriesPackages; - public ArrayList<Intent> mQueriesIntents; - @UnsupportedAppUsage public Package(String packageName) { this.packageName = packageName; @@ -7230,9 +7181,6 @@ public class PackageParser { use32bitAbi = (dest.readInt() == 1); restrictUpdateHash = dest.createByteArray(); visibleToInstantApps = dest.readInt() == 1; - mForceQueryable = dest.readBoolean(); - mQueriesIntents = dest.createTypedArrayList(Intent.CREATOR); - mQueriesPackages = dest.createStringArrayList(); } private static void internStringArrayList(List<String> list) { @@ -7248,7 +7196,7 @@ public class PackageParser { * Sets the package owner and the the {@code applicationInfo} for every component * owner by this package. */ - private void fixupOwner(List<? extends Component<?>> list) { + public void fixupOwner(List<? extends Component<?>> list) { if (list != null) { for (Component<?> c : list) { c.owner = this; @@ -7358,12 +7306,8 @@ public class PackageParser { dest.writeInt(use32bitAbi ? 1 : 0); dest.writeByteArray(restrictUpdateHash); dest.writeInt(visibleToInstantApps ? 1 : 0); - dest.writeBoolean(mForceQueryable); - dest.writeTypedList(mQueriesIntents); - dest.writeList(mQueriesPackages); } - /** * Writes the keyset mapping to the provided package. {@code null} mappings are permitted. */ @@ -7435,6 +7379,10 @@ public class PackageParser { }; } + /** + * @deprecated use a {@link ComponentParseUtils.ParsedComponent} + */ + @Deprecated public static abstract class Component<II extends IntentInfo> { @UnsupportedAppUsage public final ArrayList<II> intents; @@ -7615,6 +7563,10 @@ public class PackageParser { } } + /** + * @deprecated use {@link ComponentParseUtils.ParsedPermission} + */ + @Deprecated public final static class Permission extends Component<IntentInfo> implements Parcelable { @UnsupportedAppUsage public final PermissionInfo info; @@ -7689,6 +7641,10 @@ public class PackageParser { }; } + /** + * @deprecated use {@link ComponentParseUtils.ParsedPermissionGroup} + */ + @Deprecated public final static class PermissionGroup extends Component<IntentInfo> implements Parcelable { @UnsupportedAppUsage public final PermissionGroupInfo info; @@ -7788,7 +7744,12 @@ public class PackageParser { return false; } + /** + * @deprecated use {@link PackageInfoUtils#generateApplicationInfo( + * AndroidPackage, int, PackageUserState, int)} + */ @UnsupportedAppUsage + @Deprecated public static ApplicationInfo generateApplicationInfo(Package p, int flags, PackageUserState state) { return generateApplicationInfo(p, flags, state, UserHandle.getCallingUserId()); @@ -7845,7 +7806,12 @@ public class PackageParser { ai.icon = (sUseRoundIcon && ai.roundIconRes != 0) ? ai.roundIconRes : ai.iconRes; } + /** + * @deprecated use {@link PackageInfoUtils#generateApplicationInfo( + * AndroidPackage, int, PackageUserState, int)} + */ @UnsupportedAppUsage + @Deprecated public static ApplicationInfo generateApplicationInfo(Package p, int flags, PackageUserState state, int userId) { if (p == null) return null; @@ -7885,6 +7851,11 @@ public class PackageParser { return ai; } + /** + * @deprecated use {@link PackageInfoUtils#generateApplicationInfo( + * AndroidPackage, int, PackageUserState, int)} + */ + @Deprecated public static ApplicationInfo generateApplicationInfo(ApplicationInfo ai, int flags, PackageUserState state, int userId) { if (ai == null) return null; @@ -7904,7 +7875,12 @@ public class PackageParser { return ai; } + /** + * @deprecated use {@link PackageInfoUtils#generatePermissionInfo( + * ComponentParseUtils.ParsedPermission, int)} + */ @UnsupportedAppUsage + @Deprecated public static final PermissionInfo generatePermissionInfo( Permission p, int flags) { if (p == null) return null; @@ -7916,7 +7892,12 @@ public class PackageParser { return pi; } + /** + * @deprecated use {@link PackageInfoUtils#generatePermissionGroupInfo( + * ComponentParseUtils.ParsedPermissionGroup, int)} + */ @UnsupportedAppUsage + @Deprecated public static final PermissionGroupInfo generatePermissionGroupInfo( PermissionGroup pg, int flags) { if (pg == null) return null; @@ -7928,6 +7909,10 @@ public class PackageParser { return pgi; } + /** + * @deprecated use {@link ComponentParseUtils.ParsedActivity} + */ + @Deprecated public final static class Activity extends Component<ActivityIntentInfo> implements Parcelable { @UnsupportedAppUsage public final ActivityInfo info; @@ -8043,7 +8028,12 @@ public class PackageParser { }; } + /** + * @deprecated use {@link PackageInfoUtils#generateActivityInfo( + * AndroidPackage, ComponentParseUtils.ParsedActivity, int, PackageUserState, int)} + */ @UnsupportedAppUsage + @Deprecated public static final ActivityInfo generateActivityInfo(Activity a, int flags, PackageUserState state, int userId) { if (a == null) return null; @@ -8061,6 +8051,11 @@ public class PackageParser { return ai; } + /** + * @deprecated use {@link PackageInfoUtils#generateActivityInfo( + * AndroidPackage, ComponentParseUtils.ParsedActivity, int, PackageUserState, int)} + */ + @Deprecated public static final ActivityInfo generateActivityInfo(ActivityInfo ai, int flags, PackageUserState state, int userId) { if (ai == null) return null; @@ -8074,6 +8069,10 @@ public class PackageParser { return ai; } + /** + * @deprecated use {@link ComponentParseUtils.ParsedService} + */ + @Deprecated public final static class Service extends Component<ServiceIntentInfo> implements Parcelable { @UnsupportedAppUsage public final ServiceInfo info; @@ -8135,7 +8134,12 @@ public class PackageParser { }; } + /** + * @deprecated use {@link PackageInfoUtils#generateServiceInfo( + * AndroidPackage, ComponentParseUtils.ParsedService, int, PackageUserState, int)} + */ @UnsupportedAppUsage + @Deprecated public static final ServiceInfo generateServiceInfo(Service s, int flags, PackageUserState state, int userId) { if (s == null) return null; @@ -8153,6 +8157,10 @@ public class PackageParser { return si; } + /** + * @deprecated use {@link ComponentParseUtils.ParsedProvider} + */ + @Deprecated public final static class Provider extends Component<ProviderIntentInfo> implements Parcelable { @UnsupportedAppUsage public final ProviderInfo info; @@ -8233,7 +8241,12 @@ public class PackageParser { }; } + /** + * @deprecated use {@link PackageInfoUtils#generateProviderInfo( + * AndroidPackage, ComponentParseUtils.ParsedProvider, int, PackageUserState, int)} + */ @UnsupportedAppUsage + @Deprecated public static final ProviderInfo generateProviderInfo(Provider p, int flags, PackageUserState state, int userId) { if (p == null) return null; @@ -8256,6 +8269,10 @@ public class PackageParser { return pi; } + /** + * @deprecated use {@link ComponentParseUtils.ParsedInstrumentation} + */ + @Deprecated public final static class Instrumentation extends Component<IntentInfo> implements Parcelable { @UnsupportedAppUsage @@ -8316,7 +8333,12 @@ public class PackageParser { }; } + /** + * @deprecated use {@link PackageInfoUtils#generateInstrumentationInfo( + * ComponentParseUtils.ParsedInstrumentation, int)} + */ @UnsupportedAppUsage + @Deprecated public static final InstrumentationInfo generateInstrumentationInfo( Instrumentation i, int flags) { if (i == null) return null; @@ -8328,6 +8350,10 @@ public class PackageParser { return ii; } + /** + * @deprecated use {@link ComponentParseUtils.ParsedIntentInfo} + */ + @Deprecated public static abstract class IntentInfo extends IntentFilter { @UnsupportedAppUsage public boolean hasDefault; @@ -8371,8 +8397,10 @@ public class PackageParser { } } - public static final class QueriesIntentInfo extends IntentInfo {} - + /** + * @deprecated use {@link ComponentParseUtils.ParsedActivityIntentInfo} + */ + @Deprecated public final static class ActivityIntentInfo extends IntentInfo { @UnsupportedAppUsage public Activity activity; @@ -8396,6 +8424,10 @@ public class PackageParser { } } + /** + * @deprecated use {@link ComponentParseUtils.ParsedServiceIntentInfo} + */ + @Deprecated public final static class ServiceIntentInfo extends IntentInfo { @UnsupportedAppUsage public Service service; @@ -8419,6 +8451,10 @@ public class PackageParser { } } + /** + * @deprecated use {@link ComponentParseUtils.ParsedProviderIntentInfo} + */ + @Deprecated public static final class ProviderIntentInfo extends IntentInfo { @UnsupportedAppUsage public Provider provider; diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java index 5c74efb8ff1b..55574c3cb880 100644 --- a/core/java/android/content/pm/PackageUserState.java +++ b/core/java/android/content/pm/PackageUserState.java @@ -28,6 +28,7 @@ import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPON import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; import android.annotation.UnsupportedAppUsage; +import android.content.pm.parsing.ComponentParseUtils; import android.os.BaseBundle; import android.os.Debug; import android.os.PersistableBundle; @@ -127,6 +128,18 @@ public class PackageUserState { && (!this.hidden || matchUninstalled)); } + public boolean isMatch(ComponentInfo componentInfo, int flags) { + return isMatch(componentInfo.applicationInfo.isSystemApp(), + componentInfo.applicationInfo.enabled, componentInfo.enabled, + componentInfo.directBootAware, componentInfo.name, flags); + } + + public boolean isMatch(boolean isSystem, boolean isPackageEnabled, + ComponentParseUtils.ParsedComponent component, int flags) { + return isMatch(isSystem, isPackageEnabled, component.isEnabled(), + component.isDirectBootAware(), component.getName(), flags); + } + /** * Test if the given component is considered installed, enabled and a match * for the given flags. @@ -135,28 +148,33 @@ public class PackageUserState { * Expects at least one of {@link PackageManager#MATCH_DIRECT_BOOT_AWARE} and * {@link PackageManager#MATCH_DIRECT_BOOT_UNAWARE} are specified in {@code flags}. * </p> + * */ - public boolean isMatch(ComponentInfo componentInfo, int flags) { - final boolean isSystemApp = componentInfo.applicationInfo.isSystemApp(); + public boolean isMatch(boolean isSystem, boolean isPackageEnabled, boolean isComponentEnabled, + boolean isComponentDirectBootAware, String componentName, int flags) { final boolean matchUninstalled = (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0; - if (!isAvailable(flags) - && !(isSystemApp && matchUninstalled)) return reportIfDebug(false, flags); - if (!isEnabled(componentInfo, flags)) return reportIfDebug(false, flags); + if (!isAvailable(flags) && !(isSystem && matchUninstalled)) { + return reportIfDebug(false, flags); + } + + if (!isEnabled(isPackageEnabled, isComponentEnabled, componentName, flags)) { + return reportIfDebug(false, flags); + } if ((flags & MATCH_SYSTEM_ONLY) != 0) { - if (!isSystemApp) { + if (!isSystem) { return reportIfDebug(false, flags); } } final boolean matchesUnaware = ((flags & MATCH_DIRECT_BOOT_UNAWARE) != 0) - && !componentInfo.directBootAware; + && !isComponentDirectBootAware; final boolean matchesAware = ((flags & MATCH_DIRECT_BOOT_AWARE) != 0) - && componentInfo.directBootAware; + && isComponentDirectBootAware; return reportIfDebug(matchesUnaware || matchesAware, flags); } - private boolean reportIfDebug(boolean result, int flags) { + public boolean reportIfDebug(boolean result, int flags) { if (DEBUG && !result) { Slog.i(LOG_TAG, "No match!; flags: " + DebugUtils.flagsToString(PackageManager.class, "MATCH_", flags) + " " @@ -165,10 +183,22 @@ public class PackageUserState { return result; } + public boolean isEnabled(ComponentInfo componentInfo, int flags) { + return isEnabled(componentInfo.applicationInfo.enabled, componentInfo.enabled, + componentInfo.name, flags); + } + + public boolean isEnabled(boolean isPackageEnabled, + ComponentParseUtils.ParsedComponent parsedComponent, int flags) { + return isEnabled(isPackageEnabled, parsedComponent.isEnabled(), parsedComponent.getName(), + flags); + } + /** * Test if the given component is considered enabled. */ - public boolean isEnabled(ComponentInfo componentInfo, int flags) { + public boolean isEnabled(boolean isPackageEnabled, boolean isComponentEnabled, + String componentName, int flags) { if ((flags & MATCH_DISABLED_COMPONENTS) != 0) { return true; } @@ -183,24 +213,26 @@ public class PackageUserState { if ((flags & MATCH_DISABLED_UNTIL_USED_COMPONENTS) == 0) { return false; } + // fallthrough case COMPONENT_ENABLED_STATE_DEFAULT: - if (!componentInfo.applicationInfo.enabled) { + if (!isPackageEnabled) { return false; } + // fallthrough case COMPONENT_ENABLED_STATE_ENABLED: break; } // Check if component has explicit state before falling through to // the manifest default - if (ArrayUtils.contains(this.enabledComponents, componentInfo.name)) { + if (ArrayUtils.contains(this.enabledComponents, componentName)) { return true; } - if (ArrayUtils.contains(this.disabledComponents, componentInfo.name)) { + if (ArrayUtils.contains(this.disabledComponents, componentName)) { return false; } - return componentInfo.enabled; + return isComponentEnabled; } @Override diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java index 3488cc30892c..2863b268e795 100644 --- a/core/java/android/content/pm/SharedLibraryInfo.java +++ b/core/java/android/content/pm/SharedLibraryInfo.java @@ -20,6 +20,7 @@ import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.pm.parsing.AndroidPackage; import android.os.Parcel; import android.os.Parcelable; @@ -38,20 +39,24 @@ import java.util.List; public final class SharedLibraryInfo implements Parcelable { /** @hide */ - public static SharedLibraryInfo createForStatic(PackageParser.Package pkg) { - return new SharedLibraryInfo(null, pkg.packageName, pkg.getAllCodePaths(), - pkg.staticSharedLibName, - pkg.staticSharedLibVersion, + public static SharedLibraryInfo createForStatic(AndroidPackage pkg) { + return new SharedLibraryInfo(null, pkg.getPackageName(), + pkg.makeListAllCodePaths(), + pkg.getStaticSharedLibName(), + pkg.getStaticSharedLibVersion(), TYPE_STATIC, - new VersionedPackage(pkg.manifestPackageName, pkg.getLongVersionCode()), + new VersionedPackage(pkg.getManifestPackageName(), + pkg.getLongVersionCode()), null, null); } /** @hide */ - public static SharedLibraryInfo createForDynamic(PackageParser.Package pkg, String name) { - return new SharedLibraryInfo(null, pkg.packageName, pkg.getAllCodePaths(), name, + public static SharedLibraryInfo createForDynamic(AndroidPackage pkg, String name) { + return new SharedLibraryInfo(null, pkg.getPackageName(), + pkg.makeListAllCodePaths(), name, (long) VERSION_UNDEFINED, - TYPE_DYNAMIC, new VersionedPackage(pkg.packageName, pkg.getLongVersionCode()), + TYPE_DYNAMIC, new VersionedPackage(pkg.getPackageName(), + pkg.getLongVersionCode()), null, null); } diff --git a/core/java/android/content/pm/dex/DexMetadataHelper.java b/core/java/android/content/pm/dex/DexMetadataHelper.java index 5d10b8826b00..4cd201fbe538 100644 --- a/core/java/android/content/pm/dex/DexMetadataHelper.java +++ b/core/java/android/content/pm/dex/DexMetadataHelper.java @@ -22,6 +22,7 @@ import static android.content.pm.PackageParser.APK_FILE_EXTENSION; import android.content.pm.PackageParser; import android.content.pm.PackageParser.PackageLite; import android.content.pm.PackageParser.PackageParserException; +import android.content.pm.parsing.AndroidPackage; import android.util.ArrayMap; import android.util.jar.StrictJarFile; @@ -86,8 +87,8 @@ public class DexMetadataHelper { * * NOTE: involves I/O checks. */ - public static Map<String, String> getPackageDexMetadata(PackageParser.Package pkg) { - return buildPackageApkToDexMetadataMap(pkg.getAllCodePaths()); + public static Map<String, String> getPackageDexMetadata(AndroidPackage pkg) { + return buildPackageApkToDexMetadataMap(pkg.makeListAllCodePaths()); } /** @@ -160,7 +161,7 @@ public class DexMetadataHelper { * * @throws PackageParserException in case of errors. */ - public static void validatePackageDexMetadata(PackageParser.Package pkg) + public static void validatePackageDexMetadata(AndroidPackage pkg) throws PackageParserException { Collection<String> apkToDexMetadataList = getPackageDexMetadata(pkg).values(); for (String dexMetadata : apkToDexMetadataList) { diff --git a/core/java/android/content/pm/parsing/AndroidPackage.aidl b/core/java/android/content/pm/parsing/AndroidPackage.aidl new file mode 100644 index 000000000000..ab3cf7cb8c65 --- /dev/null +++ b/core/java/android/content/pm/parsing/AndroidPackage.aidl @@ -0,0 +1,21 @@ +/* +** +** Copyright 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; + +/* @hide */ +parcelable AndroidPackage; diff --git a/core/java/android/content/pm/parsing/AndroidPackage.java b/core/java/android/content/pm/parsing/AndroidPackage.java new file mode 100644 index 000000000000..bef984df4c10 --- /dev/null +++ b/core/java/android/content/pm/parsing/AndroidPackage.java @@ -0,0 +1,468 @@ +/* + * 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 android.annotation.Nullable; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.ConfigurationInfo; +import android.content.pm.FeatureGroupInfo; +import android.content.pm.FeatureInfo; +import android.content.pm.PackageParser; +import android.content.pm.SharedLibraryInfo; +import android.content.pm.parsing.ComponentParseUtils.ParsedActivity; +import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo; +import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation; +import android.content.pm.parsing.ComponentParseUtils.ParsedPermission; +import android.content.pm.parsing.ComponentParseUtils.ParsedPermissionGroup; +import android.content.pm.parsing.ComponentParseUtils.ParsedProvider; +import android.content.pm.parsing.ComponentParseUtils.ParsedService; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.ArraySet; +import android.util.SparseArray; + +import java.security.PublicKey; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +/** + * The last state of a package during parsing/install before it is available in + * {@link com.android.server.pm.PackageManagerService#mPackages}. + * + * It is the responsibility of the caller to understand what data is available at what step of the + * parsing or install process. + * + * TODO(b/135203078): Nullability annotations + * TODO(b/135203078): Remove get/setAppInfo differences + * + * @hide + */ +public interface AndroidPackage extends Parcelable { + + /** + * This will eventually be removed. Avoid calling this at all costs. + */ + @Deprecated + AndroidPackageWrite mutate(); + + boolean canHaveOatDir(); + + boolean cantSaveState(); + + List<String> getAdoptPermissions(); + + List<String> getAllCodePaths(); + + List<String> getAllCodePathsExcludingResourceOnly(); + + String getAppComponentFactory(); + + /** + * TODO(b/135203078): Use non-AppInfo method + * @deprecated use {@link #getClassLoaderName()} + */ + @Deprecated + String getAppInfoClassLoaderName(); + + /** + * TODO(b/135203078): Use non-AppInfo method + * @deprecated use {@link #getCodePath()} + */ + @Deprecated + String getAppInfoCodePath(); + + /** + * TODO(b/135203078): Use non-AppInfo method + * @deprecated use {@link #getName()} + */ + @Deprecated + String getAppInfoName(); + + /** + * TODO(b/135203078): Use non-AppInfo method + * @deprecated use {@link #getPackageName()} + */ + @Deprecated + String getAppInfoPackageName(); + + /** + * TODO(b/135203078): Use non-AppInfo method + * @deprecated use {@link #getProcessName()} + */ + @Deprecated + String getAppInfoProcessName(); + + /** + * TODO(b/135203078): Use non-AppInfo method + * @deprecated use {@link #getCodePath()} + */ + @Deprecated + String getAppInfoResourcePath(); + + Bundle getAppMetaData(); + + /** + * TODO(b/135203078): Use non-AppInfo method + * @deprecated use {@link #getVolumeUuid()} + */ + @Deprecated + String getApplicationInfoVolumeUuid(); + + String getBackupAgentName(); + + int getBanner(); + + String getBaseCodePath(); + + int getBaseRevisionCode(); + + int getCategory(); + + String getClassLoaderName(); + + String getClassName(); + + String getCodePath(); + + int getCompatibleWidthLimitDp(); + + int getCompileSdkVersion(); + + String getCompileSdkVersionCodeName(); + + @Nullable + List<ConfigurationInfo> getConfigPreferences(); + + String getCpuAbiOverride(); + + String getCredentialProtectedDataDir(); + + String getDataDir(); + + int getDescriptionRes(); + + String getDeviceProtectedDataDir(); + + List<FeatureGroupInfo> getFeatureGroups(); + + int getFlags(); + + int getFullBackupContent(); + + int getHiddenApiEnforcementPolicy(); + + int getIcon(); + + int getIconRes(); + + List<String> getImplicitPermissions(); + + int getInstallLocation(); + + Map<String, ArraySet<PublicKey>> getKeySetMapping(); + + int getLabelRes(); + + int getLargestWidthLimitDp(); + + long[] getLastPackageUsageTimeInMills(); + + long getLatestForegroundPackageUseTimeInMills(); + + long getLatestPackageUseTimeInMills(); + + List<String> getLibraryNames(); + + int getLogo(); + + long getLongVersionCode(); + + String getManageSpaceActivityName(); + + String getManifestPackageName(); + + float getMaxAspectRatio(); + + Bundle getMetaData(); // TODO(b/135203078): Make all the Bundles immutable + + float getMinAspectRatio(); + + int getMinSdkVersion(); + + String getName(); + + String getNativeLibraryDir(); + + String getNativeLibraryRootDir(); + + int getNetworkSecurityConfigRes(); + + CharSequence getNonLocalizedLabel(); + + @Nullable + List<String> getOriginalPackages(); + + String getOverlayCategory(); + + int getOverlayPriority(); + + String getOverlayTarget(); + + String getOverlayTargetName(); + + // TODO(b/135203078): Does this and getAppInfoPackageName have to be separate methods? + // The refactor makes them the same value with no known consequences, so should be redundant. + String getPackageName(); + + @Nullable + List<ParsedActivity> getActivities(); + + @Nullable + List<ParsedInstrumentation> getInstrumentations(); + + @Nullable + List<ParsedPermissionGroup> getPermissionGroups(); + + @Nullable + List<ParsedPermission> getPermissions(); + + @Nullable + List<ParsedProvider> getProviders(); + + @Nullable + List<ParsedActivity> getReceivers(); + + @Nullable + List<ParsedService> getServices(); + + String getPermission(); + + @Nullable + List<ParsedActivityIntentInfo> getPreferredActivityFilters(); + + int getPreferredOrder(); + + String getPrimaryCpuAbi(); + + int getPrivateFlags(); + + String getProcessName(); + + @Nullable + List<String> getProtectedBroadcasts(); + + String getPublicSourceDir(); + + List<Intent> getQueriesIntents(); + + List<String> getQueriesPackages(); + + String getRealPackage(); + + // TODO(b/135203078): Rename to getRequiredFeatures? Somewhat ambigious whether "Req" is + // required or requested. + @Nullable + List<FeatureInfo> getReqFeatures(); + + List<String> getRequestedPermissions(); + + String getRequiredAccountType(); + + int getRequiresSmallestWidthDp(); + + byte[] getRestrictUpdateHash(); + + String getRestrictedAccountType(); + + int getRoundIconRes(); + + String getScanPublicSourceDir(); + + String getScanSourceDir(); + + String getSeInfo(); + + String getSeInfoUser(); + + String getSecondaryCpuAbi(); + + String getSecondaryNativeLibraryDir(); + + String getSharedUserId(); + + int getSharedUserLabel(); + + PackageParser.SigningDetails getSigningDetails(); + + String[] getSplitClassLoaderNames(); + + @Nullable + String[] getSplitCodePaths(); + + @Nullable + SparseArray<int[]> getSplitDependencies(); + + int[] getSplitFlags(); + + String[] getSplitNames(); + + String[] getSplitPublicSourceDirs(); + + int[] getSplitRevisionCodes(); + + String getStaticSharedLibName(); + + long getStaticSharedLibVersion(); + + // TODO(b/135203078): Return String directly + UUID getStorageUuid(); + + int getTargetSandboxVersion(); + + int getTargetSdkVersion(); + + String getTaskAffinity(); + + int getTheme(); + + int getUiOptions(); + + int getUid(); + + Set<String> getUpgradeKeySets(); + + @Nullable + List<String> getUsesLibraries(); + + @Nullable + String[] getUsesLibraryFiles(); + + List<SharedLibraryInfo> getUsesLibraryInfos(); + + @Nullable + List<String> getUsesOptionalLibraries(); + + @Nullable + List<String> getUsesStaticLibraries(); + + @Nullable + String[][] getUsesStaticLibrariesCertDigests(); + + @Nullable + long[] getUsesStaticLibrariesVersions(); + + int getVersionCode(); + + int getVersionCodeMajor(); + + String getVersionName(); + + String getVolumeUuid(); + + String getZygotePreloadName(); + + boolean hasComponentClassName(String className); + + // App Info + + boolean hasRequestedLegacyExternalStorage(); + + boolean isBaseHardwareAccelerated(); + + boolean isCoreApp(); + + boolean isDefaultToDeviceProtectedStorage(); + + boolean isDirectBootAware(); + + boolean isEmbeddedDexUsed(); + + boolean isEnabled(); + + boolean isEncryptionAware(); + + boolean isExternal(); + + boolean isForceQueryable(); + + boolean isForwardLocked(); + + boolean isHiddenUntilInstalled(); + + boolean isInstantApp(); + + boolean isInternal(); + + boolean isLibrary(); + + // TODO(b/135203078): Should probably be in a utility class + boolean isMatch(int flags); + + boolean isNativeLibraryRootRequiresIsa(); + + boolean isOem(); + + boolean isOverlayIsStatic(); + + boolean isPrivileged(); + + boolean isProduct(); + + boolean isProfileableByShell(); + + boolean isRequiredForAllUsers(); + + boolean isStaticSharedLibrary(); + + boolean isStub(); + + boolean isSystem(); // TODO(b/135203078): Collapse with isSystemApp, should be exactly the same. + + boolean isSystemApp(); + + boolean isSystemExt(); + + boolean isUpdatedSystemApp(); + + boolean isUse32BitAbi(); + + boolean isVendor(); + + boolean isVisibleToInstantApps(); + + List<String> makeListAllCodePaths(); // TODO(b/135203078): Collapse with getAllCodePaths + + boolean requestsIsolatedSplitLoading(); + + ApplicationInfo toAppInfo(); + + Creator<PackageImpl> CREATOR = new Creator<PackageImpl>() { + @Override + public PackageImpl createFromParcel(Parcel source) { + return new PackageImpl(source); + } + + @Override + public PackageImpl[] newArray(int size) { + return new PackageImpl[size]; + } + }; +} diff --git a/core/java/android/content/pm/parsing/AndroidPackageWrite.java b/core/java/android/content/pm/parsing/AndroidPackageWrite.java new file mode 100644 index 000000000000..b7595d2dd710 --- /dev/null +++ b/core/java/android/content/pm/parsing/AndroidPackageWrite.java @@ -0,0 +1,59 @@ +/* + * 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 android.annotation.Nullable; +import android.content.pm.PackageParser; +import android.content.pm.SharedLibraryInfo; + +import java.util.List; + +/** + * Contains remaining mutable fields after package parsing has completed. + * + * Most are state that can probably be tracked outside of the AndroidPackage object. New methods + * should never be added to this interface. + * + * TODO(b/135203078): Remove entirely + * + * @deprecated the eventual goal is that the object returned from parsing represents exactly what + * was parsed from the APK, and so further mutation should be disallowed, + * with any state being stored in another class + * + * @hide + */ +@Deprecated +public interface AndroidPackageWrite extends AndroidPackage { + + AndroidPackageWrite setUsesLibraryFiles(@Nullable String[] usesLibraryFiles); + + // TODO(b/135203078): Remove or use a non-system wide representation of the shared libraries; + // this doesn't represent what was parsed from the APK + AndroidPackageWrite setUsesLibraryInfos(@Nullable List<SharedLibraryInfo> usesLibraryInfos); + + AndroidPackageWrite setHiddenUntilInstalled(boolean hidden); + + AndroidPackageWrite setUpdatedSystemApp(boolean updatedSystemApp); + + AndroidPackageWrite setLastPackageUsageTimeInMills(int reason, long time); + + AndroidPackageWrite setPrimaryCpuAbi(String primaryCpuAbi); + + AndroidPackageWrite setSeInfo(String seInfo); + + AndroidPackageWrite setSigningDetails(PackageParser.SigningDetails signingDetails); +} diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java new file mode 100644 index 000000000000..ac2e373f000d --- /dev/null +++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java @@ -0,0 +1,428 @@ +/* + * 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.os.Trace.TRACE_TAG_PACKAGE_MANAGER; + +import android.annotation.UnsupportedAppUsage; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageParser; +import android.content.pm.VerifierInfo; +import android.content.res.ApkAssets; +import android.content.res.XmlResourceParser; +import android.os.Trace; +import android.util.ArrayMap; +import android.util.AttributeSet; +import android.util.Pair; +import android.util.Slog; + +import com.android.internal.R; +import com.android.internal.util.ArrayUtils; + +import libcore.io.IoUtils; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.File; +import java.io.FileDescriptor; +import java.io.IOException; +import java.security.PublicKey; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** @hide */ +public class ApkLiteParseUtils { + + private static final String TAG = ApkParseUtils.TAG; + + // TODO(b/135203078): Consolidate constants + private static final int DEFAULT_MIN_SDK_VERSION = 1; + private static final int DEFAULT_TARGET_SDK_VERSION = 0; + + private static final int PARSE_DEFAULT_INSTALL_LOCATION = + PackageInfo.INSTALL_LOCATION_UNSPECIFIED; + + /** + * Parse only lightweight details about the package at the given location. + * Automatically detects if the package is a monolithic style (single APK + * file) or cluster style (directory of APKs). + * <p> + * This performs sanity checking on cluster style packages, such as + * requiring identical package name and version codes, a single base APK, + * and unique split names. + * + * @see PackageParser#parsePackage(File, int) + */ + @UnsupportedAppUsage + public static PackageParser.PackageLite parsePackageLite(File packageFile, int flags) + throws PackageParser.PackageParserException { + if (packageFile.isDirectory()) { + return parseClusterPackageLite(packageFile, flags); + } else { + return parseMonolithicPackageLite(packageFile, flags); + } + } + + public static PackageParser.PackageLite parseMonolithicPackageLite(File packageFile, int flags) + throws PackageParser.PackageParserException { + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite"); + final PackageParser.ApkLite baseApk = parseApkLite(packageFile, flags); + final String packagePath = packageFile.getAbsolutePath(); + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); + return new PackageParser.PackageLite(packagePath, baseApk, null, null, null, null, + null, null); + } + + public static PackageParser.PackageLite parseClusterPackageLite(File packageDir, int flags) + throws PackageParser.PackageParserException { + final File[] files = packageDir.listFiles(); + if (ArrayUtils.isEmpty(files)) { + throw new PackageParser.PackageParserException( + PackageManager.INSTALL_PARSE_FAILED_NOT_APK, "No packages found in split"); + } + + String packageName = null; + int versionCode = 0; + + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite"); + final ArrayMap<String, PackageParser.ApkLite> apks = new ArrayMap<>(); + for (File file : files) { + if (PackageParser.isApkFile(file)) { + final PackageParser.ApkLite lite = parseApkLite(file, flags); + + // Assert that all package names and version codes are + // consistent with the first one we encounter. + if (packageName == null) { + packageName = lite.packageName; + versionCode = lite.versionCode; + } else { + if (!packageName.equals(lite.packageName)) { + throw new PackageParser.PackageParserException( + PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST, + "Inconsistent package " + lite.packageName + " in " + file + + "; expected " + packageName); + } + if (versionCode != lite.versionCode) { + throw new PackageParser.PackageParserException( + PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST, + "Inconsistent version " + lite.versionCode + " in " + file + + "; expected " + versionCode); + } + } + + // Assert that each split is defined only oncuses-static-libe + if (apks.put(lite.splitName, lite) != null) { + throw new PackageParser.PackageParserException( + PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST, + "Split name " + lite.splitName + + " defined more than once; most recent was " + file); + } + } + } + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); + + final PackageParser.ApkLite baseApk = apks.remove(null); + if (baseApk == null) { + throw new PackageParser.PackageParserException( + PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST, + "Missing base APK in " + packageDir); + } + + // Always apply deterministic ordering based on splitName + final int size = apks.size(); + + String[] splitNames = null; + boolean[] isFeatureSplits = null; + String[] usesSplitNames = null; + String[] configForSplits = null; + String[] splitCodePaths = null; + int[] splitRevisionCodes = null; + if (size > 0) { + splitNames = new String[size]; + isFeatureSplits = new boolean[size]; + usesSplitNames = new String[size]; + configForSplits = new String[size]; + splitCodePaths = new String[size]; + splitRevisionCodes = new int[size]; + + splitNames = apks.keySet().toArray(splitNames); + Arrays.sort(splitNames, PackageParser.sSplitNameComparator); + + for (int i = 0; i < size; i++) { + final PackageParser.ApkLite apk = apks.get(splitNames[i]); + usesSplitNames[i] = apk.usesSplitName; + isFeatureSplits[i] = apk.isFeatureSplit; + configForSplits[i] = apk.configForSplit; + splitCodePaths[i] = apk.codePath; + splitRevisionCodes[i] = apk.revisionCode; + } + } + + final String codePath = packageDir.getAbsolutePath(); + return new PackageParser.PackageLite(codePath, baseApk, splitNames, isFeatureSplits, + usesSplitNames, configForSplits, splitCodePaths, splitRevisionCodes); + } + + /** + * Utility method that retrieves lightweight details about a single APK + * file, including package name, split name, and install location. + * + * @param apkFile path to a single APK + * @param flags optional parse flags, such as + * {@link PackageParser#PARSE_COLLECT_CERTIFICATES} + */ + public static PackageParser.ApkLite parseApkLite(File apkFile, int flags) + throws PackageParser.PackageParserException { + return parseApkLiteInner(apkFile, null, null, flags); + } + + /** + * Utility method that retrieves lightweight details about a single APK + * file, including package name, split name, and install location. + * + * @param fd already open file descriptor of an apk file + * @param debugPathName arbitrary text name for this file, for debug output + * @param flags optional parse flags, such as + * {@link PackageParser#PARSE_COLLECT_CERTIFICATES} + */ + public static PackageParser.ApkLite parseApkLite(FileDescriptor fd, String debugPathName, + int flags) throws PackageParser.PackageParserException { + return parseApkLiteInner(null, fd, debugPathName, flags); + } + + private static PackageParser.ApkLite parseApkLiteInner(File apkFile, FileDescriptor fd, + String debugPathName, int flags) throws PackageParser.PackageParserException { + final String apkPath = fd != null ? debugPathName : apkFile.getAbsolutePath(); + + XmlResourceParser parser = null; + ApkAssets apkAssets = null; + try { + try { + apkAssets = fd != null + ? ApkAssets.loadFromFd(fd, debugPathName, false, false) + : ApkAssets.loadFromPath(apkPath); + } catch (IOException e) { + throw new PackageParser.PackageParserException( + PackageManager.INSTALL_PARSE_FAILED_NOT_APK, + "Failed to parse " + apkPath, e); + } + + parser = apkAssets.openXml(PackageParser.ANDROID_MANIFEST_FILENAME); + + final PackageParser.SigningDetails signingDetails; + if ((flags & PackageParser.PARSE_COLLECT_CERTIFICATES) != 0) { + final boolean skipVerify = (flags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0; + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates"); + try { + signingDetails = + ApkParseUtils.collectCertificates(apkFile.getAbsolutePath(), skipVerify, + false, PackageParser.SigningDetails.UNKNOWN); + } finally { + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); + } + } else { + signingDetails = PackageParser.SigningDetails.UNKNOWN; + } + + final AttributeSet attrs = parser; + return parseApkLite(apkPath, parser, attrs, signingDetails); + + } catch (XmlPullParserException | IOException | RuntimeException e) { + Slog.w(TAG, "Failed to parse " + apkPath, e); + throw new PackageParser.PackageParserException( + PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, + "Failed to parse " + apkPath, e); + } finally { + IoUtils.closeQuietly(parser); + if (apkAssets != null) { + try { + apkAssets.close(); + } catch (Throwable ignored) { + } + } + // TODO(b/72056911): Implement AutoCloseable on ApkAssets. + } + } + + private static PackageParser.ApkLite parseApkLite( + String codePath, XmlPullParser parser, AttributeSet attrs, + PackageParser.SigningDetails signingDetails) + throws IOException, XmlPullParserException, PackageParser.PackageParserException { + final Pair<String, String> packageSplit = PackageParser.parsePackageSplitNames( + parser, attrs); + + int installLocation = PARSE_DEFAULT_INSTALL_LOCATION; + int versionCode = 0; + int versionCodeMajor = 0; + int targetSdkVersion = DEFAULT_TARGET_SDK_VERSION; + int minSdkVersion = DEFAULT_MIN_SDK_VERSION; + int revisionCode = 0; + boolean coreApp = false; + boolean debuggable = false; + boolean multiArch = false; + boolean use32bitAbi = false; + boolean extractNativeLibs = true; + boolean isolatedSplits = false; + boolean isFeatureSplit = false; + boolean isSplitRequired = false; + boolean useEmbeddedDex = false; + String configForSplit = null; + String usesSplitName = null; + + for (int i = 0; i < attrs.getAttributeCount(); i++) { + final String attr = attrs.getAttributeName(i); + switch (attr) { + case "installLocation": + installLocation = attrs.getAttributeIntValue(i, + PARSE_DEFAULT_INSTALL_LOCATION); + break; + case "versionCode": + versionCode = attrs.getAttributeIntValue(i, 0); + break; + case "versionCodeMajor": + versionCodeMajor = attrs.getAttributeIntValue(i, 0); + break; + case "revisionCode": + revisionCode = attrs.getAttributeIntValue(i, 0); + break; + case "coreApp": + coreApp = attrs.getAttributeBooleanValue(i, false); + break; + case "isolatedSplits": + isolatedSplits = attrs.getAttributeBooleanValue(i, false); + break; + case "configForSplit": + configForSplit = attrs.getAttributeValue(i); + break; + case "isFeatureSplit": + isFeatureSplit = attrs.getAttributeBooleanValue(i, false); + break; + case "isSplitRequired": + isSplitRequired = attrs.getAttributeBooleanValue(i, false); + break; + } + } + + // Only search the tree when the tag is the direct child of <manifest> tag + int type; + final int searchDepth = parser.getDepth() + 1; + + final List<VerifierInfo> verifiers = new ArrayList<>(); + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + if (parser.getDepth() != searchDepth) { + continue; + } + + if (PackageParser.TAG_PACKAGE_VERIFIER.equals(parser.getName())) { + final VerifierInfo verifier = parseVerifier(attrs); + if (verifier != null) { + verifiers.add(verifier); + } + } else if (PackageParser.TAG_APPLICATION.equals(parser.getName())) { + for (int i = 0; i < attrs.getAttributeCount(); ++i) { + final String attr = attrs.getAttributeName(i); + switch (attr) { + case "debuggable": + debuggable = attrs.getAttributeBooleanValue(i, false); + break; + case "multiArch": + multiArch = attrs.getAttributeBooleanValue(i, false); + break; + case "use32bitAbi": + use32bitAbi = attrs.getAttributeBooleanValue(i, false); + break; + case "extractNativeLibs": + extractNativeLibs = attrs.getAttributeBooleanValue(i, true); + break; + case "useEmbeddedDex": + useEmbeddedDex = attrs.getAttributeBooleanValue(i, false); + break; + } + } + } else if (PackageParser.TAG_USES_SPLIT.equals(parser.getName())) { + if (usesSplitName != null) { + Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others."); + continue; + } + + usesSplitName = attrs.getAttributeValue(PackageParser.ANDROID_RESOURCES, "name"); + if (usesSplitName == null) { + throw new PackageParser.PackageParserException( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "<uses-split> tag requires 'android:name' attribute"); + } + } else if (PackageParser.TAG_USES_SDK.equals(parser.getName())) { + for (int i = 0; i < attrs.getAttributeCount(); ++i) { + final String attr = attrs.getAttributeName(i); + if ("targetSdkVersion".equals(attr)) { + targetSdkVersion = attrs.getAttributeIntValue(i, + DEFAULT_TARGET_SDK_VERSION); + } + if ("minSdkVersion".equals(attr)) { + minSdkVersion = attrs.getAttributeIntValue(i, DEFAULT_MIN_SDK_VERSION); + } + } + } + } + + return new PackageParser.ApkLite(codePath, packageSplit.first, packageSplit.second, + isFeatureSplit, configForSplit, usesSplitName, isSplitRequired, versionCode, + versionCodeMajor, revisionCode, installLocation, verifiers, signingDetails, + coreApp, debuggable, multiArch, use32bitAbi, useEmbeddedDex, extractNativeLibs, + isolatedSplits, minSdkVersion, targetSdkVersion); + } + + public static VerifierInfo parseVerifier(AttributeSet attrs) { + String packageName = null; + String encodedPublicKey = null; + + final int attrCount = attrs.getAttributeCount(); + for (int i = 0; i < attrCount; i++) { + final int attrResId = attrs.getAttributeNameResource(i); + switch (attrResId) { + case R.attr.name: + packageName = attrs.getAttributeValue(i); + break; + + case R.attr.publicKey: + encodedPublicKey = attrs.getAttributeValue(i); + break; + } + } + + if (packageName == null || packageName.length() == 0) { + Slog.i(TAG, "verifier package name was null; skipping"); + return null; + } + + final PublicKey publicKey = PackageParser.parsePublicKey(encodedPublicKey); + if (publicKey == null) { + Slog.i(TAG, "Unable to parse verifier public key for " + packageName); + return null; + } + + return new VerifierInfo(packageName, publicKey); + } +} diff --git a/core/java/android/content/pm/parsing/ApkParseUtils.java b/core/java/android/content/pm/parsing/ApkParseUtils.java new file mode 100644 index 000000000000..0f35b27de7e2 --- /dev/null +++ b/core/java/android/content/pm/parsing/ApkParseUtils.java @@ -0,0 +1,3197 @@ +/* + * 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.ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE; +import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE; +import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; +import static android.content.pm.PackageManager.FEATURE_WATCH; +import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST; +import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; +import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; +import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK; +import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; +import static android.os.Build.VERSION_CODES.O; +import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; +import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.ActivityTaskManager; +import android.app.ActivityThread; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.ConfigurationInfo; +import android.content.pm.FeatureGroupInfo; +import android.content.pm.FeatureInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageItemInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageParser; +import android.content.pm.PackageParser.PackageParserException; +import android.content.pm.PackageParser.SigningDetails; +import android.content.pm.Signature; +import android.content.pm.permission.SplitPermissionInfoParcelable; +import android.content.pm.split.DefaultSplitAssetLoader; +import android.content.pm.split.SplitAssetDependencyLoader; +import android.content.pm.split.SplitAssetLoader; +import android.content.res.AssetManager; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.FileUtils; +import android.os.RemoteException; +import android.os.SystemProperties; +import android.os.Trace; +import android.text.TextUtils; +import android.util.ArrayMap; +import android.util.ArraySet; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.util.Pair; +import android.util.Slog; +import android.util.SparseArray; +import android.util.TypedValue; +import android.util.apk.ApkSignatureVerifier; + +import com.android.internal.R; +import com.android.internal.os.ClassLoaderFactory; +import com.android.internal.util.ArrayUtils; +import com.android.internal.util.XmlUtils; + +import libcore.io.IoUtils; +import libcore.util.EmptyArray; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.File; +import java.io.IOException; +import java.security.PublicKey; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +/** @hide */ +public class ApkParseUtils { + + // TODO(b/135203078): Consolidate log tags + static final String TAG = "PackageParsing"; + + /** + * Parse the package at the given location. Automatically detects if the + * package is a monolithic style (single APK file) or cluster style + * (directory of APKs). + * <p> + * This performs sanity checking on cluster style packages, such as + * requiring identical package name and version codes, a single base APK, + * and unique split names. + * <p> + * Note that this <em>does not</em> perform signature verification; that + * must be done separately in {@link #collectCertificates(ParsedPackage, boolean)}. + * + * If {@code useCaches} is true, the package parser might return a cached + * result from a previous parse of the same {@code packageFile} with the same + * {@code flags}. Note that this method does not check whether {@code packageFile} + * has changed since the last parse, it's up to callers to do so. + * + * @see PackageParser#parsePackageLite(File, int) + */ + public static ParsingPackage parsePackage( + ParseInput parseInput, + String[] separateProcesses, + PackageParser.Callback callback, + DisplayMetrics displayMetrics, + boolean onlyCoreApps, + File packageFile, + int flags + ) throws PackageParserException { + if (packageFile.isDirectory()) { + return parseClusterPackage(parseInput, separateProcesses, callback, displayMetrics, + onlyCoreApps, packageFile, flags); + } else { + return parseMonolithicPackage(parseInput, separateProcesses, callback, displayMetrics, + onlyCoreApps, packageFile, flags); + } + } + + /** + * Parse all APKs contained in the given directory, treating them as a + * single package. This also performs sanity checking, such as requiring + * identical package name and version codes, a single base APK, and unique + * split names. + * <p> + * Note that this <em>does not</em> perform signature verification; that + * must be done separately in {@link #collectCertificates(ParsedPackage, boolean)}. + */ + private static ParsingPackage parseClusterPackage( + ParseInput parseInput, + String[] separateProcesses, + PackageParser.Callback callback, + DisplayMetrics displayMetrics, + boolean onlyCoreApps, + File packageDir, + int flags + ) throws PackageParserException { + final PackageParser.PackageLite lite = ApkLiteParseUtils.parseClusterPackageLite(packageDir, + 0); + if (onlyCoreApps && !lite.coreApp) { + throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Not a coreApp: " + packageDir); + } + + // Build the split dependency tree. + SparseArray<int[]> splitDependencies = null; + final SplitAssetLoader assetLoader; + if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) { + try { + splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite); + assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags); + } catch (SplitAssetDependencyLoader.IllegalDependencyException e) { + throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage()); + } + } else { + assetLoader = new DefaultSplitAssetLoader(lite, flags); + } + + try { + final AssetManager assets = assetLoader.getBaseAssetManager(); + final File baseApk = new File(lite.baseCodePath); + ParsingPackage parsingPackage = parseBaseApk(parseInput, separateProcesses, callback, + displayMetrics, baseApk, assets, flags); + if (parsingPackage == null) { + throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK, + "Failed to parse base APK: " + baseApk); + } + + if (!ArrayUtils.isEmpty(lite.splitNames)) { + parsingPackage.asSplit( + lite.splitNames, + lite.splitCodePaths, + lite.splitRevisionCodes, + splitDependencies + ); + final int num = lite.splitNames.length; + + for (int i = 0; i < num; i++) { + final AssetManager splitAssets = assetLoader.getSplitAssetManager(i); + parseSplitApk(parseInput, displayMetrics, separateProcesses, parsingPackage, i, + splitAssets, flags); + } + } + + return parsingPackage.setCodePath(packageDir.getCanonicalPath()) + .setUse32BitAbi(lite.use32bitAbi); + } catch (IOException e) { + throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, + "Failed to get path: " + lite.baseCodePath, e); + } finally { + IoUtils.closeQuietly(assetLoader); + } + } + + /** + * Parse the given APK file, treating it as as a single monolithic package. + * <p> + * Note that this <em>does not</em> perform signature verification; that + * must be done separately in {@link #collectCertificates(AndroidPackage, boolean)}. + */ + public static ParsingPackage parseMonolithicPackage( + ParseInput parseInput, + String[] separateProcesses, + PackageParser.Callback callback, + DisplayMetrics displayMetrics, + boolean onlyCoreApps, + File apkFile, + int flags + ) throws PackageParserException { + final PackageParser.PackageLite lite = ApkLiteParseUtils.parseMonolithicPackageLite(apkFile, + flags); + if (onlyCoreApps) { + if (!lite.coreApp) { + throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Not a coreApp: " + apkFile); + } + } + + final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags); + try { + return parseBaseApk(parseInput, separateProcesses, callback, + displayMetrics, apkFile, assetLoader.getBaseAssetManager(), flags) + .setCodePath(apkFile.getCanonicalPath()) + .setUse32BitAbi(lite.use32bitAbi); + } catch (IOException e) { + throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, + "Failed to get path: " + apkFile, e); + } finally { + IoUtils.closeQuietly(assetLoader); + } + } + + private static ParsingPackage parseBaseApk( + ParseInput parseInput, + String[] separateProcesses, + PackageParser.Callback callback, + DisplayMetrics displayMetrics, + File apkFile, + AssetManager assets, + int flags + ) throws PackageParserException { + final String apkPath = apkFile.getAbsolutePath(); + + String volumeUuid = null; + if (apkPath.startsWith(PackageParser.MNT_EXPAND)) { + final int end = apkPath.indexOf('/', PackageParser.MNT_EXPAND.length()); + volumeUuid = apkPath.substring(PackageParser.MNT_EXPAND.length(), end); + } + + if (PackageParser.DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath); + + XmlResourceParser parser = null; + try { + final int cookie = assets.findCookieForPath(apkPath); + if (cookie == 0) { + throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, + "Failed adding asset path: " + apkPath); + } + parser = assets.openXmlResourceParser(cookie, PackageParser.ANDROID_MANIFEST_FILENAME); + final Resources res = new Resources(assets, displayMetrics, null); + + ParseResult result = parseBaseApk(parseInput, separateProcesses, callback, apkPath, res, + parser, flags); + if (!result.isSuccess()) { + throw new PackageParserException(result.getParseError(), + apkPath + " (at " + parser.getPositionDescription() + "): " + + result.getErrorMessage()); + } + + return result.getResultAndNull() + .setVolumeUuid(volumeUuid) + .setApplicationVolumeUuid(volumeUuid) + .setSigningDetails(SigningDetails.UNKNOWN); + } catch (PackageParserException e) { + throw e; + } catch (Exception e) { + throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, + "Failed to read manifest from " + apkPath, e); + } finally { + IoUtils.closeQuietly(parser); + } + } + + private static void parseSplitApk( + ParseInput parseInput, + DisplayMetrics displayMetrics, + String[] separateProcesses, + ParsingPackage parsingPackage, + int splitIndex, + AssetManager assets, + int flags + ) throws PackageParserException { + final String apkPath = parsingPackage.getSplitCodePaths()[splitIndex]; + + if (PackageParser.DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath); + + final Resources res; + XmlResourceParser parser = null; + try { + // This must always succeed, as the path has been added to the AssetManager before. + final int cookie = assets.findCookieForPath(apkPath); + if (cookie == 0) { + throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, + "Failed adding asset path: " + apkPath); + } + + parser = assets.openXmlResourceParser(cookie, PackageParser.ANDROID_MANIFEST_FILENAME); + res = new Resources(assets, displayMetrics, null); + + final String[] outError = new String[1]; + ParseResult parseResult = parseSplitApk(parseInput, separateProcesses, parsingPackage, + res, parser, flags, splitIndex, outError); + if (!parseResult.isSuccess()) { + throw new PackageParserException(parseResult.getParseError(), + apkPath + " (at " + parser.getPositionDescription() + "): " + + parseResult.getErrorMessage()); + } + } catch (PackageParserException e) { + throw e; + } catch (Exception e) { + throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION, + "Failed to read manifest from " + apkPath, e); + } finally { + IoUtils.closeQuietly(parser); + } + } + + /** + * Parse the manifest of a <em>base APK</em>. When adding new features you + * need to consider whether they should be supported by split APKs and child + * packages. + * + * @param apkPath The package apk file path + * @param res The resources from which to resolve values + * @param parser The manifest parser + * @param flags Flags how to parse + * @return Parsed package or null on error. + */ + private static ParseResult parseBaseApk( + ParseInput parseInput, + String[] separateProcesses, + PackageParser.Callback callback, + String apkPath, + Resources res, + XmlResourceParser parser, + int flags + ) throws XmlPullParserException, IOException { + final String splitName; + final String pkgName; + + try { + Pair<String, String> packageSplit = PackageParser.parsePackageSplitNames(parser, + parser); + pkgName = packageSplit.first; + splitName = packageSplit.second; + + if (!TextUtils.isEmpty(splitName)) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME, + "Expected base APK, but found split " + splitName + ); + } + } catch (PackageParserException e) { + return parseInput.error(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME); + } + + // TODO: Remove when manifest overlaying removed + if (callback != null) { + String[] overlayPaths = callback.getOverlayPaths(pkgName, apkPath); + if (overlayPaths != null && overlayPaths.length > 0) { + for (String overlayPath : overlayPaths) { + res.getAssets().addOverlayPath(overlayPath); + } + } + } + + TypedArray manifestArray = null; + + try { + manifestArray = res.obtainAttributes(parser, R.styleable.AndroidManifest); + + boolean isCoreApp = parser.getAttributeBooleanValue(null, "coreApp", false); + + ParsingPackage parsingPackage = PackageImpl.forParsing( + pkgName, + apkPath, + manifestArray, + isCoreApp + ); + + ParseResult result = parseBaseApkTags(parseInput, separateProcesses, callback, + parsingPackage, manifestArray, res, parser, flags); + if (!result.isSuccess()) { + return result; + } + + return parseInput.success(parsingPackage); + } finally { + if (manifestArray != null) { + manifestArray.recycle(); + } + } + } + + /** + * Parse the manifest of a <em>split APK</em>. + * <p> + * Note that split APKs have many more restrictions on what they're capable + * of doing, so many valid features of a base APK have been carefully + * omitted here. + * + * @param parsingPackage builder to fill + * @return false on failure + */ + private static ParseResult parseSplitApk( + ParseInput parseInput, + String[] separateProcesses, + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser, + int flags, + int splitIndex, + String[] outError + ) throws XmlPullParserException, IOException, PackageParserException { + AttributeSet attrs = parser; + + // We parsed manifest tag earlier; just skip past it + PackageParser.parsePackageSplitNames(parser, attrs); + + int type; + + boolean foundApp = false; + + int outerDepth = parser.getDepth(); + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + String tagName = parser.getName(); + if (tagName.equals(PackageParser.TAG_APPLICATION)) { + if (foundApp) { + if (PackageParser.RIGID_PARSER) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "<manifest> has more than one <application>" + ); + } else { + Slog.w(TAG, "<manifest> has more than one <application>"); + XmlUtils.skipCurrentTag(parser); + continue; + } + } + + foundApp = true; + ParseResult parseResult = parseSplitApplication(parseInput, separateProcesses, + parsingPackage, res, + parser, flags, + splitIndex, outError); + if (!parseResult.isSuccess()) { + return parseResult; + } + + } else if (PackageParser.RIGID_PARSER) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Bad element under <manifest>: " + parser.getName() + ); + + } else { + Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName() + + " at " + parsingPackage.getBaseCodePath() + " " + + parser.getPositionDescription()); + XmlUtils.skipCurrentTag(parser); + continue; + } + } + + if (!foundApp) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY, + "<manifest> does not contain an <application>" + ); + } + + return parseInput.success(parsingPackage); + } + + /** + * Parse the {@code application} XML tree at the current parse location in a + * <em>split APK</em> manifest. + * <p> + * Note that split APKs have many more restrictions on what they're capable + * of doing, so many valid features of a base APK have been carefully + * omitted here. + */ + private static ParseResult parseSplitApplication( + ParseInput parseInput, + String[] separateProcesses, + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser, + int flags, + int splitIndex, + String[] outError + ) throws XmlPullParserException, IOException { + TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestApplication); + + parsingPackage.setSplitHasCode(splitIndex, sa.getBoolean( + R.styleable.AndroidManifestApplication_hasCode, true)); + + final String classLoaderName = sa.getString( + R.styleable.AndroidManifestApplication_classLoader); + if (classLoaderName == null || ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) { + parsingPackage.setSplitClassLoaderName(splitIndex, classLoaderName); + } else { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Invalid class loader name: " + classLoaderName + ); + } + + final int innerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + ComponentParseUtils.ParsedComponent parsedComponent = null; + + String tagName = parser.getName(); + switch (tagName) { + case "activity": + ComponentParseUtils.ParsedActivity activity = + ComponentParseUtils.parseActivity(separateProcesses, + parsingPackage, + res, parser, flags, + outError, + false, + parsingPackage.isBaseHardwareAccelerated()); + if (activity == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + parsingPackage.addActivity(activity); + parsedComponent = activity; + break; + case "receiver": + activity = ComponentParseUtils.parseActivity( + separateProcesses, parsingPackage, + res, parser, flags, outError, + true, false); + if (activity == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + parsingPackage.addReceiver(activity); + parsedComponent = activity; + break; + case "service": + ComponentParseUtils.ParsedService s = ComponentParseUtils.parseService( + separateProcesses, + parsingPackage, + res, parser, flags, outError + ); + if (s == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + parsingPackage.addService(s); + parsedComponent = s; + break; + case "provider": + ComponentParseUtils.ParsedProvider p = ComponentParseUtils.parseProvider( + separateProcesses, + parsingPackage, + res, parser, flags, outError); + if (p == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + parsingPackage.addProvider(p); + parsedComponent = p; + break; + case "activity-alias": + activity = ComponentParseUtils.parseActivityAlias( + parsingPackage, + res, + parser, + outError + ); + if (activity == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + parsingPackage.addActivity(activity); + parsedComponent = activity; + break; + case "meta-data": + // note: application meta-data is stored off to the side, so it can + // remain null in the primary copy (we like to avoid extra copies because + // it can be large) + Bundle appMetaData = parseMetaData(parsingPackage, res, parser, + parsingPackage.getAppMetaData(), + outError); + if (appMetaData == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + parsingPackage.setAppMetaData(appMetaData); + break; + case "uses-static-library": + ParseResult parseResult = parseUsesStaticLibrary(parseInput, parsingPackage, + res, parser); + if (!parseResult.isSuccess()) { + return parseResult; + } + + break; + case "uses-library": + sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesLibrary); + + // Note: don't allow this value to be a reference to a resource + // that may change. + String lname = sa.getNonResourceString( + R.styleable.AndroidManifestUsesLibrary_name); + boolean req = sa.getBoolean( + R.styleable.AndroidManifestUsesLibrary_required, true); + + sa.recycle(); + + if (lname != null) { + lname = lname.intern(); + if (req) { + // Upgrade to treat as stronger constraint + parsingPackage.addUsesLibrary(lname) + .removeUsesOptionalLibrary(lname); + } else { + // Ignore if someone already defined as required + if (!ArrayUtils.contains(parsingPackage.getUsesLibraries(), lname)) { + parsingPackage.addUsesOptionalLibrary(lname); + } + } + } + + XmlUtils.skipCurrentTag(parser); + break; + case "uses-package": + // Dependencies for app installers; we don't currently try to + // enforce this. + XmlUtils.skipCurrentTag(parser); + break; + default: + if (!PackageParser.RIGID_PARSER) { + Slog.w(TAG, "Unknown element under <application>: " + tagName + + " at " + parsingPackage.getBaseCodePath() + " " + + parser.getPositionDescription()); + XmlUtils.skipCurrentTag(parser); + continue; + } else { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Bad element under <application>: " + tagName + ); + } + } + + if (parsedComponent != null && parsedComponent.getSplitName() == null) { + // If the loaded component did not specify a split, inherit the split name + // based on the split it is defined in. + // This is used to later load the correct split when starting this + // component. + parsedComponent.setSplitName(parsingPackage.getSplitNames()[splitIndex]); + } + } + + return parseInput.success(parsingPackage); + } + + private static ParseResult parseBaseApkTags( + ParseInput parseInput, + String[] separateProcesses, + PackageParser.Callback callback, + ParsingPackage parsingPackage, + TypedArray manifestArray, + Resources res, + XmlResourceParser parser, + int flags + ) throws XmlPullParserException, IOException { + int type; + boolean foundApp = false; + + TypedArray sa = manifestArray; + + ParseResult sharedUserResult = parseSharedUser(parseInput, parsingPackage, sa); + if (!sharedUserResult.isSuccess()) { + return sharedUserResult; + } + + parseManifestAttributes(sa, parsingPackage, flags); + + int outerDepth = parser.getDepth(); + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + String tagName = parser.getName(); + + // All methods return a boolean, even if they can't fail. This can be enforced + // by making this final and not assigned, forcing the switch to assign success + // once in every branch. + final boolean success; + ParseResult parseResult = null; + + // TODO(b/135203078): Either use all booleans or all ParseResults + // TODO(b/135203078): Convert to instance methods to share variables + switch (tagName) { + case PackageParser.TAG_APPLICATION: + if (foundApp) { + if (PackageParser.RIGID_PARSER) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "<manifest> has more than one <application>" + ); + } else { + Slog.w(TAG, "<manifest> has more than one <application>"); + XmlUtils.skipCurrentTag(parser); + success = true; + } + } else { + foundApp = true; + parseResult = parseBaseApplication(parseInput, separateProcesses, + callback, + parsingPackage, res, parser, flags); + success = parseResult.isSuccess(); + } + break; + case PackageParser.TAG_OVERLAY: + parseResult = parseOverlay(parseInput, parsingPackage, res, parser); + success = parseResult.isSuccess(); + break; + case PackageParser.TAG_KEY_SETS: + parseResult = parseKeySets(parseInput, parsingPackage, res, parser); + success = parseResult.isSuccess(); + break; + case PackageParser.TAG_PERMISSION_GROUP: + parseResult = parsePermissionGroup(parseInput, parsingPackage, res, + parser); + success = parseResult.isSuccess(); + break; + case PackageParser.TAG_PERMISSION: + parseResult = parsePermission(parseInput, parsingPackage, res, parser); + success = parseResult.isSuccess(); + break; + case PackageParser.TAG_PERMISSION_TREE: + parseResult = parsePermissionTree(parseInput, parsingPackage, res, parser); + success = parseResult.isSuccess(); + break; + case PackageParser.TAG_USES_PERMISSION: + case PackageParser.TAG_USES_PERMISSION_SDK_M: + case PackageParser.TAG_USES_PERMISSION_SDK_23: + parseResult = parseUsesPermission(parseInput, parsingPackage, res, parser, + callback); + success = parseResult.isSuccess(); + break; + case PackageParser.TAG_USES_CONFIGURATION: + success = parseUsesConfiguration(parsingPackage, res, parser); + break; + case PackageParser.TAG_USES_FEATURE: + success = parseUsesFeature(parsingPackage, res, parser); + break; + case PackageParser.TAG_FEATURE_GROUP: + success = parseFeatureGroup(parsingPackage, res, parser); + break; + case PackageParser.TAG_USES_SDK: + parseResult = parseUsesSdk(parseInput, parsingPackage, res, parser); + success = parseResult.isSuccess(); + break; + case PackageParser.TAG_SUPPORT_SCREENS: + success = parseSupportScreens(parsingPackage, res, parser); + break; + case PackageParser.TAG_PROTECTED_BROADCAST: + success = parseProtectedBroadcast(parsingPackage, res, parser); + break; + case PackageParser.TAG_INSTRUMENTATION: + parseResult = parseInstrumentation(parseInput, parsingPackage, res, + parser); + success = parseResult.isSuccess(); + break; + case PackageParser.TAG_ORIGINAL_PACKAGE: + success = parseOriginalPackage(parsingPackage, res, parser); + break; + case PackageParser.TAG_ADOPT_PERMISSIONS: + success = parseAdoptPermissions(parsingPackage, res, parser); + break; + case PackageParser.TAG_USES_GL_TEXTURE: + case PackageParser.TAG_COMPATIBLE_SCREENS: + case PackageParser.TAG_SUPPORTS_INPUT: + case PackageParser.TAG_EAT_COMMENT: + // Just skip this tag + XmlUtils.skipCurrentTag(parser); + success = true; + break; + case PackageParser.TAG_RESTRICT_UPDATE: + success = parseRestrictUpdateHash(flags, parsingPackage, res, parser); + break; + case PackageParser.TAG_QUERIES: + parseResult = parseQueries(parseInput, parsingPackage, res, parser); + success = parseResult.isSuccess(); + break; + default: + parseResult = parseUnknownTag(parseInput, parsingPackage, parser); + success = parseResult.isSuccess(); + break; + } + + if (parseResult != null && !parseResult.isSuccess()) { + return parseResult; + } + + if (!success) { + return parseResult; + } + } + + if (!foundApp && ArrayUtils.size(parsingPackage.getInstrumentations()) == 0) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY, + "<manifest> does not contain an <application> or <instrumentation>" + ); + } + + convertNewPermissions(parsingPackage); + + convertSplitPermissions(parsingPackage); + + // At this point we can check if an application is not supporting densities and hence + // cannot be windowed / resized. Note that an SDK version of 0 is common for + // pre-Doughnut applications. + if (parsingPackage.usesCompatibilityMode()) { + adjustPackageToBeUnresizeableAndUnpipable(parsingPackage); + } + + return parseInput.success(parsingPackage); + } + + private static ParseResult parseUnknownTag( + ParseInput parseInput, + ParsingPackage parsingPackage, + XmlResourceParser parser + ) throws IOException, XmlPullParserException { + if (PackageParser.RIGID_PARSER) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Bad element under <manifest>: " + parser.getName() + ); + } else { + Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName() + + " at " + parsingPackage.getBaseCodePath() + " " + + parser.getPositionDescription()); + XmlUtils.skipCurrentTag(parser); + return parseInput.success(parsingPackage); + } + } + + private static ParseResult parseSharedUser( + ParseInput parseInput, + ParsingPackage parsingPackage, + TypedArray manifestArray + ) { + String str = manifestArray.getNonConfigurationString( + R.styleable.AndroidManifest_sharedUserId, 0); + if (TextUtils.isEmpty(str)) { + return parseInput.success(parsingPackage); + } + + String nameError = validateName(str, true, true); + if (nameError != null && !"android".equals(parsingPackage.getPackageName())) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID, + "<manifest> specifies bad sharedUserId name \"" + str + "\": " + + nameError + ); + } + + int sharedUserLabel = manifestArray.getResourceId( + R.styleable.AndroidManifest_sharedUserLabel, 0); + parsingPackage.setSharedUserId(str.intern()) + .setSharedUserLabel(sharedUserLabel); + + return parseInput.success(parsingPackage); + } + + private static void parseManifestAttributes( + TypedArray manifestArray, + ParsingPackage parsingPackage, + int flags + ) { + int installLocation = manifestArray.getInteger(R.styleable.AndroidManifest_installLocation, + PackageParser.PARSE_DEFAULT_INSTALL_LOCATION); + + final int targetSandboxVersion = manifestArray.getInteger( + R.styleable.AndroidManifest_targetSandboxVersion, + PackageParser.PARSE_DEFAULT_TARGET_SANDBOX); + + parsingPackage.setInstallLocation(installLocation) + .setTargetSandboxVersion(targetSandboxVersion); + + /* Set the global "on SD card" flag */ + parsingPackage.setExternalStorage((flags & PackageParser.PARSE_EXTERNAL_STORAGE) != 0); + + parsingPackage.setIsolatedSplitLoading(manifestArray.getBoolean( + R.styleable.AndroidManifest_isolatedSplits, false)); + } + + private static ParseResult parseKeySets( + ParseInput parseInput, + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser + ) throws XmlPullParserException, IOException { + // we've encountered the 'key-sets' tag + // all the keys and keysets that we want must be defined here + // so we're going to iterate over the parser and pull out the things we want + int outerDepth = parser.getDepth(); + int currentKeySetDepth = -1; + int type; + String currentKeySet = null; + ArrayMap<String, PublicKey> publicKeys = new ArrayMap<>(); + ArraySet<String> upgradeKeySets = new ArraySet<>(); + ArrayMap<String, ArraySet<String>> definedKeySets = + new ArrayMap<>(); + ArraySet<String> improperKeySets = new ArraySet<>(); + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG) { + if (parser.getDepth() == currentKeySetDepth) { + currentKeySet = null; + currentKeySetDepth = -1; + } + continue; + } + String tagName = parser.getName(); + if (tagName.equals("key-set")) { + if (currentKeySet != null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Improperly nested 'key-set' tag at " + parser.getPositionDescription() + ); + } + final TypedArray sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestKeySet); + final String keysetName = sa.getNonResourceString( + R.styleable.AndroidManifestKeySet_name); + definedKeySets.put(keysetName, new ArraySet<>()); + currentKeySet = keysetName; + currentKeySetDepth = parser.getDepth(); + sa.recycle(); + } else if (tagName.equals("public-key")) { + if (currentKeySet == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Improperly nested 'key-set' tag at " + parser.getPositionDescription() + ); + } + final TypedArray sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestPublicKey); + final String publicKeyName = sa.getNonResourceString( + R.styleable.AndroidManifestPublicKey_name); + final String encodedKey = sa.getNonResourceString( + R.styleable.AndroidManifestPublicKey_value); + if (encodedKey == null && publicKeys.get(publicKeyName) == null) { + sa.recycle(); + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "'public-key' " + publicKeyName + " must define a public-key value" + + " on first use at " + parser.getPositionDescription() + ); + } else if (encodedKey != null) { + PublicKey currentKey = PackageParser.parsePublicKey(encodedKey); + if (currentKey == null) { + Slog.w(TAG, "No recognized valid key in 'public-key' tag at " + + parser.getPositionDescription() + " key-set " + currentKeySet + + " will not be added to the package's defined key-sets."); + sa.recycle(); + improperKeySets.add(currentKeySet); + XmlUtils.skipCurrentTag(parser); + continue; + } + if (publicKeys.get(publicKeyName) == null + || publicKeys.get(publicKeyName).equals(currentKey)) { + + /* public-key first definition, or matches old definition */ + publicKeys.put(publicKeyName, currentKey); + } else { + sa.recycle(); + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Value of 'public-key' " + publicKeyName + + " conflicts with previously defined value at " + + parser.getPositionDescription() + ); + } + } + definedKeySets.get(currentKeySet).add(publicKeyName); + sa.recycle(); + XmlUtils.skipCurrentTag(parser); + } else if (tagName.equals("upgrade-key-set")) { + final TypedArray sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestUpgradeKeySet); + String name = sa.getNonResourceString( + R.styleable.AndroidManifestUpgradeKeySet_name); + upgradeKeySets.add(name); + sa.recycle(); + XmlUtils.skipCurrentTag(parser); + } else if (PackageParser.RIGID_PARSER) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Bad element under <key-sets>: " + parser.getName() + + " at " + parsingPackage.getBaseCodePath() + " " + + parser.getPositionDescription() + ); + } else { + Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName() + + " at " + parsingPackage.getBaseCodePath() + " " + + parser.getPositionDescription()); + XmlUtils.skipCurrentTag(parser); + continue; + } + } + String packageName = parsingPackage.getPackageName(); + Set<String> publicKeyNames = publicKeys.keySet(); + if (publicKeyNames.removeAll(definedKeySets.keySet())) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Package" + packageName + " AndroidManifest.xml " + + "'key-set' and 'public-key' names must be distinct." + ); + } + + for (ArrayMap.Entry<String, ArraySet<String>> e : definedKeySets.entrySet()) { + final String keySetName = e.getKey(); + if (e.getValue().size() == 0) { + Slog.w(TAG, "Package" + packageName + " AndroidManifest.xml " + + "'key-set' " + keySetName + " has no valid associated 'public-key'." + + " Not including in package's defined key-sets."); + continue; + } else if (improperKeySets.contains(keySetName)) { + Slog.w(TAG, "Package" + packageName + " AndroidManifest.xml " + + "'key-set' " + keySetName + " contained improper 'public-key'" + + " tags. Not including in package's defined key-sets."); + continue; + } + + for (String s : e.getValue()) { + parsingPackage.addKeySet(keySetName, publicKeys.get(s)); + } + } + if (parsingPackage.getKeySetMapping().keySet().containsAll(upgradeKeySets)) { + parsingPackage.setUpgradeKeySets(upgradeKeySets); + } else { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Package" + packageName + " AndroidManifest.xml " + + "does not define all 'upgrade-key-set's ." + ); + } + + return parseInput.success(parsingPackage); + } + + public static boolean parsePackageItemInfo(String packageName, PackageItemInfo outInfo, + String[] outError, String tag, TypedArray sa, boolean nameRequired, + int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) { + // This case can only happen in unit tests where we sometimes need to create fakes + // of various package parser data structures. + if (sa == null) { + outError[0] = tag + " does not contain any attributes"; + return false; + } + + String name = sa.getNonConfigurationString(nameRes, 0); + if (name == null) { + if (nameRequired) { + outError[0] = tag + " does not specify android:name"; + return false; + } + } else { + String outInfoName = buildClassName(packageName, name); + if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(outInfoName)) { + outError[0] = tag + " invalid android:name"; + return false; + } + outInfo.name = outInfoName; + if (outInfoName == null) { + return false; + } + } + + int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0; + if (roundIconVal != 0) { + outInfo.icon = roundIconVal; + outInfo.nonLocalizedLabel = null; + } else { + int iconVal = sa.getResourceId(iconRes, 0); + if (iconVal != 0) { + outInfo.icon = iconVal; + outInfo.nonLocalizedLabel = null; + } + } + + int logoVal = sa.getResourceId(logoRes, 0); + if (logoVal != 0) { + outInfo.logo = logoVal; + } + + int bannerVal = sa.getResourceId(bannerRes, 0); + if (bannerVal != 0) { + outInfo.banner = bannerVal; + } + + TypedValue v = sa.peekValue(labelRes); + if (v != null && (outInfo.labelRes = v.resourceId) == 0) { + outInfo.nonLocalizedLabel = v.coerceToString(); + } + + outInfo.packageName = packageName; + + return true; + } + + private static ParseResult parsePackageItemInfo( + ParseInput parseInput, + ParsingPackage parsingPackage, + String tag, + TypedArray sa, + boolean nameRequired, + int nameRes, + int labelRes, + int iconRes, + int roundIconRes, + int logoRes, + int bannerRes + ) { + // This case can only happen in unit tests where we sometimes need to create fakes + // of various package parser data structures. + if (sa == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + tag + " does not contain any attributes" + ); + } + + String name = sa.getNonConfigurationString(nameRes, 0); + if (name == null) { + if (nameRequired) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + tag + " does not specify android:name" + ); + } + } else { + String packageName = parsingPackage.getPackageName(); + String outInfoName = buildClassName(packageName, name); + if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(outInfoName)) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + tag + " invalid android:name" + ); + } else if (outInfoName == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Empty class name in package " + packageName + ); + } + + parsingPackage.setName(outInfoName); + } + + int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0; + if (roundIconVal != 0) { + parsingPackage.setIcon(roundIconVal) + .setNonLocalizedLabel(null); + } else { + int iconVal = sa.getResourceId(iconRes, 0); + if (iconVal != 0) { + parsingPackage.setIcon(iconVal) + .setNonLocalizedLabel(null); + } + } + + int logoVal = sa.getResourceId(logoRes, 0); + if (logoVal != 0) { + parsingPackage.setLogo(logoVal); + } + + int bannerVal = sa.getResourceId(bannerRes, 0); + if (bannerVal != 0) { + parsingPackage.setBanner(bannerVal); + } + + TypedValue v = sa.peekValue(labelRes); + if (v != null) { + parsingPackage.setLabelRes(v.resourceId); + if (v.resourceId == 0) { + parsingPackage.setNonLocalizedLabel(v.coerceToString()); + } + } + + return parseInput.success(parsingPackage); + } + + private static ParseResult parsePermissionGroup( + ParseInput parseInput, + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser + ) throws XmlPullParserException, IOException { + // TODO(b/135203078): Remove, replace with ParseResult + String[] outError = new String[1]; + + ComponentParseUtils.ParsedPermissionGroup parsedPermissionGroup = + ComponentParseUtils.parsePermissionGroup(parsingPackage, + res, parser, outError); + + if (parsedPermissionGroup == null || outError[0] != null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + parsingPackage.addPermissionGroup(parsedPermissionGroup); + + return parseInput.success(parsingPackage); + } + + private static ParseResult parsePermission( + ParseInput parseInput, + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser + ) throws XmlPullParserException, IOException { + // TODO(b/135203078): Remove, replace with ParseResult + String[] outError = new String[1]; + + ComponentParseUtils.ParsedPermission parsedPermission = + ComponentParseUtils.parsePermission(parsingPackage, + res, parser, outError); + + if (parsedPermission == null || outError[0] != null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + parsingPackage.addPermission(parsedPermission); + + return parseInput.success(parsingPackage); + } + + private static ParseResult parsePermissionTree( + ParseInput parseInput, + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser + ) throws XmlPullParserException, IOException { + // TODO(b/135203078): Remove, replace with ParseResult + String[] outError = new String[1]; + + ComponentParseUtils.ParsedPermission parsedPermission = + ComponentParseUtils.parsePermissionTree(parsingPackage, + res, parser, outError); + + if (parsedPermission == null || outError[0] != null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + parsingPackage.addPermission(parsedPermission); + + return parseInput.success(parsingPackage); + } + + private static ParseResult parseUsesPermission( + ParseInput parseInput, + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser, + PackageParser.Callback callback + ) + throws XmlPullParserException, IOException { + TypedArray sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestUsesPermission); + + // Note: don't allow this value to be a reference to a resource + // that may change. + String name = sa.getNonResourceString( + R.styleable.AndroidManifestUsesPermission_name); + + int maxSdkVersion = 0; + TypedValue val = sa.peekValue( + R.styleable.AndroidManifestUsesPermission_maxSdkVersion); + if (val != null) { + if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) { + maxSdkVersion = val.data; + } + } + + final String requiredFeature = sa.getNonConfigurationString( + R.styleable.AndroidManifestUsesPermission_requiredFeature, 0); + + final String requiredNotfeature = sa.getNonConfigurationString( + R.styleable.AndroidManifestUsesPermission_requiredNotFeature, + 0); + + sa.recycle(); + + XmlUtils.skipCurrentTag(parser); + + // Can only succeed from here on out + ParseResult success = parseInput.success(parsingPackage); + + if (name == null) { + return success; + } + + if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) { + return success; + } + + // Only allow requesting this permission if the platform supports the given feature. + if (requiredFeature != null && callback != null && !callback.hasFeature(requiredFeature)) { + return success; + } + + // Only allow requesting this permission if the platform doesn't support the given feature. + if (requiredNotfeature != null && callback != null + && callback.hasFeature(requiredNotfeature)) { + return success; + } + + if (!parsingPackage.getRequestedPermissions().contains(name)) { + parsingPackage.addRequestedPermission(name.intern()); + } else { + Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: " + + name + " in package: " + parsingPackage.getPackageName() + " at: " + + parser.getPositionDescription()); + } + + return success; + } + + private static boolean parseUsesConfiguration( + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser + ) throws IOException, XmlPullParserException { + ConfigurationInfo cPref = new ConfigurationInfo(); + TypedArray sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestUsesConfiguration); + cPref.reqTouchScreen = sa.getInt( + R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen, + Configuration.TOUCHSCREEN_UNDEFINED); + cPref.reqKeyboardType = sa.getInt( + R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType, + Configuration.KEYBOARD_UNDEFINED); + if (sa.getBoolean( + R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard, + false)) { + cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD; + } + cPref.reqNavigation = sa.getInt( + R.styleable.AndroidManifestUsesConfiguration_reqNavigation, + Configuration.NAVIGATION_UNDEFINED); + if (sa.getBoolean( + R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav, + false)) { + cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV; + } + sa.recycle(); + parsingPackage.addConfigPreference(cPref); + + XmlUtils.skipCurrentTag(parser); + return true; + } + + private static boolean parseUsesFeature( + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser + ) throws IOException, XmlPullParserException { + FeatureInfo fi = parseFeatureInfo(res, parser); + parsingPackage.addReqFeature(fi); + + if (fi.name == null) { + ConfigurationInfo cPref = new ConfigurationInfo(); + cPref.reqGlEsVersion = fi.reqGlEsVersion; + parsingPackage.addConfigPreference(cPref); + } + + XmlUtils.skipCurrentTag(parser); + return true; + } + + private static FeatureInfo parseFeatureInfo(Resources res, AttributeSet attrs) { + FeatureInfo fi = new FeatureInfo(); + TypedArray sa = res.obtainAttributes(attrs, + R.styleable.AndroidManifestUsesFeature); + // Note: don't allow this value to be a reference to a resource + // that may change. + fi.name = sa.getNonResourceString(R.styleable.AndroidManifestUsesFeature_name); + fi.version = sa.getInt(R.styleable.AndroidManifestUsesFeature_version, 0); + if (fi.name == null) { + fi.reqGlEsVersion = sa.getInt(R.styleable.AndroidManifestUsesFeature_glEsVersion, + FeatureInfo.GL_ES_VERSION_UNDEFINED); + } + if (sa.getBoolean(R.styleable.AndroidManifestUsesFeature_required, true)) { + fi.flags |= FeatureInfo.FLAG_REQUIRED; + } + sa.recycle(); + return fi; + } + + private static boolean parseFeatureGroup( + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser + ) throws IOException, XmlPullParserException { + FeatureGroupInfo group = new FeatureGroupInfo(); + ArrayList<FeatureInfo> features = null; + final int innerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG + || parser.getDepth() > innerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + final String innerTagName = parser.getName(); + if (innerTagName.equals("uses-feature")) { + FeatureInfo featureInfo = parseFeatureInfo(res, parser); + // FeatureGroups are stricter and mandate that + // any <uses-feature> declared are mandatory. + featureInfo.flags |= FeatureInfo.FLAG_REQUIRED; + features = ArrayUtils.add(features, featureInfo); + } else { + Slog.w(TAG, + "Unknown element under <feature-group>: " + innerTagName + + " at " + parsingPackage.getBaseCodePath() + " " + + parser.getPositionDescription()); + } + XmlUtils.skipCurrentTag(parser); + } + + if (features != null) { + group.features = new FeatureInfo[features.size()]; + group.features = features.toArray(group.features); + } + + parsingPackage.addFeatureGroup(group); + return true; + } + + private static ParseResult parseUsesSdk( + ParseInput parseInput, + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser + ) throws IOException, XmlPullParserException { + if (PackageParser.SDK_VERSION > 0) { + TypedArray sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestUsesSdk); + + int minVers = 1; + String minCode = null; + int targetVers = 0; + String targetCode = null; + + TypedValue val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_minSdkVersion); + if (val != null) { + if (val.type == TypedValue.TYPE_STRING && val.string != null) { + minCode = val.string.toString(); + } else { + // If it's not a string, it's an integer. + minVers = val.data; + } + } + + val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_targetSdkVersion); + if (val != null) { + if (val.type == TypedValue.TYPE_STRING && val.string != null) { + targetCode = val.string.toString(); + if (minCode == null) { + minCode = targetCode; + } + } else { + // If it's not a string, it's an integer. + targetVers = val.data; + } + } else { + targetVers = minVers; + targetCode = minCode; + } + + sa.recycle(); + + // TODO(b/135203078): Remove, replace with ParseResult + String[] outError = new String[1]; + final int minSdkVersion = PackageParser.computeMinSdkVersion(minVers, + minCode, + PackageParser.SDK_VERSION, PackageParser.SDK_CODENAMES, outError); + if (minSdkVersion < 0) { + return parseInput.error( + PackageManager.INSTALL_FAILED_OLDER_SDK + ); + } + + final int targetSdkVersion = PackageParser.computeTargetSdkVersion( + targetVers, + targetCode, PackageParser.SDK_CODENAMES, outError); + if (targetSdkVersion < 0) { + return parseInput.error( + PackageManager.INSTALL_FAILED_OLDER_SDK + ); + } + + parsingPackage.setMinSdkVersion(minSdkVersion) + .setTargetSdkVersion(targetSdkVersion); + } + + XmlUtils.skipCurrentTag(parser); + return parseInput.success(parsingPackage); + } + + private static boolean parseRestrictUpdateHash( + int flags, + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser + ) throws IOException, XmlPullParserException { + if ((flags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0) { + TypedArray sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestRestrictUpdate); + final String hash = sa.getNonConfigurationString( + R.styleable.AndroidManifestRestrictUpdate_hash, + 0); + sa.recycle(); + + if (hash != null) { + final int hashLength = hash.length(); + final byte[] hashBytes = new byte[hashLength / 2]; + for (int i = 0; i < hashLength; i += 2) { + hashBytes[i / 2] = (byte) ((Character.digit(hash.charAt(i), 16) + << 4) + + Character.digit(hash.charAt(i + 1), 16)); + } + parsingPackage.setRestrictUpdateHash(hashBytes); + } else { + parsingPackage.setRestrictUpdateHash(null); + } + } + + XmlUtils.skipCurrentTag(parser); + return true; + } + + private static ParseResult parseQueries( + ParseInput parseInput, + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser + ) throws IOException, XmlPullParserException { + + final int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG + || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + if (parser.getName().equals("intent")) { + String[] outError = new String[1]; + ComponentParseUtils.ParsedQueriesIntentInfo intentInfo = + ComponentParseUtils.parsedParsedQueriesIntentInfo( + parsingPackage, res, parser, outError + ); + if (intentInfo == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + Uri data = null; + String dataType = null; + String host = ""; + final int numActions = intentInfo.countActions(); + final int numSchemes = intentInfo.countDataSchemes(); + final int numTypes = intentInfo.countDataTypes(); + final int numHosts = intentInfo.getHosts().length; + if ((numSchemes == 0 && numTypes == 0 && numActions == 0)) { + outError[0] = "intent tags must contain either an action or data."; + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + if (numActions > 1) { + outError[0] = "intent tag may have at most one action."; + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + if (numTypes > 1) { + outError[0] = "intent tag may have at most one data type."; + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + if (numSchemes > 1) { + outError[0] = "intent tag may have at most one data scheme."; + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + if (numHosts > 1) { + outError[0] = "intent tag may have at most one data host."; + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + Intent intent = new Intent(); + for (int i = 0, max = intentInfo.countCategories(); i < max; i++) { + intent.addCategory(intentInfo.getCategory(i)); + } + if (numHosts == 1) { + host = intentInfo.getHosts()[0]; + } + if (numSchemes == 1) { + data = new Uri.Builder() + .scheme(intentInfo.getDataScheme(0)) + .authority(host) + .build(); + } + if (numTypes == 1) { + dataType = intentInfo.getDataType(0); + } + intent.setDataAndType(data, dataType); + if (numActions == 1) { + intent.setAction(intentInfo.getAction(0)); + } + parsingPackage.addQueriesIntent(intent); + } else if (parser.getName().equals("package")) { + final TypedArray sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestQueriesPackage); + final String packageName = + sa.getString(R.styleable.AndroidManifestQueriesPackage_name); + if (TextUtils.isEmpty(packageName)) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Package name is missing from package tag." + ); + } + parsingPackage.addQueriesPackage(packageName.intern()); + } + } + return parseInput.success(parsingPackage); + } + + /** + * Parse the {@code application} XML tree at the current parse location in a + * <em>base APK</em> manifest. + * <p> + * When adding new features, carefully consider if they should also be + * supported by split APKs. + * + * @hide + */ + public static ParseResult parseBaseApplication( + ParseInput parseInput, + String[] separateProcesses, + PackageParser.Callback callback, + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser, + int flags + ) throws XmlPullParserException, IOException { + final String pkgName = parsingPackage.getPackageName(); + + // TODO(b/135203078): Remove, replace with ParseResult + String[] outError = new String[1]; + TypedArray sa = null; + + try { + sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestApplication); + + + parsingPackage + .setIconRes( + sa.getResourceId(R.styleable.AndroidManifestApplication_icon, 0)) + .setRoundIconRes( + sa.getResourceId(R.styleable.AndroidManifestApplication_roundIcon, 0)); + + ParseResult result = parsePackageItemInfo( + parseInput, + parsingPackage, + "<application>", + sa, false /*nameRequired*/, + R.styleable.AndroidManifestApplication_name, + R.styleable.AndroidManifestApplication_label, + R.styleable.AndroidManifestApplication_icon, + R.styleable.AndroidManifestApplication_roundIcon, + R.styleable.AndroidManifestApplication_logo, + R.styleable.AndroidManifestApplication_banner + ); + if (!result.isSuccess()) { + return result; + } + + String name = parsingPackage.getName(); + if (name != null) { + parsingPackage.setClassName(name); + } + + String manageSpaceActivity = sa.getNonConfigurationString( + R.styleable.AndroidManifestApplication_manageSpaceActivity, + Configuration.NATIVE_CONFIG_VERSION); + if (manageSpaceActivity != null) { + String manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity); + + if (manageSpaceActivityName == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Empty class name in package " + pkgName + ); + } + + parsingPackage.setManageSpaceActivityName(manageSpaceActivityName); + } + + boolean allowBackup = sa.getBoolean( + R.styleable.AndroidManifestApplication_allowBackup, true); + parsingPackage.setAllowBackup(allowBackup); + + if (allowBackup) { + // backupAgent, killAfterRestore, fullBackupContent, backupInForeground, + // and restoreAnyVersion are only relevant if backup is possible for the + // given application. + String backupAgent = sa.getNonConfigurationString( + R.styleable.AndroidManifestApplication_backupAgent, + Configuration.NATIVE_CONFIG_VERSION); + if (backupAgent != null) { + String backupAgentName = buildClassName(pkgName, backupAgent); + if (backupAgentName == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Empty class name in package " + pkgName + ); + } + + if (PackageParser.DEBUG_BACKUP) { + Slog.v(TAG, "android:backupAgent = " + backupAgentName + + " from " + pkgName + "+" + backupAgent); + } + + parsingPackage.setBackupAgentName(backupAgentName); + + parsingPackage.setKillAfterRestore(sa.getBoolean( + R.styleable.AndroidManifestApplication_killAfterRestore, true)); + + parsingPackage.setRestoreAnyVersion(sa.getBoolean( + R.styleable.AndroidManifestApplication_restoreAnyVersion, false)); + + parsingPackage.setFullBackupOnly(sa.getBoolean( + R.styleable.AndroidManifestApplication_fullBackupOnly, false)); + + parsingPackage.setBackupInForeground(sa.getBoolean( + R.styleable.AndroidManifestApplication_backupInForeground, + false)); + } + + TypedValue v = sa.peekValue( + R.styleable.AndroidManifestApplication_fullBackupContent); + int fullBackupContent = 0; + + if (v != null) { + fullBackupContent = v.resourceId; + + if (v.resourceId == 0) { + if (PackageParser.DEBUG_BACKUP) { + Slog.v(TAG, "fullBackupContent specified as boolean=" + + (v.data == 0 ? "false" : "true")); + } + // "false" => -1, "true" => 0 + fullBackupContent = v.data == 0 ? -1 : 0; + } + + parsingPackage.setFullBackupContent(fullBackupContent); + } + if (PackageParser.DEBUG_BACKUP) { + Slog.v(TAG, "fullBackupContent=" + fullBackupContent + " for " + pkgName); + } + } + + parsingPackage + .setTheme( + sa.getResourceId(R.styleable.AndroidManifestApplication_theme, 0)) + .setDescriptionRes( + sa.getResourceId(R.styleable.AndroidManifestApplication_description, + 0)); + + if (sa.getBoolean( + R.styleable.AndroidManifestApplication_persistent, + false)) { + // Check if persistence is based on a feature being present + final String requiredFeature = sa.getNonResourceString(R.styleable + .AndroidManifestApplication_persistentWhenFeatureAvailable); + parsingPackage.setPersistent(requiredFeature == null + || callback.hasFeature(requiredFeature)); + } + + boolean requiredForAllUsers = sa.getBoolean( + R.styleable.AndroidManifestApplication_requiredForAllUsers, + false); + parsingPackage.setRequiredForAllUsers(requiredForAllUsers); + + String restrictedAccountType = sa.getString(R.styleable + .AndroidManifestApplication_restrictedAccountType); + if (restrictedAccountType != null && restrictedAccountType.length() > 0) { + parsingPackage.setRestrictedAccountType(restrictedAccountType); + } + + String requiredAccountType = sa.getString(R.styleable + .AndroidManifestApplication_requiredAccountType); + if (requiredAccountType != null && requiredAccountType.length() > 0) { + parsingPackage.setRequiredAccountType(requiredAccountType); + } + + parsingPackage.setForceQueryable( + sa.getBoolean(R.styleable.AndroidManifestApplication_forceQueryable, false) + ); + + boolean debuggable = sa.getBoolean( + R.styleable.AndroidManifestApplication_debuggable, + false + ); + + parsingPackage.setDebuggable(debuggable); + + if (debuggable) { + // Debuggable implies profileable + parsingPackage.setProfileableByShell(true); + } + + parsingPackage.setVmSafeMode(sa.getBoolean( + R.styleable.AndroidManifestApplication_vmSafeMode, false)); + + boolean baseHardwareAccelerated = sa.getBoolean( + R.styleable.AndroidManifestApplication_hardwareAccelerated, + parsingPackage.getTargetSdkVersion() + >= Build.VERSION_CODES.ICE_CREAM_SANDWICH); + parsingPackage.setBaseHardwareAccelerated(baseHardwareAccelerated); + + parsingPackage.setHasCode(sa.getBoolean( + R.styleable.AndroidManifestApplication_hasCode, true)); + + parsingPackage.setAllowTaskReparenting(sa.getBoolean( + R.styleable.AndroidManifestApplication_allowTaskReparenting, false)); + + parsingPackage.setAllowClearUserData(sa.getBoolean( + R.styleable.AndroidManifestApplication_allowClearUserData, true)); + + parsingPackage.setTestOnly(sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestApplication_testOnly, + false)); + + parsingPackage.setLargeHeap(sa.getBoolean( + R.styleable.AndroidManifestApplication_largeHeap, false)); + + parsingPackage.setUsesCleartextTraffic(sa.getBoolean( + R.styleable.AndroidManifestApplication_usesCleartextTraffic, + parsingPackage.getTargetSdkVersion() < Build.VERSION_CODES.P)); + + parsingPackage.setSupportsRtl(sa.getBoolean( + R.styleable.AndroidManifestApplication_supportsRtl, + false /* default is no RTL support*/)); + + parsingPackage.setMultiArch(sa.getBoolean( + R.styleable.AndroidManifestApplication_multiArch, false)); + + parsingPackage.setExtractNativeLibs(sa.getBoolean( + R.styleable.AndroidManifestApplication_extractNativeLibs, true)); + + parsingPackage.setUseEmbeddedDex(sa.getBoolean( + R.styleable.AndroidManifestApplication_useEmbeddedDex, false)); + + parsingPackage.setDefaultToDeviceProtectedStorage(sa.getBoolean( + R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage, + false)); + + parsingPackage.setDirectBootAware(sa.getBoolean( + R.styleable.AndroidManifestApplication_directBootAware, false)); + + if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) { + parsingPackage.setActivitiesResizeModeResizeable(sa.getBoolean( + R.styleable.AndroidManifestApplication_resizeableActivity, true)); + } else { + parsingPackage.setActivitiesResizeModeResizeableViaSdkVersion( + parsingPackage.getTargetSdkVersion() >= Build.VERSION_CODES.N); + } + + parsingPackage.setAllowClearUserDataOnFailedRestore(sa.getBoolean( + R.styleable.AndroidManifestApplication_allowClearUserDataOnFailedRestore, + true)); + + + parsingPackage.setAllowAudioPlaybackCapture(sa.getBoolean( + R.styleable.AndroidManifestApplication_allowAudioPlaybackCapture, + parsingPackage.getTargetSdkVersion() >= Build.VERSION_CODES.Q)); + + parsingPackage.setRequestLegacyExternalStorage(sa.getBoolean( + R.styleable.AndroidManifestApplication_requestLegacyExternalStorage, + parsingPackage.getTargetSdkVersion() < Build.VERSION_CODES.Q)); + + parsingPackage + .setMaxAspectRatio( + sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0)) + .setMinAspectRatio( + sa.getFloat(R.styleable.AndroidManifestApplication_minAspectRatio, 0)) + .setNetworkSecurityConfigRes(sa.getResourceId( + R.styleable.AndroidManifestApplication_networkSecurityConfig, 0)) + .setCategory(sa.getInt(R.styleable.AndroidManifestApplication_appCategory, + ApplicationInfo.CATEGORY_UNDEFINED)); + + String str; + str = sa.getNonConfigurationString( + R.styleable.AndroidManifestApplication_permission, 0); + parsingPackage.setPermission((str != null && str.length() > 0) ? str.intern() : null); + + if (parsingPackage.getTargetSdkVersion() >= Build.VERSION_CODES.FROYO) { + str = sa.getNonConfigurationString( + R.styleable.AndroidManifestApplication_taskAffinity, + Configuration.NATIVE_CONFIG_VERSION); + } else { + // Some older apps have been seen to use a resource reference + // here that on older builds was ignored (with a warning). We + // need to continue to do this for them so they don't break. + str = sa.getNonResourceString( + R.styleable.AndroidManifestApplication_taskAffinity); + } + String packageName = parsingPackage.getPackageName(); + String taskAffinity = PackageParser.buildTaskAffinityName(packageName, + packageName, + str, outError); + + if (outError[0] != null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + parsingPackage.setTaskAffinity(taskAffinity); + String factory = sa.getNonResourceString( + R.styleable.AndroidManifestApplication_appComponentFactory); + if (factory != null) { + String appComponentFactory = buildClassName(packageName, factory); + if (appComponentFactory == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Empty class name in package " + pkgName + ); + } + + parsingPackage.setAppComponentFactory(appComponentFactory); + } + + parsingPackage.setUsesNonSdkApi(sa.getBoolean( + R.styleable.AndroidManifestApplication_usesNonSdkApi, false)); + + parsingPackage.setHasFragileUserData(sa.getBoolean( + R.styleable.AndroidManifestApplication_hasFragileUserData, false)); + + CharSequence pname; + if (parsingPackage.getTargetSdkVersion() >= Build.VERSION_CODES.FROYO) { + pname = sa.getNonConfigurationString( + R.styleable.AndroidManifestApplication_process, + Configuration.NATIVE_CONFIG_VERSION); + } else { + // Some older apps have been seen to use a resource reference + // here that on older builds was ignored (with a warning). We + // need to continue to do this for them so they don't break. + pname = sa.getNonResourceString( + R.styleable.AndroidManifestApplication_process); + } + String processName = PackageParser.buildProcessName(packageName, null, pname, flags, + separateProcesses, outError); + + if (outError[0] != null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + parsingPackage + .setProcessName(processName) + .setEnabled( + sa.getBoolean(R.styleable.AndroidManifestApplication_enabled, + true)); + + parsingPackage.setIsGame(sa.getBoolean( + R.styleable.AndroidManifestApplication_isGame, false)); + + boolean cantSaveState = sa.getBoolean( + R.styleable.AndroidManifestApplication_cantSaveState, false); + parsingPackage.setCantSaveState(cantSaveState); + if (cantSaveState) { + // A heavy-weight application can not be in a custom process. + // We can do direct compare because we intern all strings. + if (processName != null && !processName.equals(packageName)) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "cantSaveState applications can not use custom processes" + ); + } + } + + String classLoaderName = sa.getString( + R.styleable.AndroidManifestApplication_classLoader); + parsingPackage + .setUiOptions(sa.getInt(R.styleable.AndroidManifestApplication_uiOptions, 0)) + .setClassLoaderName(classLoaderName) + .setZygotePreloadName( + sa.getString(R.styleable.AndroidManifestApplication_zygotePreloadName)); + + if (classLoaderName != null + && !ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Invalid class loader name: " + classLoaderName + ); + } + } finally { + if (sa != null) { + sa.recycle(); + } + } + + final int innerDepth = parser.getDepth(); + int type; + boolean hasActivityOrder = false; + boolean hasReceiverOrder = false; + boolean hasServiceOrder = false; + + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + String tagName = parser.getName(); + switch (tagName) { + case "activity": + ComponentParseUtils.ParsedActivity activity = + ComponentParseUtils.parseActivity(separateProcesses, + parsingPackage, + res, parser, flags, + outError, false, + parsingPackage.isBaseHardwareAccelerated()); + if (activity == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + hasActivityOrder |= (activity.order != 0); + parsingPackage.addActivity(activity); + break; + case "receiver": + activity = ComponentParseUtils.parseActivity(separateProcesses, + parsingPackage, + res, parser, + flags, outError, + true, false); + if (activity == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + hasReceiverOrder |= (activity.order != 0); + parsingPackage.addReceiver(activity); + break; + case "service": + ComponentParseUtils.ParsedService s = ComponentParseUtils.parseService( + separateProcesses, + parsingPackage, + res, parser, flags, + outError); + if (s == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + hasServiceOrder |= (s.order != 0); + parsingPackage.addService(s); + break; + case "provider": + ComponentParseUtils.ParsedProvider p = ComponentParseUtils.parseProvider( + separateProcesses, + parsingPackage, + res, parser, flags, + outError + ); + if (p == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + parsingPackage.addProvider(p); + break; + case "activity-alias": + activity = ComponentParseUtils.parseActivityAlias( + parsingPackage, + res, + parser, + outError + ); + if (activity == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + hasActivityOrder |= (activity.order != 0); + parsingPackage.addActivity(activity); + break; + case "meta-data": + // note: application meta-data is stored off to the side, so it can + // remain null in the primary copy (we like to avoid extra copies because + // it can be large) + Bundle appMetaData = parseMetaData(parsingPackage, res, parser, + parsingPackage.getAppMetaData(), + outError); + if (appMetaData == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + parsingPackage.setAppMetaData(appMetaData); + break; + case "static-library": + sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestStaticLibrary); + + // Note: don't allow this value to be a reference to a resource + // that may change. + String lname = sa.getNonResourceString( + R.styleable.AndroidManifestStaticLibrary_name); + final int version = sa.getInt( + R.styleable.AndroidManifestStaticLibrary_version, -1); + final int versionMajor = sa.getInt( + R.styleable.AndroidManifestStaticLibrary_versionMajor, + 0); + + sa.recycle(); + + // Since the app canot run without a static lib - fail if malformed + if (lname == null || version < 0) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Bad static-library declaration name: " + lname + + " version: " + version + ); + } + + if (parsingPackage.getSharedUserId() != null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID, + "sharedUserId not allowed in static shared library" + ); + } + + if (parsingPackage.getStaticSharedLibName() != null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Multiple static-shared libs for package " + pkgName + ); + } + + parsingPackage.setStaticSharedLibName(lname.intern()); + if (version >= 0) { + parsingPackage.setStaticSharedLibVersion( + PackageInfo.composeLongVersionCode(versionMajor, version)); + } else { + parsingPackage.setStaticSharedLibVersion(version); + } + parsingPackage.setStaticSharedLibrary(true); + + XmlUtils.skipCurrentTag(parser); + + break; + case "library": + sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestLibrary); + + // Note: don't allow this value to be a reference to a resource + // that may change. + lname = sa.getNonResourceString( + R.styleable.AndroidManifestLibrary_name); + + sa.recycle(); + + if (lname != null) { + lname = lname.intern(); + if (!ArrayUtils.contains(parsingPackage.getLibraryNames(), lname)) { + parsingPackage.addLibraryName(lname); + } + } + + XmlUtils.skipCurrentTag(parser); + + break; + case "uses-static-library": + ParseResult parseResult = parseUsesStaticLibrary(parseInput, parsingPackage, + res, parser); + if (!parseResult.isSuccess()) { + return parseResult; + } + break; + case "uses-library": + sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestUsesLibrary); + + // Note: don't allow this value to be a reference to a resource + // that may change. + lname = sa.getNonResourceString( + R.styleable.AndroidManifestUsesLibrary_name); + boolean req = sa.getBoolean( + R.styleable.AndroidManifestUsesLibrary_required, + true); + + sa.recycle(); + + if (lname != null) { + lname = lname.intern(); + if (req) { + parsingPackage.addUsesLibrary(lname); + } else { + parsingPackage.addUsesOptionalLibrary(lname); + } + } + + XmlUtils.skipCurrentTag(parser); + + break; + case "uses-package": + // Dependencies for app installers; we don't currently try to + // enforce this. + XmlUtils.skipCurrentTag(parser); + break; + case "profileable": + sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestProfileable); + if (sa.getBoolean( + R.styleable.AndroidManifestProfileable_shell, false)) { + parsingPackage.setProfileableByShell(true); + } + XmlUtils.skipCurrentTag(parser); + + default: + if (!PackageParser.RIGID_PARSER) { + Slog.w(TAG, "Unknown element under <application>: " + tagName + + " at " + parsingPackage.getBaseCodePath() + " " + + parser.getPositionDescription()); + XmlUtils.skipCurrentTag(parser); + continue; + } else { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Bad element under <application>: " + tagName + ); + } + } + } + + if (TextUtils.isEmpty(parsingPackage.getStaticSharedLibName())) { + // Add a hidden app detail activity to normal apps which forwards user to App Details + // page. + ComponentParseUtils.ParsedActivity a = generateAppDetailsHiddenActivity( + parsingPackage, + outError + ); + // Ignore errors here + parsingPackage.addActivity(a); + } + + if (hasActivityOrder) { + parsingPackage.sortActivities(); + } + if (hasReceiverOrder) { + parsingPackage.sortReceivers(); + } + if (hasServiceOrder) { + parsingPackage.sortServices(); + } + // Must be ran after the entire {@link ApplicationInfo} has been fully processed and after + // every activity info has had a chance to set it from its attributes. + setMaxAspectRatio(parsingPackage); + setMinAspectRatio(parsingPackage, callback); + + parsingPackage.setHasDomainUrls(hasDomainURLs(parsingPackage)); + + return parseInput.success(parsingPackage); + } + + private static ParseResult parseUsesStaticLibrary( + ParseInput parseInput, + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser + ) throws XmlPullParserException, IOException { + TypedArray sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestUsesStaticLibrary); + + // Note: don't allow this value to be a reference to a resource that may change. + String lname = sa.getNonResourceString( + R.styleable.AndroidManifestUsesLibrary_name); + final int version = sa.getInt( + R.styleable.AndroidManifestUsesStaticLibrary_version, -1); + String certSha256Digest = sa.getNonResourceString(com.android.internal.R.styleable + .AndroidManifestUsesStaticLibrary_certDigest); + sa.recycle(); + + // Since an APK providing a static shared lib can only provide the lib - fail if malformed + if (lname == null || version < 0 || certSha256Digest == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Bad uses-static-library declaration name: " + lname + " version: " + + version + " certDigest" + certSha256Digest + ); + } + + // Can depend only on one version of the same library + List<String> usesStaticLibraries = parsingPackage.getUsesStaticLibraries(); + if (usesStaticLibraries != null && usesStaticLibraries.contains(lname)) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Depending on multiple versions of static library " + lname + ); + } + + lname = lname.intern(); + // We allow ":" delimiters in the SHA declaration as this is the format + // emitted by the certtool making it easy for developers to copy/paste. + certSha256Digest = certSha256Digest.replace(":", "").toLowerCase(); + + // Fot apps targeting O-MR1 we require explicit enumeration of all certs. + String[] additionalCertSha256Digests = EmptyArray.STRING; + if (parsingPackage.getTargetSdkVersion() >= Build.VERSION_CODES.O_MR1) { + // TODO(b/135203078): Remove, replace with ParseResult + String[] outError = new String[1]; + additionalCertSha256Digests = parseAdditionalCertificates(res, parser, outError); + if (additionalCertSha256Digests == null || outError[0] != null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + } else { + XmlUtils.skipCurrentTag(parser); + } + + final String[] certSha256Digests = new String[additionalCertSha256Digests.length + 1]; + certSha256Digests[0] = certSha256Digest; + System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests, + 1, additionalCertSha256Digests.length); + + parsingPackage.addUsesStaticLibrary(lname) + .addUsesStaticLibraryVersion(version) + .addUsesStaticLibraryCertDigests(certSha256Digests); + + return parseInput.success(parsingPackage); + } + + private static String[] parseAdditionalCertificates( + Resources resources, + XmlResourceParser parser, + String[] outError + ) throws XmlPullParserException, IOException { + String[] certSha256Digests = EmptyArray.STRING; + + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + final String nodeName = parser.getName(); + if (nodeName.equals("additional-certificate")) { + final TypedArray sa = resources.obtainAttributes(parser, com.android.internal. + R.styleable.AndroidManifestAdditionalCertificate); + String certSha256Digest = sa.getNonResourceString(com.android.internal. + R.styleable.AndroidManifestAdditionalCertificate_certDigest); + sa.recycle(); + + if (TextUtils.isEmpty(certSha256Digest)) { + outError[0] = "Bad additional-certificate declaration with empty" + + " certDigest:" + certSha256Digest; + XmlUtils.skipCurrentTag(parser); + sa.recycle(); + return null; + } + + // We allow ":" delimiters in the SHA declaration as this is the format + // emitted by the certtool making it easy for developers to copy/paste. + certSha256Digest = certSha256Digest.replace(":", "").toLowerCase(); + certSha256Digests = ArrayUtils.appendElement(String.class, + certSha256Digests, certSha256Digest); + } else { + XmlUtils.skipCurrentTag(parser); + } + } + + return certSha256Digests; + } + + /** + * Generate activity object that forwards user to App Details page automatically. + * This activity should be invisible to user and user should not know or see it. + * + * @hide + */ + @NonNull + private static ComponentParseUtils.ParsedActivity generateAppDetailsHiddenActivity( + ParsingPackage parsingPackage, + String[] outError + ) { + String packageName = parsingPackage.getPackageName(); + String processName = parsingPackage.getProcessName(); + boolean hardwareAccelerated = parsingPackage.isBaseHardwareAccelerated(); + int uiOptions = parsingPackage.getUiOptions(); + + // Build custom App Details activity info instead of parsing it from xml + ComponentParseUtils.ParsedActivity activity = new ComponentParseUtils.ParsedActivity(); + activity.setPackageName(packageName); + + activity.theme = android.R.style.Theme_NoDisplay; + activity.exported = true; + activity.className = PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME; + activity.setProcessName(processName, processName); + activity.uiOptions = uiOptions; + activity.taskAffinity = PackageParser.buildTaskAffinityName(packageName, + packageName, + ":app_details", outError); + activity.enabled = true; + activity.launchMode = ActivityInfo.LAUNCH_MULTIPLE; + activity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NONE; + activity.maxRecents = ActivityTaskManager.getDefaultAppRecentsLimitStatic(); + activity.configChanges = PackageParser.getActivityConfigChanges(0, 0); + activity.softInputMode = 0; + activity.persistableMode = ActivityInfo.PERSIST_NEVER; + activity.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED; + activity.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE; + activity.lockTaskLaunchMode = 0; + activity.directBootAware = false; + activity.rotationAnimation = ROTATION_ANIMATION_UNSPECIFIED; + activity.colorMode = ActivityInfo.COLOR_MODE_DEFAULT; + if (hardwareAccelerated) { + activity.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED; + } + + return activity; + } + + /** + * Check if one of the IntentFilter as both actions DEFAULT / VIEW and a HTTP/HTTPS data URI + */ + private static boolean hasDomainURLs( + ParsingPackage parsingPackage) { + final List<ComponentParseUtils.ParsedActivity> activities = parsingPackage.getActivities(); + final int countActivities = activities.size(); + for (int n = 0; n < countActivities; n++) { + ComponentParseUtils.ParsedActivity activity = activities.get(n); + List<ComponentParseUtils.ParsedActivityIntentInfo> filters = activity.intents; + if (filters == null) continue; + final int countFilters = filters.size(); + for (int m = 0; m < countFilters; m++) { + ComponentParseUtils.ParsedActivityIntentInfo aii = filters.get(m); + if (!aii.hasAction(Intent.ACTION_VIEW)) continue; + if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue; + if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) || + aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) { + return true; + } + } + } + return false; + } + + /** + * Sets the max aspect ratio of every child activity that doesn't already have an aspect + * ratio set. + */ + private static void setMaxAspectRatio( + ParsingPackage parsingPackage) { + // Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater. + // NOTE: 16.7:9 was the max aspect ratio Android devices can support pre-O per the CDD. + float maxAspectRatio = parsingPackage.getTargetSdkVersion() < O + ? PackageParser.DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0; + + float packageMaxAspectRatio = parsingPackage.getMaxAspectRatio(); + if (packageMaxAspectRatio != 0) { + // Use the application max aspect ration as default if set. + maxAspectRatio = packageMaxAspectRatio; + } else { + Bundle appMetaData = parsingPackage.getAppMetaData(); + if (appMetaData != null && appMetaData.containsKey( + PackageParser.METADATA_MAX_ASPECT_RATIO)) { + maxAspectRatio = appMetaData.getFloat(PackageParser.METADATA_MAX_ASPECT_RATIO, + maxAspectRatio); + } + } + + if (parsingPackage.getActivities() != null) { + for (ComponentParseUtils.ParsedActivity activity : parsingPackage.getActivities()) { + // If the max aspect ratio for the activity has already been set, skip. + if (activity.hasMaxAspectRatio()) { + continue; + } + + // By default we prefer to use a values defined on the activity directly than values + // defined on the application. We do not check the styled attributes on the activity + // as it would have already been set when we processed the activity. We wait to + // process the meta data here since this method is called at the end of processing + // the application and all meta data is guaranteed. + final float activityAspectRatio = activity.metaData != null + ? activity.metaData.getFloat(PackageParser.METADATA_MAX_ASPECT_RATIO, + maxAspectRatio) + : maxAspectRatio; + + activity.setMaxAspectRatio(activity.resizeMode, activityAspectRatio); + } + } + } + + /** + * Sets the min aspect ratio of every child activity that doesn't already have an aspect + * ratio set. + */ + private static void setMinAspectRatio( + ParsingPackage parsingPackage, + PackageParser.Callback callback + ) { + final float minAspectRatio; + float packageMinAspectRatio = parsingPackage.getMinAspectRatio(); + if (packageMinAspectRatio != 0) { + // Use the application max aspect ration as default if set. + minAspectRatio = packageMinAspectRatio; + } else { + // Default to (1.33) 4:3 aspect ratio for pre-Q apps and unset for Q and greater. + // NOTE: 4:3 was the min aspect ratio Android devices can support pre-Q per the CDD, + // except for watches which always supported 1:1. + minAspectRatio = parsingPackage.getTargetSdkVersion() >= Build.VERSION_CODES.Q + ? 0 + : (callback != null && callback.hasFeature(FEATURE_WATCH)) + ? PackageParser.DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH + : PackageParser.DEFAULT_PRE_Q_MIN_ASPECT_RATIO; + } + + if (parsingPackage.getActivities() != null) { + for (ComponentParseUtils.ParsedActivity activity : parsingPackage.getActivities()) { + if (activity.hasMinAspectRatio()) { + continue; + } + activity.setMinAspectRatio(activity.resizeMode, minAspectRatio); + } + } + } + + private static ParseResult parseOverlay( + ParseInput parseInput, + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser + ) throws IOException, XmlPullParserException { + + TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestResourceOverlay); + String target = sa.getString( + R.styleable.AndroidManifestResourceOverlay_targetPackage); + String targetName = sa.getString( + R.styleable.AndroidManifestResourceOverlay_targetName); + String category = sa.getString( + R.styleable.AndroidManifestResourceOverlay_category); + int priority = sa.getInt(R.styleable.AndroidManifestResourceOverlay_priority, + 0); + boolean isStatic = sa.getBoolean( + R.styleable.AndroidManifestResourceOverlay_isStatic, false); + + if (target == null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "<overlay> does not specify a target package" + ); + } + + if (priority < 0 || priority > 9999) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "<overlay> priority must be between 0 and 9999" + ); + } + + // check to see if overlay should be excluded based on system property condition + String propName = sa.getString( + R.styleable.AndroidManifestResourceOverlay_requiredSystemPropertyName); + String propValue = sa.getString( + R.styleable.AndroidManifestResourceOverlay_requiredSystemPropertyValue); + if (!checkOverlayRequiredSystemProperty(propName, propValue)) { + Slog.i(TAG, "Skipping target and overlay pair " + target + " and " + + parsingPackage.getBaseCodePath() + + ": overlay ignored due to required system property: " + + propName + " with value: " + propValue); + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + "Skipping target and overlay pair " + target + " and " + + parsingPackage.getBaseCodePath() + + ": overlay ignored due to required system property: " + + propName + " with value: " + propValue + ); + } + + parsingPackage + .setIsOverlay(true) + .setOverlayTarget(target) + .setOverlayTargetName(targetName) + .setOverlayCategory(category) + .setOverlayPriority(priority) + .setOverlayIsStatic(isStatic); + + sa.recycle(); + + XmlUtils.skipCurrentTag(parser); + return parseInput.success(parsingPackage); + } + + private static boolean parseProtectedBroadcast( + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser + ) throws IOException, XmlPullParserException { + TypedArray sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestProtectedBroadcast); + + // Note: don't allow this value to be a reference to a resource + // that may change. + String name = sa.getNonResourceString(R.styleable.AndroidManifestProtectedBroadcast_name); + + sa.recycle(); + + if (name != null) { + parsingPackage.addProtectedBroadcast(name); + } + + XmlUtils.skipCurrentTag(parser); + return true; + } + + private static boolean parseSupportScreens( + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser + ) throws IOException, XmlPullParserException { + TypedArray sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestSupportsScreens); + + int requiresSmallestWidthDp = sa.getInteger( + R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp, + 0); + int compatibleWidthLimitDp = sa.getInteger( + R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp, + 0); + int largestWidthLimitDp = sa.getInteger( + R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp, + 0); + + // This is a trick to get a boolean and still able to detect + // if a value was actually set. + parsingPackage + .setSupportsSmallScreens( + sa.getInteger(R.styleable.AndroidManifestSupportsScreens_smallScreens, 1)) + .setSupportsNormalScreens( + sa.getInteger(R.styleable.AndroidManifestSupportsScreens_normalScreens, 1)) + .setSupportsLargeScreens( + sa.getInteger(R.styleable.AndroidManifestSupportsScreens_largeScreens, 1)) + .setSupportsXLargeScreens( + sa.getInteger(R.styleable.AndroidManifestSupportsScreens_xlargeScreens, 1)) + .setResizeable( + sa.getInteger(R.styleable.AndroidManifestSupportsScreens_resizeable, 1)) + .setAnyDensity( + sa.getInteger(R.styleable.AndroidManifestSupportsScreens_anyDensity, 1)) + .setRequiresSmallestWidthDp(requiresSmallestWidthDp) + .setCompatibleWidthLimitDp(compatibleWidthLimitDp) + .setLargestWidthLimitDp(largestWidthLimitDp); + + sa.recycle(); + + XmlUtils.skipCurrentTag(parser); + return true; + } + + private static ParseResult parseInstrumentation( + ParseInput parseInput, + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser + ) throws XmlPullParserException, IOException { + // TODO(b/135203078): Remove, replace with ParseResult + String[] outError = new String[1]; + + ComponentParseUtils.ParsedInstrumentation parsedInstrumentation = + ComponentParseUtils.parseInstrumentation(parsingPackage, + res, parser, outError); + + if (parsedInstrumentation == null || outError[0] != null) { + return parseInput.error( + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, + outError[0] + ); + } + + parsingPackage.addInstrumentation(parsedInstrumentation); + + return parseInput.success(parsingPackage); + } + + private static boolean parseOriginalPackage( + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser + ) throws IOException, XmlPullParserException { + TypedArray sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestOriginalPackage); + + String orig = sa.getNonConfigurationString( + R.styleable.AndroidManifestOriginalPackage_name, + 0); + if (!parsingPackage.getPackageName().equals(orig)) { + if (parsingPackage.getOriginalPackages() == null) { + parsingPackage.setRealPackage(parsingPackage.getPackageName()); + } + parsingPackage.addOriginalPackage(orig); + } + + sa.recycle(); + + XmlUtils.skipCurrentTag(parser); + return true; + } + + private static boolean parseAdoptPermissions( + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser + ) throws IOException, XmlPullParserException { + TypedArray sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestOriginalPackage); + + String name = sa.getNonConfigurationString( + R.styleable.AndroidManifestOriginalPackage_name, + 0); + + sa.recycle(); + + if (name != null) { + parsingPackage.addAdoptPermission(name); + } + + XmlUtils.skipCurrentTag(parser); + return true; + } + + private static void convertNewPermissions( + ParsingPackage packageToParse) { + final int NP = PackageParser.NEW_PERMISSIONS.length; + StringBuilder newPermsMsg = null; + for (int ip = 0; ip < NP; ip++) { + final PackageParser.NewPermissionInfo npi + = PackageParser.NEW_PERMISSIONS[ip]; + if (packageToParse.getTargetSdkVersion() >= npi.sdkVersion) { + break; + } + if (!packageToParse.getRequestedPermissions().contains(npi.name)) { + if (newPermsMsg == null) { + newPermsMsg = new StringBuilder(128); + newPermsMsg.append(packageToParse.getPackageName()); + newPermsMsg.append(": compat added "); + } else { + newPermsMsg.append(' '); + } + newPermsMsg.append(npi.name); + packageToParse.addRequestedPermission(npi.name); + packageToParse.addImplicitPermission(npi.name); + } + } + if (newPermsMsg != null) { + Slog.i(TAG, newPermsMsg.toString()); + } + } + + private static void convertSplitPermissions(ParsingPackage packageToParse) { + List<SplitPermissionInfoParcelable> splitPermissions; + + try { + splitPermissions = ActivityThread.getPermissionManager().getSplitPermissions(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + + final int listSize = splitPermissions.size(); + for (int is = 0; is < listSize; is++) { + final SplitPermissionInfoParcelable spi = splitPermissions.get(is); + List<String> requestedPermissions = packageToParse.getRequestedPermissions(); + if (packageToParse.getTargetSdkVersion() >= spi.getTargetSdk() + || !requestedPermissions.contains(spi.getSplitPermission())) { + continue; + } + final List<String> newPerms = spi.getNewPermissions(); + for (int in = 0; in < newPerms.size(); in++) { + final String perm = newPerms.get(in); + if (!requestedPermissions.contains(perm)) { + packageToParse.addRequestedPermission(perm); + packageToParse.addImplicitPermission(perm); + } + } + } + } + + private static boolean checkOverlayRequiredSystemProperty(String propName, String propValue) { + if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) { + if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) { + // malformed condition - incomplete + Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName + + "=" + propValue + "' - require both requiredSystemPropertyName" + + " AND requiredSystemPropertyValue to be specified."); + return false; + } + // no valid condition set - so no exclusion criteria, overlay will be included. + return true; + } + + // check property value - make sure it is both set and equal to expected value + final String currValue = SystemProperties.get(propName); + return (currValue != null && currValue.equals(propValue)); + } + + /** + * This is a pre-density application which will get scaled - instead of being pixel perfect. + * This type of application is not resizable. + * + * @param parsingPackage The package which needs to be marked as unresizable. + */ + private static void adjustPackageToBeUnresizeableAndUnpipable( + ParsingPackage parsingPackage) { + if (parsingPackage.getActivities() != null) { + for (ComponentParseUtils.ParsedActivity a : parsingPackage.getActivities()) { + a.resizeMode = RESIZE_MODE_UNRESIZEABLE; + a.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE; + } + } + } + + private static String validateName(String name, boolean requireSeparator, + boolean requireFilename) { + final int N = name.length(); + boolean hasSep = false; + boolean front = true; + for (int i = 0; i < N; i++) { + final char c = name.charAt(i); + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + front = false; + continue; + } + if (!front) { + if ((c >= '0' && c <= '9') || c == '_') { + continue; + } + } + if (c == '.') { + hasSep = true; + front = true; + continue; + } + return "bad character '" + c + "'"; + } + if (requireFilename && !FileUtils.isValidExtFilename(name)) { + return "Invalid filename"; + } + return hasSep || !requireSeparator + ? null : "must have at least one '.' separator"; + } + + public static Bundle parseMetaData( + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser, Bundle data, String[] outError) + throws XmlPullParserException, IOException { + + TypedArray sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestMetaData); + + if (data == null) { + data = new Bundle(); + } + + String name = sa.getNonConfigurationString( + R.styleable.AndroidManifestMetaData_name, 0); + if (name == null) { + outError[0] = "<meta-data> requires an android:name attribute"; + sa.recycle(); + return null; + } + + name = name.intern(); + + TypedValue v = sa.peekValue( + R.styleable.AndroidManifestMetaData_resource); + if (v != null && v.resourceId != 0) { + //Slog.i(TAG, "Meta data ref " + name + ": " + v); + data.putInt(name, v.resourceId); + } else { + v = sa.peekValue( + R.styleable.AndroidManifestMetaData_value); + //Slog.i(TAG, "Meta data " + name + ": " + v); + if (v != null) { + if (v.type == TypedValue.TYPE_STRING) { + CharSequence cs = v.coerceToString(); + data.putString(name, cs != null ? cs.toString() : null); + } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) { + data.putBoolean(name, v.data != 0); + } else if (v.type >= TypedValue.TYPE_FIRST_INT + && v.type <= TypedValue.TYPE_LAST_INT) { + data.putInt(name, v.data); + } else if (v.type == TypedValue.TYPE_FLOAT) { + data.putFloat(name, v.getFloat()); + } else { + if (!PackageParser.RIGID_PARSER) { + Slog.w(TAG, + "<meta-data> only supports string, integer, float, color, " + + "boolean, and resource reference types: " + + parser.getName() + " at " + + parsingPackage.getBaseCodePath() + " " + + parser.getPositionDescription()); + } else { + outError[0] = + "<meta-data> only supports string, integer, float, color, " + + "boolean, and resource reference types"; + data = null; + } + } + } else { + outError[0] = "<meta-data> requires an android:value or android:resource attribute"; + data = null; + } + } + + sa.recycle(); + + XmlUtils.skipCurrentTag(parser); + + return data; + } + + /** + * Collect certificates from all the APKs described in the given package, + * populating {@link AndroidPackageWrite#setSigningDetails(SigningDetails)}. Also asserts that + * all APK contents are signed correctly and consistently. + */ + public static void collectCertificates(AndroidPackage pkg, boolean skipVerify) + throws PackageParserException { + pkg.mutate().setSigningDetails(SigningDetails.UNKNOWN); + + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates"); + try { + pkg.mutate().setSigningDetails(collectCertificates( + pkg.getBaseCodePath(), + skipVerify, + pkg.isStaticSharedLibrary(), + pkg.getSigningDetails() + )); + + String[] splitCodePaths = pkg.getSplitCodePaths(); + if (!ArrayUtils.isEmpty(splitCodePaths)) { + for (int i = 0; i < splitCodePaths.length; i++) { + pkg.mutate().setSigningDetails(collectCertificates( + splitCodePaths[i], + skipVerify, + pkg.isStaticSharedLibrary(), + pkg.getSigningDetails() + )); + } + } + } finally { + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); + } + } + + public static SigningDetails collectCertificates( + String baseCodePath, + boolean skipVerify, + boolean isStaticSharedLibrary, + @NonNull SigningDetails existingSigningDetails + ) throws PackageParserException { + int minSignatureScheme = SigningDetails.SignatureSchemeVersion.JAR; + if (isStaticSharedLibrary) { + // must use v2 signing scheme + minSignatureScheme = SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2; + } + SigningDetails verified; + if (skipVerify) { + // systemDir APKs are already trusted, save time by not verifying + verified = ApkSignatureVerifier.unsafeGetCertsWithoutVerification( + baseCodePath, minSignatureScheme); + } else { + verified = ApkSignatureVerifier.verify(baseCodePath, minSignatureScheme); + } + + // Verify that entries are signed consistently with the first pkg + // we encountered. Note that for splits, certificates may have + // already been populated during an earlier parse of a base APK. + if (existingSigningDetails == SigningDetails.UNKNOWN) { + return verified; + } else { + if (!Signature.areExactMatch(existingSigningDetails.signatures, verified.signatures)) { + throw new PackageParserException( + INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES, + baseCodePath + " has mismatched certificates"); + } + + return existingSigningDetails; + } + } + + @Nullable + public static String buildClassName(String pkg, CharSequence clsSeq) { + if (clsSeq == null || clsSeq.length() <= 0) { + return null; + } + String cls = clsSeq.toString(); + char c = cls.charAt(0); + if (c == '.') { + return pkg + cls; + } + if (cls.indexOf('.') < 0) { + StringBuilder b = new StringBuilder(pkg); + b.append('.'); + b.append(cls); + return b.toString(); + } + return cls; + } + + public interface ParseInput { + ParseResult success(ParsingPackage result); + + ParseResult error(int parseError); + + ParseResult error(int parseError, String errorMessage); + } + + public static class ParseResult implements ParseInput { + + private static final boolean DEBUG_FILL_STACK_TRACE = false; + + private ParsingPackage result; + + private int parseError; + private String errorMessage; + + public ParseInput reset() { + this.result = null; + this.parseError = PackageManager.INSTALL_SUCCEEDED; + this.errorMessage = null; + return this; + } + + @Override + public ParseResult success(ParsingPackage result) { + if (parseError != PackageManager.INSTALL_SUCCEEDED || errorMessage != null) { + throw new IllegalStateException("Cannot set to success after set to error"); + } + this.result = result; + return this; + } + + @Override + public ParseResult error(int parseError) { + return error(parseError, null); + } + + @Override + public ParseResult error(int parseError, String errorMessage) { + this.parseError = parseError; + this.errorMessage = errorMessage; + + if (DEBUG_FILL_STACK_TRACE) { + this.errorMessage += Arrays.toString(new Exception().getStackTrace()); + } + + return this; + } + + public ParsingPackage getResultAndNull() { + ParsingPackage result = this.result; + this.result = null; + return result; + } + + public boolean isSuccess() { + return parseError == PackageManager.INSTALL_SUCCEEDED; + } + + public int getParseError() { + return parseError; + } + + public String getErrorMessage() { + return errorMessage; + } + } +} diff --git a/core/java/android/content/pm/parsing/ComponentParseUtils.java b/core/java/android/content/pm/parsing/ComponentParseUtils.java new file mode 100644 index 000000000000..adf2a4f85780 --- /dev/null +++ b/core/java/android/content/pm/parsing/ComponentParseUtils.java @@ -0,0 +1,3289 @@ +/* + * 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.ActivityInfo.FLAG_ALWAYS_FOCUSABLE; +import static android.content.pm.ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE; +import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE; +import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; +import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED; + +import android.annotation.CallSuper; +import android.annotation.UnsupportedAppUsage; +import android.app.ActivityTaskManager; +import android.content.ComponentName; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageParser; +import android.content.pm.PathPermission; +import android.content.pm.PermissionInfo; +import android.content.pm.ProviderInfo; +import android.content.pm.ServiceInfo; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.os.Build; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PatternMatcher; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.Log; +import android.util.Slog; +import android.util.SparseArray; +import android.util.TypedValue; +import android.view.Gravity; + +import com.android.internal.R; +import com.android.internal.util.XmlUtils; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; + +/** + * TODO(b/135203078): Move the inner classes out to separate files. + * TODO(b/135203078): Expose inner classes as immutable through interface methods. + * + * @hide + */ +public class ComponentParseUtils { + + private static final String TAG = ApkParseUtils.TAG; + + // TODO(b/135203078): None of this class's subclasses do anything. Remove in favor of base? + public static class ParsedIntentInfo extends IntentFilter { + + /** + * <p> + * Implementation note: The serialized form for the intent list also contains the name + * of the concrete class that's stored in the list, and assumes that every element of the + * list is of the same type. This is very similar to the original parcelable mechanism. + * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable + * and is public API. It also declares Parcelable related methods as final which means + * we can't extend them. The approach of using composition instead of inheritance leads to + * a large set of cascading changes in the PackageManagerService, which seem undesirable. + * + * <p> + * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up + * to make sure their owner fields are consistent. See {@code fixupOwner}. + */ + public static void writeIntentsList(List<? extends ParsedIntentInfo> list, Parcel out, + int flags) { + if (list == null) { + out.writeInt(-1); + return; + } + + final int size = list.size(); + out.writeInt(size); + + // Don't bother writing the component name if the list is empty. + if (size > 0) { + ParsedIntentInfo info = list.get(0); + out.writeString(info.getClass().getName()); + + for (int i = 0; i < size; i++) { + list.get(i).writeIntentInfoToParcel(out, flags); + } + } + } + + public static <T extends ParsedIntentInfo> ArrayList<T> createIntentsList(Parcel in) { + int size = in.readInt(); + if (size == -1) { + return null; + } + + if (size == 0) { + return new ArrayList<>(0); + } + + String className = in.readString(); + final ArrayList<T> intentsList; + try { + final Class<T> cls = (Class<T>) Class.forName(className); + final Constructor<T> cons = cls.getConstructor(Parcel.class); + + intentsList = new ArrayList<>(size); + for (int i = 0; i < size; ++i) { + intentsList.add(cons.newInstance(in)); + } + } catch (ReflectiveOperationException ree) { + throw new AssertionError("Unable to construct intent list for: " + + className, ree); + } + + return intentsList; + } + + protected String packageName; + protected final String className; + + public boolean hasDefault; + public int labelRes; + public CharSequence nonLocalizedLabel; + public int icon; + + protected List<String> rawDataTypes; + + public void addRawDataType(String dataType) throws MalformedMimeTypeException { + if (rawDataTypes == null) { + rawDataTypes = new ArrayList<>(); + } + + rawDataTypes.add(dataType); + addDataType(dataType); + } + + public ParsedIntentInfo(String packageName, String className) { + this.packageName = packageName; + this.className = className; + } + + public ParsedIntentInfo(Parcel in) { + super(in); + packageName = in.readString(); + className = in.readString(); + hasDefault = (in.readInt() == 1); + labelRes = in.readInt(); + nonLocalizedLabel = in.readCharSequence(); + icon = in.readInt(); + } + + public void writeIntentInfoToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeString(packageName); + dest.writeString(className); + dest.writeInt(hasDefault ? 1 : 0); + dest.writeInt(labelRes); + dest.writeCharSequence(nonLocalizedLabel); + dest.writeInt(icon); + } + + public String getPackageName() { + return packageName; + } + + public String getClassName() { + return className; + } + } + + public static class ParsedActivityIntentInfo extends ParsedIntentInfo { + + public ParsedActivityIntentInfo(String packageName, String className) { + super(packageName, className); + } + + public ParsedActivityIntentInfo(Parcel in) { + super(in); + } + + public static final Creator<ParsedActivityIntentInfo> CREATOR = + new Creator<ParsedActivityIntentInfo>() { + @Override + public ParsedActivityIntentInfo createFromParcel(Parcel source) { + return new ParsedActivityIntentInfo(source); + } + + @Override + public ParsedActivityIntentInfo[] newArray(int size) { + return new ParsedActivityIntentInfo[size]; + } + }; + } + + public static class ParsedServiceIntentInfo extends ParsedIntentInfo { + + public ParsedServiceIntentInfo(String packageName, String className) { + super(packageName, className); + } + + public ParsedServiceIntentInfo(Parcel in) { + super(in); + } + + public static final Creator<ParsedServiceIntentInfo> CREATOR = + new Creator<ParsedServiceIntentInfo>() { + @Override + public ParsedServiceIntentInfo createFromParcel(Parcel source) { + return new ParsedServiceIntentInfo(source); + } + + @Override + public ParsedServiceIntentInfo[] newArray(int size) { + return new ParsedServiceIntentInfo[size]; + } + }; + } + + public static class ParsedProviderIntentInfo extends ParsedIntentInfo { + + public ParsedProviderIntentInfo(String packageName, String className) { + super(packageName, className); + } + + public ParsedProviderIntentInfo(Parcel in) { + super(in); + } + + public static final Creator<ParsedProviderIntentInfo> CREATOR = + new Creator<ParsedProviderIntentInfo>() { + @Override + public ParsedProviderIntentInfo createFromParcel(Parcel source) { + return new ParsedProviderIntentInfo(source); + } + + @Override + public ParsedProviderIntentInfo[] newArray(int size) { + return new ParsedProviderIntentInfo[size]; + } + }; + } + + public static class ParsedQueriesIntentInfo extends ParsedIntentInfo { + + public ParsedQueriesIntentInfo(String packageName, String className) { + super(packageName, className); + } + + public ParsedQueriesIntentInfo(Parcel in) { + super(in); + } + + public static final Creator<ParsedQueriesIntentInfo> CREATOR = + new Creator<ParsedQueriesIntentInfo>() { + @Override + public ParsedQueriesIntentInfo createFromParcel(Parcel source) { + return new ParsedQueriesIntentInfo(source); + } + + @Override + public ParsedQueriesIntentInfo[] newArray(int size) { + return new ParsedQueriesIntentInfo[size]; + } + }; + } + + public static class ParsedComponent<IntentInfoType extends ParsedIntentInfo> implements + Parcelable { + + // TODO(b/135203078): Replace with "name", as not all usages are an actual class + public String className; + public int icon; + public int labelRes; + public CharSequence nonLocalizedLabel; + public int logo; + public int banner; + + public int descriptionRes; + + // TODO(b/135203078): Make subclass that contains these fields only for the necessary + // subtypes + protected boolean enabled = true; + protected boolean directBootAware; + public int flags; + + private String packageName; + private String splitName; + + // TODO(b/135203078): Make nullable + public List<IntentInfoType> intents = new ArrayList<>(); + + private transient ComponentName componentName; + + protected Bundle metaData; + + public void setSplitName(String splitName) { + this.splitName = splitName; + } + + public String getSplitName() { + return splitName; + } + + @CallSuper + public void setPackageName(String packageName) { + this.packageName = packageName; + this.componentName = null; + } + + void setPackageNameInternal(String packageName) { + this.packageName = packageName; + this.componentName = null; + } + + public String getPackageName() { + return packageName; + } + + public final boolean isDirectBootAware() { + return directBootAware; + } + + public final boolean isEnabled() { + return enabled; + } + + public final String getName() { + return className; + } + + public final Bundle getMetaData() { + return metaData; + } + + @UnsupportedAppUsage + public ComponentName getComponentName() { + if (componentName != null) { + return componentName; + } + if (className != null) { + componentName = new ComponentName(getPackageName(), + className); + } + return componentName; + } + + public void setFrom(ParsedComponent other) { + this.metaData = other.metaData; + this.className = other.className; + this.icon = other.icon; + this.labelRes = other.labelRes; + this.nonLocalizedLabel = other.nonLocalizedLabel; + this.logo = other.logo; + this.banner = other.banner; + + this.descriptionRes = other.descriptionRes; + + this.enabled = other.enabled; + this.directBootAware = other.directBootAware; + this.flags = other.flags; + + this.setPackageName(other.packageName); + this.setSplitName(other.getSplitName()); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(this.className); + dest.writeInt(this.icon); + dest.writeInt(this.labelRes); + dest.writeCharSequence(this.nonLocalizedLabel); + dest.writeInt(this.logo); + dest.writeInt(this.banner); + dest.writeInt(this.descriptionRes); + dest.writeBoolean(this.enabled); + dest.writeBoolean(this.directBootAware); + dest.writeInt(this.flags); + dest.writeString(this.packageName); + dest.writeString(this.splitName); + ParsedIntentInfo.writeIntentsList(this.intents, dest, flags); + dest.writeBundle(this.metaData); + } + + public ParsedComponent() { + } + + protected ParsedComponent(Parcel in) { + // We use the boot classloader for all classes that we load. + final ClassLoader boot = Object.class.getClassLoader(); + this.className = in.readString(); + this.icon = in.readInt(); + this.labelRes = in.readInt(); + this.nonLocalizedLabel = in.readCharSequence(); + this.logo = in.readInt(); + this.banner = in.readInt(); + this.descriptionRes = in.readInt(); + this.enabled = in.readByte() != 0; + this.directBootAware = in.readByte() != 0; + this.flags = in.readInt(); + this.packageName = in.readString(); + this.splitName = in.readString(); + this.intents = ParsedIntentInfo.createIntentsList(in); + this.metaData = in.readBundle(boot); + } + } + + // TODO(b/135203078): Document this. Maybe split out ParsedComponent to be actual components + // that can have their own processes, rather than something like permission which cannot. + public static class ParsedMainComponent<IntentInfoType extends ParsedIntentInfo> extends + ParsedComponent<IntentInfoType> { + + private String processName; + private String permission; + + public void setProcessName(String appProcessName, String processName) { + // TODO(b/135203078): Is this even necessary anymore? + this.processName = TextUtils.safeIntern( + processName == null ? appProcessName : processName); + } + + public String getProcessName() { + return processName; + } + + public void setPermission(String permission) { + this.permission = TextUtils.safeIntern(permission); + } + + public String getPermission() { + return permission; + } + + @Override + public void setFrom(ParsedComponent other) { + super.setFrom(other); + if (other instanceof ParsedMainComponent) { + ParsedMainComponent otherMainComponent = (ParsedMainComponent) other; + this.setProcessName(otherMainComponent.getProcessName(), + otherMainComponent.getProcessName()); + this.setPermission(otherMainComponent.getPermission()); + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeString(this.processName); + dest.writeString(this.permission); + } + + public ParsedMainComponent() { + } + + protected ParsedMainComponent(Parcel in) { + super(in); + this.processName = TextUtils.safeIntern(in.readString()); + this.permission = TextUtils.safeIntern(in.readString()); + } + + public static final Creator<ParsedMainComponent> CREATOR = + new Creator<ParsedMainComponent>() { + @Override + public ParsedMainComponent createFromParcel(Parcel source) { + return new ParsedMainComponent(source); + } + + @Override + public ParsedMainComponent[] newArray(int size) { + return new ParsedMainComponent[size]; + } + }; + } + + public static class ParsedActivity extends ParsedMainComponent<ParsedActivityIntentInfo> + implements Parcelable { + + public boolean exported; + public int theme; + public int uiOptions; + + public String targetActivity; + + public String parentActivityName; + public String taskAffinity; + public int privateFlags; + + public int launchMode; + public int documentLaunchMode; + public int maxRecents; + public int configChanges; + public int softInputMode; + public int persistableMode; + public int lockTaskLaunchMode; + + public int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; + public int resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE; + + public float maxAspectRatio; + public boolean hasMaxAspectRatio; + + public float minAspectRatio; + public boolean hasMinAspectRatio; + + public String requestedVrComponent; + public int rotationAnimation = -1; + public int colorMode; + public int order; + + public ActivityInfo.WindowLayout windowLayout; + + @Override + public void setPackageName(String packageName) { + super.setPackageName(packageName); + for (ParsedIntentInfo intent : this.intents) { + intent.packageName = packageName; + } + } + + public boolean hasMaxAspectRatio() { + return hasMaxAspectRatio; + } + + public boolean hasMinAspectRatio() { + return hasMinAspectRatio; + } + + public void setMaxAspectRatio(int resizeMode, float maxAspectRatio) { + if (resizeMode == ActivityInfo.RESIZE_MODE_RESIZEABLE + || resizeMode == ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) { + // Resizeable activities can be put in any aspect ratio. + return; + } + + if (maxAspectRatio < 1.0f && maxAspectRatio != 0) { + // Ignore any value lesser than 1.0. + return; + } + + this.maxAspectRatio = maxAspectRatio; + hasMaxAspectRatio = true; + } + + public void setMinAspectRatio(int resizeMode, float minAspectRatio) { + if (resizeMode == RESIZE_MODE_RESIZEABLE + || resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) { + // Resizeable activities can be put in any aspect ratio. + return; + } + + if (minAspectRatio < 1.0f && minAspectRatio != 0) { + // Ignore any value lesser than 1.0. + return; + } + + this.minAspectRatio = minAspectRatio; + hasMinAspectRatio = true; + } + + public void addIntent(ParsedActivityIntentInfo intent) { + this.intents.add(intent); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeBoolean(this.exported); + dest.writeInt(this.theme); + dest.writeInt(this.uiOptions); + dest.writeString(this.targetActivity); + dest.writeString(this.parentActivityName); + dest.writeString(this.taskAffinity); + dest.writeInt(this.privateFlags); + dest.writeInt(this.launchMode); + dest.writeInt(this.documentLaunchMode); + dest.writeInt(this.maxRecents); + dest.writeInt(this.configChanges); + dest.writeInt(this.softInputMode); + dest.writeInt(this.persistableMode); + dest.writeInt(this.lockTaskLaunchMode); + dest.writeInt(this.screenOrientation); + dest.writeInt(this.resizeMode); + dest.writeFloat(this.maxAspectRatio); + dest.writeBoolean(this.hasMaxAspectRatio); + dest.writeFloat(this.minAspectRatio); + dest.writeBoolean(this.hasMinAspectRatio); + dest.writeString(this.requestedVrComponent); + dest.writeInt(this.rotationAnimation); + dest.writeInt(this.colorMode); + dest.writeInt(this.order); + dest.writeBundle(this.metaData); + + if (windowLayout != null) { + dest.writeInt(1); + dest.writeInt(windowLayout.width); + dest.writeFloat(windowLayout.widthFraction); + dest.writeInt(windowLayout.height); + dest.writeFloat(windowLayout.heightFraction); + dest.writeInt(windowLayout.gravity); + dest.writeInt(windowLayout.minWidth); + dest.writeInt(windowLayout.minHeight); + } else { + dest.writeInt(0); + } + } + + public ParsedActivity() { + } + + protected ParsedActivity(Parcel in) { + super(in); + this.exported = in.readByte() != 0; + this.theme = in.readInt(); + this.uiOptions = in.readInt(); + this.targetActivity = in.readString(); + this.parentActivityName = in.readString(); + this.taskAffinity = in.readString(); + this.privateFlags = in.readInt(); + this.launchMode = in.readInt(); + this.documentLaunchMode = in.readInt(); + this.maxRecents = in.readInt(); + this.configChanges = in.readInt(); + this.softInputMode = in.readInt(); + this.persistableMode = in.readInt(); + this.lockTaskLaunchMode = in.readInt(); + this.screenOrientation = in.readInt(); + this.resizeMode = in.readInt(); + this.maxAspectRatio = in.readFloat(); + this.hasMaxAspectRatio = in.readByte() != 0; + this.minAspectRatio = in.readFloat(); + this.hasMinAspectRatio = in.readByte() != 0; + this.requestedVrComponent = in.readString(); + this.rotationAnimation = in.readInt(); + this.colorMode = in.readInt(); + this.order = in.readInt(); + this.metaData = in.readBundle(); + if (in.readInt() == 1) { + windowLayout = new ActivityInfo.WindowLayout(in); + } + } + + public static final Creator<ParsedActivity> CREATOR = new Creator<ParsedActivity>() { + @Override + public ParsedActivity createFromParcel(Parcel source) { + return new ParsedActivity(source); + } + + @Override + public ParsedActivity[] newArray(int size) { + return new ParsedActivity[size]; + } + }; + } + + public static class ParsedService extends ParsedMainComponent<ParsedServiceIntentInfo> { + + public boolean exported; + public int flags; + public int foregroundServiceType; + public int order; + + @Override + public void setPackageName(String packageName) { + super.setPackageName(packageName); + for (ParsedIntentInfo intent : this.intents) { + intent.packageName = packageName; + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeBoolean(this.exported); + dest.writeBundle(this.metaData); + dest.writeInt(this.flags); + dest.writeInt(this.foregroundServiceType); + dest.writeInt(this.order); + } + + public ParsedService() { + } + + protected ParsedService(Parcel in) { + super(in); + this.exported = in.readByte() != 0; + this.metaData = in.readBundle(); + this.flags = in.readInt(); + this.foregroundServiceType = in.readInt(); + this.order = in.readInt(); + } + + public static final Creator<ParsedService> CREATOR = new Creator<ParsedService>() { + @Override + public ParsedService createFromParcel(Parcel source) { + return new ParsedService(source); + } + + @Override + public ParsedService[] newArray(int size) { + return new ParsedService[size]; + } + }; + } + + public static class ParsedProvider extends ParsedMainComponent<ParsedProviderIntentInfo> { + + protected boolean exported; + protected int flags; + protected int order; + private String authority; + protected boolean isSyncable; + private String readPermission; + private String writePermission; + protected boolean grantUriPermissions; + protected boolean forceUriPermissions; + protected boolean multiProcess; + protected int initOrder; + protected PatternMatcher[] uriPermissionPatterns; + protected PathPermission[] pathPermissions; + + protected void setFrom(ParsedProvider other) { + super.setFrom(other); + this.exported = other.exported; + + this.intents.clear(); + if (other.intents != null) { + this.intents.addAll(other.intents); + } + + this.flags = other.flags; + this.order = other.order; + this.setAuthority(other.getAuthority()); + this.isSyncable = other.isSyncable; + this.setReadPermission(other.getReadPermission()); + this.setWritePermission(other.getWritePermission()); + this.grantUriPermissions = other.grantUriPermissions; + this.forceUriPermissions = other.forceUriPermissions; + this.multiProcess = other.multiProcess; + this.initOrder = other.initOrder; + this.uriPermissionPatterns = other.uriPermissionPatterns; + this.pathPermissions = other.pathPermissions; + } + + @Override + public void setPackageName(String packageName) { + super.setPackageName(packageName); + for (ParsedIntentInfo intent : this.intents) { + intent.packageName = packageName; + } + } + + public boolean isExported() { + return exported; + } + + public List<ParsedProviderIntentInfo> getIntents() { + return intents; + } + + public int getFlags() { + return flags; + } + + public int getOrder() { + return order; + } + + public void setAuthority(String authority) { + this.authority = TextUtils.safeIntern(authority); + } + + public String getAuthority() { + return authority; + } + + public boolean isSyncable() { + return isSyncable; + } + + public void setReadPermission(String readPermission) { + this.readPermission = TextUtils.safeIntern(readPermission); + } + + public String getReadPermission() { + return readPermission; + } + + public void setWritePermission(String writePermission) { + this.writePermission = TextUtils.safeIntern(writePermission); + } + + public String getWritePermission() { + return writePermission; + } + + public boolean isGrantUriPermissions() { + return grantUriPermissions; + } + + public boolean isForceUriPermissions() { + return forceUriPermissions; + } + + public boolean isMultiProcess() { + return multiProcess; + } + + public int getInitOrder() { + return initOrder; + } + + public PatternMatcher[] getUriPermissionPatterns() { + return uriPermissionPatterns; + } + + public PathPermission[] getPathPermissions() { + return pathPermissions; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeBoolean(this.exported); + dest.writeInt(this.flags); + dest.writeInt(this.order); + dest.writeString(this.authority); + dest.writeBoolean(this.isSyncable); + dest.writeString(this.readPermission); + dest.writeString(this.writePermission); + dest.writeBoolean(this.grantUriPermissions); + dest.writeBoolean(this.forceUriPermissions); + dest.writeBoolean(this.multiProcess); + dest.writeInt(this.initOrder); + dest.writeTypedArray(this.uriPermissionPatterns, flags); + dest.writeTypedArray(this.pathPermissions, flags); + } + + public ParsedProvider() { + } + + protected ParsedProvider(Parcel in) { + super(in); + this.exported = in.readByte() != 0; + this.flags = in.readInt(); + this.order = in.readInt(); + this.authority = TextUtils.safeIntern(in.readString()); + this.isSyncable = in.readByte() != 0; + this.readPermission = TextUtils.safeIntern(in.readString()); + this.writePermission = TextUtils.safeIntern(in.readString()); + this.grantUriPermissions = in.readByte() != 0; + this.forceUriPermissions = in.readByte() != 0; + this.multiProcess = in.readByte() != 0; + this.initOrder = in.readInt(); + this.uriPermissionPatterns = in.createTypedArray(PatternMatcher.CREATOR); + this.pathPermissions = in.createTypedArray(PathPermission.CREATOR); + } + + public static final Creator<ParsedProvider> CREATOR = new Creator<ParsedProvider>() { + @Override + public ParsedProvider createFromParcel(Parcel source) { + return new ParsedProvider(source); + } + + @Override + public ParsedProvider[] newArray(int size) { + return new ParsedProvider[size]; + } + }; + } + + public static class ParsedPermission extends ParsedComponent<ParsedIntentInfo> { + + public String backgroundPermission; + private String group; + public int requestRes; + public int protectionLevel; + public boolean tree; + + public ParsedPermissionGroup parsedPermissionGroup; + + public void setName(String className) { + this.className = className; + } + + public void setGroup(String group) { + this.group = TextUtils.safeIntern(group); + } + + public String getGroup() { + return group; + } + + public boolean isRuntime() { + return protectionLevel == PermissionInfo.PROTECTION_DANGEROUS; + } + + public boolean isAppOp() { + return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0; + } + + @PermissionInfo.Protection + public int getProtection() { + return protectionLevel & PermissionInfo.PROTECTION_MASK_BASE; + } + + public int getProtectionFlags() { + return protectionLevel & ~PermissionInfo.PROTECTION_MASK_BASE; + } + + public int calculateFootprint() { + int size = getName().length(); + if (nonLocalizedLabel != null) { + size += nonLocalizedLabel.length(); + } + return size; + } + + public ParsedPermission() { + } + + public ParsedPermission(ParsedPermission other) { + // TODO(b/135203078): Better way to copy this? Maybe refactor to the point where copy + // isn't needed. + this.className = other.className; + this.icon = other.icon; + this.labelRes = other.labelRes; + this.nonLocalizedLabel = other.nonLocalizedLabel; + this.logo = other.logo; + this.banner = other.banner; + this.descriptionRes = other.descriptionRes; + this.enabled = other.enabled; + this.directBootAware = other.directBootAware; + this.flags = other.flags; + this.setSplitName(other.getSplitName()); + this.setPackageName(other.getPackageName()); + + this.intents.addAll(other.intents); + + if (other.metaData != null) { + this.metaData = new Bundle(); + this.metaData.putAll(other.metaData); + } + + this.backgroundPermission = other.backgroundPermission; + this.setGroup(other.group); + this.requestRes = other.requestRes; + this.protectionLevel = other.protectionLevel; + this.tree = other.tree; + + this.parsedPermissionGroup = other.parsedPermissionGroup; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeString(this.backgroundPermission); + dest.writeString(this.group); + dest.writeInt(this.requestRes); + dest.writeInt(this.protectionLevel); + dest.writeBoolean(this.tree); + dest.writeParcelable(this.parsedPermissionGroup, flags); + } + + protected ParsedPermission(Parcel in) { + super(in); + // We use the boot classloader for all classes that we load. + final ClassLoader boot = Object.class.getClassLoader(); + this.backgroundPermission = in.readString(); + this.group = TextUtils.safeIntern(in.readString()); + this.requestRes = in.readInt(); + this.protectionLevel = in.readInt(); + this.tree = in.readBoolean(); + this.parsedPermissionGroup = in.readParcelable(boot); + } + + public static final Creator<ParsedPermission> CREATOR = new Creator<ParsedPermission>() { + @Override + public ParsedPermission createFromParcel(Parcel source) { + return new ParsedPermission(source); + } + + @Override + public ParsedPermission[] newArray(int size) { + return new ParsedPermission[size]; + } + }; + } + + public static class ParsedPermissionGroup extends ParsedComponent<ParsedIntentInfo> { + + public int requestDetailResourceId; + public int backgroundRequestResourceId; + public int backgroundRequestDetailResourceId; + + public int requestRes; + public int priority; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeInt(this.requestDetailResourceId); + dest.writeInt(this.backgroundRequestResourceId); + dest.writeInt(this.backgroundRequestDetailResourceId); + dest.writeInt(this.requestRes); + dest.writeInt(this.priority); + } + + public ParsedPermissionGroup() { + } + + protected ParsedPermissionGroup(Parcel in) { + super(in); + this.requestDetailResourceId = in.readInt(); + this.backgroundRequestResourceId = in.readInt(); + this.backgroundRequestDetailResourceId = in.readInt(); + this.requestRes = in.readInt(); + this.priority = in.readInt(); + } + + public static final Creator<ParsedPermissionGroup> CREATOR = + new Creator<ParsedPermissionGroup>() { + @Override + public ParsedPermissionGroup createFromParcel(Parcel source) { + return new ParsedPermissionGroup(source); + } + + @Override + public ParsedPermissionGroup[] newArray(int size) { + return new ParsedPermissionGroup[size]; + } + }; + } + + public static class ParsedInstrumentation extends ParsedComponent<ParsedIntentInfo> { + + private String targetPackage; + private String targetProcesses; + public boolean handleProfiling; + public boolean functionalTest; + + public String sourceDir; + public String publicSourceDir; + public String[] splitNames; + public String[] splitSourceDirs; + public String[] splitPublicSourceDirs; + public SparseArray<int[]> splitDependencies; + public String dataDir; + public String deviceProtectedDataDir; + public String credentialProtectedDataDir; + public String primaryCpuAbi; + public String secondaryCpuAbi; + public String nativeLibraryDir; + public String secondaryNativeLibraryDir; + + public ParsedInstrumentation() { + } + + public void setTargetPackage(String targetPackage) { + this.targetPackage = TextUtils.safeIntern(targetPackage); + } + + public String getTargetPackage() { + return targetPackage; + } + + public void setTargetProcesses(String targetProcesses) { + this.targetProcesses = TextUtils.safeIntern(targetProcesses); + } + + public String getTargetProcesses() { + return targetProcesses; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeString(this.targetPackage); + dest.writeString(this.targetProcesses); + dest.writeBoolean(this.handleProfiling); + dest.writeBoolean(this.functionalTest); + dest.writeString(this.sourceDir); + dest.writeString(this.publicSourceDir); + dest.writeStringArray(this.splitNames); + dest.writeStringArray(this.splitSourceDirs); + dest.writeStringArray(this.splitPublicSourceDirs); + dest.writeSparseArray(this.splitDependencies); + dest.writeString(this.dataDir); + dest.writeString(this.deviceProtectedDataDir); + dest.writeString(this.credentialProtectedDataDir); + dest.writeString(this.primaryCpuAbi); + dest.writeString(this.secondaryCpuAbi); + dest.writeString(this.nativeLibraryDir); + dest.writeString(this.secondaryNativeLibraryDir); + } + + protected ParsedInstrumentation(Parcel in) { + super(in); + // We use the boot classloader for all classes that we load. + final ClassLoader boot = Object.class.getClassLoader(); + this.targetPackage = TextUtils.safeIntern(in.readString()); + this.targetProcesses = TextUtils.safeIntern(in.readString()); + this.handleProfiling = in.readByte() != 0; + this.functionalTest = in.readByte() != 0; + this.sourceDir = in.readString(); + this.publicSourceDir = in.readString(); + this.splitNames = in.createStringArray(); + this.splitSourceDirs = in.createStringArray(); + this.splitPublicSourceDirs = in.createStringArray(); + this.splitDependencies = in.readSparseArray(boot); + this.dataDir = in.readString(); + this.deviceProtectedDataDir = in.readString(); + this.credentialProtectedDataDir = in.readString(); + this.primaryCpuAbi = in.readString(); + this.secondaryCpuAbi = in.readString(); + this.nativeLibraryDir = in.readString(); + this.secondaryNativeLibraryDir = in.readString(); + } + + public static final Creator<ParsedInstrumentation> CREATOR = + new Creator<ParsedInstrumentation>() { + @Override + public ParsedInstrumentation createFromParcel(Parcel source) { + return new ParsedInstrumentation(source); + } + + @Override + public ParsedInstrumentation[] newArray(int size) { + return new ParsedInstrumentation[size]; + } + }; + } + + public static ParsedActivity parseActivity( + String[] separateProcesses, + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser, int flags, String[] outError, + boolean receiver, boolean hardwareAccelerated) + throws XmlPullParserException, IOException { + + TypedArray sa = null; + boolean visibleToEphemeral; + boolean setExported; + + int targetSdkVersion = parsingPackage.getTargetSdkVersion(); + String packageName = parsingPackage.getPackageName(); + String packageProcessName = parsingPackage.getProcessName(); + ParsedActivity result = new ParsedActivity(); + + try { + sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity); + + String tag = receiver ? "<receiver>" : "<activity>"; + + String name = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_name, 0); + if (name == null) { + outError[0] = tag + " does not specify android:name"; + return null; + } else { + String className = ApkParseUtils.buildClassName(packageName, name); + if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)) { + outError[0] = tag + " invalid android:name"; + return null; + } else if (className == null) { + outError[0] = "Empty class name in package " + packageName; + return null; + } + + result.className = className; + } + + int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId( + R.styleable.AndroidManifestActivity_roundIcon, 0) : 0; + if (roundIconVal != 0) { + result.icon = roundIconVal; + result.nonLocalizedLabel = null; + } else { + int iconVal = sa.getResourceId(R.styleable.AndroidManifestActivity_icon, 0); + if (iconVal != 0) { + result.icon = iconVal; + result.nonLocalizedLabel = null; + } + } + + int logoVal = sa.getResourceId(R.styleable.AndroidManifestActivity_logo, 0); + if (logoVal != 0) { + result.logo = logoVal; + } + + int bannerVal = sa.getResourceId(R.styleable.AndroidManifestActivity_banner, 0); + if (bannerVal != 0) { + result.banner = bannerVal; + } + + TypedValue v = sa.peekValue(R.styleable.AndroidManifestActivity_label); + if (v != null && (result.labelRes = v.resourceId) == 0) { + result.nonLocalizedLabel = v.coerceToString(); + } + + result.setPackageNameInternal(packageName); + + CharSequence pname; + if (parsingPackage.getTargetSdkVersion() >= Build.VERSION_CODES.FROYO) { + pname = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_process, + Configuration.NATIVE_CONFIG_VERSION); + } else { + // Some older apps have been seen to use a resource reference + // here that on older builds was ignored (with a warning). We + // need to continue to do this for them so they don't break. + pname = sa.getNonResourceString(R.styleable.AndroidManifestActivity_process); + } + + result.setProcessName(packageProcessName, PackageParser.buildProcessName(packageName, + packageProcessName, pname, + flags, separateProcesses, outError)); + + result.descriptionRes = sa.getResourceId( + R.styleable.AndroidManifestActivity_description, 0); + + result.enabled = sa.getBoolean(R.styleable.AndroidManifestActivity_enabled, true); + + setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported); + if (setExported) { + result.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, + false); + } + + result.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0); + + result.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions, + parsingPackage.getUiOptions()); + + String parentName = sa.getNonConfigurationString( + R.styleable.AndroidManifestActivity_parentActivityName, + Configuration.NATIVE_CONFIG_VERSION); + if (parentName != null) { + String parentClassName = ApkParseUtils.buildClassName(packageName, parentName); + if (parentClassName == null) { + Log.e(TAG, + "Activity " + result.className + + " specified invalid parentActivityName " + + parentName); + } else { + result.parentActivityName = parentClassName; + } + } + + String str; + str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0); + if (str == null) { + result.setPermission(parsingPackage.getPermission()); + } else { + result.setPermission(str); + } + + str = sa.getNonConfigurationString( + R.styleable.AndroidManifestActivity_taskAffinity, + Configuration.NATIVE_CONFIG_VERSION); + result.taskAffinity = PackageParser.buildTaskAffinityName( + packageName, + parsingPackage.getTaskAffinity(), str, outError); + + result.setSplitName( + sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_splitName, 0)); + + result.flags = 0; + if (sa.getBoolean( + R.styleable.AndroidManifestActivity_multiprocess, false)) { + result.flags |= ActivityInfo.FLAG_MULTIPROCESS; + } + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) { + result.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH; + } + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) { + result.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH; + } + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) { + result.flags |= ActivityInfo.FLAG_NO_HISTORY; + } + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) { + result.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE; + } + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) { + result.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED; + } + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) { + result.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS; + } + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting, + (parsingPackage.getFlags() & ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) + != 0)) { + result.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING; + } + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, + false)) { + result.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS; + } + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false) + || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) { + result.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS; + } + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) { + result.flags |= ActivityInfo.FLAG_IMMERSIVE; + } + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) { + result.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY; + } + + boolean directBootAware; + + if (!receiver) { + if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated, + hardwareAccelerated)) { + result.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED; + } + + result.launchMode = sa.getInt( + R.styleable.AndroidManifestActivity_launchMode, + ActivityInfo.LAUNCH_MULTIPLE); + result.documentLaunchMode = sa.getInt( + R.styleable.AndroidManifestActivity_documentLaunchMode, + ActivityInfo.DOCUMENT_LAUNCH_NONE); + result.maxRecents = sa.getInt( + R.styleable.AndroidManifestActivity_maxRecents, + ActivityTaskManager.getDefaultAppRecentsLimitStatic()); + result.configChanges = PackageParser.getActivityConfigChanges( + sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0), + sa.getInt(R.styleable.AndroidManifestActivity_recreateOnConfigChanges, 0)); + result.softInputMode = sa.getInt( + R.styleable.AndroidManifestActivity_windowSoftInputMode, 0); + + result.persistableMode = sa.getInteger( + R.styleable.AndroidManifestActivity_persistableMode, + ActivityInfo.PERSIST_ROOT_ONLY); + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) { + result.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED; + } + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, + false)) { + result.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS; + } + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, + false)) { + result.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY; + } + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) { + result.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING; + } + + int screenOrientation = sa.getInt( + R.styleable.AndroidManifestActivity_screenOrientation, + SCREEN_ORIENTATION_UNSPECIFIED); + result.screenOrientation = screenOrientation; + + int resizeMode = getActivityResizeMode(parsingPackage, sa, screenOrientation); + result.resizeMode = resizeMode; + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture, + false)) { + result.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE; + } + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) { + result.flags |= FLAG_ALWAYS_FOCUSABLE; + } + + if (sa.hasValue(R.styleable.AndroidManifestActivity_maxAspectRatio) + && sa.getType(R.styleable.AndroidManifestActivity_maxAspectRatio) + == TypedValue.TYPE_FLOAT) { + result.setMaxAspectRatio(resizeMode, + sa.getFloat(R.styleable.AndroidManifestActivity_maxAspectRatio, + 0 /*default*/)); + } + + if (sa.hasValue(R.styleable.AndroidManifestActivity_minAspectRatio) + && sa.getType(R.styleable.AndroidManifestActivity_minAspectRatio) + == TypedValue.TYPE_FLOAT) { + result.setMinAspectRatio(resizeMode, + sa.getFloat(R.styleable.AndroidManifestActivity_minAspectRatio, + 0 /*default*/)); + } + + result.lockTaskLaunchMode = + sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0); + + directBootAware = sa.getBoolean( + R.styleable.AndroidManifestActivity_directBootAware, + false); + + result.requestedVrComponent = + sa.getString(R.styleable.AndroidManifestActivity_enableVrMode); + + result.rotationAnimation = + sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, + ROTATION_ANIMATION_UNSPECIFIED); + + result.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode, + ActivityInfo.COLOR_MODE_DEFAULT); + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_showWhenLocked, false)) { + result.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED; + } + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_turnScreenOn, false)) { + result.flags |= ActivityInfo.FLAG_TURN_SCREEN_ON; + } + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_inheritShowWhenLocked, + false)) { + result.privateFlags |= ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED; + } + } else { + result.launchMode = ActivityInfo.LAUNCH_MULTIPLE; + result.configChanges = 0; + + if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) { + result.flags |= ActivityInfo.FLAG_SINGLE_USER; + } + directBootAware = sa.getBoolean( + R.styleable.AndroidManifestActivity_directBootAware, + false); + } + + result.directBootAware = directBootAware; + + if (directBootAware) { + parsingPackage.setPartiallyDirectBootAware(true); + } + + // can't make this final; we may set it later via meta-data + visibleToEphemeral = sa.getBoolean( + R.styleable.AndroidManifestActivity_visibleToInstantApps, false); + if (visibleToEphemeral) { + result.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP; + parsingPackage.setVisibleToInstantApps(true); + } + } finally { + if (sa != null) { + sa.recycle(); + } + } + + + if (receiver && (parsingPackage.getPrivateFlags() + & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) { + // A heavy-weight application can not have receives in its main process + if (result.getProcessName().equals(packageName)) { + outError[0] = "Heavy-weight applications can not have receivers in main process"; + return null; + } + } + + if (outError[0] != null) { + return null; + } + + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG + || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + if (parser.getName().equals("intent-filter")) { + ParsedActivityIntentInfo intentInfo = new ParsedActivityIntentInfo(packageName, + result.className); + if (!parseIntentInfo(intentInfo, parsingPackage, res, parser, + true /*allowGlobs*/, + true /*allowAutoVerify*/, outError)) { + return null; + } + if (intentInfo.countActions() == 0) { + Slog.w(TAG, "No actions in intent filter at " + + parsingPackage.getBaseCodePath() + " " + + parser.getPositionDescription()); + } else { + result.order = Math.max(intentInfo.getOrder(), result.order); + result.addIntent(intentInfo); + } + // adjust activity flags when we implicitly expose it via a browsable filter + final int visibility = visibleToEphemeral + ? IntentFilter.VISIBILITY_EXPLICIT + : !receiver && isImplicitlyExposedIntent(intentInfo) + ? IntentFilter.VISIBILITY_IMPLICIT + : IntentFilter.VISIBILITY_NONE; + intentInfo.setVisibilityToInstantApp(visibility); + if (intentInfo.isVisibleToInstantApp()) { + result.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP; + } + if (intentInfo.isImplicitlyVisibleToInstantApp()) { + result.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP; + } + if (PackageParser.LOG_UNSAFE_BROADCASTS && receiver + && (targetSdkVersion >= Build.VERSION_CODES.O)) { + for (int i = 0; i < intentInfo.countActions(); i++) { + final String action = intentInfo.getAction(i); + if (action == null || !action.startsWith("android.")) continue; + if (!PackageParser.SAFE_BROADCASTS.contains(action)) { + Slog.w(TAG, "Broadcast " + action + " may never be delivered to " + + packageName + " as requested at: " + + parser.getPositionDescription()); + } + } + } + } else if (!receiver && parser.getName().equals("preferred")) { + ParsedActivityIntentInfo intentInfo = new ParsedActivityIntentInfo(packageName, + result.className); + if (!parseIntentInfo(intentInfo, parsingPackage, res, parser, + false /*allowGlobs*/, + false /*allowAutoVerify*/, outError)) { + return null; + } + // adjust activity flags when we implicitly expose it via a browsable filter + final int visibility = visibleToEphemeral + ? IntentFilter.VISIBILITY_EXPLICIT + : !receiver && isImplicitlyExposedIntent(intentInfo) + ? IntentFilter.VISIBILITY_IMPLICIT + : IntentFilter.VISIBILITY_NONE; + intentInfo.setVisibilityToInstantApp(visibility); + if (intentInfo.isVisibleToInstantApp()) { + result.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP; + } + if (intentInfo.isImplicitlyVisibleToInstantApp()) { + result.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP; + } + + if (intentInfo.countActions() == 0) { + Slog.w(TAG, "No actions in preferred at " + + parsingPackage.getBaseCodePath() + " " + + parser.getPositionDescription()); + } else { + parsingPackage.addPreferredActivityFilter(intentInfo); + } + } else if (parser.getName().equals("meta-data")) { + if ((result.metaData = ApkParseUtils.parseMetaData(parsingPackage, res, parser, + result.metaData, + outError)) == null) { + return null; + } + } else if (!receiver && parser.getName().equals("layout")) { + result.windowLayout = parseLayout(res, parser); + } else { + if (!PackageParser.RIGID_PARSER) { + Slog.w(TAG, "Problem in package " + parsingPackage.getBaseCodePath() + ":"); + if (receiver) { + Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName() + + " at " + parsingPackage.getBaseCodePath() + " " + + parser.getPositionDescription()); + } else { + Slog.w(TAG, "Unknown element under <activity>: " + parser.getName() + + " at " + parsingPackage.getBaseCodePath() + " " + + parser.getPositionDescription()); + } + XmlUtils.skipCurrentTag(parser); + continue; + } else { + if (receiver) { + outError[0] = "Bad element under <receiver>: " + parser.getName(); + } else { + outError[0] = "Bad element under <activity>: " + parser.getName(); + } + return null; + } + } + } + + if (!setExported) { + result.exported = result.intents.size() > 0; + } + + return result; + } + + public static boolean isImplicitlyExposedIntent(ParsedIntentInfo intentInfo) { + return intentInfo.hasCategory(Intent.CATEGORY_BROWSABLE) + || intentInfo.hasAction(Intent.ACTION_SEND) + || intentInfo.hasAction(Intent.ACTION_SENDTO) + || intentInfo.hasAction(Intent.ACTION_SEND_MULTIPLE); + } + + public static int getActivityResizeMode( + ParsingPackage parsingPackage, + TypedArray sa, + int screenOrientation + ) { + int privateFlags = parsingPackage.getPrivateFlags(); + final boolean appExplicitDefault = (privateFlags + & (ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE + | ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE)) != 0; + + if (sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity) + || appExplicitDefault) { + // Activity or app explicitly set if it is resizeable or not; + final boolean appResizeable = (privateFlags + & ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE) != 0; + if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity, + appResizeable)) { + return ActivityInfo.RESIZE_MODE_RESIZEABLE; + } else { + return ActivityInfo.RESIZE_MODE_UNRESIZEABLE; + } + } + + if ((privateFlags + & ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) + != 0) { + // The activity or app didn't explicitly set the resizing option, however we want to + // make it resize due to the sdk version it is targeting. + return ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION; + } + + // resize preference isn't set and target sdk version doesn't support resizing apps by + // default. For the app to be resizeable if it isn't fixed orientation or immersive. + if (ActivityInfo.isFixedOrientationPortrait(screenOrientation)) { + return ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY; + } else if (ActivityInfo.isFixedOrientationLandscape(screenOrientation)) { + return ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY; + } else if (screenOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) { + return ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION; + } else { + return ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE; + } + } + + public static ParsedService parseService( + String[] separateProcesses, + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser, int flags, String[] outError + ) throws XmlPullParserException, IOException { + TypedArray sa = null; + boolean visibleToEphemeral; + boolean setExported; + + String packageName = parsingPackage.getPackageName(); + String packageProcessName = parsingPackage.getProcessName(); + ParsedService result = new ParsedService(); + + try { + sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestService); + + String name = sa.getNonConfigurationString(R.styleable.AndroidManifestService_name, 0); + if (name == null) { + outError[0] = "<service> does not specify android:name"; + return null; + } else { + String className = ApkParseUtils.buildClassName(packageName, name); + if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)) { + outError[0] = "<service> invalid android:name"; + return null; + } else if (className == null) { + outError[0] = "Empty class name in package " + packageName; + return null; + } + + result.className = className; + } + + int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId( + R.styleable.AndroidManifestService_roundIcon, 0) : 0; + if (roundIconVal != 0) { + result.icon = roundIconVal; + result.nonLocalizedLabel = null; + } else { + int iconVal = sa.getResourceId(R.styleable.AndroidManifestService_icon, 0); + if (iconVal != 0) { + result.icon = iconVal; + result.nonLocalizedLabel = null; + } + } + + int logoVal = sa.getResourceId(R.styleable.AndroidManifestService_logo, 0); + if (logoVal != 0) { + result.logo = logoVal; + } + + int bannerVal = sa.getResourceId(R.styleable.AndroidManifestService_banner, 0); + if (bannerVal != 0) { + result.banner = bannerVal; + } + + TypedValue v = sa.peekValue(R.styleable.AndroidManifestService_label); + if (v != null && (result.labelRes = v.resourceId) == 0) { + result.nonLocalizedLabel = v.coerceToString(); + } + + result.setPackageNameInternal(packageName); + + CharSequence pname; + if (parsingPackage.getTargetSdkVersion() >= Build.VERSION_CODES.FROYO) { + pname = sa.getNonConfigurationString(R.styleable.AndroidManifestService_process, + Configuration.NATIVE_CONFIG_VERSION); + } else { + // Some older apps have been seen to use a resource reference + // here that on older builds was ignored (with a warning). We + // need to continue to do this for them so they don't break. + pname = sa.getNonResourceString(R.styleable.AndroidManifestService_process); + } + + result.setProcessName(packageProcessName, PackageParser.buildProcessName(packageName, + packageProcessName, pname, + flags, separateProcesses, outError)); + + result.descriptionRes = sa.getResourceId( + R.styleable.AndroidManifestService_description, 0); + + result.enabled = sa.getBoolean(R.styleable.AndroidManifestService_enabled, true); + + setExported = sa.hasValue( + R.styleable.AndroidManifestService_exported); + if (setExported) { + result.exported = sa.getBoolean( + R.styleable.AndroidManifestService_exported, false); + } + + String str = sa.getNonConfigurationString( + R.styleable.AndroidManifestService_permission, 0); + if (str == null) { + result.setPermission(parsingPackage.getPermission()); + } else { + result.setPermission(str); + } + + result.setSplitName( + sa.getNonConfigurationString(R.styleable.AndroidManifestService_splitName, 0)); + + result.foregroundServiceType = sa.getInt( + R.styleable.AndroidManifestService_foregroundServiceType, + ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE); + + result.flags = 0; + if (sa.getBoolean( + R.styleable.AndroidManifestService_stopWithTask, + false)) { + result.flags |= ServiceInfo.FLAG_STOP_WITH_TASK; + } + if (sa.getBoolean( + R.styleable.AndroidManifestService_isolatedProcess, + false)) { + result.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS; + } + if (sa.getBoolean( + R.styleable.AndroidManifestService_externalService, + false)) { + result.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE; + } + if (sa.getBoolean( + R.styleable.AndroidManifestService_useAppZygote, + false)) { + result.flags |= ServiceInfo.FLAG_USE_APP_ZYGOTE; + } + if (sa.getBoolean( + R.styleable.AndroidManifestService_singleUser, + false)) { + result.flags |= ServiceInfo.FLAG_SINGLE_USER; + } + + result.directBootAware = sa.getBoolean( + R.styleable.AndroidManifestService_directBootAware, + false); + if (result.directBootAware) { + parsingPackage.setPartiallyDirectBootAware(true); + } + + visibleToEphemeral = sa.getBoolean( + R.styleable.AndroidManifestService_visibleToInstantApps, false); + if (visibleToEphemeral) { + result.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP; + parsingPackage.setVisibleToInstantApps(true); + } + } finally { + if (sa != null) { + sa.recycle(); + } + } + + if (parsingPackage.cantSaveState()) { + // A heavy-weight application can not have services in its main process + // We can do direct compare because we intern all strings. + if (Objects.equals(result.getProcessName(), parsingPackage.getPackageName())) { + outError[0] = "Heavy-weight applications can not have services in main process"; + return null; + } + } + + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG + || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + if (parser.getName().equals("intent-filter")) { + ParsedServiceIntentInfo intent = new ParsedServiceIntentInfo(packageName, + result.className); + if (!parseIntentInfo(intent, parsingPackage, res, parser, true /*allowGlobs*/, + false /*allowAutoVerify*/, + outError)) { + return null; + } + if (visibleToEphemeral) { + intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT); + result.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP; + } + result.order = Math.max(intent.getOrder(), result.order); + result.intents.add(intent); + } else if (parser.getName().equals("meta-data")) { + if ((result.metaData = ApkParseUtils.parseMetaData(parsingPackage, res, parser, + result.metaData, + outError)) == null) { + return null; + } + } else { + if (!PackageParser.RIGID_PARSER) { + Slog.w(TAG, "Unknown element under <service>: " + + parser.getName() + " at " + parsingPackage.getBaseCodePath() + " " + + parser.getPositionDescription()); + XmlUtils.skipCurrentTag(parser); + continue; + } else { + outError[0] = "Bad element under <service>: " + parser.getName(); + return null; + } + } + } + + if (!setExported) { + result.exported = result.intents.size() > 0; + } + + return result; + } + + public static ParsedProvider parseProvider( + String[] separateProcesses, + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser, int flags, String[] outError) + throws XmlPullParserException, IOException { + TypedArray sa = null; + String cpname; + boolean visibleToEphemeral; + + int targetSdkVersion = parsingPackage.getTargetSdkVersion(); + String packageName = parsingPackage.getPackageName(); + String packageProcessName = parsingPackage.getProcessName(); + ParsedProvider result = new ParsedProvider(); + + try { + sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestProvider); + + String name = sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_name, 0); + if (name == null) { + outError[0] = "<provider> does not specify android:name"; + return null; + } else { + String className = ApkParseUtils.buildClassName(packageName, name); + if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)) { + outError[0] = "<provider> invalid android:name"; + return null; + } else if (className == null) { + outError[0] = "Empty class name in package " + packageName; + return null; + } + + result.className = className; + } + + int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId( + R.styleable.AndroidManifestProvider_roundIcon, 0) : 0; + if (roundIconVal != 0) { + result.icon = roundIconVal; + result.nonLocalizedLabel = null; + } else { + int iconVal = sa.getResourceId(R.styleable.AndroidManifestProvider_icon, 0); + if (iconVal != 0) { + result.icon = iconVal; + result.nonLocalizedLabel = null; + } + } + + int logoVal = sa.getResourceId(R.styleable.AndroidManifestProvider_logo, 0); + if (logoVal != 0) { + result.logo = logoVal; + } + + int bannerVal = sa.getResourceId(R.styleable.AndroidManifestProvider_banner, 0); + if (bannerVal != 0) { + result.banner = bannerVal; + } + + TypedValue v = sa.peekValue(R.styleable.AndroidManifestProvider_label); + if (v != null && (result.labelRes = v.resourceId) == 0) { + result.nonLocalizedLabel = v.coerceToString(); + } + + result.setPackageNameInternal(packageName); + + CharSequence pname; + if (parsingPackage.getTargetSdkVersion() >= Build.VERSION_CODES.FROYO) { + pname = sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_process, + Configuration.NATIVE_CONFIG_VERSION); + } else { + // Some older apps have been seen to use a resource reference + // here that on older builds was ignored (with a warning). We + // need to continue to do this for them so they don't break. + pname = sa.getNonResourceString(R.styleable.AndroidManifestProvider_process); + } + + result.setProcessName(packageProcessName, PackageParser.buildProcessName(packageName, + packageProcessName, pname, + flags, separateProcesses, outError)); + + result.descriptionRes = sa.getResourceId( + R.styleable.AndroidManifestProvider_description, 0); + + result.enabled = sa.getBoolean(R.styleable.AndroidManifestProvider_enabled, true); + + boolean providerExportedDefault = false; + + if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) { + // For compatibility, applications targeting API level 16 or lower + // should have their content providers exported by default, unless they + // specify otherwise. + providerExportedDefault = true; + } + + result.exported = sa.getBoolean( + R.styleable.AndroidManifestProvider_exported, + providerExportedDefault); + + cpname = sa.getNonConfigurationString( + R.styleable.AndroidManifestProvider_authorities, 0); + + result.isSyncable = sa.getBoolean( + R.styleable.AndroidManifestProvider_syncable, + false); + + String permission = sa.getNonConfigurationString( + R.styleable.AndroidManifestProvider_permission, 0); + String str = sa.getNonConfigurationString( + R.styleable.AndroidManifestProvider_readPermission, 0); + if (str == null) { + str = permission; + } + if (str == null) { + result.setReadPermission(parsingPackage.getPermission()); + } else { + result.setReadPermission(str); + } + str = sa.getNonConfigurationString( + R.styleable.AndroidManifestProvider_writePermission, 0); + if (str == null) { + str = permission; + } + if (str == null) { + result.setWritePermission(parsingPackage.getPermission()); + } else { + result.setWritePermission(str); + } + + result.grantUriPermissions = sa.getBoolean( + R.styleable.AndroidManifestProvider_grantUriPermissions, + false); + + result.forceUriPermissions = sa.getBoolean( + R.styleable.AndroidManifestProvider_forceUriPermissions, + false); + + result.multiProcess = sa.getBoolean( + R.styleable.AndroidManifestProvider_multiprocess, + false); + + result.initOrder = sa.getInt( + R.styleable.AndroidManifestProvider_initOrder, + 0); + + result.setSplitName( + sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_splitName, 0)); + + result.flags = 0; + + if (sa.getBoolean( + R.styleable.AndroidManifestProvider_singleUser, + false)) { + result.flags |= ProviderInfo.FLAG_SINGLE_USER; + } + + result.directBootAware = sa.getBoolean( + R.styleable.AndroidManifestProvider_directBootAware, + false); + if (result.directBootAware) { + parsingPackage.setPartiallyDirectBootAware(true); + } + + visibleToEphemeral = + sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false); + if (visibleToEphemeral) { + result.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP; + parsingPackage.setVisibleToInstantApps(true); + } + } finally { + if (sa != null) { + sa.recycle(); + } + } + + if ((parsingPackage.getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) + != 0) { + // A heavy-weight application can not have providers in its main process + if (result.getProcessName().equals(packageName)) { + outError[0] = "Heavy-weight applications can not have providers in main process"; + return null; + } + } + + if (cpname == null) { + outError[0] = "<provider> does not include authorities attribute"; + return null; + } + if (cpname.length() <= 0) { + outError[0] = "<provider> has empty authorities attribute"; + return null; + } + result.setAuthority(cpname); + + if (!parseProviderTags(parsingPackage, res, parser, visibleToEphemeral, result, outError)) { + return null; + } + + return result; + } + + public static ParsedQueriesIntentInfo parsedParsedQueriesIntentInfo( + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser, + String[] outError + ) throws IOException, XmlPullParserException { + ParsedQueriesIntentInfo intentInfo = new ParsedQueriesIntentInfo( + parsingPackage.getPackageName(), + null + ); + if (!parseIntentInfo( + intentInfo, + parsingPackage, + res, + parser, + true /*allowGlobs*/, + true /*allowAutoVerify*/, + outError + )) { + return null; + } + return intentInfo; + } + + private static boolean parseProviderTags( + ParsingPackage parsingPackage, + Resources res, XmlResourceParser parser, + boolean visibleToEphemeral, ParsedProvider outInfo, String[] outError) + throws XmlPullParserException, IOException { + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG + || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + if (parser.getName().equals("intent-filter")) { + ParsedProviderIntentInfo intent = new ParsedProviderIntentInfo( + parsingPackage.getPackageName(), outInfo.className); + if (!parseIntentInfo(intent, parsingPackage, res, parser, true /*allowGlobs*/, + false /*allowAutoVerify*/, + outError)) { + return false; + } + if (visibleToEphemeral) { + intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT); + outInfo.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP; + } + outInfo.order = Math.max(intent.getOrder(), outInfo.order); + outInfo.intents.add(intent); + + } else if (parser.getName().equals("meta-data")) { + Bundle metaData = ApkParseUtils.parseMetaData(parsingPackage, res, parser, + outInfo.metaData, outError); + if (metaData == null) { + return false; + } else { + outInfo.metaData = metaData; + } + + } else if (parser.getName().equals("grant-uri-permission")) { + TypedArray sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestGrantUriPermission); + + PatternMatcher pa = null; + + String str = sa.getNonConfigurationString( + R.styleable.AndroidManifestGrantUriPermission_path, 0); + if (str != null) { + pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL); + } + + str = sa.getNonConfigurationString( + R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0); + if (str != null) { + pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX); + } + + str = sa.getNonConfigurationString( + R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0); + if (str != null) { + pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB); + } + + sa.recycle(); + + if (pa != null) { + if (outInfo.uriPermissionPatterns == null) { + outInfo.uriPermissionPatterns = new PatternMatcher[1]; + outInfo.uriPermissionPatterns[0] = pa; + } else { + final int N = outInfo.uriPermissionPatterns.length; + PatternMatcher[] newp = new PatternMatcher[N + 1]; + System.arraycopy(outInfo.uriPermissionPatterns, 0, newp, 0, N); + newp[N] = pa; + outInfo.uriPermissionPatterns = newp; + } + outInfo.grantUriPermissions = true; + } else { + if (!PackageParser.RIGID_PARSER) { + Slog.w(TAG, "Unknown element under <path-permission>: " + + parser.getName() + " at " + parsingPackage.getBaseCodePath() + + " " + + parser.getPositionDescription()); + XmlUtils.skipCurrentTag(parser); + continue; + } else { + outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>"; + return false; + } + } + XmlUtils.skipCurrentTag(parser); + + } else if (parser.getName().equals("path-permission")) { + TypedArray sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestPathPermission); + + PathPermission pa = null; + + String permission = sa.getNonConfigurationString( + R.styleable.AndroidManifestPathPermission_permission, 0); + String readPermission = sa.getNonConfigurationString( + R.styleable.AndroidManifestPathPermission_readPermission, 0); + if (readPermission == null) { + readPermission = permission; + } + String writePermission = sa.getNonConfigurationString( + R.styleable.AndroidManifestPathPermission_writePermission, 0); + if (writePermission == null) { + writePermission = permission; + } + + boolean havePerm = false; + if (readPermission != null) { + readPermission = readPermission.intern(); + havePerm = true; + } + if (writePermission != null) { + writePermission = writePermission.intern(); + havePerm = true; + } + + if (!havePerm) { + if (!PackageParser.RIGID_PARSER) { + Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: " + + parser.getName() + " at " + parsingPackage.getBaseCodePath() + + " " + + parser.getPositionDescription()); + XmlUtils.skipCurrentTag(parser); + continue; + } else { + outError[0] = "No readPermission or writePermssion for <path-permission>"; + return false; + } + } + + String path = sa.getNonConfigurationString( + R.styleable.AndroidManifestPathPermission_path, 0); + if (path != null) { + pa = new PathPermission(path, + PatternMatcher.PATTERN_LITERAL, readPermission, writePermission); + } + + path = sa.getNonConfigurationString( + R.styleable.AndroidManifestPathPermission_pathPrefix, 0); + if (path != null) { + pa = new PathPermission(path, + PatternMatcher.PATTERN_PREFIX, readPermission, writePermission); + } + + path = sa.getNonConfigurationString( + R.styleable.AndroidManifestPathPermission_pathPattern, 0); + if (path != null) { + pa = new PathPermission(path, + PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission); + } + + path = sa.getNonConfigurationString( + R.styleable.AndroidManifestPathPermission_pathAdvancedPattern, 0); + if (path != null) { + pa = new PathPermission(path, + PatternMatcher.PATTERN_ADVANCED_GLOB, readPermission, writePermission); + } + + sa.recycle(); + + if (pa != null) { + if (outInfo.pathPermissions == null) { + outInfo.pathPermissions = new PathPermission[1]; + outInfo.pathPermissions[0] = pa; + } else { + final int N = outInfo.pathPermissions.length; + PathPermission[] newp = new PathPermission[N + 1]; + System.arraycopy(outInfo.pathPermissions, 0, newp, 0, N); + newp[N] = pa; + outInfo.pathPermissions = newp; + } + } else { + if (!PackageParser.RIGID_PARSER) { + Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: " + + parser.getName() + " at " + parsingPackage.getBaseCodePath() + + " " + + parser.getPositionDescription()); + XmlUtils.skipCurrentTag(parser); + continue; + } + outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>"; + return false; + } + XmlUtils.skipCurrentTag(parser); + + } else { + if (!PackageParser.RIGID_PARSER) { + Slog.w(TAG, "Unknown element under <provider>: " + + parser.getName() + " at " + parsingPackage.getBaseCodePath() + " " + + parser.getPositionDescription()); + XmlUtils.skipCurrentTag(parser); + continue; + } else { + outError[0] = "Bad element under <provider>: " + parser.getName(); + return false; + } + } + } + return true; + } + + public static ParsedActivity parseActivityAlias( + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser, + String[] outError) + throws XmlPullParserException, IOException { + TypedArray sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestActivityAlias); + + String targetActivity = sa.getNonConfigurationString( + R.styleable.AndroidManifestActivityAlias_targetActivity, + Configuration.NATIVE_CONFIG_VERSION); + if (targetActivity == null) { + outError[0] = "<activity-alias> does not specify android:targetActivity"; + sa.recycle(); + return null; + } + + String packageName = parsingPackage.getPackageName(); + targetActivity = ApkParseUtils.buildClassName(packageName, targetActivity); + if (targetActivity == null) { + outError[0] = "Empty class name in package " + packageName; + sa.recycle(); + return null; + } + + ParsedActivity target = null; + + List<ParsedActivity> activities = parsingPackage.getActivities(); + final int NA = activities.size(); + for (int i = 0; i < NA; i++) { + ParsedActivity t = activities.get(i); + if (targetActivity.equals(t.className)) { + target = t; + break; + } + } + + if (target == null) { + outError[0] = "<activity-alias> target activity " + targetActivity + + " not found in manifest with activities = " + parsingPackage.getActivities() + + ", parsedActivities = " + activities; + sa.recycle(); + return null; + } + + ParsedActivity result = new ParsedActivity(); + result.setPackageNameInternal(target.getPackageName()); + result.targetActivity = targetActivity; + result.configChanges = target.configChanges; + result.flags = target.flags; + result.privateFlags = target.privateFlags; + result.icon = target.icon; + result.logo = target.logo; + result.banner = target.banner; + result.labelRes = target.labelRes; + result.nonLocalizedLabel = target.nonLocalizedLabel; + result.launchMode = target.launchMode; + result.lockTaskLaunchMode = target.lockTaskLaunchMode; + result.descriptionRes = target.descriptionRes; + result.screenOrientation = target.screenOrientation; + result.taskAffinity = target.taskAffinity; + result.theme = target.theme; + result.softInputMode = target.softInputMode; + result.uiOptions = target.uiOptions; + result.parentActivityName = target.parentActivityName; + result.maxRecents = target.maxRecents; + result.windowLayout = target.windowLayout; + result.resizeMode = target.resizeMode; + result.maxAspectRatio = target.maxAspectRatio; + result.hasMaxAspectRatio = target.hasMaxAspectRatio; + result.minAspectRatio = target.minAspectRatio; + result.hasMinAspectRatio = target.hasMinAspectRatio; + result.requestedVrComponent = target.requestedVrComponent; + result.directBootAware = target.directBootAware; + + result.setProcessName(parsingPackage.getAppInfoProcessName(), target.getProcessName()); + + // Not all attributes from the target ParsedActivity are copied to the alias. + // Careful when adding an attribute and determine whether or not it should be copied. +// result.enabled = target.enabled; +// result.exported = target.exported; +// result.permission = target.permission; +// result.splitName = target.splitName; +// result.documentLaunchMode = target.documentLaunchMode; +// result.persistableMode = target.persistableMode; +// result.rotationAnimation = target.rotationAnimation; +// result.colorMode = target.colorMode; +// result.intents.addAll(target.intents); +// result.order = target.order; +// result.metaData = target.metaData; + + String name = sa.getNonConfigurationString(R.styleable.AndroidManifestActivityAlias_name, + 0); + if (name == null) { + outError[0] = "<activity-alias> does not specify android:name"; + return null; + } else { + String className = ApkParseUtils.buildClassName(packageName, name); + if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)) { + outError[0] = "<activity-alias> invalid android:name"; + return null; + } else if (className == null) { + outError[0] = "Empty class name in package " + packageName; + return null; + } + + result.className = className; + } + + int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId( + R.styleable.AndroidManifestActivityAlias_roundIcon, 0) : 0; + if (roundIconVal != 0) { + result.icon = roundIconVal; + result.nonLocalizedLabel = null; + } else { + int iconVal = sa.getResourceId(R.styleable.AndroidManifestActivityAlias_icon, 0); + if (iconVal != 0) { + result.icon = iconVal; + result.nonLocalizedLabel = null; + } + } + + int logoVal = sa.getResourceId(R.styleable.AndroidManifestActivityAlias_logo, 0); + if (logoVal != 0) { + result.logo = logoVal; + } + + int bannerVal = sa.getResourceId(R.styleable.AndroidManifestActivityAlias_banner, 0); + if (bannerVal != 0) { + result.banner = bannerVal; + } + + TypedValue v = sa.peekValue(R.styleable.AndroidManifestActivityAlias_label); + if (v != null && (result.labelRes = v.resourceId) == 0) { + result.nonLocalizedLabel = v.coerceToString(); + } + + result.setPackageNameInternal(packageName); + + result.descriptionRes = sa.getResourceId( + R.styleable.AndroidManifestActivityAlias_description, 0); + + result.enabled = sa.getBoolean(R.styleable.AndroidManifestActivityAlias_enabled, true); + + final boolean setExported = sa.hasValue( + R.styleable.AndroidManifestActivityAlias_exported); + if (setExported) { + result.exported = sa.getBoolean( + R.styleable.AndroidManifestActivityAlias_exported, false); + } + + String str; + str = sa.getNonConfigurationString( + R.styleable.AndroidManifestActivityAlias_permission, 0); + if (str != null) { + result.setPermission(str); + } + + String parentName = sa.getNonConfigurationString( + R.styleable.AndroidManifestActivityAlias_parentActivityName, + Configuration.NATIVE_CONFIG_VERSION); + if (parentName != null) { + String parentClassName = ApkParseUtils.buildClassName(result.getPackageName(), + parentName); + if (parentClassName == null) { + Log.e(TAG, "Activity alias " + result.className + + " specified invalid parentActivityName " + parentName); + outError[0] = null; + } else { + result.parentActivityName = parentClassName; + } + } + + // TODO add visibleToInstantApps attribute to activity alias + final boolean visibleToEphemeral = + ((result.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0); + + sa.recycle(); + + if (outError[0] != null) { + return null; + } + + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG + || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + String tagName = parser.getName(); + if (tagName.equals("intent-filter")) { + ParsedActivityIntentInfo intent = new ParsedActivityIntentInfo(packageName, + result.className); + if (!parseIntentInfo(intent, parsingPackage, res, parser, true /*allowGlobs*/, + true /*allowAutoVerify*/, outError)) { + return null; + } + if (intent.countActions() == 0) { + Slog.w(TAG, "No actions in intent filter at " + + parsingPackage.getBaseCodePath() + " " + + parser.getPositionDescription()); + } else { + result.order = Math.max(intent.getOrder(), result.order); + result.addIntent(intent); + } + // adjust activity flags when we implicitly expose it via a browsable filter + final int visibility = visibleToEphemeral + ? IntentFilter.VISIBILITY_EXPLICIT + : isImplicitlyExposedIntent(intent) + ? IntentFilter.VISIBILITY_IMPLICIT + : IntentFilter.VISIBILITY_NONE; + intent.setVisibilityToInstantApp(visibility); + if (intent.isVisibleToInstantApp()) { + result.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP; + } + if (intent.isImplicitlyVisibleToInstantApp()) { + result.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP; + } + } else if (tagName.equals("meta-data")) { + if ((result.metaData = ApkParseUtils.parseMetaData(parsingPackage, res, parser, + result.metaData, + outError)) == null) { + return null; + } + } else { + if (!PackageParser.RIGID_PARSER) { + Slog.w(TAG, "Unknown element under <activity-alias>: " + tagName + + " at " + parsingPackage.getBaseCodePath() + " " + + parser.getPositionDescription()); + XmlUtils.skipCurrentTag(parser); + continue; + } else { + outError[0] = "Bad element under <activity-alias>: " + tagName; + return null; + } + } + } + + if (!setExported) { + result.exported = result.intents.size() > 0; + } + + return result; + } + + public static ParsedPermission parsePermission( + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser, + String[] outError + ) throws IOException, XmlPullParserException { + TypedArray sa = null; + String packageName = parsingPackage.getPackageName(); + ParsedPermission result = new ParsedPermission(); + + try { + sa = res.obtainAttributes(parser, R.styleable.AndroidManifestPermission); + + String name = sa.getNonConfigurationString(R.styleable.AndroidManifestPermission_name, + 0); + if (name == null) { + outError[0] = "<permission> does not specify android:name"; + return null; + } else { + String className = ApkParseUtils.buildClassName(packageName, name); + if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)) { + outError[0] = "<permission> invalid android:name"; + return null; + } else if (className == null) { + outError[0] = "Empty class name in package " + packageName; + return null; + } + + result.className = className; + } + + int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId( + R.styleable.AndroidManifestPermission_roundIcon, 0) : 0; + if (roundIconVal != 0) { + result.icon = roundIconVal; + result.nonLocalizedLabel = null; + } else { + int iconVal = sa.getResourceId(R.styleable.AndroidManifestPermission_icon, 0); + if (iconVal != 0) { + result.icon = iconVal; + result.nonLocalizedLabel = null; + } + } + + int logoVal = sa.getResourceId(R.styleable.AndroidManifestPermission_logo, 0); + if (logoVal != 0) { + result.logo = logoVal; + } + + int bannerVal = sa.getResourceId(R.styleable.AndroidManifestPermission_banner, 0); + if (bannerVal != 0) { + result.banner = bannerVal; + } + + TypedValue v = sa.peekValue(R.styleable.AndroidManifestPermission_label); + if (v != null && (result.labelRes = v.resourceId) == 0) { + result.nonLocalizedLabel = v.coerceToString(); + } + + result.setPackageNameInternal(packageName); + + result.descriptionRes = sa.getResourceId( + R.styleable.AndroidManifestPermission_description, 0); + + if (sa.hasValue( + R.styleable.AndroidManifestPermission_backgroundPermission)) { + if ("android".equals(packageName)) { + result.backgroundPermission = sa.getNonResourceString( + R.styleable + .AndroidManifestPermission_backgroundPermission); + } else { + Slog.w(TAG, packageName + " defines a background permission. Only the " + + "'android' package can do that."); + } + } + + // Note: don't allow this value to be a reference to a resource + // that may change. + result.setGroup(sa.getNonResourceString( + R.styleable.AndroidManifestPermission_permissionGroup)); + + result.requestRes = sa.getResourceId( + R.styleable.AndroidManifestPermission_request, 0); + + result.protectionLevel = sa.getInt( + R.styleable.AndroidManifestPermission_protectionLevel, + PermissionInfo.PROTECTION_NORMAL); + + result.flags = sa.getInt( + R.styleable.AndroidManifestPermission_permissionFlags, 0); + + // For now only platform runtime permissions can be restricted + if (!result.isRuntime() || !"android".equals(result.getPackageName())) { + result.flags &= ~PermissionInfo.FLAG_HARD_RESTRICTED; + result.flags &= ~PermissionInfo.FLAG_SOFT_RESTRICTED; + } else { + // The platform does not get to specify conflicting permissions + if ((result.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0 + && (result.flags & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0) { + throw new IllegalStateException("Permission cannot be both soft and hard" + + " restricted: " + result.getName()); + } + } + + } finally { + if (sa != null) { + sa.recycle(); + } + } + + if (result.protectionLevel == -1) { + outError[0] = "<permission> does not specify protectionLevel"; + return null; + } + + result.protectionLevel = PermissionInfo.fixProtectionLevel(result.protectionLevel); + + if (result.getProtectionFlags() != 0) { + if ((result.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) == 0 + && (result.protectionLevel & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) + == 0 + && (result.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) != + PermissionInfo.PROTECTION_SIGNATURE) { + outError[0] = "<permission> protectionLevel specifies a non-instant flag but is " + + "not based on signature type"; + return null; + } + } + + boolean success = parseAllMetaData(parsingPackage, res, parser, + "<permission>", result, outError); + if (!success || outError[0] != null) { + return null; + } + + return result; + } + + public static ParsedPermission parsePermissionTree( + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser, + String[] outError + ) throws IOException, XmlPullParserException { + TypedArray sa = null; + String packageName = parsingPackage.getPackageName(); + ParsedPermission result = new ParsedPermission(); + + try { + sa = res.obtainAttributes(parser, R.styleable.AndroidManifestPermissionTree); + + String name = sa.getNonConfigurationString( + R.styleable.AndroidManifestPermissionTree_name, 0); + if (name == null) { + outError[0] = "<permission-tree> does not specify android:name"; + return null; + } else { + String className = ApkParseUtils.buildClassName(packageName, name); + if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)) { + outError[0] = "<permission-tree> invalid android:name"; + return null; + } else if (className == null) { + outError[0] = "Empty class name in package " + packageName; + return null; + } + + result.className = className; + } + + int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId( + R.styleable.AndroidManifestPermissionTree_roundIcon, 0) : 0; + if (roundIconVal != 0) { + result.icon = roundIconVal; + result.nonLocalizedLabel = null; + } else { + int iconVal = sa.getResourceId(R.styleable.AndroidManifestPermissionTree_icon, 0); + if (iconVal != 0) { + result.icon = iconVal; + result.nonLocalizedLabel = null; + } + } + + int logoVal = sa.getResourceId(R.styleable.AndroidManifestPermissionTree_logo, 0); + if (logoVal != 0) { + result.logo = logoVal; + } + + int bannerVal = sa.getResourceId(R.styleable.AndroidManifestPermissionTree_banner, 0); + if (bannerVal != 0) { + result.banner = bannerVal; + } + + TypedValue v = sa.peekValue(R.styleable.AndroidManifestPermissionTree_label); + if (v != null && (result.labelRes = v.resourceId) == 0) { + result.nonLocalizedLabel = v.coerceToString(); + } + + result.setPackageNameInternal(packageName); + } finally { + if (sa != null) { + sa.recycle(); + } + } + + int index = result.getName().indexOf('.'); + if (index > 0) { + index = result.getName().indexOf('.', index + 1); + } + if (index < 0) { + outError[0] = + "<permission-tree> name has less than three segments: " + result.getName(); + return null; + } + + result.descriptionRes = 0; + result.requestRes = 0; + result.protectionLevel = PermissionInfo.PROTECTION_NORMAL; + result.tree = true; + + boolean success = parseAllMetaData(parsingPackage, res, parser, + "<permission-tree>", result, outError); + if (!success || outError[0] != null) { + return null; + } + + return result; + } + + public static ParsedPermissionGroup parsePermissionGroup( + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser, + String[] outError + ) throws IOException, XmlPullParserException { + TypedArray sa = null; + String packageName = parsingPackage.getPackageName(); + ParsedPermissionGroup result = new ParsedPermissionGroup(); + + try { + sa = res.obtainAttributes(parser, R.styleable.AndroidManifestPermissionGroup); + + String name = sa.getNonConfigurationString( + R.styleable.AndroidManifestPermissionGroup_name, 0); + if (name == null) { + outError[0] = "<permission> does not specify android:name"; + return null; + } else { + String className = ApkParseUtils.buildClassName(packageName, name); + if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)) { + outError[0] = "<permission> invalid android:name"; + return null; + } else if (className == null) { + outError[0] = "Empty class name in package " + packageName; + return null; + } + + result.className = className; + } + + int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId( + R.styleable.AndroidManifestPermissionGroup_roundIcon, 0) : 0; + if (roundIconVal != 0) { + result.icon = roundIconVal; + result.nonLocalizedLabel = null; + } else { + int iconVal = sa.getResourceId(R.styleable.AndroidManifestPermissionGroup_icon, 0); + if (iconVal != 0) { + result.icon = iconVal; + result.nonLocalizedLabel = null; + } + } + + int logoVal = sa.getResourceId(R.styleable.AndroidManifestPermissionGroup_logo, 0); + if (logoVal != 0) { + result.logo = logoVal; + } + + int bannerVal = sa.getResourceId(R.styleable.AndroidManifestPermissionGroup_banner, 0); + if (bannerVal != 0) { + result.banner = bannerVal; + } + + TypedValue v = sa.peekValue(R.styleable.AndroidManifestPermissionGroup_label); + if (v != null && (result.labelRes = v.resourceId) == 0) { + result.nonLocalizedLabel = v.coerceToString(); + } + + result.setPackageNameInternal(packageName); + + result.descriptionRes = sa.getResourceId( + R.styleable.AndroidManifestPermissionGroup_description, 0); + + result.requestDetailResourceId = sa.getResourceId( + R.styleable.AndroidManifestPermissionGroup_requestDetail, 0); + result.backgroundRequestResourceId = sa.getResourceId( + R.styleable.AndroidManifestPermissionGroup_backgroundRequest, + 0); + result.backgroundRequestDetailResourceId = sa.getResourceId( + R.styleable + .AndroidManifestPermissionGroup_backgroundRequestDetail, 0); + + result.requestRes = sa.getResourceId( + R.styleable.AndroidManifestPermissionGroup_request, 0); + result.flags = sa.getInt( + R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, + 0); + result.priority = sa.getInt( + R.styleable.AndroidManifestPermissionGroup_priority, 0); + + } finally { + if (sa != null) { + sa.recycle(); + } + } + + boolean success = parseAllMetaData(parsingPackage, res, parser, + "<permission-group>", result, outError); + if (!success || outError[0] != null) { + return null; + } + + return result; + } + + public static ParsedInstrumentation parseInstrumentation( + ParsingPackage parsingPackage, + Resources res, + XmlResourceParser parser, + String[] outError + ) throws IOException, XmlPullParserException { + TypedArray sa = null; + String packageName = parsingPackage.getPackageName(); + ParsedInstrumentation result = new ParsedInstrumentation(); + + try { + sa = res.obtainAttributes(parser, R.styleable.AndroidManifestInstrumentation); + + // TODO(b/135203078): Re-share all of the configuration for this. ParseComponentArgs was + // un-used for this, but can be adjusted and re-added to share all the initial result + // parsing for icon/logo/name/etc in all of these parse methods. + String name = sa.getNonConfigurationString( + R.styleable.AndroidManifestInstrumentation_name, 0); + if (name == null) { + outError[0] = "<instrumentation> does not specify android:name"; + return null; + } else { + String className = ApkParseUtils.buildClassName(packageName, name); + if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)) { + outError[0] = "<instrumentation> invalid android:name"; + return null; + } else if (className == null) { + outError[0] = "Empty class name in package " + packageName; + return null; + } + + result.className = className; + } + + int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId( + R.styleable.AndroidManifestInstrumentation_roundIcon, 0) : 0; + if (roundIconVal != 0) { + result.icon = roundIconVal; + result.nonLocalizedLabel = null; + } else { + int iconVal = sa.getResourceId(R.styleable.AndroidManifestInstrumentation_icon, 0); + if (iconVal != 0) { + result.icon = iconVal; + result.nonLocalizedLabel = null; + } + } + + int logoVal = sa.getResourceId(R.styleable.AndroidManifestInstrumentation_logo, 0); + if (logoVal != 0) { + result.logo = logoVal; + } + + int bannerVal = sa.getResourceId(R.styleable.AndroidManifestInstrumentation_banner, 0); + if (bannerVal != 0) { + result.banner = bannerVal; + } + + TypedValue v = sa.peekValue(R.styleable.AndroidManifestInstrumentation_label); + if (v != null && (result.labelRes = v.resourceId) == 0) { + result.nonLocalizedLabel = v.coerceToString(); + } + + result.setPackageNameInternal(packageName); + + String str; + // Note: don't allow this value to be a reference to a resource + // that may change. + str = sa.getNonResourceString(R.styleable.AndroidManifestInstrumentation_targetPackage); + result.setTargetPackage(str); + + str = sa.getNonResourceString( + R.styleable.AndroidManifestInstrumentation_targetProcesses); + result.setTargetProcesses(str); + result.handleProfiling = sa.getBoolean( + R.styleable.AndroidManifestInstrumentation_handleProfiling, false); + result.functionalTest = sa.getBoolean( + R.styleable.AndroidManifestInstrumentation_functionalTest, false); + + } finally { + if (sa != null) { + sa.recycle(); + } + } + + boolean success = parseAllMetaData(parsingPackage, res, parser, + "<instrumentation>", result, outError); + if (!success || outError[0] != null) { + return null; + } + + return result; + } + + public static ActivityInfo.WindowLayout parseLayout(Resources res, AttributeSet attrs) { + TypedArray sw = res.obtainAttributes(attrs, + R.styleable.AndroidManifestLayout); + int width = -1; + float widthFraction = -1f; + int height = -1; + float heightFraction = -1f; + final int widthType = sw.getType( + R.styleable.AndroidManifestLayout_defaultWidth); + if (widthType == TypedValue.TYPE_FRACTION) { + widthFraction = sw.getFraction( + R.styleable.AndroidManifestLayout_defaultWidth, + 1, 1, -1); + } else if (widthType == TypedValue.TYPE_DIMENSION) { + width = sw.getDimensionPixelSize( + R.styleable.AndroidManifestLayout_defaultWidth, + -1); + } + final int heightType = sw.getType( + R.styleable.AndroidManifestLayout_defaultHeight); + if (heightType == TypedValue.TYPE_FRACTION) { + heightFraction = sw.getFraction( + R.styleable.AndroidManifestLayout_defaultHeight, + 1, 1, -1); + } else if (heightType == TypedValue.TYPE_DIMENSION) { + height = sw.getDimensionPixelSize( + R.styleable.AndroidManifestLayout_defaultHeight, + -1); + } + int gravity = sw.getInt( + R.styleable.AndroidManifestLayout_gravity, + Gravity.CENTER); + int minWidth = sw.getDimensionPixelSize( + R.styleable.AndroidManifestLayout_minWidth, + -1); + int minHeight = sw.getDimensionPixelSize( + R.styleable.AndroidManifestLayout_minHeight, + -1); + sw.recycle(); + return new ActivityInfo.WindowLayout(width, widthFraction, + height, heightFraction, gravity, minWidth, minHeight); + } + + public static boolean parseIntentInfo( + ParsedIntentInfo intentInfo, + ParsingPackage parsingPackage, + Resources res, XmlResourceParser parser, boolean allowGlobs, + boolean allowAutoVerify, String[] outError + ) throws XmlPullParserException, IOException { + TypedArray sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestIntentFilter); + + int priority = sa.getInt( + R.styleable.AndroidManifestIntentFilter_priority, 0); + intentInfo.setPriority(priority); + + int order = sa.getInt( + R.styleable.AndroidManifestIntentFilter_order, 0); + intentInfo.setOrder(order); + + TypedValue v = sa.peekValue( + R.styleable.AndroidManifestIntentFilter_label); + if (v != null && (intentInfo.labelRes = v.resourceId) == 0) { + intentInfo.nonLocalizedLabel = v.coerceToString(); + } + + int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId( + R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0; + if (roundIconVal != 0) { + intentInfo.icon = roundIconVal; + } else { + intentInfo.icon = sa.getResourceId( + R.styleable.AndroidManifestIntentFilter_icon, 0); + } + + if (allowAutoVerify) { + intentInfo.setAutoVerify(sa.getBoolean( + R.styleable.AndroidManifestIntentFilter_autoVerify, + false)); + } + + sa.recycle(); + + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + String nodeName = parser.getName(); + if (nodeName.equals("action")) { + String value = parser.getAttributeValue( + PackageParser.ANDROID_RESOURCES, "name"); + if (TextUtils.isEmpty(value)) { + outError[0] = "No value supplied for <android:name>"; + return false; + } + XmlUtils.skipCurrentTag(parser); + + intentInfo.addAction(value); + } else if (nodeName.equals("category")) { + String value = parser.getAttributeValue( + PackageParser.ANDROID_RESOURCES, "name"); + if (TextUtils.isEmpty(value)) { + outError[0] = "No value supplied for <android:name>"; + return false; + } + XmlUtils.skipCurrentTag(parser); + + intentInfo.addCategory(value); + + } else if (nodeName.equals("data")) { + sa = res.obtainAttributes(parser, + R.styleable.AndroidManifestData); + + String str = sa.getNonConfigurationString( + R.styleable.AndroidManifestData_mimeType, 0); + if (str != null) { + try { + intentInfo.addRawDataType(str); + } catch (IntentFilter.MalformedMimeTypeException e) { + outError[0] = e.toString(); + sa.recycle(); + return false; + } + } + + str = sa.getNonConfigurationString( + R.styleable.AndroidManifestData_scheme, 0); + if (str != null) { + intentInfo.addDataScheme(str); + } + + str = sa.getNonConfigurationString( + R.styleable.AndroidManifestData_ssp, 0); + if (str != null) { + intentInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL); + } + + str = sa.getNonConfigurationString( + R.styleable.AndroidManifestData_sspPrefix, 0); + if (str != null) { + intentInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX); + } + + str = sa.getNonConfigurationString( + R.styleable.AndroidManifestData_sspPattern, 0); + if (str != null) { + if (!allowGlobs) { + outError[0] = "sspPattern not allowed here; ssp must be literal"; + return false; + } + intentInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB); + } + + String host = sa.getNonConfigurationString( + R.styleable.AndroidManifestData_host, 0); + String port = sa.getNonConfigurationString( + R.styleable.AndroidManifestData_port, 0); + if (host != null) { + intentInfo.addDataAuthority(host, port); + } + + str = sa.getNonConfigurationString( + R.styleable.AndroidManifestData_path, 0); + if (str != null) { + intentInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL); + } + + str = sa.getNonConfigurationString( + R.styleable.AndroidManifestData_pathPrefix, 0); + if (str != null) { + intentInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX); + } + + str = sa.getNonConfigurationString( + R.styleable.AndroidManifestData_pathPattern, 0); + if (str != null) { + if (!allowGlobs) { + outError[0] = "pathPattern not allowed here; path must be literal"; + return false; + } + intentInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB); + } + + str = sa.getNonConfigurationString( + R.styleable.AndroidManifestData_pathAdvancedPattern, 0); + if (str != null) { + if (!allowGlobs) { + outError[0] = "pathAdvancedPattern not allowed here; path must be literal"; + return false; + } + intentInfo.addDataPath(str, PatternMatcher.PATTERN_ADVANCED_GLOB); + } + + sa.recycle(); + XmlUtils.skipCurrentTag(parser); + } else if (!PackageParser.RIGID_PARSER) { + Slog.w(TAG, "Unknown element under <intent-filter>: " + + parser.getName() + " at " + parsingPackage.getBaseCodePath() + " " + + parser.getPositionDescription()); + XmlUtils.skipCurrentTag(parser); + } else { + outError[0] = "Bad element under <intent-filter>: " + parser.getName(); + return false; + } + } + + intentInfo.hasDefault = intentInfo.hasCategory(Intent.CATEGORY_DEFAULT); + + if (PackageParser.DEBUG_PARSER) { + final StringBuilder cats = new StringBuilder("Intent d="); + cats.append(intentInfo.hasDefault); + cats.append(", cat="); + + final Iterator<String> it = intentInfo.categoriesIterator(); + if (it != null) { + while (it.hasNext()) { + cats.append(' '); + cats.append(it.next()); + } + } + Slog.d(TAG, cats.toString()); + } + + return true; + } + + private static boolean parseAllMetaData( + ParsingPackage parsingPackage, + Resources res, XmlResourceParser parser, String tag, + ParsedComponent outInfo, + String[] outError + ) throws XmlPullParserException, IOException { + int outerDepth = parser.getDepth(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG + || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + if (parser.getName().equals("meta-data")) { + if ((outInfo.metaData = ApkParseUtils.parseMetaData(parsingPackage, res, parser, + outInfo.metaData, outError)) == null) { + return false; + } + } else { + if (!PackageParser.RIGID_PARSER) { + Slog.w(TAG, "Unknown element under " + tag + ": " + + parser.getName() + " at " + parsingPackage.getBaseCodePath() + " " + + parser.getPositionDescription()); + XmlUtils.skipCurrentTag(parser); + continue; + } else { + outError[0] = "Bad element under " + tag + ": " + parser.getName(); + } + } + } + + return true; + } + + public static boolean isImplicitlyExposedIntent(IntentFilter intent) { + return intent.hasCategory(Intent.CATEGORY_BROWSABLE) + || intent.hasAction(Intent.ACTION_SEND) + || intent.hasAction(Intent.ACTION_SENDTO) + || intent.hasAction(Intent.ACTION_SEND_MULTIPLE); + } +} diff --git a/core/java/android/content/pm/parsing/PackageImpl.java b/core/java/android/content/pm/parsing/PackageImpl.java new file mode 100644 index 000000000000..363cf80a0a1d --- /dev/null +++ b/core/java/android/content/pm/parsing/PackageImpl.java @@ -0,0 +1,3213 @@ +/* + * 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.os.Build.VERSION_CODES.DONUT; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; +import android.content.pm.ConfigurationInfo; +import android.content.pm.FeatureGroupInfo; +import android.content.pm.FeatureInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageParser; +import android.content.pm.ProviderInfo; +import android.content.pm.ServiceInfo; +import android.content.pm.SharedLibraryInfo; +import android.content.pm.parsing.ComponentParseUtils.ParsedActivity; +import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo; +import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation; +import android.content.pm.parsing.ComponentParseUtils.ParsedIntentInfo; +import android.content.pm.parsing.ComponentParseUtils.ParsedPermission; +import android.content.pm.parsing.ComponentParseUtils.ParsedPermissionGroup; +import android.content.pm.parsing.ComponentParseUtils.ParsedProvider; +import android.content.pm.parsing.ComponentParseUtils.ParsedService; +import android.content.res.TypedArray; +import android.os.Build; +import android.os.Bundle; +import android.os.Environment; +import android.os.Parcel; +import android.os.UserHandle; +import android.os.storage.StorageManager; +import android.text.TextUtils; +import android.util.ArrayMap; +import android.util.ArraySet; +import android.util.SparseArray; + +import com.android.internal.R; +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.ArrayUtils; +import com.android.server.SystemConfig; + +import java.security.PublicKey; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + +/** + * The backing data for a package that was parsed from disk. + * + * TODO(b/135203078): Convert Lists used as sets into Sets, to better express intended use case + * TODO(b/135203078): Field nullability annotations + * TODO(b/135203078): Convert = 1 fields into Booleans + * TODO(b/135203078): Make all lists nullable and Collections.unmodifiable immutable when returned. + * Prefer add/set methods if adding is necessary. + * TODO(b/135203078): Consider comments to disable auto-format and single-line, single-space all the + * get/set methods to make this class far more compact. Maybe even separate some logic into parent + * classes, assuming there is no overhead. + * TODO(b/135203078): Copy documentation from PackageParser#Package for the relevant fields included + * here. Should clarify and clean up any differences. Also consider renames if it helps make + * things clearer. + * TODO(b/135203078): Intern all possibl e String values? Initial refactor just mirrored old + * behavior. + * + * @hide + */ +public final class PackageImpl implements ParsingPackage, ParsedPackage, AndroidPackage, + AndroidPackageWrite { + + private static final String TAG = "PackageImpl"; + + // Resource boolean are -1, so 1 means we don't know the value. + private int supportsSmallScreens = 1; + private int supportsNormalScreens = 1; + private int supportsLargeScreens = 1; + private int supportsXLargeScreens = 1; + private int resizeable = 1; + private int anyDensity = 1; + + private long[] lastPackageUsageTimeInMills = + new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT]; + + private int versionCode; + private int versionCodeMajor; + private int baseRevisionCode; + private String versionName; + + private boolean coreApp; + private int compileSdkVersion; + private String compileSdkVersionCodename; + + private String packageName; + private String realPackage; + private String manifestPackageName; + private String baseCodePath; + + private boolean requiredForAllUsers; + private String restrictedAccountType; + private String requiredAccountType; + + private boolean baseHardwareAccelerated; + + private String overlayTarget; + private String overlayTargetName; + private String overlayCategory; + private int overlayPriority; + private boolean overlayIsStatic; + + private String staticSharedLibName; + private long staticSharedLibVersion; + private ArrayList<String> libraryNames; + private ArrayList<String> usesLibraries; + private ArrayList<String> usesOptionalLibraries; + + private ArrayList<String> usesStaticLibraries; + private long[] usesStaticLibrariesVersions; + private String[][] usesStaticLibrariesCertDigests; + + private String sharedUserId; + + private int sharedUserLabel; + private ArrayList<ConfigurationInfo> configPreferences; + private ArrayList<FeatureInfo> reqFeatures; + private ArrayList<FeatureGroupInfo> featureGroups; + + private byte[] restrictUpdateHash; + + private ArrayList<String> originalPackages; + private ArrayList<String> adoptPermissions; + + private ArrayList<String> requestedPermissions; + private ArrayList<String> implicitPermissions; + + private ArraySet<String> upgradeKeySets; + private Map<String, ArraySet<PublicKey>> keySetMapping; + + private ArrayList<String> protectedBroadcasts; + + @Nullable + private ArrayList<ComponentParseUtils.ParsedActivity> activities; + + @Nullable + private ArrayList<ComponentParseUtils.ParsedActivity> receivers; + + @Nullable + private ArrayList<ComponentParseUtils.ParsedService> services; + + @Nullable + private ArrayList<ComponentParseUtils.ParsedProvider> providers; + + @Nullable + private ArrayList<ComponentParseUtils.ParsedPermission> permissions; + + @Nullable + private ArrayList<ComponentParseUtils.ParsedPermissionGroup> permissionGroups; + + @Nullable + private ArrayList<ComponentParseUtils.ParsedInstrumentation> instrumentations; + + private ArrayList<ParsedActivityIntentInfo> preferredActivityFilters; + + private Bundle appMetaData; + + private String volumeUuid; + private String applicationVolumeUuid; + private PackageParser.SigningDetails signingDetails; + + private String codePath; + + private boolean use32BitAbi; + private boolean visibleToInstantApps; + + private String cpuAbiOverride; + + private boolean isStub; + + // TODO(b/135203078): Remove, should be unused + private int preferredOrder; + + private boolean forceQueryable; + + @Nullable + private ArrayList<Intent> queriesIntents; + + @Nullable + private ArrayList<String> queriesPackages; + + private String[] splitClassLoaderNames; + private String[] splitCodePaths; + private SparseArray<int[]> splitDependencies; + private int[] splitFlags; + private String[] splitNames; + private int[] splitRevisionCodes; + + // TODO(b/135203078): Audit applicationInfo.something usages, which may be different from + // package.something usages. There were differing cases of package.field = versus + // package.appInfo.field =. This class assumes some obvious ones, like packageName, + // were collapsible, but kept the following separate. + + private String applicationInfoBaseResourcePath; + private String applicationInfoCodePath; + private String applicationInfoResourcePath; + private String[] applicationInfoSplitResourcePaths; + + private String appComponentFactory; + private String backupAgentName; + private int banner; + private int category; + private String classLoaderName; + private String className; + private int compatibleWidthLimitDp; + private String credentialProtectedDataDir; + private String dataDir; + private int descriptionRes; + private String deviceProtectedDataDir; + private boolean enabled; + private int flags; + private int fullBackupContent; + private boolean hiddenUntilInstalled; + private int icon; + private int iconRes; + private int installLocation = PackageParser.PARSE_DEFAULT_INSTALL_LOCATION; + private int labelRes; + private int largestWidthLimitDp; + private int logo; + private String manageSpaceActivityName; + private float maxAspectRatio; + private float minAspectRatio; + private int minSdkVersion; + private String name; + private String nativeLibraryDir; + private String nativeLibraryRootDir; + private boolean nativeLibraryRootRequiresIsa; + private int networkSecurityConfigRes; + private CharSequence nonLocalizedLabel; + private String permission; + private String primaryCpuAbi; + private int privateFlags; + private String processName; + private int requiresSmallestWidthDp; + private int roundIconRes; + private String secondaryCpuAbi; + private String secondaryNativeLibraryDir; + private String seInfo; + private String seInfoUser; + private int targetSandboxVersion; + private int targetSdkVersion; + private String taskAffinity; + private int theme; + private int uid = -1; + private int uiOptions; + private String[] usesLibraryFiles; + private List<SharedLibraryInfo> usesLibraryInfos; + private String zygotePreloadName; + + @VisibleForTesting + public PackageImpl( + String packageName, + String baseCodePath, + TypedArray manifestArray, + boolean isCoreApp + ) { + this.packageName = TextUtils.safeIntern(packageName); + this.manifestPackageName = this.packageName; + this.baseCodePath = baseCodePath; + + this.versionCode = manifestArray.getInteger(R.styleable.AndroidManifest_versionCode, 0); + this.versionCodeMajor = manifestArray.getInteger( + R.styleable.AndroidManifest_versionCodeMajor, 0); + this.baseRevisionCode = manifestArray.getInteger(R.styleable.AndroidManifest_revisionCode, + 0); + setVersionName(manifestArray.getNonConfigurationString( + R.styleable.AndroidManifest_versionName, 0)); + this.coreApp = isCoreApp; + + this.compileSdkVersion = manifestArray.getInteger( + R.styleable.AndroidManifest_compileSdkVersion, 0); + setCompileSdkVersionCodename(manifestArray.getNonConfigurationString( + R.styleable.AndroidManifest_compileSdkVersionCodename, 0)); + } + + private PackageImpl(String packageName) { + this.packageName = TextUtils.safeIntern(packageName); + this.manifestPackageName = this.packageName; + } + + @VisibleForTesting + public static ParsingPackage forParsing(String packageName) { + return new PackageImpl(packageName); + } + + @VisibleForTesting + public static ParsingPackage forParsing( + String packageName, + String baseCodePath, + TypedArray manifestArray, + boolean isCoreApp) { + return new PackageImpl(packageName, baseCodePath, manifestArray, isCoreApp); + } + + /** + * Mock an unavailable {@link AndroidPackage} to use when removing a package from the system. + * This can occur if the package was installed on a storage device that has since been removed. + * Since the infrastructure uses {@link AndroidPackage}, but for this case only cares about + * volumeUuid, just fake it rather than having separate method paths. + */ + public static AndroidPackage buildFakeForDeletion(String packageName, String volumeUuid) { + return new PackageImpl(packageName) + .setVolumeUuid(volumeUuid) + .hideAsParsed() + .hideAsFinal(); + } + + @Override + public ParsedPackage hideAsParsed() { + return this; + } + + @Override + public AndroidPackage hideAsFinal() { + updateFlags(); + return this; + } + + @Override + @Deprecated + public AndroidPackageWrite mutate() { + return this; + } + + private void updateFlags() { + if (supportsSmallScreens < 0 || (supportsSmallScreens > 0 + && targetSdkVersion + >= Build.VERSION_CODES.DONUT)) { + this.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS; + } + if (supportsNormalScreens != 0) { + this.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS; + } + if (supportsLargeScreens < 0 || (supportsLargeScreens > 0 + && targetSdkVersion + >= Build.VERSION_CODES.DONUT)) { + this.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS; + } + if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0 + && targetSdkVersion + >= Build.VERSION_CODES.GINGERBREAD)) { + this.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS; + } + if (resizeable < 0 || (resizeable > 0 + && targetSdkVersion + >= Build.VERSION_CODES.DONUT)) { + this.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS; + } + if (anyDensity < 0 || (anyDensity > 0 + && targetSdkVersion + >= Build.VERSION_CODES.DONUT)) { + this.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES; + } + } + + @Override + public boolean usesCompatibilityMode() { + int flags = 0; + + if (supportsSmallScreens < 0 || (supportsSmallScreens > 0 + && targetSdkVersion + >= Build.VERSION_CODES.DONUT)) { + flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS; + } + if (supportsNormalScreens != 0) { + flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS; + } + if (supportsLargeScreens < 0 || (supportsLargeScreens > 0 + && targetSdkVersion + >= Build.VERSION_CODES.DONUT)) { + flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS; + } + if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0 + && targetSdkVersion + >= Build.VERSION_CODES.GINGERBREAD)) { + flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS; + } + if (resizeable < 0 || (resizeable > 0 + && targetSdkVersion + >= Build.VERSION_CODES.DONUT)) { + flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS; + } + if (anyDensity < 0 || (anyDensity > 0 + && targetSdkVersion + >= Build.VERSION_CODES.DONUT)) { + flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES; + } + + return targetSdkVersion < DONUT + || (flags & (ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS + | ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS + | ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS + | ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS + | ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES + | ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS)) == 0; + } + + @Override + public String getBaseCodePath() { + return baseCodePath; + } + + @Override + public int getTargetSdkVersion() { + return targetSdkVersion; + } + + @Override + public String getPackageName() { + return packageName; + } + + @Override + public String getProcessName() { + return processName; + } + + @Override + public String getPermission() { + return permission; + } + + @Override + public String getStaticSharedLibName() { + return staticSharedLibName; + } + + @Override + public long getStaticSharedLibVersion() { + return staticSharedLibVersion; + } + + @Override + public String getSharedUserId() { + return sharedUserId; + } + + @Override + public List<String> getRequestedPermissions() { + return requestedPermissions == null ? Collections.emptyList() : requestedPermissions; + } + + @Nullable + @Override + public List<ParsedInstrumentation> getInstrumentations() { + return instrumentations; + } + + @Override + public Map<String, ArraySet<PublicKey>> getKeySetMapping() { + return keySetMapping == null ? Collections.emptyMap() : keySetMapping; + } + + @Override + public float getMaxAspectRatio() { + return maxAspectRatio; + } + + @Override + public float getMinAspectRatio() { + return minAspectRatio; + } + + @NonNull + @Override + public List<String> getLibraryNames() { + return libraryNames == null ? Collections.emptyList() : libraryNames; + } + + @Override + public List<ParsedActivity> getActivities() { + return activities == null ? Collections.emptyList() + : activities; + } + + @Override + public Bundle getAppMetaData() { + return appMetaData; + } + + @Nullable + @Override + public List<String> getUsesLibraries() { + return usesLibraries; + } + + @Nullable + @Override + public List<String> getUsesStaticLibraries() { + return usesStaticLibraries; + } + + @Override + public boolean isBaseHardwareAccelerated() { + return baseHardwareAccelerated; + } + + @Override + public int getUiOptions() { + return uiOptions; + } + + // TODO(b/135203078): Checking flags directly can be error prone, + // consider separate interface methods? + @Override + public int getFlags() { + return flags; + } + + // TODO(b/135203078): Checking flags directly can be error prone, + // consider separate interface methods? + @Override + public int getPrivateFlags() { + return privateFlags; + } + + @Override + public String getTaskAffinity() { + return taskAffinity; + } + + @Nullable + @Override + public List<String> getOriginalPackages() { + return originalPackages; + } + + @Override + public PackageParser.SigningDetails getSigningDetails() { + return signingDetails; + } + + @Override + public String getVolumeUuid() { + return volumeUuid; + } + + @Nullable + @Override + public List<ParsedPermissionGroup> getPermissionGroups() { + return permissionGroups; + } + + @Nullable + @Override + public List<ParsedPermission> getPermissions() { + return permissions; + } + + @Override + public String getCpuAbiOverride() { + return cpuAbiOverride; + } + + @Override + public String getPrimaryCpuAbi() { + return primaryCpuAbi; + } + + @Override + public String getSecondaryCpuAbi() { + return secondaryCpuAbi; + } + + @Override + public boolean isUse32BitAbi() { + return use32BitAbi; + } + + @Override + public boolean isForceQueryable() { + return forceQueryable; + } + + @Override + public String getCodePath() { + return codePath; + } + + @Override + public String getNativeLibraryDir() { + return nativeLibraryDir; + } + + @Override + public String getNativeLibraryRootDir() { + return nativeLibraryRootDir; + } + + @Override + public boolean isNativeLibraryRootRequiresIsa() { + return nativeLibraryRootRequiresIsa; + } + + // TODO(b/135203078): Does nothing, remove? + @Override + public int getPreferredOrder() { + return preferredOrder; + } + + @Override + public long getLongVersionCode() { + return PackageInfo.composeLongVersionCode(versionCodeMajor, versionCode); + } + + @Override + public PackageImpl setIsOverlay(boolean isOverlay) { + this.privateFlags = isOverlay + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_IS_RESOURCE_OVERLAY + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_IS_RESOURCE_OVERLAY; + return this; + } + + @Override + public PackageImpl setExternalStorage(boolean externalStorage) { + this.flags = externalStorage + ? this.flags | ApplicationInfo.FLAG_EXTERNAL_STORAGE + : this.flags & ~ApplicationInfo.FLAG_EXTERNAL_STORAGE; + return this; + } + + @Override + public PackageImpl setIsolatedSplitLoading(boolean isolatedSplitLoading) { + this.privateFlags = isolatedSplitLoading + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING; + return this; + } + + @Override + public PackageImpl sortActivities() { + Collections.sort(this.activities, (a1, a2) -> Integer.compare(a2.order, a1.order)); + return this; + } + + @Override + public PackageImpl sortReceivers() { + Collections.sort(this.receivers, (a1, a2) -> Integer.compare(a2.order, a1.order)); + return this; + } + + @Override + public PackageImpl sortServices() { + Collections.sort(this.services, (a1, a2) -> Integer.compare(a2.order, a1.order)); + return this; + } + + @Override + public PackageImpl setBaseRevisionCode(int baseRevisionCode) { + this.baseRevisionCode = baseRevisionCode; + return this; + } + + @Override + public PackageImpl setPreferredOrder(int preferredOrder) { + this.preferredOrder = preferredOrder; + return this; + } + + @Override + public PackageImpl setVersionName(String versionName) { + this.versionName = TextUtils.safeIntern(versionName); + return this; + } + + @Override + public ParsingPackage setCompileSdkVersion(int compileSdkVersion) { + this.compileSdkVersion = compileSdkVersion; + return this; + } + + @Override + public ParsingPackage setCompileSdkVersionCodename(String compileSdkVersionCodename) { + this.compileSdkVersionCodename = TextUtils.safeIntern(compileSdkVersionCodename); + return this; + } + + @Override + public PackageImpl setMaxAspectRatio(float maxAspectRatio) { + this.maxAspectRatio = maxAspectRatio; + return this; + } + + @Override + public PackageImpl setMinAspectRatio(float minAspectRatio) { + this.minAspectRatio = minAspectRatio; + return this; + } + + @Override + public PackageImpl setMinSdkVersion(int minSdkVersion) { + this.minSdkVersion = minSdkVersion; + return this; + } + + @Override + public PackageImpl setTargetSdkVersion(int targetSdkVersion) { + this.targetSdkVersion = targetSdkVersion; + return this; + } + + @Override + public PackageImpl setRealPackage(String realPackage) { + this.realPackage = realPackage; + return this; + } + + @Override + public PackageImpl addConfigPreference(ConfigurationInfo configPreference) { + this.configPreferences = ArrayUtils.add(this.configPreferences, configPreference); + return this; + } + + @Override + public PackageImpl addReqFeature(FeatureInfo reqFeature) { + this.reqFeatures = ArrayUtils.add(this.reqFeatures, reqFeature); + return this; + } + + @Override + public PackageImpl addFeatureGroup(FeatureGroupInfo featureGroup) { + this.featureGroups = ArrayUtils.add(this.featureGroups, featureGroup); + return this; + } + + @Override + public PackageImpl addProtectedBroadcast(String protectedBroadcast) { + if (this.protectedBroadcasts == null + || !this.protectedBroadcasts.contains(protectedBroadcast)) { + this.protectedBroadcasts = ArrayUtils.add(this.protectedBroadcasts, + TextUtils.safeIntern(protectedBroadcast)); + } + return this; + } + + @Override + public PackageImpl addInstrumentation(ParsedInstrumentation instrumentation) { + this.instrumentations = ArrayUtils.add(this.instrumentations, instrumentation); + return this; + } + + @Override + public PackageImpl addOriginalPackage(String originalPackage) { + this.originalPackages = ArrayUtils.add(this.originalPackages, originalPackage); + return this; + } + + @Override + public PackageImpl addAdoptPermission(String adoptPermission) { + this.adoptPermissions = ArrayUtils.add(this.adoptPermissions, adoptPermission); + return this; + } + + @Override + public PackageImpl addPermission(ParsedPermission permission) { + this.permissions = ArrayUtils.add(this.permissions, permission); + return this; + } + + @Override + public PackageImpl removePermission(int index) { + this.permissions.remove(index); + return this; + } + + @Override + public PackageImpl addPermissionGroup(ParsedPermissionGroup permissionGroup) { + this.permissionGroups = ArrayUtils.add(this.permissionGroups, permissionGroup); + return this; + } + + @Override + public PackageImpl addRequestedPermission(String permission) { + this.requestedPermissions = ArrayUtils.add(this.requestedPermissions, + TextUtils.safeIntern(permission)); + return this; + } + + @Override + public PackageImpl addImplicitPermission(String permission) { + this.implicitPermissions = ArrayUtils.add(this.implicitPermissions, + TextUtils.safeIntern(permission)); + return this; + } + + @Override + public PackageImpl addKeySet(String keySetName, PublicKey publicKey) { + if (keySetMapping == null) { + keySetMapping = new ArrayMap<>(); + } + + ArraySet<PublicKey> publicKeys = keySetMapping.get(keySetName); + if (publicKeys == null) { + publicKeys = new ArraySet<>(); + keySetMapping.put(keySetName, publicKeys); + } + + publicKeys.add(publicKey); + + return this; + } + + @Override + public ParsingPackage addActivity(ParsedActivity parsedActivity) { + this.activities = ArrayUtils.add(this.activities, parsedActivity); + return this; + } + + @Override + public ParsingPackage addReceiver(ParsedActivity parsedReceiver) { + this.receivers = ArrayUtils.add(this.receivers, parsedReceiver); + return this; + } + + @Override + public ParsingPackage addService(ParsedService parsedService) { + this.services = ArrayUtils.add(this.services, parsedService); + return this; + } + + @Override + public ParsingPackage addProvider(ParsedProvider parsedProvider) { + this.providers = ArrayUtils.add(this.providers, parsedProvider); + return this; + } + + @Override + public PackageImpl addLibraryName(String libraryName) { + this.libraryNames = ArrayUtils.add(this.libraryNames, TextUtils.safeIntern(libraryName)); + return this; + } + + @Override + public PackageImpl addUsesLibrary(String libraryName) { + this.usesLibraries = ArrayUtils.add(this.usesLibraries, TextUtils.safeIntern(libraryName)); + return this; + } + + @Override + public PackageImpl addUsesOptionalLibrary(String libraryName) { + this.usesOptionalLibraries = ArrayUtils.add(this.usesOptionalLibraries, + TextUtils.safeIntern(libraryName)); + return this; + } + + @Override + public PackageImpl removeUsesOptionalLibrary(String libraryName) { + this.usesOptionalLibraries = ArrayUtils.remove(this.usesOptionalLibraries, libraryName); + return this; + } + + @Override + public PackageImpl addUsesStaticLibrary(String libraryName) { + this.usesStaticLibraries = ArrayUtils.add(this.usesStaticLibraries, + TextUtils.safeIntern(libraryName)); + return this; + } + + @Override + public PackageImpl addUsesStaticLibraryVersion(long version) { + this.usesStaticLibrariesVersions = ArrayUtils.appendLong(this.usesStaticLibrariesVersions, + version, true); + return this; + } + + @Override + public PackageImpl addUsesStaticLibraryCertDigests(String[] certSha256Digests) { + this.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String[].class, + this.usesStaticLibrariesCertDigests, certSha256Digests, true); + return this; + } + + @Override + public PackageImpl addPreferredActivityFilter( + ParsedActivityIntentInfo parsedActivityIntentInfo) { + this.preferredActivityFilters = ArrayUtils.add(this.preferredActivityFilters, + parsedActivityIntentInfo); + return this; + } + + @Override + public PackageImpl addQueriesIntent(Intent intent) { + this.queriesIntents = ArrayUtils.add(this.queriesIntents, intent); + return this; + } + + @Override + public PackageImpl addQueriesPackage(String packageName) { + this.queriesPackages = ArrayUtils.add(this.queriesPackages, + TextUtils.safeIntern(packageName)); + return this; + } + + @Override + public PackageImpl setSupportsSmallScreens(int supportsSmallScreens) { + if (supportsSmallScreens == 1) { + return this; + } + + this.supportsSmallScreens = supportsSmallScreens; + return this; + } + + @Override + public PackageImpl setSupportsNormalScreens(int supportsNormalScreens) { + if (supportsNormalScreens == 1) { + return this; + } + + this.supportsNormalScreens = supportsNormalScreens; + return this; + } + + @Override + public PackageImpl setSupportsLargeScreens(int supportsLargeScreens) { + if (supportsLargeScreens == 1) { + return this; + } + + this.supportsLargeScreens = supportsLargeScreens; + return this; + } + + @Override + public PackageImpl setSupportsXLargeScreens(int supportsXLargeScreens) { + if (supportsXLargeScreens == 1) { + return this; + } + + this.supportsXLargeScreens = supportsXLargeScreens; + return this; + } + + @Override + public PackageImpl setResizeable(int resizeable) { + if (resizeable == 1) { + return this; + } + + this.resizeable = resizeable; + return this; + } + + @Override + public PackageImpl setAnyDensity(int anyDensity) { + if (anyDensity == 1) { + return this; + } + + this.anyDensity = anyDensity; + return this; + } + + @Override + public PackageImpl setRequiresSmallestWidthDp(int requiresSmallestWidthDp) { + this.requiresSmallestWidthDp = requiresSmallestWidthDp; + return this; + } + + @Override + public PackageImpl setCompatibleWidthLimitDp(int compatibleWidthLimitDp) { + this.compatibleWidthLimitDp = compatibleWidthLimitDp; + return this; + } + + @Override + public PackageImpl setLargestWidthLimitDp(int largestWidthLimitDp) { + this.largestWidthLimitDp = largestWidthLimitDp; + return this; + } + + @Override + public PackageImpl setInstallLocation(int installLocation) { + this.installLocation = installLocation; + return this; + } + + @Override + public PackageImpl setTargetSandboxVersion(int targetSandboxVersion) { + this.targetSandboxVersion = targetSandboxVersion; + return this; + } + + @Override + public PackageImpl setRequiredForAllUsers(boolean requiredForAllUsers) { + this.requiredForAllUsers = requiredForAllUsers; + return this; + } + + @Override + public PackageImpl setRestrictedAccountType(String restrictedAccountType) { + this.restrictedAccountType = restrictedAccountType; + return this; + } + + @Override + public PackageImpl setRequiredAccountType(String requiredAccountType) { + this.requiredAccountType = requiredAccountType; + return this; + } + + @Override + public PackageImpl setBaseHardwareAccelerated(boolean baseHardwareAccelerated) { + this.baseHardwareAccelerated = baseHardwareAccelerated; + + this.flags = baseHardwareAccelerated + ? this.flags | ApplicationInfo.FLAG_HARDWARE_ACCELERATED + : this.flags & ~ApplicationInfo.FLAG_HARDWARE_ACCELERATED; + + return this; + } + + @Override + public PackageImpl setHasDomainUrls(boolean hasDomainUrls) { + this.privateFlags = hasDomainUrls + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS; + return this; + } + + @Override + public PackageImpl setAppMetaData(Bundle appMetaData) { + this.appMetaData = appMetaData; + return this; + } + + @Override + public PackageImpl setOverlayTarget(String overlayTarget) { + this.overlayTarget = overlayTarget; + return this; + } + + @Override + public PackageImpl setOverlayTargetName(String overlayTargetName) { + this.overlayTargetName = overlayTargetName; + return this; + } + + @Override + public PackageImpl setOverlayCategory(String overlayCategory) { + this.overlayCategory = overlayCategory; + return this; + } + + @Override + public PackageImpl setOverlayPriority(int overlayPriority) { + this.overlayPriority = overlayPriority; + return this; + } + + @Override + public PackageImpl setOverlayIsStatic(boolean overlayIsStatic) { + this.overlayIsStatic = overlayIsStatic; + return this; + } + + @Override + public PackageImpl setStaticSharedLibName(String staticSharedLibName) { + this.staticSharedLibName = TextUtils.safeIntern(staticSharedLibName); + return this; + } + + @Override + public PackageImpl setStaticSharedLibVersion(long staticSharedLibVersion) { + this.staticSharedLibVersion = staticSharedLibVersion; + return this; + } + + @Override + public PackageImpl setSharedUserId(String sharedUserId) { + this.sharedUserId = TextUtils.safeIntern(sharedUserId); + return this; + } + + @Override + public PackageImpl setSharedUserLabel(int sharedUserLabel) { + this.sharedUserLabel = sharedUserLabel; + return this; + } + + @Override + public PackageImpl setRestrictUpdateHash(byte[] restrictUpdateHash) { + this.restrictUpdateHash = restrictUpdateHash; + return this; + } + + @Override + public PackageImpl setUpgradeKeySets(ArraySet<String> upgradeKeySets) { + this.upgradeKeySets = upgradeKeySets; + return this; + } + + @Override + public PackageImpl setVolumeUuid(String volumeUuid) { + this.volumeUuid = volumeUuid; + return this; + } + + @Deprecated + @Override + public PackageImpl setApplicationVolumeUuid(String applicationVolumeUuid) { + this.applicationVolumeUuid = applicationVolumeUuid; + return this; + } + + @Override + public PackageImpl setSigningDetails(PackageParser.SigningDetails signingDetails) { + this.signingDetails = signingDetails; + return this; + } + + @Override + public PackageImpl setCodePath(String codePath) { + this.codePath = codePath; + return this; + } + + @Override + public PackageImpl setUse32BitAbi(boolean use32BitAbi) { + this.use32BitAbi = use32BitAbi; + return this; + } + + @Override + public PackageImpl setCpuAbiOverride(String cpuAbiOverride) { + this.cpuAbiOverride = cpuAbiOverride; + return this; + } + + @Override + public PackageImpl setForceQueryable(boolean forceQueryable) { + this.forceQueryable = forceQueryable; + return this; + } + + // TODO(b/135203078): Remove and move PackageManagerService#renameStaticSharedLibraryPackage + // into initial package parsing + @Override + public PackageImpl setPackageName(String packageName) { + this.packageName = packageName.intern(); + + if (permissions != null) { + for (ParsedPermission permission : permissions) { + permission.setPackageName(this.packageName); + } + } + + if (permissionGroups != null) { + for (ParsedPermissionGroup permissionGroup : permissionGroups) { + permissionGroup.setPackageName(this.packageName); + } + } + + if (activities != null) { + for (ParsedActivity parsedActivity : activities) { + parsedActivity.setPackageName(this.packageName); + } + } + + if (receivers != null) { + for (ParsedActivity receiver : receivers) { + receiver.setPackageName(this.packageName); + } + } + + if (providers != null) { + for (ParsedProvider provider : providers) { + provider.setPackageName(this.packageName); + } + } + + if (services != null) { + for (ParsedService service : services) { + service.setPackageName(this.packageName); + } + } + + if (instrumentations != null) { + for (ParsedInstrumentation instrumentation : instrumentations) { + instrumentation.setPackageName(this.packageName); + } + } + + return this; + } + + // Under this is parseBaseApplication + + @Override + public PackageImpl setAllowBackup(boolean allowBackup) { + this.flags = allowBackup + ? this.flags | ApplicationInfo.FLAG_ALLOW_BACKUP + : this.flags & ~ApplicationInfo.FLAG_ALLOW_BACKUP; + return this; + } + + @Override + public PackageImpl setKillAfterRestore(boolean killAfterRestore) { + this.flags = killAfterRestore + ? this.flags | ApplicationInfo.FLAG_KILL_AFTER_RESTORE + : this.flags & ~ApplicationInfo.FLAG_KILL_AFTER_RESTORE; + return this; + } + + @Override + public PackageImpl setRestoreAnyVersion(boolean restoreAnyVersion) { + this.flags = restoreAnyVersion + ? this.flags | ApplicationInfo.FLAG_RESTORE_ANY_VERSION + : this.flags & ~ApplicationInfo.FLAG_RESTORE_ANY_VERSION; + return this; + } + + @Override + public PackageImpl setFullBackupOnly(boolean fullBackupOnly) { + this.flags = fullBackupOnly + ? this.flags | ApplicationInfo.FLAG_FULL_BACKUP_ONLY + : this.flags & ~ApplicationInfo.FLAG_FULL_BACKUP_ONLY; + return this; + } + + @Override + public PackageImpl setPersistent(boolean persistent) { + this.flags = persistent + ? this.flags | ApplicationInfo.FLAG_PERSISTENT + : this.flags & ~ApplicationInfo.FLAG_PERSISTENT; + return this; + } + + @Override + public PackageImpl setDebuggable(boolean debuggable) { + this.flags = debuggable + ? this.flags | ApplicationInfo.FLAG_DEBUGGABLE + : this.flags & ~ApplicationInfo.FLAG_DEBUGGABLE; + return this; + } + + @Override + public PackageImpl setProfileableByShell(boolean profileableByShell) { + this.privateFlags = profileableByShell + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL; + return this; + } + + @Override + public PackageImpl setVmSafeMode(boolean vmSafeMode) { + this.flags = vmSafeMode + ? this.flags | ApplicationInfo.FLAG_VM_SAFE_MODE + : this.flags & ~ApplicationInfo.FLAG_VM_SAFE_MODE; + return this; + } + + @Override + public PackageImpl setHasCode(boolean hasCode) { + this.flags = hasCode + ? this.flags | ApplicationInfo.FLAG_HAS_CODE + : this.flags & ~ApplicationInfo.FLAG_HAS_CODE; + return this; + } + + @Override + public PackageImpl setAllowTaskReparenting(boolean allowTaskReparenting) { + this.flags = allowTaskReparenting + ? this.flags | ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING + : this.flags & ~ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING; + return this; + } + + @Override + public PackageImpl setAllowClearUserData(boolean allowClearUserData) { + this.flags = allowClearUserData + ? this.flags | ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA + : this.flags & ~ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA; + return this; + } + + @Override + public PackageImpl setLargeHeap(boolean largeHeap) { + this.flags = largeHeap + ? this.flags | ApplicationInfo.FLAG_LARGE_HEAP + : this.flags & ~ApplicationInfo.FLAG_LARGE_HEAP; + return this; + } + + @Override + public PackageImpl setUsesCleartextTraffic(boolean usesCleartextTraffic) { + this.flags = usesCleartextTraffic + ? this.flags | ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC + : this.flags & ~ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC; + return this; + } + + @Override + public PackageImpl setSupportsRtl(boolean supportsRtl) { + this.flags = supportsRtl + ? this.flags | ApplicationInfo.FLAG_SUPPORTS_RTL + : this.flags & ~ApplicationInfo.FLAG_SUPPORTS_RTL; + return this; + } + + @Override + public PackageImpl setTestOnly(boolean testOnly) { + this.flags = testOnly + ? this.flags | ApplicationInfo.FLAG_TEST_ONLY + : this.flags & ~ApplicationInfo.FLAG_TEST_ONLY; + return this; + } + + @Override + public PackageImpl setMultiArch(boolean multiArch) { + this.flags = multiArch + ? this.flags | ApplicationInfo.FLAG_MULTIARCH + : this.flags & ~ApplicationInfo.FLAG_MULTIARCH; + return this; + } + + @Override + public PackageImpl setExtractNativeLibs(boolean extractNativeLibs) { + this.flags = extractNativeLibs + ? this.flags | ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS + : this.flags & ~ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS; + return this; + } + + @Override + public PackageImpl setIsGame(boolean isGame) { + this.flags = isGame + ? this.flags | ApplicationInfo.FLAG_IS_GAME + : this.flags & ~ApplicationInfo.FLAG_IS_GAME; + return this; + } + + @Override + public PackageImpl setBackupInForeground(boolean backupInForeground) { + this.privateFlags = backupInForeground + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND; + return this; + } + + @Override + public PackageImpl setUseEmbeddedDex(boolean useEmbeddedDex) { + this.privateFlags = useEmbeddedDex + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_USE_EMBEDDED_DEX + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_USE_EMBEDDED_DEX; + return this; + } + + @Override + public PackageImpl setDefaultToDeviceProtectedStorage(boolean defaultToDeviceProtectedStorage) { + this.privateFlags = defaultToDeviceProtectedStorage + ? this.privateFlags | ApplicationInfo + .PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE + : this.privateFlags & ~ApplicationInfo + .PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE; + return this; + } + + @Override + public PackageImpl setDirectBootAware(boolean directBootAware) { + this.privateFlags = directBootAware + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE; + return this; + } + + @Override + public PackageImpl setPartiallyDirectBootAware(boolean partiallyDirectBootAware) { + this.privateFlags = partiallyDirectBootAware + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE; + return this; + } + + @Override + public PackageImpl setActivitiesResizeModeResizeableViaSdkVersion( + boolean resizeableViaSdkVersion + ) { + this.privateFlags = resizeableViaSdkVersion + ? this.privateFlags | ApplicationInfo + .PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION + : this.privateFlags & ~ApplicationInfo + .PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION; + return this; + } + + @Override + public PackageImpl setActivitiesResizeModeResizeable(boolean resizeable) { + this.privateFlags = resizeable + ? this.privateFlags | ApplicationInfo + .PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE + : this.privateFlags & ~ApplicationInfo + .PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE; + + this.privateFlags = !resizeable + ? this.privateFlags | ApplicationInfo + .PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE + : this.privateFlags & ~ApplicationInfo + .PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE; + return this; + } + + @Override + public PackageImpl setAllowClearUserDataOnFailedRestore( + boolean allowClearUserDataOnFailedRestore + ) { + this.privateFlags = allowClearUserDataOnFailedRestore + ? this.privateFlags | ApplicationInfo + .PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE + : this.privateFlags & ~ApplicationInfo + .PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE; + return this; + } + + @Override + public PackageImpl setAllowAudioPlaybackCapture(boolean allowAudioPlaybackCapture) { + this.privateFlags = allowAudioPlaybackCapture + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE; + return this; + } + + @Override + public PackageImpl setRequestLegacyExternalStorage(boolean requestLegacyExternalStorage) { + this.privateFlags = requestLegacyExternalStorage + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE; + return this; + } + + @Override + public PackageImpl setUsesNonSdkApi(boolean usesNonSdkApi) { + this.privateFlags = usesNonSdkApi + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API; + return this; + } + + @Override + public PackageImpl setHasFragileUserData(boolean hasFragileUserData) { + this.privateFlags = hasFragileUserData + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_HAS_FRAGILE_USER_DATA + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_HAS_FRAGILE_USER_DATA; + return this; + } + + @Override + public PackageImpl setCantSaveState(boolean cantSaveState) { + this.privateFlags = cantSaveState + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE; + return this; + } + + @Override + public boolean cantSaveState() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0; + } + + @Override + public boolean isLibrary() { + return staticSharedLibName != null || !ArrayUtils.isEmpty(libraryNames); + } + + // TODO(b/135203078): This does nothing until the final stage without applyPolicy being + // part of PackageParser + @Override + public boolean isSystemApp() { + return (flags & ApplicationInfo.FLAG_SYSTEM) != 0; + } + + // TODO(b/135203078): This does nothing until the final stage without applyPolicy being + // part of PackageParser + @Override + public boolean isSystemExt() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT) != 0; + } + + // TODO(b/135203078): This does nothing until the final stage without applyPolicy being + // part of PackageParser + @Override + public boolean isUpdatedSystemApp() { + return (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0; + } + + @Override + public PackageImpl setStaticSharedLibrary(boolean staticSharedLibrary) { + this.privateFlags = staticSharedLibrary + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY; + return this; + } + + @Override + public boolean isStaticSharedLibrary() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY) != 0; + } + + @Override + public PackageImpl setVisibleToInstantApps(boolean visibleToInstantApps) { + this.visibleToInstantApps = visibleToInstantApps; + return this; + } + + @Override + public PackageImpl setIconRes(int iconRes) { + this.iconRes = iconRes; + return this; + } + + @Override + public PackageImpl setRoundIconRes(int roundIconRes) { + this.roundIconRes = roundIconRes; + return this; + } + + @Override + public PackageImpl setClassName(String className) { + this.className = className; + return this; + } + + @Override + public PackageImpl setManageSpaceActivityName(String manageSpaceActivityName) { + this.manageSpaceActivityName = manageSpaceActivityName; + return this; + } + + @Override + public PackageImpl setBackupAgentName(String backupAgentName) { + this.backupAgentName = backupAgentName; + return this; + } + + @Override + public PackageImpl setFullBackupContent(int fullBackupContent) { + this.fullBackupContent = fullBackupContent; + return this; + } + + @Override + public PackageImpl setTheme(int theme) { + this.theme = theme; + return this; + } + + @Override + public PackageImpl setDescriptionRes(int descriptionRes) { + this.descriptionRes = descriptionRes; + return this; + } + + @Override + public PackageImpl setNetworkSecurityConfigRes(int networkSecurityConfigRes) { + this.networkSecurityConfigRes = networkSecurityConfigRes; + return this; + } + + @Override + public PackageImpl setCategory(int category) { + this.category = category; + return this; + } + + @Override + public PackageImpl setPermission(String permission) { + this.permission = permission; + return this; + } + + @Override + public PackageImpl setTaskAffinity(String taskAffinity) { + this.taskAffinity = taskAffinity; + return this; + } + + @Override + public PackageImpl setAppComponentFactory(String appComponentFactory) { + this.appComponentFactory = appComponentFactory; + return this; + } + + @Override + public PackageImpl setProcessName(String processName) { + if (processName == null) { + this.processName = packageName; + } else { + this.processName = processName; + } + return this; + } + + @Override + public PackageImpl setEnabled(boolean enabled) { + this.enabled = enabled; + return this; + } + + @Override + public PackageImpl setUiOptions(int uiOptions) { + this.uiOptions = uiOptions; + return this; + } + + @Override + public PackageImpl setClassLoaderName(String classLoaderName) { + this.classLoaderName = classLoaderName; + return this; + } + + @Override + public PackageImpl setZygotePreloadName(String zygotePreloadName) { + this.zygotePreloadName = zygotePreloadName; + return this; + } + + // parsePackageItemInfo + + @Override + public String getName() { + return name; + } + + @Override + public PackageImpl setName(String name) { + this.name = name; + return this; + } + + @Override + public PackageImpl setIcon(int icon) { + this.icon = icon; + return this; + } + + @Override + public PackageImpl setNonLocalizedLabel(CharSequence nonLocalizedLabel) { + this.nonLocalizedLabel = nonLocalizedLabel; + return this; + } + + @Override + public PackageImpl setLogo(int logo) { + this.logo = logo; + return this; + } + + @Override + public PackageImpl setBanner(int banner) { + this.banner = banner; + return this; + } + + @Override + public PackageImpl setLabelRes(int labelRes) { + this.labelRes = labelRes; + return this; + } + + @Override + public PackageImpl asSplit( + String[] splitNames, + String[] splitCodePaths, + int[] splitRevisionCodes, + SparseArray<int[]> splitDependencies + ) { + this.splitNames = splitNames; + + if (this.splitNames != null) { + for (int index = 0; index < this.splitNames.length; index++) { + splitNames[index] = TextUtils.safeIntern(splitNames[index]); + } + } + + this.splitCodePaths = splitCodePaths; + this.splitRevisionCodes = splitRevisionCodes; + this.splitDependencies = splitDependencies; + + int count = splitNames.length; + this.splitFlags = new int[count]; + this.splitClassLoaderNames = new String[count]; + return this; + } + + @Override + public String[] getSplitNames() { + return splitNames; + } + + @Override + public String[] getSplitCodePaths() { + return splitCodePaths; + } + + @Override + public PackageImpl setSplitHasCode(int splitIndex, boolean splitHasCode) { + this.splitFlags[splitIndex] = splitHasCode + ? this.splitFlags[splitIndex] | ApplicationInfo.FLAG_HAS_CODE + : this.splitFlags[splitIndex] & ~ApplicationInfo.FLAG_HAS_CODE; + return this; + } + + @Override + public PackageImpl setSplitClassLoaderName(int splitIndex, String classLoaderName) { + this.splitClassLoaderNames[splitIndex] = classLoaderName; + return this; + } + + @Override + public List<String> makeListAllCodePaths() { + ArrayList<String> paths = new ArrayList<>(); + paths.add(baseCodePath); + + if (!ArrayUtils.isEmpty(splitCodePaths)) { + Collections.addAll(paths, splitCodePaths); + } + return paths; + } + + @Override + public PackageImpl setBaseCodePath(String baseCodePath) { + this.baseCodePath = baseCodePath; + return this; + } + + @Override + public PackageImpl setSplitCodePaths(String[] splitCodePaths) { + this.splitCodePaths = splitCodePaths; + return this; + } + + @Override + public String toString() { + return "Package{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + packageName + "}"; + } + + @Override + public PackageImpl setPrimaryCpuAbi(String primaryCpuAbi) { + this.primaryCpuAbi = primaryCpuAbi; + return this; + } + + @Override + public PackageImpl setSecondaryCpuAbi(String secondaryCpuAbi) { + this.secondaryCpuAbi = secondaryCpuAbi; + return this; + } + + @Override + public PackageImpl setNativeLibraryRootDir(String nativeLibraryRootDir) { + this.nativeLibraryRootDir = nativeLibraryRootDir; + return this; + } + + @Override + public PackageImpl setNativeLibraryRootRequiresIsa(boolean nativeLibraryRootRequiresIsa) { + this.nativeLibraryRootRequiresIsa = nativeLibraryRootRequiresIsa; + return this; + } + + @Override + public PackageImpl setNativeLibraryDir(String nativeLibraryDir) { + this.nativeLibraryDir = nativeLibraryDir; + return this; + } + + @Override + public PackageImpl setSecondaryNativeLibraryDir(String secondaryNativeLibraryDir) { + this.secondaryNativeLibraryDir = secondaryNativeLibraryDir; + return this; + } + + @Deprecated + @Override + public PackageImpl setApplicationInfoCodePath(String applicationInfoCodePath) { + this.applicationInfoCodePath = applicationInfoCodePath; + return this; + } + + @Deprecated + @Override + public PackageImpl setApplicationInfoResourcePath(String applicationInfoResourcePath) { + this.applicationInfoResourcePath = applicationInfoResourcePath; + return this; + } + + @Deprecated + @Override + public PackageImpl setApplicationInfoBaseResourcePath( + String applicationInfoBaseResourcePath) { + this.applicationInfoBaseResourcePath = applicationInfoBaseResourcePath; + return this; + } + + @Deprecated + @Override + public PackageImpl setApplicationInfoSplitResourcePaths( + String[] applicationInfoSplitResourcePaths) { + this.applicationInfoSplitResourcePaths = applicationInfoSplitResourcePaths; + return this; + } + + @Override + public boolean isDirectBootAware() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE) != 0; + } + + @Override + public PackageImpl setAllComponentsDirectBootAware(boolean allComponentsDirectBootAware) { + if (activities != null) { + for (ParsedActivity parsedActivity : activities) { + parsedActivity.directBootAware = allComponentsDirectBootAware; + } + } + + if (receivers != null) { + for (ParsedActivity parsedReceiver : receivers) { + parsedReceiver.directBootAware = allComponentsDirectBootAware; + } + } + + if (providers != null) { + for (ParsedProvider parsedProvider : providers) { + parsedProvider.directBootAware = allComponentsDirectBootAware; + } + } + + if (services != null) { + for (ParsedService parsedService : services) { + parsedService.directBootAware = allComponentsDirectBootAware; + } + } + + return this; + } + + @Override + public PackageImpl setSystem(boolean system) { + this.flags = system + ? this.flags | ApplicationInfo.FLAG_SYSTEM + : this.flags & ~ApplicationInfo.FLAG_SYSTEM; + return this; + } + + @Override + public PackageImpl setSystemExt(boolean systemExt) { + this.privateFlags = systemExt + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT; + return this; + } + + @Override + public PackageImpl setIsStub(boolean isStub) { + this.isStub = isStub; + return this; + } + + @Override + public PackageImpl setCoreApp(boolean coreApp) { + this.coreApp = coreApp; + return this; + } + + @Override + public ParsedPackage capPermissionPriorities() { + if (permissionGroups != null && !permissionGroups.isEmpty()) { + for (int i = permissionGroups.size() - 1; i >= 0; --i) { + // TODO(b/135203078): Builder/immutability + permissionGroups.get(i).priority = 0; + } + } + return this; + } + + @Override + public ParsedPackage clearProtectedBroadcasts() { + if (protectedBroadcasts != null) { + protectedBroadcasts.clear(); + } + return this; + } + + @Override + public ParsedPackage markNotActivitiesAsNotExportedIfSingleUser() { + // ignore export request for single user receivers + if (receivers != null) { + for (ParsedActivity receiver : receivers) { + if ((receiver.flags & ActivityInfo.FLAG_SINGLE_USER) != 0) { + receiver.exported = false; + } + } + } + // ignore export request for single user services + if (services != null) { + for (ParsedService service : services) { + if ((service.flags & ServiceInfo.FLAG_SINGLE_USER) != 0) { + service.exported = false; + } + } + } + // ignore export request for single user providers + if (providers != null) { + for (ParsedProvider provider : providers) { + if ((provider.flags & ProviderInfo.FLAG_SINGLE_USER) != 0) { + provider.exported = false; + } + } + } + + return this; + } + + @Override + public ParsedPackage setPrivileged(boolean privileged) { + this.privateFlags = privileged + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_PRIVILEGED + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_PRIVILEGED; + return this; + } + + @Override + public ParsedPackage setOem(boolean oem) { + this.privateFlags = oem + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_OEM + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_OEM; + return this; + } + + @Override + public ParsedPackage setVendor(boolean vendor) { + this.privateFlags = vendor + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_VENDOR + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_VENDOR; + return this; + } + + @Override + public ParsedPackage setProduct(boolean product) { + this.privateFlags = product + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_PRODUCT + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_PRODUCT; + return this; + } + + @Override + public ParsedPackage setOdm(boolean odm) { + this.privateFlags = odm + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_ODM + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_ODM; + return this; + } + + @Override + public ParsedPackage setSignedWithPlatformKey(boolean signedWithPlatformKey) { + this.privateFlags = signedWithPlatformKey + ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY + : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY; + return this; + } + + @Override + public ParsedPackage clearOriginalPackages() { + if (originalPackages != null) { + originalPackages.clear(); + } + return this; + } + + @Override + public ParsedPackage clearAdoptPermissions() { + if (adoptPermissions != null) { + adoptPermissions.clear(); + } + return this; + } + + @Override + public PackageImpl addUsesLibrary(int index, String libraryName) { + this.usesLibraries = ArrayUtils.add(usesLibraries, index, libraryName); + return this; + } + + @Override + public ParsedPackage removeUsesLibrary(String libraryName) { + this.usesLibraries = ArrayUtils.remove(this.usesLibraries, libraryName); + return this; + } + + @Override + public PackageImpl addUsesOptionalLibrary(int index, String libraryName) { + this.usesOptionalLibraries = ArrayUtils.add(usesOptionalLibraries, index, libraryName); + return this; + } + + @Nullable + @Override + public List<String> getUsesOptionalLibraries() { + return usesOptionalLibraries; + } + + @Override + public int getVersionCode() { + return versionCode; + } + + @Nullable + @Override + public long[] getUsesStaticLibrariesVersions() { + return usesStaticLibrariesVersions; + } + + @Override + public PackageImpl setPackageSettingCallback(PackageSettingCallback packageSettingCallback) { + packageSettingCallback.setAndroidPackage(this); + return this; + } + + @Override + public PackageImpl setUpdatedSystemApp(boolean updatedSystemApp) { + this.flags = updatedSystemApp + ? this.flags | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP + : this.flags & ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; + return this; + } + + @Override + public boolean isPrivileged() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; + } + + @Override + public PackageImpl setSeInfo(String seInfo) { + this.seInfo = seInfo; + return this; + } + + @Override + public PackageImpl setSeInfoUser(String seInfoUser) { + this.seInfoUser = seInfoUser; + return this; + } + + @Override + public PackageImpl initForUser(int userId) { + // TODO(b/135203078): Move this user state to some other data structure + this.uid = UserHandle.getUid(userId, UserHandle.getAppId(this.uid)); + + if ("android".equals(packageName)) { + dataDir = Environment.getDataSystemDirectory().getAbsolutePath(); + return this; + } + + deviceProtectedDataDir = Environment + .getDataUserDePackageDirectory(applicationVolumeUuid, userId, packageName) + .getAbsolutePath(); + credentialProtectedDataDir = Environment + .getDataUserCePackageDirectory(applicationVolumeUuid, userId, packageName) + .getAbsolutePath(); + + if ((privateFlags & ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) != 0 + && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) { + dataDir = deviceProtectedDataDir; + } else { + dataDir = credentialProtectedDataDir; + } + return this; + } + + @Override + public ParsedPackage setFactoryTest(boolean factoryTest) { + this.flags = factoryTest + ? this.flags | ApplicationInfo.FLAG_FACTORY_TEST + : this.flags & ~ApplicationInfo.FLAG_FACTORY_TEST; + return this; + } + + @Override + public String getManifestPackageName() { + return manifestPackageName; + } + + @Override + public String getRealPackage() { + return realPackage; + } + + @Override + public String getOverlayTarget() { + return overlayTarget; + } + + @Override + public String getOverlayTargetName() { + return overlayTargetName; + } + + @Override + public boolean isOverlayIsStatic() { + return overlayIsStatic; + } + + @Override + public int[] getSplitFlags() { + return splitFlags; + } + + @Deprecated + @Override + public String getApplicationInfoVolumeUuid() { + return applicationVolumeUuid; + } + + @Nullable + @Override + public List<String> getProtectedBroadcasts() { + return protectedBroadcasts; + } + + @Nullable + @Override + public Set<String> getUpgradeKeySets() { + return upgradeKeySets; + } + + @Nullable + @Override + public String[][] getUsesStaticLibrariesCertDigests() { + return usesStaticLibrariesCertDigests; + } + + @Override + public int getOverlayPriority() { + return overlayPriority; + } + + @Deprecated + @Override + public String getAppInfoPackageName() { + return packageName; + } + + @Override + public UUID getStorageUuid() { + return StorageManager.convert(applicationVolumeUuid); + } + + @Override + public int getUid() { + return uid; + } + + @Override + public boolean isStub() { + return isStub; + } + + @Deprecated + @Override + public String getAppInfoCodePath() { + return applicationInfoCodePath; + } + + @Override + public boolean isSystem() { + return (flags & ApplicationInfo.FLAG_SYSTEM) != 0; + } + + @Override + public boolean isMatch(int flags) { + if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) { + return isSystem(); + } + return true; + } + + @Override + public boolean isVisibleToInstantApps() { + return visibleToInstantApps; + } + + @Override + public PackageImpl setLastPackageUsageTimeInMills(int reason, long time) { + lastPackageUsageTimeInMills[reason] = time; + return this; + } + + @Override + public List<SharedLibraryInfo> getUsesLibraryInfos() { + return usesLibraryInfos; + } + + @NonNull + @Override + public List<String> getAllCodePaths() { + return makeListAllCodePaths(); + } + + @Nullable + @Override + public String[] getUsesLibraryFiles() { + return usesLibraryFiles; + } + + @Override + public PackageImpl setUsesLibraryInfos( + @Nullable List<SharedLibraryInfo> usesLibraryInfos) { + this.usesLibraryInfos = usesLibraryInfos; + return this; + } + + @Override + public PackageImpl setUsesLibraryFiles(@Nullable String[] usesLibraryFiles) { + this.usesLibraryFiles = usesLibraryFiles; + return this; + } + + @Override + public PackageImpl setUid(int uid) { + this.uid = uid; + return this; + } + + @Override + public List<String> getAdoptPermissions() { + return adoptPermissions; + } + + @Override + public ApplicationInfo toAppInfo() { + updateFlags(); + + ApplicationInfo applicationInfo = new ApplicationInfo(); + applicationInfo.packageName = packageName; + applicationInfo.flags = flags; + applicationInfo.privateFlags = privateFlags; + applicationInfo.sharedLibraryFiles = usesLibraryFiles; + applicationInfo.sharedLibraryInfos = usesLibraryInfos; + + applicationInfo.appComponentFactory = appComponentFactory; + applicationInfo.backupAgentName = backupAgentName; + applicationInfo.banner = banner; + applicationInfo.category = category; + applicationInfo.classLoaderName = classLoaderName; + applicationInfo.className = className; + applicationInfo.compatibleWidthLimitDp = compatibleWidthLimitDp; + applicationInfo.credentialProtectedDataDir = credentialProtectedDataDir; + applicationInfo.dataDir = dataDir; + applicationInfo.descriptionRes = descriptionRes; + applicationInfo.deviceProtectedDataDir = deviceProtectedDataDir; + applicationInfo.enabled = enabled; + applicationInfo.fullBackupContent = fullBackupContent; + applicationInfo.icon = icon; + applicationInfo.iconRes = iconRes; + applicationInfo.installLocation = installLocation; + applicationInfo.labelRes = labelRes; + applicationInfo.largestWidthLimitDp = largestWidthLimitDp; + applicationInfo.logo = logo; + applicationInfo.manageSpaceActivityName = manageSpaceActivityName; + applicationInfo.maxAspectRatio = maxAspectRatio; + applicationInfo.minAspectRatio = minAspectRatio; + applicationInfo.minSdkVersion = minSdkVersion; + applicationInfo.name = name; + applicationInfo.nativeLibraryDir = nativeLibraryDir; + applicationInfo.nativeLibraryRootDir = nativeLibraryRootDir; + applicationInfo.nativeLibraryRootRequiresIsa = nativeLibraryRootRequiresIsa; + applicationInfo.networkSecurityConfigRes = networkSecurityConfigRes; + applicationInfo.nonLocalizedLabel = nonLocalizedLabel; + applicationInfo.permission = permission; + applicationInfo.primaryCpuAbi = primaryCpuAbi; + applicationInfo.processName = processName; + applicationInfo.requiresSmallestWidthDp = requiresSmallestWidthDp; + applicationInfo.roundIconRes = roundIconRes; + applicationInfo.secondaryCpuAbi = secondaryCpuAbi; + applicationInfo.secondaryNativeLibraryDir = secondaryNativeLibraryDir; + applicationInfo.seInfo = seInfo; + applicationInfo.seInfoUser = seInfoUser; + applicationInfo.splitClassLoaderNames = splitClassLoaderNames; + applicationInfo.splitDependencies = splitDependencies; + applicationInfo.splitNames = splitNames; + applicationInfo.storageUuid = StorageManager.convert(applicationVolumeUuid); + applicationInfo.targetSandboxVersion = targetSandboxVersion; + applicationInfo.targetSdkVersion = targetSdkVersion; + applicationInfo.taskAffinity = taskAffinity; + applicationInfo.theme = theme; + applicationInfo.uid = uid; + applicationInfo.uiOptions = uiOptions; + applicationInfo.volumeUuid = applicationVolumeUuid; + applicationInfo.zygotePreloadName = zygotePreloadName; + + applicationInfo.setBaseCodePath(baseCodePath); + applicationInfo.setBaseResourcePath(applicationInfoBaseResourcePath); + applicationInfo.setCodePath(applicationInfoCodePath); + applicationInfo.setResourcePath(applicationInfoResourcePath); + applicationInfo.setSplitCodePaths(splitCodePaths); + applicationInfo.setSplitResourcePaths(applicationInfoSplitResourcePaths); + + return applicationInfo; + } + + @Override + public PackageImpl setVersionCode(int versionCode) { + this.versionCode = versionCode; + return this; + } + + @Override + public PackageImpl setHiddenUntilInstalled(boolean hidden) { + this.hiddenUntilInstalled = hidden; + return this; + } + + @Override + public String getSeInfo() { + return seInfo; + } + + @Deprecated + @Override + public String getAppInfoResourcePath() { + return applicationInfoResourcePath; + } + + @Override + public boolean isForwardLocked() { + // TODO(b/135203078): Unused? Move to debug flag? + return false; + } + + @Override + public byte[] getRestrictUpdateHash() { + return restrictUpdateHash; + } + + @Override + public boolean hasComponentClassName(String className) { + if (activities != null) { + for (ParsedActivity parsedActivity : activities) { + if (Objects.equals(className, parsedActivity.className)) { + return true; + } + } + } + + if (receivers != null) { + for (ParsedActivity receiver : receivers) { + if (Objects.equals(className, receiver.className)) { + return true; + } + } + } + + if (providers != null) { + for (ParsedProvider provider : providers) { + if (Objects.equals(className, provider.className)) { + return true; + } + } + } + + if (services != null) { + for (ParsedService service : services) { + if (Objects.equals(className, service.className)) { + return true; + } + } + } + + if (instrumentations != null) { + for (ParsedInstrumentation instrumentation : instrumentations) { + if (Objects.equals(className, instrumentation.className)) { + return true; + } + } + } + + return false; + } + + @Override + public boolean isDefaultToDeviceProtectedStorage() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) + != 0; + } + + @Override + public boolean isInternal() { + return (flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0; + } + + @Override + public int getBaseRevisionCode() { + return baseRevisionCode; + } + + @Override + public int[] getSplitRevisionCodes() { + return splitRevisionCodes; + } + + @Override + public boolean canHaveOatDir() { + // The following app types CANNOT have oat directory + // - non-updated system apps + return !isSystem() || isUpdatedSystemApp(); + } + + @Override + public long getLatestPackageUseTimeInMills() { + long latestUse = 0L; + for (long use : lastPackageUsageTimeInMills) { + latestUse = Math.max(latestUse, use); + } + return latestUse; + } + + @Override + public long getLatestForegroundPackageUseTimeInMills() { + int[] foregroundReasons = { + PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY, + PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE + }; + + long latestUse = 0L; + for (int reason : foregroundReasons) { + latestUse = Math.max(latestUse, lastPackageUsageTimeInMills[reason]); + } + return latestUse; + } + + @Override + public boolean isCoreApp() { + return coreApp; + } + + @Override + public String getVersionName() { + return versionName; + } + + @Override + public PackageImpl setVersionCodeMajor(int versionCodeMajor) { + this.versionCodeMajor = versionCodeMajor; + return this; + } + + @Override + public long[] getLastPackageUsageTimeInMills() { + return lastPackageUsageTimeInMills; + } + + @Override + public String getDataDir() { + return dataDir; + } + + @Override + public boolean isExternal() { + return (flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0; + } + + @Override + public List<String> getImplicitPermissions() { + return implicitPermissions == null ? Collections.emptyList() : implicitPermissions; + } + + /** + * TODO(b/135203078): Remove, ensure b/140256621 is fixed or irrelevant + * TODO(b/140256621): Remove after fixing instant app check + * @deprecated This method always returns false because there's no paired set method + */ + @Deprecated + @Override + public boolean isInstantApp() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0; + } + + @Override + public boolean hasRequestedLegacyExternalStorage() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE) != 0; + } + + @Override + public boolean isVendor() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0; + } + + @Override + public boolean isProduct() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0; + } + + @Override + public boolean isOem() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0; + } + + @Override + public boolean isEncryptionAware() { + boolean isPartiallyDirectBootAware = + (privateFlags & ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE) != 0; + return isDirectBootAware() || isPartiallyDirectBootAware; + } + + @Override + public boolean isEmbeddedDexUsed() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_USE_EMBEDDED_DEX) != 0; + } + + @Deprecated + @Override + public String getAppInfoProcessName() { + return processName; + } + + @Override + public List<String> getAllCodePathsExcludingResourceOnly() { + ArrayList<String> paths = new ArrayList<>(); + if ((flags & ApplicationInfo.FLAG_HAS_CODE) != 0) { + paths.add(baseCodePath); + } + if (!ArrayUtils.isEmpty(splitCodePaths)) { + for (int i = 0; i < splitCodePaths.length; i++) { + if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) { + paths.add(splitCodePaths[i]); + } + } + } + return paths; + } + + @Deprecated + @Override + public String getAppInfoName() { + return name; + } + + private boolean isSignedWithPlatformKey() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY) != 0; + } + + private boolean usesNonSdkApi() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API) != 0; + } + + private boolean isPackageWhitelistedForHiddenApis() { + return SystemConfig.getInstance().getHiddenApiWhitelistedApps().contains(packageName); + } + + private boolean isAllowedToUseHiddenApis() { + if (isSignedWithPlatformKey()) { + return true; + } else if (isSystemApp() || isUpdatedSystemApp()) { + return usesNonSdkApi() || isPackageWhitelistedForHiddenApis(); + } else { + return false; + } + } + + @Override + public int getHiddenApiEnforcementPolicy() { + if (isAllowedToUseHiddenApis()) { + return ApplicationInfo.HIDDEN_API_ENFORCEMENT_DISABLED; + } + + // TODO(b/135203078): Handle maybeUpdateHiddenApiEnforcementPolicy. Right now it's done + // entirely through ApplicationInfo and shouldn't touch this specific class, but that + // may not always hold true. +// if (mHiddenApiPolicy != ApplicationInfo.HIDDEN_API_ENFORCEMENT_DEFAULT) { +// return mHiddenApiPolicy; +// } + return ApplicationInfo.HIDDEN_API_ENFORCEMENT_ENABLED; + } + + @Nullable + @Override + public SparseArray<int[]> getSplitDependencies() { + return splitDependencies; + } + + @Override + public boolean requestsIsolatedSplitLoading() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING) != 0; + } + + @Deprecated + @Override + public String getAppInfoClassLoaderName() { + return classLoaderName; + } + + @Override + public String getClassLoaderName() { + return classLoaderName; + } + + @Override + public String[] getSplitClassLoaderNames() { + return splitClassLoaderNames; + } + + @Override + public String getOverlayCategory() { + return overlayCategory; + } + + @Override + public boolean isProfileableByShell() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL) != 0; + } + + @Nullable + @Override + public List<ParsedActivityIntentInfo> getPreferredActivityFilters() { + return preferredActivityFilters; + } + + @Override + public boolean isHiddenUntilInstalled() { + return hiddenUntilInstalled; + } + + @Override + public int getMinSdkVersion() { + return minSdkVersion; + } + + @Override + public String getRestrictedAccountType() { + return restrictedAccountType; + } + + @Override + public String getRequiredAccountType() { + return requiredAccountType; + } + + @Override + public int getInstallLocation() { + return installLocation; + } + + @Override + public List<ParsedActivity> getReceivers() { + return receivers; + } + + @Override + public List<ParsedService> getServices() { + return services; + } + + @Override + public List<ParsedProvider> getProviders() { + return providers; + } + + @Override + public int getSharedUserLabel() { + return sharedUserLabel; + } + + @Override + public int getVersionCodeMajor() { + return versionCodeMajor; + } + + @Override + public boolean isRequiredForAllUsers() { + return requiredForAllUsers; + } + + @Override + public int getCompileSdkVersion() { + return compileSdkVersion; + } + + @Override + public String getCompileSdkVersionCodeName() { + return compileSdkVersionCodename; + } + + @Nullable + @Override + public List<ConfigurationInfo> getConfigPreferences() { + return configPreferences; + } + + @Nullable + @Override + public List<FeatureInfo> getReqFeatures() { + return reqFeatures; + } + + @Override + public List<FeatureGroupInfo> getFeatureGroups() { + return featureGroups; + } + + @Override + public String getDeviceProtectedDataDir() { + return deviceProtectedDataDir; + } + + @Override + public String getCredentialProtectedDataDir() { + return credentialProtectedDataDir; + } + + @Override + public String getSeInfoUser() { + return seInfoUser; + } + + @Override + public String getClassName() { + return className; + } + + @Override + public int getTheme() { + return theme; + } + + @Override + public int getRequiresSmallestWidthDp() { + return requiresSmallestWidthDp; + } + + @Override + public int getCompatibleWidthLimitDp() { + return compatibleWidthLimitDp; + } + + @Override + public int getLargestWidthLimitDp() { + return largestWidthLimitDp; + } + + @Override + public String getScanSourceDir() { + return applicationInfoCodePath; + } + + @Override + public String getScanPublicSourceDir() { + return applicationInfoResourcePath; + } + + @Override + public String getPublicSourceDir() { + return applicationInfoBaseResourcePath; + } + + @Override + public String[] getSplitPublicSourceDirs() { + return applicationInfoSplitResourcePaths; + } + + @Override + public String getSecondaryNativeLibraryDir() { + return secondaryNativeLibraryDir; + } + + @Override + public boolean isEnabled() { + return enabled; + } + + @Override + public String getManageSpaceActivityName() { + return manageSpaceActivityName; + } + + @Override + public int getDescriptionRes() { + return descriptionRes; + } + + @Override + public String getBackupAgentName() { + return backupAgentName; + } + + @Override + public int getFullBackupContent() { + return fullBackupContent; + } + + @Override + public int getNetworkSecurityConfigRes() { + return networkSecurityConfigRes; + } + + @Override + public int getCategory() { + return category; + } + + @Override + public int getTargetSandboxVersion() { + return targetSandboxVersion; + } + + @Override + public String getAppComponentFactory() { + return appComponentFactory; + } + + @Override + public int getIconRes() { + return iconRes; + } + + @Override + public int getRoundIconRes() { + return roundIconRes; + } + + @Override + public String getZygotePreloadName() { + return zygotePreloadName; + } + + @Override + public int getLabelRes() { + return labelRes; + } + + @Override + public CharSequence getNonLocalizedLabel() { + return nonLocalizedLabel; + } + + @Override + public int getIcon() { + return icon; + } + + @Override + public int getBanner() { + return banner; + } + + @Override + public int getLogo() { + return logo; + } + + @Override + public Bundle getMetaData() { + return appMetaData; + } + + @Override + @Nullable + public List<Intent> getQueriesIntents() { + return queriesIntents; + } + + @Override + @Nullable + public List<String> getQueriesPackages() { + return queriesPackages; + } + + private static void internStringArrayList(List<String> list) { + if (list != null) { + final int N = list.size(); + for (int i = 0; i < N; ++i) { + list.set(i, list.get(i).intern()); + } + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(this.supportsSmallScreens); + dest.writeInt(this.supportsNormalScreens); + dest.writeInt(this.supportsLargeScreens); + dest.writeInt(this.supportsXLargeScreens); + dest.writeInt(this.resizeable); + dest.writeInt(this.anyDensity); + dest.writeLongArray(this.lastPackageUsageTimeInMills); + dest.writeInt(this.versionCode); + dest.writeInt(this.versionCodeMajor); + dest.writeInt(this.baseRevisionCode); + dest.writeString(this.versionName); + dest.writeBoolean(this.coreApp); + dest.writeInt(this.compileSdkVersion); + dest.writeString(this.compileSdkVersionCodename); + dest.writeString(this.packageName); + dest.writeString(this.realPackage); + dest.writeString(this.manifestPackageName); + dest.writeString(this.baseCodePath); + dest.writeBoolean(this.requiredForAllUsers); + dest.writeString(this.restrictedAccountType); + dest.writeString(this.requiredAccountType); + dest.writeBoolean(this.baseHardwareAccelerated); + dest.writeString(this.overlayTarget); + dest.writeString(this.overlayTargetName); + dest.writeString(this.overlayCategory); + dest.writeInt(this.overlayPriority); + dest.writeBoolean(this.overlayIsStatic); + dest.writeString(this.staticSharedLibName); + dest.writeLong(this.staticSharedLibVersion); + dest.writeStringList(this.libraryNames); + dest.writeStringList(this.usesLibraries); + dest.writeStringList(this.usesOptionalLibraries); + dest.writeStringList(this.usesStaticLibraries); + dest.writeLongArray(this.usesStaticLibrariesVersions); + + if (this.usesStaticLibrariesCertDigests == null) { + dest.writeInt(-1); + } else { + dest.writeInt(this.usesStaticLibrariesCertDigests.length); + for (int index = 0; index < this.usesStaticLibrariesCertDigests.length; index++) { + dest.writeStringArray(this.usesStaticLibrariesCertDigests[index]); + } + } + + dest.writeString(this.sharedUserId); + dest.writeInt(this.sharedUserLabel); + dest.writeTypedList(this.configPreferences); + dest.writeTypedList(this.reqFeatures); + dest.writeTypedList(this.featureGroups); + dest.writeByteArray(this.restrictUpdateHash); + dest.writeStringList(this.originalPackages); + dest.writeStringList(this.adoptPermissions); + dest.writeStringList(this.requestedPermissions); + dest.writeStringList(this.implicitPermissions); + dest.writeArraySet(this.upgradeKeySets); + dest.writeMap(this.keySetMapping); + dest.writeStringList(this.protectedBroadcasts); + dest.writeTypedList(this.activities); + dest.writeTypedList(this.receivers); + dest.writeTypedList(this.services); + dest.writeTypedList(this.providers); + dest.writeTypedList(this.permissions); + dest.writeTypedList(this.permissionGroups); + dest.writeTypedList(this.instrumentations); + ParsedIntentInfo.writeIntentsList(this.preferredActivityFilters, dest, flags); + dest.writeBundle(this.appMetaData); + dest.writeString(this.volumeUuid); + dest.writeString(this.applicationVolumeUuid); + dest.writeParcelable(this.signingDetails, flags); + dest.writeString(this.codePath); + dest.writeBoolean(this.use32BitAbi); + dest.writeBoolean(this.visibleToInstantApps); + dest.writeString(this.cpuAbiOverride); + dest.writeBoolean(this.isStub); + dest.writeInt(this.preferredOrder); + dest.writeBoolean(this.forceQueryable); + dest.writeParcelableList(this.queriesIntents, flags); + dest.writeStringList(this.queriesPackages); + dest.writeString(this.applicationInfoBaseResourcePath); + dest.writeString(this.applicationInfoCodePath); + dest.writeString(this.applicationInfoResourcePath); + dest.writeStringArray(this.applicationInfoSplitResourcePaths); + dest.writeString(this.appComponentFactory); + dest.writeString(this.backupAgentName); + dest.writeInt(this.banner); + dest.writeInt(this.category); + dest.writeString(this.classLoaderName); + dest.writeString(this.className); + dest.writeInt(this.compatibleWidthLimitDp); + dest.writeString(this.credentialProtectedDataDir); + dest.writeString(this.dataDir); + dest.writeInt(this.descriptionRes); + dest.writeString(this.deviceProtectedDataDir); + dest.writeBoolean(this.enabled); + dest.writeInt(this.flags); + dest.writeInt(this.fullBackupContent); + dest.writeBoolean(this.hiddenUntilInstalled); + dest.writeInt(this.icon); + dest.writeInt(this.iconRes); + dest.writeInt(this.installLocation); + dest.writeInt(this.labelRes); + dest.writeInt(this.largestWidthLimitDp); + dest.writeInt(this.logo); + dest.writeString(this.manageSpaceActivityName); + dest.writeFloat(this.maxAspectRatio); + dest.writeFloat(this.minAspectRatio); + dest.writeInt(this.minSdkVersion); + dest.writeString(this.name); + dest.writeString(this.nativeLibraryDir); + dest.writeString(this.nativeLibraryRootDir); + dest.writeBoolean(this.nativeLibraryRootRequiresIsa); + dest.writeInt(this.networkSecurityConfigRes); + dest.writeCharSequence(this.nonLocalizedLabel); + dest.writeString(this.permission); + dest.writeString(this.primaryCpuAbi); + dest.writeInt(this.privateFlags); + dest.writeString(this.processName); + dest.writeInt(this.requiresSmallestWidthDp); + dest.writeInt(this.roundIconRes); + dest.writeString(this.secondaryCpuAbi); + dest.writeString(this.secondaryNativeLibraryDir); + dest.writeString(this.seInfo); + dest.writeString(this.seInfoUser); + dest.writeInt(this.targetSandboxVersion); + dest.writeInt(this.targetSdkVersion); + dest.writeString(this.taskAffinity); + dest.writeInt(this.theme); + dest.writeInt(this.uid); + dest.writeInt(this.uiOptions); + dest.writeStringArray(this.usesLibraryFiles); + dest.writeTypedList(this.usesLibraryInfos); + dest.writeString(this.zygotePreloadName); + dest.writeStringArray(this.splitClassLoaderNames); + dest.writeStringArray(this.splitCodePaths); + dest.writeSparseArray(this.splitDependencies); + dest.writeIntArray(this.splitFlags); + dest.writeStringArray(this.splitNames); + dest.writeIntArray(this.splitRevisionCodes); + } + + public PackageImpl(Parcel in) { + // We use the boot classloader for all classes that we load. + final ClassLoader boot = Object.class.getClassLoader(); + this.supportsSmallScreens = in.readInt(); + this.supportsNormalScreens = in.readInt(); + this.supportsLargeScreens = in.readInt(); + this.supportsXLargeScreens = in.readInt(); + this.resizeable = in.readInt(); + this.anyDensity = in.readInt(); + this.lastPackageUsageTimeInMills = in.createLongArray(); + this.versionCode = in.readInt(); + this.versionCodeMajor = in.readInt(); + this.baseRevisionCode = in.readInt(); + this.versionName = TextUtils.safeIntern(in.readString()); + this.coreApp = in.readBoolean(); + this.compileSdkVersion = in.readInt(); + this.compileSdkVersionCodename = TextUtils.safeIntern(in.readString()); + this.packageName = TextUtils.safeIntern(in.readString()); + this.realPackage = in.readString(); + this.manifestPackageName = in.readString(); + this.baseCodePath = in.readString(); + this.requiredForAllUsers = in.readBoolean(); + this.restrictedAccountType = in.readString(); + this.requiredAccountType = in.readString(); + this.baseHardwareAccelerated = in.readBoolean(); + this.overlayTarget = in.readString(); + this.overlayTargetName = in.readString(); + this.overlayCategory = in.readString(); + this.overlayPriority = in.readInt(); + this.overlayIsStatic = in.readBoolean(); + this.staticSharedLibName = TextUtils.safeIntern(in.readString()); + this.staticSharedLibVersion = in.readLong(); + this.libraryNames = in.createStringArrayList(); + internStringArrayList(this.libraryNames); + this.usesLibraries = in.createStringArrayList(); + internStringArrayList(this.usesLibraries); + this.usesOptionalLibraries = in.createStringArrayList(); + internStringArrayList(this.usesOptionalLibraries); + this.usesStaticLibraries = in.createStringArrayList(); + internStringArrayList(usesStaticLibraries); + this.usesStaticLibrariesVersions = in.createLongArray(); + + int digestsSize = in.readInt(); + if (digestsSize >= 0) { + this.usesStaticLibrariesCertDigests = new String[digestsSize][]; + for (int index = 0; index < digestsSize; index++) { + this.usesStaticLibrariesCertDigests[index] = in.readStringArray(); + } + } + + this.sharedUserId = TextUtils.safeIntern(in.readString()); + this.sharedUserLabel = in.readInt(); + this.configPreferences = in.createTypedArrayList(ConfigurationInfo.CREATOR); + this.reqFeatures = in.createTypedArrayList(FeatureInfo.CREATOR); + this.featureGroups = in.createTypedArrayList(FeatureGroupInfo.CREATOR); + this.restrictUpdateHash = in.createByteArray(); + this.originalPackages = in.createStringArrayList(); + this.adoptPermissions = in.createStringArrayList(); + this.requestedPermissions = in.createStringArrayList(); + internStringArrayList(this.requestedPermissions); + this.implicitPermissions = in.createStringArrayList(); + internStringArrayList(this.implicitPermissions); + this.upgradeKeySets = (ArraySet<String>) in.readArraySet(boot); + this.keySetMapping = in.readHashMap(boot); + this.protectedBroadcasts = in.createStringArrayList(); + internStringArrayList(this.protectedBroadcasts); + this.activities = in.createTypedArrayList(ParsedActivity.CREATOR); + this.receivers = in.createTypedArrayList(ParsedActivity.CREATOR); + this.services = in.createTypedArrayList(ParsedService.CREATOR); + this.providers = in.createTypedArrayList(ParsedProvider.CREATOR); + this.permissions = in.createTypedArrayList(ParsedPermission.CREATOR); + this.permissionGroups = in.createTypedArrayList(ParsedPermissionGroup.CREATOR); + this.instrumentations = in.createTypedArrayList(ParsedInstrumentation.CREATOR); + this.preferredActivityFilters = ParsedIntentInfo.createIntentsList(in); + this.appMetaData = in.readBundle(boot); + this.volumeUuid = in.readString(); + this.applicationVolumeUuid = in.readString(); + this.signingDetails = in.readParcelable(boot); + this.codePath = in.readString(); + this.use32BitAbi = in.readBoolean(); + this.visibleToInstantApps = in.readBoolean(); + this.cpuAbiOverride = in.readString(); + this.isStub = in.readBoolean(); + this.preferredOrder = in.readInt(); + this.forceQueryable = in.readBoolean(); + this.queriesIntents = in.createTypedArrayList(Intent.CREATOR); + this.queriesPackages = in.createStringArrayList(); + internStringArrayList(this.queriesPackages); + this.applicationInfoBaseResourcePath = in.readString(); + this.applicationInfoCodePath = in.readString(); + this.applicationInfoResourcePath = in.readString(); + this.applicationInfoSplitResourcePaths = in.createStringArray(); + this.appComponentFactory = in.readString(); + this.backupAgentName = in.readString(); + this.banner = in.readInt(); + this.category = in.readInt(); + this.classLoaderName = in.readString(); + this.className = in.readString(); + this.compatibleWidthLimitDp = in.readInt(); + this.credentialProtectedDataDir = in.readString(); + this.dataDir = in.readString(); + this.descriptionRes = in.readInt(); + this.deviceProtectedDataDir = in.readString(); + this.enabled = in.readBoolean(); + this.flags = in.readInt(); + this.fullBackupContent = in.readInt(); + this.hiddenUntilInstalled = in.readBoolean(); + this.icon = in.readInt(); + this.iconRes = in.readInt(); + this.installLocation = in.readInt(); + this.labelRes = in.readInt(); + this.largestWidthLimitDp = in.readInt(); + this.logo = in.readInt(); + this.manageSpaceActivityName = in.readString(); + this.maxAspectRatio = in.readFloat(); + this.minAspectRatio = in.readFloat(); + this.minSdkVersion = in.readInt(); + this.name = in.readString(); + this.nativeLibraryDir = in.readString(); + this.nativeLibraryRootDir = in.readString(); + this.nativeLibraryRootRequiresIsa = in.readBoolean(); + this.networkSecurityConfigRes = in.readInt(); + this.nonLocalizedLabel = in.readCharSequence(); + this.permission = TextUtils.safeIntern(in.readString()); + this.primaryCpuAbi = in.readString(); + this.privateFlags = in.readInt(); + this.processName = in.readString(); + this.requiresSmallestWidthDp = in.readInt(); + this.roundIconRes = in.readInt(); + this.secondaryCpuAbi = in.readString(); + this.secondaryNativeLibraryDir = in.readString(); + this.seInfo = in.readString(); + this.seInfoUser = in.readString(); + this.targetSandboxVersion = in.readInt(); + this.targetSdkVersion = in.readInt(); + this.taskAffinity = in.readString(); + this.theme = in.readInt(); + this.uid = in.readInt(); + this.uiOptions = in.readInt(); + this.usesLibraryFiles = in.createStringArray(); + this.usesLibraryInfos = in.createTypedArrayList(SharedLibraryInfo.CREATOR); + this.zygotePreloadName = in.readString(); + this.splitClassLoaderNames = in.createStringArray(); + this.splitCodePaths = in.createStringArray(); + this.splitDependencies = in.readSparseArray(boot); + this.splitFlags = in.createIntArray(); + this.splitNames = in.createStringArray(); + this.splitRevisionCodes = in.createIntArray(); + } + + public static final Creator<PackageImpl> CREATOR = new Creator<PackageImpl>() { + @Override + public PackageImpl createFromParcel(Parcel source) { + return new PackageImpl(source); + } + + @Override + public PackageImpl[] newArray(int size) { + return new PackageImpl[size]; + } + }; +} diff --git a/core/java/android/content/pm/parsing/PackageInfoUtils.java b/core/java/android/content/pm/parsing/PackageInfoUtils.java new file mode 100644 index 000000000000..7b329ebc5b83 --- /dev/null +++ b/core/java/android/content/pm/parsing/PackageInfoUtils.java @@ -0,0 +1,732 @@ +/* + * 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(); + } + +} diff --git a/core/java/android/content/pm/parsing/ParsedPackage.java b/core/java/android/content/pm/parsing/ParsedPackage.java new file mode 100644 index 000000000000..05cf586522f2 --- /dev/null +++ b/core/java/android/content/pm/parsing/ParsedPackage.java @@ -0,0 +1,155 @@ +/* + * 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 android.content.pm.PackageParser; + +/** + * Methods used for mutation after direct package parsing, mostly done inside + * {@link com.android.server.pm.PackageManagerService}. + * + * Java disallows defining this as an inner interface, so this must be a separate file. + * + * @hide + */ +public interface ParsedPackage extends AndroidPackage { + + AndroidPackage hideAsFinal(); + + ParsedPackage addUsesLibrary(int index, String libraryName); + + ParsedPackage addUsesOptionalLibrary(int index, String libraryName); + + ParsedPackage capPermissionPriorities(); + + ParsedPackage clearAdoptPermissions(); + + ParsedPackage clearOriginalPackages(); + + ParsedPackage clearProtectedBroadcasts(); + + /** + * TODO(b/135203078): Use non-AppInfo method + * @deprecated use {@link #setCodePath(String)} + */ + @Deprecated + ParsedPackage setApplicationInfoCodePath(String applicationInfoCodePath); + + /** + * TODO(b/135203078): Use non-AppInfo method + * @deprecated use {@link #setCodePath(String)} + */ + @Deprecated + ParsedPackage setApplicationInfoResourcePath(String applicationInfoResourcePath); + + ParsedPackage setBaseCodePath(String baseCodePath); + + ParsedPackage setCodePath(String codePath); + + ParsedPackage setCpuAbiOverride(String cpuAbiOverride); + + ParsedPackage setNativeLibraryDir(String nativeLibraryDir); + + ParsedPackage setNativeLibraryRootDir(String nativeLibraryRootDir); + + ParsedPackage setPackageName(String packageName); + + ParsedPackage setPrimaryCpuAbi(String primaryCpuAbi); + + ParsedPackage setProcessName(String processName); + + ParsedPackage setRealPackage(String realPackage); + + ParsedPackage setSecondaryCpuAbi(String secondaryCpuAbi); + + ParsedPackage setSigningDetails(PackageParser.SigningDetails signingDetails); + + ParsedPackage setSplitCodePaths(String[] splitCodePaths); + + ParsedPackage initForUser(int userId); + + ParsedPackage setNativeLibraryRootRequiresIsa(boolean nativeLibraryRootRequiresIsa); + + ParsedPackage setAllComponentsDirectBootAware(boolean allComponentsDirectBootAware); + + ParsedPackage setFactoryTest(boolean factoryTest); + + ParsedPackage markNotActivitiesAsNotExportedIfSingleUser(); + + ParsedPackage setOdm(boolean odm); + + ParsedPackage setOem(boolean oem); + + ParsedPackage setPrivileged(boolean privileged); + + ParsedPackage setProduct(boolean product); + + ParsedPackage setSignedWithPlatformKey(boolean signedWithPlatformKey); + + ParsedPackage setSystem(boolean system); + + ParsedPackage setSystemExt(boolean systemExt); + + ParsedPackage setUpdatedSystemApp(boolean updatedSystemApp); + + ParsedPackage setVendor(boolean vendor); + + ParsedPackage removePermission(int index); + + ParsedPackage removeUsesLibrary(String libraryName); + + ParsedPackage removeUsesOptionalLibrary(String libraryName); + + ParsedPackage setApplicationInfoBaseResourcePath(String applicationInfoBaseResourcePath); + + ParsedPackage setApplicationInfoSplitResourcePaths( + String[] applicationInfoSplitResourcePaths); + + ParsedPackage setApplicationVolumeUuid(String applicationVolumeUuid); + + ParsedPackage setCoreApp(boolean coreApp); + + ParsedPackage setIsStub(boolean isStub); + + // TODO(b/135203078): Remove entirely + ParsedPackage setPackageSettingCallback(PackageSettingCallback packageSettingCallback); + + ParsedPackage setRestrictUpdateHash(byte[] restrictUpdateHash); + + ParsedPackage setSeInfo(String seInfo); + + ParsedPackage setSeInfoUser(String seInfoUser); + + ParsedPackage setSecondaryNativeLibraryDir(String secondaryNativeLibraryDir); + + ParsedPackage setUid(int uid); + + ParsedPackage setVersionCode(int versionCode); + + ParsedPackage setVersionCodeMajor(int versionCodeMajor); + + // TODO(b/135203078): Move logic earlier in parse chain so nothing needs to be reverted + ParsedPackage setDefaultToDeviceProtectedStorage(boolean defaultToDeviceProtectedStorage); + + ParsedPackage setDirectBootAware(boolean directBootAware); + + ParsedPackage setPersistent(boolean persistent); + + interface PackageSettingCallback { + default void setAndroidPackage(AndroidPackage pkg){} + } +} diff --git a/core/java/android/content/pm/parsing/ParsingPackage.java b/core/java/android/content/pm/parsing/ParsingPackage.java new file mode 100644 index 000000000000..43c1f6e335b0 --- /dev/null +++ b/core/java/android/content/pm/parsing/ParsingPackage.java @@ -0,0 +1,327 @@ +/* + * 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 android.annotation.Nullable; +import android.content.Intent; +import android.content.pm.ConfigurationInfo; +import android.content.pm.FeatureGroupInfo; +import android.content.pm.FeatureInfo; +import android.content.pm.PackageParser; +import android.content.pm.parsing.ComponentParseUtils.ParsedActivity; +import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo; +import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation; +import android.content.pm.parsing.ComponentParseUtils.ParsedPermission; +import android.content.pm.parsing.ComponentParseUtils.ParsedPermissionGroup; +import android.content.pm.parsing.ComponentParseUtils.ParsedProvider; +import android.content.pm.parsing.ComponentParseUtils.ParsedService; +import android.os.Bundle; +import android.util.ArraySet; +import android.util.SparseArray; + +import java.security.PublicKey; + +/** + * Methods used for mutation during direct package parsing. + * + * Java disallows defining this as an inner interface, so this must be a separate file. + * + * @hide + */ +public interface ParsingPackage extends AndroidPackage { + + ParsingPackage addActivity(ParsedActivity parsedActivity); + + ParsingPackage addAdoptPermission(String adoptPermission); + + ParsingPackage addConfigPreference(ConfigurationInfo configPreference); + + ParsingPackage addFeatureGroup(FeatureGroupInfo featureGroup); + + ParsingPackage addImplicitPermission(String permission); + + ParsingPackage addInstrumentation(ParsedInstrumentation instrumentation); + + ParsingPackage addKeySet(String keySetName, PublicKey publicKey); + + ParsingPackage addLibraryName(String libraryName); + + ParsingPackage addOriginalPackage(String originalPackage); + + ParsingPackage addPermission(ParsedPermission permission); + + ParsingPackage addPermissionGroup(ParsedPermissionGroup permissionGroup); + + ParsingPackage addPreferredActivityFilter(ParsedActivityIntentInfo activityIntentInfo); + + ParsingPackage addProtectedBroadcast(String protectedBroadcast); + + ParsingPackage addProvider(ParsedProvider parsedProvider); + + ParsingPackage addReceiver(ParsedActivity parsedReceiver); + + ParsingPackage addReqFeature(FeatureInfo reqFeature); + + ParsingPackage addRequestedPermission(String permission); + + ParsingPackage addService(ParsedService parsedService); + + ParsingPackage addUsesLibrary(String libraryName); + + ParsingPackage addUsesOptionalLibrary(String libraryName); + + ParsingPackage addUsesStaticLibrary(String libraryName); + + ParsingPackage addUsesStaticLibraryCertDigests(String[] certSha256Digests); + + ParsingPackage addUsesStaticLibraryVersion(long version); + + ParsingPackage addQueriesIntent(Intent intent); + + ParsingPackage addQueriesPackage(String packageName); + + ParsingPackage asSplit( + String[] splitNames, + String[] splitCodePaths, + int[] splitRevisionCodes, + @Nullable SparseArray<int[]> splitDependencies + ); + + ParsingPackage setAppMetaData(Bundle appMetaData); + + ParsingPackage setForceQueryable(boolean forceQueryable); + + ParsingPackage setMaxAspectRatio(float maxAspectRatio); + + ParsingPackage setMinAspectRatio(float minAspectRatio); + + ParsingPackage setName(String name); + + ParsingPackage setPermission(String permission); + + ParsingPackage setProcessName(String processName); + + ParsingPackage setSharedUserId(String sharedUserId); + + ParsingPackage setStaticSharedLibName(String staticSharedLibName); + + ParsingPackage setTaskAffinity(String taskAffinity); + + ParsingPackage setTargetSdkVersion(int targetSdkVersion); + + ParsingPackage setUiOptions(int uiOptions); + + ParsingPackage setBaseHardwareAccelerated(boolean baseHardwareAccelerated); + + ParsingPackage setActivitiesResizeModeResizeable(boolean resizeable); + + ParsingPackage setActivitiesResizeModeResizeableViaSdkVersion(boolean resizeableViaSdkVersion); + + ParsingPackage setAllowAudioPlaybackCapture(boolean allowAudioPlaybackCapture); + + ParsingPackage setAllowBackup(boolean allowBackup); + + ParsingPackage setAllowClearUserData(boolean allowClearUserData); + + ParsingPackage setAllowClearUserDataOnFailedRestore(boolean allowClearUserDataOnFailedRestore); + + ParsingPackage setAllowTaskReparenting(boolean allowTaskReparenting); + + ParsingPackage setIsOverlay(boolean isOverlay); + + ParsingPackage setBackupInForeground(boolean backupInForeground); + + ParsingPackage setCantSaveState(boolean cantSaveState); + + ParsingPackage setDebuggable(boolean debuggable); + + ParsingPackage setDefaultToDeviceProtectedStorage(boolean defaultToDeviceProtectedStorage); + + ParsingPackage setDirectBootAware(boolean directBootAware); + + ParsingPackage setExternalStorage(boolean externalStorage); + + ParsingPackage setExtractNativeLibs(boolean extractNativeLibs); + + ParsingPackage setFullBackupOnly(boolean fullBackupOnly); + + ParsingPackage setHasCode(boolean hasCode); + + ParsingPackage setHasFragileUserData(boolean hasFragileUserData); + + ParsingPackage setIsGame(boolean isGame); + + ParsingPackage setIsolatedSplitLoading(boolean isolatedSplitLoading); + + ParsingPackage setKillAfterRestore(boolean killAfterRestore); + + ParsingPackage setLargeHeap(boolean largeHeap); + + ParsingPackage setMultiArch(boolean multiArch); + + ParsingPackage setPartiallyDirectBootAware(boolean partiallyDirectBootAware); + + ParsingPackage setPersistent(boolean persistent); + + ParsingPackage setProfileableByShell(boolean profileableByShell); + + ParsingPackage setRequestLegacyExternalStorage(boolean requestLegacyExternalStorage); + + ParsingPackage setRestoreAnyVersion(boolean restoreAnyVersion); + + ParsingPackage setSplitHasCode(int splitIndex, boolean splitHasCode); + + ParsingPackage setStaticSharedLibrary(boolean staticSharedLibrary); + + ParsingPackage setSupportsRtl(boolean supportsRtl); + + ParsingPackage setTestOnly(boolean testOnly); + + ParsingPackage setUseEmbeddedDex(boolean useEmbeddedDex); + + ParsingPackage setUsesCleartextTraffic(boolean usesCleartextTraffic); + + ParsingPackage setUsesNonSdkApi(boolean usesNonSdkApi); + + ParsingPackage setVisibleToInstantApps(boolean visibleToInstantApps); + + ParsingPackage setVmSafeMode(boolean vmSafeMode); + + ParsingPackage removeUsesOptionalLibrary(String libraryName); + + ParsingPackage setAnyDensity(int anyDensity); + + ParsingPackage setAppComponentFactory(String appComponentFactory); + + ParsingPackage setApplicationVolumeUuid(String applicationVolumeUuid); + + ParsingPackage setBackupAgentName(String backupAgentName); + + ParsingPackage setBanner(int banner); + + ParsingPackage setCategory(int category); + + ParsingPackage setClassLoaderName(String classLoaderName); + + ParsingPackage setClassName(String className); + + ParsingPackage setCodePath(String codePath); + + ParsingPackage setCompatibleWidthLimitDp(int compatibleWidthLimitDp); + + ParsingPackage setDescriptionRes(int descriptionRes); + + ParsingPackage setEnabled(boolean enabled); + + ParsingPackage setFullBackupContent(int fullBackupContent); + + ParsingPackage setHasDomainUrls(boolean hasDomainUrls); + + ParsingPackage setIcon(int icon); + + ParsingPackage setIconRes(int iconRes); + + ParsingPackage setInstallLocation(int installLocation); + + ParsingPackage setLabelRes(int labelRes); + + ParsingPackage setLargestWidthLimitDp(int largestWidthLimitDp); + + ParsingPackage setLogo(int logo); + + ParsingPackage setManageSpaceActivityName(String manageSpaceActivityName); + + ParsingPackage setMinSdkVersion(int minSdkVersion); + + ParsingPackage setNetworkSecurityConfigRes(int networkSecurityConfigRes); + + ParsingPackage setNonLocalizedLabel(CharSequence nonLocalizedLabel); + + ParsingPackage setOverlayCategory(String overlayCategory); + + ParsingPackage setOverlayIsStatic(boolean overlayIsStatic); + + ParsingPackage setOverlayPriority(int overlayPriority); + + ParsingPackage setOverlayTarget(String overlayTarget); + + ParsingPackage setOverlayTargetName(String overlayTargetName); + + ParsingPackage setRealPackage(String realPackage); + + ParsingPackage setRequiredAccountType(String requiredAccountType); + + ParsingPackage setRequiredForAllUsers(boolean requiredForAllUsers); + + ParsingPackage setRequiresSmallestWidthDp(int requiresSmallestWidthDp); + + ParsingPackage setResizeable(int resizeable); + + ParsingPackage setRestrictUpdateHash(byte[] restrictUpdateHash); + + ParsingPackage setRestrictedAccountType(String restrictedAccountType); + + ParsingPackage setRoundIconRes(int roundIconRes); + + ParsingPackage setSharedUserLabel(int sharedUserLabel); + + ParsingPackage setSigningDetails(PackageParser.SigningDetails signingDetails); + + ParsingPackage setSplitClassLoaderName(int splitIndex, String classLoaderName); + + ParsingPackage setStaticSharedLibVersion(long staticSharedLibVersion); + + ParsingPackage setSupportsLargeScreens(int supportsLargeScreens); + + ParsingPackage setSupportsNormalScreens(int supportsNormalScreens); + + ParsingPackage setSupportsSmallScreens(int supportsSmallScreens); + + ParsingPackage setSupportsXLargeScreens(int supportsXLargeScreens); + + ParsingPackage setTargetSandboxVersion(int targetSandboxVersion); + + ParsingPackage setTheme(int theme); + + ParsingPackage setUpgradeKeySets(ArraySet<String> upgradeKeySets); + + ParsingPackage setUse32BitAbi(boolean use32BitAbi); + + ParsingPackage setVolumeUuid(String volumeUuid); + + ParsingPackage setZygotePreloadName(String zygotePreloadName); + + ParsingPackage sortActivities(); + + ParsingPackage sortReceivers(); + + ParsingPackage sortServices(); + + ParsedPackage hideAsParsed(); + + ParsingPackage setBaseRevisionCode(int baseRevisionCode); + + ParsingPackage setPreferredOrder(int preferredOrder); + + ParsingPackage setVersionName(String versionName); + + ParsingPackage setCompileSdkVersion(int compileSdkVersion); + + ParsingPackage setCompileSdkVersionCodename(String compileSdkVersionCodename); + + boolean usesCompatibilityMode(); +} diff --git a/core/java/android/content/pm/AndroidHidlUpdater.java b/core/java/android/content/pm/parsing/library/AndroidHidlUpdater.java index d0657e5eb8ec..81b4bc574197 100644 --- a/core/java/android/content/pm/AndroidHidlUpdater.java +++ b/core/java/android/content/pm/parsing/library/AndroidHidlUpdater.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * 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. @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.content.pm; +package android.content.pm.parsing.library; -import static android.content.pm.SharedLibraryNames.ANDROID_HIDL_BASE; -import static android.content.pm.SharedLibraryNames.ANDROID_HIDL_MANAGER; +import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_HIDL_BASE; +import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_HIDL_MANAGER; -import android.content.pm.PackageParser.Package; +import android.content.pm.parsing.ParsedPackage; import android.os.Build; import com.android.internal.annotations.VisibleForTesting; @@ -33,20 +33,18 @@ import com.android.internal.annotations.VisibleForTesting; public class AndroidHidlUpdater extends PackageSharedLibraryUpdater { @Override - public void updatePackage(Package pkg) { - ApplicationInfo info = pkg.applicationInfo; - + public void updatePackage(ParsedPackage parsedPackage) { // This was the default <= P and is maintained for backwards compatibility. - boolean isLegacy = info.targetSdkVersion <= Build.VERSION_CODES.P; + boolean isLegacy = parsedPackage.getTargetSdkVersion() <= Build.VERSION_CODES.P; // Only system apps use these libraries - boolean isSystem = info.isSystemApp() || info.isUpdatedSystemApp(); + boolean isSystem = parsedPackage.isSystemApp() || parsedPackage.isUpdatedSystemApp(); if (isLegacy && isSystem) { - prefixRequiredLibrary(pkg, ANDROID_HIDL_BASE); - prefixRequiredLibrary(pkg, ANDROID_HIDL_MANAGER); + prefixRequiredLibrary(parsedPackage, ANDROID_HIDL_BASE); + prefixRequiredLibrary(parsedPackage, ANDROID_HIDL_MANAGER); } else { - removeLibrary(pkg, ANDROID_HIDL_BASE); - removeLibrary(pkg, ANDROID_HIDL_MANAGER); + removeLibrary(parsedPackage, ANDROID_HIDL_BASE); + removeLibrary(parsedPackage, ANDROID_HIDL_MANAGER); } } } diff --git a/core/java/android/content/pm/AndroidTestBaseUpdater.java b/core/java/android/content/pm/parsing/library/AndroidTestBaseUpdater.java index 18d3ba33552e..fc02a86a6f5a 100644 --- a/core/java/android/content/pm/AndroidTestBaseUpdater.java +++ b/core/java/android/content/pm/parsing/library/AndroidTestBaseUpdater.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * 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. @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.content.pm; +package android.content.pm.parsing.library; -import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE; -import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER; +import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_BASE; +import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_RUNNER; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; @@ -72,7 +72,7 @@ public class AndroidTestBaseUpdater extends PackageSharedLibraryUpdater { } @Override - public void updatePackage(Package pkg) { + public void updatePackage(ParsedPackage parsedPackage) { // Packages targeted at <= Q expect the classes in the android.test.base library // to be accessible so this maintains backward compatibility by adding the // android.test.base library to those packages. @@ -82,7 +82,7 @@ public class AndroidTestBaseUpdater extends PackageSharedLibraryUpdater { // If a package already depends on android.test.runner then add a dependency on // android.test.base because android.test.runner depends on classes from the // android.test.base library. - prefixImplicitDependency(pkg, ANDROID_TEST_RUNNER, ANDROID_TEST_BASE); + prefixImplicitDependency(parsedPackage, ANDROID_TEST_RUNNER, ANDROID_TEST_BASE); } } } diff --git a/core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java b/core/java/android/content/pm/parsing/library/OrgApacheHttpLegacyUpdater.java index 707443b19679..613a06b636e9 100644 --- a/core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java +++ b/core/java/android/content/pm/parsing/library/OrgApacheHttpLegacyUpdater.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * 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. @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.content.pm; +package android.content.pm.parsing.library; -import static android.content.pm.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY; +import static android.content.pm.parsing.library.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY; -import android.content.pm.PackageParser.Package; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.ParsedPackage; import android.os.Build; import com.android.internal.annotations.VisibleForTesting; @@ -31,18 +32,17 @@ import com.android.internal.annotations.VisibleForTesting; @VisibleForTesting public class OrgApacheHttpLegacyUpdater extends PackageSharedLibraryUpdater { - private static boolean apkTargetsApiLevelLessThanOrEqualToOMR1(Package pkg) { - int targetSdkVersion = pkg.applicationInfo.targetSdkVersion; - return targetSdkVersion < Build.VERSION_CODES.P; + private static boolean apkTargetsApiLevelLessThanOrEqualToOMR1(AndroidPackage pkg) { + return pkg.getTargetSdkVersion() < Build.VERSION_CODES.P; } @Override - public void updatePackage(Package pkg) { + public void updatePackage(ParsedPackage parsedPackage) { // Packages targeted at <= O_MR1 expect the classes in the org.apache.http.legacy library // to be accessible so this maintains backward compatibility by adding the // org.apache.http.legacy library to those packages. - if (apkTargetsApiLevelLessThanOrEqualToOMR1(pkg)) { - prefixRequiredLibrary(pkg, ORG_APACHE_HTTP_LEGACY); + if (apkTargetsApiLevelLessThanOrEqualToOMR1(parsedPackage)) { + prefixRequiredLibrary(parsedPackage, ORG_APACHE_HTTP_LEGACY); } } } diff --git a/core/java/android/content/pm/PackageBackwardCompatibility.java b/core/java/android/content/pm/parsing/library/PackageBackwardCompatibility.java index 4331bd4ac4d4..1220fc497b04 100644 --- a/core/java/android/content/pm/PackageBackwardCompatibility.java +++ b/core/java/android/content/pm/parsing/library/PackageBackwardCompatibility.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * 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. @@ -14,14 +14,14 @@ * limitations under the License. */ -package android.content.pm; +package android.content.pm.parsing.library; -import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE; -import static android.content.pm.SharedLibraryNames.ANDROID_TEST_MOCK; -import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER; -import static android.content.pm.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY; +import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_BASE; +import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_MOCK; +import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_RUNNER; +import static android.content.pm.parsing.library.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY; -import android.content.pm.PackageParser.Package; +import android.content.pm.parsing.ParsedPackage; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; @@ -31,7 +31,7 @@ import java.util.List; import java.util.function.Supplier; /** - * Modifies {@link Package} in order to maintain backwards compatibility. + * Modifies {@link ParsedPackage} in order to maintain backwards compatibility. * * @hide */ @@ -60,7 +60,7 @@ public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater { // will remove any references to org.apache.http.library from the package so that it does // not try and load the library when it is on the bootclasspath. boolean bootClassPathContainsATB = !addOptionalUpdater(packageUpdaters, - "android.content.pm.AndroidTestBaseUpdater", + "android.content.pm.parsing.library.AndroidTestBaseUpdater", RemoveUnnecessaryAndroidTestBaseLibrary::new); PackageSharedLibraryUpdater[] updaterArray = packageUpdaters @@ -123,20 +123,20 @@ public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater { } /** - * Modify the shared libraries in the supplied {@link Package} to maintain backwards + * Modify the shared libraries in the supplied {@link ParsedPackage} to maintain backwards * compatibility. * - * @param pkg the {@link Package} to modify. + * @param parsedPackage the {@link ParsedPackage} to modify. */ @VisibleForTesting - public static void modifySharedLibraries(Package pkg) { - INSTANCE.updatePackage(pkg); + public static void modifySharedLibraries(ParsedPackage parsedPackage) { + INSTANCE.updatePackage(parsedPackage); } @Override - public void updatePackage(Package pkg) { + public void updatePackage(ParsedPackage parsedPackage) { for (PackageSharedLibraryUpdater packageUpdater : mPackageUpdaters) { - packageUpdater.updatePackage(pkg); + packageUpdater.updatePackage(parsedPackage); } } @@ -161,10 +161,10 @@ public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater { public static class AndroidTestRunnerSplitUpdater extends PackageSharedLibraryUpdater { @Override - public void updatePackage(Package pkg) { + public void updatePackage(ParsedPackage parsedPackage) { // android.test.runner has a dependency on android.test.mock so if android.test.runner // is present but android.test.mock is not then add android.test.mock. - prefixImplicitDependency(pkg, ANDROID_TEST_RUNNER, ANDROID_TEST_MOCK); + prefixImplicitDependency(parsedPackage, ANDROID_TEST_RUNNER, ANDROID_TEST_MOCK); } } @@ -177,8 +177,8 @@ public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater { extends PackageSharedLibraryUpdater { @Override - public void updatePackage(Package pkg) { - removeLibrary(pkg, ORG_APACHE_HTTP_LEGACY); + public void updatePackage(ParsedPackage parsedPackage) { + removeLibrary(parsedPackage, ORG_APACHE_HTTP_LEGACY); } } @@ -192,8 +192,8 @@ public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater { extends PackageSharedLibraryUpdater { @Override - public void updatePackage(Package pkg) { - removeLibrary(pkg, ANDROID_TEST_BASE); + public void updatePackage(ParsedPackage parsedPackage) { + removeLibrary(parsedPackage, ANDROID_TEST_BASE); } } } diff --git a/core/java/android/content/pm/PackageSharedLibraryUpdater.java b/core/java/android/content/pm/parsing/library/PackageSharedLibraryUpdater.java index 1565d9ce77d4..8b27d140a8f4 100644 --- a/core/java/android/content/pm/PackageSharedLibraryUpdater.java +++ b/core/java/android/content/pm/parsing/library/PackageSharedLibraryUpdater.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * 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. @@ -13,18 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.content.pm; +package android.content.pm.parsing.library; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.pm.parsing.ParsedPackage; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import java.util.ArrayList; +import java.util.List; /** - * Base for classes that update a {@link PackageParser.Package}'s shared libraries. + * Base for classes that update a {@link ParsedPackage}'s shared libraries. * * @hide */ @@ -34,14 +36,13 @@ public abstract class PackageSharedLibraryUpdater { /** * Update the package's shared libraries. * - * @param pkg the package to update. + * @param parsedPackage the package to update. */ - public abstract void updatePackage(PackageParser.Package pkg); + public abstract void updatePackage(ParsedPackage parsedPackage); - static void removeLibrary(PackageParser.Package pkg, String libraryName) { - pkg.usesLibraries = ArrayUtils.remove(pkg.usesLibraries, libraryName); - pkg.usesOptionalLibraries = - ArrayUtils.remove(pkg.usesOptionalLibraries, libraryName); + static void removeLibrary(ParsedPackage parsedPackage, String libraryName) { + parsedPackage.removeUsesLibrary(libraryName) + .removeUsesOptionalLibrary(libraryName); } static @NonNull @@ -53,8 +54,8 @@ public abstract class PackageSharedLibraryUpdater { return cur; } - private static boolean isLibraryPresent(ArrayList<String> usesLibraries, - ArrayList<String> usesOptionalLibraries, String apacheHttpLegacy) { + private static boolean isLibraryPresent(List<String> usesLibraries, + List<String> usesOptionalLibraries, String apacheHttpLegacy) { return ArrayUtils.contains(usesLibraries, apacheHttpLegacy) || ArrayUtils.contains(usesOptionalLibraries, apacheHttpLegacy); } @@ -65,37 +66,32 @@ public abstract class PackageSharedLibraryUpdater { * <p>If the package has an existing dependency on {@code existingLibrary} then prefix it with * the {@code implicitDependency} if it is not already in the list of libraries. * - * @param pkg the {@link PackageParser.Package} to update. + * @param parsedPackage the {@link ParsedPackage} to update. * @param existingLibrary the existing library. * @param implicitDependency the implicit dependency to add */ - void prefixImplicitDependency(PackageParser.Package pkg, String existingLibrary, + void prefixImplicitDependency(ParsedPackage parsedPackage, String existingLibrary, String implicitDependency) { - ArrayList<String> usesLibraries = pkg.usesLibraries; - ArrayList<String> usesOptionalLibraries = pkg.usesOptionalLibraries; + List<String> usesLibraries = parsedPackage.getUsesLibraries(); + List<String> usesOptionalLibraries = parsedPackage.getUsesOptionalLibraries(); if (!isLibraryPresent(usesLibraries, usesOptionalLibraries, implicitDependency)) { if (ArrayUtils.contains(usesLibraries, existingLibrary)) { - prefix(usesLibraries, implicitDependency); + parsedPackage.addUsesLibrary(0, implicitDependency); } else if (ArrayUtils.contains(usesOptionalLibraries, existingLibrary)) { - prefix(usesOptionalLibraries, implicitDependency); + parsedPackage.addUsesOptionalLibrary(0, implicitDependency); } - - pkg.usesLibraries = usesLibraries; - pkg.usesOptionalLibraries = usesOptionalLibraries; } } - void prefixRequiredLibrary(PackageParser.Package pkg, String libraryName) { - ArrayList<String> usesLibraries = pkg.usesLibraries; - ArrayList<String> usesOptionalLibraries = pkg.usesOptionalLibraries; + void prefixRequiredLibrary(ParsedPackage parsedPackage, String libraryName) { + List<String> usesLibraries = parsedPackage.getUsesLibraries(); + List<String> usesOptionalLibraries = parsedPackage.getUsesOptionalLibraries(); boolean alreadyPresent = isLibraryPresent( usesLibraries, usesOptionalLibraries, libraryName); if (!alreadyPresent) { - usesLibraries = prefix(usesLibraries, libraryName); - - pkg.usesLibraries = usesLibraries; + parsedPackage.addUsesLibrary(0, libraryName); } } } diff --git a/core/java/android/content/pm/SharedLibraryNames.java b/core/java/android/content/pm/parsing/library/SharedLibraryNames.java index a607a9ff682b..7b691c06718e 100644 --- a/core/java/android/content/pm/SharedLibraryNames.java +++ b/core/java/android/content/pm/parsing/library/SharedLibraryNames.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * 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. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.content.pm; +package android.content.pm.parsing.library; /** * A set of shared library names diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java index 0847fbdd2291..6709ff5722eb 100644 --- a/core/java/com/android/internal/content/NativeLibraryHelper.java +++ b/core/java/com/android/internal/content/NativeLibraryHelper.java @@ -28,9 +28,9 @@ import static android.system.OsConstants.S_IXOTH; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageParser; -import android.content.pm.PackageParser.Package; import android.content.pm.PackageParser.PackageLite; import android.content.pm.PackageParser.PackageParserException; +import android.content.pm.parsing.AndroidPackage; import android.os.Build; import android.os.SELinux; import android.system.ErrnoException; @@ -87,11 +87,12 @@ public class NativeLibraryHelper { } } - public static Handle create(Package pkg) throws IOException { - return create(pkg.getAllCodePaths(), - (pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) != 0, - (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS) != 0, - (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0); + public static Handle create(AndroidPackage pkg) throws IOException { + return create( + pkg.makeListAllCodePaths(), + (pkg.getFlags() & ApplicationInfo.FLAG_MULTIARCH) != 0, + (pkg.getFlags() & ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS) != 0, + (pkg.getFlags() & ApplicationInfo.FLAG_DEBUGGABLE) != 0); } public static Handle create(PackageLite lite) throws IOException { diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java index 821022f1f917..bc8019796d22 100644 --- a/core/java/com/android/internal/util/ArrayUtils.java +++ b/core/java/com/android/internal/util/ArrayUtils.java @@ -600,6 +600,14 @@ public class ArrayUtils { return cur; } + public static @NonNull <T> ArrayList<T> add(@Nullable ArrayList<T> cur, int index, T val) { + if (cur == null) { + cur = new ArrayList<>(); + } + cur.add(index, val); + return cur; + } + public static @Nullable <T> ArrayList<T> remove(@Nullable ArrayList<T> cur, T val) { if (cur == null) { return null; diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp index a4c504b9cbdf..c009f588f8a9 100644 --- a/core/tests/coretests/Android.bp +++ b/core/tests/coretests/Android.bp @@ -74,7 +74,6 @@ java_genrule { ":FrameworksCoreTests_install_loc_internal", ":FrameworksCoreTests_install_loc_sdcard", ":FrameworksCoreTests_install_loc_unspecified", - ":FrameworksCoreTests_install_multi_package", ":FrameworksCoreTests_install_split_base", ":FrameworksCoreTests_install_split_feature_a", ":FrameworksCoreTests_install_use_perm_good", diff --git a/core/tests/coretests/apks/install_multi_package/Android.bp b/core/tests/coretests/apks/install_multi_package/Android.bp deleted file mode 100644 index 249242e239e4..000000000000 --- a/core/tests/coretests/apks/install_multi_package/Android.bp +++ /dev/null @@ -1,6 +0,0 @@ -android_test_helper_app { - name: "FrameworksCoreTests_install_multi_package", - defaults: ["FrameworksCoreTests_apks_defaults"], - - srcs: ["**/*.java"], -} diff --git a/core/tests/coretests/apks/install_multi_package/AndroidManifest.xml b/core/tests/coretests/apks/install_multi_package/AndroidManifest.xml deleted file mode 100644 index 5164cae9e5c0..000000000000 --- a/core/tests/coretests/apks/install_multi_package/AndroidManifest.xml +++ /dev/null @@ -1,104 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2011 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. ---> -<manifest - xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.frameworks.coretests.install_multi_package"> - -<!-- - This manifest is has child packages with components. ---> - - <uses-feature - android:name="com.android.frameworks.coretests.nonexistent" /> - <uses-configuration - android:reqFiveWayNav="false" /> - - <instrumentation - android:name="android.test.InstrumentationTestRunner" - android:targetPackage="com.android.frameworks.coretests" - android:label="Frameworks Core Tests" /> - - <permission - android:label="test permission" - android:name="test_permission" - android:protectionLevel="normal" /> - <uses-permission android:name="android.permission.INTERNET" /> - -<!-- - NOTE: This declares a child package, application, then another child - package, to test potential bugs that are order-dependent. Also, each - one varies the order. ---> - - <package package="com.android.frameworks.coretests.install_multi_package.first_child"> - <uses-permission android:name="android.permission.NFC" /> - <!-- NOTE: A declared permission is ignored since the tag is not whitelisted. --> - <permission - android:label="test permission" - android:name="first_child_permission" - android:protectionLevel="signature" /> - <application - android:hasCode="true"> - <activity - android:name="com.android.frameworks.coretests.FirstChildTestActivity"> - </activity> - <provider - android:name="com.android.frameworks.coretests.FirstChildTestProvider" - android:authorities="com.android.frameworks.coretests.testprovider" /> - <receiver - android:name="com.android.frameworks.coretests.FirstChildTestReceiver" /> - <service - android:name="com.android.frameworks.coretests.FirstChildTestService" /> - </application> - </package> - - <application - android:hasCode="true"> - <service - android:name="com.android.frameworks.coretests.TestService" /> - <activity - android:name="com.android.frameworks.coretests.TestActivity"> - </activity> - <provider - android:name="com.android.frameworks.coretests.TestProvider" - android:authorities="com.android.frameworks.coretests.testprovider" /> - <receiver - android:name="com.android.frameworks.coretests.TestReceiver" /> - </application> - - <package package="com.android.frameworks.coretests.blah.second_child"> - <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> - <uses-permission-sdk-23 android:name="android.permission.READ_CONTACTS" /> - <!-- NOTE: A declared permission is ignored since the tag is not whitelisted. --> - <permission - android:label="test permission" - android:name="second_child_permission" - android:protectionLevel="dangerous" /> - <application - android:hasCode="true"> - <receiver - android:name="com.android.frameworks.coretests.SecondChildTestReceiver" /> - <service - android:name="com.android.frameworks.coretests.SecondChildTestService" /> - <activity - android:name="com.android.frameworks.coretests.SecondChildTestActivity"> - </activity> - <provider - android:name="com.android.frameworks.coretests.SecondChildTestProvider" - android:authorities="com.android.frameworks.coretests.testprovider" /> - </application> - </package> -</manifest> diff --git a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/FirstChildTestActivity.java b/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/FirstChildTestActivity.java deleted file mode 100644 index 57afcb0e1a0d..000000000000 --- a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/FirstChildTestActivity.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2011 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 com.android.frameworks.coretests; - -import android.app.Activity; - -public class FirstChildTestActivity extends Activity { - -} diff --git a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/FirstChildTestProvider.java b/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/FirstChildTestProvider.java deleted file mode 100644 index 2816865b2f1f..000000000000 --- a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/FirstChildTestProvider.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2011 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 com.android.frameworks.coretests; - -import android.content.ContentProvider; -import android.content.ContentValues; -import android.database.Cursor; -import android.net.Uri; - -public class FirstChildTestProvider extends ContentProvider { - - @Override - public boolean onCreate() { - return false; - } - - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - return null; - } - - @Override - public String getType(Uri uri) { - return null; - } - - @Override - public Uri insert(Uri uri, ContentValues values) { - return null; - } - - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - return 0; - } - - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - return 0; - } -} diff --git a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/FirstChildTestReceiver.java b/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/FirstChildTestReceiver.java deleted file mode 100644 index ffe84b73dd37..000000000000 --- a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/FirstChildTestReceiver.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2011 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 com.android.frameworks.coretests; - -import android.content.ContentProvider; -import android.content.ContentValues; -import android.database.Cursor; -import android.net.Uri; - -public class FirstChildTestReceiver extends ContentProvider { - - @Override - public boolean onCreate() { - return false; - } - - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - return null; - } - - @Override - public String getType(Uri uri) { - return null; - } - - @Override - public Uri insert(Uri uri, ContentValues values) { - return null; - } - - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - return 0; - } - - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - return 0; - } -} diff --git a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/FirstChildTestService.java b/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/FirstChildTestService.java deleted file mode 100644 index faa6e9cff2b2..000000000000 --- a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/FirstChildTestService.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2011 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 com.android.frameworks.coretests; - -import android.app.Service; -import android.content.Intent; -import android.os.IBinder; - -public class FirstChildTestService extends Service { - - @Override - public IBinder onBind(Intent intent) { - return null; - } -} diff --git a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/SecondChildTestActivity.java b/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/SecondChildTestActivity.java deleted file mode 100644 index e89f26489959..000000000000 --- a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/SecondChildTestActivity.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2011 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 com.android.frameworks.coretests; - -import android.app.Activity; - -public class SecondChildTestActivity extends Activity { - -} diff --git a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/SecondChildTestProvider.java b/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/SecondChildTestProvider.java deleted file mode 100644 index 2bd40a5df94d..000000000000 --- a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/SecondChildTestProvider.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2011 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 com.android.frameworks.coretests; - -import android.content.ContentProvider; -import android.content.ContentValues; -import android.database.Cursor; -import android.net.Uri; - -public class SecondChildTestProvider extends ContentProvider { - - @Override - public boolean onCreate() { - return false; - } - - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - return null; - } - - @Override - public String getType(Uri uri) { - return null; - } - - @Override - public Uri insert(Uri uri, ContentValues values) { - return null; - } - - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - return 0; - } - - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - return 0; - } -} diff --git a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/SecondChildTestReceiver.java b/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/SecondChildTestReceiver.java deleted file mode 100644 index a6c4ddc90c6a..000000000000 --- a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/SecondChildTestReceiver.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2011 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 com.android.frameworks.coretests; - -import android.content.ContentProvider; -import android.content.ContentValues; -import android.database.Cursor; -import android.net.Uri; - -public class SecondChildTestReceiver extends ContentProvider { - - @Override - public boolean onCreate() { - return false; - } - - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - return null; - } - - @Override - public String getType(Uri uri) { - return null; - } - - @Override - public Uri insert(Uri uri, ContentValues values) { - return null; - } - - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - return 0; - } - - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - return 0; - } -} diff --git a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/SecondChildTestService.java b/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/SecondChildTestService.java deleted file mode 100644 index 1e721aa8ae5b..000000000000 --- a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/SecondChildTestService.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2011 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 com.android.frameworks.coretests; - -import android.app.Service; -import android.content.Intent; -import android.os.IBinder; - -public class SecondChildTestService extends Service { - - @Override - public IBinder onBind(Intent intent) { - return null; - } -} diff --git a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/TestActivity.java b/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/TestActivity.java deleted file mode 100644 index 10d0551a3a6f..000000000000 --- a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/TestActivity.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2011 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 com.android.frameworks.coretests; - -import android.app.Activity; - -public class TestActivity extends Activity { - -} diff --git a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/TestProvider.java b/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/TestProvider.java deleted file mode 100644 index 59f9f10c6efe..000000000000 --- a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/TestProvider.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2011 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 com.android.frameworks.coretests; - -import android.content.ContentProvider; -import android.content.ContentValues; -import android.database.Cursor; -import android.net.Uri; - -public class TestProvider extends ContentProvider { - - @Override - public boolean onCreate() { - return false; - } - - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - return null; - } - - @Override - public String getType(Uri uri) { - return null; - } - - @Override - public Uri insert(Uri uri, ContentValues values) { - return null; - } - - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - return 0; - } - - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - return 0; - } -} diff --git a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/TestReceiver.java b/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/TestReceiver.java deleted file mode 100644 index 21f6263a38bc..000000000000 --- a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/TestReceiver.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2011 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 com.android.frameworks.coretests; - -import android.content.ContentProvider; -import android.content.ContentValues; -import android.database.Cursor; -import android.net.Uri; - -public class TestReceiver extends ContentProvider { - - @Override - public boolean onCreate() { - return false; - } - - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - return null; - } - - @Override - public String getType(Uri uri) { - return null; - } - - @Override - public Uri insert(Uri uri, ContentValues values) { - return null; - } - - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - return 0; - } - - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - return 0; - } -} diff --git a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/TestService.java b/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/TestService.java deleted file mode 100644 index b330e75308f9..000000000000 --- a/core/tests/coretests/apks/install_multi_package/src/com/android/frameworks/coretests/TestService.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2011 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 com.android.frameworks.coretests; - -import android.app.Service; -import android.content.Intent; -import android.os.IBinder; - -public class TestService extends Service { - - @Override - public IBinder onBind(Intent intent) { - return null; - } -} diff --git a/core/tests/coretests/src/android/content/pm/AndroidHidlUpdaterTest.java b/core/tests/coretests/src/android/content/pm/AndroidHidlUpdaterTest.java deleted file mode 100644 index cc48239c4526..000000000000 --- a/core/tests/coretests/src/android/content/pm/AndroidHidlUpdaterTest.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2018 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; - -import static android.content.pm.PackageBuilder.builder; -import static android.content.pm.SharedLibraryNames.ANDROID_HIDL_BASE; -import static android.content.pm.SharedLibraryNames.ANDROID_HIDL_MANAGER; - -import android.os.Build; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Test for {@link AndroidHidlUpdater} - */ -@SmallTest -@RunWith(JUnit4.class) -public class AndroidHidlUpdaterTest extends PackageSharedLibraryUpdaterTest { - - private static final String OTHER_LIBRARY = "other.library"; - - @Test - public void targeted_at_P() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.P); - - // no change, not system - checkBackwardsCompatibility(before, before); - } - - @Test - public void targeted_at_P_system() { - PackageBuilder before = builder().asSystemApp() - .targetSdkVersion(Build.VERSION_CODES.P); - - // Should add both HIDL libraries - PackageBuilder after = builder().asSystemApp() - .targetSdkVersion(Build.VERSION_CODES.P) - .requiredLibraries(ANDROID_HIDL_MANAGER, ANDROID_HIDL_BASE); - - checkBackwardsCompatibility(before, after); - } - - @Test - public void targeted_at_P_not_empty_usesLibraries() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.P) - .requiredLibraries(OTHER_LIBRARY); - - // no change, not system - checkBackwardsCompatibility(before, before); - } - - @Test - public void targeted_at_P_not_empty_usesLibraries_system() { - PackageBuilder before = builder().asSystemApp() - .targetSdkVersion(Build.VERSION_CODES.P) - .requiredLibraries(OTHER_LIBRARY); - - // The hidl jars should be added at the start of the list because it - // is not on the bootclasspath and the package targets pre-P. - PackageBuilder after = builder().asSystemApp() - .targetSdkVersion(Build.VERSION_CODES.P) - .requiredLibraries(ANDROID_HIDL_MANAGER, ANDROID_HIDL_BASE, OTHER_LIBRARY); - - checkBackwardsCompatibility(before, after); - } - - @Test - public void targeted_at_P_in_usesLibraries() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.P) - .requiredLibraries(ANDROID_HIDL_MANAGER, ANDROID_HIDL_BASE); - - PackageBuilder after = builder() - .targetSdkVersion(Build.VERSION_CODES.P); - - // Libraries are removed because they are not available for non-system apps - checkBackwardsCompatibility(before, after); - } - - @Test - public void targeted_at_P_in_usesLibraries_system() { - PackageBuilder before = builder().asSystemApp() - .targetSdkVersion(Build.VERSION_CODES.P) - .requiredLibraries(ANDROID_HIDL_MANAGER, ANDROID_HIDL_BASE); - - // No change is required because the package explicitly requests the HIDL libraries - // and is targeted at the current version so does not need backwards compatibility. - checkBackwardsCompatibility(before, before); - } - - @Test - public void in_usesLibraries() { - PackageBuilder before = builder().requiredLibraries(ANDROID_HIDL_BASE); - - // Dependency is removed, it is not available. - PackageBuilder after = builder(); - - // Libraries are removed because they are not available for apps targetting Q+ - checkBackwardsCompatibility(before, after); - } - - @Test - public void in_usesOptionalLibraries() { - PackageBuilder before = builder().optionalLibraries(ANDROID_HIDL_BASE); - - // Dependency is removed, it is not available. - PackageBuilder after = builder(); - - // Libraries are removed because they are not available for apps targetting Q+ - checkBackwardsCompatibility(before, after); - } - - private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) { - checkBackwardsCompatibility(before, after, AndroidHidlUpdater::new); - } -} diff --git a/core/tests/coretests/src/android/content/pm/AndroidTestBaseUpdaterTest.java b/core/tests/coretests/src/android/content/pm/AndroidTestBaseUpdaterTest.java deleted file mode 100644 index 03108ced4816..000000000000 --- a/core/tests/coretests/src/android/content/pm/AndroidTestBaseUpdaterTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2018 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; - -import static android.content.pm.PackageBuilder.builder; -import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE; - -import android.os.Build; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Test for {@link AndroidTestBaseUpdater} - */ -@SmallTest -@RunWith(OptionalClassRunner.class) -@OptionalClassRunner.OptionalClass("android.content.pm.AndroidTestBaseUpdater") -public class AndroidTestBaseUpdaterTest extends PackageSharedLibraryUpdaterTest { - - private static final String OTHER_LIBRARY = "other.library"; - - @Test - public void targeted_at_Q() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.Q); - - // Should add org.apache.http.legacy. - PackageBuilder after = builder() - .targetSdkVersion(Build.VERSION_CODES.Q) - .requiredLibraries(ANDROID_TEST_BASE); - - checkBackwardsCompatibility(before, after); - } - - @Test - public void targeted_at_Q_not_empty_usesLibraries() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.Q) - .requiredLibraries(OTHER_LIBRARY); - - // The org.apache.http.legacy jar should be added at the start of the list because it - // is not on the bootclasspath and the package targets pre-Q. - PackageBuilder after = builder() - .targetSdkVersion(Build.VERSION_CODES.Q) - .requiredLibraries(ANDROID_TEST_BASE, OTHER_LIBRARY); - - checkBackwardsCompatibility(before, after); - } - - @Test - public void targeted_at_Q_in_usesLibraries() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.Q) - .requiredLibraries(ANDROID_TEST_BASE); - - // No change is required because although org.apache.http.legacy has been removed from - // the bootclasspath the package explicitly requests it. - checkBackwardsCompatibility(before, before); - } - - @Test - public void targeted_at_Q_in_usesOptionalLibraries() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.Q) - .optionalLibraries(ANDROID_TEST_BASE); - - // No change is required because although org.apache.http.legacy has been removed from - // the bootclasspath the package explicitly requests it. - checkBackwardsCompatibility(before, before); - } - - @Test - public void in_usesLibraries() { - PackageBuilder before = builder().requiredLibraries(ANDROID_TEST_BASE); - - // No change is required because the package explicitly requests org.apache.http.legacy - // and is targeted at the current version so does not need backwards compatibility. - checkBackwardsCompatibility(before, before); - } - - @Test - public void in_usesOptionalLibraries() { - PackageBuilder before = builder().optionalLibraries(ANDROID_TEST_BASE); - - // No change is required because the package explicitly requests org.apache.http.legacy - // and is targeted at the current version so does not need backwards compatibility. - checkBackwardsCompatibility(before, before); - } - - private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) { - checkBackwardsCompatibility(before, after, AndroidTestBaseUpdater::new); - } -} diff --git a/core/tests/coretests/src/android/content/pm/AndroidTestRunnerSplitUpdaterTest.java b/core/tests/coretests/src/android/content/pm/AndroidTestRunnerSplitUpdaterTest.java deleted file mode 100644 index 7f817d66caf7..000000000000 --- a/core/tests/coretests/src/android/content/pm/AndroidTestRunnerSplitUpdaterTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2018 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; - -import static android.content.pm.PackageBuilder.builder; -import static android.content.pm.SharedLibraryNames.ANDROID_TEST_MOCK; -import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER; - -import android.content.pm.PackageBackwardCompatibility.AndroidTestRunnerSplitUpdater; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Test for {@link AndroidTestRunnerSplitUpdater} - */ -@SmallTest -@RunWith(JUnit4.class) -public class AndroidTestRunnerSplitUpdaterTest extends PackageSharedLibraryUpdaterTest { - - @Test - public void android_test_runner_in_usesOptionalLibraries() { - PackageBuilder before = builder().optionalLibraries(ANDROID_TEST_RUNNER); - - PackageBuilder after = builder() - .optionalLibraries(ANDROID_TEST_MOCK, ANDROID_TEST_RUNNER); - - checkBackwardsCompatibility(before, after); - } - - @Test - public void android_test_runner_in_usesLibraries_android_test_mock_in_usesOptionalLibraries() { - PackageBuilder before = builder() - .requiredLibraries(ANDROID_TEST_RUNNER) - .optionalLibraries(ANDROID_TEST_MOCK); - - PackageBuilder after = builder() - .requiredLibraries(ANDROID_TEST_RUNNER) - .optionalLibraries(ANDROID_TEST_MOCK); - - checkBackwardsCompatibility(before, after); - } - - private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) { - checkBackwardsCompatibility(before, after, AndroidTestRunnerSplitUpdater::new); - } -} diff --git a/core/tests/coretests/src/android/content/pm/OrgApacheHttpLegacyUpdaterTest.java b/core/tests/coretests/src/android/content/pm/OrgApacheHttpLegacyUpdaterTest.java deleted file mode 100644 index 834a0bbeab89..000000000000 --- a/core/tests/coretests/src/android/content/pm/OrgApacheHttpLegacyUpdaterTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2018 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; - -import static android.content.pm.PackageBuilder.builder; -import static android.content.pm.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY; - -import android.os.Build; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Test for {@link OrgApacheHttpLegacyUpdater} - */ -@SmallTest -@RunWith(OptionalClassRunner.class) -@OptionalClassRunner.OptionalClass("android.content.pm.OrgApacheHttpLegacyUpdater") -public class OrgApacheHttpLegacyUpdaterTest extends PackageSharedLibraryUpdaterTest { - - private static final String OTHER_LIBRARY = "other.library"; - - @Test - public void targeted_at_O() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.O); - - // Should add org.apache.http.legacy. - PackageBuilder after = builder() - .targetSdkVersion(Build.VERSION_CODES.O) - .requiredLibraries(ORG_APACHE_HTTP_LEGACY); - - checkBackwardsCompatibility(before, after); - } - - @Test - public void targeted_at_O_not_empty_usesLibraries() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.O) - .requiredLibraries(OTHER_LIBRARY); - - // The org.apache.http.legacy jar should be added at the start of the list because it - // is not on the bootclasspath and the package targets pre-P. - PackageBuilder after = builder() - .targetSdkVersion(Build.VERSION_CODES.O) - .requiredLibraries(ORG_APACHE_HTTP_LEGACY, OTHER_LIBRARY); - - checkBackwardsCompatibility(before, after); - } - - @Test - public void targeted_at_O_in_usesLibraries() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.O) - .requiredLibraries(ORG_APACHE_HTTP_LEGACY); - - // No change is required because although org.apache.http.legacy has been removed from - // the bootclasspath the package explicitly requests it. - checkBackwardsCompatibility(before, before); - } - - @Test - public void targeted_at_O_in_usesOptionalLibraries() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.O) - .optionalLibraries(ORG_APACHE_HTTP_LEGACY); - - // No change is required because although org.apache.http.legacy has been removed from - // the bootclasspath the package explicitly requests it. - checkBackwardsCompatibility(before, before); - } - - @Test - public void in_usesLibraries() { - PackageBuilder before = builder().requiredLibraries(ORG_APACHE_HTTP_LEGACY); - - // No change is required because the package explicitly requests org.apache.http.legacy - // and is targeted at the current version so does not need backwards compatibility. - checkBackwardsCompatibility(before, before); - } - - @Test - public void in_usesOptionalLibraries() { - PackageBuilder before = builder().optionalLibraries(ORG_APACHE_HTTP_LEGACY); - - // No change is required because the package explicitly requests org.apache.http.legacy - // and is targeted at the current version so does not need backwards compatibility. - checkBackwardsCompatibility(before, before); - } - - private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) { - checkBackwardsCompatibility(before, after, OrgApacheHttpLegacyUpdater::new); - } -} diff --git a/core/tests/coretests/src/android/content/pm/PackageBuilder.java b/core/tests/coretests/src/android/content/pm/PackageBuilder.java deleted file mode 100644 index f7544af43461..000000000000 --- a/core/tests/coretests/src/android/content/pm/PackageBuilder.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2018 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; - -import static org.junit.Assert.assertEquals; - -import android.os.Build; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * Test support for building {@link PackageParser.Package} instances. - */ -class PackageBuilder { - - private int mTargetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT; - - private int mFlags = 0; - - private ArrayList<String> mRequiredLibraries; - - private ArrayList<String> mOptionalLibraries; - - public static PackageBuilder builder() { - return new PackageBuilder(); - } - - public PackageParser.Package build() { - PackageParser.Package pkg = new PackageParser.Package("org.package.name"); - pkg.applicationInfo.targetSdkVersion = mTargetSdkVersion; - pkg.applicationInfo.flags = mFlags; - pkg.usesLibraries = mRequiredLibraries; - pkg.usesOptionalLibraries = mOptionalLibraries; - return pkg; - } - - PackageBuilder targetSdkVersion(int version) { - this.mTargetSdkVersion = version; - return this; - } - - PackageBuilder asSystemApp() { - this.mFlags |= ApplicationInfo.FLAG_SYSTEM; - return this; - } - - PackageBuilder requiredLibraries(String... names) { - this.mRequiredLibraries = arrayListOrNull(names); - return this; - } - - PackageBuilder requiredLibraries(List<String> names) { - this.mRequiredLibraries = arrayListOrNull(names.toArray(new String[names.size()])); - return this; - } - - PackageBuilder optionalLibraries(String... names) { - this.mOptionalLibraries = arrayListOrNull(names); - return this; - } - - /** - * Check that this matches the supplied {@link PackageParser.Package}. - * - * @param pkg the instance to compare with this. - */ - public void check(PackageParser.Package pkg) { - assertEquals("targetSdkVersion should not be changed", - mTargetSdkVersion, - pkg.applicationInfo.targetSdkVersion); - assertEquals("usesLibraries not updated correctly", - mRequiredLibraries, - pkg.usesLibraries); - assertEquals("usesOptionalLibraries not updated correctly", - mOptionalLibraries, - pkg.usesOptionalLibraries); - } - - private static ArrayList<String> arrayListOrNull(String... strings) { - if (strings == null || strings.length == 0) { - return null; - } - ArrayList<String> list = new ArrayList<>(); - Collections.addAll(list, strings); - return list; - } - -} diff --git a/core/tests/coretests/src/android/content/pm/PackageParserTest.java b/core/tests/coretests/src/android/content/pm/PackageParserTest.java index 5c7f2af782b9..cb23850798c3 100644 --- a/core/tests/coretests/src/android/content/pm/PackageParserTest.java +++ b/core/tests/coretests/src/android/content/pm/PackageParserTest.java @@ -23,26 +23,26 @@ import static org.junit.Assert.assertTrue; import android.apex.ApexInfo; import android.content.Context; -import android.content.pm.PackageParser.Component; -import android.content.pm.PackageParser.Package; -import android.content.pm.PackageParser.Permission; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.ComponentParseUtils.ParsedComponent; +import android.content.pm.parsing.ComponentParseUtils.ParsedPermission; +import android.content.pm.parsing.ParsedPackage; import android.os.Build; import android.os.Bundle; import android.os.FileUtils; -import android.os.SystemProperties; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.frameworks.coretests.R; +import com.android.internal.util.ArrayUtils; import org.junit.Test; import org.junit.runner.RunWith; import java.io.File; import java.io.InputStream; -import java.util.Arrays; import java.util.function.Function; @SmallTest @@ -59,8 +59,8 @@ public class PackageParserTest { private static final String PRE_RELEASE_WITH_FINGERPRINT = "B.fingerprint"; private static final String NEWER_PRE_RELEASE_WITH_FINGERPRINT = "C.fingerprint"; - private static final String[] CODENAMES_RELEASED = { /* empty */ }; - private static final String[] CODENAMES_PRE_RELEASE = { PRE_RELEASE }; + private static final String[] CODENAMES_RELEASED = { /* empty */}; + private static final String[] CODENAMES_PRE_RELEASE = {PRE_RELEASE}; private static final int OLDER_VERSION = 10; private static final int PLATFORM_VERSION = 20; @@ -300,10 +300,6 @@ public class PackageParserTest { assertEquals(0x0083, finalConfigChanges); // Should be 10000011. } - Package parsePackage(String apkFileName, int apkResourceId) throws Exception { - return parsePackage(apkFileName, apkResourceId, p -> p); - } - /** * Copies a specified {@code resourceId} to a file. Returns a non-null file if the copy * succeeded, or {@code null} otherwise. @@ -331,16 +327,17 @@ public class PackageParserTest { * * APKs are put into coretests/apks/packageparser_*. * - * @param apkFileName temporary file name to store apk extracted from resources + * @param apkFileName temporary file name to store apk extracted from resources * @param apkResourceId identifier of the apk as a resource */ - Package parsePackage(String apkFileName, int apkResourceId, - Function<Package, Package> converter) throws Exception { + ParsedPackage parsePackage(String apkFileName, int apkResourceId, + Function<ParsedPackage, ParsedPackage> converter) throws Exception { // Copy the resource to a file. File outFile = null; try { outFile = copyRawResourceToFile(apkFileName, apkResourceId); - return converter.apply(new PackageParser().parsePackage(outFile, 0 /* flags */)); + return converter.apply( + new PackageParser().parseParsedPackage(outFile, 0 /* flags */, false)); } finally { if (outFile != null) { outFile.delete(); @@ -351,40 +348,40 @@ public class PackageParserTest { /** * Asserts basic properties about a component. */ - private void assertComponent(String className, String packageName, int numIntents, - Component<?> component) { + private void assertComponent(String className, int numIntents, ParsedComponent<?> component) { assertEquals(className, component.className); - assertEquals(packageName, component.owner.packageName); assertEquals(numIntents, component.intents.size()); } /** * Asserts four regularly-named components of each type: one Activity, one Service, one * Provider, and one Receiver. + * * @param template templated string with %s subbed with Activity, Service, Provider, Receiver */ - private void assertOneComponentOfEachType(String template, Package p) { - String packageName = p.packageName; + private void assertOneComponentOfEachType(String template, AndroidPackage p) { + assertEquals(2, p.getActivities().size()); + + // For normal apps, a Activity that forwards to the App Details page is added. + assertEquals("android.app.AppDetailsActivity", p.getActivities().get(1) + .className); - assertEquals(1, p.activities.size()); assertComponent(String.format(template, "Activity"), - packageName, 0 /* intents */, p.activities.get(0)); - assertEquals(1, p.services.size()); + 0 /* intents */, p.getActivities().get(0)); + assertEquals(1, p.getServices().size()); assertComponent(String.format(template, "Service"), - packageName, 0 /* intents */, p.services.get(0)); - assertEquals(1, p.providers.size()); + 0 /* intents */, p.getServices().get(0)); + assertEquals(1, p.getProviders().size()); assertComponent(String.format(template, "Provider"), - packageName, 0 /* intents */, p.providers.get(0)); - assertEquals(1, p.receivers.size()); + 0 /* intents */, p.getProviders().get(0)); + assertEquals(1, p.getReceivers().size()); assertComponent(String.format(template, "Receiver"), - packageName, 0 /* intents */, p.receivers.get(0)); + 0 /* intents */, p.getReceivers().get(0)); } - private void assertPermission(String name, String packageName, int protectionLevel, - Permission permission) { - assertEquals(packageName, permission.owner.packageName); - assertEquals(name, permission.info.name); - assertEquals(protectionLevel, permission.info.protectionLevel); + private void assertPermission(String name, int protectionLevel, ParsedPermission permission) { + assertEquals(name, permission.getName()); + assertEquals(protectionLevel, permission.getProtection()); } private void assertMetadata(Bundle b, String... keysAndValues) { @@ -416,25 +413,25 @@ public class PackageParserTest { } private void checkPackageWithComponents( - Function<Package, Package> converter) throws Exception { - Package p = parsePackage( + Function<ParsedPackage, ParsedPackage> converter) throws Exception { + ParsedPackage p = parsePackage( "install_complete_package_info.apk", R.raw.install_complete_package_info, converter); String packageName = "com.android.frameworks.coretests.install_complete_package_info"; - assertEquals(packageName, p.packageName); - assertEquals(1, p.permissions.size()); + assertEquals(packageName, p.getPackageName()); + assertEquals(1, p.getPermissions().size()); assertPermission( "com.android.frameworks.coretests.install_complete_package_info.test_permission", - packageName, PermissionInfo.PROTECTION_NORMAL, p.permissions.get(0)); + PermissionInfo.PROTECTION_NORMAL, p.getPermissions().get(0)); // Hidden "app details" activity is added to every package. boolean foundAppDetailsActivity = false; - for (int i = 0; i < p.activities.size(); i++) { - if (p.activities.get(i).className.equals( + for (int i = 0; i < ArrayUtils.size(p.getActivities()); i++) { + if (p.getActivities().get(i).className.equals( PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME)) { foundAppDetailsActivity = true; - p.activities.remove(i); + p.getActivities().remove(i); break; } } @@ -442,72 +439,23 @@ public class PackageParserTest { assertOneComponentOfEachType("com.android.frameworks.coretests.Test%s", p); - assertMetadata(p.mAppMetaData, + assertMetadata(p.getAppMetaData(), "key1", "value1", "key2", "this_is_app"); - assertMetadata(p.activities.get(0).metaData, + assertMetadata(p.getActivities().get(0).getMetaData(), "key1", "value1", "key2", "this_is_activity"); - assertMetadata(p.services.get(0).metaData, + assertMetadata(p.getServices().get(0).getMetaData(), "key1", "value1", "key2", "this_is_service"); - assertMetadata(p.receivers.get(0).metaData, + assertMetadata(p.getReceivers().get(0).getMetaData(), "key1", "value1", "key2", "this_is_receiver"); - assertMetadata(p.providers.get(0).metaData, + assertMetadata(p.getProviders().get(0).getMetaData(), "key1", "value1", "key2", "this_is_provider"); } - /** - * Determines if the current device supports multi-package APKs. - */ - private boolean supportsMultiPackageApk() { - return SystemProperties.getBoolean("persist.sys.child_packages_enabled", false); - } - - @Test - public void testMultiPackageComponents() throws Exception { - // TODO(gboyer): Remove once we decide to launch multi-package APKs. - if (!supportsMultiPackageApk()) { - return; - } - String parentName = "com.android.frameworks.coretests.install_multi_package"; - String firstChildName = - "com.android.frameworks.coretests.install_multi_package.first_child"; - String secondChildName = // NOTE: intentionally inconsistent! - "com.android.frameworks.coretests.blah.second_child"; - - Package parent = parsePackage("install_multi_package.apk", R.raw.install_multi_package); - assertEquals(parentName, parent.packageName); - assertEquals(2, parent.childPackages.size()); - assertOneComponentOfEachType("com.android.frameworks.coretests.Test%s", parent); - assertEquals(1, parent.permissions.size()); - assertPermission(parentName + ".test_permission", parentName, - PermissionInfo.PROTECTION_NORMAL, parent.permissions.get(0)); - assertEquals(Arrays.asList("android.permission.INTERNET"), - parent.requestedPermissions); - - Package firstChild = parent.childPackages.get(0); - assertEquals(firstChildName, firstChild.packageName); - assertOneComponentOfEachType( - "com.android.frameworks.coretests.FirstChildTest%s", firstChild); - assertEquals(0, firstChild.permissions.size()); // Child APKs cannot declare permissions. - assertEquals(Arrays.asList("android.permission.NFC"), - firstChild.requestedPermissions); - - Package secondChild = parent.childPackages.get(1); - assertEquals(secondChildName, secondChild.packageName); - assertOneComponentOfEachType( - "com.android.frameworks.coretests.SecondChildTest%s", secondChild); - assertEquals(0, secondChild.permissions.size()); // Child APKs cannot declare permissions. - assertEquals( - Arrays.asList( - "android.permission.ACCESS_NETWORK_STATE", - "android.permission.READ_CONTACTS"), - secondChild.requestedPermissions); - } - @Test public void testApexPackageInfoGeneration() throws Exception { String apexModuleName = "com.android.tzdata.apex"; @@ -522,7 +470,7 @@ public class PackageParserTest { int flags = PackageManager.GET_META_DATA | PackageManager.GET_SIGNING_CERTIFICATES; PackageParser pp = new PackageParser(); - Package p = pp.parsePackage(apexFile, flags, false); + PackageParser.Package p = pp.parsePackage(apexFile, flags, false); PackageParser.collectCertificates(p, false); PackageInfo pi = PackageParser.generatePackageInfo(p, apexInfo, flags); diff --git a/core/tests/coretests/src/android/content/pm/PackageSharedLibraryUpdaterTest.java b/core/tests/coretests/src/android/content/pm/PackageSharedLibraryUpdaterTest.java deleted file mode 100644 index 71a0e5e51b71..000000000000 --- a/core/tests/coretests/src/android/content/pm/PackageSharedLibraryUpdaterTest.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2018 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; - -import java.util.function.Supplier; - -/** - * Helper for classes that test {@link PackageSharedLibraryUpdater}. - */ -abstract class PackageSharedLibraryUpdaterTest { - - static void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after, - Supplier<PackageSharedLibraryUpdater> updaterSupplier) { - PackageParser.Package pkg = before.build(); - updaterSupplier.get().updatePackage(pkg); - after.check(pkg); - } -} diff --git a/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryAndroidTestBaseLibraryTest.java b/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryAndroidTestBaseLibraryTest.java deleted file mode 100644 index 216b0c8950b7..000000000000 --- a/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryAndroidTestBaseLibraryTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2018 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; - -import static android.content.pm.PackageBuilder.builder; -import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE; - -import android.content.pm.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary; -import android.os.Build; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Test for {@link RemoveUnnecessaryAndroidTestBaseLibrary} - */ -@SmallTest -@RunWith(JUnit4.class) -public class RemoveUnnecessaryAndroidTestBaseLibraryTest - extends PackageSharedLibraryUpdaterTest { - - private static final String OTHER_LIBRARY = "other.library"; - - @Test - public void targeted_at_O() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.O); - - // No change required. - checkBackwardsCompatibility(before, before); - } - - @Test - public void targeted_at_O_not_empty_usesLibraries() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.O) - .requiredLibraries(OTHER_LIBRARY); - - // No change required. - checkBackwardsCompatibility(before, before); - } - - @Test - public void targeted_at_O_in_usesLibraries() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.O) - .requiredLibraries(ANDROID_TEST_BASE); - - // android.test.base should be removed from the libraries because it is provided - // on the bootclasspath and providing both increases start up cost unnecessarily. - PackageBuilder after = builder() - .targetSdkVersion(Build.VERSION_CODES.O); - - checkBackwardsCompatibility(before, after); - } - - @Test - public void targeted_at_O_in_usesOptionalLibraries() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.O) - .optionalLibraries(ANDROID_TEST_BASE); - - // android.test.base should be removed from the libraries because it is provided - // on the bootclasspath and providing both increases start up cost unnecessarily. - PackageBuilder after = builder() - .targetSdkVersion(Build.VERSION_CODES.O); - - checkBackwardsCompatibility(before, after); - } - - @Test - public void in_usesLibraries() { - PackageBuilder before = builder().requiredLibraries(ANDROID_TEST_BASE); - - // android.test.base should be removed from the libraries because it is provided - // on the bootclasspath and providing both increases start up cost unnecessarily. - PackageBuilder after = builder(); - - checkBackwardsCompatibility(before, after); - } - - @Test - public void in_usesOptionalLibraries() { - PackageBuilder before = builder().optionalLibraries(ANDROID_TEST_BASE); - - // android.test.base should be removed from the libraries because it is provided - // on the bootclasspath and providing both increases start up cost unnecessarily. - PackageBuilder after = builder(); - - checkBackwardsCompatibility(before, after); - } - - @Test - public void in_bothLibraries() { - PackageBuilder before = builder() - .requiredLibraries(ANDROID_TEST_BASE) - .optionalLibraries(ANDROID_TEST_BASE); - - // android.test.base should be removed from the libraries because it is provided - // on the bootclasspath and providing both increases start up cost unnecessarily. - PackageBuilder after = builder(); - - checkBackwardsCompatibility(before, after); - } - - private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) { - // TODO(b/72538146) - Cannot use constructor reference here because it is also used in - // PackageBackwardCompatibility and that seems to create a package-private lambda in - // android.content.pm which this then tries to reuse but fails because it cannot access - // package-private classes/members because the test is loaded by a different ClassLoader - // than the lambda. - checkBackwardsCompatibility(before, after, - () -> new RemoveUnnecessaryAndroidTestBaseLibrary()); - } - -} diff --git a/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java b/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java deleted file mode 100644 index fc60980bb796..000000000000 --- a/core/tests/coretests/src/android/content/pm/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2018 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; - -import static android.content.pm.PackageBuilder.builder; -import static android.content.pm.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY; - -import android.content.pm.PackageBackwardCompatibility.RemoveUnnecessaryOrgApacheHttpLegacyLibrary; -import android.os.Build; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -/** - * Test for {@link RemoveUnnecessaryOrgApacheHttpLegacyLibrary} - */ -@SmallTest -@RunWith(JUnit4.class) -public class RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest - extends PackageSharedLibraryUpdaterTest { - - private static final String OTHER_LIBRARY = "other.library"; - - @Test - public void targeted_at_O() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.O); - - // No change required. - checkBackwardsCompatibility(before, before); - } - - @Test - public void targeted_at_O_not_empty_usesLibraries() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.O) - .requiredLibraries(OTHER_LIBRARY); - - // No change required. - checkBackwardsCompatibility(before, before); - } - - @Test - public void targeted_at_O_in_usesLibraries() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.O) - .requiredLibraries(ORG_APACHE_HTTP_LEGACY); - - // org.apache.http.legacy should be removed from the libraries because it is provided - // on the bootclasspath and providing both increases start up cost unnecessarily. - PackageBuilder after = builder() - .targetSdkVersion(Build.VERSION_CODES.O); - - checkBackwardsCompatibility(before, after); - } - - @Test - public void targeted_at_O_in_usesOptionalLibraries() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.O) - .optionalLibraries(ORG_APACHE_HTTP_LEGACY); - - // org.apache.http.legacy should be removed from the libraries because it is provided - // on the bootclasspath and providing both increases start up cost unnecessarily. - PackageBuilder after = builder() - .targetSdkVersion(Build.VERSION_CODES.O); - - checkBackwardsCompatibility(before, after); - } - - @Test - public void in_usesLibraries() { - PackageBuilder before = builder().requiredLibraries(ORG_APACHE_HTTP_LEGACY); - - // org.apache.http.legacy should be removed from the libraries because it is provided - // on the bootclasspath and providing both increases start up cost unnecessarily. - PackageBuilder after = builder(); - - checkBackwardsCompatibility(before, after); - } - - @Test - public void in_usesOptionalLibraries() { - PackageBuilder before = builder().optionalLibraries(ORG_APACHE_HTTP_LEGACY); - - // org.apache.http.legacy should be removed from the libraries because it is provided - // on the bootclasspath and providing both increases start up cost unnecessarily. - PackageBuilder after = builder(); - - checkBackwardsCompatibility(before, after); - } - - @Test - public void in_bothLibraries() { - PackageBuilder before = builder() - .requiredLibraries(ORG_APACHE_HTTP_LEGACY) - .optionalLibraries(ORG_APACHE_HTTP_LEGACY); - - // org.apache.http.legacy should be removed from the libraries because it is provided - // on the bootclasspath and providing both increases start up cost unnecessarily. - PackageBuilder after = builder(); - - checkBackwardsCompatibility(before, after); - } - - private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) { - // TODO(b/72538146) - Cannot use constructor reference here because it is also used in - // PackageBackwardCompatibility and that seems to create a package-private lambda in - // android.content.pm which this then tries to reuse but fails because it cannot access - // package-private classes/members because the test is loaded by a different ClassLoader - // than the lambda. - checkBackwardsCompatibility(before, after, - () -> new RemoveUnnecessaryOrgApacheHttpLegacyLibrary()); - } -} diff --git a/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java b/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java index 49849ee72a18..1e0bfb08693f 100644 --- a/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java +++ b/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java @@ -25,9 +25,9 @@ import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageParser; import android.content.pm.PackageParser.ApkLite; -import android.content.pm.PackageParser.Package; import android.content.pm.PackageParser.PackageLite; import android.content.pm.PackageParser.PackageParserException; +import android.content.pm.parsing.ParsedPackage; import android.os.FileUtils; import androidx.test.InstrumentationRegistry; @@ -36,7 +36,6 @@ import androidx.test.runner.AndroidJUnit4; import com.android.frameworks.coretests.R; -import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; @@ -95,13 +94,13 @@ public class DexMetadataHelperTest { public void testParsePackageWithDmFileValid() throws IOException, PackageParserException { copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base); createDexMetadataFile("install_split_base.apk"); - Package pkg = new PackageParser().parsePackage(mTmpDir, 0 /* flags */); + ParsedPackage pkg = new PackageParser().parseParsedPackage(mTmpDir, 0 /* flags */, false); Map<String, String> packageDexMetadata = DexMetadataHelper.getPackageDexMetadata(pkg); assertEquals(1, packageDexMetadata.size()); - String baseDexMetadata = packageDexMetadata.get(pkg.baseCodePath); + String baseDexMetadata = packageDexMetadata.get(pkg.getBaseCodePath()); assertNotNull(baseDexMetadata); - assertTrue(isDexMetadataForApk(baseDexMetadata, pkg.baseCodePath)); + assertTrue(isDexMetadataForApk(baseDexMetadata, pkg.getBaseCodePath())); } @Test @@ -111,17 +110,17 @@ public class DexMetadataHelperTest { copyApkToToTmpDir("install_split_feature_a.apk", R.raw.install_split_feature_a); createDexMetadataFile("install_split_base.apk"); createDexMetadataFile("install_split_feature_a.apk"); - Package pkg = new PackageParser().parsePackage(mTmpDir, 0 /* flags */); + ParsedPackage pkg = new PackageParser().parseParsedPackage(mTmpDir, 0 /* flags */, false); Map<String, String> packageDexMetadata = DexMetadataHelper.getPackageDexMetadata(pkg); assertEquals(2, packageDexMetadata.size()); - String baseDexMetadata = packageDexMetadata.get(pkg.baseCodePath); + String baseDexMetadata = packageDexMetadata.get(pkg.getBaseCodePath()); assertNotNull(baseDexMetadata); - assertTrue(isDexMetadataForApk(baseDexMetadata, pkg.baseCodePath)); + assertTrue(isDexMetadataForApk(baseDexMetadata, pkg.getBaseCodePath())); - String splitDexMetadata = packageDexMetadata.get(pkg.splitCodePaths[0]); + String splitDexMetadata = packageDexMetadata.get(pkg.getSplitCodePaths()[0]); assertNotNull(splitDexMetadata); - assertTrue(isDexMetadataForApk(splitDexMetadata, pkg.splitCodePaths[0])); + assertTrue(isDexMetadataForApk(splitDexMetadata, pkg.getSplitCodePaths()[0])); } @Test @@ -130,14 +129,14 @@ public class DexMetadataHelperTest { copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base); copyApkToToTmpDir("install_split_feature_a.apk", R.raw.install_split_feature_a); createDexMetadataFile("install_split_feature_a.apk"); - Package pkg = new PackageParser().parsePackage(mTmpDir, 0 /* flags */); + ParsedPackage pkg = new PackageParser().parseParsedPackage(mTmpDir, 0 /* flags */, false); Map<String, String> packageDexMetadata = DexMetadataHelper.getPackageDexMetadata(pkg); assertEquals(1, packageDexMetadata.size()); - String splitDexMetadata = packageDexMetadata.get(pkg.splitCodePaths[0]); + String splitDexMetadata = packageDexMetadata.get(pkg.getSplitCodePaths()[0]); assertNotNull(splitDexMetadata); - assertTrue(isDexMetadataForApk(splitDexMetadata, pkg.splitCodePaths[0])); + assertTrue(isDexMetadataForApk(splitDexMetadata, pkg.getSplitCodePaths()[0])); } @Test @@ -146,7 +145,8 @@ public class DexMetadataHelperTest { File invalidDmFile = new File(mTmpDir, "install_split_base.dm"); Files.createFile(invalidDmFile.toPath()); try { - PackageParser.Package pkg = new PackageParser().parsePackage(mTmpDir, 0 /* flags */); + ParsedPackage pkg = new PackageParser() + .parseParsedPackage(mTmpDir, 0 /* flags */, false); DexMetadataHelper.validatePackageDexMetadata(pkg); } catch (PackageParserException e) { assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA); @@ -163,7 +163,8 @@ public class DexMetadataHelperTest { Files.createFile(invalidDmFile.toPath()); try { - PackageParser.Package pkg = new PackageParser().parsePackage(mTmpDir, 0 /* flags */); + ParsedPackage pkg = new PackageParser() + .parseParsedPackage(mTmpDir, 0 /* flags */, false); DexMetadataHelper.validatePackageDexMetadata(pkg); } catch (PackageParserException e) { assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA); diff --git a/core/tests/coretests/src/android/content/pm/parsing/library/AndroidHidlUpdaterTest.java b/core/tests/coretests/src/android/content/pm/parsing/library/AndroidHidlUpdaterTest.java new file mode 100644 index 000000000000..21479c096752 --- /dev/null +++ b/core/tests/coretests/src/android/content/pm/parsing/library/AndroidHidlUpdaterTest.java @@ -0,0 +1,191 @@ +/* + * 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.library; + +import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_HIDL_BASE; +import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_HIDL_MANAGER; + +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.PackageImpl; +import android.content.pm.parsing.ParsedPackage; +import android.os.Build; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Test for {@link AndroidHidlUpdater} + */ +@SmallTest +@RunWith(JUnit4.class) +public class AndroidHidlUpdaterTest extends PackageSharedLibraryUpdaterTest { + + private static final String OTHER_LIBRARY = "other.library"; + + @Test + public void targeted_at_P() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.P) + .hideAsParsed(); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.P) + .hideAsParsed() + .hideAsFinal(); + + // no change, not system + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_P_system() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.P) + .hideAsParsed() + .setSystem(true); + + // Should add both HIDL libraries + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.P) + .addUsesLibrary(ANDROID_HIDL_MANAGER) + .addUsesLibrary(ANDROID_HIDL_BASE) + .hideAsParsed() + .setSystem(true) + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_P_not_empty_usesLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.P) + .addUsesLibrary(OTHER_LIBRARY) + .hideAsParsed(); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.P) + .addUsesLibrary(OTHER_LIBRARY) + .hideAsParsed() + .hideAsFinal(); + + // no change, not system + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_P_not_empty_usesLibraries_system() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.P) + .addUsesLibrary(OTHER_LIBRARY) + .hideAsParsed() + .setSystem(true); + + // The hidl jars should be added at the start of the list because it + // is not on the bootclasspath and the package targets pre-P. + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.P) + .addUsesLibrary(ANDROID_HIDL_MANAGER) + .addUsesLibrary(ANDROID_HIDL_BASE) + .addUsesLibrary(OTHER_LIBRARY) + .hideAsParsed() + .setSystem(true) + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_P_in_usesLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.P) + .addUsesLibrary(ANDROID_HIDL_MANAGER) + .addUsesLibrary(ANDROID_HIDL_BASE) + .hideAsParsed(); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.P) + .hideAsParsed() + .hideAsFinal(); + + // Libraries are removed because they are not available for non-system apps + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_P_in_usesLibraries_system() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.P) + .addUsesLibrary(ANDROID_HIDL_MANAGER) + .addUsesLibrary(ANDROID_HIDL_BASE) + .hideAsParsed() + .setSystem(true); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.P) + .addUsesLibrary(ANDROID_HIDL_MANAGER) + .addUsesLibrary(ANDROID_HIDL_BASE) + .hideAsParsed() + .setSystem(true) + .hideAsFinal(); + + // No change is required because the package explicitly requests the HIDL libraries + // and is targeted at the current version so does not need backwards compatibility. + checkBackwardsCompatibility(before, after); + } + + @Test + public void in_usesLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesLibrary(ANDROID_HIDL_BASE) + .hideAsParsed(); + + // Dependency is removed, it is not available. + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .hideAsParsed() + .hideAsFinal(); + + // Libraries are removed because they are not available for apps targeting Q+ + checkBackwardsCompatibility(before, after); + } + + @Test + public void in_usesOptionalLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesOptionalLibrary(ANDROID_HIDL_BASE) + .hideAsParsed(); + + // Dependency is removed, it is not available. + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .hideAsParsed() + .hideAsFinal(); + + // Libraries are removed because they are not available for apps targeting Q+ + checkBackwardsCompatibility(before, after); + } + + private void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after) { + checkBackwardsCompatibility(before, after, AndroidHidlUpdater::new); + } +} diff --git a/core/tests/coretests/src/android/content/pm/parsing/library/AndroidTestBaseUpdaterTest.java b/core/tests/coretests/src/android/content/pm/parsing/library/AndroidTestBaseUpdaterTest.java new file mode 100644 index 000000000000..65ae219058f4 --- /dev/null +++ b/core/tests/coretests/src/android/content/pm/parsing/library/AndroidTestBaseUpdaterTest.java @@ -0,0 +1,152 @@ +/* + * 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.library; + +import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_BASE; + +import android.content.pm.OptionalClassRunner; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.PackageImpl; +import android.content.pm.parsing.ParsedPackage; +import android.os.Build; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Test for {@link AndroidTestBaseUpdater} + */ +@SmallTest +@RunWith(OptionalClassRunner.class) +@OptionalClassRunner.OptionalClass("android.content.pm.parsing.library.AndroidTestBaseUpdater") +public class AndroidTestBaseUpdaterTest extends PackageSharedLibraryUpdaterTest { + + private static final String OTHER_LIBRARY = "other.library"; + + @Test + public void targeted_at_Q() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.Q) + .hideAsParsed(); + + // Should add org.apache.http.legacy. + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.Q) + .addUsesLibrary(ANDROID_TEST_BASE) + .hideAsParsed() + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_Q_not_empty_usesLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.Q) + .addUsesLibrary(OTHER_LIBRARY) + .hideAsParsed(); + + // The org.apache.http.legacy jar should be added at the start of the list because it + // is not on the bootclasspath and the package targets pre-Q. + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.Q) + .addUsesLibrary(ANDROID_TEST_BASE) + .addUsesLibrary(OTHER_LIBRARY) + .hideAsParsed() + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_Q_in_usesLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.Q) + .addUsesLibrary(ANDROID_TEST_BASE) + .hideAsParsed(); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.Q) + .addUsesLibrary(ANDROID_TEST_BASE) + .hideAsParsed() + .hideAsFinal(); + + // No change is required because although org.apache.http.legacy has been removed from + // the bootclasspath the package explicitly requests it. + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_Q_in_usesOptionalLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.Q) + .addUsesOptionalLibrary(ANDROID_TEST_BASE) + .hideAsParsed(); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.Q) + .addUsesOptionalLibrary(ANDROID_TEST_BASE) + .hideAsParsed() + .hideAsFinal(); + + // No change is required because although org.apache.http.legacy has been removed from + // the bootclasspath the package explicitly requests it. + checkBackwardsCompatibility(before, after); + } + + @Test + public void in_usesLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesLibrary(ANDROID_TEST_BASE) + .hideAsParsed(); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesLibrary(ANDROID_TEST_BASE) + .hideAsParsed() + .hideAsFinal(); + + // No change is required because the package explicitly requests org.apache.http.legacy + // and is targeted at the current version so does not need backwards compatibility. + checkBackwardsCompatibility(before, after); + } + + @Test + public void in_usesOptionalLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesOptionalLibrary(ANDROID_TEST_BASE) + .hideAsParsed(); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesOptionalLibrary(ANDROID_TEST_BASE) + .hideAsParsed() + .hideAsFinal(); + + // No change is required because the package explicitly requests org.apache.http.legacy + // and is targeted at the current version so does not need backwards compatibility. + checkBackwardsCompatibility(before, after); + } + + private void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after) { + checkBackwardsCompatibility(before, after, AndroidTestBaseUpdater::new); + } +} diff --git a/core/tests/coretests/src/android/content/pm/parsing/library/AndroidTestRunnerSplitUpdaterTest.java b/core/tests/coretests/src/android/content/pm/parsing/library/AndroidTestRunnerSplitUpdaterTest.java new file mode 100644 index 000000000000..38755b9aa965 --- /dev/null +++ b/core/tests/coretests/src/android/content/pm/parsing/library/AndroidTestRunnerSplitUpdaterTest.java @@ -0,0 +1,79 @@ +/* + * 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.library; + +import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_MOCK; +import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_RUNNER; + +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.PackageImpl; +import android.content.pm.parsing.ParsedPackage; +import android.content.pm.parsing.library.PackageBackwardCompatibility.AndroidTestRunnerSplitUpdater; +import android.os.Build; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Test for {@link AndroidTestRunnerSplitUpdater} + */ +@SmallTest +@RunWith(JUnit4.class) +public class AndroidTestRunnerSplitUpdaterTest extends PackageSharedLibraryUpdaterTest { + + @Test + public void android_test_runner_in_usesOptionalLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesOptionalLibrary(ANDROID_TEST_RUNNER) + .hideAsParsed(); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesOptionalLibrary(ANDROID_TEST_MOCK) + .addUsesOptionalLibrary(ANDROID_TEST_RUNNER) + .hideAsParsed() + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void android_test_runner_in_usesLibraries_android_test_mock_in_usesOptionalLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesLibrary(ANDROID_TEST_RUNNER) + .addUsesOptionalLibrary(ANDROID_TEST_MOCK) + .hideAsParsed(); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesLibrary(ANDROID_TEST_RUNNER) + .addUsesOptionalLibrary(ANDROID_TEST_MOCK) + .hideAsParsed() + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + private void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after) { + checkBackwardsCompatibility(before, after, AndroidTestRunnerSplitUpdater::new); + } +} diff --git a/core/tests/coretests/src/android/content/pm/parsing/library/OrgApacheHttpLegacyUpdaterTest.java b/core/tests/coretests/src/android/content/pm/parsing/library/OrgApacheHttpLegacyUpdaterTest.java new file mode 100644 index 000000000000..4c7899b47164 --- /dev/null +++ b/core/tests/coretests/src/android/content/pm/parsing/library/OrgApacheHttpLegacyUpdaterTest.java @@ -0,0 +1,152 @@ +/* + * 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.library; + +import static android.content.pm.parsing.library.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY; + +import android.content.pm.OptionalClassRunner; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.PackageImpl; +import android.content.pm.parsing.ParsedPackage; +import android.os.Build; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Test for {@link OrgApacheHttpLegacyUpdater} + */ +@SmallTest +@RunWith(OptionalClassRunner.class) +@OptionalClassRunner.OptionalClass("android.content.pm.parsing.library.OrgApacheHttpLegacyUpdater") +public class OrgApacheHttpLegacyUpdaterTest extends PackageSharedLibraryUpdaterTest { + + private static final String OTHER_LIBRARY = "other.library"; + + @Test + public void targeted_at_O() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .hideAsParsed(); + + // Should add org.apache.http.legacy. + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .addUsesLibrary(ORG_APACHE_HTTP_LEGACY) + .hideAsParsed() + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_O_not_empty_usesLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .addUsesLibrary(OTHER_LIBRARY) + .hideAsParsed(); + + // The org.apache.http.legacy jar should be added at the start of the list because it + // is not on the bootclasspath and the package targets pre-P. + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .addUsesLibrary(ORG_APACHE_HTTP_LEGACY) + .addUsesLibrary(OTHER_LIBRARY) + .hideAsParsed() + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_O_in_usesLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .addUsesLibrary(ORG_APACHE_HTTP_LEGACY) + .hideAsParsed(); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .addUsesLibrary(ORG_APACHE_HTTP_LEGACY) + .hideAsParsed() + .hideAsFinal(); + + // No change is required because although org.apache.http.legacy has been removed from + // the bootclasspath the package explicitly requests it. + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_O_in_usesOptionalLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .addUsesOptionalLibrary(ORG_APACHE_HTTP_LEGACY) + .hideAsParsed(); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .addUsesOptionalLibrary(ORG_APACHE_HTTP_LEGACY) + .hideAsParsed() + .hideAsFinal(); + + // No change is required because although org.apache.http.legacy has been removed from + // the bootclasspath the package explicitly requests it. + checkBackwardsCompatibility(before, after); + } + + @Test + public void in_usesLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesLibrary(ORG_APACHE_HTTP_LEGACY) + .hideAsParsed(); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesLibrary(ORG_APACHE_HTTP_LEGACY) + .hideAsParsed() + .hideAsFinal(); + + // No change is required because the package explicitly requests org.apache.http.legacy + // and is targeted at the current version so does not need backwards compatibility. + checkBackwardsCompatibility(before, after); + } + + @Test + public void in_usesOptionalLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesOptionalLibrary(ORG_APACHE_HTTP_LEGACY) + .hideAsParsed(); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesOptionalLibrary(ORG_APACHE_HTTP_LEGACY) + .hideAsParsed() + .hideAsFinal(); + + // No change is required because the package explicitly requests org.apache.http.legacy + // and is targeted at the current version so does not need backwards compatibility. + checkBackwardsCompatibility(before, after); + } + + private void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after) { + checkBackwardsCompatibility(before, after, OrgApacheHttpLegacyUpdater::new); + } +} diff --git a/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java b/core/tests/coretests/src/android/content/pm/parsing/library/PackageBackwardCompatibilityTest.java index ad9814bd01b1..00d468de4ee4 100644 --- a/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java +++ b/core/tests/coretests/src/android/content/pm/parsing/library/PackageBackwardCompatibilityTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * 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. @@ -14,15 +14,18 @@ * limitations under the License. */ -package android.content.pm; +package android.content.pm.parsing.library; -import static android.content.pm.PackageBuilder.builder; -import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE; -import static android.content.pm.SharedLibraryNames.ANDROID_TEST_MOCK; -import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER; -import static android.content.pm.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY; +import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_BASE; +import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_MOCK; +import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_RUNNER; +import static android.content.pm.parsing.library.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY; -import android.content.pm.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.PackageImpl; +import android.content.pm.parsing.ParsedPackage; +import android.content.pm.parsing.ParsingPackage; +import android.content.pm.parsing.library.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary; import android.os.Build; import androidx.test.filters.SmallTest; @@ -32,17 +35,20 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; -import java.util.ArrayList; -import java.util.List; - @SmallTest @RunWith(JUnit4.class) public class PackageBackwardCompatibilityTest extends PackageSharedLibraryUpdaterTest { @Test public void null_usesLibraries_and_usesOptionalLibraries() { - PackageBuilder before = builder(); - PackageBuilder after = builder(); + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .hideAsParsed(); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .hideAsParsed() + .hideAsFinal(); checkBackwardsCompatibility(before, after); } @@ -68,20 +74,21 @@ public class PackageBackwardCompatibilityTest extends PackageSharedLibraryUpdate */ @Test public void targeted_at_O() { - PackageBuilder before = builder() - .targetSdkVersion(Build.VERSION_CODES.O); + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .hideAsParsed(); + + ParsingPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .setTargetSdkVersion(Build.VERSION_CODES.O); - List<String> expected = new ArrayList<>(); if (!PackageBackwardCompatibility.bootClassPathContainsATB()) { - expected.add(ANDROID_TEST_BASE); + after.addUsesLibrary(ANDROID_TEST_BASE); } - expected.add(ORG_APACHE_HTTP_LEGACY); - - PackageBuilder after = builder() - .targetSdkVersion(Build.VERSION_CODES.O) - .requiredLibraries(expected); + after.addUsesLibrary(ORG_APACHE_HTTP_LEGACY); - checkBackwardsCompatibility(before, after); + checkBackwardsCompatibility(before, after.hideAsParsed().hideAsFinal()); } /** @@ -98,12 +105,17 @@ public class PackageBackwardCompatibilityTest extends PackageSharedLibraryUpdate + ANDROID_TEST_BASE + " is on the bootclasspath", PackageBackwardCompatibility.bootClassPathContainsATB()); - PackageBuilder before = builder() - .requiredLibraries(ANDROID_TEST_BASE); + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesLibrary(ANDROID_TEST_BASE) + .hideAsParsed(); // android.test.base should be removed from the libraries because it is provided // on the bootclasspath and providing both increases start up cost unnecessarily. - PackageBuilder after = builder(); + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .hideAsParsed() + .hideAsFinal(); checkBackwardsCompatibility(before, after); } @@ -117,22 +129,23 @@ public class PackageBackwardCompatibilityTest extends PackageSharedLibraryUpdate */ @Test public void android_test_runner_in_usesLibraries() { - PackageBuilder before = builder().requiredLibraries(ANDROID_TEST_RUNNER); + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesLibrary(ANDROID_TEST_RUNNER) + .hideAsParsed(); - List<String> expected = new ArrayList<>(); + ParsingPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT); if (!PackageBackwardCompatibility.bootClassPathContainsATB()) { - expected.add(ANDROID_TEST_BASE); + after.addUsesLibrary(ANDROID_TEST_BASE); } - expected.add(ANDROID_TEST_MOCK); - expected.add(ANDROID_TEST_RUNNER); - - PackageBuilder after = builder() - .requiredLibraries(expected); + after.addUsesLibrary(ANDROID_TEST_MOCK); + after.addUsesLibrary(ANDROID_TEST_RUNNER); - checkBackwardsCompatibility(before, after); + checkBackwardsCompatibility(before, after.hideAsParsed().hideAsFinal()); } - private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) { + private void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after) { checkBackwardsCompatibility(before, after, PackageBackwardCompatibility::getInstance); } } diff --git a/core/tests/coretests/src/android/content/pm/parsing/library/PackageSharedLibraryUpdaterTest.java b/core/tests/coretests/src/android/content/pm/parsing/library/PackageSharedLibraryUpdaterTest.java new file mode 100644 index 000000000000..e7a80e1a7618 --- /dev/null +++ b/core/tests/coretests/src/android/content/pm/parsing/library/PackageSharedLibraryUpdaterTest.java @@ -0,0 +1,50 @@ +/* + * 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.library; + +import static org.junit.Assert.assertEquals; + +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.ParsedPackage; + +import java.util.function.Supplier; + +/** + * Helper for classes that test {@link PackageSharedLibraryUpdater}. + */ +abstract class PackageSharedLibraryUpdaterTest { + + protected static final String PACKAGE_NAME = "org.package.name"; + + static void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after, + Supplier<PackageSharedLibraryUpdater> updaterSupplier) { + updaterSupplier.get().updatePackage(before); + check(before.hideAsFinal(), after); + } + + private static void check(AndroidPackage before, AndroidPackage after) { + assertEquals("targetSdkVersion should not be changed", + after.getTargetSdkVersion(), + before.getTargetSdkVersion()); + assertEquals("usesLibraries not updated correctly", + after.getUsesLibraries(), + before.getUsesLibraries()); + assertEquals("usesOptionalLibraries not updated correctly", + after.getUsesOptionalLibraries(), + before.getUsesOptionalLibraries()); + } +} diff --git a/core/tests/coretests/src/android/content/pm/parsing/library/RemoveUnnecessaryAndroidTestBaseLibraryTest.java b/core/tests/coretests/src/android/content/pm/parsing/library/RemoveUnnecessaryAndroidTestBaseLibraryTest.java new file mode 100644 index 000000000000..fd3ba2bd0c68 --- /dev/null +++ b/core/tests/coretests/src/android/content/pm/parsing/library/RemoveUnnecessaryAndroidTestBaseLibraryTest.java @@ -0,0 +1,169 @@ +/* + * 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.library; + +import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_BASE; + +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.PackageImpl; +import android.content.pm.parsing.ParsedPackage; +import android.content.pm.parsing.library.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary; +import android.os.Build; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Test for {@link RemoveUnnecessaryAndroidTestBaseLibrary} + */ +@SmallTest +@RunWith(JUnit4.class) +public class RemoveUnnecessaryAndroidTestBaseLibraryTest + extends PackageSharedLibraryUpdaterTest { + + private static final String OTHER_LIBRARY = "other.library"; + + @Test + public void targeted_at_O() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .hideAsParsed(); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .hideAsParsed() + .hideAsFinal(); + + // No change required. + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_O_not_empty_usesLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .addUsesLibrary(OTHER_LIBRARY) + .hideAsParsed(); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .addUsesLibrary(OTHER_LIBRARY) + .hideAsParsed() + .hideAsFinal(); + + // No change required. + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_O_in_usesLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .addUsesLibrary(ANDROID_TEST_BASE) + .hideAsParsed(); + + // android.test.base should be removed from the libraries because it is provided + // on the bootclasspath and providing both increases start up cost unnecessarily. + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .hideAsParsed() + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_O_in_usesOptionalLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .addUsesOptionalLibrary(ANDROID_TEST_BASE) + .hideAsParsed(); + + // android.test.base should be removed from the libraries because it is provided + // on the bootclasspath and providing both increases start up cost unnecessarily. + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .hideAsParsed() + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void in_usesLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .addUsesLibrary(ANDROID_TEST_BASE) + .hideAsParsed(); + + // android.test.base should be removed from the libraries because it is provided + // on the bootclasspath and providing both increases start up cost unnecessarily. + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .hideAsParsed() + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void in_usesOptionalLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesOptionalLibrary(ANDROID_TEST_BASE) + .hideAsParsed(); + + // android.test.base should be removed from the libraries because it is provided + // on the bootclasspath and providing both increases start up cost unnecessarily. + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .hideAsParsed() + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void in_bothLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesLibrary(ANDROID_TEST_BASE) + .addUsesOptionalLibrary(ANDROID_TEST_BASE) + .hideAsParsed(); + + // android.test.base should be removed from the libraries because it is provided + // on the bootclasspath and providing both increases start up cost unnecessarily. + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .hideAsParsed() + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + private void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after) { + // TODO(b/72538146) - Cannot use constructor reference here because it is also used in + // PackageBackwardCompatibility and that seems to create a package-private lambda in + // android.content.pm which this then tries to reuse but fails because it cannot access + // package-private classes/members because the test is loaded by a different ClassLoader + // than the lambda. + checkBackwardsCompatibility(before, after, + () -> new RemoveUnnecessaryAndroidTestBaseLibrary()); + } + +} diff --git a/core/tests/coretests/src/android/content/pm/parsing/library/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java b/core/tests/coretests/src/android/content/pm/parsing/library/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java new file mode 100644 index 000000000000..d3494d93ae52 --- /dev/null +++ b/core/tests/coretests/src/android/content/pm/parsing/library/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java @@ -0,0 +1,168 @@ +/* + * 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.library; + +import static android.content.pm.parsing.library.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY; + +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.PackageImpl; +import android.content.pm.parsing.ParsedPackage; +import android.content.pm.parsing.library.PackageBackwardCompatibility.RemoveUnnecessaryOrgApacheHttpLegacyLibrary; +import android.os.Build; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Test for {@link RemoveUnnecessaryOrgApacheHttpLegacyLibrary} + */ +@SmallTest +@RunWith(JUnit4.class) +public class RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest + extends PackageSharedLibraryUpdaterTest { + + private static final String OTHER_LIBRARY = "other.library"; + + @Test + public void targeted_at_O() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .hideAsParsed(); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .hideAsParsed() + .hideAsFinal(); + + // No change required. + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_O_not_empty_usesLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .addUsesLibrary(OTHER_LIBRARY) + .hideAsParsed(); + + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .addUsesLibrary(OTHER_LIBRARY) + .hideAsParsed() + .hideAsFinal(); + + // No change required. + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_O_in_usesLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .addUsesLibrary(ORG_APACHE_HTTP_LEGACY) + .hideAsParsed(); + + // org.apache.http.legacy should be removed from the libraries because it is provided + // on the bootclasspath and providing both increases start up cost unnecessarily. + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .hideAsParsed() + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void targeted_at_O_in_usesOptionalLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .addUsesOptionalLibrary(ORG_APACHE_HTTP_LEGACY) + .hideAsParsed(); + + // org.apache.http.legacy should be removed from the libraries because it is provided + // on the bootclasspath and providing both increases start up cost unnecessarily. + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.O) + .hideAsParsed() + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void in_usesLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesLibrary(ORG_APACHE_HTTP_LEGACY) + .hideAsParsed(); + + // org.apache.http.legacy should be removed from the libraries because it is provided + // on the bootclasspath and providing both increases start up cost unnecessarily. + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .hideAsParsed() + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void in_usesOptionalLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesOptionalLibrary(ORG_APACHE_HTTP_LEGACY) + .hideAsParsed(); + + // org.apache.http.legacy should be removed from the libraries because it is provided + // on the bootclasspath and providing both increases start up cost unnecessarily. + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .hideAsParsed() + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + @Test + public void in_bothLibraries() { + ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .addUsesLibrary(ORG_APACHE_HTTP_LEGACY) + .addUsesOptionalLibrary(ORG_APACHE_HTTP_LEGACY) + .hideAsParsed(); + + // org.apache.http.legacy should be removed from the libraries because it is provided + // on the bootclasspath and providing both increases start up cost unnecessarily. + AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME) + .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT) + .hideAsParsed() + .hideAsFinal(); + + checkBackwardsCompatibility(before, after); + } + + private void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after) { + // TODO(b/72538146) - Cannot use constructor reference here because it is also used in + // PackageBackwardCompatibility and that seems to create a package-private lambda in + // android.content.pm which this then tries to reuse but fails because it cannot access + // package-private classes/members because the test is loaded by a different ClassLoader + // than the lambda. + checkBackwardsCompatibility(before, after, + () -> new RemoveUnnecessaryOrgApacheHttpLegacyLibrary()); + } +} diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java index de6cca520e65..21f5f899e75c 100644 --- a/services/core/java/android/content/pm/PackageManagerInternal.java +++ b/services/core/java/android/content/pm/PackageManagerInternal.java @@ -29,6 +29,8 @@ import android.content.pm.PackageManager.ApplicationInfoFlags; import android.content.pm.PackageManager.ComponentInfoFlags; import android.content.pm.PackageManager.PackageInfoFlags; import android.content.pm.PackageManager.ResolveInfoFlags; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.ComponentParseUtils; import android.os.Bundle; import android.os.PersistableBundle; import android.util.ArraySet; @@ -326,7 +328,7 @@ public abstract class PackageManagerInternal { * @param installed the new installed state * @return true if the installed state changed as a result */ - public abstract boolean setInstalled(PackageParser.Package pkg, + public abstract boolean setInstalled(AndroidPackage pkg, @UserIdInt int userId, boolean installed); /** @@ -405,7 +407,7 @@ public abstract class PackageManagerInternal { * Returns whether or not the given package represents a legacy system application released * prior to runtime permissions. */ - public abstract boolean isLegacySystemApp(PackageParser.Package pkg); + public abstract boolean isLegacySystemApp(AndroidPackage pkg); /** * Get all overlay packages for a user. @@ -497,13 +499,17 @@ public abstract class PackageManagerInternal { /** * Returns a package object for the given package name. */ - public abstract @Nullable PackageParser.Package getPackage(@NonNull String packageName); + public abstract @Nullable AndroidPackage getPackage(@NonNull String packageName); + + // TODO(b/135203078): PackageSetting can't be referenced directly. Should move to a server side + // internal PM which is aware of PS. + public abstract @Nullable Object getPackageSetting(String packageName); /** * Returns a package for the given UID. If the UID is part of a shared user ID, one * of the packages will be chosen to be returned. */ - public abstract @Nullable PackageParser.Package getPackage(int uid); + public abstract @Nullable AndroidPackage getPackage(int uid); /** * Returns a list without a change observer. @@ -534,17 +540,19 @@ public abstract class PackageManagerInternal { */ public abstract void removePackageListObserver(@NonNull PackageListObserver observer); + // TODO(b/135203078): PackageSetting can't be referenced directly /** * Returns a package object for the disabled system package name. */ - public abstract @Nullable PackageParser.Package getDisabledSystemPackage( - @NonNull String packageName); + public abstract @Nullable Object getDisabledSystemPackage(@NonNull String packageName); /** * Returns the package name for the disabled system package. * * This is equivalent to - * {@link #getDisabledSystemPackage(String)}.{@link PackageParser.Package#packageName} + * {@link #getDisabledSystemPackage(String)} + * .{@link com.android.server.pm.PackageSetting#pkg} + * .{@link AndroidPackage#getPackageName()} */ public abstract @Nullable String getDisabledSystemPackageName(@NonNull String packageName); @@ -579,7 +587,7 @@ public abstract class PackageManagerInternal { * @see #canAccessInstantApps */ public abstract boolean filterAppAccess( - @NonNull PackageParser.Package pkg, int callingUid, int userId); + @NonNull AndroidPackage pkg, int callingUid, int userId); /** * Returns whether or not access to the application should be filtered. @@ -653,7 +661,8 @@ public abstract class PackageManagerInternal { throws IOException; /** Returns {@code true} if the specified component is enabled and matches the given flags. */ - public abstract boolean isEnabledAndMatches(@NonNull ComponentInfo info, int flags, int userId); + public abstract boolean isEnabledAndMatches( + @NonNull ComponentParseUtils.ParsedComponent component, int flags, int userId); /** Returns {@code true} if the given user requires extra badging for icons. */ public abstract boolean userNeedsBadging(int userId); @@ -664,14 +673,14 @@ public abstract class PackageManagerInternal { * * @param actionLocked action to be performed */ - public abstract void forEachPackage(Consumer<PackageParser.Package> actionLocked); + public abstract void forEachPackage(Consumer<AndroidPackage> actionLocked); /** * Perform the given action for each installed package for a user. * Note that packages lock will be held while performin the actions. */ public abstract void forEachInstalledPackage( - @NonNull Consumer<PackageParser.Package> actionLocked, @UserIdInt int userId); + @NonNull Consumer<AndroidPackage> actionLocked, @UserIdInt int userId); /** Returns the list of enabled components */ public abstract ArraySet<String> getEnabledComponents(String packageName, int userId); @@ -806,7 +815,7 @@ public abstract class PackageManagerInternal { * Otherwise, {@code false}. */ public abstract boolean isCallerInstallerOfRecord( - @NonNull PackageParser.Package pkg, int callingUid); + @NonNull AndroidPackage pkg, int callingUid); /** Returns whether or not default runtime permissions are granted for the given user */ public abstract boolean areDefaultRuntimePermissionsGranted(@UserIdInt int userId); diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java index 14ef2d3a38e1..be548a23e709 100644 --- a/services/core/java/com/android/server/pm/AppsFilter.java +++ b/services/core/java/com/android/server/pm/AppsFilter.java @@ -26,8 +26,11 @@ import android.annotation.Nullable; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; -import android.content.pm.PackageParser; -import android.content.pm.ProviderInfo; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.ComponentParseUtils; +import android.content.pm.parsing.ComponentParseUtils.ParsedComponent; +import android.content.pm.parsing.ComponentParseUtils.ParsedIntentInfo; +import android.content.pm.parsing.ComponentParseUtils.ParsedProvider; import android.net.Uri; import android.os.Process; import android.os.Trace; diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java index b1eb7e79bc1b..591f7497c890 100644 --- a/services/core/java/com/android/server/pm/ComponentResolver.java +++ b/services/core/java/com/android/server/pm/ComponentResolver.java @@ -21,7 +21,6 @@ import static android.content.pm.PackageManagerInternal.PACKAGE_SETUP_WIZARD; import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING; import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE; -import static com.android.server.pm.PackageManagerService.fixProcessName; import android.annotation.Nullable; import android.content.ComponentName; @@ -33,13 +32,18 @@ import android.content.pm.AuxiliaryResolveInfo; import android.content.pm.InstantAppResolveInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; -import android.content.pm.PackageParser; -import android.content.pm.PackageParser.ActivityIntentInfo; -import android.content.pm.PackageParser.ServiceIntentInfo; import android.content.pm.PackageUserState; import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.ComponentParseUtils.ParsedActivity; +import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo; +import android.content.pm.parsing.ComponentParseUtils.ParsedProvider; +import android.content.pm.parsing.ComponentParseUtils.ParsedProviderIntentInfo; +import android.content.pm.parsing.ComponentParseUtils.ParsedService; +import android.content.pm.parsing.ComponentParseUtils.ParsedServiceIntentInfo; +import android.content.pm.parsing.PackageInfoUtils; import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; @@ -55,11 +59,14 @@ import com.android.server.IntentResolver; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; +import java.util.function.Function; /** Resolves all Android component types [activities, services, providers and receivers]. */ public class ComponentResolver { @@ -160,7 +167,7 @@ public class ComponentResolver { /** All available receivers, for your resolving pleasure. */ @GuardedBy("mLock") - private final ActivityIntentResolver mReceivers = new ActivityIntentResolver(); + private final ActivityIntentResolver mReceivers = new ReceiverIntentResolver(); /** All available services, for your resolving pleasure. */ @GuardedBy("mLock") @@ -168,7 +175,7 @@ public class ComponentResolver { /** Mapping from provider authority [first directory in content URI codePath) to provider. */ @GuardedBy("mLock") - private final ArrayMap<String, PackageParser.Provider> mProvidersByAuthority = new ArrayMap<>(); + private final ArrayMap<String, ParsedProvider> mProvidersByAuthority = new ArrayMap<>(); /** Whether or not processing protected filters should be deferred. */ private boolean mDeferProtectedFilters = true; @@ -183,7 +190,7 @@ public class ComponentResolver { * /system partition in order to know which component is the setup wizard. This can * only ever be non-empty if {@link #mDeferProtectedFilters} is {@code true}. */ - private List<PackageParser.ActivityIntentInfo> mProtectedFilters; + private List<ParsedActivityIntentInfo> mProtectedFilters; ComponentResolver(UserManagerService userManager, PackageManagerInternal packageManagerInternal, @@ -194,28 +201,28 @@ public class ComponentResolver { } /** Returns the given activity */ - PackageParser.Activity getActivity(ComponentName component) { + ParsedActivity getActivity(ComponentName component) { synchronized (mLock) { return mActivities.mActivities.get(component); } } /** Returns the given provider */ - PackageParser.Provider getProvider(ComponentName component) { + ParsedProvider getProvider(ComponentName component) { synchronized (mLock) { return mProviders.mProviders.get(component); } } /** Returns the given receiver */ - PackageParser.Activity getReceiver(ComponentName component) { + ParsedActivity getReceiver(ComponentName component) { synchronized (mLock) { return mReceivers.mActivities.get(component); } } /** Returns the given service */ - PackageParser.Service getService(ComponentName component) { + ParsedService getService(ComponentName component) { synchronized (mLock) { return mServices.mServices.get(component); } @@ -230,7 +237,7 @@ public class ComponentResolver { @Nullable List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags, - List<PackageParser.Activity> activities, int userId) { + List<ParsedActivity> activities, int userId) { synchronized (mLock) { return mActivities.queryIntentForPackage( intent, resolvedType, flags, activities, userId); @@ -246,7 +253,7 @@ public class ComponentResolver { @Nullable List<ResolveInfo> queryProviders(Intent intent, String resolvedType, int flags, - List<PackageParser.Provider> providers, int userId) { + List<ParsedProvider> providers, int userId) { synchronized (mLock) { return mProviders.queryIntentForPackage(intent, resolvedType, flags, providers, userId); } @@ -261,25 +268,34 @@ public class ComponentResolver { List<ProviderInfo> providerList = null; synchronized (mLock) { for (int i = mProviders.mProviders.size() - 1; i >= 0; --i) { - final PackageParser.Provider p = mProviders.mProviders.valueAt(i); - final PackageSetting ps = (PackageSetting) p.owner.mExtras; + final ParsedProvider p = mProviders.mProviders.valueAt(i); + if (p.getAuthority() == null) { + continue; + } + + final PackageSetting ps = + (PackageSetting) sPackageManagerInternal.getPackageSetting( + p.getPackageName()); if (ps == null) { continue; } - if (p.info.authority == null) { + + AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName()); + if (pkg == null) { continue; } - if (processName != null && (!p.info.processName.equals(processName) - || !UserHandle.isSameApp(p.info.applicationInfo.uid, uid))) { + + if (processName != null && (!p.getProcessName().equals(processName) + || !UserHandle.isSameApp(pkg.getUid(), uid))) { continue; } // See PM.queryContentProviders()'s javadoc for why we have the metaData parameter. if (metaDataKey != null - && (p.metaData == null || !p.metaData.containsKey(metaDataKey))) { + && (p.getMetaData() == null || !p.getMetaData().containsKey(metaDataKey))) { continue; } - final ProviderInfo info = PackageParser.generateProviderInfo( - p, flags, ps.readUserState(userId), userId); + final ProviderInfo info = PackageInfoUtils.generateProviderInfo( + pkg, p, flags, ps.readUserState(userId), userId); if (info == null) { continue; } @@ -295,15 +311,21 @@ public class ComponentResolver { @Nullable ProviderInfo queryProvider(String authority, int flags, int userId) { synchronized (mLock) { - final PackageParser.Provider p = mProvidersByAuthority.get(authority); + final ParsedProvider p = mProvidersByAuthority.get(authority); if (p == null) { return null; } - final PackageSetting ps = (PackageSetting) p.owner.mExtras; + final PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting( + p.getPackageName()); if (ps == null) { return null; } - return PackageParser.generateProviderInfo(p, flags, ps.readUserState(userId), userId); + final AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName()); + if (pkg == null) { + return null; + } + return PackageInfoUtils.generateProviderInfo(pkg, p, flags, + ps.readUserState(userId), userId); } } @@ -311,20 +333,29 @@ public class ComponentResolver { int userId) { synchronized (mLock) { for (int i = mProvidersByAuthority.size() - 1; i >= 0; --i) { - final PackageParser.Provider p = mProvidersByAuthority.valueAt(i); - final PackageSetting ps = (PackageSetting) p.owner.mExtras; + final ParsedProvider p = mProvidersByAuthority.valueAt(i); + if (!p.isSyncable()) { + continue; + } + + final PackageSetting ps = + (PackageSetting) sPackageManagerInternal.getPackageSetting( + p.getPackageName()); if (ps == null) { continue; } - if (!p.syncable) { + + final AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName()); + if (pkg == null) { continue; } - if (safeMode - && (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { + + if (safeMode && (pkg.getFlags() & ApplicationInfo.FLAG_SYSTEM) == 0) { continue; } final ProviderInfo info = - PackageParser.generateProviderInfo(p, 0, ps.readUserState(userId), userId); + PackageInfoUtils.generateProviderInfo(pkg, p, 0, + ps.readUserState(userId), userId); if (info == null) { continue; } @@ -343,7 +374,7 @@ public class ComponentResolver { @Nullable List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, int flags, - List<PackageParser.Activity> receivers, int userId) { + List<ParsedActivity> receivers, int userId) { synchronized (mLock) { return mReceivers.queryIntentForPackage(intent, resolvedType, flags, receivers, userId); } @@ -358,7 +389,7 @@ public class ComponentResolver { @Nullable List<ResolveInfo> queryServices(Intent intent, String resolvedType, int flags, - List<PackageParser.Service> services, int userId) { + List<ParsedService> services, int userId) { synchronized (mLock) { return mServices.queryIntentForPackage(intent, resolvedType, flags, services, userId); } @@ -372,15 +403,15 @@ public class ComponentResolver { } /** Asserts none of the providers defined in the given package haven't already been defined. */ - void assertProvidersNotDefined(PackageParser.Package pkg) throws PackageManagerException { + void assertProvidersNotDefined(AndroidPackage pkg) throws PackageManagerException { synchronized (mLock) { assertProvidersNotDefinedLocked(pkg); } } /** Add all components defined in the given package to the internal structures. */ - void addAllComponents(PackageParser.Package pkg, boolean chatty) { - final ArrayList<PackageParser.ActivityIntentInfo> newIntents = new ArrayList<>(); + void addAllComponents(AndroidPackage pkg, boolean chatty) { + final ArrayList<ParsedActivityIntentInfo> newIntents = new ArrayList<>(); synchronized (mLock) { addActivitiesLocked(pkg, newIntents, chatty); addReceiversLocked(pkg, chatty); @@ -393,17 +424,19 @@ public class ComponentResolver { PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM)); for (int i = newIntents.size() - 1; i >= 0; --i) { - final PackageParser.ActivityIntentInfo intentInfo = newIntents.get(i); - final PackageParser.Package disabledPkg = sPackageManagerInternal - .getDisabledSystemPackage(intentInfo.activity.info.packageName); - final List<PackageParser.Activity> systemActivities = - disabledPkg != null ? disabledPkg.activities : null; + final ParsedActivityIntentInfo intentInfo = newIntents.get(i); + final PackageSetting disabledPkgSetting = (PackageSetting) sPackageManagerInternal + .getDisabledSystemPackage(intentInfo.getPackageName()); + final AndroidPackage disabledPkg = + disabledPkgSetting == null ? null : disabledPkgSetting.pkg; + final List<ParsedActivity> systemActivities = + disabledPkg != null ? disabledPkg.getActivities() : null; adjustPriority(systemActivities, intentInfo, setupWizardPackage); } } /** Removes all components defined in the given package from the internal structures. */ - void removeAllComponents(PackageParser.Package pkg, boolean chatty) { + void removeAllComponents(AndroidPackage pkg, boolean chatty) { synchronized (mLock) { removeAllComponentsLocked(pkg, chatty); } @@ -422,7 +455,7 @@ public class ComponentResolver { if (mProtectedFilters == null || mProtectedFilters.size() == 0) { return; } - final List<ActivityIntentInfo> protectedFilters = mProtectedFilters; + final List<ParsedActivityIntentInfo> protectedFilters = mProtectedFilters; mProtectedFilters = null; // expect single setupwizard package @@ -435,13 +468,13 @@ public class ComponentResolver { + " All protected intents capped to priority 0"); } for (int i = protectedFilters.size() - 1; i >= 0; --i) { - final ActivityIntentInfo filter = protectedFilters.get(i); - if (filter.activity.info.packageName.equals(setupWizardPackage)) { + final ParsedActivityIntentInfo filter = protectedFilters.get(i); + if (filter.getPackageName().equals(setupWizardPackage)) { if (DEBUG_FILTERS) { Slog.i(TAG, "Found setup wizard;" + " allow priority " + filter.getPriority() + ";" - + " package: " + filter.activity.info.packageName - + " activity: " + filter.activity.className + + " package: " + filter.getPackageName() + + " activity: " + filter.getClassName() + " priority: " + filter.getPriority()); } // skip setup wizard; allow it to keep the high priority filter @@ -449,8 +482,8 @@ public class ComponentResolver { } if (DEBUG_FILTERS) { Slog.i(TAG, "Protected action; cap priority to 0;" - + " package: " + filter.activity.info.packageName - + " activity: " + filter.activity.className + + " package: " + filter.getPackageName() + + " activity: " + filter.getClassName() + " origPrio: " + filter.getPriority()); } filter.setPriority(0); @@ -491,8 +524,8 @@ public class ComponentResolver { void dumpContentProviders(PrintWriter pw, DumpState dumpState, String packageName) { boolean printedSomething = false; - for (PackageParser.Provider p : mProviders.mProviders.values()) { - if (packageName != null && !packageName.equals(p.info.packageName)) { + for (ParsedProvider p : mProviders.mProviders.values()) { + if (packageName != null && !packageName.equals(p.getPackageName())) { continue; } if (!printedSomething) { @@ -502,14 +535,17 @@ public class ComponentResolver { pw.println("Registered ContentProviders:"); printedSomething = true; } - pw.print(" "); p.printComponentShortName(pw); pw.println(":"); - pw.print(" "); pw.println(p.toString()); + pw.print(" "); + ComponentName.printShortString(pw, p.getPackageName(), p.className); + pw.println(":"); + pw.print(" "); + pw.println(p.toString()); } printedSomething = false; - for (Map.Entry<String, PackageParser.Provider> entry : + for (Map.Entry<String, ParsedProvider> entry : mProvidersByAuthority.entrySet()) { - PackageParser.Provider p = entry.getValue(); - if (packageName != null && !packageName.equals(p.info.packageName)) { + ParsedProvider p = entry.getValue(); + if (packageName != null && !packageName.equals(p.getPackageName())) { continue; } if (!printedSomething) { @@ -521,25 +557,43 @@ public class ComponentResolver { } pw.print(" ["); pw.print(entry.getKey()); pw.println("]:"); pw.print(" "); pw.println(p.toString()); - if (p.info != null && p.info.applicationInfo != null) { - final String appInfo = p.info.applicationInfo.toString(); - pw.print(" applicationInfo="); pw.println(appInfo); + + AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName()); + + if (pkg != null) { + // TODO(b/135203078): Print AppInfo? + pw.print(" applicationInfo="); pw.println(pkg.toAppInfo()); } } } - void dumpServicePermissions(PrintWriter pw, DumpState dumpState, String packageName) { + void dumpServicePermissions(PrintWriter pw, DumpState dumpState) { if (dumpState.onTitlePrinted()) pw.println(); pw.println("Service permissions:"); - final Iterator<ServiceIntentInfo> filterIterator = mServices.filterIterator(); + final Iterator<ParsedServiceIntentInfo> filterIterator = mServices.filterIterator(); while (filterIterator.hasNext()) { - final ServiceIntentInfo info = filterIterator.next(); - final ServiceInfo serviceInfo = info.service.info; - final String permission = serviceInfo.permission; + final ParsedServiceIntentInfo info = filterIterator.next(); + + ParsedService service = null; + + AndroidPackage pkg = sPackageManagerInternal.getPackage(info.getPackageName()); + if (pkg != null && pkg.getServices() != null) { + for (ParsedService parsedService : pkg.getServices()) { + if (Objects.equals(parsedService.className, info.getClassName())) { + service = parsedService; + } + } + } + + if (service == null) { + continue; + } + + final String permission = service.getPermission(); if (permission != null) { pw.print(" "); - pw.print(serviceInfo.getComponentName().flattenToShortString()); + pw.print(service.getComponentName().flattenToShortString()); pw.print(": "); pw.println(permission); } @@ -547,14 +601,12 @@ public class ComponentResolver { } @GuardedBy("mLock") - private void addActivitiesLocked(PackageParser.Package pkg, - List<PackageParser.ActivityIntentInfo> newIntents, boolean chatty) { - final int activitiesSize = pkg.activities.size(); + private void addActivitiesLocked(AndroidPackage pkg, + List<ParsedActivityIntentInfo> newIntents, boolean chatty) { + final int activitiesSize = ArrayUtils.size(pkg.getActivities()); StringBuilder r = null; for (int i = 0; i < activitiesSize; i++) { - PackageParser.Activity a = pkg.activities.get(i); - a.info.processName = - fixProcessName(pkg.applicationInfo.processName, a.info.processName); + ParsedActivity a = pkg.getActivities().get(i); mActivities.addActivity(a, "activity", newIntents); if (DEBUG_PACKAGE_SCANNING && chatty) { if (r == null) { @@ -562,7 +614,7 @@ public class ComponentResolver { } else { r.append(' '); } - r.append(a.info.name); + r.append(a.getName()); } } if (DEBUG_PACKAGE_SCANNING && chatty) { @@ -571,20 +623,17 @@ public class ComponentResolver { } @GuardedBy("mLock") - private void addProvidersLocked(PackageParser.Package pkg, boolean chatty) { - final int providersSize = pkg.providers.size(); + private void addProvidersLocked(AndroidPackage pkg, boolean chatty) { + final int providersSize = ArrayUtils.size(pkg.getProviders()); StringBuilder r = null; for (int i = 0; i < providersSize; i++) { - PackageParser.Provider p = pkg.providers.get(i); - p.info.processName = fixProcessName(pkg.applicationInfo.processName, - p.info.processName); + EffectiveProvider p = new EffectiveProvider(pkg.getProviders().get(i)); mProviders.addProvider(p); - p.syncable = p.info.isSyncable; - if (p.info.authority != null) { - String[] names = p.info.authority.split(";"); - p.info.authority = null; + if (p.getAuthority() != null) { + String[] names = p.getAuthority().split(";"); + p.setEffectiveAuthority(null); for (int j = 0; j < names.length; j++) { - if (j == 1 && p.syncable) { + if (j == 1 && p.isSyncable()) { // We only want the first authority for a provider to possibly be // syncable, so if we already added this provider using a different // authority clear the syncable flag. We copy the provider before @@ -592,23 +641,23 @@ public class ComponentResolver { // to a provider that we don't want to change. // Only do this for the second authority since the resulting provider // object can be the same for all future authorities for this provider. - p = new PackageParser.Provider(p); - p.syncable = false; + p = new EffectiveProvider(p); + p.setEffectiveSyncable(false); } if (!mProvidersByAuthority.containsKey(names[j])) { mProvidersByAuthority.put(names[j], p); - if (p.info.authority == null) { - p.info.authority = names[j]; + if (p.getAuthority() == null) { + p.setEffectiveAuthority(names[j]); } else { - p.info.authority = p.info.authority + ";" + names[j]; + p.setEffectiveAuthority(p.getAuthority() + ";" + names[j]); } if (DEBUG_PACKAGE_SCANNING && chatty) { Log.d(TAG, "Registered content provider: " + names[j] - + ", className = " + p.info.name - + ", isSyncable = " + p.info.isSyncable); + + ", className = " + p.getName() + + ", isSyncable = " + p.isSyncable()); } } else { - final PackageParser.Provider other = + final ParsedProvider other = mProvidersByAuthority.get(names[j]); final ComponentName component = (other != null && other.getComponentName() != null) @@ -616,7 +665,7 @@ public class ComponentResolver { final String packageName = component != null ? component.getPackageName() : "?"; Slog.w(TAG, "Skipping provider name " + names[j] - + " (in package " + pkg.applicationInfo.packageName + ")" + + " (in package " + pkg.getAppInfoPackageName() + ")" + ": name already used by " + packageName); } } @@ -627,7 +676,7 @@ public class ComponentResolver { } else { r.append(' '); } - r.append(p.info.name); + r.append(p.getName()); } } if (DEBUG_PACKAGE_SCANNING && chatty) { @@ -636,13 +685,11 @@ public class ComponentResolver { } @GuardedBy("mLock") - private void addReceiversLocked(PackageParser.Package pkg, boolean chatty) { - final int receiversSize = pkg.receivers.size(); + private void addReceiversLocked(AndroidPackage pkg, boolean chatty) { + final int receiversSize = ArrayUtils.size(pkg.getReceivers()); StringBuilder r = null; for (int i = 0; i < receiversSize; i++) { - PackageParser.Activity a = pkg.receivers.get(i); - a.info.processName = fixProcessName(pkg.applicationInfo.processName, - a.info.processName); + ParsedActivity a = pkg.getReceivers().get(i); mReceivers.addActivity(a, "receiver", null); if (DEBUG_PACKAGE_SCANNING && chatty) { if (r == null) { @@ -650,7 +697,7 @@ public class ComponentResolver { } else { r.append(' '); } - r.append(a.info.name); + r.append(a.getName()); } } if (DEBUG_PACKAGE_SCANNING && chatty) { @@ -659,13 +706,11 @@ public class ComponentResolver { } @GuardedBy("mLock") - private void addServicesLocked(PackageParser.Package pkg, boolean chatty) { - final int servicesSize = pkg.services.size(); + private void addServicesLocked(AndroidPackage pkg, boolean chatty) { + final int servicesSize = ArrayUtils.size(pkg.getServices()); StringBuilder r = null; for (int i = 0; i < servicesSize; i++) { - PackageParser.Service s = pkg.services.get(i); - s.info.processName = fixProcessName(pkg.applicationInfo.processName, - s.info.processName); + ParsedService s = pkg.getServices().get(i); mServices.addService(s); if (DEBUG_PACKAGE_SCANNING && chatty) { if (r == null) { @@ -673,7 +718,7 @@ public class ComponentResolver { } else { r.append(' '); } - r.append(s.info.name); + r.append(s.getName()); } } if (DEBUG_PACKAGE_SCANNING && chatty) { @@ -681,13 +726,12 @@ public class ComponentResolver { } } - /** * <em>WARNING</em> for performance reasons, the passed in intentList WILL BE * MODIFIED. Do not pass in a list that should not be changed. */ - private static <T> void getIntentListSubset(List<ActivityIntentInfo> intentList, - IterGenerator<T> generator, Iterator<T> searchIterator) { + private static <T> void getIntentListSubset(List<ParsedActivityIntentInfo> intentList, + Function<ParsedActivityIntentInfo, Iterator<T>> generator, Iterator<T> searchIterator) { // loop through the set of actions; every one must be found in the intent filter while (searchIterator.hasNext()) { // we must have at least one filter in the list to consider a match @@ -698,14 +742,14 @@ public class ComponentResolver { final T searchAction = searchIterator.next(); // loop through the set of intent filters - final Iterator<ActivityIntentInfo> intentIter = intentList.iterator(); + final Iterator<ParsedActivityIntentInfo> intentIter = intentList.iterator(); while (intentIter.hasNext()) { - final ActivityIntentInfo intentInfo = intentIter.next(); + final ParsedActivityIntentInfo intentInfo = intentIter.next(); boolean selectionFound = false; // loop through the intent filter's selection criteria; at least one // of them must match the searched criteria - final Iterator<T> intentSelectionIter = generator.generate(intentInfo); + final Iterator<T> intentSelectionIter = generator.apply(intentInfo); while (intentSelectionIter != null && intentSelectionIter.hasNext()) { final T intentSelection = intentSelectionIter.next(); if (intentSelection != null && intentSelection.equals(searchAction)) { @@ -723,7 +767,7 @@ public class ComponentResolver { } } - private static boolean isProtectedAction(ActivityIntentInfo filter) { + private static boolean isProtectedAction(ParsedActivityIntentInfo filter) { final Iterator<String> actionsIter = filter.actionsIterator(); while (actionsIter != null && actionsIter.hasNext()) { final String filterAction = actionsIter.next(); @@ -737,20 +781,20 @@ public class ComponentResolver { /** * Finds a privileged activity that matches the specified activity names. */ - private static PackageParser.Activity findMatchingActivity( - List<PackageParser.Activity> activityList, ActivityInfo activityInfo) { - for (PackageParser.Activity sysActivity : activityList) { - if (sysActivity.info.name.equals(activityInfo.name)) { + private static ParsedActivity findMatchingActivity( + List<ParsedActivity> activityList, ParsedActivity activityInfo) { + for (ParsedActivity sysActivity : activityList) { + if (sysActivity.getName().equals(activityInfo.getName())) { return sysActivity; } - if (sysActivity.info.name.equals(activityInfo.targetActivity)) { + if (sysActivity.getName().equals(activityInfo.targetActivity)) { return sysActivity; } - if (sysActivity.info.targetActivity != null) { - if (sysActivity.info.targetActivity.equals(activityInfo.name)) { + if (sysActivity.targetActivity != null) { + if (sysActivity.targetActivity.equals(activityInfo.getName())) { return sysActivity; } - if (sysActivity.info.targetActivity.equals(activityInfo.targetActivity)) { + if (sysActivity.targetActivity.equals(activityInfo.targetActivity)) { return sysActivity; } } @@ -771,24 +815,23 @@ public class ComponentResolver { * <em>NOTE:</em> There is one exception. For security reasons, the setup wizard is * allowed to obtain any priority on any action. */ - private void adjustPriority(List<PackageParser.Activity> systemActivities, - ActivityIntentInfo intent, String setupWizardPackage) { + private void adjustPriority(List<ParsedActivity> systemActivities, + ParsedActivityIntentInfo intent, String setupWizardPackage) { // nothing to do; priority is fine as-is if (intent.getPriority() <= 0) { return; } - final ActivityInfo activityInfo = intent.activity.info; - final ApplicationInfo applicationInfo = activityInfo.applicationInfo; + AndroidPackage pkg = sPackageManagerInternal.getPackage(intent.getPackageName()); final boolean privilegedApp = - ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0); + ((pkg.getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0); if (!privilegedApp) { // non-privileged applications can never define a priority >0 if (DEBUG_FILTERS) { Slog.i(TAG, "Non-privileged app; cap priority to 0;" - + " package: " + applicationInfo.packageName - + " activity: " + intent.activity.className + + " package: " + pkg.getPackageName() + + " activity: " + intent.getClassName() + " origPrio: " + intent.getPriority()); } intent.setPriority(0); @@ -812,8 +855,8 @@ public class ComponentResolver { mProtectedFilters.add(intent); if (DEBUG_FILTERS) { Slog.i(TAG, "Protected action; save for later;" - + " package: " + applicationInfo.packageName - + " activity: " + intent.activity.className + + " package: " + pkg.getPackageName() + + " activity: " + intent.getClassName() + " origPrio: " + intent.getPriority()); } return; @@ -822,12 +865,12 @@ public class ComponentResolver { Slog.i(TAG, "No setup wizard;" + " All protected intents capped to priority 0"); } - if (intent.activity.info.packageName.equals(setupWizardPackage)) { + if (intent.getPackageName().equals(setupWizardPackage)) { if (DEBUG_FILTERS) { Slog.i(TAG, "Found setup wizard;" + " allow priority " + intent.getPriority() + ";" - + " package: " + intent.activity.info.packageName - + " activity: " + intent.activity.className + + " package: " + intent.getPackageName() + + " activity: " + intent.getClassName() + " priority: " + intent.getPriority()); } // setup wizard gets whatever it wants @@ -835,8 +878,8 @@ public class ComponentResolver { } if (DEBUG_FILTERS) { Slog.i(TAG, "Protected action; cap priority to 0;" - + " package: " + intent.activity.info.packageName - + " activity: " + intent.activity.className + + " package: " + intent.getPackageName() + + " activity: " + intent.getClassName() + " origPrio: " + intent.getPriority()); } intent.setPriority(0); @@ -848,14 +891,28 @@ public class ComponentResolver { } // privileged app unbundled update ... try to find the same activity - final PackageParser.Activity foundActivity = - findMatchingActivity(systemActivities, activityInfo); + + ParsedActivity foundActivity = null; + ParsedActivity activity = null; + + if (pkg.getActivities() != null) { + for (ParsedActivity parsedProvider : pkg.getActivities()) { + if (Objects.equals(parsedProvider.className, intent.getClassName())) { + activity = parsedProvider; + } + } + } + + if (activity != null) { + foundActivity = findMatchingActivity(systemActivities, activity); + } + if (foundActivity == null) { // this is a new activity; it cannot obtain >0 priority if (DEBUG_FILTERS) { Slog.i(TAG, "New activity; cap priority to 0;" - + " package: " + applicationInfo.packageName - + " activity: " + intent.activity.className + + " package: " + pkg.getPackageName() + + " activity: " + intent.getClassName() + " origPrio: " + intent.getPriority()); } intent.setPriority(0); @@ -865,19 +922,19 @@ public class ComponentResolver { // found activity, now check for filter equivalence // a shallow copy is enough; we modify the list, not its contents - final List<ActivityIntentInfo> intentListCopy = new ArrayList<>(foundActivity.intents); - final List<ActivityIntentInfo> foundFilters = mActivities.findFilters(intent); + final List<ParsedActivityIntentInfo> intentListCopy = + new ArrayList<>(foundActivity.intents); // find matching action subsets final Iterator<String> actionsIterator = intent.actionsIterator(); if (actionsIterator != null) { - getIntentListSubset(intentListCopy, new ActionIterGenerator(), actionsIterator); + getIntentListSubset(intentListCopy, IntentFilter::actionsIterator, actionsIterator); if (intentListCopy.size() == 0) { // no more intents to match; we're not equivalent if (DEBUG_FILTERS) { Slog.i(TAG, "Mismatched action; cap priority to 0;" - + " package: " + applicationInfo.packageName - + " activity: " + intent.activity.className + + " package: " + pkg.getPackageName() + + " activity: " + intent.getClassName() + " origPrio: " + intent.getPriority()); } intent.setPriority(0); @@ -888,13 +945,14 @@ public class ComponentResolver { // find matching category subsets final Iterator<String> categoriesIterator = intent.categoriesIterator(); if (categoriesIterator != null) { - getIntentListSubset(intentListCopy, new CategoriesIterGenerator(), categoriesIterator); + getIntentListSubset(intentListCopy, IntentFilter::categoriesIterator, + categoriesIterator); if (intentListCopy.size() == 0) { // no more intents to match; we're not equivalent if (DEBUG_FILTERS) { Slog.i(TAG, "Mismatched category; cap priority to 0;" - + " package: " + applicationInfo.packageName - + " activity: " + intent.activity.className + + " package: " + pkg.getPackageName() + + " activity: " + intent.getClassName() + " origPrio: " + intent.getPriority()); } intent.setPriority(0); @@ -905,13 +963,13 @@ public class ComponentResolver { // find matching schemes subsets final Iterator<String> schemesIterator = intent.schemesIterator(); if (schemesIterator != null) { - getIntentListSubset(intentListCopy, new SchemesIterGenerator(), schemesIterator); + getIntentListSubset(intentListCopy, IntentFilter::schemesIterator, schemesIterator); if (intentListCopy.size() == 0) { // no more intents to match; we're not equivalent if (DEBUG_FILTERS) { Slog.i(TAG, "Mismatched scheme; cap priority to 0;" - + " package: " + applicationInfo.packageName - + " activity: " + intent.activity.className + + " package: " + pkg.getPackageName() + + " activity: " + intent.getClassName() + " origPrio: " + intent.getPriority()); } intent.setPriority(0); @@ -923,14 +981,14 @@ public class ComponentResolver { final Iterator<IntentFilter.AuthorityEntry> authoritiesIterator = intent.authoritiesIterator(); if (authoritiesIterator != null) { - getIntentListSubset(intentListCopy, new AuthoritiesIterGenerator(), + getIntentListSubset(intentListCopy, IntentFilter::authoritiesIterator, authoritiesIterator); if (intentListCopy.size() == 0) { // no more intents to match; we're not equivalent if (DEBUG_FILTERS) { Slog.i(TAG, "Mismatched authority; cap priority to 0;" - + " package: " + applicationInfo.packageName - + " activity: " + intent.activity.className + + " package: " + pkg.getPackageName() + + " activity: " + intent.getClassName() + " origPrio: " + intent.getPriority()); } intent.setPriority(0); @@ -947,8 +1005,8 @@ public class ComponentResolver { if (DEBUG_FILTERS) { Slog.i(TAG, "Found matching filter(s);" + " cap priority to " + cappedPriority + ";" - + " package: " + applicationInfo.packageName - + " activity: " + intent.activity.className + + " package: " + pkg.getPackageName() + + " activity: " + intent.getClassName() + " origPrio: " + intent.getPriority()); } intent.setPriority(cappedPriority); @@ -958,15 +1016,15 @@ public class ComponentResolver { } @GuardedBy("mLock") - private void removeAllComponentsLocked(PackageParser.Package pkg, boolean chatty) { + private void removeAllComponentsLocked(AndroidPackage pkg, boolean chatty) { int componentSize; StringBuilder r; int i; - componentSize = pkg.activities.size(); + componentSize = ArrayUtils.size(pkg.getActivities()); r = null; for (i = 0; i < componentSize; i++) { - PackageParser.Activity a = pkg.activities.get(i); + ParsedActivity a = pkg.getActivities().get(i); mActivities.removeActivity(a, "activity"); if (DEBUG_REMOVE && chatty) { if (r == null) { @@ -974,32 +1032,32 @@ public class ComponentResolver { } else { r.append(' '); } - r.append(a.info.name); + r.append(a.getName()); } } if (DEBUG_REMOVE && chatty) { Log.d(TAG, " Activities: " + (r == null ? "<NONE>" : r)); } - componentSize = pkg.providers.size(); + componentSize = ArrayUtils.size(pkg.getProviders()); r = null; for (i = 0; i < componentSize; i++) { - PackageParser.Provider p = pkg.providers.get(i); + ParsedProvider p = pkg.getProviders().get(i); mProviders.removeProvider(p); - if (p.info.authority == null) { + if (p.getAuthority() == null) { // Another content provider with this authority existed when this app was // installed, so this authority is null. Ignore it as we don't have to // unregister the provider. continue; } - String[] names = p.info.authority.split(";"); + String[] names = p.getAuthority().split(";"); for (int j = 0; j < names.length; j++) { if (mProvidersByAuthority.get(names[j]) == p) { mProvidersByAuthority.remove(names[j]); if (DEBUG_REMOVE && chatty) { Log.d(TAG, "Unregistered content provider: " + names[j] - + ", className = " + p.info.name + ", isSyncable = " - + p.info.isSyncable); + + ", className = " + p.getName() + ", isSyncable = " + + p.isSyncable()); } } } @@ -1009,17 +1067,17 @@ public class ComponentResolver { } else { r.append(' '); } - r.append(p.info.name); + r.append(p.getName()); } } if (DEBUG_REMOVE && chatty) { Log.d(TAG, " Providers: " + (r == null ? "<NONE>" : r)); } - componentSize = pkg.receivers.size(); + componentSize = ArrayUtils.size(pkg.getReceivers()); r = null; for (i = 0; i < componentSize; i++) { - PackageParser.Activity a = pkg.receivers.get(i); + ParsedActivity a = pkg.getReceivers().get(i); mReceivers.removeActivity(a, "receiver"); if (DEBUG_REMOVE && chatty) { if (r == null) { @@ -1027,17 +1085,17 @@ public class ComponentResolver { } else { r.append(' '); } - r.append(a.info.name); + r.append(a.getName()); } } if (DEBUG_REMOVE && chatty) { Log.d(TAG, " Receivers: " + (r == null ? "<NONE>" : r)); } - componentSize = pkg.services.size(); + componentSize = ArrayUtils.size(pkg.getServices()); r = null; for (i = 0; i < componentSize; i++) { - PackageParser.Service s = pkg.services.get(i); + ParsedService s = pkg.getServices().get(i); mServices.removeService(s); if (DEBUG_REMOVE && chatty) { if (r == null) { @@ -1045,7 +1103,7 @@ public class ComponentResolver { } else { r.append(' '); } - r.append(s.info.name); + r.append(s.getName()); } } if (DEBUG_REMOVE && chatty) { @@ -1054,26 +1112,26 @@ public class ComponentResolver { } @GuardedBy("mLock") - private void assertProvidersNotDefinedLocked(PackageParser.Package pkg) + private void assertProvidersNotDefinedLocked(AndroidPackage pkg) throws PackageManagerException { - final int providersSize = pkg.providers.size(); + final int providersSize = ArrayUtils.size(pkg.getProviders()); int i; for (i = 0; i < providersSize; i++) { - PackageParser.Provider p = pkg.providers.get(i); - if (p.info.authority != null) { - final String[] names = p.info.authority.split(";"); + ParsedProvider p = pkg.getProviders().get(i); + if (p.getAuthority() != null) { + final String[] names = p.getAuthority().split(";"); for (int j = 0; j < names.length; j++) { if (mProvidersByAuthority.containsKey(names[j])) { - final PackageParser.Provider other = mProvidersByAuthority.get(names[j]); + final ParsedProvider other = mProvidersByAuthority.get(names[j]); final String otherPackageName = (other != null && other.getComponentName() != null) ? other.getComponentName().getPackageName() : "?"; // if we're installing over the same already-installed package, this is ok - if (!otherPackageName.equals(pkg.packageName)) { + if (!otherPackageName.equals(pkg.getPackageName())) { throw new PackageManagerException( INSTALL_FAILED_CONFLICTING_PROVIDER, "Can't install because provider name " + names[j] - + " (in package " + pkg.applicationInfo.packageName + + " (in package " + pkg.getPackageName() + ") is already used by " + otherPackageName); } } @@ -1082,8 +1140,9 @@ public class ComponentResolver { } } - private static final class ActivityIntentResolver - extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> { + private static class ActivityIntentResolver + extends IntentResolver<ParsedActivityIntentInfo, ResolveInfo> { + @Override public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, boolean defaultOnly, int userId) { @@ -1104,24 +1163,24 @@ public class ComponentResolver { } List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType, - int flags, List<PackageParser.Activity> packageActivities, int userId) { + int flags, List<ParsedActivity> packageActivities, int userId) { if (!sUserManager.exists(userId)) { return null; } if (packageActivities == null) { - return null; + return Collections.emptyList(); } mFlags = flags; final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0; final int activitiesSize = packageActivities.size(); - ArrayList<PackageParser.ActivityIntentInfo[]> listCut = new ArrayList<>(activitiesSize); + ArrayList<ParsedActivityIntentInfo[]> listCut = new ArrayList<>(activitiesSize); - ArrayList<PackageParser.ActivityIntentInfo> intentFilters; + List<ParsedActivityIntentInfo> intentFilters; for (int i = 0; i < activitiesSize; ++i) { intentFilters = packageActivities.get(i).intents; if (intentFilters != null && intentFilters.size() > 0) { - PackageParser.ActivityIntentInfo[] array = - new PackageParser.ActivityIntentInfo[intentFilters.size()]; + ParsedActivityIntentInfo[] array = + new ParsedActivityIntentInfo[intentFilters.size()]; intentFilters.toArray(array); listCut.add(array); } @@ -1129,21 +1188,21 @@ public class ComponentResolver { return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId); } - private void addActivity(PackageParser.Activity a, String type, - List<PackageParser.ActivityIntentInfo> newIntents) { + private void addActivity(ParsedActivity a, String type, + List<ParsedActivityIntentInfo> newIntents) { mActivities.put(a.getComponentName(), a); if (DEBUG_SHOW_INFO) { - final CharSequence label = a.info.nonLocalizedLabel != null - ? a.info.nonLocalizedLabel - : a.info.name; + final CharSequence label = a.nonLocalizedLabel != null + ? a.nonLocalizedLabel + : a.getName(); Log.v(TAG, " " + type + " " + label + ":"); } if (DEBUG_SHOW_INFO) { - Log.v(TAG, " Class=" + a.info.name); + Log.v(TAG, " Class=" + a.getName()); } final int intentsSize = a.intents.size(); for (int j = 0; j < intentsSize; j++) { - PackageParser.ActivityIntentInfo intent = a.intents.get(j); + ParsedActivityIntentInfo intent = a.intents.get(j); if (newIntents != null && "activity".equals(type)) { newIntents.add(intent); } @@ -1152,23 +1211,23 @@ public class ComponentResolver { intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); } if (!intent.debugCheck()) { - Log.w(TAG, "==> For Activity " + a.info.name); + Log.w(TAG, "==> For Activity " + a.getName()); } addFilter(intent); } } - private void removeActivity(PackageParser.Activity a, String type) { + private void removeActivity(ParsedActivity a, String type) { mActivities.remove(a.getComponentName()); if (DEBUG_SHOW_INFO) { Log.v(TAG, " " + type + " " - + (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel - : a.info.name) + ":"); - Log.v(TAG, " Class=" + a.info.name); + + (a.nonLocalizedLabel != null ? a.nonLocalizedLabel + : a.getName()) + ":"); + Log.v(TAG, " Class=" + a.getName()); } final int intentsSize = a.intents.size(); for (int j = 0; j < intentsSize; j++) { - PackageParser.ActivityIntentInfo intent = a.intents.get(j); + ParsedActivityIntentInfo intent = a.intents.get(j); if (DEBUG_SHOW_INFO) { Log.v(TAG, " IntentFilter:"); intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); @@ -1179,11 +1238,11 @@ public class ComponentResolver { @Override protected boolean allowFilterResult( - PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) { - ActivityInfo filterAi = filter.activity.info; + ParsedActivityIntentInfo filter, List<ResolveInfo> dest) { for (int i = dest.size() - 1; i >= 0; --i) { ActivityInfo destAi = dest.get(i).activityInfo; - if (destAi.name == filterAi.name && destAi.packageName == filterAi.packageName) { + if (Objects.equals(destAi.name, filter.getClassName()) + && Objects.equals(destAi.packageName, filter.getPackageName())) { return false; } } @@ -1191,34 +1250,39 @@ public class ComponentResolver { } @Override - protected ActivityIntentInfo[] newArray(int size) { - return new ActivityIntentInfo[size]; + protected ParsedActivityIntentInfo[] newArray(int size) { + return new ParsedActivityIntentInfo[size]; } @Override - protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) { + protected boolean isFilterStopped(ParsedActivityIntentInfo filter, int userId) { if (!sUserManager.exists(userId)) return true; - PackageParser.Package p = filter.activity.owner; - if (p != null) { - PackageSetting ps = (PackageSetting) p.mExtras; - if (ps != null) { - // System apps are never considered stopped for purposes of - // filtering, because there may be no way for the user to - // actually re-launch them. - return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0 - && ps.getStopped(userId); - } + + AndroidPackage pkg = sPackageManagerInternal.getPackage(filter.getPackageName()); + if (pkg == null) { + return false; } - return false; + + PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting( + filter.getPackageName()); + if (ps == null) { + return false; + } + + // System apps are never considered stopped for purposes of + // filtering, because there may be no way for the user to + // actually re-launch them. + return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0 + && ps.getStopped(userId); } @Override protected boolean isPackageForFilter(String packageName, - PackageParser.ActivityIntentInfo info) { - return packageName.equals(info.activity.owner.packageName); + ParsedActivityIntentInfo info) { + return packageName.equals(info.getPackageName()); } - private void log(String reason, ActivityIntentInfo info, int match, + private void log(String reason, ParsedActivityIntentInfo info, int match, int userId) { Slog.w(TAG, reason + "; match: " @@ -1228,7 +1292,7 @@ public class ComponentResolver { } @Override - protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info, + protected ResolveInfo newResult(ParsedActivityIntentInfo info, int match, int userId) { if (!sUserManager.exists(userId)) { if (DEBUG) { @@ -1236,7 +1300,29 @@ public class ComponentResolver { } return null; } - if (!sPackageManagerInternal.isEnabledAndMatches(info.activity.info, mFlags, userId)) { + + ParsedActivity activity = null; + + AndroidPackage pkg = sPackageManagerInternal.getPackage(info.getPackageName()); + if (pkg == null) { + return null; + } + + // TODO(b/135203078): Consider more efficient ways of doing this. + List<ParsedActivity> activities = getResolveList(pkg); + if (activities != null) { + for (ParsedActivity parsedActivity : activities) { + if (Objects.equals(parsedActivity.className, info.getClassName())) { + activity = parsedActivity; + } + } + } + + if (activity == null) { + return null; + } + + if (!sPackageManagerInternal.isEnabledAndMatches(activity, mFlags, userId)) { if (DEBUG) { log("!PackageManagerInternal.isEnabledAndMatches; mFlags=" + DebugUtils.flagsToString(PackageManager.class, "MATCH_", mFlags), @@ -1244,8 +1330,8 @@ public class ComponentResolver { } return null; } - final PackageParser.Activity activity = info.activity; - PackageSetting ps = (PackageSetting) activity.owner.mExtras; + PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting( + info.getPackageName()); if (ps == null) { if (DEBUG) { log("info.activity.owner.mExtras == null", info, match, userId); @@ -1254,10 +1340,10 @@ public class ComponentResolver { } final PackageUserState userState = ps.readUserState(userId); ActivityInfo ai = - PackageParser.generateActivityInfo(activity, mFlags, userState, userId); + PackageInfoUtils.generateActivityInfo(pkg, activity, mFlags, userState, userId); if (ai == null) { if (DEBUG) { - log("Failed to create ActivityInfo based on " + info.activity, info, match, + log("Failed to create ActivityInfo based on " + activity, info, match, userId); } return null; @@ -1307,7 +1393,7 @@ public class ComponentResolver { } res.handleAllWebDataURI = info.handleAllWebDataURI(); res.priority = info.getPriority(); - res.preferredOrder = activity.owner.mPreferredOrder; + res.preferredOrder = pkg.getPreferredOrder(); //System.out.println("Result: " + res.activityInfo.className + // " = " + res.priority); res.match = match; @@ -1332,40 +1418,64 @@ public class ComponentResolver { @Override protected void dumpFilter(PrintWriter out, String prefix, - PackageParser.ActivityIntentInfo filter) { + ParsedActivityIntentInfo filter) { + ParsedActivity activity = null; + + AndroidPackage pkg = sPackageManagerInternal.getPackage(filter.getPackageName()); + if (pkg != null && pkg.getActivities() != null) { + for (ParsedActivity parsedActivity : pkg.getActivities()) { + if (Objects.equals(parsedActivity.className, filter.getClassName())) { + activity = parsedActivity; + } + } + } + out.print(prefix); - out.print(Integer.toHexString(System.identityHashCode(filter.activity))); + out.print(Integer.toHexString(System.identityHashCode(activity))); out.print(' '); - filter.activity.printComponentShortName(out); + ComponentName.printShortString(out, filter.getPackageName(), filter.getClassName()); out.print(" filter "); out.println(Integer.toHexString(System.identityHashCode(filter))); } @Override - protected Object filterToLabel(PackageParser.ActivityIntentInfo filter) { - return filter.activity; + protected Object filterToLabel(ParsedActivityIntentInfo filter) { + return filter; } protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) { - PackageParser.Activity activity = (PackageParser.Activity) label; + ParsedActivityIntentInfo activity = (ParsedActivityIntentInfo) label; out.print(prefix); out.print(Integer.toHexString(System.identityHashCode(activity))); out.print(' '); - activity.printComponentShortName(out); + ComponentName.printShortString(out, activity.getPackageName(), activity.getClassName()); if (count > 1) { out.print(" ("); out.print(count); out.print(" filters)"); } out.println(); } + protected List<ParsedActivity> getResolveList(AndroidPackage pkg) { + return pkg.getActivities(); + } + // Keys are String (activity class name), values are Activity. - private final ArrayMap<ComponentName, PackageParser.Activity> mActivities = + private final ArrayMap<ComponentName, ParsedActivity> mActivities = new ArrayMap<>(); private int mFlags; } + // Both receivers and activities share a class, but point to different get methods + private static final class ReceiverIntentResolver extends ActivityIntentResolver { + + @Override + protected List<ParsedActivity> getResolveList(AndroidPackage pkg) { + return pkg.getReceivers(); + } + } + private static final class ProviderIntentResolver - extends IntentResolver<PackageParser.ProviderIntentInfo, ResolveInfo> { + extends IntentResolver<ParsedProviderIntentInfo, ResolveInfo> { @Override public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, boolean defaultOnly, int userId) { @@ -1387,24 +1497,24 @@ public class ComponentResolver { @Nullable List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType, - int flags, List<PackageParser.Provider> packageProviders, int userId) { + int flags, List<ParsedProvider> packageProviders, int userId) { if (!sUserManager.exists(userId)) { return null; } if (packageProviders == null) { - return null; + return Collections.emptyList(); } mFlags = flags; final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0; final int providersSize = packageProviders.size(); - ArrayList<PackageParser.ProviderIntentInfo[]> listCut = new ArrayList<>(providersSize); + ArrayList<ParsedProviderIntentInfo[]> listCut = new ArrayList<>(providersSize); - ArrayList<PackageParser.ProviderIntentInfo> intentFilters; + List<ParsedProviderIntentInfo> intentFilters; for (int i = 0; i < providersSize; ++i) { - intentFilters = packageProviders.get(i).intents; + intentFilters = packageProviders.get(i).getIntents(); if (intentFilters != null && intentFilters.size() > 0) { - PackageParser.ProviderIntentInfo[] array = - new PackageParser.ProviderIntentInfo[intentFilters.size()]; + ParsedProviderIntentInfo[] array = + new ParsedProviderIntentInfo[intentFilters.size()]; intentFilters.toArray(array); listCut.add(array); } @@ -1412,7 +1522,7 @@ public class ComponentResolver { return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId); } - void addProvider(PackageParser.Provider p) { + void addProvider(ParsedProvider p) { if (mProviders.containsKey(p.getComponentName())) { Slog.w(TAG, "Provider " + p.getComponentName() + " already defined; ignoring"); return; @@ -1421,39 +1531,39 @@ public class ComponentResolver { mProviders.put(p.getComponentName(), p); if (DEBUG_SHOW_INFO) { Log.v(TAG, " " - + (p.info.nonLocalizedLabel != null - ? p.info.nonLocalizedLabel - : p.info.name) + + (p.nonLocalizedLabel != null + ? p.nonLocalizedLabel + : p.getName()) + ":"); - Log.v(TAG, " Class=" + p.info.name); + Log.v(TAG, " Class=" + p.getName()); } - final int intentsSize = p.intents.size(); + final int intentsSize = p.getIntents().size(); int j; for (j = 0; j < intentsSize; j++) { - PackageParser.ProviderIntentInfo intent = p.intents.get(j); + ParsedProviderIntentInfo intent = p.getIntents().get(j); if (DEBUG_SHOW_INFO) { Log.v(TAG, " IntentFilter:"); intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); } if (!intent.debugCheck()) { - Log.w(TAG, "==> For Provider " + p.info.name); + Log.w(TAG, "==> For Provider " + p.getName()); } addFilter(intent); } } - void removeProvider(PackageParser.Provider p) { + void removeProvider(ParsedProvider p) { mProviders.remove(p.getComponentName()); if (DEBUG_SHOW_INFO) { - Log.v(TAG, " " + (p.info.nonLocalizedLabel != null - ? p.info.nonLocalizedLabel - : p.info.name) + ":"); - Log.v(TAG, " Class=" + p.info.name); + Log.v(TAG, " " + (p.nonLocalizedLabel != null + ? p.nonLocalizedLabel + : p.getName()) + ":"); + Log.v(TAG, " Class=" + p.getName()); } - final int intentsSize = p.intents.size(); + final int intentsSize = p.getIntents().size(); int j; for (j = 0; j < intentsSize; j++) { - PackageParser.ProviderIntentInfo intent = p.intents.get(j); + ParsedProviderIntentInfo intent = p.getIntents().get(j); if (DEBUG_SHOW_INFO) { Log.v(TAG, " IntentFilter:"); intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); @@ -1464,12 +1574,11 @@ public class ComponentResolver { @Override protected boolean allowFilterResult( - PackageParser.ProviderIntentInfo filter, List<ResolveInfo> dest) { - ProviderInfo filterPi = filter.provider.info; + ParsedProviderIntentInfo filter, List<ResolveInfo> dest) { for (int i = dest.size() - 1; i >= 0; i--) { ProviderInfo destPi = dest.get(i).providerInfo; - if (destPi.name == filterPi.name - && destPi.packageName == filterPi.packageName) { + if (Objects.equals(destPi.name, filter.getClassName()) + && Objects.equals(destPi.packageName, filter.getPackageName())) { return false; } } @@ -1477,47 +1586,68 @@ public class ComponentResolver { } @Override - protected PackageParser.ProviderIntentInfo[] newArray(int size) { - return new PackageParser.ProviderIntentInfo[size]; + protected ParsedProviderIntentInfo[] newArray(int size) { + return new ParsedProviderIntentInfo[size]; } @Override - protected boolean isFilterStopped(PackageParser.ProviderIntentInfo filter, int userId) { + protected boolean isFilterStopped(ParsedProviderIntentInfo filter, int userId) { if (!sUserManager.exists(userId)) { return true; } - PackageParser.Package p = filter.provider.owner; - if (p != null) { - PackageSetting ps = (PackageSetting) p.mExtras; - if (ps != null) { - // System apps are never considered stopped for purposes of - // filtering, because there may be no way for the user to - // actually re-launch them. - return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0 - && ps.getStopped(userId); - } + + AndroidPackage pkg = sPackageManagerInternal.getPackage(filter.getPackageName()); + if (pkg == null) { + return false; + } + + PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting( + filter.getPackageName()); + if (ps == null) { + return false; } - return false; + + // System apps are never considered stopped for purposes of + // filtering, because there may be no way for the user to + // actually re-launch them. + return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0 + && ps.getStopped(userId); } @Override protected boolean isPackageForFilter(String packageName, - PackageParser.ProviderIntentInfo info) { - return packageName.equals(info.provider.owner.packageName); + ParsedProviderIntentInfo info) { + return packageName.equals(info.getPackageName()); } @Override - protected ResolveInfo newResult(PackageParser.ProviderIntentInfo filter, + protected ResolveInfo newResult(ParsedProviderIntentInfo filter, int match, int userId) { if (!sUserManager.exists(userId)) { return null; } - final PackageParser.ProviderIntentInfo info = filter; - if (!sPackageManagerInternal.isEnabledAndMatches(info.provider.info, mFlags, userId)) { + + ParsedProvider provider = null; + + AndroidPackage pkg = sPackageManagerInternal.getPackage(filter.getPackageName()); + if (pkg != null && pkg.getProviders() != null) { + for (ParsedProvider parsedProvider : pkg.getProviders()) { + if (Objects.equals(parsedProvider.className, filter.getClassName())) { + provider = parsedProvider; + } + } + } + + if (provider == null) { + return null; + } + + if (!sPackageManagerInternal.isEnabledAndMatches(provider, mFlags, userId)) { return null; } - final PackageParser.Provider provider = info.provider; - PackageSetting ps = (PackageSetting) provider.owner.mExtras; + + PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting( + filter.getPackageName()); if (ps == null) { return null; } @@ -1527,7 +1657,7 @@ public class ComponentResolver { final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0; // throw out filters that aren't visible to instant applications if (matchVisibleToInstantApp - && !(info.isVisibleToInstantApp() || userState.instantApp)) { + && !(filter.isVisibleToInstantApp() || userState.instantApp)) { return null; } // throw out instant application filters if we're not explicitly requesting them @@ -1539,8 +1669,8 @@ public class ComponentResolver { if (userState.instantApp && ps.isUpdateAvailable()) { return null; } - ProviderInfo pi = PackageParser.generateProviderInfo(provider, mFlags, - userState, userId); + ProviderInfo pi = PackageInfoUtils.generateProviderInfo(pkg, provider, + mFlags, userState, userId); if (pi == null) { return null; } @@ -1549,13 +1679,13 @@ public class ComponentResolver { if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) { res.filter = filter; } - res.priority = info.getPriority(); - res.preferredOrder = provider.owner.mPreferredOrder; + res.priority = filter.getPriority(); + res.preferredOrder = pkg.getPreferredOrder(); res.match = match; - res.isDefault = info.hasDefault; - res.labelRes = info.labelRes; - res.nonLocalizedLabel = info.nonLocalizedLabel; - res.icon = info.icon; + res.isDefault = filter.hasDefault; + res.labelRes = filter.labelRes; + res.nonLocalizedLabel = filter.nonLocalizedLabel; + res.icon = filter.icon; res.system = res.providerInfo.applicationInfo.isSystemApp(); return res; } @@ -1567,26 +1697,37 @@ public class ComponentResolver { @Override protected void dumpFilter(PrintWriter out, String prefix, - PackageParser.ProviderIntentInfo filter) { + ParsedProviderIntentInfo filter) { + ParsedProvider provider = null; + + AndroidPackage pkg = sPackageManagerInternal.getPackage(filter.getPackageName()); + if (pkg != null && pkg.getProviders() != null) { + for (ParsedProvider parsedProvider : pkg.getProviders()) { + if (Objects.equals(parsedProvider.className, filter.getClassName())) { + provider = parsedProvider; + } + } + } + out.print(prefix); - out.print(Integer.toHexString(System.identityHashCode(filter.provider))); + out.print(Integer.toHexString(System.identityHashCode(provider))); out.print(' '); - filter.provider.printComponentShortName(out); + ComponentName.printShortString(out, filter.getPackageName(), filter.getClassName()); out.print(" filter "); out.println(Integer.toHexString(System.identityHashCode(filter))); } @Override - protected Object filterToLabel(PackageParser.ProviderIntentInfo filter) { - return filter.provider; + protected Object filterToLabel(ParsedProviderIntentInfo filter) { + return filter; } protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) { - final PackageParser.Provider provider = (PackageParser.Provider) label; + final ParsedProviderIntentInfo provider = (ParsedProviderIntentInfo) label; out.print(prefix); out.print(Integer.toHexString(System.identityHashCode(provider))); out.print(' '); - provider.printComponentShortName(out); + ComponentName.printShortString(out, provider.getPackageName(), provider.getClassName()); if (count > 1) { out.print(" ("); out.print(count); @@ -1595,12 +1736,12 @@ public class ComponentResolver { out.println(); } - private final ArrayMap<ComponentName, PackageParser.Provider> mProviders = new ArrayMap<>(); + private final ArrayMap<ComponentName, ParsedProvider> mProviders = new ArrayMap<>(); private int mFlags; } private static final class ServiceIntentResolver - extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> { + extends IntentResolver<ParsedServiceIntentInfo, ResolveInfo> { @Override public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, boolean defaultOnly, int userId) { @@ -1618,22 +1759,22 @@ public class ComponentResolver { } List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType, - int flags, List<PackageParser.Service> packageServices, int userId) { + int flags, List<ParsedService> packageServices, int userId) { if (!sUserManager.exists(userId)) return null; if (packageServices == null) { - return null; + return Collections.emptyList(); } mFlags = flags; final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0; final int servicesSize = packageServices.size(); - ArrayList<PackageParser.ServiceIntentInfo[]> listCut = new ArrayList<>(servicesSize); + ArrayList<ParsedServiceIntentInfo[]> listCut = new ArrayList<>(servicesSize); - ArrayList<PackageParser.ServiceIntentInfo> intentFilters; + List<ParsedServiceIntentInfo> intentFilters; for (int i = 0; i < servicesSize; ++i) { intentFilters = packageServices.get(i).intents; if (intentFilters != null && intentFilters.size() > 0) { - PackageParser.ServiceIntentInfo[] array = - new PackageParser.ServiceIntentInfo[intentFilters.size()]; + ParsedServiceIntentInfo[] array = + new ParsedServiceIntentInfo[intentFilters.size()]; intentFilters.toArray(array); listCut.add(array); } @@ -1641,40 +1782,40 @@ public class ComponentResolver { return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId); } - void addService(PackageParser.Service s) { + void addService(ParsedService s) { mServices.put(s.getComponentName(), s); if (DEBUG_SHOW_INFO) { Log.v(TAG, " " - + (s.info.nonLocalizedLabel != null - ? s.info.nonLocalizedLabel : s.info.name) + ":"); - Log.v(TAG, " Class=" + s.info.name); + + (s.nonLocalizedLabel != null + ? s.nonLocalizedLabel : s.getName()) + ":"); + Log.v(TAG, " Class=" + s.getName()); } final int intentsSize = s.intents.size(); int j; for (j = 0; j < intentsSize; j++) { - PackageParser.ServiceIntentInfo intent = s.intents.get(j); + ParsedServiceIntentInfo intent = s.intents.get(j); if (DEBUG_SHOW_INFO) { Log.v(TAG, " IntentFilter:"); intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); } if (!intent.debugCheck()) { - Log.w(TAG, "==> For Service " + s.info.name); + Log.w(TAG, "==> For Service " + s.getName()); } addFilter(intent); } } - void removeService(PackageParser.Service s) { + void removeService(ParsedService s) { mServices.remove(s.getComponentName()); if (DEBUG_SHOW_INFO) { - Log.v(TAG, " " + (s.info.nonLocalizedLabel != null - ? s.info.nonLocalizedLabel : s.info.name) + ":"); - Log.v(TAG, " Class=" + s.info.name); + Log.v(TAG, " " + (s.nonLocalizedLabel != null + ? s.nonLocalizedLabel : s.getName()) + ":"); + Log.v(TAG, " Class=" + s.getName()); } final int intentsSize = s.intents.size(); int j; for (j = 0; j < intentsSize; j++) { - PackageParser.ServiceIntentInfo intent = s.intents.get(j); + ParsedServiceIntentInfo intent = s.intents.get(j); if (DEBUG_SHOW_INFO) { Log.v(TAG, " IntentFilter:"); intent.dump(new LogPrinter(Log.VERBOSE, TAG), " "); @@ -1685,12 +1826,11 @@ public class ComponentResolver { @Override protected boolean allowFilterResult( - PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) { - ServiceInfo filterSi = filter.service.info; + ParsedServiceIntentInfo filter, List<ResolveInfo> dest) { for (int i = dest.size() - 1; i >= 0; --i) { ServiceInfo destAi = dest.get(i).serviceInfo; - if (destAi.name == filterSi.name - && destAi.packageName == filterSi.packageName) { + if (Objects.equals(destAi.name, filter.getClassName()) + && Objects.equals(destAi.packageName, filter.getPackageName())) { return false; } } @@ -1698,48 +1838,69 @@ public class ComponentResolver { } @Override - protected PackageParser.ServiceIntentInfo[] newArray(int size) { - return new PackageParser.ServiceIntentInfo[size]; + protected ParsedServiceIntentInfo[] newArray(int size) { + return new ParsedServiceIntentInfo[size]; } @Override - protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) { + protected boolean isFilterStopped(ParsedServiceIntentInfo filter, int userId) { if (!sUserManager.exists(userId)) return true; - PackageParser.Package p = filter.service.owner; - if (p != null) { - PackageSetting ps = (PackageSetting) p.mExtras; - if (ps != null) { - // System apps are never considered stopped for purposes of - // filtering, because there may be no way for the user to - // actually re-launch them. - return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0 - && ps.getStopped(userId); - } + + AndroidPackage pkg = sPackageManagerInternal.getPackage(filter.getPackageName()); + if (pkg == null) { + return false; } - return false; + + PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting( + filter.getPackageName()); + if (ps == null) { + return false; + } + + // System apps are never considered stopped for purposes of + // filtering, because there may be no way for the user to + // actually re-launch them. + return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0 + && ps.getStopped(userId); } @Override protected boolean isPackageForFilter(String packageName, - PackageParser.ServiceIntentInfo info) { - return packageName.equals(info.service.owner.packageName); + ParsedServiceIntentInfo info) { + return packageName.equals(info.getPackageName()); } @Override - protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter, + protected ResolveInfo newResult(ParsedServiceIntentInfo filter, int match, int userId) { if (!sUserManager.exists(userId)) return null; - final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo) filter; - if (!sPackageManagerInternal.isEnabledAndMatches(info.service.info, mFlags, userId)) { + + ParsedService service = null; + + AndroidPackage pkg = sPackageManagerInternal.getPackage(filter.getPackageName()); + if (pkg != null && pkg.getServices() != null) { + for (ParsedService parsedService : pkg.getServices()) { + if (Objects.equals(parsedService.className, filter.getClassName())) { + service = parsedService; + } + } + } + + if (service == null) { + return null; + } + + if (!sPackageManagerInternal.isEnabledAndMatches(service, mFlags, userId)) { return null; } - final PackageParser.Service service = info.service; - PackageSetting ps = (PackageSetting) service.owner.mExtras; + + PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting( + filter.getPackageName()); if (ps == null) { return null; } final PackageUserState userState = ps.readUserState(userId); - ServiceInfo si = PackageParser.generateServiceInfo(service, mFlags, + ServiceInfo si = PackageInfoUtils.generateServiceInfo(pkg, service, mFlags, userState, userId); if (si == null) { return null; @@ -1749,7 +1910,7 @@ public class ComponentResolver { final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0; // throw out filters that aren't visible to ephemeral apps if (matchVisibleToInstantApp - && !(info.isVisibleToInstantApp() || userState.instantApp)) { + && !(filter.isVisibleToInstantApp() || userState.instantApp)) { return null; } // throw out ephemeral filters if we're not explicitly requesting them @@ -1766,13 +1927,13 @@ public class ComponentResolver { if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) { res.filter = filter; } - res.priority = info.getPriority(); - res.preferredOrder = service.owner.mPreferredOrder; + res.priority = filter.getPriority(); + res.preferredOrder = pkg.getPreferredOrder(); res.match = match; - res.isDefault = info.hasDefault; - res.labelRes = info.labelRes; - res.nonLocalizedLabel = info.nonLocalizedLabel; - res.icon = info.icon; + res.isDefault = filter.hasDefault; + res.labelRes = filter.labelRes; + res.nonLocalizedLabel = filter.nonLocalizedLabel; + res.icon = filter.icon; res.system = res.serviceInfo.applicationInfo.isSystemApp(); return res; } @@ -1784,31 +1945,42 @@ public class ComponentResolver { @Override protected void dumpFilter(PrintWriter out, String prefix, - PackageParser.ServiceIntentInfo filter) { + ParsedServiceIntentInfo filter) { + ParsedService service = null; + + AndroidPackage pkg = sPackageManagerInternal.getPackage(filter.getPackageName()); + if (pkg != null && pkg.getServices() != null) { + for (ParsedService parsedService : pkg.getServices()) { + if (Objects.equals(parsedService.className, filter.getClassName())) { + service = parsedService; + } + } + } + out.print(prefix); - out.print(Integer.toHexString(System.identityHashCode(filter.service))); + out.print(Integer.toHexString(System.identityHashCode(service))); out.print(' '); - filter.service.printComponentShortName(out); + ComponentName.printShortString(out, filter.getPackageName(), filter.getClassName()); out.print(" filter "); out.print(Integer.toHexString(System.identityHashCode(filter))); - if (filter.service.info.permission != null) { - out.print(" permission "); out.println(filter.service.info.permission); + if (service != null && service.getPermission() != null) { + out.print(" permission "); out.println(service.getPermission()); } else { out.println(); } } @Override - protected Object filterToLabel(PackageParser.ServiceIntentInfo filter) { - return filter.service; + protected Object filterToLabel(ParsedServiceIntentInfo filter) { + return filter; } protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) { - final PackageParser.Service service = (PackageParser.Service) label; + final ParsedServiceIntentInfo service = (ParsedServiceIntentInfo) label; out.print(prefix); out.print(Integer.toHexString(System.identityHashCode(service))); out.print(' '); - service.printComponentShortName(out); + ComponentName.printShortString(out, service.getPackageName(), service.getClassName()); if (count > 1) { out.print(" ("); out.print(count); out.print(" filters)"); } @@ -1816,7 +1988,7 @@ public class ComponentResolver { } // Keys are String (activity class name), values are Activity. - private final ArrayMap<ComponentName, PackageParser.Service> mServices = new ArrayMap<>(); + private final ArrayMap<ComponentName, ParsedService> mServices = new ArrayMap<>(); private int mFlags; } @@ -1905,7 +2077,7 @@ public class ComponentResolver { /** Generic to create an {@link Iterator} for a data type */ static class IterGenerator<E> { - public Iterator<E> generate(ActivityIntentInfo info) { + public Iterator<E> generate(ParsedActivityIntentInfo info) { return null; } } @@ -1913,7 +2085,7 @@ public class ComponentResolver { /** Create an {@link Iterator} for intent actions */ static class ActionIterGenerator extends IterGenerator<String> { @Override - public Iterator<String> generate(ActivityIntentInfo info) { + public Iterator<String> generate(ParsedActivityIntentInfo info) { return info.actionsIterator(); } } @@ -1921,7 +2093,7 @@ public class ComponentResolver { /** Create an {@link Iterator} for intent categories */ static class CategoriesIterGenerator extends IterGenerator<String> { @Override - public Iterator<String> generate(ActivityIntentInfo info) { + public Iterator<String> generate(ParsedActivityIntentInfo info) { return info.categoriesIterator(); } } @@ -1929,7 +2101,7 @@ public class ComponentResolver { /** Create an {@link Iterator} for intent schemes */ static class SchemesIterGenerator extends IterGenerator<String> { @Override - public Iterator<String> generate(ActivityIntentInfo info) { + public Iterator<String> generate(ParsedActivityIntentInfo info) { return info.schemesIterator(); } } @@ -1937,9 +2109,39 @@ public class ComponentResolver { /** Create an {@link Iterator} for intent authorities */ static class AuthoritiesIterGenerator extends IterGenerator<IntentFilter.AuthorityEntry> { @Override - public Iterator<IntentFilter.AuthorityEntry> generate(ActivityIntentInfo info) { + public Iterator<IntentFilter.AuthorityEntry> generate(ParsedActivityIntentInfo info) { return info.authoritiesIterator(); } } + // TODO(b/135203078): Document or remove this if possible. + class EffectiveProvider extends ParsedProvider { + + private String mEffectiveAuthority; + private boolean mEffectiveSyncable; + + public EffectiveProvider(ParsedProvider parsedProvider) { + this.setFrom(parsedProvider); + this.mEffectiveAuthority = parsedProvider.getAuthority(); + this.mEffectiveSyncable = parsedProvider.isSyncable(); + } + + public void setEffectiveAuthority(String authority) { + this.mEffectiveAuthority = authority; + } + + public void setEffectiveSyncable(boolean syncable) { + this.mEffectiveSyncable = syncable; + } + + @Override + public String getAuthority() { + return mEffectiveAuthority; + } + + @Override + public boolean isSyncable() { + return mEffectiveSyncable; + } + } } diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java index 9e04c4b69bd0..f9113fa38825 100644 --- a/services/core/java/com/android/server/pm/InstantAppRegistry.java +++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java @@ -20,9 +20,11 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.content.Intent; +import android.content.pm.ApplicationInfo; import android.content.pm.InstantAppInfo; import android.content.pm.PackageManager; import android.content.pm.PackageParser; +import android.content.pm.parsing.AndroidPackage; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; @@ -137,7 +139,7 @@ class InstantAppRegistry { public byte[] getInstantAppCookieLPw(@NonNull String packageName, @UserIdInt int userId) { // Only installed packages can get their own cookie - PackageParser.Package pkg = mService.mPackages.get(packageName); + AndroidPackage pkg = mService.mPackages.get(packageName); if (pkg == null) { return null; } @@ -171,7 +173,7 @@ class InstantAppRegistry { } // Only an installed package can set its own cookie - PackageParser.Package pkg = mService.mPackages.get(packageName); + AndroidPackage pkg = mService.mPackages.get(packageName); if (pkg == null) { return false; } @@ -264,15 +266,15 @@ class InstantAppRegistry { } @GuardedBy("mService.mLock") - public void onPackageInstalledLPw(@NonNull PackageParser.Package pkg, @NonNull int[] userIds) { - PackageSetting ps = (PackageSetting) pkg.mExtras; + public void onPackageInstalledLPw(@NonNull AndroidPackage pkg, @NonNull int[] userIds) { + PackageSetting ps = mService.getPackageSetting(pkg.getPackageName()); if (ps == null) { return; } for (int userId : userIds) { // Ignore not installed apps - if (mService.mPackages.get(pkg.packageName) == null || !ps.getInstalled(userId)) { + if (mService.mPackages.get(pkg.getPackageName()) == null || !ps.getInstalled(userId)) { continue; } @@ -286,16 +288,16 @@ class InstantAppRegistry { // Remove the in-memory state removeUninstalledInstantAppStateLPw((UninstalledInstantAppState state) -> - state.mInstantAppInfo.getPackageName().equals(pkg.packageName), + state.mInstantAppInfo.getPackageName().equals(pkg.getPackageName()), userId); // Remove the on-disk state except the cookie - File instantAppDir = getInstantApplicationDir(pkg.packageName, userId); + File instantAppDir = getInstantApplicationDir(pkg.getPackageName(), userId); new File(instantAppDir, INSTANT_APP_METADATA_FILE).delete(); new File(instantAppDir, INSTANT_APP_ICON_FILE).delete(); // If app signature changed - wipe the cookie - File currentCookieFile = peekInstantCookieFile(pkg.packageName, userId); + File currentCookieFile = peekInstantCookieFile(pkg.getPackageName(), userId); if (currentCookieFile == null) { continue; } @@ -310,7 +312,7 @@ class InstantAppRegistry { // We prefer the modern computation procedure where all certs are taken // into account but also allow the value from the old computation to avoid // data loss. - if (pkg.mSigningDetails.checkCapability(currentCookieSha256, + if (pkg.getSigningDetails().checkCapability(currentCookieSha256, PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA)) { return; } @@ -318,7 +320,7 @@ class InstantAppRegistry { // For backwards compatibility we accept match based on any signature, since we may have // recorded only the first for multiply-signed packages final String[] signaturesSha256Digests = - PackageUtils.computeSignaturesSha256Digests(pkg.mSigningDetails.signatures); + PackageUtils.computeSignaturesSha256Digests(pkg.getSigningDetails().signatures); for (String s : signaturesSha256Digests) { if (s.equals(currentCookieSha256)) { return; @@ -326,7 +328,7 @@ class InstantAppRegistry { } // Sorry, you are out of luck - different signatures - nuke data - Slog.i(LOG_TAG, "Signature for package " + pkg.packageName + Slog.i(LOG_TAG, "Signature for package " + pkg.getPackageName() + " changed - dropping cookie"); // Make sure a pending write for the old signed app is cancelled mCookiePersistence.cancelPendingPersistLPw(pkg, userId); @@ -335,15 +337,15 @@ class InstantAppRegistry { } @GuardedBy("mService.mLock") - public void onPackageUninstalledLPw(@NonNull PackageParser.Package pkg, + public void onPackageUninstalledLPw(@NonNull AndroidPackage pkg, @NonNull int[] userIds) { - PackageSetting ps = (PackageSetting) pkg.mExtras; + PackageSetting ps = mService.getPackageSetting(pkg.getPackageName()); if (ps == null) { return; } for (int userId : userIds) { - if (mService.mPackages.get(pkg.packageName) != null && ps.getInstalled(userId)) { + if (mService.mPackages.get(pkg.getPackageName()) != null && ps.getInstalled(userId)) { continue; } @@ -353,7 +355,7 @@ class InstantAppRegistry { removeInstantAppLPw(userId, ps.appId); } else { // Deleting an app prunes all instant state such as cookie - deleteDir(getInstantApplicationDir(pkg.packageName, userId)); + deleteDir(getInstantApplicationDir(pkg.getPackageName(), userId)); mCookiePersistence.cancelPendingPersistLPw(pkg, userId); removeAppLPw(userId, ps.appId); } @@ -487,7 +489,7 @@ class InstantAppRegistry { } @GuardedBy("mService.mLock") - private void addUninstalledInstantAppLPw(@NonNull PackageParser.Package pkg, + private void addUninstalledInstantAppLPw(@NonNull AndroidPackage pkg, @UserIdInt int userId) { InstantAppInfo uninstalledApp = createInstantAppInfoForPackage( pkg, userId, false); @@ -511,14 +513,15 @@ class InstantAppRegistry { writeInstantApplicationIconLPw(pkg, userId); } - private void writeInstantApplicationIconLPw(@NonNull PackageParser.Package pkg, + private void writeInstantApplicationIconLPw(@NonNull AndroidPackage pkg, @UserIdInt int userId) { - File appDir = getInstantApplicationDir(pkg.packageName, userId); + File appDir = getInstantApplicationDir(pkg.getPackageName(), userId); if (!appDir.exists()) { return; } - Drawable icon = pkg.applicationInfo.loadIcon(mService.mContext.getPackageManager()); + // TODO(b/135203078): Remove toAppInfo call? Requires significant additions/changes to PM + Drawable icon = pkg.toAppInfo().loadIcon(mService.mContext.getPackageManager()); final Bitmap bitmap; if (icon instanceof BitmapDrawable) { @@ -531,7 +534,7 @@ class InstantAppRegistry { icon.draw(canvas); } - File iconFile = new File(getInstantApplicationDir(pkg.packageName, userId), + File iconFile = new File(getInstantApplicationDir(pkg.getPackageName(), userId), INSTANT_APP_ICON_FILE); try (FileOutputStream out = new FileOutputStream(iconFile)) { @@ -690,14 +693,16 @@ class InstantAppRegistry { final int packageCount = mService.mPackages.size(); for (int i = 0; i < packageCount; i++) { - final PackageParser.Package pkg = mService.mPackages.valueAt(i); + final AndroidPackage pkg = mService.mPackages.valueAt(i); if (now - pkg.getLatestPackageUseTimeInMills() < maxInstalledCacheDuration) { continue; } - if (!(pkg.mExtras instanceof PackageSetting)) { + + final PackageSetting ps = mService.getPackageSetting(pkg.getPackageName()); + if (ps == null) { continue; } - final PackageSetting ps = (PackageSetting) pkg.mExtras; + boolean installedOnlyAsInstantApp = false; for (int userId : allUsers) { if (ps.getInstalled(userId)) { @@ -713,14 +718,14 @@ class InstantAppRegistry { if (packagesToDelete == null) { packagesToDelete = new ArrayList<>(); } - packagesToDelete.add(pkg.packageName); + packagesToDelete.add(pkg.getPackageName()); } } if (packagesToDelete != null) { packagesToDelete.sort((String lhs, String rhs) -> { - final PackageParser.Package lhsPkg = mService.mPackages.get(lhs); - final PackageParser.Package rhsPkg = mService.mPackages.get(rhs); + final AndroidPackage lhsPkg = mService.mPackages.get(lhs); + final AndroidPackage rhsPkg = mService.mPackages.get(rhs); if (lhsPkg == null && rhsPkg == null) { return 0; } else if (lhsPkg == null) { @@ -735,18 +740,23 @@ class InstantAppRegistry { rhsPkg.getLatestPackageUseTimeInMills()) { return -1; } else { - if (lhsPkg.mExtras instanceof PackageSetting - && rhsPkg.mExtras instanceof PackageSetting) { - final PackageSetting lhsPs = (PackageSetting) lhsPkg.mExtras; - final PackageSetting rhsPs = (PackageSetting) rhsPkg.mExtras; - if (lhsPs.firstInstallTime > rhsPs.firstInstallTime) { - return 1; - } else { - return -1; - } - } else { + final PackageSetting lhsPs = mService.getPackageSetting( + lhsPkg.getPackageName()); + if (lhsPs == null) { + return 0; + } + + final PackageSetting rhsPs = mService.getPackageSetting( + rhsPkg.getPackageName()); + if (rhsPs == null) { return 0; } + + if (lhsPs.firstInstallTime > rhsPs.firstInstallTime) { + return 1; + } else { + return -1; + } } } }); @@ -818,8 +828,8 @@ class InstantAppRegistry { final int packageCount = mService.mPackages.size(); for (int i = 0; i < packageCount; i++) { - final PackageParser.Package pkg = mService.mPackages.valueAt(i); - final PackageSetting ps = (PackageSetting) pkg.mExtras; + final AndroidPackage pkg = mService.mPackages.valueAt(i); + final PackageSetting ps = mService.getPackageSetting(pkg.getPackageName()); if (ps == null || !ps.getInstantApp(userId)) { continue; } @@ -839,9 +849,9 @@ class InstantAppRegistry { private @NonNull InstantAppInfo createInstantAppInfoForPackage( - @NonNull PackageParser.Package pkg, @UserIdInt int userId, + @NonNull AndroidPackage pkg, @UserIdInt int userId, boolean addApplicationInfo) { - PackageSetting ps = (PackageSetting) pkg.mExtras; + PackageSetting ps = mService.getPackageSetting(pkg.getPackageName()); if (ps == null) { return null; } @@ -849,19 +859,20 @@ class InstantAppRegistry { return null; } - String[] requestedPermissions = new String[pkg.requestedPermissions.size()]; - pkg.requestedPermissions.toArray(requestedPermissions); + String[] requestedPermissions = new String[pkg.getRequestedPermissions().size()]; + pkg.getRequestedPermissions().toArray(requestedPermissions); Set<String> permissions = ps.getPermissionsState().getPermissions(userId); String[] grantedPermissions = new String[permissions.size()]; permissions.toArray(grantedPermissions); + ApplicationInfo appInfo = pkg.toAppInfo(); if (addApplicationInfo) { - return new InstantAppInfo(pkg.applicationInfo, + return new InstantAppInfo(appInfo, requestedPermissions, grantedPermissions); } else { - return new InstantAppInfo(pkg.applicationInfo.packageName, - pkg.applicationInfo.loadLabel(mService.mContext.getPackageManager()), + return new InstantAppInfo(appInfo.packageName, + appInfo.loadLabel(mService.mContext.getPackageManager()), requestedPermissions, grantedPermissions); } } @@ -887,10 +898,10 @@ class InstantAppRegistry { return uninstalledApps; } - private void propagateInstantAppPermissionsIfNeeded(@NonNull PackageParser.Package pkg, + private void propagateInstantAppPermissionsIfNeeded(@NonNull AndroidPackage pkg, @UserIdInt int userId) { InstantAppInfo appInfo = peekOrParseUninstalledInstantAppInfo( - pkg.packageName, userId); + pkg.getPackageName(), userId); if (appInfo == null) { return; } @@ -902,8 +913,10 @@ class InstantAppRegistry { for (String grantedPermission : appInfo.getGrantedPermissions()) { final boolean propagatePermission = mService.mSettings.canPropagatePermissionToInstantApp(grantedPermission); - if (propagatePermission && pkg.requestedPermissions.contains(grantedPermission)) { - mService.grantRuntimePermission(pkg.packageName, grantedPermission, userId); + if (propagatePermission && pkg.getRequestedPermissions().contains( + grantedPermission)) { + mService.grantRuntimePermission(pkg.getPackageName(), grantedPermission, + userId); } } } finally { @@ -1188,18 +1201,19 @@ class InstantAppRegistry { super(looper); } - public void schedulePersistLPw(@UserIdInt int userId, @NonNull PackageParser.Package pkg, + public void schedulePersistLPw(@UserIdInt int userId, @NonNull AndroidPackage pkg, @NonNull byte[] cookie) { // Before we used only the first signature to compute the SHA 256 but some // apps could be singed by multiple certs and the cert order is undefined. // We prefer the modern computation procedure where all certs are taken // into account and delete the file derived via the legacy hash computation. - File newCookieFile = computeInstantCookieFile(pkg.packageName, - PackageUtils.computeSignaturesSha256Digest(pkg.mSigningDetails.signatures), userId); - if (!pkg.mSigningDetails.hasSignatures()) { + File newCookieFile = computeInstantCookieFile(pkg.getPackageName(), + PackageUtils.computeSignaturesSha256Digest(pkg.getSigningDetails().signatures), + userId); + if (!pkg.getSigningDetails().hasSignatures()) { Slog.wtf(LOG_TAG, "Parsed Instant App contains no valid signatures!"); } - File oldCookieFile = peekInstantCookieFile(pkg.packageName, userId); + File oldCookieFile = peekInstantCookieFile(pkg.getPackageName(), userId); if (oldCookieFile != null && !newCookieFile.equals(oldCookieFile)) { oldCookieFile.delete(); } @@ -1209,12 +1223,12 @@ class InstantAppRegistry { PERSIST_COOKIE_DELAY_MILLIS); } - public @Nullable byte[] getPendingPersistCookieLPr(@NonNull PackageParser.Package pkg, + public @Nullable byte[] getPendingPersistCookieLPr(@NonNull AndroidPackage pkg, @UserIdInt int userId) { ArrayMap<String, SomeArgs> pendingWorkForUser = mPendingPersistCookies.get(userId); if (pendingWorkForUser != null) { - SomeArgs state = pendingWorkForUser.get(pkg.packageName); + SomeArgs state = pendingWorkForUser.get(pkg.getPackageName()); if (state != null) { return (byte[]) state.arg1; } @@ -1222,7 +1236,7 @@ class InstantAppRegistry { return null; } - public void cancelPendingPersistLPw(@NonNull PackageParser.Package pkg, + public void cancelPendingPersistLPw(@NonNull AndroidPackage pkg, @UserIdInt int userId) { removeMessages(userId, pkg); SomeArgs state = removePendingPersistCookieLPr(pkg, userId); @@ -1232,7 +1246,7 @@ class InstantAppRegistry { } private void addPendingPersistCookieLPw(@UserIdInt int userId, - @NonNull PackageParser.Package pkg, @NonNull byte[] cookie, + @NonNull AndroidPackage pkg, @NonNull byte[] cookie, @NonNull File cookieFile) { ArrayMap<String, SomeArgs> pendingWorkForUser = mPendingPersistCookies.get(userId); @@ -1243,16 +1257,16 @@ class InstantAppRegistry { SomeArgs args = SomeArgs.obtain(); args.arg1 = cookie; args.arg2 = cookieFile; - pendingWorkForUser.put(pkg.packageName, args); + pendingWorkForUser.put(pkg.getPackageName(), args); } - private SomeArgs removePendingPersistCookieLPr(@NonNull PackageParser.Package pkg, + private SomeArgs removePendingPersistCookieLPr(@NonNull AndroidPackage pkg, @UserIdInt int userId) { ArrayMap<String, SomeArgs> pendingWorkForUser = mPendingPersistCookies.get(userId); SomeArgs state = null; if (pendingWorkForUser != null) { - state = pendingWorkForUser.remove(pkg.packageName); + state = pendingWorkForUser.remove(pkg.getPackageName()); if (pendingWorkForUser.isEmpty()) { mPendingPersistCookies.remove(userId); } @@ -1263,7 +1277,7 @@ class InstantAppRegistry { @Override public void handleMessage(Message message) { int userId = message.what; - PackageParser.Package pkg = (PackageParser.Package) message.obj; + AndroidPackage pkg = (AndroidPackage) message.obj; SomeArgs state = removePendingPersistCookieLPr(pkg, userId); if (state == null) { return; @@ -1271,7 +1285,7 @@ class InstantAppRegistry { byte[] cookie = (byte[]) state.arg1; File cookieFile = (File) state.arg2; state.recycle(); - persistInstantApplicationCookie(cookie, pkg.packageName, cookieFile, userId); + persistInstantApplicationCookie(cookie, pkg.getPackageName(), cookieFile, userId); } } } diff --git a/services/core/java/com/android/server/pm/InstructionSets.java b/services/core/java/com/android/server/pm/InstructionSets.java index ec48713b0874..0a065eba4309 100644 --- a/services/core/java/com/android/server/pm/InstructionSets.java +++ b/services/core/java/com/android/server/pm/InstructionSets.java @@ -16,7 +16,7 @@ package com.android.server.pm; -import android.content.pm.ApplicationInfo; +import android.content.pm.parsing.AndroidPackage; import android.os.Build; import android.os.SystemProperties; import android.text.TextUtils; @@ -35,30 +35,16 @@ import java.util.List; public class InstructionSets { private static final String PREFERRED_INSTRUCTION_SET = VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]); - public static String[] getAppDexInstructionSets(ApplicationInfo info) { - if (info.primaryCpuAbi != null) { - if (info.secondaryCpuAbi != null) { - return new String[] { - VMRuntime.getInstructionSet(info.primaryCpuAbi), - VMRuntime.getInstructionSet(info.secondaryCpuAbi) }; - } else { - return new String[] { - VMRuntime.getInstructionSet(info.primaryCpuAbi) }; - } - } - return new String[] { getPreferredInstructionSet() }; - } - - public static String[] getAppDexInstructionSets(PackageSetting ps) { - if (ps.primaryCpuAbiString != null) { - if (ps.secondaryCpuAbiString != null) { + public static String[] getAppDexInstructionSets(String primaryCpuAbi, String secondaryCpuAbi) { + if (primaryCpuAbi != null) { + if (secondaryCpuAbi != null) { return new String[] { - VMRuntime.getInstructionSet(ps.primaryCpuAbiString), - VMRuntime.getInstructionSet(ps.secondaryCpuAbiString) }; + VMRuntime.getInstructionSet(primaryCpuAbi), + VMRuntime.getInstructionSet(secondaryCpuAbi) }; } else { return new String[] { - VMRuntime.getInstructionSet(ps.primaryCpuAbiString) }; + VMRuntime.getInstructionSet(primaryCpuAbi) }; } } @@ -124,4 +110,12 @@ public class InstructionSets { return VMRuntime.getInstructionSet(abis.primary); } + public static String getPrimaryInstructionSet(AndroidPackage pkg) { + if (pkg.getPrimaryCpuAbi() == null) { + return getPreferredInstructionSet(); + } + + return VMRuntime.getInstructionSet(pkg.getPrimaryCpuAbi()); + } + } diff --git a/services/core/java/com/android/server/pm/IntentFilterVerificationState.java b/services/core/java/com/android/server/pm/IntentFilterVerificationState.java index a4e9d103b6da..c97d85df00ab 100644 --- a/services/core/java/com/android/server/pm/IntentFilterVerificationState.java +++ b/services/core/java/com/android/server/pm/IntentFilterVerificationState.java @@ -17,7 +17,7 @@ package com.android.server.pm; import android.content.pm.PackageManager; -import android.content.pm.PackageParser; +import android.content.pm.parsing.ComponentParseUtils; import android.util.ArraySet; import android.util.Slog; @@ -35,7 +35,7 @@ public class IntentFilterVerificationState { private int mState; - private ArrayList<PackageParser.ActivityIntentInfo> mFilters = new ArrayList<>(); + private ArrayList<ComponentParseUtils.ParsedActivityIntentInfo> mFilters = new ArrayList<>(); private ArraySet<String> mHosts = new ArraySet<>(); private int mUserId; @@ -66,7 +66,7 @@ public class IntentFilterVerificationState { setState(STATE_VERIFICATION_PENDING); } - public ArrayList<PackageParser.ActivityIntentInfo> getFilters() { + public ArrayList<ComponentParseUtils.ParsedActivityIntentInfo> getFilters() { return mFilters; } @@ -123,7 +123,7 @@ public class IntentFilterVerificationState { return false; } - public void addFilter(PackageParser.ActivityIntentInfo filter) { + public void addFilter(ComponentParseUtils.ParsedActivityIntentInfo filter) { mFilters.add(filter); mHosts.addAll(filter.getHostsList()); } diff --git a/services/core/java/com/android/server/pm/KeySetManagerService.java b/services/core/java/com/android/server/pm/KeySetManagerService.java index 93d3b77511bc..70c0f8d98447 100644 --- a/services/core/java/com/android/server/pm/KeySetManagerService.java +++ b/services/core/java/com/android/server/pm/KeySetManagerService.java @@ -20,23 +20,26 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK; import static com.android.server.pm.PackageManagerService.SCAN_INITIAL; -import com.android.internal.util.Preconditions; import android.content.pm.PackageParser; +import android.content.pm.parsing.AndroidPackage; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Base64; -import android.util.Slog; import android.util.LongSparseArray; +import android.util.Slog; -import java.io.IOException; -import java.io.PrintWriter; -import java.security.PublicKey; -import java.util.Set; +import com.android.internal.util.Preconditions; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; +import java.io.IOException; +import java.io.PrintWriter; +import java.security.PublicKey; +import java.util.Map; +import java.util.Set; + /* * Manages system-wide KeySet state. */ @@ -182,33 +185,31 @@ public class KeySetManagerService { * * Returns true if the package can safely be added to the keyset metadata. */ - public void assertScannedPackageValid(PackageParser.Package pkg) + public void assertScannedPackageValid(AndroidPackage pkg) throws PackageManagerException { - if (pkg == null || pkg.packageName == null) { + if (pkg == null || pkg.getPackageName() == null) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Passed invalid package to keyset validation."); } - ArraySet<PublicKey> signingKeys = pkg.mSigningDetails.publicKeys; + ArraySet<PublicKey> signingKeys = pkg.getSigningDetails().publicKeys; if (signingKeys == null || !(signingKeys.size() > 0) || signingKeys.contains(null)) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Package has invalid signing-key-set."); } - ArrayMap<String, ArraySet<PublicKey>> definedMapping = pkg.mKeySetMapping; + Map<String, ArraySet<PublicKey>> definedMapping = pkg.getKeySetMapping(); if (definedMapping != null) { if (definedMapping.containsKey(null) || definedMapping.containsValue(null)) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Package has null defined key set."); } - int defMapSize = definedMapping.size(); - for (int i = 0; i < defMapSize; i++) { - if (!(definedMapping.valueAt(i).size() > 0) - || definedMapping.valueAt(i).contains(null)) { + for (ArraySet<PublicKey> value : definedMapping.values()) { + if (!(value.size() > 0) || value.contains(null)) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Package has null/no public keys for defined key-sets."); } } } - ArraySet<String> upgradeAliases = pkg.mUpgradeKeySets; + Set<String> upgradeAliases = pkg.getUpgradeKeySets(); if (upgradeAliases != null) { if (definedMapping == null || !(definedMapping.keySet().containsAll(upgradeAliases))) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, @@ -217,17 +218,17 @@ public class KeySetManagerService { } } - public void addScannedPackageLPw(PackageParser.Package pkg) { + public void addScannedPackageLPw(AndroidPackage pkg) { Preconditions.checkNotNull(pkg, "Attempted to add null pkg to ksms."); - Preconditions.checkNotNull(pkg.packageName, "Attempted to add null pkg to ksms."); - PackageSetting ps = mPackages.get(pkg.packageName); - Preconditions.checkNotNull(ps, "pkg: " + pkg.packageName + Preconditions.checkNotNull(pkg.getPackageName(), "Attempted to add null pkg to ksms."); + PackageSetting ps = mPackages.get(pkg.getPackageName()); + Preconditions.checkNotNull(ps, "pkg: " + pkg.getPackageName() + "does not have a corresponding entry in mPackages."); - addSigningKeySetToPackageLPw(ps, pkg.mSigningDetails.publicKeys); - if (pkg.mKeySetMapping != null) { - addDefinedKeySetsToPackageLPw(ps, pkg.mKeySetMapping); - if (pkg.mUpgradeKeySets != null) { - addUpgradeKeySetsToPackageLPw(ps, pkg.mUpgradeKeySets); + addSigningKeySetToPackageLPw(ps, pkg.getSigningDetails().publicKeys); + if (pkg.getKeySetMapping() != null) { + addDefinedKeySetsToPackageLPw(ps, pkg.getKeySetMapping()); + if (pkg.getUpgradeKeySets() != null) { + addUpgradeKeySetsToPackageLPw(ps, pkg.getUpgradeKeySets()); } } } @@ -280,15 +281,14 @@ public class KeySetManagerService { * Remove any KeySets the package no longer defines. */ void addDefinedKeySetsToPackageLPw(PackageSetting pkg, - ArrayMap<String, ArraySet<PublicKey>> definedMapping) { + Map<String, ArraySet<PublicKey>> definedMapping) { ArrayMap<String, Long> prevDefinedKeySets = pkg.keySetData.getAliases(); /* add all of the newly defined KeySets */ - ArrayMap<String, Long> newKeySetAliases = new ArrayMap<String, Long>(); - final int defMapSize = definedMapping.size(); - for (int i = 0; i < defMapSize; i++) { - String alias = definedMapping.keyAt(i); - ArraySet<PublicKey> pubKeys = definedMapping.valueAt(i); + Map<String, Long> newKeySetAliases = new ArrayMap<>(); + for (Map.Entry<String, ArraySet<PublicKey>> entry : definedMapping.entrySet()) { + String alias = entry.getKey(); + ArraySet<PublicKey> pubKeys = entry.getValue(); if (alias != null && pubKeys != null && pubKeys.size() > 0) { KeySetHandle ks = addKeySetLPw(pubKeys); newKeySetAliases.put(alias, ks.getId()); @@ -313,12 +313,10 @@ public class KeySetManagerService { * after all of the defined KeySets have been added. */ void addUpgradeKeySetsToPackageLPw(PackageSetting pkg, - ArraySet<String> upgradeAliases) { - final int uaSize = upgradeAliases.size(); - for (int i = 0; i < uaSize; i++) { - pkg.keySetData.addUpgradeKeySet(upgradeAliases.valueAt(i)); + Set<String> upgradeAliases) { + for (String upgradeAlias : upgradeAliases) { + pkg.keySetData.addUpgradeKeySet(upgradeAlias); } - return; } /** @@ -364,14 +362,14 @@ public class KeySetManagerService { return true; } - public boolean checkUpgradeKeySetLocked(PackageSettingBase oldPS, - PackageParser.Package newPkg) { + public boolean checkUpgradeKeySetLocked(PackageSettingBase oldPS, AndroidPackage pkg) { // Upgrade keysets are being used. Determine if new package has a superset of the // required keys. long[] upgradeKeySets = oldPS.keySetData.getUpgradeKeySets(); for (int i = 0; i < upgradeKeySets.length; i++) { Set<PublicKey> upgradeSet = getPublicKeysFromKeySetLPr(upgradeKeySets[i]); - if (upgradeSet != null && newPkg.mSigningDetails.publicKeys.containsAll(upgradeSet)) { + if (upgradeSet != null + && pkg.getSigningDetails().publicKeys.containsAll(upgradeSet)) { return true; } } diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index f7fd1b2ddb37..673e265787f3 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -40,13 +40,13 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageInstaller.SessionInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; -import android.content.pm.PackageParser; import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutServiceInternal; import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener; import android.content.pm.UserInfo; +import android.content.pm.parsing.AndroidPackage; import android.graphics.Rect; import android.net.Uri; import android.os.Binder; @@ -447,7 +447,7 @@ public class LauncherAppsService extends SystemService { } final PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class); - final PackageParser.Package pkg = pmInt.getPackage(appInfo.packageName); + final AndroidPackage pkg = pmInt.getPackage(appInfo.packageName); if (pkg == null) { // Should not happen, but we shouldn't be failing if it does return false; @@ -458,8 +458,8 @@ public class LauncherAppsService extends SystemService { appInfo.packageName); } - private boolean requestsPermissions(@NonNull PackageParser.Package pkg) { - return !ArrayUtils.isEmpty(pkg.requestedPermissions); + private boolean requestsPermissions(@NonNull AndroidPackage pkg) { + return !ArrayUtils.isEmpty(pkg.getRequestedPermissions()); } private boolean hasDefaultEnableLauncherActivity(@NonNull String packageName) { diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java index d49ecdda679d..ae7a4a7b81f5 100644 --- a/services/core/java/com/android/server/pm/OtaDexoptService.java +++ b/services/core/java/com/android/server/pm/OtaDexoptService.java @@ -22,7 +22,7 @@ import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets; import android.annotation.Nullable; import android.content.Context; import android.content.pm.IOtaDexopt; -import android.content.pm.PackageParser; +import android.content.pm.parsing.AndroidPackage; import android.os.Environment; import android.os.RemoteException; import android.os.ResultReceiver; @@ -118,8 +118,8 @@ public class OtaDexoptService extends IOtaDexopt.Stub { if (mDexoptCommands != null) { throw new IllegalStateException("already called prepare()"); } - final List<PackageParser.Package> important; - final List<PackageParser.Package> others; + final List<AndroidPackage> important; + final List<AndroidPackage> others; synchronized (mPackageManagerService.mLock) { // Important: the packages we need to run with ab-ota compiler-reason. important = PackageManagerServiceUtils.getPackagesForDexopt( @@ -133,12 +133,12 @@ public class OtaDexoptService extends IOtaDexopt.Stub { mDexoptCommands = new ArrayList<>(3 * mPackageManagerService.mPackages.size() / 2); } - for (PackageParser.Package p : important) { + for (AndroidPackage p : important) { mDexoptCommands.addAll(generatePackageDexopts(p, PackageManagerService.REASON_AB_OTA)); } - for (PackageParser.Package p : others) { + for (AndroidPackage p : others) { // We assume here that there are no core apps left. - if (p.coreApp) { + if (p.isCoreApp()) { throw new IllegalStateException("Found a core app that's not important"); } mDexoptCommands.addAll( @@ -150,8 +150,8 @@ public class OtaDexoptService extends IOtaDexopt.Stub { if (spaceAvailable < BULK_DELETE_THRESHOLD) { Log.i(TAG, "Low on space, deleting oat files in an attempt to free up space: " + PackageManagerServiceUtils.packagesToString(others)); - for (PackageParser.Package pkg : others) { - mPackageManagerService.deleteOatArtifactsOfPackage(pkg.packageName); + for (AndroidPackage pkg : others) { + mPackageManagerService.deleteOatArtifactsOfPackage(pkg.getPackageName()); } } long spaceAvailableNow = getAvailableSpace(); @@ -161,15 +161,15 @@ public class OtaDexoptService extends IOtaDexopt.Stub { if (DEBUG_DEXOPT) { try { // Output some data about the packages. - PackageParser.Package lastUsed = Collections.max(important, + AndroidPackage lastUsed = Collections.max(important, (pkg1, pkg2) -> Long.compare( pkg1.getLatestForegroundPackageUseTimeInMills(), pkg2.getLatestForegroundPackageUseTimeInMills())); Log.d(TAG, "A/B OTA: lastUsed time = " + lastUsed.getLatestForegroundPackageUseTimeInMills()); Log.d(TAG, "A/B OTA: deprioritized packages:"); - for (PackageParser.Package pkg : others) { - Log.d(TAG, " " + pkg.packageName + " - " + for (AndroidPackage pkg : others) { + Log.d(TAG, " " + pkg.getPackageName() + " - " + pkg.getLatestForegroundPackageUseTimeInMills()); } } catch (Exception ignored) { @@ -262,7 +262,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub { /** * Generate all dexopt commands for the given package. */ - private synchronized List<String> generatePackageDexopts(PackageParser.Package pkg, + private synchronized List<String> generatePackageDexopts(AndroidPackage pkg, int compilationReason) { // Intercept and collect dexopt requests final List<String> commands = new ArrayList<String>(); @@ -336,8 +336,9 @@ public class OtaDexoptService extends IOtaDexopt.Stub { optimizer.performDexOpt(pkg, null /* ISAs */, null /* CompilerStats.PackageStats */, - mPackageManagerService.getDexManager().getPackageUseInfoOrDefault(pkg.packageName), - new DexoptOptions(pkg.packageName, compilationReason, + mPackageManagerService.getDexManager().getPackageUseInfoOrDefault( + pkg.getPackageName()), + new DexoptOptions(pkg.getPackageName(), compilationReason, DexoptOptions.DEXOPT_BOOT_COMPLETE)); return commands; @@ -359,10 +360,10 @@ public class OtaDexoptService extends IOtaDexopt.Stub { } // Look into all packages. - Collection<PackageParser.Package> pkgs = mPackageManagerService.getPackages(); + Collection<AndroidPackage> pkgs = mPackageManagerService.getPackages(); int packagePaths = 0; int pathsSuccessful = 0; - for (PackageParser.Package pkg : pkgs) { + for (AndroidPackage pkg : pkgs) { if (pkg == null) { continue; } @@ -371,27 +372,28 @@ public class OtaDexoptService extends IOtaDexopt.Stub { if (!PackageDexOptimizer.canOptimizePackage(pkg)) { continue; } - if (pkg.codePath == null) { + if (pkg.getCodePath() == null) { Slog.w(TAG, "Package " + pkg + " can be optimized but has null codePath"); continue; } // If the path is in /system, /vendor, /product or /system_ext, ignore. It will // have been ota-dexopted into /data/ota and moved into the dalvik-cache already. - if (pkg.codePath.startsWith("/system") - || pkg.codePath.startsWith("/vendor") - || pkg.codePath.startsWith("/product") - || pkg.codePath.startsWith("/system_ext")) { + if (pkg.getCodePath().startsWith("/system") + || pkg.getCodePath().startsWith("/vendor") + || pkg.getCodePath().startsWith("/product") + || pkg.getCodePath().startsWith("/system_ext")) { continue; } - final String[] instructionSets = getAppDexInstructionSets(pkg.applicationInfo); + final String[] instructionSets = getAppDexInstructionSets(pkg.getPrimaryCpuAbi(), + pkg.getSecondaryCpuAbi()); final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly(); final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets); for (String dexCodeInstructionSet : dexCodeInstructionSets) { for (String path : paths) { - String oatDir = PackageDexOptimizer.getOatDir(new File(pkg.codePath)). - getAbsolutePath(); + String oatDir = PackageDexOptimizer.getOatDir( + new File(pkg.getCodePath())).getAbsolutePath(); // TODO: Check first whether there is an artifact, to save the roundtrip time. diff --git a/services/core/java/com/android/server/pm/PackageAbiHelper.java b/services/core/java/com/android/server/pm/PackageAbiHelper.java index c21d0cf54d91..d7c161cc1a86 100644 --- a/services/core/java/com/android/server/pm/PackageAbiHelper.java +++ b/services/core/java/com/android/server/pm/PackageAbiHelper.java @@ -17,7 +17,8 @@ package com.android.server.pm; import android.annotation.Nullable; -import android.content.pm.PackageParser; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.ParsedPackage; import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; @@ -25,21 +26,21 @@ import com.android.internal.annotations.VisibleForTesting; import java.io.File; import java.util.Set; +// TODO: Move to .parsing sub-package @VisibleForTesting public interface PackageAbiHelper { /** * Derive and get the location of native libraries for the given package, * which varies depending on where and how the package was installed. */ - NativeLibraryPaths getNativeLibraryPaths( - PackageParser.Package pkg, File appLib32InstallDir); + NativeLibraryPaths getNativeLibraryPaths(AndroidPackage pkg, File appLib32InstallDir); /** * Calculate the abis for a bundled app. These can uniquely be determined from the contents of * the system partition, i.e whether it contains 64 or 32 bit shared libraries etc. We do not * validate any of this information, and instead assume that the system was built sensibly. */ - Abis getBundledAppAbis(PackageParser.Package pkg); + Abis getBundledAppAbis(AndroidPackage pkg); /** * Derive the ABI of a non-system package located at {@code pkg}. This information @@ -48,7 +49,7 @@ public interface PackageAbiHelper { * If {@code extractLibs} is true, native libraries are extracted from the app if required. */ Pair<Abis, NativeLibraryPaths> derivePackageAbi( - PackageParser.Package pkg, String cpuAbiOverride, boolean extractLibs) + AndroidPackage pkg, String cpuAbiOverride, boolean extractLibs) throws PackageManagerException; /** @@ -69,11 +70,11 @@ public interface PackageAbiHelper { */ @Nullable String getAdjustedAbiForSharedUser( - Set<PackageSetting> packagesForUser, PackageParser.Package scannedPackage); + Set<PackageSetting> packagesForUser, AndroidPackage scannedPackage); /** * The native library paths and related properties that should be set on a - * {@link android.content.pm.PackageParser.Package}. + * {@link ParsedPackage}. */ final class NativeLibraryPaths { public final String nativeLibraryRootDir; @@ -91,11 +92,11 @@ public interface PackageAbiHelper { this.secondaryNativeLibraryDir = secondaryNativeLibraryDir; } - public void applyTo(PackageParser.Package pkg) { - pkg.applicationInfo.nativeLibraryRootDir = nativeLibraryRootDir; - pkg.applicationInfo.nativeLibraryRootRequiresIsa = nativeLibraryRootRequiresIsa; - pkg.applicationInfo.nativeLibraryDir = nativeLibraryDir; - pkg.applicationInfo.secondaryNativeLibraryDir = secondaryNativeLibraryDir; + public void applyTo(ParsedPackage pkg) { + pkg.setNativeLibraryRootDir(nativeLibraryRootDir) + .setNativeLibraryRootRequiresIsa(nativeLibraryRootRequiresIsa) + .setNativeLibraryDir(nativeLibraryDir) + .setSecondaryNativeLibraryDir(secondaryNativeLibraryDir); } } @@ -112,13 +113,13 @@ public interface PackageAbiHelper { this.secondary = secondary; } - Abis(PackageParser.Package pkg) { - this(pkg.applicationInfo.primaryCpuAbi, pkg.applicationInfo.secondaryCpuAbi); + Abis(AndroidPackage pkg) { + this(pkg.getPrimaryCpuAbi(), pkg.getSecondaryCpuAbi()); } - public void applyTo(PackageParser.Package pkg) { - pkg.applicationInfo.primaryCpuAbi = primary; - pkg.applicationInfo.secondaryCpuAbi = secondary; + public void applyTo(ParsedPackage pkg) { + pkg.setPrimaryCpuAbi(primary) + .setSecondaryCpuAbi(secondary); } public void applyTo(PackageSetting pkgSetting) { // pkgSetting might be null during rescan following uninstall of updates diff --git a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java index 7e478009b6b3..66acb86445d2 100644 --- a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java +++ b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java @@ -29,7 +29,7 @@ import static com.android.server.pm.InstructionSets.getPrimaryInstructionSet; import android.annotation.Nullable; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; -import android.content.pm.PackageParser; +import android.content.pm.parsing.AndroidPackage; import android.os.Build; import android.os.Environment; import android.os.FileUtils; @@ -132,10 +132,10 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { @Override public NativeLibraryPaths getNativeLibraryPaths( - PackageParser.Package pkg, File appLib32InstallDir) { - return getNativeLibraryPaths(new Abis(pkg), appLib32InstallDir, pkg.codePath, - pkg.applicationInfo.sourceDir, pkg.applicationInfo.isSystemApp(), - pkg.applicationInfo.isUpdatedSystemApp()); + AndroidPackage pkg, File appLib32InstallDir) { + return getNativeLibraryPaths(new Abis(pkg), appLib32InstallDir, pkg.getCodePath(), + pkg.getBaseCodePath(), pkg.isSystemApp(), + pkg.isUpdatedSystemApp()); } private static NativeLibraryPaths getNativeLibraryPaths(final Abis abis, @@ -202,12 +202,12 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { } @Override - public Abis getBundledAppAbis(PackageParser.Package pkg) { - final String apkName = deriveCodePathName(pkg.applicationInfo.getCodePath()); + public Abis getBundledAppAbis(AndroidPackage pkg) { + final String apkName = deriveCodePathName(pkg.getCodePath()); // If "/system/lib64/apkname" exists, assume that is the per-package // native library directory to use; otherwise use "/system/lib/apkname". - final String apkRoot = calculateBundledApkRoot(pkg.applicationInfo.sourceDir); + final String apkRoot = calculateBundledApkRoot(pkg.getBaseCodePath()); final Abis abis = getBundledAppAbi(pkg, apkRoot, apkName); return abis; } @@ -220,8 +220,8 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { * {@code /oem} under which system libraries are installed. * @param apkName the name of the installed package. */ - private Abis getBundledAppAbi(PackageParser.Package pkg, String apkRoot, String apkName) { - final File codeFile = new File(pkg.codePath); + private Abis getBundledAppAbi(AndroidPackage pkg, String apkRoot, String apkName) { + final File codeFile = new File(pkg.getCodePath()); final boolean has64BitLibs; final boolean has32BitLibs; @@ -273,7 +273,7 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { // ABI that's higher on the list, i.e, a device that's configured to prefer // 64 bit apps will see a 64 bit primary ABI, - if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) == 0) { + if ((pkg.getFlags() & ApplicationInfo.FLAG_MULTIARCH) == 0) { Slog.e(PackageManagerService.TAG, "Package " + pkg + " has multiple bundled libs, but is not multiarch."); } @@ -294,14 +294,14 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { @Override public Pair<Abis, NativeLibraryPaths> derivePackageAbi( - PackageParser.Package pkg, String cpuAbiOverride, boolean extractLibs) + AndroidPackage pkg, String cpuAbiOverride, boolean extractLibs) throws PackageManagerException { // Give ourselves some initial paths; we'll come back for another // pass once we've determined ABI below. final NativeLibraryPaths initialLibraryPaths = getNativeLibraryPaths(new Abis(pkg), - PackageManagerService.sAppLib32InstallDir, pkg.codePath, - pkg.applicationInfo.sourceDir, pkg.applicationInfo.isSystemApp(), - pkg.applicationInfo.isUpdatedSystemApp()); + PackageManagerService.sAppLib32InstallDir, pkg.getCodePath(), + pkg.getBaseCodePath(), pkg.isSystemApp(), + pkg.isUpdatedSystemApp()); // We shouldn't attempt to extract libs from system app when it was not updated. if (PackageManagerService.isSystemApp(pkg) && !pkg.isUpdatedSystemApp()) { @@ -329,12 +329,13 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { // Null out the abis so that they can be recalculated. primaryCpuAbi = null; secondaryCpuAbi = null; - if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_MULTIARCH) != 0) { + if ((pkg.getFlags() & ApplicationInfo.FLAG_MULTIARCH) != 0) { // Warn if we've set an abiOverride for multi-lib packages.. // By definition, we need to copy both 32 and 64 bit libraries for // such packages. - if (pkg.cpuAbiOverride != null - && !NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(pkg.cpuAbiOverride)) { + if (pkg.getCpuAbiOverride() != null + && !NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals( + pkg.getCpuAbiOverride())) { Slog.w(PackageManagerService.TAG, "Ignoring abiOverride for multi arch application."); } @@ -409,7 +410,7 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { if (abi32 >= 0) { final String abi = Build.SUPPORTED_32_BIT_ABIS[abi32]; if (abi64 >= 0) { - if (pkg.use32bitAbi) { + if (pkg.isUse32BitAbi()) { secondaryCpuAbi = primaryCpuAbi; primaryCpuAbi = abi; } else { @@ -482,9 +483,9 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { final Abis abis = new Abis(primaryCpuAbi, secondaryCpuAbi); return new Pair<>(abis, getNativeLibraryPaths(abis, PackageManagerService.sAppLib32InstallDir, - pkg.codePath, pkg.applicationInfo.sourceDir, - pkg.applicationInfo.isSystemApp(), - pkg.applicationInfo.isUpdatedSystemApp())); + pkg.getCodePath(), pkg.getBaseCodePath(), + pkg.isSystemApp(), + pkg.isUpdatedSystemApp())); } /** @@ -503,11 +504,11 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { @Override @Nullable public String getAdjustedAbiForSharedUser( - Set<PackageSetting> packagesForUser, PackageParser.Package scannedPackage) { + Set<PackageSetting> packagesForUser, AndroidPackage scannedPackage) { String requiredInstructionSet = null; - if (scannedPackage != null && scannedPackage.applicationInfo.primaryCpuAbi != null) { + if (scannedPackage != null && scannedPackage.getPrimaryCpuAbi() != null) { requiredInstructionSet = VMRuntime.getInstructionSet( - scannedPackage.applicationInfo.primaryCpuAbi); + scannedPackage.getPrimaryCpuAbi()); } PackageSetting requirer = null; @@ -516,7 +517,7 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { // when scannedPackage is an update of an existing package. Without this check, // we will never be able to change the ABI of any package belonging to a shared // user, even if it's compatible with other packages. - if (scannedPackage != null && scannedPackage.packageName.equals(ps.name)) { + if (scannedPackage != null && scannedPackage.getPackageName().equals(ps.name)) { continue; } if (ps.primaryCpuAbiString == null) { @@ -554,7 +555,7 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { } else { // requirer == null implies that we're updating all ABIs in the set to // match scannedPackage. - adjustedAbi = scannedPackage.applicationInfo.primaryCpuAbi; + adjustedAbi = scannedPackage.getPrimaryCpuAbi(); } return adjustedAbi; } diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index 4f7c8c8da4a9..2b422211077b 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -41,10 +41,10 @@ import static dalvik.system.DexFile.isProfileGuidedCompilerFilter; import android.annotation.Nullable; import android.content.Context; import android.content.pm.ApplicationInfo; -import android.content.pm.PackageParser; import android.content.pm.SharedLibraryInfo; import android.content.pm.dex.ArtManager; import android.content.pm.dex.DexMetadataHelper; +import android.content.pm.parsing.AndroidPackage; import android.os.FileUtils; import android.os.PowerManager; import android.os.SystemClock; @@ -53,6 +53,7 @@ import android.os.UserHandle; import android.os.WorkSource; import android.util.Log; import android.util.Slog; +import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.IndentingPrintWriter; @@ -109,9 +110,9 @@ public class PackageDexOptimizer { this.mSystemReady = from.mSystemReady; } - static boolean canOptimizePackage(PackageParser.Package pkg) { + static boolean canOptimizePackage(AndroidPackage pkg) { // We do not dexopt a package with no code. - if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) == 0) { + if ((pkg.getFlags() & ApplicationInfo.FLAG_HAS_CODE) == 0) { return false; } @@ -125,18 +126,18 @@ public class PackageDexOptimizer { * <p>Calls to {@link com.android.server.pm.Installer#dexopt} on {@link #mInstaller} are * synchronized on {@link #mInstallLock}. */ - int performDexOpt(PackageParser.Package pkg, + int performDexOpt(AndroidPackage pkg, String[] instructionSets, CompilerStats.PackageStats packageStats, PackageDexUsage.PackageUseInfo packageUseInfo, DexoptOptions options) { - if (pkg.applicationInfo.uid == -1) { - throw new IllegalArgumentException("Dexopt for " + pkg.packageName + if (pkg.getUid() == -1) { + throw new IllegalArgumentException("Dexopt for " + pkg.getPackageName() + " has invalid uid."); } if (!canOptimizePackage(pkg)) { return DEX_OPT_SKIPPED; } synchronized (mInstallLock) { - final long acquireTime = acquireWakeLockLI(pkg.applicationInfo.uid); + final long acquireTime = acquireWakeLockLI(pkg.getUid()); try { return performDexOptLI(pkg, instructionSets, packageStats, packageUseInfo, options); @@ -151,19 +152,20 @@ public class PackageDexOptimizer { * It assumes the install lock is held. */ @GuardedBy("mInstallLock") - private int performDexOptLI(PackageParser.Package pkg, + private int performDexOptLI(AndroidPackage pkg, String[] targetInstructionSets, CompilerStats.PackageStats packageStats, PackageDexUsage.PackageUseInfo packageUseInfo, DexoptOptions options) { - final List<SharedLibraryInfo> sharedLibraries = pkg.usesLibraryInfos; + final List<SharedLibraryInfo> sharedLibraries = pkg.getUsesLibraryInfos(); final String[] instructionSets = targetInstructionSets != null ? - targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo); + targetInstructionSets : getAppDexInstructionSets(pkg.getPrimaryCpuAbi(), + pkg.getSecondaryCpuAbi()); final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets); final List<String> paths = pkg.getAllCodePaths(); - int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); + int sharedGid = UserHandle.getSharedAppGid(pkg.getUid()); if (sharedGid == -1) { - Slog.wtf(TAG, "Well this is awkward; package " + pkg.applicationInfo.name + " had UID " - + pkg.applicationInfo.uid, new Throwable()); + Slog.wtf(TAG, "Well this is awkward; package " + pkg.getAppInfoName() + " had UID " + + pkg.getUid(), new Throwable()); sharedGid = android.os.Process.NOBODY_UID; } @@ -171,21 +173,21 @@ public class PackageDexOptimizer { // For each code path in the package, this array contains the class loader context that // needs to be passed to dexopt in order to ensure correct optimizations. boolean[] pathsWithCode = new boolean[paths.size()]; - pathsWithCode[0] = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0; + pathsWithCode[0] = (pkg.getFlags() & ApplicationInfo.FLAG_HAS_CODE) != 0; for (int i = 1; i < paths.size(); i++) { - pathsWithCode[i] = (pkg.splitFlags[i - 1] & ApplicationInfo.FLAG_HAS_CODE) != 0; + pathsWithCode[i] = (pkg.getSplitFlags()[i - 1] & ApplicationInfo.FLAG_HAS_CODE) != 0; } String[] classLoaderContexts = DexoptUtils.getClassLoaderContexts( - pkg.applicationInfo, sharedLibraries, pathsWithCode); + pkg, sharedLibraries, pathsWithCode); // Sanity check that we do not call dexopt with inconsistent data. if (paths.size() != classLoaderContexts.length) { - String[] splitCodePaths = pkg.applicationInfo.getSplitCodePaths(); + String[] splitCodePaths = pkg.getSplitCodePaths(); throw new IllegalStateException("Inconsistent information " + "between PackageParser.Package and its ApplicationInfo. " + "pkg.getAllCodePaths=" + paths - + " pkg.applicationInfo.getBaseCodePath=" + pkg.applicationInfo.getBaseCodePath() - + " pkg.applicationInfo.getSplitCodePaths=" + + " pkg.getBaseCodePath=" + pkg.getBaseCodePath() + + " pkg.getSplitCodePaths=" + (splitCodePaths == null ? "null" : Arrays.toString(splitCodePaths))); } @@ -211,7 +213,8 @@ public class PackageDexOptimizer { } } - String profileName = ArtManager.getProfileName(i == 0 ? null : pkg.splitNames[i - 1]); + String profileName = ArtManager.getProfileName( + i == 0 ? null : pkg.getSplitNames()[i - 1]); String dexMetadataPath = null; if (options.isDexoptInstallWithDexMetadata()) { @@ -222,7 +225,7 @@ public class PackageDexOptimizer { final boolean isUsedByOtherApps = options.isDexoptAsSharedLibrary() || packageUseInfo.isUsedByOtherApps(path); - final String compilerFilter = getRealCompilerFilter(pkg.applicationInfo, + final String compilerFilter = getRealCompilerFilter(pkg, options.getCompilerFilter(), isUsedByOtherApps); final boolean profileUpdated = options.isCheckForProfileUpdates() && isProfileUpdated(pkg, sharedGid, profileName, compilerFilter); @@ -257,7 +260,7 @@ public class PackageDexOptimizer { * DEX_OPT_SKIPPED if the path does not need to be deopt-ed. */ @GuardedBy("mInstallLock") - private int dexOptPath(PackageParser.Package pkg, String path, String isa, + private int dexOptPath(AndroidPackage pkg, String path, String isa, String compilerFilter, boolean profileUpdated, String classLoaderContext, int dexoptFlags, int uid, CompilerStats.PackageStats packageStats, boolean downgrade, String profileName, String dexMetadataPath, int compilationReason) { @@ -270,7 +273,7 @@ public class PackageDexOptimizer { String oatDir = getPackageOatDirIfSupported(pkg); Log.i(TAG, "Running dexopt (dexoptNeeded=" + dexoptNeeded + ") on: " + path - + " pkg=" + pkg.applicationInfo.packageName + " isa=" + isa + + " pkg=" + pkg.getAppInfoPackageName() + " isa=" + isa + " dexoptFlags=" + printDexoptFlags(dexoptFlags) + " targetFilter=" + compilerFilter + " oatDir=" + oatDir + " classLoaderContext=" + classLoaderContext); @@ -281,9 +284,9 @@ public class PackageDexOptimizer { // TODO: Consider adding 2 different APIs for primary and secondary dexopt. // installd only uses downgrade flag for secondary dex files and ignores it for // primary dex files. - mInstaller.dexopt(path, uid, pkg.packageName, isa, dexoptNeeded, oatDir, dexoptFlags, - compilerFilter, pkg.volumeUuid, classLoaderContext, pkg.applicationInfo.seInfo, - false /* downgrade*/, pkg.applicationInfo.targetSdkVersion, + mInstaller.dexopt(path, uid, pkg.getPackageName(), isa, dexoptNeeded, oatDir, + dexoptFlags, compilerFilter, pkg.getVolumeUuid(), classLoaderContext, + pkg.getSeInfo(), false /* downgrade*/, pkg.getTargetSdkVersion(), profileName, dexMetadataPath, getAugmentedReasonName(compilationReason, dexMetadataPath != null)); @@ -446,9 +449,10 @@ public class PackageDexOptimizer { /** * Dumps the dexopt state of the given package {@code pkg} to the given {@code PrintWriter}. */ - void dumpDexoptState(IndentingPrintWriter pw, PackageParser.Package pkg, + void dumpDexoptState(IndentingPrintWriter pw, AndroidPackage pkg, PackageDexUsage.PackageUseInfo useInfo) { - final String[] instructionSets = getAppDexInstructionSets(pkg.applicationInfo); + final String[] instructionSets = getAppDexInstructionSets(pkg.getPrimaryCpuAbi(), + pkg.getSecondaryCpuAbi()); final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets); final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly(); @@ -504,7 +508,7 @@ public class PackageDexOptimizer { // When an app or priv app is configured to run out of box, only verify it. if (info.isEmbeddedDexUsed() || (info.isPrivilegedApp() - && DexManager.isPackageSelectedToRunOob(info.packageName))) { + && DexManager.isPackageSelectedToRunOob(info.packageName))) { return "verify"; } @@ -535,12 +539,43 @@ public class PackageDexOptimizer { } /** - * Computes the dex flags that needs to be pass to installd for the given package and compiler - * filter. + * Returns the compiler filter that should be used to optimize the package code. + * The target filter will be updated if the package code is used by other apps + * or if it has the safe mode flag set. */ - private int getDexFlags(PackageParser.Package pkg, String compilerFilter, - DexoptOptions options) { - return getDexFlags(pkg.applicationInfo, compilerFilter, options); + private String getRealCompilerFilter(AndroidPackage pkg, String targetCompilerFilter, + boolean isUsedByOtherApps) { + // When an app or priv app is configured to run out of box, only verify it. + if (pkg.isEmbeddedDexUsed() + || (pkg.isPrivileged() + && DexManager.isPackageSelectedToRunOob(pkg.getPackageName()))) { + return "verify"; + } + + // We force vmSafeMode on debuggable apps as well: + // - the runtime ignores their compiled code + // - they generally have lots of methods that could make the compiler used run + // out of memory (b/130828957) + // Note that forcing the compiler filter here applies to all compilations (even if they + // are done via adb shell commands). That's ok because right now the runtime will ignore + // the compiled code anyway. The alternative would have been to update either + // PackageDexOptimizer#canOptimizePackage or PackageManagerService#getOptimizablePackages + // but that would have the downside of possibly producing a big odex files which would + // be ignored anyway. + boolean vmSafeModeOrDebuggable = ((pkg.getFlags() & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0) + || ((pkg.getFlags() & ApplicationInfo.FLAG_DEBUGGABLE) != 0); + + if (vmSafeModeOrDebuggable) { + return getSafeModeCompilerFilter(targetCompilerFilter); + } + + if (isProfileGuidedCompilerFilter(targetCompilerFilter) && isUsedByOtherApps) { + // If the dex files is used by other apps, apply the shared filter. + return PackageManagerServiceCompilerMapping.getCompilerFilterForReason( + PackageManagerService.REASON_SHARED); + } + + return targetCompilerFilter; } private boolean isAppImageEnabled() { @@ -548,7 +583,24 @@ public class PackageDexOptimizer { } private int getDexFlags(ApplicationInfo info, String compilerFilter, DexoptOptions options) { - int flags = info.flags; + return getDexFlags(info.flags, info.getHiddenApiEnforcementPolicy(), + info.splitDependencies, info.requestsIsolatedSplitLoading(), compilerFilter, + options); + } + private int getDexFlags(AndroidPackage pkg, String compilerFilter, + DexoptOptions options) { + return getDexFlags(pkg.getFlags(), pkg.getHiddenApiEnforcementPolicy(), + pkg.getSplitDependencies(), pkg.requestsIsolatedSplitLoading(), compilerFilter, + options); + } + + /** + * Computes the dex flags that needs to be pass to installd for the given package and compiler + * filter. + */ + private int getDexFlags(int flags, int hiddenApiEnforcementPolicy, + SparseArray<int[]> splitDependencies, boolean requestsIsolatedSplitLoading, + String compilerFilter, DexoptOptions options) { boolean debuggable = (flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; // Profile guide compiled oat files should not be public unles they are based // on profiles from dex metadata archives. @@ -560,7 +612,9 @@ public class PackageDexOptimizer { // Some apps are executed with restrictions on hidden API usage. If this app is one // of them, pass a flag to dexopt to enable the same restrictions during compilation. // TODO we should pass the actual flag value to dexopt, rather than assuming blacklist - int hiddenApiFlag = info.getHiddenApiEnforcementPolicy() == HIDDEN_API_ENFORCEMENT_DISABLED + // TODO(b/135203078): This flag is no longer set as part of AndroidPackage + // and may not be preserved + int hiddenApiFlag = hiddenApiEnforcementPolicy == HIDDEN_API_ENFORCEMENT_DISABLED ? 0 : DEXOPT_ENABLE_HIDDEN_API_CHECKS; // Avoid generating CompactDex for modes that are latency critical. @@ -578,8 +632,8 @@ public class PackageDexOptimizer { // declare inter-split dependencies, then all the splits will be loaded in the base // apk class loader (in the order of their definition, otherwise disable app images // because they are unsupported for multiple class loaders. b/7269679 - boolean generateAppImage = isProfileGuidedFilter && (info.splitDependencies == null || - !info.requestsIsolatedSplitLoading()) && isAppImageEnabled(); + boolean generateAppImage = isProfileGuidedFilter && (splitDependencies == null || + !requestsIsolatedSplitLoading) && isAppImageEnabled(); int dexFlags = (isPublic ? DEXOPT_PUBLIC : 0) | (debuggable ? DEXOPT_DEBUGGABLE : 0) @@ -617,7 +671,7 @@ public class PackageDexOptimizer { * current profile and the reference profile will be merged and subsequent calls * may return a different result. */ - private boolean isProfileUpdated(PackageParser.Package pkg, int uid, String profileName, + private boolean isProfileUpdated(AndroidPackage pkg, int uid, String profileName, String compilerFilter) { // Check if we are allowed to merge and if the compiler filter is profile guided. if (!isProfileGuidedCompilerFilter(compilerFilter)) { @@ -625,7 +679,7 @@ public class PackageDexOptimizer { } // Merge profiles. It returns whether or not there was an updated in the profile info. try { - return mInstaller.mergeProfiles(uid, pkg.packageName, profileName); + return mInstaller.mergeProfiles(uid, pkg.getPackageName(), profileName); } catch (InstallerException e) { Slog.w(TAG, "Failed to merge profiles", e); } @@ -645,11 +699,11 @@ public class PackageDexOptimizer { * not needed or unsupported for the package. */ @Nullable - private String getPackageOatDirIfSupported(PackageParser.Package pkg) { + private String getPackageOatDirIfSupported(AndroidPackage pkg) { if (!pkg.canHaveOatDir()) { return null; } - File codePath = new File(pkg.codePath); + File codePath = new File(pkg.getCodePath()); if (!codePath.isDirectory()) { return null; } diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 883baf7886af..518ec5085a5e 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -66,6 +66,7 @@ import android.content.pm.PackageParser.ApkLite; import android.content.pm.PackageParser.PackageLite; import android.content.pm.PackageParser.PackageParserException; import android.content.pm.dex.DexMetadataHelper; +import android.content.pm.parsing.ApkLiteParseUtils; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Binder; @@ -1677,7 +1678,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { for (File addedFile : addedFiles) { final ApkLite apk; try { - apk = PackageParser.parseApkLite( + apk = ApkLiteParseUtils.parseApkLite( addedFile, PackageParser.PARSE_COLLECT_CERTIFICATES); } catch (PackageParserException e) { throw PackageManagerException.from(e); @@ -1776,7 +1777,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { ApplicationInfo appInfo = pkgInfo.applicationInfo; try { existing = PackageParser.parsePackageLite(new File(appInfo.getCodePath()), 0); - existingBase = PackageParser.parseApkLite(new File(appInfo.getBaseCodePath()), + existingBase = ApkLiteParseUtils.parseApkLite(new File(appInfo.getBaseCodePath()), PackageParser.PARSE_COLLECT_CERTIFICATES); } catch (PackageParserException e) { throw PackageManagerException.from(e); diff --git a/services/core/java/com/android/server/pm/PackageKeySetData.java b/services/core/java/com/android/server/pm/PackageKeySetData.java index 031b5ce3d5b9..10685b06716f 100644 --- a/services/core/java/com/android/server/pm/PackageKeySetData.java +++ b/services/core/java/com/android/server/pm/PackageKeySetData.java @@ -20,6 +20,8 @@ import android.util.ArrayMap; import com.android.internal.util.ArrayUtils; +import java.util.Map; + public class PackageKeySetData { static final long KEYSET_UNASSIGNED = -1; @@ -90,16 +92,13 @@ public class PackageKeySetData { /* * Replace defined keysets with new ones. */ - protected void setAliases(ArrayMap<String, Long> newAliases) { + protected void setAliases(Map<String, Long> newAliases) { /* remove old aliases */ removeAllDefinedKeySets(); /* add new ones */ - final int newAliasSize = newAliases.size(); - for (int i = 0; i < newAliasSize; i++) { - mKeySetAliases.put(newAliases.keyAt(i), newAliases.valueAt(i));; - } + mKeySetAliases.putAll(newAliases); } protected void addDefinedKeySet(long ks, String alias) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 3d4247e761b5..8fef6b9104ba 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -34,7 +34,6 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; -import static android.content.pm.PackageManager.DELETE_KEEP_DATA; import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT; import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED; import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT; @@ -160,7 +159,6 @@ import android.content.pm.InstrumentationInfo; import android.content.pm.IntentFilterVerificationInfo; import android.content.pm.KeySet; import android.content.pm.ModuleInfo; -import android.content.pm.PackageBackwardCompatibility; import android.content.pm.PackageInfo; import android.content.pm.PackageInfoLite; import android.content.pm.PackageInstaller; @@ -170,7 +168,6 @@ import android.content.pm.PackageManager.ModuleInfoFlags; import android.content.pm.PackageManagerInternal; import android.content.pm.PackageManagerInternal.PackageListObserver; import android.content.pm.PackageParser; -import android.content.pm.PackageParser.ActivityIntentInfo; import android.content.pm.PackageParser.PackageLite; import android.content.pm.PackageParser.PackageParserException; import android.content.pm.PackageParser.ParseFlags; @@ -195,6 +192,19 @@ import android.content.pm.VersionedPackage; import android.content.pm.dex.ArtManager; import android.content.pm.dex.DexMetadataHelper; import android.content.pm.dex.IArtManager; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.ApkParseUtils; +import android.content.pm.parsing.ComponentParseUtils.ParsedActivity; +import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo; +import android.content.pm.parsing.ComponentParseUtils.ParsedComponent; +import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation; +import android.content.pm.parsing.ComponentParseUtils.ParsedPermission; +import android.content.pm.parsing.ComponentParseUtils.ParsedProvider; +import android.content.pm.parsing.ComponentParseUtils.ParsedService; +import android.content.pm.parsing.PackageImpl; +import android.content.pm.parsing.PackageInfoUtils; +import android.content.pm.parsing.ParsedPackage; +import android.content.pm.parsing.library.PackageBackwardCompatibility; import android.content.res.Resources; import android.content.rollback.IRollbackManager; import android.database.ContentObserver; @@ -462,20 +472,19 @@ public class PackageManagerService extends IPackageManager.Stub static final int SCAN_REQUIRE_KNOWN = 1 << 7; static final int SCAN_MOVE = 1 << 8; static final int SCAN_INITIAL = 1 << 9; - static final int SCAN_CHECK_ONLY = 1 << 10; - static final int SCAN_DONT_KILL_APP = 1 << 11; - static final int SCAN_IGNORE_FROZEN = 1 << 12; - static final int SCAN_FIRST_BOOT_OR_UPGRADE = 1 << 13; - static final int SCAN_AS_INSTANT_APP = 1 << 14; - static final int SCAN_AS_FULL_APP = 1 << 15; - static final int SCAN_AS_VIRTUAL_PRELOAD = 1 << 16; - static final int SCAN_AS_SYSTEM = 1 << 17; - static final int SCAN_AS_PRIVILEGED = 1 << 18; - static final int SCAN_AS_OEM = 1 << 19; - static final int SCAN_AS_VENDOR = 1 << 20; - static final int SCAN_AS_PRODUCT = 1 << 21; - static final int SCAN_AS_SYSTEM_EXT = 1 << 22; - static final int SCAN_AS_ODM = 1 << 23; + static final int SCAN_DONT_KILL_APP = 1 << 10; + static final int SCAN_IGNORE_FROZEN = 1 << 11; + static final int SCAN_FIRST_BOOT_OR_UPGRADE = 1 << 12; + static final int SCAN_AS_INSTANT_APP = 1 << 13; + static final int SCAN_AS_FULL_APP = 1 << 14; + static final int SCAN_AS_VIRTUAL_PRELOAD = 1 << 15; + static final int SCAN_AS_SYSTEM = 1 << 16; + static final int SCAN_AS_PRIVILEGED = 1 << 17; + static final int SCAN_AS_OEM = 1 << 18; + static final int SCAN_AS_VENDOR = 1 << 19; + static final int SCAN_AS_PRODUCT = 1 << 20; + static final int SCAN_AS_SYSTEM_EXT = 1 << 21; + static final int SCAN_AS_ODM = 1 << 22; @IntDef(flag = true, prefix = { "SCAN_" }, value = { SCAN_NO_DEX, @@ -486,7 +495,6 @@ public class PackageManagerService extends IPackageManager.Stub SCAN_REQUIRE_KNOWN, SCAN_MOVE, SCAN_INITIAL, - SCAN_CHECK_ONLY, SCAN_DONT_KILL_APP, SCAN_IGNORE_FROZEN, SCAN_FIRST_BOOT_OR_UPGRADE, @@ -605,11 +613,19 @@ public class PackageManagerService extends IPackageManager.Stub public static final int REASON_LAST = REASON_SHARED; /** - * Whether the package parser cache is enabled. + * The initial enabled state of the cache before other checks are done. */ private static final boolean DEFAULT_PACKAGE_PARSER_CACHE_ENABLED = true; /** + * Whether to skip all other checks and force the cache to be enabled. + * + * Setting this to true will cause the cache to be named "debug" to avoid eviction from + * build fingerprint changes. + */ + private static final boolean FORCE_PACKAGE_PARSED_CACHE_ENABLED = false; + + /** * Permissions required in order to receive instant application lifecycle broadcasts. */ private static final String[] INSTANT_APP_BROADCAST_PERMISSION = @@ -666,7 +682,7 @@ public class PackageManagerService extends IPackageManager.Stub // Keys are String (package name), values are Package. @GuardedBy("mLock") - final ArrayMap<String, PackageParser.Package> mPackages = new ArrayMap<>(); + final ArrayMap<String, AndroidPackage> mPackages = new ArrayMap<>(); // Keys are isolated uids and values are the uid of the application // that created the isolated proccess. @@ -990,7 +1006,7 @@ public class PackageManagerService extends IPackageManager.Stub new ArrayMap<>(); // Mapping from instrumentation class names to info about them. - final ArrayMap<ComponentName, PackageParser.Instrumentation> mInstrumentation = + final ArrayMap<ComponentName, ParsedInstrumentation> mInstrumentation = new ArrayMap<>(); // Packages whose data we have transfered into another package, thus @@ -1039,13 +1055,13 @@ public class PackageManagerService extends IPackageManager.Stub final ActivityInfo mResolveActivity = new ActivityInfo(); final ResolveInfo mResolveInfo = new ResolveInfo(); ComponentName mResolveComponentName; - PackageParser.Package mPlatformPackage; + AndroidPackage mPlatformPackage; ComponentName mCustomResolverComponentName; boolean mResolverReplaced = false; private final @Nullable ComponentName mIntentFilterVerifierComponent; - private final @Nullable IntentFilterVerifier<ActivityIntentInfo> mIntentFilterVerifier; + private final @Nullable IntentFilterVerifier<ParsedActivityIntentInfo> mIntentFilterVerifier; private int mIntentFilterVerificationToken = 0; @@ -1080,14 +1096,19 @@ public class PackageManagerService extends IPackageManager.Stub private final IncrementalManager mIncrementalManager; private static class IFVerificationParams { - PackageParser.Package pkg; + String packageName; + boolean hasDomainUrls; + List<ParsedActivity> activities; boolean replacing; int userId; int verifierUid; - public IFVerificationParams(PackageParser.Package _pkg, boolean _replacing, + public IFVerificationParams(String packageName, boolean hasDomainUrls, + List<ParsedActivity> activities, boolean _replacing, int _userId, int _verifierUid) { - pkg = _pkg; + this.packageName = packageName; + this.hasDomainUrls = hasDomainUrls; + this.activities = activities; replacing = _replacing; userId = _userId; verifierUid = _verifierUid; @@ -1101,7 +1122,7 @@ public class PackageManagerService extends IPackageManager.Stub void receiveVerificationResponse(int verificationId); } - private class IntentVerifierProxy implements IntentFilterVerifier<ActivityIntentInfo> { + private class IntentVerifierProxy implements IntentFilterVerifier<ParsedActivityIntentInfo> { private Context mContext; private ComponentName mIntentFilterVerifierComponent; private ArrayList<Integer> mCurrentIntentFilterVerifications = new ArrayList<>(); @@ -1126,11 +1147,11 @@ public class PackageManagerService extends IPackageManager.Stub String packageName = ivs.getPackageName(); - ArrayList<PackageParser.ActivityIntentInfo> filters = ivs.getFilters(); + ArrayList<ParsedActivityIntentInfo> filters = ivs.getFilters(); final int filterCount = filters.size(); ArraySet<String> domainsSet = new ArraySet<>(); for (int m=0; m<filterCount; m++) { - PackageParser.ActivityIntentInfo filter = filters.get(m); + ParsedActivityIntentInfo filter = filters.get(m); domainsSet.addAll(filter.getHostsList()); } synchronized (mLock) { @@ -1182,14 +1203,14 @@ public class PackageManagerService extends IPackageManager.Stub final boolean verified = ivs.isVerified(); - ArrayList<PackageParser.ActivityIntentInfo> filters = ivs.getFilters(); + ArrayList<ParsedActivityIntentInfo> filters = ivs.getFilters(); final int count = filters.size(); if (DEBUG_DOMAIN_VERIFICATION) { Slog.i(TAG, "Received verification response " + verificationId + " for " + count + " filters, verified=" + verified); } for (int n=0; n<count; n++) { - PackageParser.ActivityIntentInfo filter = filters.get(n); + ParsedActivityIntentInfo filter = filters.get(n); filter.setVerified(verified); if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "IntentFilter " + filter.toString() @@ -1302,7 +1323,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean addOneIntentFilterVerification(int verifierUid, int userId, int verificationId, - ActivityIntentInfo filter, String packageName) { + ParsedActivityIntentInfo filter, String packageName) { if (!hasValidDomains(filter)) { return false; } @@ -1331,7 +1352,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - private static boolean hasValidDomains(ActivityIntentInfo filter) { + private static boolean hasValidDomains(ParsedActivityIntentInfo filter) { return filter.hasCategory(Intent.CATEGORY_BROWSABLE) && (filter.hasDataScheme(IntentFilter.SCHEME_HTTP) || filter.hasDataScheme(IntentFilter.SCHEME_HTTPS)); @@ -1598,7 +1619,7 @@ public class PackageManagerService extends IPackageManager.Stub final List<String> whitelistedRestrictedPermissions = ((args.installFlags & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) != 0 && parentRes.pkg != null) - ? parentRes.pkg.requestedPermissions + ? parentRes.pkg.getRequestedPermissions() : args.whitelistedRestrictedPermissions; // Handle the parent package @@ -1744,8 +1765,8 @@ public class PackageManagerService extends IPackageManager.Stub } case START_INTENT_FILTER_VERIFICATIONS: { IFVerificationParams params = (IFVerificationParams) msg.obj; - verifyIntentFiltersIfNeeded(params.userId, params.verifierUid, - params.replacing, params.pkg); + verifyIntentFiltersIfNeeded(params.userId, params.verifierUid, params.replacing, + params.packageName, params.hasDomainUrls, params.activities); break; } case INTENT_FILTER_VERIFIED: { @@ -1895,20 +1916,11 @@ public class PackageManagerService extends IPackageManager.Stub ? res.removedInfo.installerPackageName : null; - // If this is the first time we have child packages for a disabled privileged - // app that had no children, we grant requested runtime permissions to the new - // children if the parent on the system image had them already granted. - if (res.pkg.parentPackage != null) { - final int callingUid = Binder.getCallingUid(); - mPermissionManager.grantRuntimePermissionsGrantedToDisabledPackage( - res.pkg, callingUid); - } - synchronized (mLock) { mInstantAppRegistry.onPackageInstalledLPw(res.pkg, res.newUsers); } - final String packageName = res.pkg.applicationInfo.packageName; + final String packageName = res.pkg.getAppInfoPackageName(); // Determine the set of users who are adding this package for // the first time vs. those who are seeing an update. @@ -1917,7 +1929,7 @@ public class PackageManagerService extends IPackageManager.Stub int[] updateUserIds = EMPTY_INT_ARRAY; int[] instantUserIds = EMPTY_INT_ARRAY; final boolean allNewUsers = res.origUsers == null || res.origUsers.length == 0; - final PackageSetting ps = (PackageSetting) res.pkg.mExtras; + final PackageSetting ps = getPackageSetting(res.pkg.getPackageName()); for (int newUser : res.newUsers) { final boolean isInstantApp = ps.getInstantApp(newUser); if (allNewUsers) { @@ -1951,13 +1963,14 @@ public class PackageManagerService extends IPackageManager.Stub } // Send installed broadcasts if the package is not a static shared lib. - if (res.pkg.staticSharedLibName == null) { - mProcessLoggingHandler.invalidateProcessLoggingBaseApkHash(res.pkg.baseCodePath); + if (res.pkg.getStaticSharedLibName() == null) { + mProcessLoggingHandler.invalidateProcessLoggingBaseApkHash( + res.pkg.getBaseCodePath()); // Send added for users that see the package for the first time // sendPackageAddedForNewUsers also deals with system apps int appId = UserHandle.getAppId(res.uid); - boolean isSystem = res.pkg.applicationInfo.isSystemApp(); + boolean isSystem = res.pkg.isSystemApp(); sendPackageAddedForNewUsers(packageName, isSystem || virtualPreload, virtualPreload /*startReceiver*/, appId, firstUserIds, firstInstantUserIds); @@ -2035,26 +2048,26 @@ public class PackageManagerService extends IPackageManager.Stub final StorageManager storage = mInjector.getStorageManager(); VolumeInfo volume = storage.findVolumeByUuid( - res.pkg.applicationInfo.storageUuid.toString()); + res.pkg.getStorageUuid().toString()); int packageExternalStorageType = getPackageExternalStorageType(volume, isExternal(res.pkg)); // If the package was installed externally, log it. if (packageExternalStorageType != StorageEnums.UNKNOWN) { StatsLog.write(StatsLog.APP_INSTALL_ON_EXTERNAL_STORAGE_REPORTED, - packageExternalStorageType, res.pkg.packageName); + packageExternalStorageType, res.pkg.getPackageName()); } } if (DEBUG_INSTALL) { Slog.i(TAG, "upgrading pkg " + res.pkg + " is external"); } - final int[] uidArray = new int[]{res.pkg.applicationInfo.uid}; + final int[] uidArray = new int[]{res.pkg.getUid()}; ArrayList<String> pkgList = new ArrayList<>(1); pkgList.add(packageName); sendResourcesChangedBroadcast(true, true, pkgList, uidArray, null); } } else if (!ArrayUtils.isEmpty(res.libraryConsumers)) { // if static shared lib for (int i = 0; i < res.libraryConsumers.size(); i++) { - PackageParser.Package pkg = res.libraryConsumers.get(i); + AndroidPackage pkg = res.libraryConsumers.get(i); // send broadcast that all consumers of the static shared library have changed sendPackageChangedBroadcast(pkg.packageName, false /* dontKillApp */, new ArrayList<>(Collections.singletonList(pkg.packageName)), @@ -2188,7 +2201,7 @@ public class PackageManagerService extends IPackageManager.Stub private void scheduleDeferredNoKillInstallObserver(PackageInstalledInfo info, IPackageInstallObserver2 observer) { - String packageName = info.pkg.packageName; + String packageName = info.pkg.getPackageName(); mNoKillInstallObservers.put(packageName, Pair.create(info, observer)); Message message = mHandler.obtainMessage(DEFERRED_NO_KILL_INSTALL_OBSERVER, packageName); mHandler.sendMessageDelayed(message, DEFERRED_NO_KILL_INSTALL_OBSERVER_DELAY_MS); @@ -2783,11 +2796,11 @@ public class PackageManagerService extends IPackageManager.Stub final List<String> stubSystemApps = new ArrayList<>(); if (!mOnlyCore) { // do this first before mucking with mPackages for the "expecting better" case - final Iterator<PackageParser.Package> pkgIterator = mPackages.values().iterator(); + final Iterator<AndroidPackage> pkgIterator = mPackages.values().iterator(); while (pkgIterator.hasNext()) { - final PackageParser.Package pkg = pkgIterator.next(); - if (pkg.isStub) { - stubSystemApps.add(pkg.packageName); + final AndroidPackage pkg = pkgIterator.next(); + if (pkg.isStub()) { + stubSystemApps.add(pkg.getPackageName()); } } @@ -2806,7 +2819,7 @@ public class PackageManagerService extends IPackageManager.Stub /* * If the package is scanned, it's not erased. */ - final PackageParser.Package scannedPkg = mPackages.get(ps.name); + final AndroidPackage scannedPkg = mPackages.get(ps.name); if (scannedPkg != null) { /* * If the system app is both scanned and in the @@ -2883,7 +2896,7 @@ public class PackageManagerService extends IPackageManager.Stub // app completely. Otherwise, revoke their system privileges. for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) { final String packageName = possiblyDeletedUpdatedSystemApps.get(i); - final PackageParser.Package pkg = mPackages.get(packageName); + final AndroidPackage pkg = mPackages.get(packageName); final String msg; // remove from the disabled system list; do this first so any future @@ -2909,7 +2922,7 @@ public class PackageManagerService extends IPackageManager.Stub // special privileges removePackageLI(pkg, true); try { - final File codePath = new File(pkg.applicationInfo.getCodePath()); + final File codePath = new File(pkg.getAppInfoCodePath()); scanPackageTracedLI(codePath, 0, scanFlags, 0, null); } catch (PackageManagerException e) { Slog.e(TAG, "Failed to parse updated, ex-system package: " @@ -3105,7 +3118,7 @@ public class PackageManagerService extends IPackageManager.Stub } int count = 0; for (String pkgName : deferPackages) { - PackageParser.Package pkg = null; + AndroidPackage pkg = null; synchronized (mLock) { PackageSetting ps = mSettings.getPackageLPr(pkgName); if (ps != null && ps.getInstalled(UserHandle.USER_SYSTEM)) { @@ -3205,12 +3218,12 @@ public class PackageManagerService extends IPackageManager.Stub // Initialize InstantAppRegistry's Instant App list for all users. final int[] userIds = UserManagerService.getInstance().getUserIds(); - for (PackageParser.Package pkg : mPackages.values()) { + for (AndroidPackage pkg : mPackages.values()) { if (pkg.isSystem()) { continue; } for (int userId : userIds) { - final PackageSetting ps = (PackageSetting) pkg.mExtras; + final PackageSetting ps = getPackageSetting(pkg.getPackageName()); if (ps == null || !ps.getInstantApp(userId) || !ps.getInstalled(userId)) { continue; } @@ -3297,7 +3310,7 @@ public class PackageManagerService extends IPackageManager.Stub continue; } // skip if the package isn't installed (?!); this should never happen - final PackageParser.Package pkg = mPackages.get(packageName); + final AndroidPackage pkg = mPackages.get(packageName); if (pkg == null) { systemStubPackageNames.remove(i); continue; @@ -3341,43 +3354,46 @@ public class PackageManagerService extends IPackageManager.Stub * APK will be installed and the package will be disabled. To recover from this situation, * the user will need to go into system settings and re-enable the package. */ - private boolean enableCompressedPackage(PackageParser.Package stubPkg) { + private boolean enableCompressedPackage(AndroidPackage stubPkg) { final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY | PackageParser.PARSE_ENFORCE_CODE; synchronized (mInstallLock) { - final PackageParser.Package pkg; + final AndroidPackage pkg; try (PackageFreezer freezer = - freezePackage(stubPkg.packageName, "setEnabledSetting")) { + freezePackage(stubPkg.getPackageName(), "setEnabledSetting")) { pkg = installStubPackageLI(stubPkg, parseFlags, 0 /*scanFlags*/); synchronized (mLock) { prepareAppDataAfterInstallLIF(pkg); try { - updateSharedLibrariesLocked(pkg, null, mPackages); + updateSharedLibrariesLocked(pkg, null, + Collections.unmodifiableMap(mPackages)); } catch (PackageManagerException e) { Slog.e(TAG, "updateAllSharedLibrariesLPw failed: ", e); } - mPermissionManager.updatePermissions(pkg.packageName, pkg); + mPermissionManager.updatePermissions(pkg.getPackageName(), pkg); mSettings.writeLPr(); } } catch (PackageManagerException e) { // Whoops! Something went very wrong; roll back to the stub and disable the package try (PackageFreezer freezer = - freezePackage(stubPkg.packageName, "setEnabledSetting")) { + freezePackage(stubPkg.getPackageName(), "setEnabledSetting")) { synchronized (mLock) { // NOTE: Ensure the system package is enabled; even for a compressed stub. // If we don't, installing the system package fails during scan enableSystemPackageLPw(stubPkg); } - installPackageFromSystemLIF(stubPkg.codePath, + installPackageFromSystemLIF(stubPkg.getCodePath(), null /*allUserHandles*/, null /*origUserHandles*/, null /*origPermissionsState*/, true /*writeSettings*/); } catch (PackageManagerException pme) { // Serious WTF; we have to be able to install the stub - Slog.wtf(TAG, "Failed to restore system package:" + stubPkg.packageName, pme); + Slog.wtf(TAG, "Failed to restore system package:" + stubPkg.getPackageName(), + pme); } finally { // Disable the package; the stub by itself is not runnable synchronized (mLock) { - final PackageSetting stubPs = mSettings.mPackages.get(stubPkg.packageName); + final PackageSetting stubPs = mSettings.mPackages.get( + stubPkg.getPackageName()); if (stubPs != null) { stubPs.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, UserHandle.USER_SYSTEM, "android"); @@ -3389,31 +3405,33 @@ public class PackageManagerService extends IPackageManager.Stub } clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); - mDexManager.notifyPackageUpdated(pkg.packageName, - pkg.baseCodePath, pkg.splitCodePaths); + mDexManager.notifyPackageUpdated(pkg.getPackageName(), + pkg.getBaseCodePath(), pkg.getSplitCodePaths()); } return true; } - private PackageParser.Package installStubPackageLI(PackageParser.Package stubPkg, + private AndroidPackage installStubPackageLI(AndroidPackage stubPkg, @ParseFlags int parseFlags, @ScanFlags int scanFlags) throws PackageManagerException { if (DEBUG_COMPRESSION) { - Slog.i(TAG, "Uncompressing system stub; pkg: " + stubPkg.packageName); + Slog.i(TAG, "Uncompressing system stub; pkg: " + stubPkg.getPackageName()); } // uncompress the binary to its eventual destination on /data - final File scanFile = decompressPackage(stubPkg.packageName, stubPkg.codePath); + final File scanFile = decompressPackage(stubPkg.getPackageName(), stubPkg.getCodePath()); if (scanFile == null) { - throw new PackageManagerException("Unable to decompress stub at " + stubPkg.codePath); + throw new PackageManagerException( + "Unable to decompress stub at " + stubPkg.getCodePath()); } synchronized (mLock) { - mSettings.disableSystemPackageLPw(stubPkg.packageName, true /*replaced*/); + mSettings.disableSystemPackageLPw(stubPkg.getPackageName(), true /*replaced*/); } removePackageLI(stubPkg, true /*chatty*/); try { return scanPackageTracedLI(scanFile, parseFlags, scanFlags, 0, null); } catch (PackageManagerException e) { - Slog.w(TAG, "Failed to install compressed system package:" + stubPkg.packageName, e); + Slog.w(TAG, "Failed to install compressed system package:" + stubPkg.getPackageName(), + e); // Remove the failed install removeCodePathLI(scanFile); throw e; @@ -3496,18 +3514,20 @@ public class PackageManagerService extends IPackageManager.Stub } private static @Nullable File preparePackageParserCache() { - if (!DEFAULT_PACKAGE_PARSER_CACHE_ENABLED) { - return null; - } + if (!FORCE_PACKAGE_PARSED_CACHE_ENABLED) { + if (!DEFAULT_PACKAGE_PARSER_CACHE_ENABLED) { + return null; + } - // Disable package parsing on eng builds to allow for faster incremental development. - if (Build.IS_ENG) { - return null; - } + // Disable package parsing on eng builds to allow for faster incremental development. + if (Build.IS_ENG) { + return null; + } - if (SystemProperties.getBoolean("pm.boot.disable_package_cache", false)) { - Slog.i(TAG, "Disabling package parser cache due to system property."); - return null; + if (SystemProperties.getBoolean("pm.boot.disable_package_cache", false)) { + Slog.i(TAG, "Disabling package parser cache due to system property."); + return null; + } } // The base directory for the package parser cache lives under /data/system/. @@ -3519,10 +3539,12 @@ public class PackageManagerService extends IPackageManager.Stub // There are several items that need to be combined together to safely // identify cached items. In particular, changing the value of certain // feature flags should cause us to invalidate any caches. - final String cacheName = SystemProperties.digestOf( - "ro.build.fingerprint", - StorageManager.PROP_ISOLATED_STORAGE, - StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT); + final String cacheName = FORCE_PACKAGE_PARSED_CACHE_ENABLED ? "debug" + : SystemProperties.digestOf( + "ro.build.fingerprint", + StorageManager.PROP_ISOLATED_STORAGE, + StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT + ); // Reconcile cache directories, keeping only what we'd actually use. for (File cacheDir : FileUtils.listFilesOrEmpty(cacheBaseDir)) { @@ -3846,7 +3868,7 @@ public class PackageManagerService extends IPackageManager.Stub ArraySet<String> packages = systemConfig.getLinkedApps(); for (String packageName : packages) { - PackageParser.Package pkg = mPackages.get(packageName); + AndroidPackage pkg = mPackages.get(packageName); if (pkg != null) { if (!pkg.isSystem()) { Slog.w(TAG, "Non-system app '" + packageName + "' in sysconfig <app-link>"); @@ -3854,13 +3876,15 @@ public class PackageManagerService extends IPackageManager.Stub } ArraySet<String> domains = null; - for (PackageParser.Activity a : pkg.activities) { - for (ActivityIntentInfo filter : a.intents) { - if (hasValidDomains(filter)) { - if (domains == null) { - domains = new ArraySet<>(); + if (pkg.getActivities() != null) { + for (ParsedActivity a : pkg.getActivities()) { + for (ParsedActivityIntentInfo filter : a.intents) { + if (hasValidDomains(filter)) { + if (domains == null) { + domains = new ArraySet<>(); + } + domains.addAll(filter.getHostsList()); } - domains.addAll(filter.getHostsList()); } } } @@ -3976,7 +4000,7 @@ public class PackageManagerService extends IPackageManager.Stub } final PackageUserState state = ps.readUserState(userId); - PackageParser.Package p = ps.pkg; + AndroidPackage p = ps.pkg; if (p != null) { final PermissionsState permissionsState = ps.getPermissionsState(); @@ -3984,10 +4008,10 @@ public class PackageManagerService extends IPackageManager.Stub final int[] gids = (flags & PackageManager.GET_GIDS) == 0 ? EMPTY_INT_ARRAY : permissionsState.computeGids(userId); // Compute granted permissions only if package has requested permissions - final Set<String> permissions = ArrayUtils.isEmpty(p.requestedPermissions) + final Set<String> permissions = ArrayUtils.isEmpty(p.getRequestedPermissions()) ? Collections.emptySet() : permissionsState.getPermissions(userId); - PackageInfo packageInfo = PackageParser.generatePackageInfo(p, gids, flags, + PackageInfo packageInfo = PackageInfoUtils.generate(p, gids, flags, ps.firstInstallTime, ps.lastUpdateTime, permissions, state, userId); if (packageInfo == null) { @@ -4050,7 +4074,7 @@ public class PackageManagerService extends IPackageManager.Stub throw new SecurityException("Package " + packageName + " is currently frozen!"); } - if (!userKeyUnlocked && !ps.pkg.applicationInfo.isEncryptionAware()) { + if (!userKeyUnlocked && !ps.pkg.isEncryptionAware()) { throw new SecurityException("Package " + packageName + " is not encryption aware!"); } } @@ -4063,9 +4087,9 @@ public class PackageManagerService extends IPackageManager.Stub mPermissionManager.enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/, false /*checkShell*/, "is package available"); synchronized (mLock) { - PackageParser.Package p = mPackages.get(packageName); + AndroidPackage p = mPackages.get(packageName); if (p != null) { - final PackageSetting ps = (PackageSetting) p.mExtras; + final PackageSetting ps = getPackageSetting(p.getPackageName()); if (shouldFilterApplicationLocked(ps, callingUid, userId)) { return false; } @@ -4130,21 +4154,22 @@ public class PackageManagerService extends IPackageManager.Stub } } - PackageParser.Package p = mPackages.get(packageName); + AndroidPackage p = mPackages.get(packageName); if (matchFactoryOnly && p != null && !isSystemApp(p)) { return null; } if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getPackageInfo " + packageName + ": " + p); if (p != null) { - final PackageSetting ps = (PackageSetting) p.mExtras; + final PackageSetting ps = getPackageSetting(p.getPackageName()); if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) { return null; } if (ps != null && shouldFilterApplicationLocked(ps, filterCallingUid, userId)) { return null; } - return generatePackageInfo((PackageSetting)p.mExtras, flags, userId); + + return generatePackageInfo(ps, flags, userId); } if (!matchFactoryOnly && (flags & MATCH_KNOWN_PACKAGES) != 0) { final PackageSetting ps = mSettings.mPackages.get(packageName); @@ -4180,34 +4205,34 @@ public class PackageManagerService extends IPackageManager.Stub private boolean isComponentVisibleToInstantApp( @Nullable ComponentName component, @ComponentType int type) { if (type == TYPE_ACTIVITY) { - final PackageParser.Activity activity = mComponentResolver.getActivity(component); + final ParsedActivity activity = mComponentResolver.getActivity(component); if (activity == null) { return false; } final boolean visibleToInstantApp = - (activity.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0; + (activity.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0; final boolean explicitlyVisibleToInstantApp = - (activity.info.flags & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0; + (activity.flags & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0; return visibleToInstantApp && explicitlyVisibleToInstantApp; } else if (type == TYPE_RECEIVER) { - final PackageParser.Activity activity = mComponentResolver.getReceiver(component); + final ParsedActivity activity = mComponentResolver.getReceiver(component); if (activity == null) { return false; } final boolean visibleToInstantApp = - (activity.info.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0; + (activity.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0; final boolean explicitlyVisibleToInstantApp = - (activity.info.flags & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0; + (activity.flags & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0; return visibleToInstantApp && !explicitlyVisibleToInstantApp; } else if (type == TYPE_SERVICE) { - final PackageParser.Service service = mComponentResolver.getService(component); + final ParsedService service = mComponentResolver.getService(component); return service != null - ? (service.info.flags & ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0 + ? (service.flags & ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0 : false; } else if (type == TYPE_PROVIDER) { - final PackageParser.Provider provider = mComponentResolver.getProvider(component); + final ParsedProvider provider = mComponentResolver.getProvider(component); return provider != null - ? (provider.info.flags & ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0 + ? (provider.getFlags() & ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0 : false; } else if (type == TYPE_UNKNOWN) { return isComponentVisibleToInstantApp(component); @@ -4251,16 +4276,16 @@ public class PackageManagerService extends IPackageManager.Stub // request for a specific component; if it hasn't been explicitly exposed through // property or instrumentation target, filter if (component != null) { - final PackageParser.Instrumentation instrumentation = + final ParsedInstrumentation instrumentation = mInstrumentation.get(component); if (instrumentation != null - && isCallerSameApp(instrumentation.info.targetPackage, callingUid)) { + && isCallerSameApp(instrumentation.getTargetPackage(), callingUid)) { return false; } return !isComponentVisibleToInstantApp(component, componentType); } // request for application; if no components have been explicitly exposed, filter - return !ps.pkg.visibleToInstantApps; + return !ps.pkg.isVisibleToInstantApps(); } if (ps.getInstantApp(userId)) { // caller can see all components of all instant applications, don't filter @@ -4309,12 +4334,12 @@ public class PackageManagerService extends IPackageManager.Stub } // No package means no static lib as it is always on internal storage - if (ps == null || ps.pkg == null || !ps.pkg.applicationInfo.isStaticSharedLibrary()) { + if (ps == null || ps.pkg == null || !ps.pkg.isStaticSharedLibrary()) { return false; } - final SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(ps.pkg.staticSharedLibName, - ps.pkg.staticSharedLibVersion); + final SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr( + ps.pkg.getStaticSharedLibName(), ps.pkg.getStaticSharedLibVersion()); if (libraryInfo == null) { return false; } @@ -4336,7 +4361,8 @@ public class PackageManagerService extends IPackageManager.Stub if (index < 0) { continue; } - if (uidPs.pkg.usesStaticLibrariesVersions[index] == libraryInfo.getLongVersion()) { + if (uidPs.pkg.getUsesStaticLibrariesVersions()[index] + == libraryInfo.getLongVersion()) { return false; } } @@ -4410,13 +4436,13 @@ public class PackageManagerService extends IPackageManager.Stub // reader synchronized (mLock) { - final PackageParser.Package p = mPackages.get(packageName); + final AndroidPackage p = mPackages.get(packageName); if (p != null && p.isMatch(flags)) { - PackageSetting ps = (PackageSetting) p.mExtras; + PackageSetting ps = getPackageSetting(p.getPackageName()); if (shouldFilterApplicationLocked(ps, callingUid, userId)) { return -1; } - return UserHandle.getUid(userId, p.applicationInfo.uid); + return UserHandle.getUid(userId, p.getUid()); } if ((flags & MATCH_KNOWN_PACKAGES) != 0) { final PackageSetting ps = mSettings.mPackages.get(packageName); @@ -4440,9 +4466,9 @@ public class PackageManagerService extends IPackageManager.Stub // reader synchronized (mLock) { - final PackageParser.Package p = mPackages.get(packageName); + final AndroidPackage p = mPackages.get(packageName); if (p != null && p.isMatch(flags)) { - PackageSetting ps = (PackageSetting) p.mExtras; + PackageSetting ps = getPackageSetting(p.getPackageName()); if (shouldFilterApplicationLocked(ps, callingUid, userId)) { return null; } @@ -4492,7 +4518,7 @@ public class PackageManagerService extends IPackageManager.Stub } return null; } - ApplicationInfo ai = PackageParser.generateApplicationInfo(ps.pkg, flags, + ApplicationInfo ai = PackageInfoUtils.generateApplicationInfo(ps.pkg, flags, ps.readUserState(userId), userId); if (ai != null) { ai.packageName = resolveExternalPackageNameLPr(ps.pkg); @@ -4530,7 +4556,7 @@ public class PackageManagerService extends IPackageManager.Stub packageName = resolveInternalPackageNameLPr(packageName, PackageManager.VERSION_CODE_HIGHEST); - PackageParser.Package p = mPackages.get(packageName); + AndroidPackage p = mPackages.get(packageName); if (DEBUG_PACKAGE_INFO) Log.v( TAG, "getApplicationInfo " + packageName + ": " + p); @@ -4544,7 +4570,7 @@ public class PackageManagerService extends IPackageManager.Stub return null; } // Note: isEnabledLP() does not apply here - always return info - ApplicationInfo ai = PackageParser.generateApplicationInfo( + ApplicationInfo ai = PackageInfoUtils.generateApplicationInfo( p, flags, ps.readUserState(userId), userId); if (ai != null) { ai.packageName = resolveExternalPackageNameLPr(p); @@ -4916,17 +4942,19 @@ public class PackageManagerService extends IPackageManager.Stub } synchronized (mLock) { - PackageParser.Activity a = mComponentResolver.getActivity(component); + ParsedActivity a = mComponentResolver.getActivity(component); if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a); - if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) { + + AndroidPackage pkg = a == null ? null : mPackages.get(a.getPackageName()); + if (pkg != null && mSettings.isEnabledAndMatchLPr(pkg, a, flags, userId)) { PackageSetting ps = mSettings.mPackages.get(component.getPackageName()); if (ps == null) return null; if (shouldFilterApplicationLocked( ps, filterCallingUid, component, TYPE_ACTIVITY, userId)) { return null; } - return PackageParser.generateActivityInfo( + return PackageInfoUtils.generateActivityInfo(pkg, a, flags, ps.readUserState(userId), userId); } if (mResolveComponentName.equals(component)) { @@ -4963,7 +4991,7 @@ public class PackageManagerService extends IPackageManager.Stub } final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); - PackageParser.Activity a = mComponentResolver.getActivity(component); + ParsedActivity a = mComponentResolver.getActivity(component); if (a == null) { return false; } @@ -4993,17 +5021,27 @@ public class PackageManagerService extends IPackageManager.Stub mPermissionManager.enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */, false /* checkShell */, "get receiver info"); synchronized (mLock) { - PackageParser.Activity a = mComponentResolver.getReceiver(component); + ParsedActivity a = mComponentResolver.getReceiver(component); if (DEBUG_PACKAGE_INFO) Log.v( TAG, "getReceiverInfo " + component + ": " + a); - if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) { + + if (a == null) { + return null; + } + + AndroidPackage pkg = mPackages.get(a.getPackageName()); + if (pkg == null) { + return null; + } + + if (mSettings.isEnabledAndMatchLPr(pkg, a, flags, userId)) { PackageSetting ps = mSettings.mPackages.get(component.getPackageName()); if (ps == null) return null; if (shouldFilterApplicationLocked( ps, callingUid, component, TYPE_RECEIVER, userId)) { return null; } - return PackageParser.generateActivityInfo( + return PackageInfoUtils.generateActivityInfo(pkg, a, flags, ps.readUserState(userId), userId); } } @@ -5182,13 +5220,13 @@ public class PackageManagerService extends IPackageManager.Stub } // If the dependent is a static shared lib, use the public package name String dependentPackageName = ps.name; - if (ps.pkg != null && ps.pkg.applicationInfo.isStaticSharedLibrary()) { - dependentPackageName = ps.pkg.manifestPackageName; + if (ps.pkg != null && ps.pkg.isStaticSharedLibrary()) { + dependentPackageName = ps.pkg.getManifestPackageName(); } versionedPackages.add(new VersionedPackage(dependentPackageName, ps.versionCode)); } else if (ps.pkg != null) { - if (ArrayUtils.contains(ps.pkg.usesLibraries, libName) - || ArrayUtils.contains(ps.pkg.usesOptionalLibraries, libName)) { + if (ArrayUtils.contains(ps.pkg.getUsesLibraries(), libName) + || ArrayUtils.contains(ps.pkg.getUsesOptionalLibraries(), libName)) { if (versionedPackages == null) { versionedPackages = new ArrayList<>(); } @@ -5208,17 +5246,22 @@ public class PackageManagerService extends IPackageManager.Stub mPermissionManager.enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */, false /* checkShell */, "get service info"); synchronized (mLock) { - PackageParser.Service s = mComponentResolver.getService(component); + ParsedService s = mComponentResolver.getService(component); if (DEBUG_PACKAGE_INFO) Log.v( - TAG, "getServiceInfo " + component + ": " + s); - if (s != null && mSettings.isEnabledAndMatchLPr(s.info, flags, userId)) { + TAG, "getServiceInfo " + component + ": " + s); + if (s == null) { + return null; + } + + AndroidPackage pkg = mPackages.get(s.getPackageName()); + if (mSettings.isEnabledAndMatchLPr(pkg, s, flags, userId)) { PackageSetting ps = mSettings.mPackages.get(component.getPackageName()); if (ps == null) return null; if (shouldFilterApplicationLocked( ps, callingUid, component, TYPE_SERVICE, userId)) { return null; } - return PackageParser.generateServiceInfo( + return PackageInfoUtils.generateServiceInfo(pkg, s, flags, ps.readUserState(userId), userId); } } @@ -5233,18 +5276,27 @@ public class PackageManagerService extends IPackageManager.Stub mPermissionManager.enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */, false /* checkShell */, "get provider info"); synchronized (mLock) { - PackageParser.Provider p = mComponentResolver.getProvider(component); + ParsedProvider p = mComponentResolver.getProvider(component); if (DEBUG_PACKAGE_INFO) Log.v( - TAG, "getProviderInfo " + component + ": " + p); - if (p != null && mSettings.isEnabledAndMatchLPr(p.info, flags, userId)) { + TAG, "getProviderInfo " + component + ": " + p); + if (p == null) { + return null; + } + + AndroidPackage pkg = mPackages.get(p.getPackageName()); + if (pkg == null) { + return null; + } + + if (mSettings.isEnabledAndMatchLPr(pkg, p, flags, userId)) { PackageSetting ps = mSettings.mPackages.get(component.getPackageName()); if (ps == null) return null; if (shouldFilterApplicationLocked( ps, callingUid, component, TYPE_PROVIDER, userId)) { return null; } - return PackageParser.generateProviderInfo( - p, flags, ps.readUserState(userId), userId); + PackageUserState state = ps.readUserState(userId); + return PackageInfoUtils.generateProviderInfo(pkg, p, flags, state, userId); } } return null; @@ -5502,21 +5554,21 @@ public class PackageManagerService extends IPackageManager.Stub @Override public int checkSignatures(String pkg1, String pkg2) { synchronized (mLock) { - final PackageParser.Package p1 = mPackages.get(pkg1); - final PackageParser.Package p2 = mPackages.get(pkg2); - if (p1 == null || p1.mExtras == null - || p2 == null || p2.mExtras == null) { + final AndroidPackage p1 = mPackages.get(pkg1); + final AndroidPackage p2 = mPackages.get(pkg2); + final PackageSetting ps1 = p1 == null ? null : getPackageSetting(p1.getPackageName()); + final PackageSetting ps2 = p2 == null ? null : getPackageSetting(p2.getPackageName()); + if (p1 == null || ps1 == null || p2 == null || ps2 == null) { return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; } final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); - final PackageSetting ps1 = (PackageSetting) p1.mExtras; - final PackageSetting ps2 = (PackageSetting) p2.mExtras; if (shouldFilterApplicationLocked(ps1, callingUid, callingUserId) || shouldFilterApplicationLocked(ps2, callingUid, callingUserId)) { return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; } - return compareSignatures(p1.mSigningDetails.signatures, p2.mSigningDetails.signatures); + return compareSignatures(p1.getSigningDetails().signatures, + p2.getSigningDetails().signatures); } } @@ -5579,21 +5631,21 @@ public class PackageManagerService extends IPackageManager.Stub String packageName, byte[] certificate, @PackageManager.CertificateInputType int type) { synchronized (mLock) { - final PackageParser.Package p = mPackages.get(packageName); - if (p == null || p.mExtras == null) { + final AndroidPackage p = mPackages.get(packageName); + final PackageSetting ps = getPackageSetting(p.getPackageName()); + if (p == null || ps == null) { return false; } final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); - final PackageSetting ps = (PackageSetting) p.mExtras; if (shouldFilterApplicationLocked(ps, callingUid, callingUserId)) { return false; } switch (type) { case CERT_INPUT_RAW_X509: - return p.mSigningDetails.hasCertificate(certificate); + return p.getSigningDetails().hasCertificate(certificate); case CERT_INPUT_SHA256: - return p.mSigningDetails.hasSha256Certificate(certificate); + return p.getSigningDetails().hasSha256Certificate(certificate); default: return false; } @@ -5646,16 +5698,16 @@ public class PackageManagerService extends IPackageManager.Stub * external storage) is less than the version where package signatures * were updated, return true. */ - private boolean isCompatSignatureUpdateNeeded(PackageParser.Package scannedPkg) { - return isCompatSignatureUpdateNeeded(getSettingsVersionForPackage(scannedPkg)); + private boolean isCompatSignatureUpdateNeeded(AndroidPackage pkg) { + return isCompatSignatureUpdateNeeded(getSettingsVersionForPackage(pkg)); } private static boolean isCompatSignatureUpdateNeeded(VersionInfo ver) { return ver.databaseVersion < DatabaseVersion.SIGNATURE_END_ENTITY; } - private boolean isRecoverSignatureUpdateNeeded(PackageParser.Package scannedPkg) { - return isRecoverSignatureUpdateNeeded(getSettingsVersionForPackage(scannedPkg)); + private boolean isRecoverSignatureUpdateNeeded(AndroidPackage pkg) { + return isRecoverSignatureUpdateNeeded(getSettingsVersionForPackage(pkg)); } private static boolean isRecoverSignatureUpdateNeeded(VersionInfo ver) { @@ -5674,24 +5726,23 @@ public class PackageManagerService extends IPackageManager.Stub final List<String> result = new ArrayList<>(); if (instantAppPkgName != null) { // caller is an instant application; filter unexposed applications - for (PackageParser.Package pkg : mPackages.values()) { - if (!pkg.visibleToInstantApps) { + for (AndroidPackage pkg : mPackages.values()) { + if (!pkg.isVisibleToInstantApps()) { continue; } - result.add(pkg.packageName); + result.add(pkg.getPackageName()); } } else { // caller is a normal application; filter instant applications - for (PackageParser.Package pkg : mPackages.values()) { - final PackageSetting ps = - pkg.mExtras != null ? (PackageSetting) pkg.mExtras : null; + for (AndroidPackage pkg : mPackages.values()) { + final PackageSetting ps = getPackageSetting(pkg.getPackageName()); if (ps != null && ps.getInstantApp(callingUserId) && !mInstantAppRegistry.isInstantAccessGranted( callingUserId, UserHandle.getAppId(callingUid), ps.appId)) { continue; } - result.add(pkg.packageName); + result.add(pkg.getPackageName()); } } return result; @@ -6535,7 +6586,7 @@ public class PackageManagerService extends IPackageManager.Stub if (obj instanceof PackageSetting) { final PackageSetting ps = (PackageSetting) obj; final boolean isInstantApp = ps.getInstantApp(UserHandle.getUserId(callingUid)); - return isInstantApp ? ps.pkg.packageName : null; + return isInstantApp ? ps.pkg.getPackageName() : null; } } return null; @@ -6607,9 +6658,11 @@ public class PackageManagerService extends IPackageManager.Stub list.add(ri); } } - return applyPostResolutionFilter( + + List<ResolveInfo> result = applyPostResolutionFilter( list, instantAppPkgName, allowDynamicSplits, filterCallingUid, resolveForStart, userId, intent); + return result; } // reader @@ -6686,11 +6739,11 @@ public class PackageManagerService extends IPackageManager.Stub sortResult = true; } } else { - final PackageParser.Package pkg = mPackages.get(pkgName); + final AndroidPackage pkg = mPackages.get(pkgName); result = null; if (pkg != null) { result = filterIfNotSystemUser(mComponentResolver.queryActivities( - intent, resolvedType, flags, pkg.activities, userId), userId); + intent, resolvedType, flags, pkg.getActivities(), userId), userId); } if (result == null || result.size() == 0) { // the caller wants to resolve for a particular package; however, there @@ -7584,7 +7637,7 @@ public class PackageManagerService extends IPackageManager.Stub result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId, intent); } - final PackageParser.Package pkg = mPackages.get(pkgName); + final AndroidPackage pkg = mPackages.get(pkgName); if (pkg != null) { final List<ResolveInfo> result = mComponentResolver.queryReceivers( intent, resolvedType, flags, pkg.receivers, userId); @@ -7693,7 +7746,7 @@ public class PackageManagerService extends IPackageManager.Stub resolveInfos, instantAppPkgName); } - final PackageParser.Package pkg = mPackages.get(pkgName); + final AndroidPackage pkg = mPackages.get(pkgName); if (pkg != null) { final List<ResolveInfo> resolveInfos = mComponentResolver.queryServices(intent, resolvedType, flags, pkg.services, @@ -7820,7 +7873,7 @@ public class PackageManagerService extends IPackageManager.Stub resolveInfos, instantAppPkgName); } - final PackageParser.Package pkg = mPackages.get(pkgName); + final AndroidPackage pkg = mPackages.get(pkgName); if (pkg != null) { final List<ResolveInfo> resolveInfos = mComponentResolver.queryProviders(intent, resolvedType, flags, @@ -7914,16 +7967,15 @@ public class PackageManagerService extends IPackageManager.Stub } } else { list = new ArrayList<>(mPackages.size()); - for (PackageParser.Package p : mPackages.values()) { - final PackageSetting ps = (PackageSetting) p.mExtras; + for (AndroidPackage p : mPackages.values()) { + final PackageSetting ps = getPackageSetting(p.getPackageName()); if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) { continue; } if (shouldFilterApplicationLocked(ps, callingUid, userId)) { continue; } - final PackageInfo pi = generatePackageInfo((PackageSetting) - p.mExtras, flags, userId); + final PackageInfo pi = generatePackageInfo(ps, flags, userId); if (pi != null) { list.add(pi); } @@ -8002,8 +8054,8 @@ public class PackageManagerService extends IPackageManager.Stub userId); } } else { - for (PackageParser.Package pkg : mPackages.values()) { - PackageSetting ps = (PackageSetting)pkg.mExtras; + for (AndroidPackage pkg : mPackages.values()) { + PackageSetting ps = getPackageSetting(pkg.getPackageName()); if (ps != null) { addPackageHoldingPermissions(list, ps, permissions, tmpBools, flags, userId); @@ -8056,7 +8108,7 @@ public class PackageManagerService extends IPackageManager.Stub if (shouldFilterApplicationLocked(ps, callingUid, userId)) { continue; } - ai = PackageParser.generateApplicationInfo(ps.pkg, effectiveFlags, + ai = PackageInfoUtils.generateApplicationInfo(ps.pkg, effectiveFlags, ps.readUserState(userId), userId); if (ai != null) { ai.packageName = resolveExternalPackageNameLPr(ps.pkg); @@ -8073,16 +8125,16 @@ public class PackageManagerService extends IPackageManager.Stub } } else { list = new ArrayList<>(mPackages.size()); - for (PackageParser.Package p : mPackages.values()) { - if (p.mExtras != null) { - PackageSetting ps = (PackageSetting) p.mExtras; + for (AndroidPackage p : mPackages.values()) { + final PackageSetting ps = getPackageSetting(p.getPackageName()); + if (ps != null) { if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) { continue; } if (shouldFilterApplicationLocked(ps, callingUid, userId)) { continue; } - ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags, + ApplicationInfo ai = PackageInfoUtils.generateApplicationInfo(p, flags, ps.readUserState(userId), userId); if (ai != null) { ai.packageName = resolveExternalPackageNameLPr(p); @@ -8138,7 +8190,6 @@ public class PackageManagerService extends IPackageManager.Stub callingUid = mIsolatedOwners.get(callingUid); } final PackageSetting ps = mSettings.mPackages.get(packageName); - PackageParser.Package pkg = mPackages.get(packageName); final boolean returnAllowed = ps != null && (isCallerSameApp(packageName, callingUid) @@ -8209,9 +8260,9 @@ public class PackageManagerService extends IPackageManager.Stub } private boolean isCallerSameApp(String packageName, int uid) { - PackageParser.Package pkg = mPackages.get(packageName); + AndroidPackage pkg = mPackages.get(packageName); return pkg != null - && UserHandle.getAppId(uid) == pkg.applicationInfo.uid; + && UserHandle.getAppId(uid) == pkg.getUid(); } @Override @@ -8227,23 +8278,22 @@ public class PackageManagerService extends IPackageManager.Stub // reader synchronized (mLock) { - final Iterator<PackageParser.Package> i = mPackages.values().iterator(); + final Iterator<AndroidPackage> i = mPackages.values().iterator(); final int userId = UserHandle.getCallingUserId(); while (i.hasNext()) { - final PackageParser.Package p = i.next(); - if (p.applicationInfo == null) continue; + final AndroidPackage p = i.next(); final boolean matchesUnaware = ((flags & MATCH_DIRECT_BOOT_UNAWARE) != 0) - && !p.applicationInfo.isDirectBootAware(); + && !p.isDirectBootAware(); final boolean matchesAware = ((flags & MATCH_DIRECT_BOOT_AWARE) != 0) - && p.applicationInfo.isDirectBootAware(); + && p.isDirectBootAware(); - if ((p.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0 + if ((p.getFlags() & ApplicationInfo.FLAG_PERSISTENT) != 0 && (!mSafeMode || isSystemApp(p)) && (matchesUnaware || matchesAware)) { - PackageSetting ps = mSettings.mPackages.get(p.packageName); + PackageSetting ps = mSettings.mPackages.get(p.getPackageName()); if (ps != null) { - ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags, + ApplicationInfo ai = PackageInfoUtils.generateApplicationInfo(p, flags, ps.readUserState(userId), userId); if (ai != null) { finalList.add(ai); @@ -8265,7 +8315,8 @@ public class PackageManagerService extends IPackageManager.Stub if (!mUserManager.exists(userId)) return null; flags = updateFlagsForComponent(flags, userId); final int callingUid = Binder.getCallingUid(); - final ProviderInfo providerInfo = mComponentResolver.queryProvider(name, flags, userId); + final ProviderInfo providerInfo = mComponentResolver.queryProvider(name, flags, callingUid, + userId); if (providerInfo == null) { return null; } @@ -8347,8 +8398,8 @@ public class PackageManagerService extends IPackageManager.Stub ps, callingUid, component, TYPE_UNKNOWN, callingUserId)) { return null; } - final PackageParser.Instrumentation i = mInstrumentation.get(component); - return PackageParser.generateInstrumentationInfo(i, flags); + final ParsedInstrumentation i = mInstrumentation.get(component); + return PackageInfoUtils.generateInstrumentationInfo(i, flags); } } @@ -8370,12 +8421,12 @@ public class PackageManagerService extends IPackageManager.Stub // reader synchronized (mLock) { - final Iterator<PackageParser.Instrumentation> i = mInstrumentation.values().iterator(); + final Iterator<ParsedInstrumentation> i = mInstrumentation.values().iterator(); while (i.hasNext()) { - final PackageParser.Instrumentation p = i.next(); + final ParsedInstrumentation p = i.next(); if (targetPackage == null - || targetPackage.equals(p.info.targetPackage)) { - InstrumentationInfo ii = PackageParser.generateInstrumentationInfo(p, + || targetPackage.equals(p.getTargetPackage())) { + InstrumentationInfo ii = PackageInfoUtils.generateInstrumentationInfo(p, flags); if (ii != null) { finalList.add(ii); @@ -8432,18 +8483,18 @@ public class PackageManagerService extends IPackageManager.Stub if (throwable == null) { // TODO(toddke): move lower in the scan chain // Static shared libraries have synthetic package names - if (parseResult.pkg.applicationInfo.isStaticSharedLibrary()) { - renameStaticSharedLibraryPackage(parseResult.pkg); + if (parseResult.parsedPackage.isStaticSharedLibrary()) { + renameStaticSharedLibraryPackage(parseResult.parsedPackage); } try { - scanPackageChildLI(parseResult.pkg, parseFlags, scanFlags, + addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags, currentTime, null); } catch (PackageManagerException e) { errorCode = e.error; Slog.w(TAG, "Failed to scan " + parseResult.scanFile + ": " + e.getMessage()); } - } else if (throwable instanceof PackageParser.PackageParserException) { - PackageParser.PackageParserException e = (PackageParser.PackageParserException) + } else if (throwable instanceof PackageParserException) { + PackageParserException e = (PackageParserException) throwable; errorCode = e.error; Slog.w(TAG, "Failed to parse " + parseResult.scanFile + ": " + e.getMessage()); @@ -8467,15 +8518,16 @@ public class PackageManagerService extends IPackageManager.Stub logCriticalInfo(priority, msg); } - private void collectCertificatesLI(PackageSetting ps, PackageParser.Package pkg, + private void collectCertificatesLI(PackageSetting ps, ParsedPackage parsedPackage, boolean forceCollect, boolean skipVerify) throws PackageManagerException { // When upgrading from pre-N MR1, verify the package time stamp using the package // directory and not the APK file. final long lastModifiedTime = mIsPreNMR1Upgrade - ? new File(pkg.codePath).lastModified() : getLastModifiedTime(pkg); - final VersionInfo settingsVersionForPackage = getSettingsVersionForPackage(pkg); + ? new File(parsedPackage.getCodePath()).lastModified() + : getLastModifiedTime(parsedPackage); + final VersionInfo settingsVersionForPackage = getSettingsVersionForPackage(parsedPackage); if (ps != null && !forceCollect - && ps.codePathString.equals(pkg.codePath) + && ps.codePathString.equals(parsedPackage.getCodePath()) && ps.timeStamp == lastModifiedTime && !isCompatSignatureUpdateNeeded(settingsVersionForPackage) && !isRecoverSignatureUpdateNeeded(settingsVersionForPackage)) { @@ -8485,21 +8537,21 @@ public class PackageManagerService extends IPackageManager.Stub != SignatureSchemeVersion.UNKNOWN) { // Optimization: reuse the existing cached signing data // if the package appears to be unchanged. - pkg.mSigningDetails = - new PackageParser.SigningDetails(ps.signatures.mSigningDetails); + parsedPackage.setSigningDetails( + new PackageParser.SigningDetails(ps.signatures.mSigningDetails)); return; } Slog.w(TAG, "PackageSetting for " + ps.name + " is missing signatures. Collecting certs again to recover them."); } else { - Slog.i(TAG, pkg.codePath + " changed; collecting certs" + + Slog.i(TAG, parsedPackage.getCodePath() + " changed; collecting certs" + (forceCollect ? " (forced)" : "")); } try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates"); - PackageParser.collectCertificates(pkg, skipVerify); + ApkParseUtils.collectCertificates(parsedPackage, skipVerify); } catch (PackageParserException e) { throw PackageManagerException.from(e); } finally { @@ -8513,20 +8565,20 @@ public class PackageManagerService extends IPackageManager.Stub */ private void maybeClearProfilesForUpgradesLI( @Nullable PackageSetting originalPkgSetting, - @NonNull PackageParser.Package currentPkg) { + @NonNull AndroidPackage pkg) { if (originalPkgSetting == null || !isDeviceUpgrading()) { return; } - if (originalPkgSetting.versionCode == currentPkg.mVersionCode) { + if (originalPkgSetting.versionCode == pkg.getVersionCode()) { return; } - clearAppProfilesLIF(currentPkg, UserHandle.USER_ALL); + clearAppProfilesLIF(pkg, UserHandle.USER_ALL); if (DEBUG_INSTALL) { Slog.d(TAG, originalPkgSetting.name + " clear profile due to version change " + originalPkgSetting.versionCode + " != " - + currentPkg.mVersionCode); + + pkg.getVersionCode()); } } @@ -8535,7 +8587,7 @@ public class PackageManagerService extends IPackageManager.Stub * @see #scanPackageLI(File, int, int, long, UserHandle) */ @GuardedBy({"mInstallLock", "mLock"}) - private PackageParser.Package scanPackageTracedLI(File scanFile, final int parseFlags, + private AndroidPackage scanPackageTracedLI(File scanFile, final int parseFlags, int scanFlags, long currentTime, UserHandle user) throws PackageManagerException { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage [" + scanFile.toString() + "]"); try { @@ -8550,7 +8602,7 @@ public class PackageManagerService extends IPackageManager.Stub * Returns {@code null} in case of errors and the error code is stored in mLastScanError */ @GuardedBy({"mInstallLock", "mLock"}) - private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags, + private AndroidPackage scanPackageLI(File scanFile, int parseFlags, int scanFlags, long currentTime, UserHandle user) throws PackageManagerException { if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile); PackageParser pp = new PackageParser(); @@ -8560,9 +8612,9 @@ public class PackageManagerService extends IPackageManager.Stub pp.setCallback(mPackageParserCallback); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage"); - final PackageParser.Package pkg; + final ParsedPackage parsedPackage; try { - pkg = pp.parsePackage(scanFile, parseFlags); + parsedPackage = pp.parseParsedPackage(scanFile, parseFlags, false); } catch (PackageParserException e) { throw PackageManagerException.from(e); } finally { @@ -8570,66 +8622,25 @@ public class PackageManagerService extends IPackageManager.Stub } // Static shared libraries have synthetic package names - if (pkg.applicationInfo.isStaticSharedLibrary()) { - renameStaticSharedLibraryPackage(pkg); + if (parsedPackage.isStaticSharedLibrary()) { + renameStaticSharedLibraryPackage(parsedPackage); } - return scanPackageChildLI(pkg, parseFlags, scanFlags, currentTime, user); - } - - /** - * Scans a package and returns the newly parsed package. - * @throws PackageManagerException on a parse error. - */ - @GuardedBy({"mInstallLock", "mLock"}) - private PackageParser.Package scanPackageChildLI(PackageParser.Package pkg, - final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime, - @Nullable UserHandle user) - throws PackageManagerException { - // If the package has children and this is the first dive in the function - // we scan the package with the SCAN_CHECK_ONLY flag set to see whether all - // packages (parent and children) would be successfully scanned before the - // actual scan since scanning mutates internal state and we want to atomically - // install the package and its children. - if ((scanFlags & SCAN_CHECK_ONLY) == 0) { - if (pkg.childPackages != null && pkg.childPackages.size() > 0) { - scanFlags |= SCAN_CHECK_ONLY; - } - } else { - scanFlags &= ~SCAN_CHECK_ONLY; - } - - // Scan the parent - PackageParser.Package scannedPkg = addForInitLI(pkg, parseFlags, - scanFlags, currentTime, user); - - // Scan the children - final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; - for (int i = 0; i < childCount; i++) { - PackageParser.Package childPackage = pkg.childPackages.get(i); - addForInitLI(childPackage, parseFlags, scanFlags, - currentTime, user); - } - - - if ((scanFlags & SCAN_CHECK_ONLY) != 0) { - return scanPackageChildLI(pkg, parseFlags, scanFlags, currentTime, user); - } - - return scannedPkg; + return addForInitLI(parsedPackage, parseFlags, scanFlags, currentTime, user); } /** * Returns if forced apk verification can be skipped for the whole package, including splits. */ - private boolean canSkipForcedPackageVerification(PackageParser.Package pkg) { - if (!canSkipForcedApkVerification(pkg.baseCodePath)) { + private boolean canSkipForcedPackageVerification(AndroidPackage pkg) { + if (!canSkipForcedApkVerification(pkg.getBaseCodePath())) { return false; } // TODO: Allow base and splits to be verified individually. - if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { - for (int i = 0; i < pkg.splitCodePaths.length; i++) { - if (!canSkipForcedApkVerification(pkg.splitCodePaths[i])) { + String[] splitCodePaths = pkg.getSplitCodePaths(); + if (!ArrayUtils.isEmpty(splitCodePaths)) { + for (int i = 0; i < splitCodePaths.length; i++) { + if (!canSkipForcedApkVerification(splitCodePaths[i])) { return false; } } @@ -8678,7 +8689,7 @@ public class PackageManagerService extends IPackageManager.Stub * <p>NOTE: The return value should be removed. It's the passed in package object. */ @GuardedBy({"mInstallLock", "mLock"}) - private PackageParser.Package addForInitLI(PackageParser.Package pkg, + private AndroidPackage addForInitLI(ParsedPackage parsedPackage, @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime, @Nullable UserHandle user) throws PackageManagerException { @@ -8694,22 +8705,23 @@ public class PackageManagerService extends IPackageManager.Stub // stack [such as scanPackageOnly()]. However, we verify the application // info prior to that [in scanPackageNew()] and thus have to setup // the application info early. - pkg.setApplicationVolumeUuid(pkg.volumeUuid); - pkg.setApplicationInfoCodePath(pkg.codePath); - pkg.setApplicationInfoBaseCodePath(pkg.baseCodePath); - pkg.setApplicationInfoSplitCodePaths(pkg.splitCodePaths); - pkg.setApplicationInfoResourcePath(pkg.codePath); - pkg.setApplicationInfoBaseResourcePath(pkg.baseCodePath); - pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths); + // TODO(b/135203078): Remove all of these application info calls + parsedPackage.setApplicationVolumeUuid(parsedPackage.getVolumeUuid()) + .setApplicationInfoCodePath(parsedPackage.getCodePath()) + .setApplicationInfoResourcePath(parsedPackage.getCodePath()) + .setApplicationInfoBaseResourcePath(parsedPackage.getBaseCodePath()) + .setApplicationInfoSplitResourcePaths(parsedPackage.getSplitCodePaths()); synchronized (mLock) { - renamedPkgName = mSettings.getRenamedPackageLPr(pkg.mRealPackage); - final String realPkgName = getRealPackageName(pkg, renamedPkgName); + renamedPkgName = mSettings.getRenamedPackageLPr(parsedPackage.getRealPackage()); + final String realPkgName = getRealPackageName(parsedPackage, renamedPkgName); if (realPkgName != null) { - ensurePackageRenamed(pkg, renamedPkgName); + ensurePackageRenamed(parsedPackage, renamedPkgName); } - final PackageSetting originalPkgSetting = getOriginalPackageLocked(pkg, renamedPkgName); - final PackageSetting installedPkgSetting = mSettings.getPackageLPr(pkg.packageName); + final PackageSetting originalPkgSetting = getOriginalPackageLocked(parsedPackage, + renamedPkgName); + final PackageSetting installedPkgSetting = mSettings.getPackageLPr( + parsedPackage.getPackageName()); pkgSetting = originalPkgSetting == null ? installedPkgSetting : originalPkgSetting; pkgAlreadyExists = pkgSetting != null; final String disabledPkgName = pkgAlreadyExists ? pkgSetting.name : pkg.packageName; @@ -8730,49 +8742,29 @@ public class PackageManagerService extends IPackageManager.Stub Slog.d(TAG, "updatedPkg = " + disabledPkgSetting); } - final SharedUserSetting sharedUserSetting = (pkg.mSharedUserId != null) - ? mSettings.getSharedUserLPw(pkg.mSharedUserId, + final SharedUserSetting sharedUserSetting = (parsedPackage.getSharedUserId() != null) + ? mSettings.getSharedUserLPw(parsedPackage.getSharedUserId(), 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, true) : null; if (DEBUG_PACKAGE_SCANNING && (parseFlags & PackageParser.PARSE_CHATTY) != 0 && sharedUserSetting != null) { - Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + Log.d(TAG, "Shared UserID " + parsedPackage.getSharedUserId() + " (uid=" + sharedUserSetting.userId + "):" + " packages=" + sharedUserSetting.packages); } if (scanSystemPartition) { - // Potentially prune child packages. If the application on the /system - // partition has been updated via OTA, but, is still disabled by a - // version on /data, cycle through all of its children packages and - // remove children that are no longer defined. if (isSystemPkgUpdated) { - final int scannedChildCount = (pkg.childPackages != null) - ? pkg.childPackages.size() : 0; - final int disabledChildCount = disabledPkgSetting.childPackageNames != null - ? disabledPkgSetting.childPackageNames.size() : 0; - for (int i = 0; i < disabledChildCount; i++) { - String disabledChildPackageName = - disabledPkgSetting.childPackageNames.get(i); - boolean disabledPackageAvailable = false; - for (int j = 0; j < scannedChildCount; j++) { - PackageParser.Package childPkg = pkg.childPackages.get(j); - if (childPkg.packageName.equals(disabledChildPackageName)) { - disabledPackageAvailable = true; - break; - } - } - if (!disabledPackageAvailable) { - mSettings.removeDisabledSystemPackageLPw(disabledChildPackageName); - } - } // we're updating the disabled package, so, scan it as the package setting - final ScanRequest request = new ScanRequest(pkg, sharedUserSetting, null, - disabledPkgSetting /* pkgSetting */, null /* disabledPkgSetting */, - null /* originalPkgSetting */, null, parseFlags, scanFlags, - (pkg == mPlatformPackage), user); - applyPolicy(pkg, parseFlags, scanFlags, mPlatformPackage); + boolean isPlatformPackage = mPlatformPackage != null + && Objects.equals(mPlatformPackage.getPackageName(), + parsedPackage.getPackageName()); + final ScanRequest request = new ScanRequest(parsedPackage, sharedUserSetting, + null, disabledPkgSetting /* pkgSetting */, + null /* disabledPkgSetting */, null /* originalPkgSetting */, + null, parseFlags, scanFlags, isPlatformPackage, user); + applyPolicy(parsedPackage, parseFlags, scanFlags, mPlatformPackage); final ScanResult scanResult = scanPackageOnlyLI(request, mInjector, mFactoryTest, -1L); if (scanResult.existingSettingCopied && scanResult.request.pkgSetting != null) { @@ -8783,9 +8775,9 @@ public class PackageManagerService extends IPackageManager.Stub } final boolean newPkgChangedPaths = - pkgAlreadyExists && !pkgSetting.codePathString.equals(pkg.codePath); + pkgAlreadyExists && !pkgSetting.codePathString.equals(parsedPackage.getCodePath()); final boolean newPkgVersionGreater = - pkgAlreadyExists && pkg.getLongVersionCode() > pkgSetting.versionCode; + pkgAlreadyExists && parsedPackage.getLongVersionCode() > pkgSetting.versionCode; final boolean isSystemPkgBetter = scanSystemPartition && isSystemPkgUpdated && newPkgChangedPaths && newPkgVersionGreater; if (isSystemPkgBetter) { @@ -8801,12 +8793,13 @@ public class PackageManagerService extends IPackageManager.Stub logCriticalInfo(Log.WARN, "System package updated;" + " name: " + pkgSetting.name - + "; " + pkgSetting.versionCode + " --> " + pkg.getLongVersionCode() - + "; " + pkgSetting.codePathString + " --> " + pkg.codePath); + + "; " + pkgSetting.versionCode + " --> " + parsedPackage.getLongVersionCode() + + "; " + pkgSetting.codePathString + " --> " + parsedPackage.getCodePath()); final InstallArgs args = createInstallArgsForExisting( pkgSetting.codePathString, - pkgSetting.resourcePathString, getAppDexInstructionSets(pkgSetting)); + pkgSetting.resourcePathString, getAppDexInstructionSets( + pkgSetting.primaryCpuAbiString, pkgSetting.secondaryCpuAbiString)); args.cleanUpResourcesLI(); synchronized (mLock) { mSettings.enableSystemPackageLPw(pkgSetting.name); @@ -8817,9 +8810,10 @@ public class PackageManagerService extends IPackageManager.Stub // The version of the application on the /system partition is less than or // equal to the version on the /data partition. Throw an exception and use // the application already installed on the /data partition. - throw new PackageManagerException(Log.WARN, "Package " + pkg.packageName + " at " - + pkg.codePath + " ignored: updated version " + pkgSetting.versionCode - + " better than this " + pkg.getLongVersionCode()); + throw new PackageManagerException(Log.WARN, "Package " + parsedPackage.getPackageName() + + " at " + parsedPackage.getCodePath() + " ignored: updated version " + + pkgSetting.versionCode + " better than this " + + parsedPackage.getLongVersionCode()); } // Verify certificates against what was last scanned. Force re-collecting certificate in two @@ -8830,7 +8824,7 @@ public class PackageManagerService extends IPackageManager.Stub final boolean forceCollect = scanSystemPartition ? mIsUpgrade : PackageManagerServiceUtils.isApkVerificationForced(pkgSetting); if (DEBUG_VERIFY && forceCollect) { - Slog.d(TAG, "Force collect certificate of " + pkg.packageName); + Slog.d(TAG, "Force collect certificate of " + parsedPackage.getPackageName()); } // Full APK verification can be skipped during certificate collection, only if the file is @@ -8838,11 +8832,11 @@ public class PackageManagerService extends IPackageManager.Stub // cases, only data in Signing Block is verified instead of the whole file. // TODO(b/136132412): skip for Incremental installation final boolean skipVerify = scanSystemPartition - || (forceCollect && canSkipForcedPackageVerification(pkg)); - collectCertificatesLI(pkgSetting, pkg, forceCollect, skipVerify); + || (forceCollect && canSkipForcedPackageVerification(parsedPackage)); + collectCertificatesLI(pkgSetting, parsedPackage, forceCollect, skipVerify); // Reset profile if the application version is changed - maybeClearProfilesForUpgradesLI(pkgSetting, pkg); + maybeClearProfilesForUpgradesLI(pkgSetting, parsedPackage); /* * A new system app appeared, but we already had a non-system one of the @@ -8854,17 +8848,20 @@ public class PackageManagerService extends IPackageManager.Stub if (scanSystemPartition && !isSystemPkgUpdated && pkgAlreadyExists && !pkgSetting.isSystem()) { - if (!pkg.mSigningDetails.checkCapability(pkgSetting.signatures.mSigningDetails, + if (!parsedPackage.getSigningDetails() + .checkCapability(pkgSetting.signatures.mSigningDetails, PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA) && !pkgSetting.signatures.mSigningDetails.checkCapability( - pkg.mSigningDetails, + parsedPackage.getSigningDetails(), PackageParser.SigningDetails.CertCapabilities.ROLLBACK)) { logCriticalInfo(Log.WARN, "System package signature mismatch;" + " name: " + pkgSetting.name); - try (PackageFreezer freezer = freezePackage(pkg.packageName, + try (@SuppressWarnings("unused") PackageFreezer freezer = freezePackage( + parsedPackage.getPackageName(), "scanPackageInternalLI")) { - deletePackageLIF(pkg.packageName, null, true, null, 0, null, false, null); + deletePackageLIF(parsedPackage.getPackageName(), null, true, null, 0, null, + false, null); } pkgSetting = null; } else if (newPkgVersionGreater) { @@ -8873,12 +8870,15 @@ public class PackageManagerService extends IPackageManager.Stub // and replace it with the version on /system. logCriticalInfo(Log.WARN, "System package enabled;" - + " name: " + pkgSetting.name - + "; " + pkgSetting.versionCode + " --> " + pkg.getLongVersionCode() - + "; " + pkgSetting.codePathString + " --> " + pkg.codePath); + + " name: " + pkgSetting.name + + "; " + pkgSetting.versionCode + " --> " + + parsedPackage.getLongVersionCode() + + "; " + pkgSetting.codePathString + " --> " + + parsedPackage.getCodePath()); InstallArgs args = createInstallArgsForExisting( pkgSetting.codePathString, - pkgSetting.resourcePathString, getAppDexInstructionSets(pkgSetting)); + pkgSetting.resourcePathString, getAppDexInstructionSets( + pkgSetting.primaryCpuAbiString, pkgSetting.secondaryCpuAbiString)); synchronized (mInstallLock) { args.cleanUpResourcesLI(); } @@ -8889,13 +8889,15 @@ public class PackageManagerService extends IPackageManager.Stub shouldHideSystemApp = true; logCriticalInfo(Log.INFO, "System package disabled;" - + " name: " + pkgSetting.name - + "; old: " + pkgSetting.codePathString + " @ " + pkgSetting.versionCode - + "; new: " + pkg.codePath + " @ " + pkg.codePath); + + " name: " + pkgSetting.name + + "; old: " + pkgSetting.codePathString + " @ " + + pkgSetting.versionCode + + "; new: " + parsedPackage.getCodePath() + " @ " + + parsedPackage.getCodePath()); } } - final ScanResult scanResult = scanPackageNewLI(pkg, parseFlags, scanFlags + final ScanResult scanResult = scanPackageNewLI(parsedPackage, parseFlags, scanFlags | SCAN_UPDATE_SIGNATURE, currentTime, user); if (scanResult.success) { synchronized (mLock) { @@ -8908,7 +8910,7 @@ public class PackageManagerService extends IPackageManager.Stub mSharedLibraries, mPackages, Collections.singletonMap( - pkgName, getSettingsVersionForPackage(pkg)), + pkgName, getSettingsVersionForPackage(parsedPackage)), Collections.singletonMap(pkgName, getSharedLibLatestVersionSetting(scanResult))), mSettings.mKeySetManagerService); @@ -8925,16 +8927,17 @@ public class PackageManagerService extends IPackageManager.Stub if (shouldHideSystemApp) { synchronized (mLock) { - mSettings.disableSystemPackageLPw(pkg.packageName, true); + mSettings.disableSystemPackageLPw(parsedPackage.getPackageName(), true); } } return scanResult.pkgSetting.pkg; } - private static void renameStaticSharedLibraryPackage(PackageParser.Package pkg) { + // TODO:(b/135203078): Move to parsing + private static void renameStaticSharedLibraryPackage(ParsedPackage parsedPackage) { // Derive the new package synthetic package name - pkg.setPackageName(pkg.packageName + STATIC_SHARED_LIB_DELIMITER - + pkg.staticSharedLibVersion); + parsedPackage.setPackageName(parsedPackage.getPackageName() + STATIC_SHARED_LIB_DELIMITER + + parsedPackage.getStaticSharedLibVersion()); } static String fixProcessName(String defProcessName, String processName) { @@ -9035,7 +9038,7 @@ public class PackageManagerService extends IPackageManager.Stub return; } - List<PackageParser.Package> pkgs; + List<AndroidPackage> pkgs; synchronized (mLock) { pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this); } @@ -9058,8 +9061,8 @@ public class PackageManagerService extends IPackageManager.Stub /* * Return the prebuilt profile path given a package base code path. */ - private static String getPrebuildProfilePath(PackageParser.Package pkg) { - return pkg.baseCodePath + ".prof"; + private static String getPrebuildProfilePath(AndroidPackage pkg) { + return pkg.getBaseCodePath() + ".prof"; } /** @@ -9068,7 +9071,7 @@ public class PackageManagerService extends IPackageManager.Stub * which are (in order) {@code numberOfPackagesOptimized}, {@code numberOfPackagesSkipped} * and {@code numberOfPackagesFailed}. */ - private int[] performDexOptUpgrade(List<PackageParser.Package> pkgs, boolean showDialog, + private int[] performDexOptUpgrade(List<AndroidPackage> pkgs, boolean showDialog, final int compilationReason, boolean bootComplete) { int numberOfPackagesVisited = 0; @@ -9077,7 +9080,7 @@ public class PackageManagerService extends IPackageManager.Stub int numberOfPackagesFailed = 0; final int numberOfPackagesToDexopt = pkgs.size(); - for (PackageParser.Package pkg : pkgs) { + for (AndroidPackage pkg : pkgs) { numberOfPackagesVisited++; boolean useProfileForDexopt = false; @@ -9093,7 +9096,7 @@ public class PackageManagerService extends IPackageManager.Stub // PackageDexOptimizer to prevent this happening on first boot. The issue // is that we don't have a good way to say "do this only once". if (!mInstaller.copySystemProfile(profileFile.getAbsolutePath(), - pkg.applicationInfo.uid, pkg.packageName, + pkg.getUid(), pkg.getPackageName(), ArtManager.getProfileName(null))) { Log.e(TAG, "Installer failed to copy system profile!"); } else { @@ -9106,11 +9109,12 @@ public class PackageManagerService extends IPackageManager.Stub e); } } else { - PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(pkg.packageName); + PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr( + pkg.getPackageName()); // Handle compressed APKs in this path. Only do this for stubs with profiles to // minimize the number off apps being speed-profile compiled during first boot. // The other paths will not change the filter. - if (disabledPs != null && disabledPs.pkg.isStub) { + if (disabledPs != null && disabledPs.pkg.isStub()) { // The package is the stub one, remove the stub suffix to get the normal // package and APK names. String systemProfilePath = @@ -9129,7 +9133,7 @@ public class PackageManagerService extends IPackageManager.Stub // issue is that we don't have a good way to say "do this only // once". if (!mInstaller.copySystemProfile(profileFile.getAbsolutePath(), - pkg.applicationInfo.uid, pkg.packageName, + pkg.getUid(), pkg.getPackageName(), ArtManager.getProfileName(null))) { Log.e(TAG, "Failed to copy system profile for stub package!"); } else { @@ -9146,7 +9150,7 @@ public class PackageManagerService extends IPackageManager.Stub if (!PackageDexOptimizer.canOptimizePackage(pkg)) { if (DEBUG_DEXOPT) { - Log.i(TAG, "Skipping update of of non-optimizable app " + pkg.packageName); + Log.i(TAG, "Skipping update of non-optimizable app " + pkg.getPackageName()); } numberOfPackagesSkipped++; continue; @@ -9154,7 +9158,7 @@ public class PackageManagerService extends IPackageManager.Stub if (DEBUG_DEXOPT) { Log.i(TAG, "Updating app " + numberOfPackagesVisited + " of " + - numberOfPackagesToDexopt + ": " + pkg.packageName); + numberOfPackagesToDexopt + ": " + pkg.getPackageName()); } if (showDialog) { @@ -9191,7 +9195,7 @@ public class PackageManagerService extends IPackageManager.Stub dexoptFlags |= DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE; } int primaryDexOptStaus = performDexOptTraced(new DexoptOptions( - pkg.packageName, + pkg.getPackageName(), pkgCompilationReason, dexoptFlags)); @@ -9235,11 +9239,11 @@ public class PackageManagerService extends IPackageManager.Stub @GuardedBy("mLock") private void notifyPackageUseLocked(String packageName, int reason) { - final PackageParser.Package p = mPackages.get(packageName); + final AndroidPackage p = mPackages.get(packageName); if (p == null) { return; } - p.mLastPackageUsageTimeInMills[reason] = System.currentTimeMillis(); + p.mutate().setLastPackageUsageTimeInMills(reason, System.currentTimeMillis()); } @Override @@ -9319,7 +9323,7 @@ public class PackageManagerService extends IPackageManager.Stub */ @Override public boolean compileLayouts(String packageName) { - PackageParser.Package pkg; + AndroidPackage pkg; synchronized (mLock) { pkg = mPackages.get(packageName); if (pkg == null) { @@ -9366,7 +9370,7 @@ public class PackageManagerService extends IPackageManager.Stub // Run dexopt on a given package. Returns true if dexopt did not fail, i.e. // if the package can now be considered up to date for the given filter. private int performDexOptInternal(DexoptOptions options) { - PackageParser.Package p; + AndroidPackage p; synchronized (mLock) { p = mPackages.get(options.getPackageName()); if (p == null) { @@ -9389,16 +9393,16 @@ public class PackageManagerService extends IPackageManager.Stub public ArraySet<String> getOptimizablePackages() { ArraySet<String> pkgs = new ArraySet<>(); synchronized (mLock) { - for (PackageParser.Package p : mPackages.values()) { + for (AndroidPackage p : mPackages.values()) { if (PackageDexOptimizer.canOptimizePackage(p)) { - pkgs.add(p.packageName); + pkgs.add(p.getPackageName()); } } } return pkgs; } - private int performDexOptInternalWithDependenciesLI(PackageParser.Package p, + private int performDexOptInternalWithDependenciesLI(AndroidPackage p, DexoptOptions options) { // Select the dex optimizer based on the force parameter. // Note: The force option is rarely used (cmdline input for testing, mostly), so it's OK to @@ -9415,14 +9419,15 @@ public class PackageManagerService extends IPackageManager.Stub // and the first package that uses the library will dexopt it. The // others will see that the compiled code for the library is up to date. Collection<SharedLibraryInfo> deps = findSharedLibraries(p); - final String[] instructionSets = getAppDexInstructionSets(p.applicationInfo); + final String[] instructionSets = getAppDexInstructionSets(p.getPrimaryCpuAbi(), + p.getSecondaryCpuAbi()); if (!deps.isEmpty()) { DexoptOptions libraryOptions = new DexoptOptions(options.getPackageName(), options.getCompilationReason(), options.getCompilerFilter(), options.getSplitName(), options.getFlags() | DexoptOptions.DEXOPT_AS_SHARED_LIBRARY); for (SharedLibraryInfo info : deps) { - PackageParser.Package depPackage = null; + AndroidPackage depPackage = null; synchronized (mLock) { depPackage = mPackages.get(info.getPackageName()); } @@ -9430,7 +9435,7 @@ public class PackageManagerService extends IPackageManager.Stub // TODO: Analyze and investigate if we (should) profile libraries. pdo.performDexOpt(depPackage, instructionSets, getOrCreateCompilerPackageStats(depPackage), - mDexManager.getPackageUseInfoOrDefault(depPackage.packageName), + mDexManager.getPackageUseInfoOrDefault(depPackage.getPackageName()), libraryOptions); } else { // TODO(ngeoffray): Support dexopting system shared libraries. @@ -9439,7 +9444,7 @@ public class PackageManagerService extends IPackageManager.Stub } return pdo.performDexOpt(p, instructionSets, getOrCreateCompilerPackageStats(p), - mDexManager.getPackageUseInfoOrDefault(p.packageName), options); + mDexManager.getPackageUseInfoOrDefault(p.getPackageName()), options); } /** @@ -9480,11 +9485,11 @@ public class PackageManagerService extends IPackageManager.Stub } } - private static List<SharedLibraryInfo> findSharedLibraries(PackageParser.Package p) { - if (p.usesLibraryInfos != null) { + private static List<SharedLibraryInfo> findSharedLibraries(AndroidPackage p) { + if (p.getUsesLibraryInfos() != null) { ArrayList<SharedLibraryInfo> retValue = new ArrayList<>(); Set<String> collectedNames = new HashSet<>(); - for (SharedLibraryInfo info : p.usesLibraryInfos) { + for (SharedLibraryInfo info : p.getUsesLibraryInfos()) { findSharedLibrariesRecursive(info, retValue, collectedNames); } return retValue; @@ -9507,13 +9512,13 @@ public class PackageManagerService extends IPackageManager.Stub } } - List<PackageParser.Package> findSharedNonSystemLibraries(PackageParser.Package pkg) { + List<AndroidPackage> findSharedNonSystemLibraries(AndroidPackage pkg) { List<SharedLibraryInfo> deps = findSharedLibraries(pkg); if (!deps.isEmpty()) { - ArrayList<PackageParser.Package> retValue = new ArrayList<>(); + ArrayList<AndroidPackage> retValue = new ArrayList<>(); synchronized (mLock) { for (SharedLibraryInfo info : deps) { - PackageParser.Package depPackage = mPackages.get(info.getPackageName()); + AndroidPackage depPackage = mPackages.get(info.getPackageName()); if (depPackage != null) { retValue.add(depPackage); } @@ -9551,9 +9556,9 @@ public class PackageManagerService extends IPackageManager.Stub return versionedLib.get(version); } - private SharedLibraryInfo getLatestSharedLibraVersionLPr(PackageParser.Package pkg) { + private SharedLibraryInfo getLatestSharedLibraVersionLPr(AndroidPackage pkg) { LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get( - pkg.staticSharedLibName); + pkg.getStaticSharedLibName()); if (versionedLib == null) { return null; } @@ -9561,7 +9566,7 @@ public class PackageManagerService extends IPackageManager.Stub final int versionCount = versionedLib.size(); for (int i = 0; i < versionCount; i++) { final long libVersion = versionedLib.keyAt(i); - if (libVersion < pkg.staticSharedLibVersion) { + if (libVersion < pkg.getStaticSharedLibVersion()) { previousLibVersion = Math.max(previousLibVersion, libVersion); } } @@ -9577,7 +9582,7 @@ public class PackageManagerService extends IPackageManager.Stub PackageSetting sharedLibPackage = null; synchronized (mLock) { final SharedLibraryInfo latestSharedLibraVersionLPr = - getLatestSharedLibraVersionLPr(scanResult.pkgSetting.pkg); + getLatestSharedLibraVersionLPr(scanResult.request.parsedPackage); if (latestSharedLibraVersionLPr != null) { sharedLibPackage = mSettings.getPackageLPr( latestSharedLibraVersionLPr.getPackageName()); @@ -9606,7 +9611,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public void dumpProfiles(String packageName) { - PackageParser.Package pkg; + AndroidPackage pkg; synchronized (mLock) { pkg = mPackages.get(packageName); if (pkg == null) { @@ -9617,7 +9622,7 @@ public class PackageManagerService extends IPackageManager.Stub int callingUid = Binder.getCallingUid(); if (callingUid != Process.SHELL_UID && callingUid != Process.ROOT_UID && - callingUid != pkg.applicationInfo.uid) { + callingUid != pkg.getUid()) { throw new SecurityException("dumpProfiles"); } @@ -9632,7 +9637,7 @@ public class PackageManagerService extends IPackageManager.Stub public void forceDexOpt(String packageName) { enforceSystemOrRoot("forceDexOpt"); - PackageParser.Package pkg; + AndroidPackage pkg; synchronized (mLock) { pkg = mPackages.get(packageName); if (pkg == null) { @@ -9659,15 +9664,15 @@ public class PackageManagerService extends IPackageManager.Stub } @GuardedBy("mLock") - private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) { + private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, AndroidPackage newPkg) { if ((oldPkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) { Slog.w(TAG, "Unable to update from " + oldPkg.name - + " to " + newPkg.packageName + + " to " + newPkg.getPackageName() + ": old package not in system partition"); return false; } else if (mPackages.get(oldPkg.name) != null) { Slog.w(TAG, "Unable to update from " + oldPkg.name - + " to " + newPkg.packageName + + " to " + newPkg.getPackageName() + ": old package still exists"); return false; } @@ -9691,122 +9696,86 @@ public class PackageManagerService extends IPackageManager.Stub return (userId == UserHandle.USER_ALL) ? mUserManager.getUserIds() : new int[] { userId }; } - private void clearAppDataLIF(PackageParser.Package pkg, int userId, int flags) { + private void clearAppDataLIF(AndroidPackage pkg, int userId, int flags) { if (pkg == null) { Slog.wtf(TAG, "Package was null!", new Throwable()); return; } clearAppDataLeafLIF(pkg, userId, flags); - final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; - for (int i = 0; i < childCount; i++) { - clearAppDataLeafLIF(pkg.childPackages.get(i), userId, flags); - } if ((flags & Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES) == 0) { clearAppProfilesLIF(pkg, UserHandle.USER_ALL); } } - private void clearAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) { + private void clearAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) { final PackageSetting ps; synchronized (mLock) { - ps = mSettings.mPackages.get(pkg.packageName); + ps = mSettings.mPackages.get(pkg.getPackageName()); } for (int realUserId : resolveUserIds(userId)) { final long ceDataInode = (ps != null) ? ps.getCeDataInode(realUserId) : 0; try { - mInstaller.clearAppData(pkg.volumeUuid, pkg.packageName, realUserId, flags, - ceDataInode); + mInstaller.clearAppData(pkg.getVolumeUuid(), pkg.getPackageName(), realUserId, + flags, ceDataInode); } catch (InstallerException e) { Slog.w(TAG, String.valueOf(e)); } } } - private void destroyAppDataLIF(PackageParser.Package pkg, int userId, int flags) { + private void destroyAppDataLIF(AndroidPackage pkg, int userId, int flags) { if (pkg == null) { Slog.wtf(TAG, "Package was null!", new Throwable()); return; } destroyAppDataLeafLIF(pkg, userId, flags); - final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; - for (int i = 0; i < childCount; i++) { - destroyAppDataLeafLIF(pkg.childPackages.get(i), userId, flags); - } } - private void destroyAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) { + private void destroyAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) { final PackageSetting ps; synchronized (mLock) { - ps = mSettings.mPackages.get(pkg.packageName); + ps = mSettings.mPackages.get(pkg.getPackageName()); } for (int realUserId : resolveUserIds(userId)) { final long ceDataInode = (ps != null) ? ps.getCeDataInode(realUserId) : 0; try { - mInstaller.destroyAppData(pkg.volumeUuid, pkg.packageName, realUserId, flags, - ceDataInode); + mInstaller.destroyAppData(pkg.getVolumeUuid(), pkg.getPackageName(), realUserId, + flags, ceDataInode); } catch (InstallerException e) { Slog.w(TAG, String.valueOf(e)); } - mDexManager.notifyPackageDataDestroyed(pkg.packageName, userId); + mDexManager.notifyPackageDataDestroyed(pkg.getPackageName(), userId); } } - private void destroyAppProfilesLIF(PackageParser.Package pkg) { + private void destroyAppProfilesLIF(AndroidPackage pkg) { if (pkg == null) { Slog.wtf(TAG, "Package was null!", new Throwable()); return; } destroyAppProfilesLeafLIF(pkg); - final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; - for (int i = 0; i < childCount; i++) { - destroyAppProfilesLeafLIF(pkg.childPackages.get(i)); - } } - private void destroyAppProfilesLeafLIF(PackageParser.Package pkg) { + private void destroyAppProfilesLeafLIF(AndroidPackage pkg) { try { - mInstaller.destroyAppProfiles(pkg.packageName); + mInstaller.destroyAppProfiles(pkg.getPackageName()); } catch (InstallerException e) { Slog.w(TAG, String.valueOf(e)); } } - private void clearAppProfilesLIF(PackageParser.Package pkg, int userId) { + private void clearAppProfilesLIF(AndroidPackage pkg, int userId) { if (pkg == null) { Slog.wtf(TAG, "Package was null!", new Throwable()); return; } mArtManagerService.clearAppProfiles(pkg); - final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; - for (int i = 0; i < childCount; i++) { - mArtManagerService.clearAppProfiles(pkg.childPackages.get(i)); - } - } - - private void setInstallAndUpdateTime(PackageParser.Package pkg, long firstInstallTime, - long lastUpdateTime) { - // Set parent install/update time - PackageSetting ps = (PackageSetting) pkg.mExtras; - if (ps != null) { - ps.firstInstallTime = firstInstallTime; - ps.lastUpdateTime = lastUpdateTime; - } - // Set children install/update time - final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; - for (int i = 0; i < childCount; i++) { - PackageParser.Package childPkg = pkg.childPackages.get(i); - ps = (PackageSetting) childPkg.mExtras; - if (ps != null) { - ps.firstInstallTime = firstInstallTime; - ps.lastUpdateTime = lastUpdateTime; - } - } } @GuardedBy("mLock") private void applyDefiningSharedLibraryUpdateLocked( - PackageParser.Package pkg, SharedLibraryInfo libInfo, + AndroidPackage pkg, SharedLibraryInfo libInfo, BiConsumer<SharedLibraryInfo, SharedLibraryInfo> action) { // Note that libraries defined by this package may be null if: // - Package manager was unable to create the shared library. The package still @@ -9815,14 +9784,14 @@ public class PackageManagerService extends IPackageManager.Stub // - Package manager is in a state where package isn't scanned yet. This will // get called again after scanning to fix the dependencies. if (pkg.isLibrary()) { - if (pkg.staticSharedLibName != null) { + if (pkg.getStaticSharedLibName() != null) { SharedLibraryInfo definedLibrary = getSharedLibraryInfoLPr( - pkg.staticSharedLibName, pkg.staticSharedLibVersion); + pkg.getStaticSharedLibName(), pkg.getStaticSharedLibVersion()); if (definedLibrary != null) { action.accept(definedLibrary, libInfo); } } else { - for (String libraryName : pkg.libraryNames) { + for (String libraryName : pkg.getLibraryNames()) { SharedLibraryInfo definedLibrary = getSharedLibraryInfoLPr( libraryName, SharedLibraryInfo.VERSION_UNDEFINED); if (definedLibrary != null) { @@ -9834,19 +9803,19 @@ public class PackageManagerService extends IPackageManager.Stub } @GuardedBy("mLock") - private void addSharedLibraryLPr(PackageParser.Package pkg, Set<String> usesLibraryFiles, - SharedLibraryInfo libInfo, PackageParser.Package changingLib) { + private void addSharedLibraryLPr(AndroidPackage pkg, Set<String> usesLibraryFiles, + SharedLibraryInfo libInfo, AndroidPackage changingLib) { if (libInfo.getPath() != null) { usesLibraryFiles.add(libInfo.getPath()); return; } - PackageParser.Package p = mPackages.get(libInfo.getPackageName()); - if (changingLib != null && changingLib.packageName.equals(libInfo.getPackageName())) { + AndroidPackage p = mPackages.get(libInfo.getPackageName()); + if (changingLib != null && changingLib.getPackageName().equals(libInfo.getPackageName())) { // If we are doing this while in the middle of updating a library apk, // then we need to make sure to use that new apk for determining the // dependencies here. (We haven't yet finished committing the new apk // to the package manager state.) - if (p == null || p.packageName.equals(changingLib.packageName)) { + if (p == null || p.getPackageName().equals(changingLib.getPackageName())) { p = changingLib; } } @@ -9856,23 +9825,23 @@ public class PackageManagerService extends IPackageManager.Stub applyDefiningSharedLibraryUpdateLocked(pkg, libInfo, (definingLibrary, dependency) -> { definingLibrary.addDependency(dependency); }); - if (p.usesLibraryFiles != null) { - Collections.addAll(usesLibraryFiles, p.usesLibraryFiles); + if (p.getUsesLibraryFiles() != null) { + Collections.addAll(usesLibraryFiles, p.getUsesLibraryFiles()); } } } @GuardedBy("mLock") - private void updateSharedLibrariesLocked(PackageParser.Package pkg, - PackageParser.Package changingLib, Map<String, PackageParser.Package> availablePackages) + private void updateSharedLibrariesLocked(AndroidPackage pkg, + AndroidPackage changingLib, Map<String, AndroidPackage> availablePackages) throws PackageManagerException { final ArrayList<SharedLibraryInfo> sharedLibraryInfos = collectSharedLibraryInfos(pkg, availablePackages, mSharedLibraries, null); executeSharedLibrariesUpdateLPr(pkg, changingLib, sharedLibraryInfos); } - private static ArrayList<SharedLibraryInfo> collectSharedLibraryInfos(PackageParser.Package pkg, - Map<String, PackageParser.Package> availablePackages, + private static ArrayList<SharedLibraryInfo> collectSharedLibraryInfos(AndroidPackage pkg, + Map<String, AndroidPackage> availablePackages, @NonNull final Map<String, LongSparseArray<SharedLibraryInfo>> existingLibraries, @Nullable final Map<String, LongSparseArray<SharedLibraryInfo>> newLibraries) throws PackageManagerException { @@ -9883,44 +9852,45 @@ public class PackageManagerService extends IPackageManager.Stub // that libraries are searched in the correct order) and must have no // duplicates. ArrayList<SharedLibraryInfo> usesLibraryInfos = null; - if (pkg.usesLibraries != null) { - usesLibraryInfos = collectSharedLibraryInfos(pkg.usesLibraries, null, null, - pkg.packageName, true, pkg.applicationInfo.targetSdkVersion, null, + if (pkg.getUsesLibraries() != null) { + usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesLibraries(), null, null, + pkg.getPackageName(), true, pkg.getTargetSdkVersion(), null, availablePackages, existingLibraries, newLibraries); } - if (pkg.usesStaticLibraries != null) { - usesLibraryInfos = collectSharedLibraryInfos(pkg.usesStaticLibraries, - pkg.usesStaticLibrariesVersions, pkg.usesStaticLibrariesCertDigests, - pkg.packageName, true, pkg.applicationInfo.targetSdkVersion, usesLibraryInfos, + if (pkg.getUsesStaticLibraries() != null) { + usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesStaticLibraries(), + pkg.getUsesStaticLibrariesVersions(), pkg.getUsesStaticLibrariesCertDigests(), + pkg.getPackageName(), true, pkg.getTargetSdkVersion(), usesLibraryInfos, availablePackages, existingLibraries, newLibraries); } - if (pkg.usesOptionalLibraries != null) { - usesLibraryInfos = collectSharedLibraryInfos(pkg.usesOptionalLibraries, - null, null, pkg.packageName, false, pkg.applicationInfo.targetSdkVersion, + if (pkg.getUsesOptionalLibraries() != null) { + usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesOptionalLibraries(), + null, null, pkg.getPackageName(), false, pkg.getTargetSdkVersion(), usesLibraryInfos, availablePackages, existingLibraries, newLibraries); } return usesLibraryInfos; } - private void executeSharedLibrariesUpdateLPr(PackageParser.Package pkg, - PackageParser.Package changingLib, ArrayList<SharedLibraryInfo> usesLibraryInfos) { + private void executeSharedLibrariesUpdateLPr(AndroidPackage pkg, + AndroidPackage changingLib, ArrayList<SharedLibraryInfo> usesLibraryInfos) { // If the package provides libraries, clear their old dependencies. // This method will set them up again. applyDefiningSharedLibraryUpdateLocked(pkg, null, (definingLibrary, dependency) -> { definingLibrary.clearDependencies(); }); if (usesLibraryInfos != null) { - pkg.usesLibraryInfos = usesLibraryInfos; + pkg.mutate().setUsesLibraryInfos(usesLibraryInfos); // Use LinkedHashSet to preserve the order of files added to // usesLibraryFiles while eliminating duplicates. Set<String> usesLibraryFiles = new LinkedHashSet<>(); for (SharedLibraryInfo libInfo : usesLibraryInfos) { addSharedLibraryLPr(pkg, usesLibraryFiles, libInfo, changingLib); } - pkg.usesLibraryFiles = usesLibraryFiles.toArray(new String[usesLibraryFiles.size()]); + pkg.mutate().setUsesLibraryFiles(usesLibraryFiles.toArray( + new String[usesLibraryFiles.size()])); } else { - pkg.usesLibraryInfos = null; - pkg.usesLibraryFiles = null; + pkg.mutate().setUsesLibraryInfos(null) + .setUsesLibraryFiles(null); } } @@ -9930,7 +9900,7 @@ public class PackageManagerService extends IPackageManager.Stub @Nullable long[] requiredVersions, @Nullable String[][] requiredCertDigests, @NonNull String packageName, boolean required, int targetSdk, @Nullable ArrayList<SharedLibraryInfo> outUsedLibraries, - @NonNull final Map<String, PackageParser.Package> availablePackages, + @NonNull final Map<String, AndroidPackage> availablePackages, @NonNull final Map<String, LongSparseArray<SharedLibraryInfo>> existingLibraries, @Nullable final Map<String, LongSparseArray<SharedLibraryInfo>> newLibraries) throws PackageManagerException { @@ -9959,8 +9929,8 @@ public class PackageManagerService extends IPackageManager.Stub + " library " + libName + " version " + libraryInfo.getLongVersion() + "; failing!"); } - PackageParser.Package libPkg = - availablePackages.get(libraryInfo.getPackageName()); + AndroidPackage pkg = availablePackages.get(libraryInfo.getPackageName()); + SigningDetails libPkg = pkg == null ? null : pkg.getSigningDetails(); if (libPkg == null) { throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY, "Package " + packageName + " requires unavailable static shared" @@ -9971,9 +9941,9 @@ public class PackageManagerService extends IPackageManager.Stub // For apps targeting O MR1 we require explicit enumeration of all certs. final String[] libCertDigests = (targetSdk >= Build.VERSION_CODES.O_MR1) ? PackageUtils.computeSignaturesSha256Digests( - libPkg.mSigningDetails.signatures) + libPkg.signatures) : PackageUtils.computeSignaturesSha256Digests( - new Signature[]{libPkg.mSigningDetails.signatures[0]}); + new Signature[]{libPkg.signatures[0]}); // Take a shortcut if sizes don't match. Note that if an app doesn't // target O we don't parse the "additional-certificate" tags similarly @@ -10003,7 +9973,7 @@ public class PackageManagerService extends IPackageManager.Stub // if the new one has been blessed by the old byte[] digestBytes = HexEncoding.decode( expectedCertDigests[0], false /* allowSingleChar */); - if (!libPkg.mSigningDetails.hasSha256Certificate(digestBytes)) { + if (!libPkg.hasSha256Certificate(digestBytes)) { throw new PackageManagerException( INSTALL_FAILED_MISSING_SHARED_LIBRARY, "Package " + packageName + " requires differently signed" + @@ -10035,28 +10005,28 @@ public class PackageManagerService extends IPackageManager.Stub } @GuardedBy("mLock") - private ArrayList<PackageParser.Package> updateAllSharedLibrariesLocked( - PackageParser.Package updatedPkg, - Map<String, PackageParser.Package> availablePackages) { - ArrayList<PackageParser.Package> resultList = null; + private ArrayList<AndroidPackage> updateAllSharedLibrariesLocked( + AndroidPackage updatedPkg, + Map<String, AndroidPackage> availablePackages) { + ArrayList<AndroidPackage> resultList = null; // Set of all descendants of a library; used to eliminate cycles ArraySet<String> descendants = null; // The current list of packages that need updating - ArrayList<PackageParser.Package> needsUpdating = null; + ArrayList<AndroidPackage> needsUpdating = null; if (updatedPkg != null) { needsUpdating = new ArrayList<>(1); needsUpdating.add(updatedPkg); } do { - final PackageParser.Package changingPkg = + final AndroidPackage changingPkg = (needsUpdating == null) ? null : needsUpdating.remove(0); for (int i = mPackages.size() - 1; i >= 0; --i) { - final PackageParser.Package pkg = mPackages.valueAt(i); + final AndroidPackage pkg = mPackages.valueAt(i); if (changingPkg != null - && !hasString(pkg.usesLibraries, changingPkg.libraryNames) - && !hasString(pkg.usesOptionalLibraries, changingPkg.libraryNames) - && !ArrayUtils.contains(pkg.usesStaticLibraries, - changingPkg.staticSharedLibName)) { + && !hasString(pkg.getUsesLibraries(), changingPkg.getLibraryNames()) + && !hasString(pkg.getUsesOptionalLibraries(), changingPkg.getLibraryNames()) + && !ArrayUtils.contains(pkg.getUsesStaticLibraries(), + changingPkg.getStaticSharedLibName())) { continue; } if (resultList == null) { @@ -10068,8 +10038,8 @@ public class PackageManagerService extends IPackageManager.Stub if (descendants == null) { descendants = new ArraySet<>(); } - if (!descendants.contains(pkg.packageName)) { - descendants.add(pkg.packageName); + if (!descendants.contains(pkg.getPackageName())) { + descendants.add(pkg.getPackageName()); needsUpdating.add(pkg); } } @@ -10084,8 +10054,9 @@ public class PackageManagerService extends IPackageManager.Stub if (!pkg.isSystem() || pkg.isUpdatedSystemApp()) { final int flags = pkg.isUpdatedSystemApp() ? PackageManager.DELETE_KEEP_DATA : 0; - deletePackageLIF(pkg.packageName, null, true, mUserManager.getUserIds(), - flags , null, true, null); + deletePackageLIF(pkg.getPackageName(), null, true, + mUserManager.getUserIds(), flags, null, + true, null); } Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage()); } @@ -10095,43 +10066,15 @@ public class PackageManagerService extends IPackageManager.Stub } @GuardedBy({"mInstallLock", "mLock"}) - private List<ScanResult> scanPackageTracedLI(PackageParser.Package pkg, + private ScanResult scanPackageTracedLI(ParsedPackage parsedPackage, final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime, @Nullable UserHandle user) throws PackageManagerException { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage"); - // If the package has children and this is the first dive in the function - // we recursively scan the package with the SCAN_CHECK_ONLY flag set to see - // whether all packages (parent and children) would be successfully scanned - // before the actual scan since scanning mutates internal state and we want - // to atomically install the package and its children. - if ((scanFlags & SCAN_CHECK_ONLY) == 0) { - if (pkg.childPackages != null && pkg.childPackages.size() > 0) { - scanFlags |= SCAN_CHECK_ONLY; - } - } else { - scanFlags &= ~SCAN_CHECK_ONLY; - } - - final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; - final List<ScanResult> scanResults = new ArrayList<>(1 + childCount); try { - // Scan the parent - scanResults.add(scanPackageNewLI(pkg, parseFlags, scanFlags, currentTime, user)); - // Scan the children - for (int i = 0; i < childCount; i++) { - PackageParser.Package childPkg = pkg.childPackages.get(i); - scanResults.add(scanPackageNewLI(childPkg, parseFlags, - scanFlags, currentTime, user)); - } + return scanPackageNewLI(parsedPackage, parseFlags, scanFlags, currentTime, user); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } - - if ((scanFlags & SCAN_CHECK_ONLY) != 0) { - return scanPackageTracedLI(pkg, parseFlags, scanFlags, currentTime, user); - } - - return scanResults; } /** The result of a package scan. */ @@ -10178,9 +10121,9 @@ public class PackageManagerService extends IPackageManager.Stub @VisibleForTesting static class ScanRequest { /** The parsed package */ - @NonNull public final PackageParser.Package pkg; + @NonNull public final ParsedPackage parsedPackage; /** The package this package replaces */ - @Nullable public final PackageParser.Package oldPkg; + @Nullable public final AndroidPackage oldPkg; /** Shared user settings, if the package has a shared user */ @Nullable public final SharedUserSetting sharedUserSetting; /** @@ -10204,9 +10147,9 @@ public class PackageManagerService extends IPackageManager.Stub /** Whether or not the platform package is being scanned */ public final boolean isPlatformPackage; public ScanRequest( - @NonNull PackageParser.Package pkg, + @NonNull ParsedPackage parsedPackage, @Nullable SharedUserSetting sharedUserSetting, - @Nullable PackageParser.Package oldPkg, + @Nullable AndroidPackage oldPkg, @Nullable PackageSetting pkgSetting, @Nullable PackageSetting disabledPkgSetting, @Nullable PackageSetting originalPkgSetting, @@ -10215,7 +10158,7 @@ public class PackageManagerService extends IPackageManager.Stub @ScanFlags int scanFlags, boolean isPlatformPackage, @Nullable UserHandle user) { - this.pkg = pkg; + this.parsedPackage = parsedPackage; this.oldPkg = oldPkg; this.pkgSetting = pkgSetting; this.sharedUserSetting = sharedUserSetting; @@ -10248,7 +10191,7 @@ public class PackageManagerService extends IPackageManager.Stub */ private @ScanFlags int adjustScanFlags(@ScanFlags int scanFlags, PackageSetting pkgSetting, PackageSetting disabledPkgSetting, UserHandle user, - PackageParser.Package pkg) { + AndroidPackage pkg) { // TODO(patb): Do away entirely with disabledPkgSetting here. PkgSetting will always contain // the correct isSystem value now that we don't disable system packages before scan. @@ -10300,12 +10243,14 @@ public class PackageManagerService extends IPackageManager.Stub && SystemProperties.getInt("ro.vndk.version", 28) < 28; if (((scanFlags & SCAN_AS_PRIVILEGED) == 0) && !pkg.isPrivileged() - && (pkg.mSharedUserId != null) + && (pkg.getSharedUserId() != null) && !skipVendorPrivilegeScan) { SharedUserSetting sharedUserSetting = null; try { - sharedUserSetting = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, 0, false); - } catch (PackageManagerException ignore) {} + sharedUserSetting = mSettings.getSharedUserLPw(pkg.getSharedUserId(), 0, + 0, false); + } catch (PackageManagerException ignore) { + } if (sharedUserSetting != null && sharedUserSetting.isPrivileged()) { // Exempt SharedUsers signed with the platform key. // TODO(b/72378145) Fix this exemption. Force signature apps @@ -10314,7 +10259,8 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mLock) { PackageSetting platformPkgSetting = mSettings.mPackages.get("android"); if ((compareSignatures(platformPkgSetting.signatures.mSigningDetails.signatures, - pkg.mSigningDetails.signatures) != PackageManager.SIGNATURE_MATCH)) { + pkg.getSigningDetails().signatures) + != PackageManager.SIGNATURE_MATCH)) { scanFlags |= SCAN_AS_PRIVILEGED; } } @@ -10329,46 +10275,50 @@ public class PackageManagerService extends IPackageManager.Stub // method. Also, we need to solve the problem of potentially creating a new shared user // setting. That can probably be done later and patch things up after the fact. @GuardedBy({"mInstallLock", "mLock"}) - private ScanResult scanPackageNewLI(@NonNull PackageParser.Package pkg, + private ScanResult scanPackageNewLI(@NonNull ParsedPackage parsedPackage, final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime, @Nullable UserHandle user) throws PackageManagerException { - final String renamedPkgName = mSettings.getRenamedPackageLPr(pkg.mRealPackage); - final String realPkgName = getRealPackageName(pkg, renamedPkgName); + final String renamedPkgName = mSettings.getRenamedPackageLPr( + parsedPackage.getRealPackage()); + final String realPkgName = getRealPackageName(parsedPackage, renamedPkgName); if (realPkgName != null) { - ensurePackageRenamed(pkg, renamedPkgName); + ensurePackageRenamed(parsedPackage, renamedPkgName); } - final PackageSetting originalPkgSetting = getOriginalPackageLocked(pkg, renamedPkgName); - final PackageSetting pkgSetting = mSettings.getPackageLPr(pkg.packageName); + final PackageSetting originalPkgSetting = getOriginalPackageLocked(parsedPackage, + renamedPkgName); + final PackageSetting pkgSetting = mSettings.getPackageLPr(parsedPackage.getPackageName()); final PackageSetting disabledPkgSetting = - mSettings.getDisabledSystemPkgLPr(pkg.packageName); + mSettings.getDisabledSystemPkgLPr(parsedPackage.getPackageName()); - if (mTransferedPackages.contains(pkg.packageName)) { - Slog.w(TAG, "Package " + pkg.packageName + if (mTransferedPackages.contains(parsedPackage.getPackageName())) { + Slog.w(TAG, "Package " + parsedPackage.getPackageName() + " was transferred to another, but its .apk remains"); } - scanFlags = adjustScanFlags(scanFlags, pkgSetting, disabledPkgSetting, user, pkg); + scanFlags = adjustScanFlags(scanFlags, pkgSetting, disabledPkgSetting, user, parsedPackage); synchronized (mLock) { - applyPolicy(pkg, parseFlags, scanFlags, mPlatformPackage); - assertPackageIsValid(pkg, parseFlags, scanFlags); + applyPolicy(parsedPackage, parseFlags, scanFlags, mPlatformPackage); + assertPackageIsValid(parsedPackage, parseFlags, scanFlags); SharedUserSetting sharedUserSetting = null; - if (pkg.mSharedUserId != null) { + if (parsedPackage.getSharedUserId() != null) { // SIDE EFFECTS; may potentially allocate a new shared user - sharedUserSetting = mSettings.getSharedUserLPw( - pkg.mSharedUserId, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, true /*create*/); + sharedUserSetting = mSettings.getSharedUserLPw(parsedPackage.getSharedUserId(), + 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, true /*create*/); if (DEBUG_PACKAGE_SCANNING) { if ((parseFlags & PackageParser.PARSE_CHATTY) != 0) - Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + Log.d(TAG, "Shared UserID " + parsedPackage.getSharedUserId() + " (uid=" + sharedUserSetting.userId + "):" + " packages=" + sharedUserSetting.packages); } } - final ScanRequest request = new ScanRequest(pkg, sharedUserSetting, + String platformPackageName = mPlatformPackage == null + ? null : mPlatformPackage.getPackageName(); + final ScanRequest request = new ScanRequest(parsedPackage, sharedUserSetting, pkgSetting == null ? null : pkgSetting.pkg, pkgSetting, disabledPkgSetting, originalPkgSetting, realPkgName, parseFlags, scanFlags, - (pkg == mPlatformPackage), user); + Objects.equals(parsedPackage.getPackageName(), platformPackageName), user); return scanPackageOnlyLI(request, mInjector, mFactoryTest, currentTime); } } @@ -10411,11 +10361,18 @@ public class PackageManagerService extends IPackageManager.Stub * possible and the system is not left in an inconsistent state. */ @GuardedBy({"mLock", "mInstallLock"}) - private void commitReconciledScanResultLocked(@NonNull ReconciledPackage reconciledPkg) { + private AndroidPackage commitReconciledScanResultLocked( + @NonNull ReconciledPackage reconciledPkg) { final ScanResult result = reconciledPkg.scanResult; final ScanRequest request = result.request; - final PackageParser.Package pkg = request.pkg; - final PackageParser.Package oldPkg = request.oldPkg; + // TODO(b/135203078): Move this even further away + ParsedPackage parsedPackage = request.parsedPackage; + if ("android".equals(parsedPackage.getPackageName())) { + // TODO(b/135203078): Move this to initial parse + parsedPackage.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; @@ -10432,13 +10389,11 @@ public class PackageManagerService extends IPackageManager.Stub if (result.existingSettingCopied) { pkgSetting = request.pkgSetting; pkgSetting.updateFrom(result.pkgSetting); - pkg.mExtras = pkgSetting; } else { pkgSetting = result.pkgSetting; if (originalPkgSetting != null) { - mSettings.addRenamedPackageLPw(pkg.packageName, originalPkgSetting.name); - } - if (originalPkgSetting != null && (scanFlags & SCAN_CHECK_ONLY) == 0) { + mSettings.addRenamedPackageLPw(parsedPackage.getPackageName(), + originalPkgSetting.name); mTransferedPackages.add(originalPkgSetting.name); } } @@ -10451,12 +10406,13 @@ public class PackageManagerService extends IPackageManager.Stub // 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. - pkg.applicationInfo.uid = pkgSetting.appId; + parsedPackage.setUid(pkgSetting.appId); + final AndroidPackage pkg = parsedPackage.hideAsFinal(); mSettings.writeUserRestrictionsLPw(pkgSetting, oldPkgSetting); - if ((scanFlags & SCAN_CHECK_ONLY) == 0 && realPkgName != null) { - mTransferedPackages.add(pkg.packageName); + if (realPkgName != null) { + mTransferedPackages.add(pkg.getPackageName()); } if (reconciledPkg.collectedSharedLibraryInfos != null) { @@ -10465,7 +10421,7 @@ public class PackageManagerService extends IPackageManager.Stub final KeySetManagerService ksms = mSettings.mKeySetManagerService; if (reconciledPkg.removeAppKeySetData) { - ksms.removeAppKeySetDataLPw(pkg.packageName); + ksms.removeAppKeySetDataLPw(pkg.getPackageName()); } if (reconciledPkg.sharedUserSignaturesChanged) { pkgSetting.sharedUser.signaturesChanged = Boolean.TRUE; @@ -10473,17 +10429,17 @@ public class PackageManagerService extends IPackageManager.Stub } pkgSetting.signatures.mSigningDetails = reconciledPkg.signingDetails; - if ((scanFlags & SCAN_CHECK_ONLY) == 0 && pkg.mAdoptPermissions != null) { + if (pkg.getAdoptPermissions() != null) { // This package wants to adopt ownership of permissions from // another package. - for (int i = pkg.mAdoptPermissions.size() - 1; i >= 0; i--) { - final String origName = pkg.mAdoptPermissions.get(i); + for (int i = pkg.getAdoptPermissions().size() - 1; i >= 0; i--) { + final String origName = pkg.getAdoptPermissions().get(i); final PackageSetting orig = mSettings.getPackageLPr(origName); if (orig != null) { if (verifyPackageUpdateLPr(orig, pkg)) { Slog.i(TAG, "Adopting permissions from " + origName + " to " - + pkg.packageName); - mSettings.mPermissions.transferPermissions(origName, pkg.packageName); + + pkg.getPackageName()); + mSettings.mPermissions.transferPermissions(origName, pkg.getPackageName()); } } } @@ -10500,21 +10456,15 @@ public class PackageManagerService extends IPackageManager.Stub } } - if ((scanFlags & SCAN_CHECK_ONLY) != 0) { - if (oldPkgSetting != null) { - synchronized (mLock) { - mSettings.mPackages.put(oldPkgSetting.name, oldPkgSetting); - } - } - } else { - final int userId = user == null ? 0 : user.getIdentifier(); - // Modify state for the given package setting - commitPackageSettings(pkg, oldPkg, pkgSetting, scanFlags, - (parseFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/, reconciledPkg); - if (pkgSetting.getInstantApp(userId)) { - mInstantAppRegistry.addInstantAppLPw(userId, pkgSetting.appId); - } + final int userId = user == null ? 0 : user.getIdentifier(); + // Modify state for the given package setting + commitPackageSettings(pkg, oldPkg, pkgSetting, scanFlags, + (parseFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/, reconciledPkg); + if (pkgSetting.getInstantApp(userId)) { + mInstantAppRegistry.addInstantAppLPw(userId, pkgSetting.appId); } + + return pkg; } /** @@ -10522,18 +10472,19 @@ public class PackageManagerService extends IPackageManager.Stub * <p>This may differ from the package's actual name if the application has already * been installed under one of this package's original names. */ - private static @Nullable String getRealPackageName(@NonNull PackageParser.Package pkg, + private static @Nullable String getRealPackageName(@NonNull AndroidPackage pkg, @Nullable String renamedPkgName) { if (isPackageRenamed(pkg, renamedPkgName)) { - return pkg.mRealPackage; + return pkg.getRealPackage(); } return null; } /** Returns {@code true} if the package has been renamed. Otherwise, {@code false}. */ - private static boolean isPackageRenamed(@NonNull PackageParser.Package pkg, + private static boolean isPackageRenamed(@NonNull AndroidPackage pkg, @Nullable String renamedPkgName) { - return pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(renamedPkgName); + return pkg.getOriginalPackages() != null + && pkg.getOriginalPackages().contains(renamedPkgName); } /** @@ -10544,14 +10495,14 @@ public class PackageManagerService extends IPackageManager.Stub * shared user [if any]. */ @GuardedBy("mLock") - private @Nullable PackageSetting getOriginalPackageLocked(@NonNull PackageParser.Package pkg, + private @Nullable PackageSetting getOriginalPackageLocked(@NonNull AndroidPackage pkg, @Nullable String renamedPkgName) { if (!isPackageRenamed(pkg, renamedPkgName)) { return null; } - for (int i = pkg.mOriginalPackages.size() - 1; i >= 0; --i) { + for (int i = ArrayUtils.size(pkg.getOriginalPackages()) - 1; i >= 0; --i) { final PackageSetting originalPs = - mSettings.getPackageLPr(pkg.mOriginalPackages.get(i)); + mSettings.getPackageLPr(pkg.getOriginalPackages().get(i)); if (originalPs != null) { // the package is already installed under its original name... // but, should we use it? @@ -10559,18 +10510,18 @@ public class PackageManagerService extends IPackageManager.Stub // the new package is incompatible with the original continue; } else if (originalPs.sharedUser != null) { - if (!originalPs.sharedUser.name.equals(pkg.mSharedUserId)) { + if (!originalPs.sharedUser.name.equals(pkg.getSharedUserId())) { // the shared user id is incompatible with the original Slog.w(TAG, "Unable to migrate data from " + originalPs.name - + " to " + pkg.packageName + ": old uid " + + " to " + pkg.getPackageName() + ": old uid " + originalPs.sharedUser.name - + " differs from " + pkg.mSharedUserId); + + " differs from " + pkg.getSharedUserId()); continue; } // TODO: Add case when shared user id is added [b/28144775] } else { if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package " - + pkg.packageName + " to old name " + originalPs.name); + + pkg.getPackageName() + " to old name " + originalPs.name); } return originalPs; } @@ -10583,19 +10534,19 @@ public class PackageManagerService extends IPackageManager.Stub * <p>When we've already installed the package under an original name, update * the new package so we can continue to have the old name. */ - private static void ensurePackageRenamed(@NonNull PackageParser.Package pkg, + private static void ensurePackageRenamed(@NonNull ParsedPackage parsedPackage, @NonNull String renamedPackageName) { - if (pkg.mOriginalPackages == null - || !pkg.mOriginalPackages.contains(renamedPackageName) - || pkg.packageName.equals(renamedPackageName)) { + if (parsedPackage.getOriginalPackages() == null + || !parsedPackage.getOriginalPackages().contains(renamedPackageName) + || parsedPackage.getPackageName().equals(renamedPackageName)) { return; } - pkg.setPackageName(renamedPackageName); + parsedPackage.setPackageName(renamedPackageName); } /** * Applies the adjusted ABI calculated by - * {@link PackageAbiHelper#getAdjustedAbiForSharedUser(Set, PackageParser.Package)} to all + * {@link PackageAbiHelper#getAdjustedAbiForSharedUser(Set, AndroidPackage)} to all * relevant packages and settings. * @param sharedUserSetting The {@code SharedUserSetting} to adjust * @param scannedPackage the package being scanned or null @@ -10603,22 +10554,20 @@ public class PackageManagerService extends IPackageManager.Stub * @return the list of code paths that belong to packages that had their ABIs adjusted. */ private static List<String> applyAdjustedAbiToSharedUser(SharedUserSetting sharedUserSetting, - PackageParser.Package scannedPackage, String adjustedAbi) { + ParsedPackage scannedPackage, String adjustedAbi) { if (scannedPackage != null) { - scannedPackage.applicationInfo.primaryCpuAbi = adjustedAbi; + scannedPackage.setPrimaryCpuAbi(adjustedAbi); } List<String> changedAbiCodePath = null; for (PackageSetting ps : sharedUserSetting.packages) { - if (scannedPackage == null || !scannedPackage.packageName.equals(ps.name)) { + if (scannedPackage == null || !scannedPackage.getPackageName().equals(ps.name)) { if (ps.primaryCpuAbiString != null) { continue; } ps.primaryCpuAbiString = adjustedAbi; - if (ps.pkg != null && ps.pkg.applicationInfo != null - && !TextUtils.equals( - adjustedAbi, ps.pkg.applicationInfo.primaryCpuAbi)) { - ps.pkg.applicationInfo.primaryCpuAbi = adjustedAbi; + if (ps.pkg != null && !TextUtils.equals(adjustedAbi, ps.pkg.getPrimaryCpuAbi())) { + ps.pkg.mutate().setPrimaryCpuAbi(adjustedAbi); if (DEBUG_ABI_SELECTION) { Slog.i(TAG, "Adjusting ABI for " + ps.name + " to " + adjustedAbi @@ -10702,7 +10651,7 @@ public class PackageManagerService extends IPackageManager.Stub throws PackageManagerException { final PackageAbiHelper packageAbiHelper = injector.getAbiHelper(); final UserManagerInternal userManager = injector.getUserManagerInternal(); - final PackageParser.Package pkg = request.pkg; + ParsedPackage parsedPackage = request.parsedPackage; PackageSetting pkgSetting = request.pkgSetting; final PackageSetting disabledPkgSetting = request.disabledPkgSetting; final PackageSetting originalPkgSetting = request.originalPkgSetting; @@ -10717,13 +10666,12 @@ public class PackageManagerService extends IPackageManager.Stub if (DEBUG_PACKAGE_SCANNING) { if ((parseFlags & PackageParser.PARSE_CHATTY) != 0) - Log.d(TAG, "Scanning package " + pkg.packageName); + Log.d(TAG, "Scanning package " + parsedPackage.getPackageName()); } // Initialize package source and resource directories - final File scanFile = new File(pkg.codePath); - final File destCodeFile = new File(pkg.applicationInfo.getCodePath()); - final File destResourceFile = new File(pkg.applicationInfo.getResourcePath()); + final File destCodeFile = new File(parsedPackage.getAppInfoCodePath()); + final File destResourceFile = new File(parsedPackage.getAppInfoResourcePath()); // We keep references to the derived CPU Abis from settings in oder to reuse // them in the case where we're not upgrading or booting for the first time. @@ -10742,7 +10690,7 @@ public class PackageManagerService extends IPackageManager.Stub if (pkgSetting != null && pkgSetting.sharedUser != sharedUserSetting) { PackageManagerService.reportSettingsProblem(Log.WARN, - "Package " + pkg.packageName + " shared user changed from " + "Package " + parsedPackage.getPackageName() + " shared user changed from " + (pkgSetting.sharedUser != null ? pkgSetting.sharedUser.name : "<nothing>") + " to " @@ -10752,30 +10700,28 @@ public class PackageManagerService extends IPackageManager.Stub } String[] usesStaticLibraries = null; - if (pkg.usesStaticLibraries != null) { - usesStaticLibraries = new String[pkg.usesStaticLibraries.size()]; - pkg.usesStaticLibraries.toArray(usesStaticLibraries); + if (parsedPackage.getUsesStaticLibraries() != null) { + usesStaticLibraries = new String[parsedPackage.getUsesStaticLibraries().size()]; + parsedPackage.getUsesStaticLibraries().toArray(usesStaticLibraries); } final boolean createNewPackage = (pkgSetting == null); if (createNewPackage) { - final String parentPackageName = (pkg.parentPackage != null) - ? pkg.parentPackage.packageName : null; final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0; final boolean virtualPreload = (scanFlags & SCAN_AS_VIRTUAL_PRELOAD) != 0; // REMOVE SharedUserSetting from method; update in a separate call - pkgSetting = Settings.createNewSetting(pkg.packageName, originalPkgSetting, - disabledPkgSetting, realPkgName, sharedUserSetting, destCodeFile, - destResourceFile, pkg.applicationInfo.nativeLibraryRootDir, - pkg.applicationInfo.primaryCpuAbi, pkg.applicationInfo.secondaryCpuAbi, - pkg.mVersionCode, pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags, - user, true /*allowInstall*/, instantApp, virtualPreload, - parentPackageName, pkg.getChildPackageNames(), - UserManagerService.getInstance(), usesStaticLibraries, - pkg.usesStaticLibrariesVersions); + pkgSetting = Settings.createNewSetting(parsedPackage.getPackageName(), + originalPkgSetting, disabledPkgSetting, realPkgName, sharedUserSetting, + destCodeFile, destResourceFile, parsedPackage.getNativeLibraryRootDir(), + parsedPackage.getPrimaryCpuAbi(), parsedPackage.getSecondaryCpuAbi(), + parsedPackage.getVersionCode(), parsedPackage.getFlags(), + parsedPackage.getPrivateFlags(), user, true /*allowInstall*/, instantApp, + virtualPreload, UserManagerService.getInstance(), usesStaticLibraries, + parsedPackage.getUsesStaticLibrariesVersions()); } else { // make a deep copy to avoid modifying any existing system state. pkgSetting = new PackageSetting(pkgSetting); - pkgSetting.pkg = pkg; + // TODO(b/135203078): Remove entirely. Set package directly. + parsedPackage.setPackageSettingCallback(pkgSetting); // REMOVE SharedUserSetting from method; update in a separate call. // @@ -10783,18 +10729,18 @@ public class PackageManagerService extends IPackageManager.Stub // secondaryCpuAbi are not known at this point so we always update them // to null here, only to reset them at a later point. Settings.updatePackageSetting(pkgSetting, disabledPkgSetting, sharedUserSetting, - destCodeFile, destResourceFile, pkg.applicationInfo.nativeLibraryDir, - pkg.applicationInfo.primaryCpuAbi, pkg.applicationInfo.secondaryCpuAbi, - pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags, - pkg.getChildPackageNames(), UserManagerService.getInstance(), - usesStaticLibraries, pkg.usesStaticLibrariesVersions); + destCodeFile, destResourceFile, parsedPackage.getNativeLibraryDir(), + parsedPackage.getPrimaryCpuAbi(), parsedPackage.getSecondaryCpuAbi(), + parsedPackage.getFlags(), parsedPackage.getPrivateFlags(), + UserManagerService.getInstance(), + usesStaticLibraries, parsedPackage.getUsesStaticLibrariesVersions()); } if (createNewPackage && originalPkgSetting != null) { // This is the initial transition from the original package, so, // fix up the new package's name now. We must do this after looking // up the package under its new name, so getPackageLP takes care of // fiddling things correctly. - pkg.setPackageName(originalPkgSetting.name); + parsedPackage.setPackageName(originalPkgSetting.name); // File a report about this. String msg = "New package " + pkgSetting.realName @@ -10813,7 +10759,7 @@ public class PackageManagerService extends IPackageManager.Stub if (disabledPkgSetting != null || (0 != (scanFlags & SCAN_NEW_INSTALL) && pkgSetting != null && pkgSetting.isSystem())) { - pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; + parsedPackage.mutate().setUpdatedSystemApp(true); } pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, sharedUserSetting, @@ -10828,7 +10774,7 @@ public class PackageManagerService extends IPackageManager.Stub if (!isPlatformPackage) { // Get all of our default paths setup - pkg.applicationInfo.initForUser(UserHandle.USER_SYSTEM); + parsedPackage.initForUser(UserHandle.USER_SYSTEM); } if (pkg.isSystem()) { @@ -10840,41 +10786,43 @@ public class PackageManagerService extends IPackageManager.Stub if ((scanFlags & SCAN_NEW_INSTALL) == 0) { if (needToDeriveAbi) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi"); - final boolean extractNativeLibs = !pkg.isLibrary(); + final boolean extractNativeLibs = !parsedPackage.isLibrary(); final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths> derivedAbi = - packageAbiHelper.derivePackageAbi(pkg, cpuAbiOverride, extractNativeLibs); - derivedAbi.first.applyTo(pkg); - derivedAbi.second.applyTo(pkg); + packageAbiHelper.derivePackageAbi(parsedPackage, cpuAbiOverride, + extractNativeLibs); + derivedAbi.first.applyTo(parsedPackage); + derivedAbi.second.applyTo(parsedPackage); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); // Some system apps still use directory structure for native libraries // in which case we might end up not detecting abi solely based on apk // structure. Try to detect abi based on directory structure. - if (isSystemApp(pkg) && !pkg.isUpdatedSystemApp() && - pkg.applicationInfo.primaryCpuAbi == null) { + if (isSystemApp(parsedPackage) && !parsedPackage.isUpdatedSystemApp() && + parsedPackage.getPrimaryCpuAbi() == null) { final PackageAbiHelper.Abis abis = packageAbiHelper.getBundledAppAbis( - pkg); - abis.applyTo(pkg); + parsedPackage); + abis.applyTo(parsedPackage); abis.applyTo(pkgSetting); final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths = - packageAbiHelper.getNativeLibraryPaths(pkg, sAppLib32InstallDir); - nativeLibraryPaths.applyTo(pkg); + packageAbiHelper.getNativeLibraryPaths(parsedPackage, + sAppLib32InstallDir); + nativeLibraryPaths.applyTo(parsedPackage); } } else { // This is not a first boot or an upgrade, don't bother deriving the // ABI during the scan. Instead, trust the value that was stored in the // package setting. - pkg.applicationInfo.primaryCpuAbi = primaryCpuAbiFromSettings; - pkg.applicationInfo.secondaryCpuAbi = secondaryCpuAbiFromSettings; + parsedPackage.setPrimaryCpuAbi(primaryCpuAbiFromSettings) + .setSecondaryCpuAbi(secondaryCpuAbiFromSettings); final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths = - packageAbiHelper.getNativeLibraryPaths(pkg, sAppLib32InstallDir); - nativeLibraryPaths.applyTo(pkg); + packageAbiHelper.getNativeLibraryPaths(parsedPackage, sAppLib32InstallDir); + nativeLibraryPaths.applyTo(parsedPackage); if (DEBUG_ABI_SELECTION) { Slog.i(TAG, "Using ABIS and native lib paths from settings : " + - pkg.packageName + " " + pkg.applicationInfo.primaryCpuAbi + ", " + - pkg.applicationInfo.secondaryCpuAbi); + parsedPackage.getPackageName() + " " + parsedPackage.getPrimaryCpuAbi() + + ", " + parsedPackage.getSecondaryCpuAbi()); } } } else { @@ -10882,8 +10830,8 @@ public class PackageManagerService extends IPackageManager.Stub // We haven't run dex-opt for this move (since we've moved the compiled output too) // but we already have this packages package info in the PackageSetting. We just // use that and derive the native library path based on the new codepath. - pkg.applicationInfo.primaryCpuAbi = pkgSetting.primaryCpuAbiString; - pkg.applicationInfo.secondaryCpuAbi = pkgSetting.secondaryCpuAbiString; + parsedPackage.setPrimaryCpuAbi(pkgSetting.primaryCpuAbiString) + .setSecondaryCpuAbi(pkgSetting.secondaryCpuAbiString); } // Set native library paths again. For moves, the path will be updated based on the @@ -10891,8 +10839,8 @@ public class PackageManagerService extends IPackageManager.Stub // ABIs we determined during compilation, but the path will depend on the final // package path (after the rename away from the stage path). final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths = - packageAbiHelper.getNativeLibraryPaths(pkg, sAppLib32InstallDir); - nativeLibraryPaths.applyTo(pkg); + packageAbiHelper.getNativeLibraryPaths(parsedPackage, sAppLib32InstallDir); + nativeLibraryPaths.applyTo(parsedPackage); } // This is a special case for the "system" package, where the ABI is @@ -10900,8 +10848,8 @@ public class PackageManagerService extends IPackageManager.Stub // of this ABI so that we can deal with "normal" applications that run under // the same UID correctly. if (isPlatformPackage) { - pkg.applicationInfo.primaryCpuAbi = VMRuntime.getRuntime().is64Bit() ? - Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0]; + parsedPackage.setPrimaryCpuAbi(VMRuntime.getRuntime().is64Bit() ? + Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0]); } // If there's a mismatch between the abi-override in the package setting @@ -10909,34 +10857,34 @@ public class PackageManagerService extends IPackageManager.Stub // would've already compiled the app without taking the package setting into // account. if ((scanFlags & SCAN_NO_DEX) == 0 && (scanFlags & SCAN_NEW_INSTALL) != 0) { - if (cpuAbiOverride == null && pkg.packageName != null) { + if (cpuAbiOverride == null && parsedPackage.getPackageName() != null) { Slog.w(TAG, "Ignoring persisted ABI override " + cpuAbiOverride + - " for package " + pkg.packageName); + " for package " + parsedPackage.getPackageName()); } } - pkgSetting.primaryCpuAbiString = pkg.applicationInfo.primaryCpuAbi; - pkgSetting.secondaryCpuAbiString = pkg.applicationInfo.secondaryCpuAbi; + pkgSetting.primaryCpuAbiString = parsedPackage.getPrimaryCpuAbi(); + pkgSetting.secondaryCpuAbiString = parsedPackage.getSecondaryCpuAbi(); pkgSetting.cpuAbiOverrideString = cpuAbiOverride; // Copy the derived override back to the parsed package, so that we can // update the package settings accordingly. - pkg.cpuAbiOverride = cpuAbiOverride; + parsedPackage.setCpuAbiOverride(cpuAbiOverride); if (DEBUG_ABI_SELECTION) { - Slog.d(TAG, "Resolved nativeLibraryRoot for " + pkg.packageName - + " to root=" + pkg.applicationInfo.nativeLibraryRootDir + ", isa=" - + pkg.applicationInfo.nativeLibraryRootRequiresIsa); + Slog.d(TAG, "Resolved nativeLibraryRoot for " + parsedPackage.getPackageName() + + " to root=" + parsedPackage.getNativeLibraryRootDir() + ", isa=" + + parsedPackage.isNativeLibraryRootRequiresIsa()); } // Push the derived path down into PackageSettings so we know what to // clean up at uninstall time. - pkgSetting.legacyNativeLibraryPathString = pkg.applicationInfo.nativeLibraryRootDir; + pkgSetting.legacyNativeLibraryPathString = parsedPackage.getNativeLibraryRootDir(); if (DEBUG_ABI_SELECTION) { - Log.d(TAG, "Abis for package[" + pkg.packageName + "] are" + - " primary=" + pkg.applicationInfo.primaryCpuAbi + - " secondary=" + pkg.applicationInfo.secondaryCpuAbi); + Log.d(TAG, "Abis for package[" + parsedPackage.getPackageName() + "] are" + + " primary=" + parsedPackage.getPrimaryCpuAbi() + + " secondary=" + parsedPackage.getSecondaryCpuAbi()); } if ((scanFlags & SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) { @@ -10946,22 +10894,20 @@ public class PackageManagerService extends IPackageManager.Stub // We also do this *before* we perform dexopt on this package, so that // we can avoid redundant dexopts, and also to make sure we've got the // code and package path correct. - changedAbiCodePath = applyAdjustedAbiToSharedUser(pkgSetting.sharedUser, pkg, + changedAbiCodePath = applyAdjustedAbiToSharedUser(pkgSetting.sharedUser, parsedPackage, packageAbiHelper.getAdjustedAbiForSharedUser( - pkgSetting.sharedUser.packages, pkg)); + pkgSetting.sharedUser.packages, parsedPackage)); } - if (isUnderFactoryTest && pkg.requestedPermissions.contains( - android.Manifest.permission.FACTORY_TEST)) { - pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST; - } + parsedPackage.setFactoryTest(isUnderFactoryTest && parsedPackage.getRequestedPermissions() + .contains(android.Manifest.permission.FACTORY_TEST)); if (isSystemApp(pkg)) { pkgSetting.setIsOrphaned(true); } // Take care of first install / last update times. - final long scanFileTime = getLastModifiedTime(pkg); + final long scanFileTime = getLastModifiedTime(parsedPackage); if (currentTime != 0) { if (pkgSetting.firstInstallTime == 0) { pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime; @@ -10979,32 +10925,33 @@ public class PackageManagerService extends IPackageManager.Stub } } pkgSetting.setTimeStamp(scanFileTime); - - pkgSetting.pkg = pkg; - pkgSetting.pkgFlags = pkg.applicationInfo.flags; - if (pkg.getLongVersionCode() != pkgSetting.versionCode) { - pkgSetting.versionCode = pkg.getLongVersionCode(); + // TODO(b/135203078): Remove, move to constructor + parsedPackage.setPackageSettingCallback(pkgSetting); + pkgSetting.pkgFlags = parsedPackage.getFlags(); + if (parsedPackage.getLongVersionCode() != pkgSetting.versionCode) { + pkgSetting.versionCode = parsedPackage.getLongVersionCode(); } // Update volume if needed - final String volumeUuid = pkg.applicationInfo.volumeUuid; + final String volumeUuid = parsedPackage.getApplicationInfoVolumeUuid(); if (!Objects.equals(volumeUuid, pkgSetting.volumeUuid)) { Slog.i(PackageManagerService.TAG, "Update" + (pkgSetting.isSystem() ? " system" : "") - + " package " + pkg.packageName + + " package " + parsedPackage.getPackageName() + " volume from " + pkgSetting.volumeUuid + " to " + volumeUuid); pkgSetting.volumeUuid = volumeUuid; } SharedLibraryInfo staticSharedLibraryInfo = null; - if (!TextUtils.isEmpty(pkg.staticSharedLibName)) { - staticSharedLibraryInfo = SharedLibraryInfo.createForStatic(pkg); + if (!TextUtils.isEmpty(parsedPackage.getStaticSharedLibName())) { + staticSharedLibraryInfo = SharedLibraryInfo.createForStatic(parsedPackage); } List<SharedLibraryInfo> dynamicSharedLibraryInfos = null; - if (!ArrayUtils.isEmpty(pkg.libraryNames)) { - dynamicSharedLibraryInfos = new ArrayList<>(pkg.libraryNames.size()); - for (String name : pkg.libraryNames) { - dynamicSharedLibraryInfos.add(SharedLibraryInfo.createForDynamic(pkg, name)); + if (!ArrayUtils.isEmpty(parsedPackage.getLibraryNames())) { + dynamicSharedLibraryInfos = new ArrayList<>(parsedPackage.getLibraryNames().size()); + for (String name : parsedPackage.getLibraryNames()) { + dynamicSharedLibraryInfos.add( + SharedLibraryInfo.createForDynamic(parsedPackage, name)); } } @@ -11040,22 +10987,21 @@ public class PackageManagerService extends IPackageManager.Stub * * @throws PackageManagerException If bytecode could not be found when it should exist */ - private static void assertCodePolicy(PackageParser.Package pkg) + private static void assertCodePolicy(AndroidPackage pkg) throws PackageManagerException { - final boolean shouldHaveCode = - (pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0; - if (shouldHaveCode && !apkHasCode(pkg.baseCodePath)) { + final boolean shouldHaveCode = (pkg.getFlags() & ApplicationInfo.FLAG_HAS_CODE) != 0; + if (shouldHaveCode && !apkHasCode(pkg.getBaseCodePath())) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, - "Package " + pkg.baseCodePath + " code is missing"); + "Package " + pkg.getBaseCodePath() + " code is missing"); } - if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { - for (int i = 0; i < pkg.splitCodePaths.length; i++) { + if (!ArrayUtils.isEmpty(pkg.getSplitCodePaths())) { + for (int i = 0; i < pkg.getSplitCodePaths().length; i++) { final boolean splitShouldHaveCode = - (pkg.splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0; - if (splitShouldHaveCode && !apkHasCode(pkg.splitCodePaths[i])) { + (pkg.getSplitFlags()[i] & ApplicationInfo.FLAG_HAS_CODE) != 0; + if (splitShouldHaveCode && !apkHasCode(pkg.getSplitCodePaths()[i])) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, - "Package " + pkg.splitCodePaths[i] + " code is missing"); + "Package " + pkg.getSplitCodePaths()[i] + " code is missing"); } } } @@ -11068,118 +11014,59 @@ public class PackageManagerService extends IPackageManager.Stub * Implementation detail: This method must NOT have any side effect. It would * ideally be static, but, it requires locks to read system state. */ - private static void applyPolicy(PackageParser.Package pkg, final @ParseFlags int parseFlags, - final @ScanFlags int scanFlags, PackageParser.Package platformPkg) { + private static void applyPolicy(ParsedPackage parsedPackage, final @ParseFlags int parseFlags, + final @ScanFlags int scanFlags, AndroidPackage platformPkg) { if ((scanFlags & SCAN_AS_SYSTEM) != 0) { - pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM; - if (pkg.applicationInfo.isDirectBootAware()) { - // we're direct boot aware; set for all components - for (PackageParser.Service s : pkg.services) { - s.info.directBootAware = true; - } - for (PackageParser.Provider p : pkg.providers) { - p.info.directBootAware = true; - } - for (PackageParser.Activity a : pkg.activities) { - a.info.directBootAware = true; - } - for (PackageParser.Activity r : pkg.receivers) { - r.info.directBootAware = true; - } + parsedPackage.setSystem(true); + // TODO(b/135203078): Can this be done in PackageParser? Or just inferred when the flag + // is set during parse. + if (parsedPackage.isDirectBootAware()) { + parsedPackage.setAllComponentsDirectBootAware(true); } - if (compressedFileExists(pkg.codePath)) { - pkg.isStub = true; + if (compressedFileExists(parsedPackage.getCodePath())) { + parsedPackage.setIsStub(true); } } else { - // non system apps can't be flagged as core - pkg.coreApp = false; - // clear flags not applicable to regular apps - pkg.applicationInfo.flags &= - ~ApplicationInfo.FLAG_PERSISTENT; - pkg.applicationInfo.privateFlags &= - ~ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE; - pkg.applicationInfo.privateFlags &= - ~ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE; - // cap permission priorities - if (pkg.permissionGroups != null && pkg.permissionGroups.size() > 0) { - for (int i = pkg.permissionGroups.size() - 1; i >= 0; --i) { - pkg.permissionGroups.get(i).info.priority = 0; - } - } + parsedPackage + // non system apps can't be flagged as core + .setCoreApp(false) + // clear flags not applicable to regular apps + .setPersistent(false) + .setDefaultToDeviceProtectedStorage(false) + .setDirectBootAware(false) + // non system apps can't have permission priority + .capPermissionPriorities(); } if ((scanFlags & SCAN_AS_PRIVILEGED) == 0) { - // clear protected broadcasts - pkg.protectedBroadcasts = null; - // ignore export request for single user receivers - if (pkg.receivers != null) { - for (int i = pkg.receivers.size() - 1; i >= 0; --i) { - final PackageParser.Activity receiver = pkg.receivers.get(i); - if ((receiver.info.flags & ActivityInfo.FLAG_SINGLE_USER) != 0) { - receiver.info.exported = false; - } - } - } - // ignore export request for single user services - if (pkg.services != null) { - for (int i = pkg.services.size() - 1; i >= 0; --i) { - final PackageParser.Service service = pkg.services.get(i); - if ((service.info.flags & ServiceInfo.FLAG_SINGLE_USER) != 0) { - service.info.exported = false; - } - } - } - // ignore export request for single user providers - if (pkg.providers != null) { - for (int i = pkg.providers.size() - 1; i >= 0; --i) { - final PackageParser.Provider provider = pkg.providers.get(i); - if ((provider.info.flags & ProviderInfo.FLAG_SINGLE_USER) != 0) { - provider.info.exported = false; - } - } - } - } - - if ((scanFlags & SCAN_AS_PRIVILEGED) != 0) { - pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED; + parsedPackage + .clearProtectedBroadcasts() + .markNotActivitiesAsNotExportedIfSingleUser(); } - if ((scanFlags & SCAN_AS_OEM) != 0) { - pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_OEM; - } - - if ((scanFlags & SCAN_AS_VENDOR) != 0) { - pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VENDOR; - } - - if ((scanFlags & SCAN_AS_PRODUCT) != 0) { - pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRODUCT; - } - - if ((scanFlags & SCAN_AS_SYSTEM_EXT) != 0) { - pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT; - } - - if ((scanFlags & SCAN_AS_ODM) != 0) { - pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ODM; - } + parsedPackage.setPrivileged((scanFlags & SCAN_AS_PRIVILEGED) != 0) + .setOem((scanFlags & SCAN_AS_OEM) != 0) + .setVendor((scanFlags & SCAN_AS_VENDOR) != 0) + .setProduct((scanFlags & SCAN_AS_PRODUCT) != 0) + .setSystemExt((scanFlags & SCAN_AS_SYSTEM_EXT) != 0) + .setOdm((scanFlags & SCAN_AS_ODM) != 0); // Check if the package is signed with the same key as the platform package. - if (PLATFORM_PACKAGE_NAME.equals(pkg.packageName) || - (platformPkg != null && compareSignatures( - platformPkg.mSigningDetails.signatures, - pkg.mSigningDetails.signatures) == PackageManager.SIGNATURE_MATCH)) { - pkg.applicationInfo.privateFlags |= - ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY; - } - - if (!isSystemApp(pkg)) { + parsedPackage.setSignedWithPlatformKey( + (PLATFORM_PACKAGE_NAME.equals(parsedPackage.getPackageName()) + || (platformPkg != null && compareSignatures( + platformPkg.getSigningDetails().signatures, + parsedPackage.getSigningDetails().signatures + ) == PackageManager.SIGNATURE_MATCH)) + ); + + if (!isSystemApp(parsedPackage)) { // Only system apps can use these features. - pkg.mOriginalPackages = null; - pkg.mRealPackage = null; - pkg.mAdoptPermissions = null; + parsedPackage.clearOriginalPackages() + .setRealPackage(null) + .clearAdoptPermissions(); } - PackageBackwardCompatibility.modifySharedLibraries(pkg); + PackageBackwardCompatibility.modifySharedLibraries(parsedPackage); } private static @NonNull <T> T assertNotNull(@Nullable T object, String message) @@ -11199,15 +11086,15 @@ public class PackageManagerService extends IPackageManager.Stub * * @throws PackageManagerException If the package fails any of the validation checks */ - private void assertPackageIsValid(PackageParser.Package pkg, final @ParseFlags int parseFlags, + private void assertPackageIsValid(AndroidPackage pkg, final @ParseFlags int parseFlags, final @ScanFlags int scanFlags) throws PackageManagerException { if ((parseFlags & PackageParser.PARSE_ENFORCE_CODE) != 0) { assertCodePolicy(pkg); } - if (pkg.applicationInfo.getCodePath() == null || - pkg.applicationInfo.getResourcePath() == null) { + if (pkg.getAppInfoCodePath() == null || + pkg.getAppInfoResourcePath() == null) { // Bail out. The resource and code paths haven't been set. throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Code and resource paths haven't been set correctly"); @@ -11218,9 +11105,10 @@ public class PackageManagerService extends IPackageManager.Stub final boolean isUserInstall = (scanFlags & SCAN_BOOTING) == 0; final boolean isFirstBootOrUpgrade = (scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0; if ((isUserInstall || isFirstBootOrUpgrade) - && mApexManager.isApexPackage(pkg.packageName)) { + && mApexManager.isApexPackage(pkg.getPackageName())) { throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE, - pkg.packageName + " is an APEX package and can't be installed as an APK."); + pkg.getPackageName() + + " is an APEX package and can't be installed as an APK."); } // Make sure we're not adding any bogus keyset info @@ -11229,11 +11117,11 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mLock) { // The special "android" package can only be defined once - if (pkg.packageName.equals("android")) { + if (pkg.getPackageName().equals("android")) { if (mAndroidApplication != null) { Slog.w(TAG, "*************************************************"); Slog.w(TAG, "Core android package being redefined. Skipping."); - Slog.w(TAG, " codePath=" + pkg.codePath); + Slog.w(TAG, " codePath=" + pkg.getCodePath()); Slog.w(TAG, "*************************************************"); throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE, "Core android package being redefined. Skipping."); @@ -11241,23 +11129,24 @@ public class PackageManagerService extends IPackageManager.Stub } // A package name must be unique; don't allow duplicates - if ((scanFlags & SCAN_NEW_INSTALL) == 0 && mPackages.containsKey(pkg.packageName)) { + if ((scanFlags & SCAN_NEW_INSTALL) == 0 + && mPackages.containsKey(pkg.getPackageName())) { throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE, - "Application package " + pkg.packageName + "Application package " + pkg.getPackageName() + " already installed. Skipping duplicate."); } - if (pkg.applicationInfo.isStaticSharedLibrary()) { + if (pkg.isStaticSharedLibrary()) { // Static libs have a synthetic package name containing the version // but we still want the base name to be unique. if ((scanFlags & SCAN_NEW_INSTALL) == 0 - && mPackages.containsKey(pkg.manifestPackageName)) { + && mPackages.containsKey(pkg.getManifestPackageName())) { throw new PackageManagerException( "Duplicate static shared lib provider package"); } // Static shared libraries should have at least O target SDK - if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.O) { + if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.O) { throw new PackageManagerException( "Packages declaring static-shared libs must target O SDK or higher"); } @@ -11270,73 +11159,67 @@ public class PackageManagerService extends IPackageManager.Stub // Package declaring static a shared lib cannot be renamed since the package // name is synthetic and apps can't code around package manager internals. - if (!ArrayUtils.isEmpty(pkg.mOriginalPackages)) { + if (!ArrayUtils.isEmpty(pkg.getOriginalPackages())) { throw new PackageManagerException( "Packages declaring static-shared libs cannot be renamed"); } - // Package declaring static a shared lib cannot declare child packages - if (!ArrayUtils.isEmpty(pkg.childPackages)) { - throw new PackageManagerException( - "Packages declaring static-shared libs cannot have child packages"); - } - // Package declaring static a shared lib cannot declare dynamic libs - if (!ArrayUtils.isEmpty(pkg.libraryNames)) { + if (!ArrayUtils.isEmpty(pkg.getLibraryNames())) { throw new PackageManagerException( "Packages declaring static-shared libs cannot declare dynamic libs"); } // Package declaring static a shared lib cannot declare shared users - if (pkg.mSharedUserId != null) { + if (pkg.getSharedUserId() != null) { throw new PackageManagerException( "Packages declaring static-shared libs cannot declare shared users"); } // Static shared libs cannot declare activities - if (!pkg.activities.isEmpty()) { + if (pkg.getActivities() != null && !pkg.getActivities().isEmpty()) { throw new PackageManagerException( "Static shared libs cannot declare activities"); } // Static shared libs cannot declare services - if (!pkg.services.isEmpty()) { + if (pkg.getServices() != null && !pkg.getServices().isEmpty()) { throw new PackageManagerException( "Static shared libs cannot declare services"); } // Static shared libs cannot declare providers - if (!pkg.providers.isEmpty()) { + if (pkg.getProviders() != null && !pkg.getProviders().isEmpty()) { throw new PackageManagerException( "Static shared libs cannot declare content providers"); } // Static shared libs cannot declare receivers - if (!pkg.receivers.isEmpty()) { + if (pkg.getReceivers() != null && !pkg.getReceivers().isEmpty()) { throw new PackageManagerException( "Static shared libs cannot declare broadcast receivers"); } // Static shared libs cannot declare permission groups - if (!pkg.permissionGroups.isEmpty()) { + if (pkg.getPermissionGroups() != null && !pkg.getPermissionGroups().isEmpty()) { throw new PackageManagerException( "Static shared libs cannot declare permission groups"); } // Static shared libs cannot declare permissions - if (!pkg.permissions.isEmpty()) { + if (pkg.getPermissions() != null && !pkg.getPermissions().isEmpty()) { throw new PackageManagerException( "Static shared libs cannot declare permissions"); } // Static shared libs cannot declare protected broadcasts - if (pkg.protectedBroadcasts != null) { + if (pkg.getProtectedBroadcasts() != null) { throw new PackageManagerException( "Static shared libs cannot declare protected broadcasts"); } // Static shared libs cannot be overlay targets - if (pkg.mOverlayTarget != null) { + if (pkg.getOverlayTarget() != null) { throw new PackageManagerException( "Static shared libs cannot be overlay targets"); } @@ -11346,16 +11229,17 @@ public class PackageManagerService extends IPackageManager.Stub long maxVersionCode = Long.MAX_VALUE; LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get( - pkg.staticSharedLibName); + pkg.getStaticSharedLibName()); if (versionedLib != null) { final int versionCount = versionedLib.size(); for (int i = 0; i < versionCount; i++) { SharedLibraryInfo libInfo = versionedLib.valueAt(i); final long libVersionCode = libInfo.getDeclaringPackage() .getLongVersionCode(); - if (libInfo.getLongVersion() < pkg.staticSharedLibVersion) { + if (libInfo.getLongVersion() < pkg.getStaticSharedLibVersion()) { minVersionCode = Math.max(minVersionCode, libVersionCode + 1); - } else if (libInfo.getLongVersion() > pkg.staticSharedLibVersion) { + } else if (libInfo.getLongVersion() + > pkg.getStaticSharedLibVersion()) { maxVersionCode = Math.min(maxVersionCode, libVersionCode - 1); } else { minVersionCode = maxVersionCode = libVersionCode; @@ -11370,23 +11254,6 @@ public class PackageManagerService extends IPackageManager.Stub } } - // Only privileged apps and updated privileged apps can add child packages. - if (pkg.childPackages != null && !pkg.childPackages.isEmpty()) { - if ((scanFlags & SCAN_AS_PRIVILEGED) == 0) { - throw new PackageManagerException("Only privileged apps can add child " - + "packages. Ignoring package " + pkg.packageName); - } - final int childCount = pkg.childPackages.size(); - for (int i = 0; i < childCount; i++) { - PackageParser.Package childPkg = pkg.childPackages.get(i); - if (mSettings.hasOtherDisabledSystemPkgWithChildLPr(pkg.packageName, - childPkg.packageName)) { - throw new PackageManagerException("Can't override child of " - + "another disabled app. Ignoring package " + pkg.packageName); - } - } - } - // If we're only installing presumed-existing packages, require that the // scanned APK is both already known and at the path previously established // for it. Previously unknown packages we pick up normally, but if we have an @@ -11396,29 +11263,30 @@ public class PackageManagerService extends IPackageManager.Stub // to the user-installed location. If we don't allow this change, any newer, // user-installed version of the application will be ignored. if ((scanFlags & SCAN_REQUIRE_KNOWN) != 0) { - if (mExpectingBetter.containsKey(pkg.packageName)) { + if (mExpectingBetter.containsKey(pkg.getPackageName())) { logCriticalInfo(Log.WARN, - "Relax SCAN_REQUIRE_KNOWN requirement for package " + pkg.packageName); + "Relax SCAN_REQUIRE_KNOWN requirement for package " + + pkg.getPackageName()); } else { - PackageSetting known = mSettings.getPackageLPr(pkg.packageName); + PackageSetting known = mSettings.getPackageLPr(pkg.getPackageName()); if (known != null) { if (DEBUG_PACKAGE_SCANNING) { - Log.d(TAG, "Examining " + pkg.codePath + Log.d(TAG, "Examining " + pkg.getCodePath() + " and requiring known paths " + known.codePathString + " & " + known.resourcePathString); } - if (!pkg.applicationInfo.getCodePath().equals(known.codePathString) - || !pkg.applicationInfo.getResourcePath().equals( + if (!pkg.getAppInfoCodePath().equals(known.codePathString) + || !pkg.getAppInfoResourcePath().equals( known.resourcePathString)) { throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED, - "Application package " + pkg.packageName - + " found at " + pkg.applicationInfo.getCodePath() + "Application package " + pkg.getPackageName() + + " found at " + pkg.getAppInfoCodePath() + " but expected at " + known.codePathString + "; ignoring."); } } else { throw new PackageManagerException(INSTALL_FAILED_INVALID_INSTALL_LOCATION, - "Application package " + pkg.packageName + "Application package " + pkg.getPackageName() + " not found; ignoring."); } } @@ -11433,11 +11301,13 @@ public class PackageManagerService extends IPackageManager.Stub } // Verify that packages sharing a user with a privileged app are marked as privileged. - if (!pkg.isPrivileged() && (pkg.mSharedUserId != null)) { + if (!pkg.isPrivileged() && (pkg.getSharedUserId() != null)) { SharedUserSetting sharedUserSetting = null; try { - sharedUserSetting = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, 0, false); - } catch (PackageManagerException ignore) {} + sharedUserSetting = mSettings.getSharedUserLPw(pkg.getSharedUserId(), + 0, 0, false); + } catch (PackageManagerException ignore) { + } if (sharedUserSetting != null && sharedUserSetting.isPrivileged()) { // Exempt SharedUsers signed with the platform key. PackageSetting platformPkgSetting = mSettings.mPackages.get("android"); @@ -11445,18 +11315,18 @@ public class PackageManagerService extends IPackageManager.Stub != PackageParser.SigningDetails.UNKNOWN) && (compareSignatures( platformPkgSetting.signatures.mSigningDetails.signatures, - pkg.mSigningDetails.signatures) + pkg.getSigningDetails().signatures) != PackageManager.SIGNATURE_MATCH)) { throw new PackageManagerException("Apps that share a user with a " + "privileged app must themselves be marked as privileged. " + - pkg.packageName + " shares privileged user " + - pkg.mSharedUserId + "."); + pkg.getPackageName() + " shares privileged user " + + pkg.getSharedUserId() + "."); } } } // Apply policies specific for runtime resource overlays (RROs). - if (pkg.mOverlayTarget != null) { + if (pkg.getOverlayTarget() != null) { // System overlays have some restrictions on their use of the 'static' state. if ((scanFlags & SCAN_AS_SYSTEM) != 0) { // We are scanning a system overlay. This can be the first scan of the @@ -11464,54 +11334,62 @@ public class PackageManagerService extends IPackageManager.Stub if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) { // This must be an update to a system overlay. final PackageSetting previousPkg = assertNotNull( - mSettings.getPackageLPr(pkg.packageName), + mSettings.getPackageLPr(pkg.getPackageName()), "previous package state not present"); // previousPkg.pkg may be null: the package will be not be scanned if the // package manager knows there is a newer version on /data. // TODO[b/79435695]: Find a better way to keep track of the "static" // property for RROs instead of having to parse packages on /system - PackageParser.Package ppkg = previousPkg.pkg; + AndroidPackage ppkg = previousPkg.pkg; if (ppkg == null) { try { final PackageParser pp = new PackageParser(); - ppkg = pp.parsePackage(previousPkg.codePath, - parseFlags | PackageParser.PARSE_IS_SYSTEM_DIR); + // TODO(b/135203078): Do we really need to parse here? Maybe use + // a shortened path? + ppkg = pp.parseParsedPackage(previousPkg.codePath, + parseFlags | PackageParser.PARSE_IS_SYSTEM_DIR, + false) + .hideAsFinal(); } catch (PackageParserException e) { Slog.w(TAG, "failed to parse " + previousPkg.codePath, e); } } // Static overlays cannot be updated. - if (ppkg != null && ppkg.mOverlayIsStatic) { - throw new PackageManagerException("Overlay " + pkg.packageName + - " is static and cannot be upgraded."); + if (ppkg != null && ppkg.isOverlayIsStatic()) { + throw new PackageManagerException("Overlay " + + pkg.getPackageName() + + " is static and cannot be upgraded."); // Non-static overlays cannot be converted to static overlays. - } else if (pkg.mOverlayIsStatic) { - throw new PackageManagerException("Overlay " + pkg.packageName + - " cannot be upgraded into a static overlay."); + } else if (pkg.isOverlayIsStatic()) { + throw new PackageManagerException("Overlay " + + pkg.getPackageName() + + " cannot be upgraded into a static overlay."); } } } else { // The overlay is a non-system overlay. Non-system overlays cannot be static. - if (pkg.mOverlayIsStatic) { - throw new PackageManagerException("Overlay " + pkg.packageName + - " is static but not pre-installed."); + if (pkg.isOverlayIsStatic()) { + throw new PackageManagerException("Overlay " + + pkg.getPackageName() + + " is static but not pre-installed."); } // A non-preloaded overlay packages must have targetSdkVersion >= Q, or be // signed with the platform certificate. Check this in increasing order of // computational cost. - if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.Q) { + if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.Q) { final PackageSetting platformPkgSetting = mSettings.getPackageLPr("android"); if ((platformPkgSetting.signatures.mSigningDetails != PackageParser.SigningDetails.UNKNOWN) && (compareSignatures( platformPkgSetting.signatures.mSigningDetails.signatures, - pkg.mSigningDetails.signatures) + pkg.getSigningDetails().signatures) != PackageManager.SIGNATURE_MATCH)) { - throw new PackageManagerException("Overlay " + pkg.packageName + throw new PackageManagerException("Overlay " + + pkg.getPackageName() + " must target Q or later, " + "or be signed with the platform certificate"); } @@ -11521,18 +11399,19 @@ public class PackageManagerService extends IPackageManager.Stub // only be used if it is signed with the same certificate as its target. If the // target is already installed, check this here to augment the last line of // defence which is OMS. - if (pkg.mOverlayTargetName == null) { + if (pkg.getOverlayTargetName() == null) { final PackageSetting targetPkgSetting = - mSettings.getPackageLPr(pkg.mOverlayTarget); + mSettings.getPackageLPr(pkg.getOverlayTarget()); if (targetPkgSetting != null) { if ((targetPkgSetting.signatures.mSigningDetails != PackageParser.SigningDetails.UNKNOWN) && (compareSignatures( targetPkgSetting.signatures.mSigningDetails.signatures, - pkg.mSigningDetails.signatures) + pkg.getSigningDetails().signatures) != PackageManager.SIGNATURE_MATCH)) { - throw new PackageManagerException("Overlay " + pkg.packageName - + " and target " + pkg.mOverlayTarget + " signed with" + throw new PackageManagerException("Overlay " + + pkg.getPackageName() + " and target " + + pkg.getOverlayTarget() + " signed with" + " different certificates, and the overlay lacks" + " <overlay android:targetName>"); } @@ -11612,71 +11491,67 @@ public class PackageManagerService extends IPackageManager.Stub * Adds a scanned package to the system. When this method is finished, the package will * be available for query, resolution, etc... */ - private void commitPackageSettings(PackageParser.Package pkg, - @Nullable PackageParser.Package oldPkg, PackageSetting pkgSetting, + private void commitPackageSettings(AndroidPackage pkg, + @Nullable AndroidPackage oldPkg, PackageSetting pkgSetting, final @ScanFlags int scanFlags, boolean chatty, ReconciledPackage reconciledPkg) { - final String pkgName = pkg.packageName; + final String pkgName = pkg.getPackageName(); if (mCustomResolverComponentName != null && - mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) { + mCustomResolverComponentName.getPackageName().equals(pkg.getPackageName())) { setUpCustomResolverActivity(pkg); } - if (pkg.packageName.equals("android")) { + if (pkg.getPackageName().equals("android")) { synchronized (mLock) { - if ((scanFlags & SCAN_CHECK_ONLY) == 0) { - // Set up information for our fall-back user intent resolution activity. - mPlatformPackage = pkg; - pkg.mVersionCode = mSdkVersion; - pkg.mVersionCodeMajor = 0; - mAndroidApplication = pkg.applicationInfo; - if (!mResolverReplaced) { - mResolveActivity.applicationInfo = mAndroidApplication; - mResolveActivity.name = ResolverActivity.class.getName(); - mResolveActivity.packageName = mAndroidApplication.packageName; - mResolveActivity.processName = "system:ui"; - mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE; - mResolveActivity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NEVER; - mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS; - mResolveActivity.theme = R.style.Theme_Material_Dialog_Alert; - mResolveActivity.exported = true; - mResolveActivity.enabled = true; - mResolveActivity.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE; - mResolveActivity.configChanges = ActivityInfo.CONFIG_SCREEN_SIZE - | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE - | ActivityInfo.CONFIG_SCREEN_LAYOUT - | ActivityInfo.CONFIG_ORIENTATION - | ActivityInfo.CONFIG_KEYBOARD - | ActivityInfo.CONFIG_KEYBOARD_HIDDEN; - mResolveInfo.activityInfo = mResolveActivity; - mResolveInfo.priority = 0; - mResolveInfo.preferredOrder = 0; - mResolveInfo.match = 0; - mResolveComponentName = new ComponentName( - mAndroidApplication.packageName, mResolveActivity.name); - } - } - } - } - - ArrayList<PackageParser.Package> clientLibPkgs = null; + // Set up information for our fall-back user intent resolution activity. + mPlatformPackage = pkg; + mAndroidApplication = pkg.toAppInfo(); + if (!mResolverReplaced) { + mResolveActivity.applicationInfo = mAndroidApplication; + mResolveActivity.name = ResolverActivity.class.getName(); + mResolveActivity.packageName = mAndroidApplication.packageName; + mResolveActivity.processName = "system:ui"; + mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE; + mResolveActivity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NEVER; + mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS; + mResolveActivity.theme = R.style.Theme_Material_Dialog_Alert; + mResolveActivity.exported = true; + mResolveActivity.enabled = true; + mResolveActivity.resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE; + mResolveActivity.configChanges = ActivityInfo.CONFIG_SCREEN_SIZE + | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE + | ActivityInfo.CONFIG_SCREEN_LAYOUT + | ActivityInfo.CONFIG_ORIENTATION + | ActivityInfo.CONFIG_KEYBOARD + | ActivityInfo.CONFIG_KEYBOARD_HIDDEN; + mResolveInfo.activityInfo = mResolveActivity; + mResolveInfo.priority = 0; + mResolveInfo.preferredOrder = 0; + mResolveInfo.match = 0; + mResolveComponentName = new ComponentName( + mAndroidApplication.packageName, mResolveActivity.name); + } + } + } + + ArrayList<AndroidPackage> clientLibPkgs = null; // writer synchronized (mLock) { if (!ArrayUtils.isEmpty(reconciledPkg.allowedSharedLibraryInfos)) { for (SharedLibraryInfo info : reconciledPkg.allowedSharedLibraryInfos) { commitSharedLibraryInfoLocked(info); } - final Map<String, PackageParser.Package> combinedPackages = - reconciledPkg.getCombinedPackages(); + final Map<String, AndroidPackage> combinedSigningDetails = + reconciledPkg.getCombinedAvailablePackages(); try { // Shared libraries for the package need to be updated. - updateSharedLibrariesLocked(pkg, null, combinedPackages); + updateSharedLibrariesLocked(pkg, 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, combinedPackages); + clientLibPkgs = updateAllSharedLibrariesLocked(pkg, combinedSigningDetails); } } } @@ -11700,9 +11575,9 @@ public class PackageManagerService extends IPackageManager.Stub // Also need to kill any apps that are dependent on the library. if (clientLibPkgs != null) { for (int i=0; i<clientLibPkgs.size(); i++) { - PackageParser.Package clientPkg = clientLibPkgs.get(i); - killApplication(clientPkg.applicationInfo.packageName, - clientPkg.applicationInfo.uid, "update lib"); + AndroidPackage clientPkg = clientLibPkgs.get(i); + killApplication(clientPkg.getAppInfoPackageName(), + clientPkg.getUid(), "update lib"); } } @@ -11715,7 +11590,7 @@ public class PackageManagerService extends IPackageManager.Stub // Add the new setting to mSettings mSettings.insertPackageSettingLPw(pkgSetting, pkg); // Add the new setting to mPackages - mPackages.put(pkg.applicationInfo.packageName, pkg); + mPackages.put(pkg.getAppInfoPackageName(), pkg); // Add the package's KeySets to the global KeySetManagerService KeySetManagerService ksms = mSettings.mKeySetManagerService; @@ -11726,7 +11601,7 @@ public class PackageManagerService extends IPackageManager.Stub // Don't allow ephemeral applications to define new permissions groups. if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) { - Slog.w(TAG, "Permission groups from package " + pkg.packageName + Slog.w(TAG, "Permission groups from package " + pkg.getPackageName() + " ignored: instant apps cannot define new permission groups."); } else { mPermissionManager.addAllPermissionGroups(pkg, chatty); @@ -11734,31 +11609,31 @@ public class PackageManagerService extends IPackageManager.Stub // Don't allow ephemeral applications to define new permissions. if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) { - Slog.w(TAG, "Permissions from package " + pkg.packageName + Slog.w(TAG, "Permissions from package " + pkg.getPackageName() + " ignored: instant apps cannot define new permissions."); } else { mPermissionManager.addAllPermissions(pkg, chatty); } - int collectionSize = pkg.instrumentation.size(); + int collectionSize = ArrayUtils.size(pkg.getInstrumentations()); StringBuilder r = null; int i; for (i = 0; i < collectionSize; i++) { - PackageParser.Instrumentation a = pkg.instrumentation.get(i); - a.info.packageName = pkg.applicationInfo.packageName; - a.info.sourceDir = pkg.applicationInfo.sourceDir; - a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir; - a.info.splitNames = pkg.splitNames; - a.info.splitSourceDirs = pkg.applicationInfo.splitSourceDirs; - a.info.splitPublicSourceDirs = pkg.applicationInfo.splitPublicSourceDirs; - a.info.splitDependencies = pkg.applicationInfo.splitDependencies; - a.info.dataDir = pkg.applicationInfo.dataDir; - a.info.deviceProtectedDataDir = pkg.applicationInfo.deviceProtectedDataDir; - a.info.credentialProtectedDataDir = pkg.applicationInfo.credentialProtectedDataDir; - a.info.primaryCpuAbi = pkg.applicationInfo.primaryCpuAbi; - a.info.secondaryCpuAbi = pkg.applicationInfo.secondaryCpuAbi; - a.info.nativeLibraryDir = pkg.applicationInfo.nativeLibraryDir; - a.info.secondaryNativeLibraryDir = pkg.applicationInfo.secondaryNativeLibraryDir; + ParsedInstrumentation a = pkg.getInstrumentations().get(i); + a.setPackageName(pkg.getAppInfoPackageName()); + a.sourceDir = pkg.getBaseCodePath(); + a.publicSourceDir = pkg.getPublicSourceDir(); + a.splitNames = pkg.getSplitNames(); + a.splitSourceDirs = pkg.getSplitCodePaths(); + a.splitPublicSourceDirs = pkg.getSplitPublicSourceDirs(); + a.splitDependencies = pkg.getSplitDependencies(); + a.dataDir = pkg.getDataDir(); + a.deviceProtectedDataDir = pkg.getDeviceProtectedDataDir(); + a.credentialProtectedDataDir = pkg.getCredentialProtectedDataDir(); + a.primaryCpuAbi = pkg.getPrimaryCpuAbi(); + a.secondaryCpuAbi = pkg.getSecondaryCpuAbi(); + a.nativeLibraryDir = pkg.getNativeLibraryDir(); + a.secondaryNativeLibraryDir = pkg.getSecondaryNativeLibraryDir(); mInstrumentation.put(a.getComponentName(), a); if (chatty) { if (r == null) { @@ -11766,19 +11641,16 @@ public class PackageManagerService extends IPackageManager.Stub } else { r.append(' '); } - r.append(a.info.name); + r.append(a.getName()); } } if (r != null) { if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, " Instrumentation: " + r); } - if (pkg.protectedBroadcasts != null) { - collectionSize = pkg.protectedBroadcasts.size(); + if (pkg.getProtectedBroadcasts() != null) { synchronized (mProtectedBroadcasts) { - for (i = 0; i < collectionSize; i++) { - mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i)); - } + mProtectedBroadcasts.addAll(pkg.getProtectedBroadcasts()); } } @@ -11802,14 +11674,14 @@ public class PackageManagerService extends IPackageManager.Stub Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } - private void setUpCustomResolverActivity(PackageParser.Package pkg) { + private void setUpCustomResolverActivity(AndroidPackage pkg) { synchronized (mLock) { mResolverReplaced = true; // Set up information for custom user intent resolution activity. - mResolveActivity.applicationInfo = pkg.applicationInfo; + mResolveActivity.applicationInfo = pkg.toAppInfo(); mResolveActivity.name = mCustomResolverComponentName.getClassName(); - mResolveActivity.packageName = pkg.applicationInfo.packageName; - mResolveActivity.processName = pkg.applicationInfo.packageName; + mResolveActivity.packageName = pkg.getAppInfoPackageName(); + mResolveActivity.processName = pkg.getAppInfoProcessName(); mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE; mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS | ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS; @@ -11876,22 +11748,13 @@ public class PackageManagerService extends IPackageManager.Stub } } - private void removePackageLI(PackageParser.Package pkg, boolean chatty) { + private void removePackageLI(AndroidPackage pkg, boolean chatty) { // Remove the parent package setting - PackageSetting ps = (PackageSetting) pkg.mExtras; + PackageSetting ps = getPackageSetting(pkg.getPackageName()); if (ps != null) { removePackageLI(ps.name, chatty); } else if (DEBUG_REMOVE && chatty) { - Log.d(TAG, "Not removing package " + pkg.packageName + "; mExtras == null"); - } - // Remove the child package setting - final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; - for (int i = 0; i < childCount; i++) { - PackageParser.Package childPkg = pkg.childPackages.get(i); - ps = (PackageSetting) childPkg.mExtras; - if (ps != null) { - removePackageLI(ps.name, chatty); - } + Log.d(TAG, "Not removing package " + pkg.getPackageName() + "; mExtras == null"); } } @@ -11903,7 +11766,7 @@ public class PackageManagerService extends IPackageManager.Stub // writer synchronized (mLock) { - final PackageParser.Package removedPackage = mPackages.remove(packageName); + final AndroidPackage removedPackage = mPackages.remove(packageName); if (removedPackage != null) { cleanPackageDataStructuresLILPw(removedPackage, chatty); } @@ -11916,11 +11779,11 @@ public class PackageManagerService extends IPackageManager.Stub mInjector.getUserManagerInternal().getUserIds(), mSettings.mPackages); mPermissionManager.removeAllPermissions(pkg, chatty); - final int instrumentationSize = pkg.instrumentation.size(); + final int instrumentationSize = ArrayUtils.size(pkg.getInstrumentations()); StringBuilder r = null; int i; for (i = 0; i < instrumentationSize; i++) { - PackageParser.Instrumentation a = pkg.instrumentation.get(i); + ParsedInstrumentation a = pkg.getInstrumentations().get(i); mInstrumentation.remove(a.getComponentName()); if (DEBUG_REMOVE && chatty) { if (r == null) { @@ -11928,7 +11791,7 @@ public class PackageManagerService extends IPackageManager.Stub } else { r.append(' '); } - r.append(a.info.name); + r.append(a.getName()); } } if (r != null) { @@ -11936,12 +11799,12 @@ public class PackageManagerService extends IPackageManager.Stub } r = null; - if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) { + if ((pkg.getFlags() & ApplicationInfo.FLAG_SYSTEM) != 0) { // Only system apps can hold shared libraries. - if (pkg.libraryNames != null) { - final int libraryNamesSize = pkg.libraryNames.size(); + if (pkg.getLibraryNames() != null) { + final int libraryNamesSize = pkg.getLibraryNames().size(); for (i = 0; i < libraryNamesSize; i++) { - String name = pkg.libraryNames.get(i); + String name = pkg.getLibraryNames().get(i); if (removeSharedLibraryLPw(name, 0)) { if (DEBUG_REMOVE && chatty) { if (r == null) { @@ -11959,15 +11822,16 @@ public class PackageManagerService extends IPackageManager.Stub r = null; // Any package can hold static shared libraries. - if (pkg.staticSharedLibName != null) { - if (removeSharedLibraryLPw(pkg.staticSharedLibName, pkg.staticSharedLibVersion)) { + if (pkg.getStaticSharedLibName() != null) { + if (removeSharedLibraryLPw(pkg.getStaticSharedLibName(), + pkg.getStaticSharedLibVersion())) { if (DEBUG_REMOVE && chatty) { if (r == null) { r = new StringBuilder(256); } else { r.append(' '); } - r.append(pkg.staticSharedLibName); + r.append(pkg.getStaticSharedLibName()); } } } @@ -12308,11 +12172,11 @@ public class PackageManagerService extends IPackageManager.Stub // Cannot hide static shared libs as they are considered // a part of the using app (emulating static linking). Also // static libs are installed always on internal storage. - PackageParser.Package pkg = mPackages.get(packageName); - if (pkg != null && pkg.staticSharedLibName != null) { + AndroidPackage pkg = mPackages.get(packageName); + if (pkg != null && pkg.getStaticSharedLibName() != null) { Slog.w(TAG, "Cannot hide package: " + packageName + " providing static shared library: " - + pkg.staticSharedLibName); + + pkg.getStaticSharedLibName()); return false; } // Only allow protected packages to hide themselves. @@ -12358,17 +12222,17 @@ public class PackageManagerService extends IPackageManager.Stub if (pkgSetting == null || !pkgSetting.isSystem()) { return; } - PackageParser.Package pkg = pkgSetting.pkg; - if (pkg != null && pkg.applicationInfo != null) { - pkg.applicationInfo.hiddenUntilInstalled = hidden; + AndroidPackage pkg = pkgSetting.pkg; + if (pkg != null) { + pkg.mutate().setHiddenUntilInstalled(hidden); } final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(packageName); if (disabledPs == null) { return; } pkg = disabledPs.pkg; - if (pkg != null && pkg.applicationInfo != null) { - pkg.applicationInfo.hiddenUntilInstalled = hidden; + if (pkg != null) { + pkg.mutate().setHiddenUntilInstalled(hidden); } } } @@ -12560,7 +12424,7 @@ public class PackageManagerService extends IPackageManager.Stub if (installed) { if ((installFlags & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS) != 0 && pkgSetting.pkg != null) { - whiteListedPermissions = pkgSetting.pkg.requestedPermissions; + whiteListedPermissions = pkgSetting.pkg.getRequestedPermissions(); } mPermissionManager.setWhitelistedRestrictedPermissions(packageName, whiteListedPermissions, FLAG_PERMISSION_WHITELIST_INSTALLER, userId); @@ -12990,11 +12854,11 @@ public class PackageManagerService extends IPackageManager.Stub // Cannot suspend static shared libs as they are considered // a part of the using app (emulating static linking). Also // static libs are installed always on internal storage. - PackageParser.Package pkg = mPackages.get(packageName); - if (pkg != null && pkg.applicationInfo.isStaticSharedLibrary()) { + AndroidPackage pkg = mPackages.get(packageName); + if (pkg != null && pkg.isStaticSharedLibrary()) { Slog.w(TAG, "Cannot suspend package: " + packageName + " providing static shared library: " - + pkg.staticSharedLibName); + + pkg.getStaticSharedLibName()); continue; } } @@ -13139,10 +13003,10 @@ public class PackageManagerService extends IPackageManager.Stub private int getUidForVerifier(VerifierInfo verifierInfo) { synchronized (mLock) { - final PackageParser.Package pkg = mPackages.get(verifierInfo.packageName); + final AndroidPackage pkg = mPackages.get(verifierInfo.packageName); if (pkg == null) { return -1; - } else if (pkg.mSigningDetails.signatures.length != 1) { + } else if (pkg.getSigningDetails().signatures.length != 1) { Slog.i(TAG, "Verifier package " + verifierInfo.packageName + " has more than one signature; ignoring"); return -1; @@ -13156,7 +13020,7 @@ public class PackageManagerService extends IPackageManager.Stub final byte[] expectedPublicKey; try { - final Signature verifierSig = pkg.mSigningDetails.signatures[0]; + final Signature verifierSig = pkg.getSigningDetails().signatures[0]; final PublicKey publicKey = verifierSig.getPublicKey(); expectedPublicKey = publicKey.getEncoded(); } catch (CertificateException e) { @@ -13171,7 +13035,7 @@ public class PackageManagerService extends IPackageManager.Stub return -1; } - return pkg.applicationInfo.uid; + return pkg.getUid(); } } @@ -13347,26 +13211,33 @@ public class PackageManagerService extends IPackageManager.Stub final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); synchronized (mLock) { - PackageParser.Package pkg = mPackages.get(packageName); - if (pkg == null || pkg.activities == null) { + AndroidPackage pkg = mPackages.get(packageName); + if (pkg == null || ArrayUtils.isEmpty(pkg.getActivities())) { return ParceledListSlice.emptyList(); } - if (pkg.mExtras == null) { + final PackageSetting ps = getPackageSetting(pkg.getPackageName()); + if (ps == null) { return ParceledListSlice.emptyList(); } - final PackageSetting ps = (PackageSetting) pkg.mExtras; if (shouldFilterApplicationLocked(ps, callingUid, callingUserId)) { return ParceledListSlice.emptyList(); } - final int count = pkg.activities.size(); + final int count = ArrayUtils.size(pkg.getActivities()); ArrayList<IntentFilter> result = new ArrayList<>(); for (int n=0; n<count; n++) { - PackageParser.Activity activity = pkg.activities.get(n); + ParsedActivity activity = pkg.getActivities().get(n); if (activity.intents != null && activity.intents.size() > 0) { result.addAll(activity.intents); } } - return new ParceledListSlice<>(result); + return new ParceledListSlice<IntentFilter>(result) { + @Override + protected void writeElement(IntentFilter parcelable, Parcel dest, int callFlags) { + // IntentFilter has final Parcelable methods, so redirect to the subclass + ((ParsedActivityIntentInfo) parcelable).writeIntentInfoToParcel(dest, + callFlags); + } + }; } } @@ -13549,7 +13420,7 @@ public class PackageManagerService extends IPackageManager.Stub // package has not opted out of backup participation. final boolean update = res.removedInfo != null && res.removedInfo.removedPackage != null; - final int flags = (res.pkg == null) ? 0 : res.pkg.applicationInfo.flags; + final int flags = (res.pkg == null) ? 0 : res.pkg.getFlags(); boolean doRestore = !update && ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0); @@ -13587,7 +13458,7 @@ public class PackageManagerService extends IPackageManager.Stub try { if (bm.isBackupServiceActive(userId)) { bm.restoreAtInstallForUser( - userId, res.pkg.applicationInfo.packageName, token); + userId, res.pkg.getAppInfoPackageName(), token); } else { doRestore = false; } @@ -13612,8 +13483,8 @@ public class PackageManagerService extends IPackageManager.Stub IRollbackManager rm = IRollbackManager.Stub.asInterface( ServiceManager.getService(Context.ROLLBACK_SERVICE)); - final String packageName = res.pkg.applicationInfo.packageName; - final String seInfo = res.pkg.applicationInfo.seInfo; + final String packageName = res.pkg.getAppInfoPackageName(); + final String seInfo = res.pkg.getSeInfo(); final int[] allUsers = mUserManager.getUserIds(); final int[] installedUsers; @@ -13682,7 +13553,7 @@ public class PackageManagerService extends IPackageManager.Stub if (data.res.returnCode != PackageManager.INSTALL_SUCCEEDED) { continue; } - if (packageName.equals(data.res.pkg.applicationInfo.packageName)) { + if (packageName.equals(data.res.pkg.getAppInfoPackageName())) { // right package; but is it for the right user? for (int uIndex = 0; uIndex < data.res.newUsers.length; uIndex++) { if (userId == data.res.newUsers[uIndex]) { @@ -14025,12 +13896,12 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mLock) { // Currently installed package which the new package is attempting to replace or // null if no such package is installed. - PackageParser.Package installedPkg = mPackages.get(packageName); + AndroidPackage installedPkg = mPackages.get(packageName); // Package which currently owns the data which the new package will own if installed. // If an app is unstalled while keeping data (e.g., adb uninstall -k), installedPkg // will be null whereas dataOwnerPkg will contain information about the package // which was uninstalled while keeping its data. - PackageParser.Package dataOwnerPkg = installedPkg; + AndroidPackage dataOwnerPkg = installedPkg; if (dataOwnerPkg == null) { PackageSetting ps = mSettings.mPackages.get(packageName); if (ps != null) { @@ -14057,7 +13928,7 @@ public class PackageManagerService extends IPackageManager.Stub if (dataOwnerPkg != null) { if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags, - dataOwnerPkg.applicationInfo.flags)) { + dataOwnerPkg.getFlags())) { try { checkDowngrade(dataOwnerPkg, pkgLite); } catch (PackageManagerException e) { @@ -14070,7 +13941,7 @@ public class PackageManagerService extends IPackageManager.Stub if (installedPkg != null) { if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { // Check for updated system application. - if ((installedPkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { + if ((installedPkg.getFlags() & ApplicationInfo.FLAG_SYSTEM) != 0) { return PackageHelper.RECOMMEND_INSTALL_INTERNAL; } else { // If current upgrade specifies particular preference @@ -14543,7 +14414,7 @@ public class PackageManagerService extends IPackageManager.Stub * Rename package into final resting place. All paths on the given * scanned package should be updated to reflect the rename. */ - abstract boolean doRename(int status, PackageParser.Package pkg); + abstract boolean doRename(int status, ParsedPackage parsedPackage); abstract int doPostInstall(int status, int uid); /** @see PackageSettingBase#codePathString */ @@ -14687,7 +14558,8 @@ public class PackageManagerService extends IPackageManager.Stub return status; } - boolean doRename(int status, PackageParser.Package pkg) { + @Override + boolean doRename(int status, ParsedPackage parsedPackage) { if (status != PackageManager.INSTALL_SUCCEEDED) { cleanUp(); return false; @@ -14695,7 +14567,7 @@ public class PackageManagerService extends IPackageManager.Stub final File targetDir = codeFile.getParentFile(); final File beforeCodeFile = codeFile; - final File afterCodeFile = getNextCodePath(targetDir, pkg.packageName); + final File afterCodeFile = getNextCodePath(targetDir, parsedPackage.getPackageName()); if (DEBUG_INSTALL) Slog.d(TAG, "Renaming " + beforeCodeFile + " to " + afterCodeFile); final boolean onIncremental = mIncrementalManager != null @@ -14723,24 +14595,23 @@ public class PackageManagerService extends IPackageManager.Stub // Reflect the rename in scanned details try { - pkg.setCodePath(afterCodeFile.getCanonicalPath()); + parsedPackage.setCodePath(afterCodeFile.getCanonicalPath()); } catch (IOException e) { Slog.e(TAG, "Failed to get path: " + afterCodeFile, e); return false; } - pkg.setBaseCodePath(FileUtils.rewriteAfterRename(beforeCodeFile, - afterCodeFile, pkg.baseCodePath)); - pkg.setSplitCodePaths(FileUtils.rewriteAfterRename(beforeCodeFile, - afterCodeFile, pkg.splitCodePaths)); + parsedPackage.setBaseCodePath(FileUtils.rewriteAfterRename(beforeCodeFile, + afterCodeFile, parsedPackage.getBaseCodePath())); + parsedPackage.setSplitCodePaths(FileUtils.rewriteAfterRename(beforeCodeFile, + afterCodeFile, parsedPackage.getSplitCodePaths())); // Reflect the rename in app info - pkg.setApplicationVolumeUuid(pkg.volumeUuid); - pkg.setApplicationInfoCodePath(pkg.codePath); - pkg.setApplicationInfoBaseCodePath(pkg.baseCodePath); - pkg.setApplicationInfoSplitCodePaths(pkg.splitCodePaths); - pkg.setApplicationInfoResourcePath(pkg.codePath); - pkg.setApplicationInfoBaseResourcePath(pkg.baseCodePath); - pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths); + // TODO(b/135203078): Remove all of these application info calls + parsedPackage.setApplicationVolumeUuid(parsedPackage.getVolumeUuid()) + .setApplicationInfoCodePath(parsedPackage.getCodePath()) + .setApplicationInfoResourcePath(parsedPackage.getCodePath()) + .setApplicationInfoBaseResourcePath(parsedPackage.getBaseCodePath()) + .setApplicationInfoSplitResourcePaths(parsedPackage.getSplitCodePaths()); return true; } @@ -14843,20 +14714,20 @@ public class PackageManagerService extends IPackageManager.Stub return status; } - boolean doRename(int status, PackageParser.Package pkg) { + @Override + boolean doRename(int status, ParsedPackage parsedPackage) { if (status != PackageManager.INSTALL_SUCCEEDED) { cleanUp(move.toUuid); return false; } // Reflect the move in app info - pkg.setApplicationVolumeUuid(pkg.volumeUuid); - pkg.setApplicationInfoCodePath(pkg.codePath); - pkg.setApplicationInfoBaseCodePath(pkg.baseCodePath); - pkg.setApplicationInfoSplitCodePaths(pkg.splitCodePaths); - pkg.setApplicationInfoResourcePath(pkg.codePath); - pkg.setApplicationInfoBaseResourcePath(pkg.baseCodePath); - pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths); + // TODO(b/135203078): Remove all of these application info calls + parsedPackage.setApplicationVolumeUuid(parsedPackage.getVolumeUuid()) + .setApplicationInfoCodePath(parsedPackage.getCodePath()) + .setApplicationInfoResourcePath(parsedPackage.getCodePath()) + .setApplicationInfoBaseResourcePath(parsedPackage.getBaseCodePath()) + .setApplicationInfoSplitResourcePaths(parsedPackage.getSplitCodePaths()); return true; } @@ -14932,14 +14803,14 @@ public class PackageManagerService extends IPackageManager.Stub int[] origUsers; // The set of users that now have this package installed. int[] newUsers; - PackageParser.Package pkg; + AndroidPackage pkg; int returnCode; String returnMsg; String installerPackageName; PackageRemovedInfo removedInfo; ArrayMap<String, PackageInstalledInfo> addedChildPackages; // The set of packages consuming this shared library or null if no consumers exist. - ArrayList<PackageParser.Package> libraryConsumers; + ArrayList<AndroidPackage> libraryConsumers; public void setError(int code, String msg) { setReturnCode(code); @@ -14995,66 +14866,15 @@ public class PackageManagerService extends IPackageManager.Stub } } - /** - * Checks whether the parent or any of the child packages have a change shared - * user. For a package to be a valid update the shred users of the parent and - * the children should match. We may later support changing child shared users. - * @param oldPkg The updated package. - * @param newPkg The update package. - * @return The shared user that change between the versions. - */ - private String getParentOrChildPackageChangedSharedUser(PackageParser.Package oldPkg, - PackageParser.Package newPkg) { - // Check parent shared user - if (!Objects.equals(oldPkg.mSharedUserId, newPkg.mSharedUserId)) { - return newPkg.packageName; - } - // Check child shared users - final int oldChildCount = (oldPkg.childPackages != null) ? oldPkg.childPackages.size() : 0; - final int newChildCount = (newPkg.childPackages != null) ? newPkg.childPackages.size() : 0; - for (int i = 0; i < newChildCount; i++) { - PackageParser.Package newChildPkg = newPkg.childPackages.get(i); - // If this child was present, did it have the same shared user? - for (int j = 0; j < oldChildCount; j++) { - PackageParser.Package oldChildPkg = oldPkg.childPackages.get(j); - if (newChildPkg.packageName.equals(oldChildPkg.packageName) - && !Objects.equals(newChildPkg.mSharedUserId, oldChildPkg.mSharedUserId)) { - return newChildPkg.packageName; - } - } - } - return null; - } - private void removeNativeBinariesLI(PackageSetting ps) { - // Remove the lib path for the parent package if (ps != null) { NativeLibraryHelper.removeNativeBinariesLI(ps.legacyNativeLibraryPathString); - // Remove the lib path for the child packages - final int childCount = (ps.childPackageNames != null) ? ps.childPackageNames.size() : 0; - for (int i = 0; i < childCount; i++) { - PackageSetting childPs = null; - synchronized (mLock) { - childPs = mSettings.getPackageLPr(ps.childPackageNames.get(i)); - } - if (childPs != null) { - NativeLibraryHelper.removeNativeBinariesLI(childPs - .legacyNativeLibraryPathString); - } - } } } @GuardedBy("mLock") - private void enableSystemPackageLPw(PackageParser.Package pkg) { - // Enable the parent package - mSettings.enableSystemPackageLPw(pkg.packageName); - // Enable the child packages - final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; - for (int i = 0; i < childCount; i++) { - PackageParser.Package childPkg = pkg.childPackages.get(i); - mSettings.enableSystemPackageLPw(childPkg.packageName); - } + private void enableSystemPackageLPw(AndroidPackage pkg) { + mSettings.enableSystemPackageLPw(pkg.getPackageName()); } @GuardedBy("mLock") @@ -15095,7 +14915,7 @@ public class PackageManagerService extends IPackageManager.Stub final int[] installedForUsers = res.origUsers; final int installReason = installArgs.installReason; - if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.codePath); + if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.getCodePath()); synchronized (mLock) { // NOTE: This changes slightly to include UPDATE_PERMISSIONS_ALL regardless of the size of pkg.permissions mPermissionManager.updatePermissions(pkgName, pkg); @@ -15168,7 +14988,7 @@ public class PackageManagerService extends IPackageManager.Stub mSettings.writeKernelMappingLPr(ps); } res.name = pkgName; - res.uid = pkg.applicationInfo.uid; + res.uid = pkg.getUid(); res.pkg = pkg; mSettings.setInstallerPackageName(pkgName, installerPackageName); res.setReturnCode(PackageManager.INSTALL_SUCCEEDED); @@ -15226,7 +15046,7 @@ public class PackageManagerService extends IPackageManager.Stub private static class ReconcileRequest { public final Map<String, ScanResult> scannedPackages; - public final Map<String, PackageParser.Package> allPackages; + public final Map<String, AndroidPackage> allPackages; public final Map<String, LongSparseArray<SharedLibraryInfo>> sharedLibrarySource; public final Map<String, InstallArgs> installArgs; public final Map<String, PackageInstalledInfo> installResults; @@ -15239,7 +15059,7 @@ public class PackageManagerService extends IPackageManager.Stub Map<String, PackageInstalledInfo> installResults, Map<String, PrepareResult> preparedPackages, Map<String, LongSparseArray<SharedLibraryInfo>> sharedLibrarySource, - Map<String, PackageParser.Package> allPackages, + Map<String, AndroidPackage> allPackages, Map<String, VersionInfo> versionInfos, Map<String, PackageSetting> lastStaticSharedLibSettings) { this.scannedPackages = scannedPackages; @@ -15254,7 +15074,7 @@ public class PackageManagerService extends IPackageManager.Stub private ReconcileRequest(Map<String, ScanResult> scannedPackages, Map<String, LongSparseArray<SharedLibraryInfo>> sharedLibrarySource, - Map<String, PackageParser.Package> allPackages, + Map<String, AndroidPackage> allPackages, Map<String, VersionInfo> versionInfos, Map<String, PackageSetting> lastStaticSharedLibSettings) { this(scannedPackages, Collections.emptyMap(), Collections.emptyMap(), @@ -15322,15 +15142,17 @@ public class PackageManagerService extends IPackageManager.Stub * with the package(s) currently being installed. The to-be installed packages take * precedence and may shadow already installed packages. */ - private Map<String, PackageParser.Package> getCombinedPackages() { - final ArrayMap<String, PackageParser.Package> combinedPackages = + private Map<String, AndroidPackage> getCombinedAvailablePackages() { + final ArrayMap<String, AndroidPackage> combined = new ArrayMap<>(request.allPackages.size() + request.scannedPackages.size()); - combinedPackages.putAll(request.allPackages); + combined.putAll(request.allPackages); + for (ScanResult scanResult : request.scannedPackages.values()) { - combinedPackages.put(scanResult.pkgSetting.name, scanResult.request.pkg); + combined.put(scanResult.pkgSetting.name, scanResult.request.parsedPackage); } - return combinedPackages; + + return combined; } } @@ -15343,8 +15165,9 @@ public class PackageManagerService extends IPackageManager.Stub final Map<String, ReconciledPackage> result = new ArrayMap<>(scannedPackages.size()); // make a copy of the existing set of packages so we can combine them with incoming packages - final ArrayMap<String, PackageParser.Package> combinedPackages = + final ArrayMap<String, AndroidPackage> combinedPackages = new ArrayMap<>(request.allPackages.size() + scannedPackages.size()); + combinedPackages.putAll(request.allPackages); final Map<String, LongSparseArray<SharedLibraryInfo>> incomingSharedLibraries = @@ -15354,7 +15177,7 @@ public class PackageManagerService extends IPackageManager.Stub final ScanResult scanResult = scannedPackages.get(installPackageName); // add / replace existing with incoming packages - combinedPackages.put(scanResult.pkgSetting.name, scanResult.request.pkg); + combinedPackages.put(scanResult.pkgSetting.name, scanResult.request.parsedPackage); // in the first pass, we'll build up the set of incoming shared libraries final List<SharedLibraryInfo> allowedSharedLibInfos = @@ -15387,7 +15210,7 @@ public class PackageManagerService extends IPackageManager.Stub | (killApp ? 0 : PackageManager.DELETE_DONT_KILL_APP); deletePackageAction = mayDeletePackageLocked(res.removedInfo, prepareResult.originalPs, prepareResult.disabledPs, - prepareResult.childPackageSettings, deleteFlags, null /* all users */); + deleteFlags, null /* all users */); if (deletePackageAction == null) { throw new ReconcileFailure( PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE, @@ -15399,7 +15222,7 @@ public class PackageManagerService extends IPackageManager.Stub final int scanFlags = scanResult.request.scanFlags; final int parseFlags = scanResult.request.parseFlags; - final PackageParser.Package pkg = scanResult.request.pkg; + final ParsedPackage parsedPackage = scanResult.request.parsedPackage; final PackageSetting disabledPkgSetting = scanResult.request.disabledPkgSetting; final PackageSetting lastStaticSharedLibSetting = @@ -15412,35 +15235,37 @@ public class PackageManagerService extends IPackageManager.Stub boolean sharedUserSignaturesChanged = false; SigningDetails signingDetails = null; if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, scanFlags)) { - if (ksms.checkUpgradeKeySetLocked(signatureCheckPs, pkg)) { + if (ksms.checkUpgradeKeySetLocked(signatureCheckPs, parsedPackage)) { // We just determined the app is signed correctly, so bring // over the latest parsed certs. } else { if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) { throw new ReconcileFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, - "Package " + pkg.packageName + " upgrade keys do not match the " - + "previously installed version"); + "Package " + parsedPackage.getPackageName() + + " upgrade keys do not match the previously installed" + + " version"); } else { - String msg = "System package " + pkg.packageName + String msg = "System package " + parsedPackage.getPackageName() + " signature changed; retaining data."; reportSettingsProblem(Log.WARN, msg); } } - signingDetails = pkg.mSigningDetails; + signingDetails = parsedPackage.getSigningDetails(); } else { try { final VersionInfo versionInfo = request.versionInfos.get(installPackageName); final boolean compareCompat = isCompatSignatureUpdateNeeded(versionInfo); final boolean compareRecover = isRecoverSignatureUpdateNeeded(versionInfo); final boolean compatMatch = verifySignatures(signatureCheckPs, - disabledPkgSetting, pkg.mSigningDetails, compareCompat, compareRecover); + disabledPkgSetting, parsedPackage.getSigningDetails(), compareCompat, + compareRecover); // The new KeySets will be re-added later in the scanning process. if (compatMatch) { removeAppKeySetData = true; } // We just determined the app is signed correctly, so bring // over the latest parsed certs. - signingDetails = pkg.mSigningDetails; + signingDetails = parsedPackage.getSigningDetails(); // if this is is a sharedUser, check to see if the new package is signed by a @@ -15448,10 +15273,10 @@ public class PackageManagerService extends IPackageManager.Stub // signing certificate than the existing one, and if so, copy over the new // details if (signatureCheckPs.sharedUser != null) { - if (pkg.mSigningDetails.hasAncestor( + if (parsedPackage.getSigningDetails().hasAncestor( signatureCheckPs.sharedUser.signatures.mSigningDetails)) { signatureCheckPs.sharedUser.signatures.mSigningDetails = - pkg.mSigningDetails; + parsedPackage.getSigningDetails(); } if (signatureCheckPs.sharedUser.signaturesChanged == null) { signatureCheckPs.sharedUser.signaturesChanged = Boolean.FALSE; @@ -15461,7 +15286,7 @@ public class PackageManagerService extends IPackageManager.Stub if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) { throw new ReconcileFailure(e); } - signingDetails = pkg.mSigningDetails; + signingDetails = parsedPackage.getSigningDetails(); // If the system app is part of a shared user we allow that shared user to // change @@ -15476,7 +15301,7 @@ public class PackageManagerService extends IPackageManager.Stub signatureCheckPs.sharedUser.signatures.mSigningDetails.signatures; if (signatureCheckPs.sharedUser.signaturesChanged != null && compareSignatures(sharedUserSignatures, - pkg.mSigningDetails.signatures) + parsedPackage.getSigningDetails().signatures) != PackageManager.SIGNATURE_MATCH) { if (SystemProperties.getInt("ro.product.first_api_level", 0) <= 29) { // Mismatched signatures is an error and silently skipping system @@ -15496,18 +15321,19 @@ public class PackageManagerService extends IPackageManager.Stub // whichever package happened to be scanned later. throw new IllegalStateException( "Signature mismatch on system package " - + pkg.packageName + " for shared user " + + parsedPackage.getPackageName() + + " for shared user " + scanResult.pkgSetting.sharedUser); } } sharedUserSignaturesChanged = true; signatureCheckPs.sharedUser.signatures.mSigningDetails = - pkg.mSigningDetails; + parsedPackage.getSigningDetails(); signatureCheckPs.sharedUser.signaturesChanged = Boolean.TRUE; } // File a report about this. - String msg = "System package " + pkg.packageName + String msg = "System package " + parsedPackage.getPackageName() + " signature changed; retaining data."; reportSettingsProblem(Log.WARN, msg); } catch (IllegalArgumentException e) { @@ -15541,8 +15367,9 @@ public class PackageManagerService extends IPackageManager.Stub } try { result.get(installPackageName).collectedSharedLibraryInfos = - collectSharedLibraryInfos(scanResult.request.pkg, combinedPackages, - request.sharedLibrarySource, incomingSharedLibraries); + collectSharedLibraryInfos(scanResult.request.parsedPackage, + combinedPackages, request.sharedLibrarySource, + incomingSharedLibraries); } catch (PackageManagerException e) { throw new ReconcileFailure(e.error, e.getMessage()); @@ -15560,7 +15387,7 @@ public class PackageManagerService extends IPackageManager.Stub ScanResult scanResult, Map<String, LongSparseArray<SharedLibraryInfo>> existingSharedLibraries) { // Let's used the parsed package as scanResult.pkgSetting may be null - final PackageParser.Package pkg = scanResult.request.pkg; + final ParsedPackage parsedPackage = scanResult.request.parsedPackage; if (scanResult.staticSharedLibraryInfo == null && scanResult.dynamicSharedLibraryInfos == null) { return null; @@ -15571,12 +15398,12 @@ public class PackageManagerService extends IPackageManager.Stub return Collections.singletonList(scanResult.staticSharedLibraryInfo); } final boolean hasDynamicLibraries = - (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0 + (parsedPackage.getFlags() & ApplicationInfo.FLAG_SYSTEM) != 0 && scanResult.dynamicSharedLibraryInfos != null; if (!hasDynamicLibraries) { return null; } - final boolean isUpdatedSystemApp = pkg.isUpdatedSystemApp(); + final boolean isUpdatedSystemApp = parsedPackage.isUpdatedSystemApp(); // We may not yet have disabled the updated package yet, so be sure to grab the // current setting if that's the case. final PackageSetting updatedSystemPs = isUpdatedSystemApp @@ -15585,9 +15412,9 @@ public class PackageManagerService extends IPackageManager.Stub : scanResult.request.disabledPkgSetting : null; if (isUpdatedSystemApp && (updatedSystemPs.pkg == null - || updatedSystemPs.pkg.libraryNames == null)) { - Slog.w(TAG, "Package " + pkg.packageName + " declares libraries that are not " - + "declared on the system image; skipping"); + || updatedSystemPs.pkg.getLibraryNames() == null)) { + Slog.w(TAG, "Package " + parsedPackage.getPackageName() + + " declares libraries that are not declared on the system image; skipping"); return null; } final ArrayList<SharedLibraryInfo> infos = @@ -15605,16 +15432,17 @@ public class PackageManagerService extends IPackageManager.Stub // with it. Better to just have the restriction here, be // conservative, and create many fewer cases that can negatively // impact the user experience. - if (!updatedSystemPs.pkg.libraryNames.contains(name)) { - Slog.w(TAG, "Package " + pkg.packageName + " declares library " + name + if (!updatedSystemPs.pkg.getLibraryNames().contains(name)) { + Slog.w(TAG, "Package " + parsedPackage.getPackageName() + + " declares library " + name + " that is not declared on system image; skipping"); continue; } } if (sharedLibExists( name, SharedLibraryInfo.VERSION_UNDEFINED, existingSharedLibraries)) { - Slog.w(TAG, "Package " + pkg.packageName + " declares library " + name - + " that already exists; skipping"); + Slog.w(TAG, "Package " + parsedPackage.getPackageName() + " declares library " + + name + " that already exists; skipping"); continue; } infos.add(info); @@ -15652,68 +15480,38 @@ public class PackageManagerService extends IPackageManager.Stub for (ReconciledPackage reconciledPkg : request.reconciledPackages.values()) { final ScanResult scanResult = reconciledPkg.scanResult; final ScanRequest scanRequest = scanResult.request; - final PackageParser.Package pkg = scanRequest.pkg; - final String packageName = pkg.packageName; + final ParsedPackage parsedPackage = scanRequest.parsedPackage; + final String packageName = parsedPackage.getPackageName(); final PackageInstalledInfo res = reconciledPkg.installResult; if (reconciledPkg.prepareResult.replace) { - PackageParser.Package oldPackage = mPackages.get(packageName); + AndroidPackage oldPackage = mPackages.get(packageName); // Set the update and install times - PackageSetting deletedPkgSetting = (PackageSetting) oldPackage.mExtras; - setInstallAndUpdateTime(pkg, deletedPkgSetting.firstInstallTime, - System.currentTimeMillis()); + PackageSetting deletedPkgSetting = getPackageSetting(oldPackage.getPackageName()); + reconciledPkg.pkgSetting.firstInstallTime = deletedPkgSetting.firstInstallTime; + reconciledPkg.pkgSetting.lastUpdateTime = System.currentTimeMillis(); if (reconciledPkg.prepareResult.system) { // Remove existing system package removePackageLI(oldPackage, true); - if (!disableSystemPackageLPw(oldPackage, pkg)) { + if (!disableSystemPackageLPw(oldPackage)) { // We didn't 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 one's .apk. res.removedInfo.args = createInstallArgsForExisting( - oldPackage.applicationInfo.getCodePath(), - oldPackage.applicationInfo.getResourcePath(), - getAppDexInstructionSets(oldPackage.applicationInfo)); + oldPackage.getAppInfoCodePath(), + oldPackage.getAppInfoResourcePath(), + getAppDexInstructionSets(oldPackage.getPrimaryCpuAbi(), + oldPackage.getSecondaryCpuAbi())); } else { res.removedInfo.args = null; } - - // Update the package dynamic state if succeeded - // Now that the install succeeded make sure we remove data - // directories for any child package the update removed. - final int deletedChildCount = (oldPackage.childPackages != null) - ? oldPackage.childPackages.size() : 0; - final int newChildCount = (pkg.childPackages != null) - ? pkg.childPackages.size() : 0; - for (int i = 0; i < deletedChildCount; i++) { - PackageParser.Package deletedChildPkg = oldPackage.childPackages.get(i); - boolean childPackageDeleted = true; - for (int j = 0; j < newChildCount; j++) { - PackageParser.Package newChildPkg = pkg.childPackages.get(j); - if (deletedChildPkg.packageName.equals(newChildPkg.packageName)) { - childPackageDeleted = false; - break; - } - } - if (childPackageDeleted) { - PackageSetting ps1 = mSettings.getDisabledSystemPkgLPr( - deletedChildPkg.packageName); - if (ps1 != null && res.removedInfo.removedChildPackages != null) { - PackageRemovedInfo removedChildRes = res.removedInfo - .removedChildPackages.get(deletedChildPkg.packageName); - removePackageDataLIF(ps1, request.mAllUsers, removedChildRes, 0, - false); - removedChildRes.removedForAllUsers = mPackages.get(ps1.name) - == null; - } - } - } } else { try { // Settings will be written during the call to updateSettingsLI(). executeDeletePackageLIF(reconciledPkg.deletePackageAction, packageName, - true, request.mAllUsers, false, pkg); + true, request.mAllUsers, false, parsedPackage); } catch (SystemDeleteException e) { if (Build.IS_ENG) { throw new RuntimeException("Unexpected failure", e); @@ -15729,56 +15527,34 @@ public class PackageManagerService extends IPackageManager.Stub Slog.i(TAG, "upgrading pkg " + oldPackage + " is ASEC-hosted -> UNAVAILABLE"); } - final int[] uidArray = new int[]{oldPackage.applicationInfo.uid}; + final int[] uidArray = new int[]{oldPackage.getUid()}; final ArrayList<String> pkgList = new ArrayList<>(1); - pkgList.add(oldPackage.applicationInfo.packageName); + pkgList.add(oldPackage.getAppInfoPackageName()); sendResourcesChangedBroadcast(false, true, pkgList, uidArray, null); } // Update the in-memory copy of the previous code paths. PackageSetting ps1 = mSettings.mPackages.get( - reconciledPkg.prepareResult.existingPackage.packageName); + 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.baseCodePath); - if (oldPackage.splitCodePaths != null) { - Collections.addAll(ps1.mOldCodePaths, oldPackage.splitCodePaths); + Collections.addAll(ps1.mOldCodePaths, oldPackage.getBaseCodePath()); + if (oldPackage.getSplitCodePaths() != null) { + Collections.addAll(ps1.mOldCodePaths, oldPackage.getSplitCodePaths()); } } else { ps1.mOldCodePaths = null; } - if (ps1.childPackageNames != null) { - for (int i = ps1.childPackageNames.size() - 1; i >= 0; --i) { - final String childPkgName = ps1.childPackageNames.get(i); - final PackageSetting childPs = mSettings.mPackages.get(childPkgName); - childPs.mOldCodePaths = ps1.mOldCodePaths; - } - } if (reconciledPkg.installResult.returnCode == PackageManager.INSTALL_SUCCEEDED) { - PackageSetting ps2 = mSettings.getPackageLPr(pkg.packageName); + PackageSetting ps2 = mSettings.getPackageLPr( + parsedPackage.getPackageName()); if (ps2 != null) { res.removedInfo.removedForAllUsers = mPackages.get(ps2.name) == null; - if (res.removedInfo.removedChildPackages != null) { - final int childCount1 = res.removedInfo.removedChildPackages.size(); - // Iterate in reverse as we may modify the collection - for (int i = childCount1 - 1; i >= 0; i--) { - String childPackageName = - res.removedInfo.removedChildPackages.keyAt(i); - if (res.addedChildPackages.containsKey(childPackageName)) { - res.removedInfo.removedChildPackages.removeAt(i); - } else { - PackageRemovedInfo childInfo = res.removedInfo - .removedChildPackages.valueAt(i); - childInfo.removedForAllUsers = mPackages.get( - childInfo.removedPackage) == null; - } - } - } } } } @@ -15862,33 +15638,31 @@ public class PackageManagerService extends IPackageManager.Stub request.installResult.installerPackageName = request.args.installSource.installerPackageName; - final String packageName = prepareResult.packageToScan.packageName; + final String packageName = prepareResult.packageToScan.getPackageName(); prepareResults.put(packageName, prepareResult); installResults.put(packageName, request.installResult); installArgs.put(packageName, request.args); try { - final List<ScanResult> scanResults = scanPackageTracedLI( + final ScanResult result = scanPackageTracedLI( prepareResult.packageToScan, prepareResult.parseFlags, prepareResult.scanFlags, System.currentTimeMillis(), request.args.user); - for (ScanResult result : scanResults) { - if (null != preparedScans.put(result.pkgSetting.pkg.packageName, result)) { - request.installResult.setError( - PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE, - "Duplicate package " + result.pkgSetting.pkg.packageName - + " in multi-package install request."); - return; - } - createdAppId.put(packageName, optimisticallyRegisterAppId(result)); - versionInfos.put(result.pkgSetting.pkg.packageName, - getSettingsVersionForPackage(result.pkgSetting.pkg)); - if (result.staticSharedLibraryInfo != null) { - final PackageSetting sharedLibLatestVersionSetting = - getSharedLibLatestVersionSetting(result); - if (sharedLibLatestVersionSetting != null) { - lastStaticSharedLibSettings.put(result.pkgSetting.pkg.packageName, - sharedLibLatestVersionSetting); - } + if (null != preparedScans.put(result.pkgSetting.pkg.getPackageName(), result)) { + request.installResult.setError( + PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE, + "Duplicate package " + result.pkgSetting.pkg.getPackageName() + + " in multi-package install request."); + return; + } + createdAppId.put(packageName, optimisticallyRegisterAppId(result)); + versionInfos.put(result.pkgSetting.pkg.getPackageName(), + getSettingsVersionForPackage(result.pkgSetting.pkg)); + if (result.staticSharedLibraryInfo != null) { + final PackageSetting sharedLibLatestVersionSetting = + getSharedLibLatestVersionSetting(result); + if (sharedLibLatestVersionSetting != null) { + lastStaticSharedLibSettings.put(result.pkgSetting.pkg.getPackageName(), + sharedLibLatestVersionSetting); } } } catch (PackageManagerException e) { @@ -15931,7 +15705,8 @@ public class PackageManagerService extends IPackageManager.Stub } finally { if (!success) { for (ScanResult result : preparedScans.values()) { - if (createdAppId.getOrDefault(result.request.pkg.packageName, false)) { + if (createdAppId.getOrDefault(result.request.parsedPackage.getPackageName(), + false)) { cleanUpAppIdCreation(result); } } @@ -15971,8 +15746,8 @@ public class PackageManagerService extends IPackageManager.Stub | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); } if (reconciledPkg.prepareResult.replace) { - mDexManager.notifyPackageUpdated(pkg.packageName, - pkg.baseCodePath, pkg.splitCodePaths); + mDexManager.notifyPackageUpdated(pkg.getPackageName(), + pkg.getBaseCodePath(), pkg.getSplitCodePaths()); } // Prepare the application profiles for the new code paths. @@ -15986,7 +15761,7 @@ public class PackageManagerService extends IPackageManager.Stub // Check whether we need to dexopt the app. // // NOTE: it is IMPORTANT to call dexopt: - // - after doRename which will sync the package data from PackageParser.Package and + // - after doRename which will sync the package data from AndroidPackage and // its corresponding ApplicationInfo. // - after installNewPackageLIF or replacePackageLIF which will update result with the // uid of the application (pkg.applicationInfo.uid). @@ -16051,14 +15826,13 @@ public class PackageManagerService extends IPackageManager.Stub public final int scanFlags; public final int parseFlags; @Nullable /* The original Package if it is being replaced, otherwise {@code null} */ - public final PackageParser.Package existingPackage; - public final PackageParser.Package packageToScan; + public final AndroidPackage existingPackage; + public final ParsedPackage packageToScan; public final boolean clearCodeCache; public final boolean system; public final PackageFreezer freezer; public final PackageSetting originalPs; public final PackageSetting disabledPs; - public final PackageSetting[] childPackageSettings; private PrepareResult(boolean replace, int scanFlags, int parseFlags, PackageParser.Package existingPackage, @@ -16075,7 +15849,6 @@ public class PackageManagerService extends IPackageManager.Stub this.freezer = freezer; this.originalPs = originalPs; this.disabledPs = disabledPs; - this.childPackageSettings = childPackageSettings; } } @@ -16154,10 +15927,10 @@ public class PackageManagerService extends IPackageManager.Stub pp.setCallback(mPackageParserCallback); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage"); - final PackageParser.Package pkg; + ParsedPackage parsedPackage; try { - pkg = pp.parsePackage(tmpPackageFile, parseFlags); - DexMetadataHelper.validatePackageDexMetadata(pkg); + parsedPackage = pp.parseParsedPackage(tmpPackageFile, parseFlags, false); + DexMetadataHelper.validatePackageDexMetadata(parsedPackage); } catch (PackageParserException e) { throw new PrepareFailure("Failed parse during installPackageLI", e); } finally { @@ -16166,23 +15939,23 @@ public class PackageManagerService extends IPackageManager.Stub // Instant apps have several additional install-time checks. if (instantApp) { - if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.O) { - Slog.w(TAG, - "Instant app package " + pkg.packageName + " does not target at least O"); + if (parsedPackage.getTargetSdkVersion() < Build.VERSION_CODES.O) { + Slog.w(TAG, "Instant app package " + parsedPackage.getPackageName() + + " does not target at least O"); throw new PrepareFailure(INSTALL_FAILED_INSTANT_APP_INVALID, "Instant app package must target at least O"); } - if (pkg.mSharedUserId != null) { - Slog.w(TAG, "Instant app package " + pkg.packageName + if (parsedPackage.getSharedUserId() != null) { + Slog.w(TAG, "Instant app package " + parsedPackage.getPackageName() + " may not declare sharedUserId."); throw new PrepareFailure(INSTALL_FAILED_INSTANT_APP_INVALID, "Instant app package may not declare a sharedUserId"); } } - if (pkg.applicationInfo.isStaticSharedLibrary()) { + if (parsedPackage.isStaticSharedLibrary()) { // Static shared libraries have synthetic package names - renameStaticSharedLibraryPackage(pkg); + renameStaticSharedLibraryPackage(parsedPackage); // No static shared libs on external storage if (onExternal) { @@ -16223,12 +15996,14 @@ public class PackageManagerService extends IPackageManager.Stub // If package doesn't declare API override, mark that we have an install // time CPU ABI override. - if (TextUtils.isEmpty(pkg.cpuAbiOverride)) { - pkg.cpuAbiOverride = args.abiOverride; + // TODO(b/135203078): Isn't this always true because cpuAbiOverride isn't assigned during + // parsing? + if (TextUtils.isEmpty(parsedPackage.getCpuAbiOverride())) { + parsedPackage.setCpuAbiOverride(args.abiOverride); } - String pkgName = res.name = pkg.packageName; - if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_TEST_ONLY) != 0) { + String pkgName = res.name = parsedPackage.getPackageName(); + if ((parsedPackage.getFlags() & ApplicationInfo.FLAG_TEST_ONLY) != 0) { if ((installFlags & PackageManager.INSTALL_ALLOW_TEST) == 0) { throw new PrepareFailure(INSTALL_FAILED_TEST_ONLY, "installPackageLI"); } @@ -16237,7 +16012,7 @@ public class PackageManagerService extends IPackageManager.Stub try { // either use what we've been given or parse directly from the APK if (args.signingDetails != PackageParser.SigningDetails.UNKNOWN) { - pkg.setSigningDetails(args.signingDetails); + parsedPackage.setSigningDetails(args.signingDetails); } else { // TODO(b/136132412): skip for Incremental installation PackageParser.collectCertificates(pkg, false /* skipVerify */); @@ -16246,9 +16021,9 @@ public class PackageManagerService extends IPackageManager.Stub throw new PrepareFailure("Failed collect during installPackageLI", e); } - if (instantApp && pkg.mSigningDetails.signatureSchemeVersion + if (instantApp && parsedPackage.getSigningDetails().signatureSchemeVersion < SignatureSchemeVersion.SIGNING_BLOCK_V2) { - Slog.w(TAG, "Instant app package " + pkg.packageName + Slog.w(TAG, "Instant app package " + parsedPackage.getPackageName() + " is not signed with at least APK Signature Scheme v2"); throw new PrepareFailure(INSTALL_FAILED_INSTANT_APP_INVALID, "Instant app package must be signed with APK Signature Scheme v2 or greater"); @@ -16262,15 +16037,15 @@ public class PackageManagerService extends IPackageManager.Stub // Check if installing already existing package if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { String oldName = mSettings.getRenamedPackageLPr(pkgName); - if (pkg.mOriginalPackages != null - && pkg.mOriginalPackages.contains(oldName) + if (parsedPackage.getOriginalPackages() != null + && parsedPackage.getOriginalPackages().contains(oldName) && mPackages.containsKey(oldName)) { // This package is derived from an original package, // and this device has been updating from that original // name. We must continue using the original name, so // rename the new package here. - pkg.setPackageName(oldName); - pkgName = pkg.packageName; + parsedPackage.setPackageName(oldName); + pkgName = parsedPackage.getPackageName(); replace = true; if (DEBUG_INSTALL) { Slog.d(TAG, "Replacing existing renamed package: oldName=" @@ -16283,43 +16058,27 @@ public class PackageManagerService extends IPackageManager.Stub if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing pacakge: " + pkgName); } - // Child packages are installed through the parent package - if (pkg.parentPackage != null) { - throw new PrepareFailure( - PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME, - "Package " + pkg.packageName + " is child of package " - + pkg.parentPackage.parentPackage + ". Child packages " - + "can be updated only through the parent package."); - } - if (replace) { // Prevent apps opting out from runtime permissions - PackageParser.Package oldPackage = mPackages.get(pkgName); - final int oldTargetSdk = oldPackage.applicationInfo.targetSdkVersion; - final int newTargetSdk = pkg.applicationInfo.targetSdkVersion; + AndroidPackage oldPackage = mPackages.get(pkgName); + final int oldTargetSdk = oldPackage.getTargetSdkVersion(); + final int newTargetSdk = parsedPackage.getTargetSdkVersion(); if (oldTargetSdk > Build.VERSION_CODES.LOLLIPOP_MR1 && newTargetSdk <= Build.VERSION_CODES.LOLLIPOP_MR1) { throw new PrepareFailure( PackageManager.INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE, - "Package " + pkg.packageName + " new target SDK " + newTargetSdk + "Package " + parsedPackage.getPackageName() + + " new target SDK " + newTargetSdk + " doesn't support runtime permissions but the old" + " target SDK " + oldTargetSdk + " does."); } // Prevent persistent apps from being updated - if (((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0) + if (((oldPackage.getFlags() & ApplicationInfo.FLAG_PERSISTENT) != 0) && ((installFlags & PackageManager.INSTALL_STAGED) == 0)) { throw new PrepareFailure(PackageManager.INSTALL_FAILED_INVALID_APK, - "Package " + oldPackage.packageName + " is a persistent app. " + "Package " + oldPackage.getPackageName() + " is a persistent app. " + "Persistent apps are not updateable."); } - // Prevent installing of child packages - if (oldPackage.parentPackage != null) { - throw new PrepareFailure( - PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME, - "Package " + pkg.packageName + " is child of package " - + oldPackage.parentPackage + ". Child packages " - + "can be updated only through the parent package."); - } } } @@ -16332,8 +16091,8 @@ public class PackageManagerService extends IPackageManager.Stub // of the same package, therefore we need to compare signatures against // the package setting for the latest library version. PackageSetting signatureCheckPs = ps; - if (pkg.applicationInfo.isStaticSharedLibrary()) { - SharedLibraryInfo libraryInfo = getLatestSharedLibraVersionLPr(pkg); + if (parsedPackage.isStaticSharedLibrary()) { + SharedLibraryInfo libraryInfo = getLatestSharedLibraVersionLPr(parsedPackage); if (libraryInfo != null) { signatureCheckPs = mSettings.getPackageLPr(libraryInfo.getPackageName()); } @@ -16344,23 +16103,23 @@ public class PackageManagerService extends IPackageManager.Stub // bail early here before tripping over redefined permissions. final KeySetManagerService ksms = mSettings.mKeySetManagerService; if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, scanFlags)) { - if (!ksms.checkUpgradeKeySetLocked(signatureCheckPs, pkg)) { + if (!ksms.checkUpgradeKeySetLocked(signatureCheckPs, parsedPackage)) { throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "Package " - + pkg.packageName + " upgrade keys do not match the " + + parsedPackage.getPackageName() + " upgrade keys do not match the " + "previously installed version"); } } else { try { - final boolean compareCompat = isCompatSignatureUpdateNeeded(pkg); - final boolean compareRecover = isRecoverSignatureUpdateNeeded(pkg); + final boolean compareCompat = isCompatSignatureUpdateNeeded(parsedPackage); + final boolean compareRecover = isRecoverSignatureUpdateNeeded( + parsedPackage); // We don't care about disabledPkgSetting on install for now. - final boolean compatMatch = verifySignatures( - signatureCheckPs, null, pkg.mSigningDetails, compareCompat, - compareRecover); + final boolean compatMatch = verifySignatures(signatureCheckPs, null, + parsedPackage.getSigningDetails(), compareCompat, compareRecover); // The new KeySets will be re-added later in the scanning process. if (compatMatch) { synchronized (mLock) { - ksms.removeAppKeySetDataLPw(pkg.packageName); + ksms.removeAppKeySetDataLPw(parsedPackage.getPackageName()); } } } catch (PackageManagerException e) { @@ -16368,27 +16127,25 @@ public class PackageManagerService extends IPackageManager.Stub } } - if (ps.pkg != null && ps.pkg.applicationInfo != null) { - systemApp = (ps.pkg.applicationInfo.flags & - ApplicationInfo.FLAG_SYSTEM) != 0; + if (ps.pkg != null) { + systemApp = (ps.pkg.getFlags() & ApplicationInfo.FLAG_SYSTEM) != 0; } res.origUsers = ps.queryInstalledUsers(mUserManager.getUserIds(), true); } - int N = pkg.permissions.size(); + int N = ArrayUtils.size(parsedPackage.getPermissions()); for (int i = N - 1; i >= 0; i--) { - final PackageParser.Permission perm = pkg.permissions.get(i); - final BasePermission bp = - (BasePermission) mPermissionManager.getPermissionTEMP(perm.info.name); + final ParsedPermission perm = parsedPackage.getPermissions().get(i); + final BasePermission bp = mPermissionManager.getPermissionTEMP(perm.getName()); // Don't allow anyone but the system to define ephemeral permissions. - if ((perm.info.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0 + if ((perm.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0 && !systemApp) { - Slog.w(TAG, "Non-System package " + pkg.packageName + Slog.w(TAG, "Non-System package " + parsedPackage.getPackageName() + " attempting to delcare ephemeral permission " - + perm.info.name + "; Removing ephemeral."); - perm.info.protectionLevel &= ~PermissionInfo.PROTECTION_FLAG_INSTANT; + + perm.getName() + "; Removing ephemeral."); + perm.protectionLevel &= ~PermissionInfo.PROTECTION_FLAG_INSTANT; } // Check whether the newly-scanned package wants to define an already-defined perm @@ -16400,26 +16157,27 @@ public class PackageManagerService extends IPackageManager.Stub final String sourcePackageName = bp.getSourcePackageName(); final PackageSettingBase sourcePackageSetting = bp.getSourcePackageSetting(); final KeySetManagerService ksms = mSettings.mKeySetManagerService; - if (sourcePackageName.equals(pkg.packageName) + if (sourcePackageName.equals(parsedPackage.getPackageName()) && (ksms.shouldCheckUpgradeKeySetLocked( sourcePackageSetting, scanFlags))) { - sigsOk = ksms.checkUpgradeKeySetLocked(sourcePackageSetting, pkg); + sigsOk = ksms.checkUpgradeKeySetLocked(sourcePackageSetting, parsedPackage); } else { // in the event of signing certificate rotation, we need to see if the // package's certificate has rotated from the current one, or if it is an // older certificate with which the current is ok with sharing permissions if (sourcePackageSetting.signatures.mSigningDetails.checkCapability( - pkg.mSigningDetails, + parsedPackage.getSigningDetails(), PackageParser.SigningDetails.CertCapabilities.PERMISSION)) { sigsOk = true; - } else if (pkg.mSigningDetails.checkCapability( + } else if (parsedPackage.getSigningDetails().checkCapability( sourcePackageSetting.signatures.mSigningDetails, PackageParser.SigningDetails.CertCapabilities.PERMISSION)) { // the scanned package checks out, has signing certificate rotation // history, and is newer; bring it over - sourcePackageSetting.signatures.mSigningDetails = pkg.mSigningDetails; + sourcePackageSetting.signatures.mSigningDetails = + parsedPackage.getSigningDetails(); sigsOk = true; } else { sigsOk = false; @@ -16431,30 +16189,31 @@ public class PackageManagerService extends IPackageManager.Stub // redefinitions. if (!sourcePackageName.equals("android")) { throw new PrepareFailure(INSTALL_FAILED_DUPLICATE_PERMISSION, "Package " - + pkg.packageName + + parsedPackage.getPackageName() + " attempting to redeclare permission " - + perm.info.name + " already owned by " + + perm.getName() + " already owned by " + sourcePackageName) - .conflictsWithExistingPermission(perm.info.name, + .conflictsWithExistingPermission(perm.getName(), sourcePackageName); } else { - Slog.w(TAG, "Package " + pkg.packageName + Slog.w(TAG, "Package " + parsedPackage.getPackageName() + " attempting to redeclare system permission " - + perm.info.name + "; ignoring new declaration"); - pkg.permissions.remove(i); + + perm.getName() + "; ignoring new declaration"); + parsedPackage.removePermission(i); } - } else if (!PLATFORM_PACKAGE_NAME.equals(pkg.packageName)) { + } else if (!PLATFORM_PACKAGE_NAME.equals(parsedPackage.getPackageName())) { // Prevent apps to change protection level to dangerous from any other // type as this would allow a privilege escalation where an app adds a // normal/signature permission in other app's group and later redefines // it as dangerous leading to the group auto-grant. - if ((perm.info.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) + if ((perm.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) == PermissionInfo.PROTECTION_DANGEROUS) { if (bp != null && !bp.isRuntime()) { - Slog.w(TAG, "Package " + pkg.packageName + " trying to change a " - + "non-runtime permission " + perm.info.name + Slog.w(TAG, "Package " + parsedPackage.getPackageName() + + " trying to change a non-runtime permission " + + perm.getName() + " to runtime; keeping old protection level"); - perm.info.protectionLevel = bp.getProtectionLevel(); + perm.protectionLevel = bp.getProtectionLevel(); } } } @@ -16488,8 +16247,8 @@ public class PackageManagerService extends IPackageManager.Stub // We moved the entire application as-is, so bring over the // previously derived ABI information. - pkg.applicationInfo.primaryCpuAbi = ps.primaryCpuAbiString; - pkg.applicationInfo.secondaryCpuAbi = ps.secondaryCpuAbiString; + parsedPackage.setPrimaryCpuAbi(ps.primaryCpuAbiString) + .setSecondaryCpuAbi(ps.secondaryCpuAbiString); } } else { @@ -16497,14 +16256,14 @@ public class PackageManagerService extends IPackageManager.Stub scanFlags |= SCAN_NO_DEX; try { - String abiOverride = (TextUtils.isEmpty(pkg.cpuAbiOverride) ? - args.abiOverride : pkg.cpuAbiOverride); - final boolean extractNativeLibs = !pkg.isLibrary(); + String abiOverride = (TextUtils.isEmpty(parsedPackage.getCpuAbiOverride()) + ? args.abiOverride : parsedPackage.getCpuAbiOverride()); + final boolean extractNativeLibs = !parsedPackage.isLibrary(); final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths> derivedAbi = mInjector.getAbiHelper().derivePackageAbi( - pkg, abiOverride, extractNativeLibs); - derivedAbi.first.applyTo(pkg); - derivedAbi.second.applyTo(pkg); + parsedPackage, abiOverride, extractNativeLibs); + derivedAbi.first.applyTo(parsedPackage); + derivedAbi.second.applyTo(parsedPackage); } catch (PackageManagerException pme) { Slog.e(TAG, "Error deriving application ABI", pme); throw new PrepareFailure(INSTALL_FAILED_INTERNAL_ERROR, @@ -16512,19 +16271,19 @@ public class PackageManagerService extends IPackageManager.Stub } } - if (!args.doRename(res.returnCode, pkg)) { + if (!args.doRename(res.returnCode, parsedPackage)) { throw new PrepareFailure(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Failed rename"); } try { - setUpFsVerityIfPossible(pkg); + setUpFsVerityIfPossible(parsedPackage); } catch (InstallerException | IOException | DigestException | NoSuchAlgorithmException e) { throw new PrepareFailure(INSTALL_FAILED_INTERNAL_ERROR, "Failed to set up verity: " + e); } if (!instantApp) { - startIntentFilterVerifications(args.user.getIdentifier(), replace, pkg); + startIntentFilterVerifications(args.user.getIdentifier(), replace, parsedPackage); } else { if (DEBUG_DOMAIN_VERIFICATION) { Slog.d(TAG, "Not verifying instant app install for app links: " + pkgName); @@ -16534,7 +16293,7 @@ public class PackageManagerService extends IPackageManager.Stub freezePackageForInstall(pkgName, installFlags, "installPackageLI"); boolean shouldCloseFreezerBeforeReturn = true; try { - final PackageParser.Package existingPackage; + final AndroidPackage existingPackage; String renamedPackage = null; boolean sysPkg = false; int targetScanFlags = scanFlags; @@ -16548,9 +16307,10 @@ public class PackageManagerService extends IPackageManager.Stub // and cannot be updated as an update would get a new package name, // unless this is the exact same version code which is useful for // development. - PackageParser.Package existingPkg = mPackages.get(pkg.packageName); + AndroidPackage existingPkg = mPackages.get(parsedPackage.getPackageName()); if (existingPkg != null - && existingPkg.getLongVersionCode() != pkg.getLongVersionCode()) { + && existingPkg.getLongVersionCode() + != parsedPackage.getLongVersionCode()) { throw new PrepareFailure(INSTALL_FAILED_DUPLICATE_PACKAGE, "Packages declaring " + "static-shared libs cannot be updated"); @@ -16559,8 +16319,8 @@ public class PackageManagerService extends IPackageManager.Stub final boolean isInstantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0; - final PackageParser.Package oldPackage; - final String pkgName11 = pkg.packageName; + final AndroidPackage oldPackage; + final String pkgName11 = parsedPackage.getPackageName(); final int[] allUsers; final int[] installedUsers; @@ -16568,8 +16328,9 @@ public class PackageManagerService extends IPackageManager.Stub oldPackage = mPackages.get(pkgName11); existingPackage = oldPackage; if (DEBUG_INSTALL) { + // TODO(b/135203078): PackageImpl.toString() Slog.d(TAG, - "replacePackageLI: new=" + pkg + ", old=" + oldPackage); + "replacePackageLI: new=" + parsedPackage + ", old=" + oldPackage); } ps = mSettings.mPackages.get(pkgName11); @@ -16578,17 +16339,18 @@ public class PackageManagerService extends IPackageManager.Stub // verify signatures are valid final KeySetManagerService ksms = mSettings.mKeySetManagerService; if (ksms.shouldCheckUpgradeKeySetLocked(ps, scanFlags)) { - if (!ksms.checkUpgradeKeySetLocked(ps, pkg)) { + if (!ksms.checkUpgradeKeySetLocked(ps, parsedPackage)) { throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "New package not signed by keys specified by upgrade-keysets: " + pkgName11); } } else { // default to original signature matching - if (!pkg.mSigningDetails.checkCapability(oldPackage.mSigningDetails, + if (!parsedPackage.getSigningDetails().checkCapability( + oldPackage.getSigningDetails(), SigningDetails.CertCapabilities.INSTALLED_DATA) - && !oldPackage.mSigningDetails.checkCapability( - pkg.mSigningDetails, + && !oldPackage.getSigningDetails().checkCapability( + parsedPackage.getSigningDetails(), SigningDetails.CertCapabilities.ROLLBACK)) { throw new PrepareFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE, "New package has a different signature: " + pkgName11); @@ -16596,13 +16358,13 @@ public class PackageManagerService extends IPackageManager.Stub } // don't allow a system upgrade unless the upgrade hash matches - if (oldPackage.restrictUpdateHash != null && oldPackage.isSystem()) { + if (oldPackage.getRestrictUpdateHash() != null && oldPackage.isSystem()) { final byte[] digestBytes; try { final MessageDigest digest = MessageDigest.getInstance("SHA-512"); - updateDigest(digest, new File(pkg.baseCodePath)); - if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { - for (String path : pkg.splitCodePaths) { + updateDigest(digest, new File(parsedPackage.getBaseCodePath())); + if (!ArrayUtils.isEmpty(parsedPackage.getSplitCodePaths())) { + for (String path : parsedPackage.getSplitCodePaths()) { updateDigest(digest, new File(path)); } } @@ -16611,21 +16373,25 @@ public class PackageManagerService extends IPackageManager.Stub throw new PrepareFailure(INSTALL_FAILED_INVALID_APK, "Could not compute hash: " + pkgName11); } - if (!Arrays.equals(oldPackage.restrictUpdateHash, digestBytes)) { + if (!Arrays.equals(oldPackage.getRestrictUpdateHash(), digestBytes)) { throw new PrepareFailure(INSTALL_FAILED_INVALID_APK, "New package fails restrict-update check: " + pkgName11); } // retain upgrade restriction - pkg.restrictUpdateHash = oldPackage.restrictUpdateHash; + parsedPackage.setRestrictUpdateHash(oldPackage.getRestrictUpdateHash()); } // Check for shared user id changes - String invalidPackageName = - getParentOrChildPackageChangedSharedUser(oldPackage, pkg); + String invalidPackageName = null; + if (!Objects.equals(oldPackage.getSharedUserId(), + parsedPackage.getSharedUserId())) { + invalidPackageName = parsedPackage.getPackageName(); + } + if (invalidPackageName != null) { throw new PrepareFailure(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE, "Package " + invalidPackageName + " tried to change user " - + oldPackage.mSharedUserId); + + oldPackage.getSharedUserId()); } // In case of rollback, remember per-user/profile install state @@ -16735,41 +16501,30 @@ public class PackageManagerService extends IPackageManager.Stub | (odm ? SCAN_AS_ODM : 0); if (DEBUG_INSTALL) { - Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg + Slog.d(TAG, "replaceSystemPackageLI: new=" + parsedPackage + ", old=" + oldPackage); } res.setReturnCode(PackageManager.INSTALL_SUCCEEDED); - pkg.setApplicationInfoFlags(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP, - ApplicationInfo.FLAG_UPDATED_SYSTEM_APP); + parsedPackage.setUpdatedSystemApp(true); targetParseFlags = systemParseFlags; targetScanFlags = systemScanFlags; } else { // non system replace replace = true; if (DEBUG_INSTALL) { Slog.d(TAG, - "replaceNonSystemPackageLI: new=" + pkg + ", old=" + "replaceNonSystemPackageLI: new=" + parsedPackage + ", old=" + oldPackage); } - - String pkgName1 = oldPackage.packageName; - boolean deletedPkg = true; - boolean addedPkg = false; - boolean updatedSettings = false; - - final long origUpdateTime = (pkg.mExtras != null) - ? ((PackageSetting) pkg.mExtras).lastUpdateTime : 0; - } } else { // new package install ps = null; - childPackages = null; disabledPs = null; replace = false; existingPackage = null; // Remember this for later, in case we need to rollback this install - String pkgName1 = pkg.packageName; + String pkgName1 = parsedPackage.getPackageName(); - if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg); + if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + parsedPackage); // TODO(patb): MOVE TO RECONCILE synchronized (mLock) { @@ -16812,7 +16567,7 @@ public class PackageManagerService extends IPackageManager.Stub * <p>When the feature flag is set to legacy mode, only APK is supported (with some experimental * kernel patches). In normal mode, all file format can be supported. */ - private void setUpFsVerityIfPossible(PackageParser.Package pkg) throws InstallerException, + private void setUpFsVerityIfPossible(AndroidPackage pkg) throws InstallerException, PrepareFailure, IOException, DigestException, NoSuchAlgorithmException { final boolean standardMode = PackageManagerServiceUtils.isApkVerityEnabled(); final boolean legacyMode = PackageManagerServiceUtils.isLegacyApkVerityEnabled(); @@ -16824,11 +16579,11 @@ public class PackageManagerService extends IPackageManager.Stub ArrayMap<String, String> fsverityCandidates = new ArrayMap<>(); if (legacyMode) { synchronized (mLock) { - final PackageSetting ps = mSettings.mPackages.get(pkg.packageName); + final PackageSetting ps = mSettings.mPackages.get(pkg.getPackageName()); if (ps != null && ps.isPrivileged()) { - fsverityCandidates.put(pkg.baseCodePath, null); - if (pkg.splitCodePaths != null) { - for (String splitPath : pkg.splitCodePaths) { + fsverityCandidates.put(pkg.getBaseCodePath(), null); + if (pkg.getSplitCodePaths() != null) { + for (String splitPath : pkg.getSplitCodePaths()) { fsverityCandidates.put(splitPath, null); } } @@ -16837,16 +16592,17 @@ public class PackageManagerService extends IPackageManager.Stub } else { // NB: These files will become only accessible if the signing key is loaded in kernel's // .fs-verity keyring. - fsverityCandidates.put(pkg.baseCodePath, - VerityUtils.getFsveritySignatureFilePath(pkg.baseCodePath)); + fsverityCandidates.put(pkg.getBaseCodePath(), + VerityUtils.getFsveritySignatureFilePath(pkg.getBaseCodePath())); - final String dmPath = DexMetadataHelper.buildDexMetadataPathForApk(pkg.baseCodePath); + final String dmPath = DexMetadataHelper.buildDexMetadataPathForApk( + pkg.getBaseCodePath()); if (new File(dmPath).exists()) { fsverityCandidates.put(dmPath, VerityUtils.getFsveritySignatureFilePath(dmPath)); } - if (pkg.splitCodePaths != null) { - for (String path : pkg.splitCodePaths) { + if (pkg.getSplitCodePaths() != null) { + for (String path : pkg.getSplitCodePaths()) { fsverityCandidates.put(path, VerityUtils.getFsveritySignatureFilePath(path)); final String splitDmPath = DexMetadataHelper.buildDexMetadataPathForApk(path); @@ -16900,8 +16656,7 @@ public class PackageManagerService extends IPackageManager.Stub } } - private void startIntentFilterVerifications(int userId, boolean replacing, - PackageParser.Package pkg) { + private void startIntentFilterVerifications(int userId, boolean replacing, AndroidPackage pkg) { if (mIntentFilterVerifierComponent == null) { Slog.w(TAG, "No IntentFilter verification will not be done as " + "there is no IntentFilterVerifier available!"); @@ -16914,29 +16669,29 @@ public class PackageManagerService extends IPackageManager.Stub (userId == UserHandle.USER_ALL) ? UserHandle.USER_SYSTEM : userId); Message msg = mHandler.obtainMessage(START_INTENT_FILTER_VERIFICATIONS); - msg.obj = new IFVerificationParams(pkg, replacing, userId, verifierUid); + msg.obj = new IFVerificationParams( + pkg.getPackageName(), + hasDomainURLs(pkg), + pkg.getActivities(), + replacing, + userId, + verifierUid + ); mHandler.sendMessage(msg); - - final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; - for (int i = 0; i < childCount; i++) { - PackageParser.Package childPkg = pkg.childPackages.get(i); - msg = mHandler.obtainMessage(START_INTENT_FILTER_VERIFICATIONS); - msg.obj = new IFVerificationParams(childPkg, replacing, userId, verifierUid); - mHandler.sendMessage(msg); - } } private void verifyIntentFiltersIfNeeded(int userId, int verifierUid, boolean replacing, - PackageParser.Package pkg) { - int size = pkg.activities.size(); + String packageName, + boolean hasDomainUrls, + List<ParsedActivity> activities) { + int size = activities.size(); if (size == 0) { if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "No activity, so no need to verify any IntentFilter!"); return; } - final boolean hasDomainURLs = hasDomainURLs(pkg); - if (!hasDomainURLs) { + if (!hasDomainUrls) { if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "No domain URLs, so no need to verify any IntentFilter!"); return; @@ -16947,7 +16702,6 @@ public class PackageManagerService extends IPackageManager.Stub + " Activities needs verification ..."); int count = 0; - final String packageName = pkg.packageName; synchronized (mLock) { // If this is a new install and we see that we've already run verification for this @@ -16966,8 +16720,8 @@ public class PackageManagerService extends IPackageManager.Stub // If any filters need to be verified, then all need to be. boolean needToVerify = false; - for (PackageParser.Activity a : pkg.activities) { - for (ActivityIntentInfo filter : a.intents) { + for (ParsedActivity a : activities) { + for (ParsedActivityIntentInfo filter : a.intents) { if (filter.needsVerification() && needsNetworkVerificationLPr(filter)) { if (DEBUG_DOMAIN_VERIFICATION) { Slog.d(TAG, @@ -16981,8 +16735,8 @@ public class PackageManagerService extends IPackageManager.Stub if (needToVerify) { final int verificationId = mIntentFilterVerificationToken++; - for (PackageParser.Activity a : pkg.activities) { - for (ActivityIntentInfo filter : a.intents) { + for (ParsedActivity a : activities) { + for (ParsedActivityIntentInfo filter : a.intents) { if (filter.handlesWebUris(true) && needsNetworkVerificationLPr(filter)) { if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Verification needed for IntentFilter:" + filter.toString()); @@ -17008,9 +16762,8 @@ public class PackageManagerService extends IPackageManager.Stub } @GuardedBy("mLock") - private boolean needsNetworkVerificationLPr(ActivityIntentInfo filter) { - final ComponentName cn = filter.activity.getComponentName(); - final String packageName = cn.getPackageName(); + private boolean needsNetworkVerificationLPr(ParsedActivityIntentInfo filter) { + final String packageName = filter.getPackageName(); IntentFilterVerificationInfo ivi = mSettings.getIntentFilterVerificationLPr( packageName); @@ -17030,45 +16783,45 @@ public class PackageManagerService extends IPackageManager.Stub } } - private static boolean isExternal(PackageParser.Package pkg) { - return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0; + private static boolean isExternal(AndroidPackage pkg) { + return (pkg.getFlags() & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0; } private static boolean isExternal(PackageSetting ps) { return (ps.pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0; } - static boolean isSystemApp(PackageParser.Package pkg) { - return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; + static boolean isSystemApp(AndroidPackage pkg) { + return (pkg.getFlags() & ApplicationInfo.FLAG_SYSTEM) != 0; } - private static boolean isPrivilegedApp(PackageParser.Package pkg) { - return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; + private static boolean isPrivilegedApp(AndroidPackage pkg) { + return (pkg.getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; } - private static boolean isOemApp(PackageParser.Package pkg) { - return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0; + private static boolean isOemApp(AndroidPackage pkg) { + return (pkg.getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_OEM) != 0; } - private static boolean isVendorApp(PackageParser.Package pkg) { - return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0; + private static boolean isVendorApp(AndroidPackage pkg) { + return (pkg.getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0; } - private static boolean isProductApp(PackageParser.Package pkg) { - return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0; + private static boolean isProductApp(AndroidPackage pkg) { + return (pkg.getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0; } - private static boolean isSystemExtApp(PackageParser.Package pkg) { - return (pkg.applicationInfo.privateFlags + private static boolean isSystemExtApp(AndroidPackage pkg) { + return (pkg.getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT) != 0; } - private static boolean isOdmApp(PackageParser.Package pkg) { - return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_ODM) != 0; + private static boolean isOdmApp(AndroidPackage pkg) { + return (pkg.getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_ODM) != 0; } - private static boolean hasDomainURLs(PackageParser.Package pkg) { - return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0; + private static boolean hasDomainURLs(AndroidPackage pkg) { + return (pkg.getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0; } private static boolean isSystemApp(PackageSetting ps) { @@ -17079,12 +16832,12 @@ public class PackageManagerService extends IPackageManager.Stub return (ps.pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0; } - private VersionInfo getSettingsVersionForPackage(PackageParser.Package pkg) { + private VersionInfo getSettingsVersionForPackage(AndroidPackage pkg) { if (isExternal(pkg)) { - if (TextUtils.isEmpty(pkg.volumeUuid)) { + if (TextUtils.isEmpty(pkg.getVolumeUuid())) { return mSettings.getExternalVersion(); } else { - return mSettings.findOrCreateVersion(pkg.volumeUuid); + return mSettings.findOrCreateVersion(pkg.getVolumeUuid()); } } else { return mSettings.getInternalVersion(); @@ -17092,6 +16845,7 @@ public class PackageManagerService extends IPackageManager.Stub } private void deleteTempPackageFiles() { + // TODO: Is this used? final FilenameFilter filter = (dir, name) -> name.startsWith("vmdl") && name.endsWith(".tmp"); } @@ -17225,11 +16979,11 @@ public class PackageManagerService extends IPackageManager.Stub }); } - private String resolveExternalPackageNameLPr(PackageParser.Package pkg) { - if (pkg.staticSharedLibName != null) { - return pkg.manifestPackageName; + private String resolveExternalPackageNameLPr(AndroidPackage pkg) { + if (pkg.getStaticSharedLibName() != null) { + return pkg.getManifestPackageName(); } - return pkg.packageName; + return pkg.getPackageName(); } @GuardedBy("mLock") @@ -17436,7 +17190,7 @@ public class PackageManagerService extends IPackageManager.Stub final PackageSetting uninstalledPs; final PackageSetting disabledSystemPs; - final PackageParser.Package pkg; + final AndroidPackage pkg; // for the uninstall-updates case and restricted profiles, remember the per- // user handle installed state @@ -17468,9 +17222,9 @@ public class PackageManagerService extends IPackageManager.Stub allUsers = mUserManager.getUserIds(); - if (pkg != null && pkg.staticSharedLibName != null) { - SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(pkg.staticSharedLibName, - pkg.staticSharedLibVersion); + if (pkg != null && pkg.getStaticSharedLibName() != null) { + SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr( + pkg.getStaticSharedLibName(), pkg.getStaticSharedLibVersion()); if (libraryInfo != null) { for (int currUserId : allUsers) { if (removeUser != UserHandle.USER_ALL && removeUser != currUserId) { @@ -17479,7 +17233,7 @@ public class PackageManagerService extends IPackageManager.Stub List<VersionedPackage> libClientPackages = getPackagesUsingSharedLibraryLPr( libraryInfo, MATCH_KNOWN_PACKAGES, currUserId); if (!ArrayUtils.isEmpty(libClientPackages)) { - Slog.w(TAG, "Not removing package " + pkg.manifestPackageName + Slog.w(TAG, "Not removing package " + pkg.getManifestPackageName() + " hosting lib " + libraryInfo.getName() + " version " + libraryInfo.getLongVersion() + " used by " + libClientPackages + " for user " + currUserId); @@ -17534,13 +17288,13 @@ public class PackageManagerService extends IPackageManager.Stub if (info.args != null) { info.args.doPostDeleteLI(true); } - final PackageParser.Package stubPkg = + final AndroidPackage stubPkg = (disabledSystemPs == null) ? null : disabledSystemPs.pkg; - if (stubPkg != null && stubPkg.isStub) { + if (stubPkg != null && stubPkg.isStub()) { synchronized (mLock) { // restore the enabled state of the stub; the state is overwritten when // the stub is uninstalled - final PackageSetting stubPs = mSettings.mPackages.get(stubPkg.packageName); + final PackageSetting stubPs = mSettings.mPackages.get(stubPkg.getPackageName()); if (stubPs != null) { stubPs.setEnabled(origEnabledState, userId, "android"); } @@ -17549,7 +17303,7 @@ public class PackageManagerService extends IPackageManager.Stub || origEnabledState == COMPONENT_ENABLED_STATE_ENABLED) { if (DEBUG_COMPRESSION) { Slog.i(TAG, "Enabling system stub after removal; pkg: " - + stubPkg.packageName); + + stubPkg.getPackageName()); } enableCompressedPackage(stubPkg); } @@ -17577,7 +17331,6 @@ public class PackageManagerService extends IPackageManager.Stub boolean isStaticSharedLib; // Clean up resources deleted packages. InstallArgs args = null; - ArrayMap<String, PackageRemovedInfo> removedChildPackages; ArrayMap<String, PackageInstalledInfo> appearedChildPackages; PackageRemovedInfo(PackageSender packageSender) { @@ -17586,24 +17339,11 @@ public class PackageManagerService extends IPackageManager.Stub void sendPackageRemovedBroadcasts(boolean killApp) { sendPackageRemovedBroadcastInternal(killApp); - final int childCount = removedChildPackages != null ? removedChildPackages.size() : 0; - for (int i = 0; i < childCount; i++) { - PackageRemovedInfo childInfo = removedChildPackages.valueAt(i); - childInfo.sendPackageRemovedBroadcastInternal(killApp); - } } void sendSystemPackageUpdatedBroadcasts() { if (isRemovedPackageSystemUpdate) { sendSystemPackageUpdatedBroadcastsInternal(); - final int childCount = (removedChildPackages != null) - ? removedChildPackages.size() : 0; - for (int i = 0; i < childCount; i++) { - PackageRemovedInfo childInfo = removedChildPackages.valueAt(i); - if (childInfo.isRemovedPackageSystemUpdate) { - childInfo.sendSystemPackageUpdatedBroadcastsInternal(); - } - } } } @@ -17715,12 +17455,12 @@ public class PackageManagerService extends IPackageManager.Stub String packageName = deletedPs.name; if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + deletedPs); // Retrieve object to delete permissions for shared user later on - final PackageParser.Package deletedPkg = deletedPs.pkg; + final AndroidPackage deletedPkg = deletedPs.pkg; if (outInfo != null) { outInfo.removedPackage = packageName; outInfo.installerPackageName = deletedPs.installSource.installerPackageName; outInfo.isStaticSharedLib = deletedPkg != null - && deletedPkg.staticSharedLibName != null; + && deletedPkg.getStaticSharedLibName() != null; outInfo.populateUsers(deletedPs == null ? null : deletedPs.queryInstalledUsers(mUserManager.getUserIds(), true), deletedPs); } @@ -17728,14 +17468,14 @@ public class PackageManagerService extends IPackageManager.Stub removePackageLI(deletedPs.name, (flags & PackageManager.DELETE_CHATTY) != 0); if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) { - final PackageParser.Package resolvedPkg; + final AndroidPackage resolvedPkg; if (deletedPkg != null) { resolvedPkg = deletedPkg; } else { // We don't have a parsed package when it lives on an ejected // adopted storage device, so fake something together - resolvedPkg = new PackageParser.Package(deletedPs.name); - resolvedPkg.setVolumeUuid(deletedPs.volumeUuid); + resolvedPkg = PackageImpl.buildFakeForDeletion(deletedPs.name, + deletedPs.volumeUuid); } destroyAppDataLIF(resolvedPkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL); @@ -17849,13 +17589,13 @@ public class PackageManagerService extends IPackageManager.Stub throws SystemDeleteException { final boolean applyUserRestrictions = (allUserHandles != null) && outInfo != null && (outInfo.origUsers != null); - final PackageParser.Package deletedPkg = deletedPs.pkg; + final AndroidPackage deletedPkg = deletedPs.pkg; // Confirm if the system package has been updated // An updated system app can be deleted. This will also have to restore // the system pkg from system partition // reader final PackageSetting disabledPs = action.disabledPs; - if (DEBUG_REMOVE) Slog.d(TAG, "deleteSystemPackageLI: newPs=" + deletedPkg.packageName + if (DEBUG_REMOVE) Slog.d(TAG, "deleteSystemPackageLI: newPs=" + deletedPkg.getPackageName() + " disabledPs=" + disabledPs); Slog.d(TAG, "Deleting system pkg from data partition"); @@ -17872,21 +17612,6 @@ public class PackageManagerService extends IPackageManager.Stub if (outInfo != null) { // Delete the updated package outInfo.isRemovedPackageSystemUpdate = true; - if (outInfo.removedChildPackages != null) { - final int childCount = (deletedPs.childPackageNames != null) - ? deletedPs.childPackageNames.size() : 0; - for (int i = 0; i < childCount; i++) { - String childPackageName = deletedPs.childPackageNames.get(i); - if (disabledPs.childPackageNames != null && disabledPs.childPackageNames - .contains(childPackageName)) { - PackageRemovedInfo childInfo = outInfo.removedChildPackages.get( - childPackageName); - if (childInfo != null) { - childInfo.isRemovedPackageSystemUpdate = true; - } - } - } - } } if (disabledPs.versionCode < deletedPs.versionCode) { @@ -17898,7 +17623,7 @@ public class PackageManagerService extends IPackageManager.Stub } deleteInstalledPackageLIF(deletedPs, true, flags, allUserHandles, - outInfo, writeSettings, disabledPs.pkg); + outInfo, writeSettings); // writer synchronized (mLock) { @@ -17919,16 +17644,16 @@ public class PackageManagerService extends IPackageManager.Stub outInfo == null ? null : outInfo.origUsers, deletedPs.getPermissionsState(), writeSettings); } catch (PackageManagerException e) { - Slog.w(TAG, "Failed to restore system package:" + deletedPkg.packageName + ": " + Slog.w(TAG, "Failed to restore system package:" + deletedPkg.getPackageName() + ": " + e.getMessage()); // TODO(patb): can we avoid this; throw would come from scan... throw new SystemDeleteException(e); } finally { - if (disabledPs.pkg.isStub) { + if (disabledPs.pkg.isStub()) { // We've re-installed the stub; make sure it's disabled here. If package was // originally enabled, we'll install the compressed version of the application // and re-enable it afterward. - final PackageSetting stubPs = mSettings.mPackages.get(deletedPkg.packageName); + final PackageSetting stubPs = mSettings.mPackages.get(deletedPkg.getPackageName()); if (stubPs != null) { stubPs.setEnabled( COMPONENT_ENABLED_STATE_DISABLED, UserHandle.USER_SYSTEM, "android"); @@ -17940,7 +17665,7 @@ public class PackageManagerService extends IPackageManager.Stub /** * Installs a package that's already on the system partition. */ - private PackageParser.Package installPackageFromSystemLIF(@NonNull String codePathString, + private AndroidPackage installPackageFromSystemLIF(@NonNull String codePathString, @Nullable int[] allUserHandles, @Nullable int[] origUserHandles, @Nullable PermissionsState origPermissionState, boolean writeSettings) throws PackageManagerException { @@ -17961,7 +17686,7 @@ public class PackageManagerService extends IPackageManager.Stub } final File codePath = new File(codePathString); - final PackageParser.Package pkg = + final AndroidPackage pkg = scanPackageTracedLI(codePath, parseFlags, scanFlags, 0 /*currentTime*/, null); try { @@ -17975,7 +17700,7 @@ public class PackageManagerService extends IPackageManager.Stub // writer synchronized (mLock) { - PackageSetting ps = mSettings.mPackages.get(pkg.packageName); + PackageSetting ps = mSettings.mPackages.get(pkg.getPackageName()); // Propagate the permissions state as we do not want to drop on the floor // runtime permissions. The update permissions method below will take @@ -17983,7 +17708,7 @@ public class PackageManagerService extends IPackageManager.Stub if (origPermissionState != null) { ps.getPermissionsState().copyFrom(origPermissionState); } - mPermissionManager.updatePermissions(pkg.packageName, pkg); + mPermissionManager.updatePermissions(pkg.getPackageName(), pkg); final boolean applyUserRestrictions = (allUserHandles != null) && (origUserHandles != null); @@ -18021,58 +17746,22 @@ public class PackageManagerService extends IPackageManager.Stub private void deleteInstalledPackageLIF(PackageSetting ps, boolean deleteCodeAndResources, int flags, int[] allUserHandles, - PackageRemovedInfo outInfo, boolean writeSettings, - PackageParser.Package replacingPackage) { + PackageRemovedInfo outInfo, boolean writeSettings) { synchronized (mLock) { if (outInfo != null) { outInfo.uid = ps.appId; } - - if (outInfo != null && outInfo.removedChildPackages != null) { - final int childCount = (ps.childPackageNames != null) - ? ps.childPackageNames.size() : 0; - for (int i = 0; i < childCount; i++) { - String childPackageName = ps.childPackageNames.get(i); - PackageSetting childPs = mSettings.mPackages.get(childPackageName); - PackageRemovedInfo childInfo = outInfo.removedChildPackages.get( - childPackageName); - if (childInfo != null) { - childInfo.uid = childPs.appId; - } - } - } } // Delete package data from internal structures and also remove data if flag is set removePackageDataLIF(ps, allUserHandles, outInfo, flags, writeSettings); - // Delete the child packages data - final int childCount = (ps.childPackageNames != null) ? ps.childPackageNames.size() : 0; - for (int i = 0; i < childCount; i++) { - PackageSetting childPs; - synchronized (mLock) { - childPs = mSettings.getPackageLPr(ps.childPackageNames.get(i)); - } - if (childPs != null) { - PackageRemovedInfo childOutInfo = (outInfo != null - && outInfo.removedChildPackages != null) - ? outInfo.removedChildPackages.get(childPs.name) : null; - final int deleteFlags = (flags & DELETE_KEEP_DATA) != 0 - && (replacingPackage != null - && !replacingPackage.hasChildPackage(childPs.name)) - ? flags & ~DELETE_KEEP_DATA : flags; - removePackageDataLIF(childPs, allUserHandles, childOutInfo, - deleteFlags, writeSettings); - } - } - // Delete application code and resources only for parent packages - if (ps.parentPackageName == null) { - if (deleteCodeAndResources && (outInfo != null)) { - outInfo.args = createInstallArgsForExisting( - ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(ps)); - if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.args); - } + if (deleteCodeAndResources && (outInfo != null)) { + outInfo.args = createInstallArgsForExisting( + ps.codePathString, ps.resourcePathString, getAppDexInstructionSets( + ps.primaryCpuAbiString, ps.secondaryCpuAbiString)); + if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.args); } } @@ -18085,10 +17774,10 @@ public class PackageManagerService extends IPackageManager.Stub // Cannot block uninstall of static shared libs as they are // considered a part of the using app (emulating static linking). // Also static libs are installed always on internal storage. - PackageParser.Package pkg = mPackages.get(packageName); - if (pkg != null && pkg.staticSharedLibName != null) { + AndroidPackage pkg = mPackages.get(packageName); + if (pkg != null && pkg.getStaticSharedLibName() != null) { Slog.w(TAG, "Cannot block uninstall of package: " + packageName - + " providing static shared library: " + pkg.staticSharedLibName); + + " providing static shared library: " + pkg.getStaticSharedLibName()); return false; } mSettings.setBlockUninstallLPw(userId, packageName, blockUninstall); @@ -18152,40 +17841,22 @@ public class PackageManagerService extends IPackageManager.Stub @GuardedBy("mLock") private static DeletePackageAction mayDeletePackageLocked( PackageRemovedInfo outInfo, PackageSetting ps, @Nullable PackageSetting disabledPs, - @Nullable PackageSetting[] children, int flags, UserHandle user) { + int flags, UserHandle user) { if (ps == null) { return null; } if (isSystemApp(ps)) { - if (ps.parentPackageName != null) { - Slog.w(TAG, "Attempt to delete child system package " + ps.pkg.packageName); - return null; - } - final boolean deleteSystem = (flags & PackageManager.DELETE_SYSTEM_APP) != 0; final boolean deleteAllUsers = user == null || user.getIdentifier() == UserHandle.USER_ALL; if ((!deleteSystem || deleteAllUsers) && disabledPs == null) { - Slog.w(TAG, "Attempt to delete unknown system package " + ps.pkg.packageName); + Slog.w(TAG, "Attempt to delete unknown system package " + ps.pkg.getPackageName()); return null; } // Confirmed if the system package has been updated // An updated system app can be deleted. This will also have to restore // the system pkg from system partition reader } - final int parentReferenceCount = - (ps.childPackageNames != null) ? ps.childPackageNames.size() : 0; - final int childCount = children != null ? children.length : 0; - if (childCount != parentReferenceCount) { - return null; - } - if (childCount != 0 && outInfo != null && outInfo.removedChildPackages != null) { - for (PackageSetting child : children) { - if (child == null || !ps.childPackageNames.contains(child.name)) { - return null; - } - } - } return new DeletePackageAction(ps, disabledPs, outInfo, flags, user); } @@ -18195,13 +17866,12 @@ public class PackageManagerService extends IPackageManager.Stub private boolean deletePackageLIF(@NonNull String packageName, UserHandle user, boolean deleteCodeAndResources, int[] allUserHandles, int flags, PackageRemovedInfo outInfo, boolean writeSettings, - PackageParser.Package replacingPackage) { + ParsedPackage replacingPackage) { final DeletePackageAction action; synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(packageName); final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps); - PackageSetting[] children = mSettings.getChildSettingsLPr(ps); - action = mayDeletePackageLocked(outInfo, ps, disabledPs, children, flags, user); + action = mayDeletePackageLocked(outInfo, ps, disabledPs, flags, user); } if (DEBUG_REMOVE) Slog.d(TAG, "deletePackageLI: " + packageName + " user " + user); if (null == action) { @@ -18232,30 +17902,13 @@ public class PackageManagerService extends IPackageManager.Stub private void executeDeletePackageLIF(DeletePackageAction action, String packageName, boolean deleteCodeAndResources, int[] allUserHandles, boolean writeSettings, - PackageParser.Package replacingPackage) throws SystemDeleteException { + 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); - if (ps.parentPackageName != null - && (!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)) { - if (DEBUG_REMOVE) { - Slog.d(TAG, "Uninstalled child package:" + packageName + " for user:" - + ((user == null) ? UserHandle.USER_ALL : user)); - } - final int removedUserId = (user != null) ? user.getIdentifier() - : UserHandle.USER_ALL; - - clearPackageStateForUserLIF(ps, removedUserId, outInfo, flags); - synchronized (mLock) { - markPackageUninstalledForUserLPw(ps, user); - scheduleWritePackageRestrictionsLocked(user); - } - return; - } - final int userId = user == null ? UserHandle.USER_ALL : user.getIdentifier(); if (ps.getPermissionsState().hasPermission(Manifest.permission.SUSPEND_APPS, userId)) { unsuspendForSuspendingPackage(packageName, userId); @@ -18334,53 +17987,12 @@ public class PackageManagerService extends IPackageManager.Stub } else { if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package: " + ps.name); deleteInstalledPackageLIF(ps, deleteCodeAndResources, flags, allUserHandles, - outInfo, writeSettings, replacingPackage); + outInfo, writeSettings); } // Take a note whether we deleted the package for all users if (outInfo != null) { outInfo.removedForAllUsers = mPackages.get(ps.name) == null; - if (outInfo.removedChildPackages != null) { - synchronized (mLock) { - final int childCount = outInfo.removedChildPackages.size(); - for (int i = 0; i < childCount; i++) { - PackageRemovedInfo childInfo = outInfo.removedChildPackages.valueAt(i); - if (childInfo != null) { - childInfo.removedForAllUsers = mPackages.get( - childInfo.removedPackage) == null; - } - } - } - } - // If we uninstalled an update to a system app there may be some - // child packages that appeared as they are declared in the system - // app but were not declared in the update. - if (systemApp) { - synchronized (mLock) { - PackageSetting updatedPs = mSettings.getPackageLPr(ps.name); - final int childCount = (updatedPs.childPackageNames != null) - ? updatedPs.childPackageNames.size() : 0; - for (int i = 0; i < childCount; i++) { - String childPackageName = updatedPs.childPackageNames.get(i); - if (outInfo.removedChildPackages == null - || outInfo.removedChildPackages.indexOfKey(childPackageName) < 0) { - PackageSetting childPs = mSettings.getPackageLPr(childPackageName); - if (childPs == null) { - continue; - } - PackageInstalledInfo installRes = new PackageInstalledInfo(); - installRes.name = childPackageName; - installRes.newUsers = childPs.queryInstalledUsers(allUserHandles, true); - installRes.pkg = mPackages.get(childPackageName); - installRes.uid = childPs.pkg.applicationInfo.uid; - if (outInfo.appearedChildPackages == null) { - outInfo.appearedChildPackages = new ArrayMap<>(); - } - outInfo.appearedChildPackages.put(childPackageName, installRes); - } - } - } - } } } @@ -18414,7 +18026,7 @@ public class PackageManagerService extends IPackageManager.Stub private void clearPackageStateForUserLIF(PackageSetting ps, int userId, PackageRemovedInfo outInfo, int flags) { - final PackageParser.Package pkg; + final AndroidPackage pkg; synchronized (mLock) { pkg = mPackages.get(ps.name); } @@ -18467,7 +18079,7 @@ public class PackageManagerService extends IPackageManager.Stub public void clearApplicationProfileData(String packageName) { enforceSystemOrRoot("Only the system can clear all profile data"); - final PackageParser.Package pkg; + final AndroidPackage pkg; synchronized (mLock) { pkg = mPackages.get(packageName); } @@ -18545,7 +18157,7 @@ public class PackageManagerService extends IPackageManager.Stub } // Try finding details about the requested package - PackageParser.Package pkg; + AndroidPackage pkg; synchronized (mLock) { pkg = mPackages.get(packageName); if (pkg == null) { @@ -18564,7 +18176,7 @@ public class PackageManagerService extends IPackageManager.Stub clearAppDataLIF(pkg, userId, FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL); - final int appId = UserHandle.getAppId(pkg.applicationInfo.uid); + final int appId = UserHandle.getAppId(pkg.getUid()); removeKeystoreDataIfNeeded(mInjector.getUserManagerInternal(), userId, appId); UserManagerInternal umInternal = mInjector.getUserManagerInternal(); @@ -18641,14 +18253,14 @@ public class PackageManagerService extends IPackageManager.Stub final int hasAccessInstantApps = mContext.checkCallingOrSelfPermission( android.Manifest.permission.ACCESS_INSTANT_APPS); - final PackageParser.Package pkg; + final AndroidPackage pkg; synchronized (mLock) { pkg = mPackages.get(packageName); } // Queue up an async operation since the package deletion may take a little while. mHandler.post(() -> { - final PackageSetting ps = pkg == null ? null : (PackageSetting) pkg.mExtras; + final PackageSetting ps = pkg == null ? null : getPackageSetting(pkg.getPackageName()); boolean doClearData = true; if (ps != null) { final boolean targetIsInstantApp = @@ -18728,7 +18340,7 @@ public class PackageManagerService extends IPackageManager.Stub while (it.hasNext()) { final PackageSetting ps = it.next(); if (ps.pkg != null) { - int v = ps.pkg.applicationInfo.targetSdkVersion; + int v = ps.pkg.getTargetSdkVersion(); if (v < vers) vers = v; } } @@ -18736,7 +18348,7 @@ public class PackageManagerService extends IPackageManager.Stub } else if (obj instanceof PackageSetting) { final PackageSetting ps = (PackageSetting) obj; if (ps.pkg != null) { - return ps.pkg.applicationInfo.targetSdkVersion; + return ps.pkg.getTargetSdkVersion(); } } return Build.VERSION_CODES.CUR_DEVELOPMENT; @@ -18744,9 +18356,9 @@ public class PackageManagerService extends IPackageManager.Stub @GuardedBy("mLock") private int getPackageTargetSdkVersionLockedLPr(String packageName) { - final PackageParser.Package p = mPackages.get(packageName); + final AndroidPackage p = mPackages.get(packageName); if (p != null) { - return p.applicationInfo.targetSdkVersion; + return p.getTargetSdkVersion(); } return Build.VERSION_CODES.CUR_DEVELOPMENT; } @@ -18915,7 +18527,7 @@ public class PackageManagerService extends IPackageManager.Stub } // writer synchronized (mLock) { - PackageParser.Package pkg = mPackages.get(packageName); + AndroidPackage pkg = mPackages.get(packageName); if (pkg == null || !isCallerSameApp(packageName, callingUid)) { if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.SET_PREFERRED_APPLICATIONS) @@ -18989,8 +18601,8 @@ public class PackageManagerService extends IPackageManager.Stub private void clearIntentFilterVerificationsLPw(int userId) { final int packageCount = mPackages.size(); for (int i = 0; i < packageCount; i++) { - PackageParser.Package pkg = mPackages.valueAt(i); - clearIntentFilterVerificationsLPw(pkg.packageName, userId); + AndroidPackage pkg = mPackages.valueAt(i); + clearIntentFilterVerificationsLPw(pkg.getPackageName(), userId); } } @@ -19938,8 +19550,8 @@ public class PackageManagerService extends IPackageManager.Stub // If we're enabling a system stub, there's a little more work to do. // Prior to enabling the package, we need to decompress the APK(s) to the // data partition and then replace the version on the system partition. - final PackageParser.Package deletedPkg = pkgSetting.pkg; - final boolean isSystemStub = deletedPkg.isStub + final AndroidPackage deletedPkg = pkgSetting.pkg; + final boolean isSystemStub = deletedPkg.isStub() && deletedPkg.isSystem(); if (isSystemStub && (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT @@ -19960,10 +19572,10 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mLock) { // We're dealing with a component level state change // First, verify that this is a valid class name. - PackageParser.Package pkg = pkgSetting.pkg; + AndroidPackage pkg = pkgSetting.pkg; if (pkg == null || !pkg.hasComponentClassName(className)) { if (pkg != null && - pkg.applicationInfo.targetSdkVersion >= + pkg.getTargetSdkVersion() >= Build.VERSION_CODES.JELLY_BEAN) { throw new IllegalArgumentException("Component class " + className + " does not exist in " + packageName); @@ -21024,7 +20636,7 @@ public class PackageManagerService extends IPackageManager.Stub if (!checkin && dumpState.isDumping(DumpState.DUMP_SERVICE_PERMISSIONS) && packageName == null) { - mComponentResolver.dumpServicePermissions(pw, dumpState, packageName); + mComponentResolver.dumpServicePermissions(pw, dumpState); } if (!checkin && dumpState.isDumping(DumpState.DUMP_DEXOPT)) { @@ -21167,9 +20779,9 @@ public class PackageManagerService extends IPackageManager.Stub ipw.println(); ipw.println("Dexopt state:"); ipw.increaseIndent(); - Collection<PackageParser.Package> packages; + Collection<AndroidPackage> packages; if (packageName != null) { - PackageParser.Package targetPackage = mPackages.get(packageName); + AndroidPackage targetPackage = mPackages.get(packageName); if (targetPackage != null) { packages = Collections.singletonList(targetPackage); } else { @@ -21180,11 +20792,11 @@ public class PackageManagerService extends IPackageManager.Stub packages = mPackages.values(); } - for (PackageParser.Package pkg : packages) { - ipw.println("[" + pkg.packageName + "]"); + for (AndroidPackage pkg : packages) { + ipw.println("[" + pkg.getPackageName() + "]"); ipw.increaseIndent(); mPackageDexOptimizer.dumpDexoptState(ipw, pkg, - mDexManager.getPackageUseInfoOrDefault(pkg.packageName)); + mDexManager.getPackageUseInfoOrDefault(pkg.getPackageName())); ipw.decreaseIndent(); } } @@ -21196,9 +20808,9 @@ public class PackageManagerService extends IPackageManager.Stub ipw.println(); ipw.println("Compiler stats:"); ipw.increaseIndent(); - Collection<PackageParser.Package> packages; + Collection<AndroidPackage> packages; if (packageName != null) { - PackageParser.Package targetPackage = mPackages.get(packageName); + AndroidPackage targetPackage = mPackages.get(packageName); if (targetPackage != null) { packages = Collections.singletonList(targetPackage); } else { @@ -21209,11 +20821,11 @@ public class PackageManagerService extends IPackageManager.Stub packages = mPackages.values(); } - for (PackageParser.Package pkg : packages) { - ipw.println("[" + pkg.packageName + "]"); + for (AndroidPackage pkg : packages) { + ipw.println("[" + pkg.getPackageName() + "]"); ipw.increaseIndent(); - CompilerStats.PackageStats stats = getCompilerPackageStats(pkg.packageName); + CompilerStats.PackageStats stats = getCompilerPackageStats(pkg.getPackageName()); if (stats == null) { ipw.println("(No recorded stats)"); } else { @@ -21284,14 +20896,14 @@ public class PackageManagerService extends IPackageManager.Stub } private void sendResourcesChangedBroadcast(boolean mediaStatus, boolean replacing, - ArrayList<ApplicationInfo> infos, IIntentReceiver finishedReceiver) { - final int size = infos.size(); + ArrayList<AndroidPackage> packages, IIntentReceiver finishedReceiver) { + final int size = packages.size(); final String[] packageNames = new String[size]; final int[] packageUids = new int[size]; for (int i = 0; i < size; i++) { - final ApplicationInfo info = infos.get(i); - packageNames[i] = info.packageName; - packageUids[i] = info.uid; + final AndroidPackage pkg = packages.get(i); + packageNames[i] = pkg.getAppInfoPackageName(); + packageUids[i] = pkg.getUid(); } sendResourcesChangedBroadcast(mediaStatus, replacing, packageNames, packageUids, finishedReceiver); @@ -21334,7 +20946,7 @@ public class PackageManagerService extends IPackageManager.Stub } final ArrayList<PackageFreezer> freezers = new ArrayList<>(); - final ArrayList<ApplicationInfo> loaded = new ArrayList<>(); + final ArrayList<AndroidPackage> loaded = new ArrayList<>(); final int parseFlags = mDefParseFlags | PackageParser.PARSE_EXTERNAL_STORAGE; final VersionInfo ver; @@ -21347,10 +20959,10 @@ public class PackageManagerService extends IPackageManager.Stub for (PackageSetting ps : packages) { freezers.add(freezePackage(ps.name, "loadPrivatePackagesInner")); synchronized (mInstallLock) { - final PackageParser.Package pkg; + final AndroidPackage pkg; try { pkg = scanPackageTracedLI(ps.codePath, parseFlags, SCAN_INITIAL, 0, null); - loaded.add(pkg.applicationInfo); + loaded.add(pkg); } catch (PackageManagerException e) { Slog.w(TAG, "Failed to scan " + ps.codePath + ": " + e.getMessage()); @@ -21422,14 +21034,14 @@ public class PackageManagerService extends IPackageManager.Stub return; } - final ArrayList<ApplicationInfo> unloaded = new ArrayList<>(); + final ArrayList<AndroidPackage> unloaded = new ArrayList<>(); synchronized (mInstallLock) { synchronized (mLock) { final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(volumeUuid); for (PackageSetting ps : packages) { if (ps.pkg == null) continue; - final ApplicationInfo info = ps.pkg.applicationInfo; + final AndroidPackage pkg = ps.pkg; final int deleteFlags = PackageManager.DELETE_KEEP_DATA; final PackageRemovedInfo outInfo = new PackageRemovedInfo(this); @@ -21437,7 +21049,7 @@ public class PackageManagerService extends IPackageManager.Stub "unloadPrivatePackagesInner")) { if (deletePackageLIF(ps.name, null, false, null, deleteFlags, outInfo, false, null)) { - unloaded.add(info); + unloaded.add(pkg); } else { Slog.w(TAG, "Failed to unload " + ps.codePath); } @@ -21652,7 +21264,7 @@ public class PackageManagerService extends IPackageManager.Stub continue; } // Skip non-core apps if requested - if (onlyCoreApps && !ps.pkg.coreApp) { + if (onlyCoreApps && !ps.pkg.isCoreApp()) { result.add(packageName); continue; } @@ -21679,10 +21291,10 @@ public class PackageManagerService extends IPackageManager.Stub * <p> * <em>Note: To avoid a deadlock, do not call this method with {@code mLock} lock held</em> */ - private void prepareAppDataAfterInstallLIF(PackageParser.Package pkg) { + private void prepareAppDataAfterInstallLIF(AndroidPackage pkg) { final PackageSetting ps; synchronized (mLock) { - ps = mSettings.mPackages.get(pkg.packageName); + ps = mSettings.mPackages.get(pkg.getPackageName()); mSettings.writeKernelMappingLPr(ps); } @@ -21712,19 +21324,15 @@ public class PackageManagerService extends IPackageManager.Stub * will try recovering system apps by wiping data; third-party app data is * left intact. */ - private void prepareAppDataLIF(PackageParser.Package pkg, int userId, int flags) { + private void prepareAppDataLIF(AndroidPackage pkg, int userId, int flags) { if (pkg == null) { Slog.wtf(TAG, "Package was null!", new Throwable()); return; } prepareAppDataLeafLIF(pkg, userId, flags); - final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; - for (int i = 0; i < childCount; i++) { - prepareAppDataLeafLIF(pkg.childPackages.get(i), userId, flags); - } } - private void prepareAppDataAndMigrateLIF(PackageParser.Package pkg, int userId, int flags, + private void prepareAppDataAndMigrateLIF(AndroidPackage pkg, int userId, int flags, boolean maybeMigrateAppData) { prepareAppDataLIF(pkg, userId, flags); @@ -21735,43 +21343,37 @@ public class PackageManagerService extends IPackageManager.Stub } } - private void prepareAppDataLeafLIF(PackageParser.Package pkg, int userId, int flags) { + private void prepareAppDataLeafLIF(AndroidPackage pkg, int userId, int flags) { if (DEBUG_APP_DATA) { - Slog.v(TAG, "prepareAppData for " + pkg.packageName + " u" + userId + " 0x" + Slog.v(TAG, "prepareAppData for " + pkg.getPackageName() + " u" + userId + " 0x" + Integer.toHexString(flags)); } final PackageSetting ps; synchronized (mLock) { - ps = mSettings.mPackages.get(pkg.packageName); - } - final String volumeUuid = pkg.volumeUuid; - final String packageName = pkg.packageName; - - ApplicationInfo app = (ps == null) - ? pkg.applicationInfo - : PackageParser.generateApplicationInfo(pkg, 0, ps.readUserState(userId), userId); - if (app == null) { - app = pkg.applicationInfo; + ps = mSettings.mPackages.get(pkg.getPackageName()); } + final String volumeUuid = pkg.getVolumeUuid(); + final String packageName = pkg.getPackageName(); - final int appId = UserHandle.getAppId(app.uid); + final int appId = UserHandle.getAppId(pkg.getUid()); - Preconditions.checkNotNull(app.seInfo); + Preconditions.checkNotNull(pkg.getSeInfo()); - final String seInfo = app.seInfo + (app.seInfoUser != null ? app.seInfoUser : ""); + final String seInfo = + pkg.getSeInfo() + (pkg.getSeInfoUser() != null ? pkg.getSeInfoUser() : ""); long ceDataInode = -1; try { ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags, - appId, seInfo, app.targetSdkVersion); + appId, seInfo, pkg.getTargetSdkVersion()); } catch (InstallerException e) { - if (app.isSystemApp()) { + if (pkg.isSystemApp()) { logCriticalInfo(Log.ERROR, "Failed to create app data for " + packageName + ", but trying to recover: " + e); destroyAppDataLeafLIF(pkg, userId, flags); try { ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags, - appId, seInfo, app.targetSdkVersion); + appId, seInfo, pkg.getTargetSdkVersion()); logCriticalInfo(Log.DEBUG, "Recovery succeeded!"); } catch (InstallerException e2) { logCriticalInfo(Log.DEBUG, "Recovery failed!"); @@ -21813,29 +21415,24 @@ public class PackageManagerService extends IPackageManager.Stub prepareAppDataContentsLeafLIF(pkg, userId, flags); } - private void prepareAppDataContentsLIF(PackageParser.Package pkg, int userId, int flags) { + private void prepareAppDataContentsLIF(AndroidPackage pkg, int userId, int flags) { if (pkg == null) { Slog.wtf(TAG, "Package was null!", new Throwable()); return; } prepareAppDataContentsLeafLIF(pkg, userId, flags); - final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0; - for (int i = 0; i < childCount; i++) { - prepareAppDataContentsLeafLIF(pkg.childPackages.get(i), userId, flags); - } } - private void prepareAppDataContentsLeafLIF(PackageParser.Package pkg, int userId, int flags) { - final String volumeUuid = pkg.volumeUuid; - final String packageName = pkg.packageName; - final ApplicationInfo app = pkg.applicationInfo; + private void prepareAppDataContentsLeafLIF(AndroidPackage pkg, int userId, int flags) { + final String volumeUuid = pkg.getVolumeUuid(); + final String packageName = pkg.getPackageName(); if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) { // Create a native library symlink only if we have native libraries // and if the native libraries are 32 bit libraries. We do not provide // this symlink for 64 bit libraries. - if (app.primaryCpuAbi != null && !VMRuntime.is64BitAbi(app.primaryCpuAbi)) { - final String nativeLibPath = app.nativeLibraryDir; + if (pkg.getPrimaryCpuAbi() != null && !VMRuntime.is64BitAbi(pkg.getPrimaryCpuAbi())) { + final String nativeLibPath = pkg.getNativeLibraryDir(); try { mInstaller.linkNativeLibraryDirectory(volumeUuid, packageName, nativeLibPath, userId); @@ -21851,17 +21448,17 @@ public class PackageManagerService extends IPackageManager.Stub * CE/DE data to match the {@code defaultToDeviceProtectedStorage} flag * requested by the app. */ - private boolean maybeMigrateAppDataLIF(PackageParser.Package pkg, int userId) { + private boolean maybeMigrateAppDataLIF(AndroidPackage pkg, int userId) { if (pkg.isSystem() && !StorageManager.isFileEncryptedNativeOrEmulated() && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) { - final int storageTarget = pkg.applicationInfo.isDefaultToDeviceProtectedStorage() + final int storageTarget = pkg.isDefaultToDeviceProtectedStorage() ? StorageManager.FLAG_STORAGE_DE : StorageManager.FLAG_STORAGE_CE; try { - mInstaller.migrateAppData(pkg.volumeUuid, pkg.packageName, userId, + mInstaller.migrateAppData(pkg.getVolumeUuid(), pkg.getPackageName(), userId, storageTarget); } catch (InstallerException e) { logCriticalInfo(Log.WARN, - "Failed to migrate " + pkg.packageName + ": " + e.getMessage()); + "Failed to migrate " + pkg.getPackageName() + ": " + e.getMessage()); } return true; } else { @@ -21912,7 +21509,6 @@ public class PackageManagerService extends IPackageManager.Stub */ private class PackageFreezer implements AutoCloseable { private final String mPackageName; - private final PackageFreezer[] mChildren; private final boolean mWeFroze; @@ -21927,7 +21523,6 @@ public class PackageManagerService extends IPackageManager.Stub */ public PackageFreezer() { mPackageName = null; - mChildren = null; mWeFroze = false; mCloseGuard.open("close"); } @@ -21941,18 +21536,6 @@ public class PackageManagerService extends IPackageManager.Stub if (ps != null) { killApplication(ps.name, ps.appId, userId, killReason); } - - final PackageParser.Package p = mPackages.get(packageName); - if (p != null && p.childPackages != null) { - final int N = p.childPackages.size(); - mChildren = new PackageFreezer[N]; - for (int i = 0; i < N; i++) { - mChildren[i] = new PackageFreezer(p.childPackages.get(i).packageName, - userId, killReason); - } - } else { - mChildren = null; - } } mCloseGuard.open("close"); } @@ -21975,12 +21558,6 @@ public class PackageManagerService extends IPackageManager.Stub if (mWeFroze) { mFrozenPackages.remove(mPackageName); } - - if (mChildren != null) { - for (PackageFreezer freezer : mChildren) { - freezer.close(); - } - } } } } @@ -22035,14 +21612,14 @@ public class PackageManagerService extends IPackageManager.Stub // reader synchronized (mLock) { - final PackageParser.Package pkg = mPackages.get(packageName); + final AndroidPackage pkg = mPackages.get(packageName); final PackageSetting ps = mSettings.mPackages.get(packageName); if (pkg == null || ps == null || shouldFilterApplicationLocked(ps, callingUid, user.getIdentifier())) { throw new PackageManagerException(MOVE_FAILED_DOESNT_EXIST, "Missing package"); } - if (pkg.applicationInfo.isSystemApp()) { + if (pkg.isSystemApp()) { throw new PackageManagerException(MOVE_FAILED_SYSTEM_PACKAGE, "Cannot move system application"); } @@ -22057,7 +21634,7 @@ public class PackageManagerService extends IPackageManager.Stub currentVolumeUuid = ps.volumeUuid; - final File probe = new File(pkg.codePath); + final File probe = new File(pkg.getCodePath()); final File probeOat = new File(probe, "oat"); if (!probe.isDirectory() || !probeOat.isDirectory()) { throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, @@ -22068,7 +21645,7 @@ public class PackageManagerService extends IPackageManager.Stub throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, "Package already moved to " + volumeUuid); } - if (pkg.applicationInfo.isInternal() && isPackageDeviceAdminOnAnyUser(packageName)) { + if (pkg.isInternal() && isPackageDeviceAdminOnAnyUser(packageName)) { throw new PackageManagerException(MOVE_FAILED_DEVICE_ADMIN, "Device admin cannot be moved"); } @@ -22082,10 +21659,10 @@ public class PackageManagerService extends IPackageManager.Stub codeFile = new File(pkg.codePath); installSource = ps.installSource; packageAbiOverride = ps.cpuAbiOverrideString; - appId = UserHandle.getAppId(pkg.applicationInfo.uid); - seinfo = pkg.applicationInfo.seInfo; - label = String.valueOf(pm.getApplicationLabel(pkg.applicationInfo)); - targetSdkVersion = pkg.applicationInfo.targetSdkVersion; + appId = UserHandle.getAppId(pkg.getUid()); + seinfo = pkg.getSeInfo(); + label = String.valueOf(pm.getApplicationLabel(pkg.toAppInfo())); + targetSdkVersion = pkg.getTargetSdkVersion(); freezer = freezePackage(packageName, "movePackageInternal"); installedUserIds = ps.queryInstalledUsers(mUserManager.getUserIds(), true); } @@ -22246,7 +21823,7 @@ public class PackageManagerService extends IPackageManager.Stub * @param packageName The package that was moved. */ private void logAppMovedStorage(String packageName, boolean isPreviousLocationExternal) { - final PackageParser.Package pkg; + final AndroidPackage pkg; synchronized (mLock) { pkg = mPackages.get(packageName); } @@ -22254,8 +21831,8 @@ public class PackageManagerService extends IPackageManager.Stub return; } - final StorageManager storage = mInjector.getStorageManager(); - VolumeInfo volume = storage.findVolumeByUuid(pkg.applicationInfo.storageUuid.toString()); + final StorageManager storage = mInjector.getStorageManager();; + VolumeInfo volume = storage.findVolumeByUuid(pkg.getStorageUuid().toString()); int packageExternalStorageType = getPackageExternalStorageType(volume, isExternal(pkg)); if (!isPreviousLocationExternal && isExternal(pkg)) { @@ -22499,13 +22076,13 @@ public class PackageManagerService extends IPackageManager.Stub if (packageName == null || alias == null) { return null; } - synchronized (mLock) { - final PackageParser.Package pkg = mPackages.get(packageName); + synchronized(mLock) { + final AndroidPackage pkg = mPackages.get(packageName); if (pkg == null) { Slog.w(TAG, "KeySet requested for unknown package: " + packageName); throw new IllegalArgumentException("Unknown package: " + packageName); } - final PackageSetting ps = (PackageSetting) pkg.mExtras; + final PackageSetting ps = getPackageSetting(pkg.getPackageName()); if (shouldFilterApplicationLocked( ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) { Slog.w(TAG, "KeySet requested for filtered package: " + packageName); @@ -22524,19 +22101,19 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mLock) { final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); - final PackageParser.Package pkg = mPackages.get(packageName); + final AndroidPackage pkg = mPackages.get(packageName); if (pkg == null) { Slog.w(TAG, "KeySet requested for unknown package: " + packageName); throw new IllegalArgumentException("Unknown package: " + packageName); } - final PackageSetting ps = (PackageSetting) pkg.mExtras; + final PackageSetting ps = getPackageSetting(pkg.getPackageName()); if (shouldFilterApplicationLocked(ps, callingUid, callingUserId)) { // filter and pretend the package doesn't exist Slog.w(TAG, "KeySet requested for filtered package: " + packageName + ", uid:" + callingUid); throw new IllegalArgumentException("Unknown package: " + packageName); } - if (pkg.applicationInfo.uid != callingUid + if (pkg.getUid() != callingUid && Process.SYSTEM_UID != callingUid) { throw new SecurityException("May not access signing KeySet of other apps."); } @@ -22554,11 +22131,11 @@ public class PackageManagerService extends IPackageManager.Stub if (packageName == null || ks == null) { return false; } - synchronized (mLock) { - final PackageParser.Package pkg = mPackages.get(packageName); + synchronized(mLock) { + final AndroidPackage pkg = mPackages.get(packageName); if (pkg == null - || shouldFilterApplicationLocked((PackageSetting) pkg.mExtras, callingUid, - UserHandle.getUserId(callingUid))) { + || shouldFilterApplicationLocked(getPackageSetting(pkg.getPackageName()), + callingUid, UserHandle.getUserId(callingUid))) { Slog.w(TAG, "KeySet requested for unknown package: " + packageName); throw new IllegalArgumentException("Unknown package: " + packageName); } @@ -22581,10 +22158,10 @@ public class PackageManagerService extends IPackageManager.Stub return false; } synchronized (mLock) { - final PackageParser.Package pkg = mPackages.get(packageName); + final AndroidPackage pkg = mPackages.get(packageName); if (pkg == null - || shouldFilterApplicationLocked((PackageSetting) pkg.mExtras, callingUid, - UserHandle.getUserId(callingUid))) { + || shouldFilterApplicationLocked(getPackageSetting(pkg.getPackageName()), + callingUid, UserHandle.getUserId(callingUid))) { Slog.w(TAG, "KeySet requested for unknown package: " + packageName); throw new IllegalArgumentException("Unknown package: " + packageName); } @@ -22616,29 +22193,29 @@ public class PackageManagerService extends IPackageManager.Stub * Check and throw if the given before/after packages would be considered a * downgrade. */ - private static void checkDowngrade(PackageParser.Package before, PackageInfoLite after) + private static void checkDowngrade(AndroidPackage before, PackageInfoLite after) throws PackageManagerException { if (after.getLongVersionCode() < before.getLongVersionCode()) { throw new PackageManagerException(INSTALL_FAILED_VERSION_DOWNGRADE, "Update version code " + after.versionCode + " is older than current " + before.getLongVersionCode()); } else if (after.getLongVersionCode() == before.getLongVersionCode()) { - if (after.baseRevisionCode < before.baseRevisionCode) { + if (after.baseRevisionCode < before.getBaseRevisionCode()) { throw new PackageManagerException(INSTALL_FAILED_VERSION_DOWNGRADE, "Update base revision code " + after.baseRevisionCode - + " is older than current " + before.baseRevisionCode); + + " is older than current " + before.getBaseRevisionCode()); } if (!ArrayUtils.isEmpty(after.splitNames)) { for (int i = 0; i < after.splitNames.length; i++) { final String splitName = after.splitNames[i]; - final int j = ArrayUtils.indexOf(before.splitNames, splitName); + final int j = ArrayUtils.indexOf(before.getSplitNames(), splitName); if (j != -1) { - if (after.splitRevisionCodes[i] < before.splitRevisionCodes[j]) { + if (after.splitRevisionCodes[i] < before.getSplitRevisionCodes()[j]) { throw new PackageManagerException(INSTALL_FAILED_VERSION_DOWNGRADE, "Update split " + splitName + " revision code " + after.splitRevisionCodes[i] + " is older than current " - + before.splitRevisionCodes[j]); + + before.getSplitRevisionCodes()[j]); } } } @@ -22828,13 +22405,13 @@ public class PackageManagerService extends IPackageManager.Stub if (packageSetting == null) { return false; } - PackageParser.Package pkg = packageSetting.pkg; + AndroidPackage pkg = packageSetting.pkg; if (pkg == null) { // May happen if package in on a removable sd card return false; } - return pkg.mSigningDetails.hasAncestorOrSelf(mPlatformPackage.mSigningDetails) - || mPlatformPackage.mSigningDetails.checkCapability(pkg.mSigningDetails, + return pkg.getSigningDetails().hasAncestorOrSelf(mPlatformPackage.getSigningDetails()) + || mPlatformPackage.getSigningDetails().checkCapability(pkg.getSigningDetails(), PackageParser.SigningDetails.CertCapabilities.PERMISSION); } @@ -22870,11 +22447,11 @@ public class PackageManagerService extends IPackageManager.Stub private SigningDetails getSigningDetails(@NonNull String packageName) { synchronized (mLock) { - PackageParser.Package p = mPackages.get(packageName); + AndroidPackage p = mPackages.get(packageName); if (p == null) { return null; } - return p.mSigningDetails; + return p.getSigningDetails(); } } @@ -22905,28 +22482,25 @@ public class PackageManagerService extends IPackageManager.Stub } @Override - public boolean filterAppAccess(PackageParser.Package pkg, int callingUid, int userId) { + public boolean filterAppAccess(AndroidPackage pkg, int callingUid, int userId) { synchronized (mLock) { - return PackageManagerService.this.shouldFilterApplicationLocked( - (PackageSetting) pkg.mExtras, callingUid, userId); + PackageSetting ps = getPackageSetting(pkg.getPackageName()); + return PackageManagerService.this.shouldFilterApplicationLocked(ps, callingUid, + userId); } } @Override public boolean filterAppAccess(String packageName, int callingUid, int userId) { synchronized (mLock) { - final PackageParser.Package pkg = mPackages.get(packageName); - if (pkg == null) { - return false; - } - return PackageManagerService.this - .shouldFilterApplicationLocked( - (PackageSetting) pkg.mExtras, callingUid, userId); + PackageSetting ps = getPackageSetting(packageName); + return PackageManagerService.this.shouldFilterApplicationLocked(ps, callingUid, + userId); } } @Override - public PackageParser.Package getPackage(String packageName) { + public AndroidPackage getPackage(String packageName) { synchronized (mLock) { packageName = resolveInternalPackageNameLPr( packageName, PackageManager.VERSION_CODE_HIGHEST); @@ -22935,10 +22509,10 @@ public class PackageManagerService extends IPackageManager.Stub } @Override - public PackageParser.Package getPackage(int uid) { + public AndroidPackage getPackage(int uid) { synchronized (mLock) { final String[] packageNames = getPackagesForUid(uid); - PackageParser.Package pkg = null; + AndroidPackage pkg = null; final int numPackages = packageNames == null ? 0 : packageNames.length; for (int i = 0; pkg == null && i < numPackages; i++) { pkg = mPackages.get(packageNames[i]); @@ -22947,6 +22521,12 @@ public class PackageManagerService extends IPackageManager.Stub } } + @Nullable + @Override + public PackageSetting getPackageSetting(String packageName) { + return PackageManagerService.this.getPackageSetting(packageName); + } + @Override public PackageList getPackageList(PackageListObserver observer) { synchronized (mLock) { @@ -22971,17 +22551,19 @@ public class PackageManagerService extends IPackageManager.Stub } @Override - public PackageParser.Package getDisabledSystemPackage(String packageName) { + public Object getDisabledSystemPackage(@NonNull String packageName) { synchronized (mLock) { - final PackageSetting ps = mSettings.getDisabledSystemPkgLPr(packageName); - return (ps != null) ? ps.pkg : null; + return mSettings.getDisabledSystemPkgLPr(packageName); } } @Override - public @Nullable String getDisabledSystemPackageName(@NonNull String packageName) { - PackageParser.Package pkg = getDisabledSystemPackage(packageName); - return pkg == null ? null : pkg.packageName; + public @Nullable + String getDisabledSystemPackageName(@NonNull String packageName) { + PackageSetting disabledPkgSetting = (PackageSetting) getDisabledSystemPackage( + packageName); + AndroidPackage disabledPkg = disabledPkgSetting == null ? null : disabledPkgSetting.pkg; + return disabledPkg == null ? null : disabledPkg.getPackageName(); } /** @@ -23094,7 +22676,7 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean isPermissionsReviewRequired(String packageName, int userId) { synchronized (mLock) { - final PackageParser.Package pkg = mPackages.get(packageName); + final AndroidPackage pkg = mPackages.get(packageName); if (pkg == null) { return false; } @@ -23280,9 +22862,10 @@ public class PackageManagerService extends IPackageManager.Stub } @Override - public boolean isEnabledAndMatches(ComponentInfo info, int flags, int userId) { + public boolean isEnabledAndMatches(ParsedComponent component, int flags, int userId) { synchronized (mLock) { - return mSettings.isEnabledAndMatchLPr(info, flags, userId); + AndroidPackage pkg = getPackage(component.getPackageName()); + return mSettings.isEnabledAndMatchLPr(pkg, component, flags, userId); } } @@ -23299,10 +22882,10 @@ public class PackageManagerService extends IPackageManager.Stub } @Override - public boolean setInstalled(PackageParser.Package pkg, @UserIdInt int userId, + public boolean setInstalled(AndroidPackage pkg, @UserIdInt int userId, boolean installed) { synchronized (mLock) { - final PackageSetting ps = mSettings.mPackages.get(pkg.packageName); + final PackageSetting ps = mSettings.mPackages.get(pkg.getPackageName()); if (ps.getInstalled(userId) != installed) { ps.setInstalled(installed, userId); return true; @@ -23332,8 +22915,8 @@ public class PackageManagerService extends IPackageManager.Stub return; } - final boolean instantApp = isInstantAppInternal(callingPackage.packageName, userId, - callingUid); + final boolean instantApp = isInstantAppInternal(callingPackage.getPackageName(), + userId, callingUid); if (instantApp) { mInstantAppRegistry.grantInstantAccessLPw(userId, intent, UserHandle.getAppId(callingUid), targetAppId); @@ -23370,9 +22953,9 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean isPackagePersistent(String packageName) { synchronized (mLock) { - PackageParser.Package pkg = mPackages.get(packageName); + AndroidPackage pkg = mPackages.get(packageName); return pkg != null - ? ((pkg.applicationInfo.flags&(ApplicationInfo.FLAG_SYSTEM + ? ((pkg.getFlags() & (ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_PERSISTENT)) == (ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_PERSISTENT)) : false; @@ -23380,9 +22963,9 @@ public class PackageManagerService extends IPackageManager.Stub } @Override - public boolean isLegacySystemApp(PackageParser.Package pkg) { + public boolean isLegacySystemApp(AndroidPackage pkg) { synchronized (mLock) { - final PackageSetting ps = (PackageSetting) pkg.mExtras; + final PackageSetting ps = getPackageSetting(pkg.getPackageName()); return mPromoteSystemApps && ps.isSystem() && mExistingSystemPackages.contains(ps.name); @@ -23393,9 +22976,10 @@ public class PackageManagerService extends IPackageManager.Stub public List<PackageInfo> getOverlayPackages(int userId) { final ArrayList<PackageInfo> overlayPackages = new ArrayList<PackageInfo>(); synchronized (mLock) { - for (PackageParser.Package p : mPackages.values()) { - if (p.mOverlayTarget != null) { - PackageInfo pkg = generatePackageInfo((PackageSetting)p.mExtras, 0, userId); + for (AndroidPackage p : mPackages.values()) { + if (p.getOverlayTarget() != null) { + PackageInfo pkg = generatePackageInfo(getPackageSetting(p.getPackageName()), + 0, userId); if (pkg != null) { overlayPackages.add(pkg); } @@ -23409,9 +22993,9 @@ public class PackageManagerService extends IPackageManager.Stub public List<String> getTargetPackageNames(int userId) { List<String> targetPackages = new ArrayList<>(); synchronized (mLock) { - for (PackageParser.Package p : mPackages.values()) { - if (p.mOverlayTarget == null) { - targetPackages.add(p.packageName); + for (AndroidPackage p : mPackages.values()) { + if (p.getOverlayTarget() == null) { + targetPackages.add(p.getPackageName()); } } } @@ -23432,12 +23016,12 @@ public class PackageManagerService extends IPackageManager.Stub overlayPaths = new ArrayList<>(N); for (int i = 0; i < N; i++) { final String packageName = overlayPackageNames.get(i); - final PackageParser.Package pkg = mPackages.get(packageName); + final AndroidPackage pkg = mPackages.get(packageName); if (pkg == null) { Slog.e(TAG, "failed to find package " + packageName); return false; } - overlayPaths.add(pkg.baseCodePath); + overlayPaths.add(pkg.getBaseCodePath()); } } @@ -23555,12 +23139,12 @@ public class PackageManagerService extends IPackageManager.Stub } @Override - public void forEachPackage(Consumer<PackageParser.Package> actionLocked) { + public void forEachPackage(Consumer<AndroidPackage> actionLocked) { PackageManagerService.this.forEachPackage(actionLocked); } @Override - public void forEachInstalledPackage(@NonNull Consumer<PackageParser.Package> actionLocked, + public void forEachInstalledPackage(@NonNull Consumer<AndroidPackage> actionLocked, @UserIdInt int userId) { PackageManagerService.this.forEachInstalledPackage(actionLocked, userId); } @@ -23609,7 +23193,7 @@ public class PackageManagerService extends IPackageManager.Stub */ @Override public boolean compileLayouts(String packageName) { - PackageParser.Package pkg; + AndroidPackage pkg; synchronized (mLock) { pkg = mPackages.get(packageName); if (pkg == null) { @@ -23716,12 +23300,12 @@ public class PackageManagerService extends IPackageManager.Stub @Override public boolean isCallerInstallerOfRecord( - @NonNull PackageParser.Package pkg, int callingUid) { + @NonNull AndroidPackage pkg, int callingUid) { synchronized (mLock) { if (pkg == null) { return false; } - final PackageSetting packageSetting = (PackageSetting) pkg.mExtras; + final PackageSetting packageSetting = getPackageSetting(pkg.getPackageName()); if (packageSetting == null) { return false; } @@ -23818,7 +23402,16 @@ public class PackageManagerService extends IPackageManager.Stub } } - void forEachPackage(Consumer<PackageParser.Package> actionLocked) { + @Nullable + public PackageSetting getPackageSetting(String packageName) { + synchronized (mPackages) { + packageName = resolveInternalPackageNameLPr( + packageName, PackageManager.VERSION_CODE_HIGHEST); + return mSettings.mPackages.get(packageName); + } + } + + void forEachPackage(Consumer<AndroidPackage> actionLocked) { synchronized (mLock) { int numPackages = mPackages.size(); for (int i = 0; i < numPackages; i++) { @@ -23827,13 +23420,13 @@ public class PackageManagerService extends IPackageManager.Stub } } - void forEachInstalledPackage(@NonNull Consumer<PackageParser.Package> actionLocked, + void forEachInstalledPackage(@NonNull Consumer<AndroidPackage> actionLocked, @UserIdInt int userId) { synchronized (mLock) { int numPackages = mPackages.size(); for (int i = 0; i < numPackages; i++) { - PackageParser.Package pkg = mPackages.valueAt(i); - PackageSetting setting = mSettings.getPackageLPr(pkg.packageName); + AndroidPackage pkg = mPackages.valueAt(i); + PackageSetting setting = mSettings.getPackageLPr(pkg.getPackageName()); if (setting == null || !setting.getInstalled(userId)) { continue; } @@ -23850,7 +23443,7 @@ public class PackageManagerService extends IPackageManager.Stub * Return a <b>copy</b> of the collection of packages known to the package manager. * @return A copy of the values of mPackages. */ - Collection<PackageParser.Package> getPackages() { + Collection<AndroidPackage> getPackages() { synchronized (mLock) { return new ArrayList<>(mPackages.values()); } @@ -23886,8 +23479,8 @@ public class PackageManagerService extends IPackageManager.Stub return mCompilerStats.getPackageStats(pkgName); } - public CompilerStats.PackageStats getOrCreateCompilerPackageStats(PackageParser.Package pkg) { - return getOrCreateCompilerPackageStats(pkg.packageName); + public CompilerStats.PackageStats getOrCreateCompilerPackageStats(AndroidPackage pkg) { + return getOrCreateCompilerPackageStats(pkg.getPackageName()); } public CompilerStats.PackageStats getOrCreateCompilerPackageStats(String pkgName) { @@ -23997,7 +23590,7 @@ public class PackageManagerService extends IPackageManager.Stub boolean canHaveOatDir(String packageName) { synchronized (mLock) { - PackageParser.Package p = mPackages.get(packageName); + AndroidPackage p = mPackages.get(packageName); if (p == null) { return false; } @@ -24005,11 +23598,11 @@ public class PackageManagerService extends IPackageManager.Stub } } - private String getOatDir(PackageParser.Package pkg) { + private String getOatDir(AndroidPackage pkg) { if (!pkg.canHaveOatDir()) { return null; } - File codePath = new File(pkg.codePath); + File codePath = new File(pkg.getCodePath()); if (codePath.isDirectory()) { return PackageDexOptimizer.getOatDir(codePath).getAbsolutePath(); } @@ -24020,11 +23613,12 @@ public class PackageManagerService extends IPackageManager.Stub final String[] instructionSets; final List<String> codePaths; final String oatDir; - final PackageParser.Package pkg; + final AndroidPackage pkg; synchronized (mLock) { pkg = mPackages.get(packageName); } - instructionSets = getAppDexInstructionSets(pkg.applicationInfo); + instructionSets = getAppDexInstructionSets(pkg.getPrimaryCpuAbi(), + pkg.getSecondaryCpuAbi()); codePaths = pkg.getAllCodePaths(); oatDir = getOatDir(pkg); @@ -24043,19 +23637,19 @@ public class PackageManagerService extends IPackageManager.Stub Set<String> unusedPackages = new HashSet<>(); long currentTimeInMillis = System.currentTimeMillis(); synchronized (mLock) { - for (PackageParser.Package pkg : mPackages.values()) { - PackageSetting ps = mSettings.mPackages.get(pkg.packageName); + for (AndroidPackage pkg : mPackages.values()) { + PackageSetting ps = mSettings.mPackages.get(pkg.getPackageName()); if (ps == null) { continue; } PackageDexUsage.PackageUseInfo packageUseInfo = - getDexManager().getPackageUseInfoOrDefault(pkg.packageName); + getDexManager().getPackageUseInfoOrDefault(pkg.getPackageName()); if (PackageManagerServiceUtils .isUnusedSinceTimeInMillis(ps.firstInstallTime, currentTimeInMillis, downgradeTimeThresholdMillis, packageUseInfo, pkg.getLatestPackageUseTimeInMills(), pkg.getLatestForegroundPackageUseTimeInMills())) { - unusedPackages.add(pkg.packageName); + unusedPackages.add(pkg.getPackageName()); } } } diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index ef47410ded8c..ded9a9c58c5e 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -35,10 +35,13 @@ import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfoLite; import android.content.pm.PackageManager; +import android.content.pm.PackageManagerInternal; import android.content.pm.PackageParser; import android.content.pm.PackageParser.PackageParserException; import android.content.pm.ResolveInfo; import android.content.pm.Signature; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.ApkParseUtils; import android.os.Build; import android.os.Debug; import android.os.Environment; @@ -120,7 +123,7 @@ public class PackageManagerServiceUtils { // Sort a list of apps by their last usage, most recently used apps first. The order of // packages without usage data is undefined (but they will be sorted after the packages // that do have usage data). - public static void sortPackagesByUsageDate(List<PackageParser.Package> pkgs, + public static void sortPackagesByUsageDate(List<AndroidPackage> pkgs, PackageManagerService packageManagerService) { if (!packageManagerService.isHistoricalPackageUsageAvailable()) { return; @@ -135,12 +138,12 @@ public class PackageManagerServiceUtils { // package will be removed from {@code packages} and added to {@code result} with its // dependencies. If usage data is available, the positive packages will be sorted by usage // data (with {@code sortTemp} as temporary storage). - private static void applyPackageFilter(Predicate<PackageParser.Package> filter, - Collection<PackageParser.Package> result, - Collection<PackageParser.Package> packages, - @NonNull List<PackageParser.Package> sortTemp, + private static void applyPackageFilter(Predicate<AndroidPackage> filter, + Collection<AndroidPackage> result, + Collection<AndroidPackage> packages, + @NonNull List<AndroidPackage> sortTemp, PackageManagerService packageManagerService) { - for (PackageParser.Package pkg : packages) { + for (AndroidPackage pkg : packages) { if (filter.test(pkg)) { sortTemp.add(pkg); } @@ -149,10 +152,10 @@ public class PackageManagerServiceUtils { sortPackagesByUsageDate(sortTemp, packageManagerService); packages.removeAll(sortTemp); - for (PackageParser.Package pkg : sortTemp) { + for (AndroidPackage pkg : sortTemp) { result.add(pkg); - Collection<PackageParser.Package> deps = + Collection<AndroidPackage> deps = packageManagerService.findSharedNonSystemLibraries(pkg); if (!deps.isEmpty()) { deps.removeAll(result); @@ -166,50 +169,51 @@ public class PackageManagerServiceUtils { // Sort apps by importance for dexopt ordering. Important apps are given // more priority in case the device runs out of space. - public static List<PackageParser.Package> getPackagesForDexopt( - Collection<PackageParser.Package> packages, + public static List<AndroidPackage> getPackagesForDexopt( + Collection<AndroidPackage> packages, PackageManagerService packageManagerService) { return getPackagesForDexopt(packages, packageManagerService, DEBUG_DEXOPT); } - public static List<PackageParser.Package> getPackagesForDexopt( - Collection<PackageParser.Package> packages, + public static List<AndroidPackage> getPackagesForDexopt( + Collection<AndroidPackage> packages, PackageManagerService packageManagerService, boolean debug) { - ArrayList<PackageParser.Package> remainingPkgs = new ArrayList<>(packages); - LinkedList<PackageParser.Package> result = new LinkedList<>(); - ArrayList<PackageParser.Package> sortTemp = new ArrayList<>(remainingPkgs.size()); + ArrayList<AndroidPackage> remainingPkgs = new ArrayList<>(packages); + LinkedList<AndroidPackage> result = new LinkedList<>(); + ArrayList<AndroidPackage> sortTemp = new ArrayList<>(remainingPkgs.size()); // Give priority to core apps. - applyPackageFilter((pkg) -> pkg.coreApp, result, remainingPkgs, sortTemp, + applyPackageFilter((pkg) -> pkg.isCoreApp(), result, remainingPkgs, sortTemp, packageManagerService); // Give priority to system apps that listen for pre boot complete. Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED); final ArraySet<String> pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM); - applyPackageFilter((pkg) -> pkgNames.contains(pkg.packageName), result, remainingPkgs, + applyPackageFilter((pkg) -> pkgNames.contains(pkg.getPackageName()), result, remainingPkgs, sortTemp, packageManagerService); // Give priority to apps used by other apps. DexManager dexManager = packageManagerService.getDexManager(); applyPackageFilter((pkg) -> - dexManager.getPackageUseInfoOrDefault(pkg.packageName) + dexManager.getPackageUseInfoOrDefault(pkg.getPackageName()) .isAnyCodePathUsedByOtherApps(), result, remainingPkgs, sortTemp, packageManagerService); // Filter out packages that aren't recently used, add all remaining apps. // TODO: add a property to control this? - Predicate<PackageParser.Package> remainingPredicate; + Predicate<AndroidPackage> remainingPredicate; if (!remainingPkgs.isEmpty() && packageManagerService.isHistoricalPackageUsageAvailable()) { if (debug) { Log.i(TAG, "Looking at historical package use"); } // Get the package that was used last. - PackageParser.Package lastUsed = Collections.max(remainingPkgs, (pkg1, pkg2) -> + AndroidPackage lastUsed = Collections.max(remainingPkgs, (pkg1, pkg2) -> Long.compare(pkg1.getLatestForegroundPackageUseTimeInMills(), pkg2.getLatestForegroundPackageUseTimeInMills())); if (debug) { - Log.i(TAG, "Taking package " + lastUsed.packageName + " as reference in time use"); + Log.i(TAG, "Taking package " + lastUsed.getPackageName() + + " as reference in time use"); } long estimatedPreviousSystemUseTime = lastUsed.getLatestForegroundPackageUseTimeInMills(); @@ -285,13 +289,13 @@ public class PackageManagerServiceUtils { } } - public static String packagesToString(Collection<PackageParser.Package> c) { + public static String packagesToString(Collection<AndroidPackage> c) { StringBuilder sb = new StringBuilder(); - for (PackageParser.Package pkg : c) { + for (AndroidPackage pkg : c) { if (sb.length() > 0) { sb.append(", "); } - sb.append(pkg.packageName); + sb.append(pkg.getPackageName()); } return sb.toString(); } @@ -309,16 +313,16 @@ public class PackageManagerServiceUtils { return false; } - public static long getLastModifiedTime(PackageParser.Package pkg) { - final File srcFile = new File(pkg.codePath); + public static long getLastModifiedTime(AndroidPackage pkg) { + final File srcFile = new File(pkg.getCodePath()); if (!srcFile.isDirectory()) { return srcFile.lastModified(); } - final File baseFile = new File(pkg.baseCodePath); + final File baseFile = new File(pkg.getBaseCodePath()); long maxModifiedTime = baseFile.lastModified(); - if (pkg.splitCodePaths != null) { - for (int i = pkg.splitCodePaths.length - 1; i >=0; --i) { - final File splitFile = new File(pkg.splitCodePaths[i]); + if (pkg.getSplitCodePaths() != null) { + for (int i = pkg.getSplitCodePaths().length - 1; i >=0; --i) { + final File splitFile = new File(pkg.getSplitCodePaths()[i]); maxModifiedTime = Math.max(maxModifiedTime, splitFile.lastModified()); } } @@ -539,7 +543,7 @@ public class PackageManagerServiceUtils { private static boolean matchSignatureInSystem(PackageSetting pkgSetting, PackageSetting disabledPkgSetting) { try { - PackageParser.collectCertificates(disabledPkgSetting.pkg, true /* skipVerify */); + ApkParseUtils.collectCertificates(disabledPkgSetting.pkg, true /* skipVerify */); if (pkgSetting.signatures.mSigningDetails.checkCapability( disabledPkgSetting.signatures.mSigningDetails, PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA) @@ -905,8 +909,10 @@ public class PackageManagerServiceUtils { * Returns the {@link PermissionsState} for the given package. If the {@link PermissionsState} * could not be found, {@code null} will be returned. */ - public static PermissionsState getPermissionsState(PackageParser.Package pkg) { - final PackageSetting packageSetting = (PackageSetting) pkg.mExtras; + public static PermissionsState getPermissionsState( + PackageManagerInternal packageManagerInternal, AndroidPackage pkg) { + final PackageSetting packageSetting = + (PackageSetting) packageManagerInternal.getPackageSetting(pkg.getPackageName()); if (packageSetting == null) { return null; } diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index b96109683115..fff404f3ede6 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -48,7 +48,6 @@ import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; -import android.content.pm.PackageParser; import android.content.pm.PackageParser.ApkLite; import android.content.pm.PackageParser.PackageLite; import android.content.pm.PackageParser.PackageParserException; @@ -62,6 +61,7 @@ import android.content.pm.VersionedPackage; import android.content.pm.dex.ArtManager; import android.content.pm.dex.DexMetadataHelper; import android.content.pm.dex.ISnapshotRuntimeProfileCallback; +import android.content.pm.parsing.ApkLiteParseUtils; import android.content.res.AssetManager; import android.content.res.Resources; import android.content.rollback.IRollbackManager; @@ -453,7 +453,7 @@ class PackageManagerShellCommand extends ShellCommand { throw new IllegalArgumentException("Error: Can't open file: " + inPath); } try { - ApkLite baseApk = PackageParser.parseApkLite(fd.getFileDescriptor(), inPath, 0); + ApkLite baseApk = ApkLiteParseUtils.parseApkLite(fd.getFileDescriptor(), inPath, 0); PackageLite pkgLite = new PackageLite(null, baseApk, null, null, null, null, null, null); sessionSize += PackageHelper.calculateInstalledSize(pkgLite, diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index d38dd9344821..bbc0dc986b0c 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -18,8 +18,9 @@ package com.android.server.pm; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; -import android.content.pm.PackageParser; import android.content.pm.UserInfo; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.ParsedPackage; import android.service.pm.PackageProto; import android.util.proto.ProtoOutputStream; @@ -31,9 +32,11 @@ import java.util.List; /** * Settings data for a particular package we know about. */ -public final class PackageSetting extends PackageSettingBase { +public final class PackageSetting extends PackageSettingBase implements + ParsedPackage.PackageSettingCallback { int appId; - PackageParser.Package pkg; + + public AndroidPackage pkg; /** * WARNING. The object reference is important. We perform integer equality and NOT * object equality to check whether shared user settings are the same. @@ -50,12 +53,12 @@ public final class PackageSetting extends PackageSettingBase { PackageSetting(String name, String realName, File codePath, File resourcePath, String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString, String cpuAbiOverrideString, - long pVersionCode, int pkgFlags, int privateFlags, String parentPackageName, - List<String> childPackageNames, int sharedUserId, String[] usesStaticLibraries, + long pVersionCode, int pkgFlags, int privateFlags, + int sharedUserId, String[] usesStaticLibraries, long[] usesStaticLibrariesVersions) { super(name, realName, codePath, resourcePath, legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString, - pVersionCode, pkgFlags, privateFlags, parentPackageName, childPackageNames, + pVersionCode, pkgFlags, privateFlags, usesStaticLibraries, usesStaticLibrariesVersions); this.sharedUserId = sharedUserId; } @@ -116,10 +119,6 @@ public final class PackageSetting extends PackageSettingBase { : super.getPermissionsState(); } - public PackageParser.Package getPackage() { - return pkg; - } - public int getAppId() { return appId; } @@ -132,6 +131,7 @@ public final class PackageSetting extends PackageSettingBase { return installPermissionsFixed; } + // TODO(b/135203078): Remove these in favor of reading from the package directly public boolean isPrivileged() { return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; } @@ -176,10 +176,6 @@ public final class PackageSetting extends PackageSettingBase { return true; } - public boolean hasChildPackages() { - return childPackageNames != null && !childPackageNames.isEmpty(); - } - public void dumpDebug(ProtoOutputStream proto, long fieldId, List<UserInfo> users) { final long packageToken = proto.start(fieldId); proto.write(PackageProto.NAME, (realName != null ? realName : name)); @@ -190,18 +186,19 @@ public final class PackageSetting extends PackageSettingBase { proto.write(PackageProto.INSTALLER_NAME, installSource.installerPackageName); if (pkg != null) { - proto.write(PackageProto.VERSION_STRING, pkg.mVersionName); + proto.write(PackageProto.VERSION_STRING, pkg.getVersionName()); long splitToken = proto.start(PackageProto.SPLITS); proto.write(PackageProto.SplitProto.NAME, "base"); - proto.write(PackageProto.SplitProto.REVISION_CODE, pkg.baseRevisionCode); + proto.write(PackageProto.SplitProto.REVISION_CODE, pkg.getBaseRevisionCode()); proto.end(splitToken); - if (pkg.splitNames != null) { - for (int i = 0; i < pkg.splitNames.length; i++) { + if (pkg.getSplitNames() != null) { + for (int i = 0; i < pkg.getSplitNames().length; i++) { splitToken = proto.start(PackageProto.SPLITS); - proto.write(PackageProto.SplitProto.NAME, pkg.splitNames[i]); - proto.write(PackageProto.SplitProto.REVISION_CODE, pkg.splitRevisionCodes[i]); + proto.write(PackageProto.SplitProto.NAME, pkg.getSplitNames()[i]); + proto.write(PackageProto.SplitProto.REVISION_CODE, + pkg.getSplitRevisionCodes()[i]); proto.end(splitToken); } } @@ -225,4 +222,10 @@ public final class PackageSetting extends PackageSettingBase { sharedUserId = other.sharedUserId; sharedUser = other.sharedUser; } + + // TODO(b/135203078): Move to constructor + @Override + public void setAndroidPackage(AndroidPackage pkg) { + this.pkg = pkg; + } } diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java index 45ab3575c805..671450d71b4d 100644 --- a/services/core/java/com/android/server/pm/PackageSettingBase.java +++ b/services/core/java/com/android/server/pm/PackageSettingBase.java @@ -39,7 +39,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import java.io.File; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Set; @@ -54,9 +53,6 @@ public abstract class PackageSettingBase extends SettingBase { public final String name; final String realName; - String parentPackageName; - List<String> childPackageNames; - /** * Path where this package was found on disk. For monolithic packages * this is path to single base APK file; for cluster packages this is @@ -138,14 +134,10 @@ public abstract class PackageSettingBase extends SettingBase { String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString, String cpuAbiOverrideString, long pVersionCode, int pkgFlags, int pkgPrivateFlags, - String parentPackageName, List<String> childPackageNames, String[] usesStaticLibraries, long[] usesStaticLibrariesVersions) { super(pkgFlags, pkgPrivateFlags); this.name = name; this.realName = realName; - this.parentPackageName = parentPackageName; - this.childPackageNames = (childPackageNames != null) - ? new ArrayList<>(childPackageNames) : null; this.usesStaticLibraries = usesStaticLibraries; this.usesStaticLibrariesVersions = usesStaticLibrariesVersions; this.codePath = codePath; @@ -235,8 +227,6 @@ public abstract class PackageSettingBase extends SettingBase { } private void doCopy(PackageSettingBase orig) { - childPackageNames = (orig.childPackageNames != null) - ? new ArrayList<>(orig.childPackageNames) : null; codePath = orig.codePath; codePathString = orig.codePathString; cpuAbiOverrideString = orig.cpuAbiOverrideString; @@ -247,7 +237,6 @@ public abstract class PackageSettingBase extends SettingBase { lastUpdateTime = orig.lastUpdateTime; legacyNativeLibraryPathString = orig.legacyNativeLibraryPathString; // Intentionally skip mOldCodePaths; it's not relevant for copies - parentPackageName = orig.parentPackageName; primaryCpuAbiString = orig.primaryCpuAbiString; resourcePath = orig.resourcePath; resourcePathString = orig.resourcePathString; @@ -670,8 +659,6 @@ public abstract class PackageSettingBase extends SettingBase { protected PackageSettingBase updateFrom(PackageSettingBase other) { super.copyFrom(other); - this.parentPackageName = other.parentPackageName; - this.childPackageNames = other.childPackageNames; this.codePath = other.codePath; this.codePathString = other.codePathString; this.resourcePath = other.resourcePath; diff --git a/services/core/java/com/android/server/pm/PackageUsage.java b/services/core/java/com/android/server/pm/PackageUsage.java index ac1f739cd9f8..ce2c9e767d5e 100644 --- a/services/core/java/com/android/server/pm/PackageUsage.java +++ b/services/core/java/com/android/server/pm/PackageUsage.java @@ -20,7 +20,7 @@ import static android.os.Process.PACKAGE_INFO_GID; import static android.os.Process.SYSTEM_UID; import android.content.pm.PackageManager; -import android.content.pm.PackageParser; +import android.content.pm.parsing.AndroidPackage; import android.os.FileUtils; import android.util.AtomicFile; import android.util.Log; @@ -36,7 +36,7 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.Map; -class PackageUsage extends AbstractStatsBase<Map<String, PackageParser.Package>> { +class PackageUsage extends AbstractStatsBase<Map<String, AndroidPackage>> { private static final String USAGE_FILE_MAGIC = "PACKAGE_USAGE__VERSION_"; private static final String USAGE_FILE_MAGIC_VERSION_1 = USAGE_FILE_MAGIC + "1"; @@ -52,7 +52,7 @@ class PackageUsage extends AbstractStatsBase<Map<String, PackageParser.Package>> } @Override - protected void writeInternal(Map<String, PackageParser.Package> packages) { + protected void writeInternal(Map<String, AndroidPackage> packages) { AtomicFile file = getFile(); FileOutputStream f = null; try { @@ -66,13 +66,13 @@ class PackageUsage extends AbstractStatsBase<Map<String, PackageParser.Package>> sb.append('\n'); out.write(sb.toString().getBytes(StandardCharsets.US_ASCII)); - for (PackageParser.Package pkg : packages.values()) { + for (AndroidPackage pkg : packages.values()) { if (pkg.getLatestPackageUseTimeInMills() == 0L) { continue; } sb.setLength(0); - sb.append(pkg.packageName); - for (long usageTimeInMillis : pkg.mLastPackageUsageTimeInMills) { + sb.append(pkg.getPackageName()); + for (long usageTimeInMillis : pkg.getLastPackageUsageTimeInMills()) { sb.append(' '); sb.append(usageTimeInMillis); } @@ -90,7 +90,7 @@ class PackageUsage extends AbstractStatsBase<Map<String, PackageParser.Package>> } @Override - protected void readInternal(Map<String, PackageParser.Package> packages) { + protected void readInternal(Map<String, AndroidPackage> packages) { AtomicFile file = getFile(); BufferedInputStream in = null; try { @@ -114,7 +114,7 @@ class PackageUsage extends AbstractStatsBase<Map<String, PackageParser.Package>> } } - private void readVersion0LP(Map<String, PackageParser.Package> packages, InputStream in, + private void readVersion0LP(Map<String, AndroidPackage> packages, InputStream in, StringBuffer sb, String firstLine) throws IOException { // Initial version of the file had no version number and stored one @@ -128,7 +128,7 @@ class PackageUsage extends AbstractStatsBase<Map<String, PackageParser.Package>> } String packageName = tokens[0]; - PackageParser.Package pkg = packages.get(packageName); + AndroidPackage pkg = packages.get(packageName); if (pkg == null) { continue; } @@ -137,12 +137,12 @@ class PackageUsage extends AbstractStatsBase<Map<String, PackageParser.Package>> for (int reason = 0; reason < PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT; reason++) { - pkg.mLastPackageUsageTimeInMills[reason] = timestamp; + pkg.mutate().setLastPackageUsageTimeInMills(reason, timestamp); } } } - private void readVersion1LP(Map<String, PackageParser.Package> packages, InputStream in, + private void readVersion1LP(Map<String, AndroidPackage> packages, InputStream in, StringBuffer sb) throws IOException { // Version 1 of the file started with the corresponding version // number and then stored a package name and eight timestamps per line. @@ -154,7 +154,7 @@ class PackageUsage extends AbstractStatsBase<Map<String, PackageParser.Package>> } String packageName = tokens[0]; - PackageParser.Package pkg = packages.get(packageName); + AndroidPackage pkg = packages.get(packageName); if (pkg == null) { continue; } @@ -162,7 +162,8 @@ class PackageUsage extends AbstractStatsBase<Map<String, PackageParser.Package>> for (int reason = 0; reason < PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT; reason++) { - pkg.mLastPackageUsageTimeInMills[reason] = parseAsLong(tokens[reason + 1]); + pkg.mutate().setLastPackageUsageTimeInMills(reason, + parseAsLong(tokens[reason + 1])); } } } @@ -196,4 +197,4 @@ class PackageUsage extends AbstractStatsBase<Map<String, PackageParser.Package>> sb.append((char)ch); } } -}
\ No newline at end of file +} diff --git a/services/core/java/com/android/server/pm/ParallelPackageParser.java b/services/core/java/com/android/server/pm/ParallelPackageParser.java index 4ff3e1218b53..a5065145cafd 100644 --- a/services/core/java/com/android/server/pm/ParallelPackageParser.java +++ b/services/core/java/com/android/server/pm/ParallelPackageParser.java @@ -16,7 +16,10 @@ package com.android.server.pm; +import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; + import android.content.pm.PackageParser; +import android.content.pm.parsing.ParsedPackage; import android.os.Process; import android.os.Trace; import android.util.DisplayMetrics; @@ -30,8 +33,6 @@ import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; -import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; - /** * Helper class for parallel parsing of packages using {@link PackageParser}. * <p>Parsing requests are processed by a thread-pool of {@link #MAX_THREADS}. @@ -65,14 +66,14 @@ class ParallelPackageParser implements AutoCloseable { static class ParseResult { - PackageParser.Package pkg; // Parsed package + ParsedPackage parsedPackage; // Parsed package File scanFile; // File that was parsed Throwable throwable; // Set if an error occurs during parsing @Override public String toString() { return "ParseResult{" + - "pkg=" + pkg + + "parsedPackage=" + parsedPackage + ", scanFile=" + scanFile + ", throwable=" + throwable + '}'; @@ -100,7 +101,7 @@ class ParallelPackageParser implements AutoCloseable { /** * Submits the file for parsing * @param scanFile file to scan - * @param parseFlags parse falgs + * @param parseFlags parse flags */ public void submit(File scanFile, int parseFlags) { mService.submit(() -> { @@ -114,7 +115,7 @@ class ParallelPackageParser implements AutoCloseable { pp.setCacheDir(mCacheDir); pp.setCallback(mPackageParserCallback); pr.scanFile = scanFile; - pr.pkg = parsePackage(pp, scanFile, parseFlags); + pr.parsedPackage = parsePackage(pp, scanFile, parseFlags); } catch (Throwable e) { pr.throwable = e; } finally { @@ -133,9 +134,9 @@ class ParallelPackageParser implements AutoCloseable { } @VisibleForTesting - protected PackageParser.Package parsePackage(PackageParser packageParser, File scanFile, + protected ParsedPackage parsePackage(PackageParser packageParser, File scanFile, int parseFlags) throws PackageParser.PackageParserException { - return packageParser.parsePackage(scanFile, parseFlags, true /* useCaches */); + return packageParser.parseParsedPackage(scanFile, parseFlags, true); } @Override diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java index d20f20ffec46..f4076fdd9ff8 100644 --- a/services/core/java/com/android/server/pm/SELinuxMMAC.java +++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java @@ -21,6 +21,7 @@ import android.compat.annotation.EnabledAfter; import android.content.pm.PackageParser; import android.content.pm.PackageParser.SigningDetails; import android.content.pm.Signature; +import android.content.pm.parsing.AndroidPackage; import android.os.Environment; import android.util.Slog; import android.util.Xml; @@ -391,7 +392,7 @@ public final class SELinuxMMAC { * MINIMUM_TARGETSDKVERSION. * @return String representing the resulting seinfo. */ - public static String getSeInfo(PackageParser.Package pkg, boolean isPrivileged, + public static String getSeInfo(AndroidPackage pkg, boolean isPrivileged, int targetSdkVersion) { String seInfo = null; synchronized (sPolicies) { @@ -420,8 +421,8 @@ public final class SELinuxMMAC { seInfo += TARGETSDKVERSION_STR + targetSdkVersion; if (DEBUG_POLICY_INSTALL) { - Slog.i(TAG, "package (" + pkg.packageName + ") labeled with " + - "seinfo=" + seInfo); + Slog.i(TAG, "package (" + pkg.getPackageName() + ") labeled with " + + "seinfo=" + seInfo); } return seInfo; } @@ -430,7 +431,7 @@ public final class SELinuxMMAC { /** * Holds valid policy representations of individual stanzas from a mac_permissions.xml * file. Each instance can further be used to assign seinfo values to apks using the - * {@link Policy#getMatchedSeinfo} method. To create an instance of this use the + * {@link Policy#getMatchedSeInfo(AndroidPackage)} method. To create an instance of this use the * {@link PolicyBuilder} pattern class, where each instance is validated against a set * of invariants before being built and returned. Each instance can be guaranteed to * hold one valid policy stanza as outlined in the system/sepolicy/mac_permissions.xml @@ -557,21 +558,21 @@ final class Policy { * @return A string representing the seinfo matched during policy lookup. * A value of null can also be returned if no match occured. */ - public String getMatchedSeInfo(PackageParser.Package pkg) { + public String getMatchedSeInfo(AndroidPackage pkg) { // Check for exact signature matches across all certs. Signature[] certs = mCerts.toArray(new Signature[0]); - if (pkg.mSigningDetails != SigningDetails.UNKNOWN - && !Signature.areExactMatch(certs, pkg.mSigningDetails.signatures)) { + if (pkg.getSigningDetails() != SigningDetails.UNKNOWN + && !Signature.areExactMatch(certs, pkg.getSigningDetails().signatures)) { // certs aren't exact match, but the package may have rotated from the known system cert - if (certs.length > 1 || !pkg.mSigningDetails.hasCertificate(certs[0])) { + if (certs.length > 1 || !pkg.getSigningDetails().hasCertificate(certs[0])) { return null; } } // Check for inner package name matches given that the // signature checks already passed. - String seinfoValue = mPkgMap.get(pkg.packageName); + String seinfoValue = mPkgMap.get(pkg.getPackageName()); if (seinfoValue != null) { return seinfoValue; } diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 1082eaa0374e..40ad095ed966 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -42,7 +42,6 @@ import android.content.pm.ComponentInfo; import android.content.pm.IntentFilterVerificationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; -import android.content.pm.PackageParser; import android.content.pm.PackageUserState; import android.content.pm.PermissionInfo; import android.content.pm.ResolveInfo; @@ -50,6 +49,10 @@ import android.content.pm.Signature; import android.content.pm.SuspendDialogInfo; import android.content.pm.UserInfo; import android.content.pm.VerifierDeviceIdentity; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.ComponentParseUtils; +import android.content.pm.parsing.ComponentParseUtils.ParsedComponent; +import android.content.pm.parsing.ComponentParseUtils.ParsedPermission; import android.net.Uri; import android.os.Binder; import android.os.Build; @@ -479,8 +482,8 @@ public final class Settings { final PackageSetting dp = mDisabledSysPackages.get(name); // always make sure the system package code and resource paths dont change if (dp == null && p.pkg != null && p.pkg.isSystem() && !p.pkg.isUpdatedSystemApp()) { - if((p.pkg != null) && (p.pkg.applicationInfo != null)) { - p.pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; + if(p.pkg != null) { + p.pkg.mutate().setUpdatedSystemApp(true); } final PackageSetting disabled; if (replaced) { @@ -506,14 +509,14 @@ public final class Settings { return null; } // Reset flag in ApplicationInfo object - if((p.pkg != null) && (p.pkg.applicationInfo != null)) { - p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; + if(p.pkg != null) { + p.pkg.mutate().setUpdatedSystemApp(false); } PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath, p.legacyNativeLibraryPathString, p.primaryCpuAbiString, p.secondaryCpuAbiString, p.cpuAbiOverrideString, p.appId, p.versionCode, p.pkgFlags, p.pkgPrivateFlags, - p.parentPackageName, p.childPackageNames, p.usesStaticLibraries, + p.usesStaticLibraries, p.usesStaticLibrariesVersions); mDisabledSysPackages.remove(name); return ret; @@ -530,8 +533,7 @@ public final class Settings { PackageSetting addPackageLPw(String name, String realName, File codePath, File resourcePath, String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString, String cpuAbiOverrideString, int uid, long vc, int - pkgFlags, int pkgPrivateFlags, String parentPackageName, - List<String> childPackageNames, String[] usesStaticLibraries, + pkgFlags, int pkgPrivateFlags, String[] usesStaticLibraries, long[] usesStaticLibraryNames) { PackageSetting p = mPackages.get(name); if (p != null) { @@ -544,8 +546,8 @@ public final class Settings { } p = new PackageSetting(name, realName, codePath, resourcePath, legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString, - cpuAbiOverrideString, vc, pkgFlags, pkgPrivateFlags, parentPackageName, - childPackageNames, 0 /*userId*/, usesStaticLibraries, usesStaticLibraryNames); + cpuAbiOverrideString, vc, pkgFlags, pkgPrivateFlags, + 0 /*userId*/, usesStaticLibraries, usesStaticLibraryNames); p.appId = uid; if (registerExistingAppIdLPw(uid, p, name)) { mPackages.put(name, p); @@ -607,19 +609,15 @@ public final class Settings { File codePath, File resourcePath, String legacyNativeLibraryPath, String primaryCpuAbi, String secondaryCpuAbi, long versionCode, int pkgFlags, int pkgPrivateFlags, UserHandle installUser, boolean allowInstall, boolean instantApp, - boolean virtualPreload, String parentPkgName, List<String> childPkgNames, - UserManagerService userManager, + boolean virtualPreload, UserManagerService userManager, String[] usesStaticLibraries, long[] usesStaticLibrariesVersions) { final PackageSetting pkgSetting; if (originalPkg != null) { if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package " + pkgName + " is adopting original package " + originalPkg.name); pkgSetting = new PackageSetting(originalPkg, pkgName /*realPkgName*/); - pkgSetting.childPackageNames = - (childPkgNames != null) ? new ArrayList<>(childPkgNames) : null; pkgSetting.codePath = codePath; pkgSetting.legacyNativeLibraryPathString = legacyNativeLibraryPath; - pkgSetting.parentPackageName = parentPkgName; pkgSetting.pkgFlags = pkgFlags; pkgSetting.pkgPrivateFlags = pkgPrivateFlags; pkgSetting.primaryCpuAbiString = primaryCpuAbi; @@ -637,7 +635,7 @@ public final class Settings { pkgSetting = new PackageSetting(pkgName, realPkgName, codePath, resourcePath, legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi, null /*cpuAbiOverrideString*/, versionCode, pkgFlags, pkgPrivateFlags, - parentPkgName, childPkgNames, 0 /*sharedUserId*/, usesStaticLibraries, + 0 /*sharedUserId*/, usesStaticLibraries, usesStaticLibrariesVersions); pkgSetting.setTimeStamp(codePath.lastModified()); pkgSetting.sharedUser = sharedUser; @@ -721,7 +719,7 @@ public final class Settings { @NonNull File codePath, File resourcePath, @Nullable String legacyNativeLibraryPath, @Nullable String primaryCpuAbi, @Nullable String secondaryCpuAbi, int pkgFlags, int pkgPrivateFlags, - @Nullable List<String> childPkgNames, @NonNull UserManagerService userManager, + @NonNull UserManagerService userManager, @Nullable String[] usesStaticLibraries, @Nullable long[] usesStaticLibrariesVersions) throws PackageManagerException { final String pkgName = pkgSetting.name; @@ -799,9 +797,6 @@ public final class Settings { pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_ODM; pkgSetting.primaryCpuAbiString = primaryCpuAbi; pkgSetting.secondaryCpuAbiString = secondaryCpuAbi; - if (childPkgNames != null) { - pkgSetting.childPackageNames = new ArrayList<>(childPkgNames); - } // Update static shared library dependencies if needed if (usesStaticLibraries != null && usesStaticLibrariesVersions != null && usesStaticLibraries.length == usesStaticLibrariesVersions.length) { @@ -870,15 +865,15 @@ public final class Settings { // TODO: Move to scanPackageOnlyLI() after verifying signatures are setup correctly // by that time. - void insertPackageSettingLPw(PackageSetting p, PackageParser.Package pkg) { + void insertPackageSettingLPw(PackageSetting p, AndroidPackage pkg) { // Update signatures if needed. if (p.signatures.mSigningDetails.signatures == null) { - p.signatures.mSigningDetails = pkg.mSigningDetails; + p.signatures.mSigningDetails = pkg.getSigningDetails(); } // If this app defines a shared user id initialize // the shared user signatures as well. if (p.sharedUser != null && p.sharedUser.signatures.mSigningDetails.signatures == null) { - p.sharedUser.signatures.mSigningDetails = pkg.mSigningDetails; + p.sharedUser.signatures.mSigningDetails = pkg.getSigningDetails(); } addPackageSettingLPw(p, p.sharedUser); } @@ -955,7 +950,7 @@ public final class Settings { int affectedUserId = UserHandle.USER_NULL; // Update permissions - for (String eachPerm : deletedPs.pkg.requestedPermissions) { + for (String eachPerm : deletedPs.pkg.getRequestedPermissions()) { BasePermission bp = mPermissions.getPermission(eachPerm); if (bp == null) { continue; @@ -965,8 +960,8 @@ public final class Settings { boolean used = false; for (PackageSetting pkg : sus.packages) { if (pkg.pkg != null - && !pkg.pkg.packageName.equals(deletedPs.pkg.packageName) - && pkg.pkg.requestedPermissions.contains(eachPerm)) { + && !pkg.pkg.getPackageName().equals(deletedPs.pkg.getPackageName()) + && pkg.pkg.getRequestedPermissions().contains(eachPerm)) { used = true; break; } @@ -976,13 +971,13 @@ public final class Settings { } PermissionsState permissionsState = sus.getPermissionsState(); - PackageSetting disabledPs = getDisabledSystemPkgLPr(deletedPs.pkg.packageName); + PackageSetting disabledPs = getDisabledSystemPkgLPr(deletedPs.pkg.getPackageName()); // If the package is shadowing is a disabled system package, // do not drop permissions that the shadowed package requests. if (disabledPs != null) { boolean reqByDisabledSysPkg = false; - for (String permission : disabledPs.pkg.requestedPermissions) { + for (String permission : disabledPs.pkg.getRequestedPermissions()) { if (permission.equals(eachPerm)) { reqByDisabledSysPkg = true; break; @@ -2215,20 +2210,6 @@ public final class Settings { serializer.endTag(null, TAG_PERMISSIONS); } - void writeChildPackagesLPw(XmlSerializer serializer, List<String> childPackageNames) - throws IOException { - if (childPackageNames == null) { - return; - } - final int childCount = childPackageNames.size(); - for (int i = 0; i < childCount; i++) { - String childPackageName = childPackageNames.get(i); - serializer.startTag(null, TAG_CHILD_PACKAGE); - serializer.attribute(null, ATTR_NAME, childPackageName); - serializer.endTag(null, TAG_CHILD_PACKAGE); - } - } - void readUsesStaticLibLPw(XmlPullParser parser, PackageSetting outPs) throws IOException, XmlPullParserException { int outerDepth = parser.getDepth(); @@ -2682,17 +2663,15 @@ public final class Settings { StringBuilder sb = new StringBuilder(); for (final PackageSetting pkg : mPackages.values()) { - if (pkg.pkg == null || pkg.pkg.applicationInfo == null - || pkg.pkg.applicationInfo.dataDir == null) { + if (pkg.pkg == null || pkg.pkg.getDataDir() == null) { if (!"android".equals(pkg.name)) { Slog.w(TAG, "Skipping " + pkg + " due to missing metadata"); } continue; } - final ApplicationInfo ai = pkg.pkg.applicationInfo; - final String dataPath = ai.dataDir; - final boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; + final String dataPath = pkg.pkg.getDataDir(); + final boolean isDebug = (pkg.pkg.getFlags() & ApplicationInfo.FLAG_DEBUGGABLE) != 0; final int[] gids = pkg.getPermissionsState().computeGids(userIds); // Avoid any application that has a space in its path. @@ -2717,13 +2696,13 @@ public final class Settings { // system/core/libpackagelistparser // sb.setLength(0); - sb.append(ai.packageName); + sb.append(pkg.pkg.getPackageName()); sb.append(" "); - sb.append(ai.uid); + sb.append(pkg.pkg.getUid()); sb.append(isDebug ? " 1 " : " 0 "); sb.append(dataPath); sb.append(" "); - sb.append(ai.seInfo); + sb.append(pkg.pkg.getSeInfo()); sb.append(" "); if (gids != null && gids.length > 0) { sb.append(gids[0]); @@ -2735,9 +2714,9 @@ public final class Settings { sb.append("none"); } sb.append(" "); - sb.append(ai.isProfileableByShell() ? "1" : "0"); + sb.append(pkg.pkg.isProfileableByShell() ? "1" : "0"); sb.append(" "); - sb.append(String.valueOf(ai.longVersionCode)); + sb.append(pkg.pkg.getLongVersionCode()); sb.append("\n"); writer.append(sb); } @@ -2786,12 +2765,6 @@ public final class Settings { serializer.attribute(null, "sharedUserId", Integer.toString(pkg.appId)); } - if (pkg.parentPackageName != null) { - serializer.attribute(null, "parentPackageName", pkg.parentPackageName); - } - - writeChildPackagesLPw(serializer, pkg.childPackageNames); - writeUsesStaticLibLPw(serializer, pkg.usesStaticLibraries, pkg.usesStaticLibrariesVersions); // If this is a shared user, the permissions will be written there. @@ -2861,15 +2834,10 @@ public final class Settings { if (pkg.categoryHint != ApplicationInfo.CATEGORY_UNDEFINED) { serializer.attribute(null, "categoryHint", Integer.toString(pkg.categoryHint)); } - if (pkg.parentPackageName != null) { - serializer.attribute(null, "parentPackageName", pkg.parentPackageName); - } if (pkg.updateAvailable) { serializer.attribute(null, "updateAvailable", "true"); } - writeChildPackagesLPw(serializer, pkg.childPackageNames); - writeUsesStaticLibLPw(serializer, pkg.usesStaticLibraries, pkg.usesStaticLibrariesVersions); pkg.signatures.writeXml(serializer, "sigs", mPastSignatures); @@ -3161,13 +3129,13 @@ public final class Settings { LocalServices.getService(PackageManagerInternal.class); for (PackageSetting ps : mPackages.values()) { if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0 && ps.pkg != null - && ps.pkg.preferredActivityFilters != null) { - ArrayList<PackageParser.ActivityIntentInfo> intents - = ps.pkg.preferredActivityFilters; + && ps.pkg.getPreferredActivityFilters() != null) { + List<ComponentParseUtils.ParsedActivityIntentInfo> intents + = ps.pkg.getPreferredActivityFilters(); for (int i=0; i<intents.size(); i++) { - PackageParser.ActivityIntentInfo aii = intents.get(i); + ComponentParseUtils.ParsedActivityIntentInfo aii = intents.get(i); applyDefaultPreferredActivityLPw(pmInternal, aii, new ComponentName( - ps.name, aii.activity.className), userId); + ps.name, aii.getClassName()), userId); } } } @@ -3527,7 +3495,7 @@ public final class Settings { PackageSetting ps = new PackageSetting(name, realName, new File(codePathStr), new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiStr, secondaryCpuAbiStr, cpuAbiOverrideStr, versionCode, pkgFlags, pkgPrivateFlags, - parentPackageName, null /*childPackageNames*/, 0 /*sharedUserId*/, null, null); + 0 /*sharedUserId*/, null, null); String timeStampStr = parser.getAttributeValue(null, "ft"); if (timeStampStr != null) { try { @@ -3576,12 +3544,6 @@ public final class Settings { if (parser.getName().equals(TAG_PERMISSIONS)) { readInstallPermissionsLPr(parser, ps.getPermissionsState()); - } else if (parser.getName().equals(TAG_CHILD_PACKAGE)) { - String childPackageName = parser.getAttributeValue(null, ATTR_NAME); - if (ps.childPackageNames == null) { - ps.childPackageNames = new ArrayList<>(); - } - ps.childPackageNames.add(childPackageName); } else if (parser.getName().equals(TAG_USES_STATIC_LIB)) { readUsesStaticLibLPw(parser, ps); } else { @@ -3628,7 +3590,6 @@ public final class Settings { PackageSetting packageSetting = null; String version = null; long versionCode = 0; - String parentPackageName; try { name = parser.getAttributeValue(null, ATTR_NAME); realName = parser.getAttributeValue(null, "realName"); @@ -3640,8 +3601,6 @@ public final class Settings { legacyCpuAbiString = parser.getAttributeValue(null, "requiredCpuAbi"); - parentPackageName = parser.getAttributeValue(null, "parentPackageName"); - legacyNativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath"); primaryCpuAbiString = parser.getAttributeValue(null, "primaryCpuAbi"); secondaryCpuAbiString = parser.getAttributeValue(null, "secondaryCpuAbi"); @@ -3770,7 +3729,7 @@ public final class Settings { packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr), new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString, userId, versionCode, pkgFlags, - pkgPrivateFlags, parentPackageName, null /*childPackageNames*/, + pkgPrivateFlags, null /*usesStaticLibraries*/, null /*usesStaticLibraryVersions*/); if (PackageManagerService.DEBUG_SETTINGS) Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId=" @@ -3789,8 +3748,8 @@ public final class Settings { packageSetting = new PackageSetting(name.intern(), realName, new File( codePathStr), new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString, - versionCode, pkgFlags, pkgPrivateFlags, parentPackageName, - null /*childPackageNames*/, sharedUserId, + versionCode, pkgFlags, pkgPrivateFlags, + sharedUserId, null /*usesStaticLibraries*/, null /*usesStaticLibraryVersions*/); packageSetting.setTimeStamp(timeStamp); packageSetting.firstInstallTime = firstInstallTime; @@ -3899,12 +3858,6 @@ public final class Settings { packageSetting.keySetData.addDefinedKeySet(id, alias); } else if (tagName.equals(TAG_DOMAIN_VERIFICATION)) { readDomainVerificationLPw(parser, packageSetting); - } else if (tagName.equals(TAG_CHILD_PACKAGE)) { - String childPackageName = parser.getAttributeValue(null, ATTR_NAME); - if (packageSetting.childPackageNames == null) { - packageSetting.childPackageNames = new ArrayList<>(); - } - packageSetting.childPackageNames.add(childPackageName); } else { PackageManagerService.reportSettingsProblem(Log.WARN, "Unknown element under <package>: " + parser.getName()); @@ -4057,13 +4010,13 @@ public final class Settings { Iterator<PackageSetting> packagesIterator = packages.iterator(); for (int i = 0; i < packagesCount; i++) { PackageSetting ps = packagesIterator.next(); - if (ps.pkg == null || ps.pkg.applicationInfo == null) { + if (ps.pkg == null) { continue; } final boolean shouldInstall = ps.isSystem() && (skipPackageWhitelist || installablePackages.contains(ps.name)) && !ArrayUtils.contains(disallowedPackages, ps.name) && - !ps.pkg.applicationInfo.hiddenUntilInstalled; + !ps.pkg.isHiddenUntilInstalled(); // Only system apps are initially installed. ps.setInstalled(shouldInstall, userHandle); if (!shouldInstall) { @@ -4074,8 +4027,8 @@ public final class Settings { volumeUuids[i] = ps.volumeUuid; names[i] = ps.name; appIds[i] = ps.appId; - seinfos[i] = ps.pkg.applicationInfo.seInfo; - targetSdkVersions[i] = ps.pkg.applicationInfo.targetSdkVersion; + seinfos[i] = ps.pkg.getSeInfo(); + targetSdkVersions[i] = ps.pkg.getTargetSdkVersion(); } } t.traceBegin("createAppData"); @@ -4185,28 +4138,6 @@ public final class Settings { return mVerifierDeviceIdentity; } - boolean hasOtherDisabledSystemPkgWithChildLPr(String parentPackageName, - String childPackageName) { - final int packageCount = mDisabledSysPackages.size(); - for (int i = 0; i < packageCount; i++) { - PackageSetting disabledPs = mDisabledSysPackages.valueAt(i); - if (disabledPs.childPackageNames == null || disabledPs.childPackageNames.isEmpty()) { - continue; - } - if (disabledPs.name.equals(parentPackageName)) { - continue; - } - final int childCount = disabledPs.childPackageNames.size(); - for (int j = 0; j < childCount; j++) { - String currChildPackageName = disabledPs.childPackageNames.get(j); - if (currChildPackageName.equals(childPackageName)) { - return true; - } - } - } - return false; - } - /** * Returns the disabled {@link PackageSetting} for the provided package name if one exists, * {@code null} otherwise. @@ -4229,26 +4160,6 @@ public final class Settings { return getDisabledSystemPkgLPr(enabledPackageSetting.name); } - /** - * Fetches an array of the child {@link PackageSetting}s for all child package names referenced - * by the provided parent {@link PackageSetting} or {@code null} if no children are referenced. - * - * Note: Any child packages not found will be null in the returned array. - */ - @Nullable - public PackageSetting[] getChildSettingsLPr(PackageSetting parentPackageSetting) { - if (parentPackageSetting == null || !parentPackageSetting.hasChildPackages()) { - return null; - } - final int childCount = parentPackageSetting.childPackageNames.size(); - PackageSetting[] children = - new PackageSetting[childCount]; - for (int i = 0; i < childCount; i++) { - children[i] = mPackages.get(parentPackageSetting.childPackageNames.get(i)); - } - return children; - } - boolean isEnabledAndMatchLPr(ComponentInfo componentInfo, int flags, int userId) { final PackageSetting ps = mPackages.get(componentInfo.packageName); if (ps == null) return false; @@ -4467,6 +4378,7 @@ public final class Settings { void dumpPackageLPr(PrintWriter pw, String prefix, String checkinTag, ArraySet<String> permissionNames, PackageSetting ps, SimpleDateFormat sdf, Date date, List<UserInfo> users, boolean dumpAll, boolean dumpAllComponents) { + AndroidPackage pkg = ps.pkg; if (checkinTag != null) { pw.print(checkinTag); pw.print(","); @@ -4483,15 +4395,16 @@ public final class Settings { pw.print(ps.installSource.installerPackageName != null ? ps.installSource.installerPackageName : "?"); pw.println(); - if (ps.pkg != null) { + if (pkg != null) { pw.print(checkinTag); pw.print("-"); pw.print("splt,"); pw.print("base,"); - pw.println(ps.pkg.baseRevisionCode); - if (ps.pkg.splitNames != null) { - for (int i = 0; i < ps.pkg.splitNames.length; i++) { + pw.println(pkg.getBaseRevisionCode()); + if (pkg.getSplitNames() != null) { + int[] splitRevisionCodes = pkg.getSplitRevisionCodes(); + for (int i = 0; i < pkg.getSplitNames().length; i++) { pw.print(checkinTag); pw.print("-"); pw.print("splt,"); - pw.print(ps.pkg.splitNames[i]); pw.print(","); - pw.println(ps.pkg.splitRevisionCodes[i]); + pw.print(pkg.getSplitNames()[i]); pw.print(","); + pw.println(splitRevisionCodes[i]); } } } @@ -4538,7 +4451,7 @@ public final class Settings { if (ps.sharedUser != null) { pw.print(prefix); pw.print(" sharedUser="); pw.println(ps.sharedUser); } - pw.print(prefix); pw.print(" pkg="); pw.println(ps.pkg); + pw.print(prefix); pw.print(" pkg="); pw.println(pkg); pw.print(prefix); pw.print(" codePath="); pw.println(ps.codePathString); if (permissionNames == null) { pw.print(prefix); pw.print(" resourcePath="); pw.println(ps.resourcePathString); @@ -4548,140 +4461,123 @@ public final class Settings { pw.print(prefix); pw.print(" secondaryCpuAbi="); pw.println(ps.secondaryCpuAbiString); } pw.print(prefix); pw.print(" versionCode="); pw.print(ps.versionCode); - if (ps.pkg != null) { - pw.print(" minSdk="); pw.print(ps.pkg.applicationInfo.minSdkVersion); - pw.print(" targetSdk="); pw.print(ps.pkg.applicationInfo.targetSdkVersion); + if (pkg != null) { + pw.print(" minSdk="); pw.print(pkg.getMinSdkVersion()); + pw.print(" targetSdk="); pw.print(pkg.getTargetSdkVersion()); } pw.println(); - if (ps.pkg != null) { - if (ps.pkg.parentPackage != null) { - PackageParser.Package parentPkg = ps.pkg.parentPackage; - PackageSetting pps = mPackages.get(parentPkg.packageName); - if (pps == null || !pps.codePathString.equals(parentPkg.codePath)) { - pps = mDisabledSysPackages.get(parentPkg.packageName); - } - if (pps != null) { - pw.print(prefix); pw.print(" parentPackage="); - pw.println(pps.realName != null ? pps.realName : pps.name); - } - } else if (ps.pkg.childPackages != null) { - pw.print(prefix); pw.print(" childPackages=["); - final int childCount = ps.pkg.childPackages.size(); - for (int i = 0; i < childCount; i++) { - PackageParser.Package childPkg = ps.pkg.childPackages.get(i); - PackageSetting cps = mPackages.get(childPkg.packageName); - if (cps == null || !cps.codePathString.equals(childPkg.codePath)) { - cps = mDisabledSysPackages.get(childPkg.packageName); - } - if (cps != null) { - if (i > 0) { - pw.print(", "); - } - pw.print(cps.realName != null ? cps.realName : cps.name); - } - } - pw.println("]"); - } - pw.print(prefix); pw.print(" versionName="); pw.println(ps.pkg.mVersionName); - pw.print(prefix); pw.print(" splits="); dumpSplitNames(pw, ps.pkg); pw.println(); - final int apkSigningVersion = ps.pkg.mSigningDetails.signatureSchemeVersion; + if (pkg != null) { + pw.print(prefix); pw.print(" versionName="); pw.println(pkg.getVersionName()); + pw.print(prefix); pw.print(" splits="); dumpSplitNames(pw, pkg); pw.println(); + final int apkSigningVersion = pkg.getSigningDetails().signatureSchemeVersion; pw.print(prefix); pw.print(" apkSigningVersion="); pw.println(apkSigningVersion); + // TODO(b/135203078): Is there anything to print here with AppInfo removed? pw.print(prefix); pw.print(" applicationInfo="); - pw.println(ps.pkg.applicationInfo.toString()); - pw.print(prefix); pw.print(" flags="); printFlags(pw, ps.pkg.applicationInfo.flags, + pw.println(pkg.toAppInfo().toString()); + pw.print(prefix); pw.print(" flags="); printFlags(pw, pkg.getFlags(), FLAG_DUMP_SPEC); pw.println(); - if (ps.pkg.applicationInfo.privateFlags != 0) { + if (pkg.getPrivateFlags() != 0) { pw.print(prefix); pw.print(" privateFlags="); printFlags(pw, - ps.pkg.applicationInfo.privateFlags, PRIVATE_FLAG_DUMP_SPEC); pw.println(); + pkg.getPrivateFlags(), PRIVATE_FLAG_DUMP_SPEC); pw.println(); } - pw.print(prefix); pw.print(" forceQueryable="); pw.println(ps.pkg.mForceQueryable); - if (ps.pkg.mQueriesPackages != null) { - pw.append(prefix).append(" queriesPackages=").println(ps.pkg.mQueriesPackages); + pw.print(prefix); pw.print(" forceQueryable="); pw.println(ps.pkg.isForceQueryable()); + if (ps.pkg.getQueriesPackages() != null) { + pw.append(prefix).append(" queriesPackages=").println(ps.pkg.getQueriesPackages()); } - if (ps.pkg.mQueriesIntents != null) { - pw.append(prefix).append(" queriesIntents=").println(ps.pkg.mQueriesIntents); + if (ps.pkg.getQueriesIntents() != null) { + pw.append(prefix).append(" queriesIntents=").println(ps.pkg.getQueriesIntents()); } - pw.print(prefix); pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir); + pw.print(prefix); pw.print(" dataDir="); pw.println(ps.pkg.getDataDir()); pw.print(prefix); pw.print(" supportsScreens=["); boolean first = true; - if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) { + if ((pkg.getFlags() & ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) { if (!first) pw.print(", "); first = false; pw.print("small"); } - if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) { + if ((pkg.getFlags() & ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) { if (!first) pw.print(", "); first = false; pw.print("medium"); } - if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) { + if ((pkg.getFlags() & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) { if (!first) pw.print(", "); first = false; pw.print("large"); } - if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) { + if ((pkg.getFlags() & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) { if (!first) pw.print(", "); first = false; pw.print("xlarge"); } - if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) { + if ((pkg.getFlags() & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) { if (!first) pw.print(", "); first = false; pw.print("resizeable"); } - if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) { + if ((pkg.getFlags() & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) { if (!first) pw.print(", "); first = false; pw.print("anyDensity"); } pw.println("]"); - if (ps.pkg.libraryNames != null && ps.pkg.libraryNames.size() > 0) { + List<String> libraryNames = pkg.getLibraryNames(); + if (libraryNames != null && libraryNames.size() > 0) { pw.print(prefix); pw.println(" dynamic libraries:"); - for (int i = 0; i<ps.pkg.libraryNames.size(); i++) { + for (int i = 0; i< libraryNames.size(); i++) { pw.print(prefix); pw.print(" "); - pw.println(ps.pkg.libraryNames.get(i)); + pw.println(libraryNames.get(i)); } } - if (ps.pkg.staticSharedLibName != null) { + if (pkg.getStaticSharedLibName() != null) { pw.print(prefix); pw.println(" static library:"); pw.print(prefix); pw.print(" "); - pw.print("name:"); pw.print(ps.pkg.staticSharedLibName); - pw.print(" version:"); pw.println(ps.pkg.staticSharedLibVersion); + pw.print("name:"); pw.print(pkg.getStaticSharedLibName()); + pw.print(" version:"); pw.println(pkg.getStaticSharedLibVersion()); } - if (ps.pkg.usesLibraries != null && ps.pkg.usesLibraries.size() > 0) { + + List<String> usesLibraries = pkg.getUsesLibraries(); + if (usesLibraries != null && usesLibraries.size() > 0) { pw.print(prefix); pw.println(" usesLibraries:"); - for (int i=0; i<ps.pkg.usesLibraries.size(); i++) { - pw.print(prefix); pw.print(" "); pw.println(ps.pkg.usesLibraries.get(i)); + for (int i=0; i< usesLibraries.size(); i++) { + pw.print(prefix); pw.print(" "); pw.println(usesLibraries.get(i)); } } - if (ps.pkg.usesStaticLibraries != null - && ps.pkg.usesStaticLibraries.size() > 0) { + + List<String> usesStaticLibraries = pkg.getUsesStaticLibraries(); + long[] usesStaticLibrariesVersions = pkg.getUsesStaticLibrariesVersions(); + if (usesStaticLibraries != null + && usesStaticLibraries.size() > 0) { pw.print(prefix); pw.println(" usesStaticLibraries:"); - for (int i=0; i<ps.pkg.usesStaticLibraries.size(); i++) { + for (int i=0; i< usesStaticLibraries.size(); i++) { pw.print(prefix); pw.print(" "); - pw.print(ps.pkg.usesStaticLibraries.get(i)); pw.print(" version:"); - pw.println(ps.pkg.usesStaticLibrariesVersions[i]); + pw.print(usesStaticLibraries.get(i)); pw.print(" version:"); + pw.println(usesStaticLibrariesVersions[i]); } } - if (ps.pkg.usesOptionalLibraries != null - && ps.pkg.usesOptionalLibraries.size() > 0) { + + List<String> usesOptionalLibraries = pkg.getUsesOptionalLibraries(); + if (usesOptionalLibraries != null + && usesOptionalLibraries.size() > 0) { pw.print(prefix); pw.println(" usesOptionalLibraries:"); - for (int i=0; i<ps.pkg.usesOptionalLibraries.size(); i++) { + for (int i=0; i< usesOptionalLibraries.size(); i++) { pw.print(prefix); pw.print(" "); - pw.println(ps.pkg.usesOptionalLibraries.get(i)); + pw.println(usesOptionalLibraries.get(i)); } } - if (ps.pkg.usesLibraryFiles != null - && ps.pkg.usesLibraryFiles.length > 0) { + + String[] usesLibraryFiles = pkg.getUsesLibraryFiles(); + if (usesLibraryFiles != null + && usesLibraryFiles.length > 0) { pw.print(prefix); pw.println(" usesLibraryFiles:"); - for (int i=0; i<ps.pkg.usesLibraryFiles.length; i++) { - pw.print(prefix); pw.print(" "); pw.println(ps.pkg.usesLibraryFiles[i]); + for (int i=0; i< usesLibraryFiles.length; i++) { + pw.print(prefix); pw.print(" "); pw.println(usesLibraryFiles[i]); } } } @@ -4709,40 +4605,40 @@ public final class Settings { pw.print(prefix); pw.print(" pkgFlags="); printFlags(pw, ps.pkgFlags, FLAG_DUMP_SPEC); pw.println(); - if (ps.pkg != null && ps.pkg.mOverlayTarget != null) { - pw.print(prefix); pw.print(" overlayTarget="); pw.println(ps.pkg.mOverlayTarget); - pw.print(prefix); pw.print(" overlayCategory="); pw.println(ps.pkg.mOverlayCategory); + if (pkg != null && pkg.getOverlayTarget() != null) { + pw.print(prefix); pw.print(" overlayTarget="); pw.println(pkg.getOverlayTarget()); + pw.print(prefix); pw.print(" overlayCategory="); pw.println(pkg.getOverlayCategory()); } - if (ps.pkg != null && ps.pkg.permissions != null && ps.pkg.permissions.size() > 0) { - final ArrayList<PackageParser.Permission> perms = ps.pkg.permissions; + if (pkg != null && pkg.getPermissions() != null && pkg.getPermissions().size() > 0) { + final List<ParsedPermission> perms = pkg.getPermissions(); pw.print(prefix); pw.println(" declared permissions:"); for (int i=0; i<perms.size(); i++) { - PackageParser.Permission perm = perms.get(i); + ParsedPermission perm = perms.get(i); if (permissionNames != null - && !permissionNames.contains(perm.info.name)) { + && !permissionNames.contains(perm.getName())) { continue; } - pw.print(prefix); pw.print(" "); pw.print(perm.info.name); + pw.print(prefix); pw.print(" "); pw.print(perm.getName()); pw.print(": prot="); - pw.print(PermissionInfo.protectionToString(perm.info.protectionLevel)); - if ((perm.info.flags&PermissionInfo.FLAG_COSTS_MONEY) != 0) { + pw.print(PermissionInfo.protectionToString(perm.protectionLevel)); + if ((perm.flags&PermissionInfo.FLAG_COSTS_MONEY) != 0) { pw.print(", COSTS_MONEY"); } - if ((perm.info.flags&PermissionInfo.FLAG_REMOVED) != 0) { + if ((perm.flags&PermissionInfo.FLAG_REMOVED) != 0) { pw.print(", HIDDEN"); } - if ((perm.info.flags&PermissionInfo.FLAG_INSTALLED) != 0) { + if ((perm.flags&PermissionInfo.FLAG_INSTALLED) != 0) { pw.print(", INSTALLED"); } pw.println(); } } - if ((permissionNames != null || dumpAll) && ps.pkg != null - && ps.pkg.requestedPermissions != null - && ps.pkg.requestedPermissions.size() > 0) { - final ArrayList<String> perms = ps.pkg.requestedPermissions; + if ((permissionNames != null || dumpAll) && pkg != null + && pkg.getRequestedPermissions() != null + && pkg.getRequestedPermissions().size() > 0) { + final List<String> perms = pkg.getRequestedPermissions(); pw.print(prefix); pw.println(" requested permissions:"); for (int i=0; i<perms.size(); i++) { String perm = perms.get(i); @@ -5019,22 +4915,24 @@ public final class Settings { pw.print(mReadMessages.toString()); } - private static void dumpSplitNames(PrintWriter pw, PackageParser.Package pkg) { + private static void dumpSplitNames(PrintWriter pw, AndroidPackage pkg) { if (pkg == null) { pw.print("unknown"); } else { // [base:10, config.mdpi, config.xhdpi:12] pw.print("["); pw.print("base"); - if (pkg.baseRevisionCode != 0) { - pw.print(":"); pw.print(pkg.baseRevisionCode); + if (pkg.getBaseRevisionCode() != 0) { + pw.print(":"); pw.print(pkg.getBaseRevisionCode()); } - if (pkg.splitNames != null) { - for (int i = 0; i < pkg.splitNames.length; i++) { + String[] splitNames = pkg.getSplitNames(); + int[] splitRevisionCodes = pkg.getSplitRevisionCodes(); + if (splitNames != null) { + for (int i = 0; i < splitNames.length; i++) { pw.print(", "); - pw.print(pkg.splitNames[i]); - if (pkg.splitRevisionCodes[i] != 0) { - pw.print(":"); pw.print(pkg.splitRevisionCodes[i]); + pw.print(splitNames[i]); + if (splitRevisionCodes[i] != 0) { + pw.print(":"); pw.print(splitRevisionCodes[i]); } } } @@ -5110,22 +5008,23 @@ public final class Settings { } void dumpComponents(PrintWriter pw, String prefix, PackageSetting ps) { - dumpComponents(pw, prefix, ps, "activities:", ps.pkg.activities); - dumpComponents(pw, prefix, ps, "services:", ps.pkg.services); - dumpComponents(pw, prefix, ps, "receivers:", ps.pkg.receivers); - dumpComponents(pw, prefix, ps, "providers:", ps.pkg.providers); - dumpComponents(pw, prefix, ps, "instrumentations:", ps.pkg.instrumentation); + // TODO(b/135203078): ParsedComponent toString methods for dumping + dumpComponents(pw, prefix, "activities:", ps.pkg.getActivities()); + dumpComponents(pw, prefix, "services:", ps.pkg.getServices()); + dumpComponents(pw, prefix, "receivers:", ps.pkg.getReceivers()); + dumpComponents(pw, prefix, "providers:", ps.pkg.getProviders()); + dumpComponents(pw, prefix, "instrumentations:", ps.pkg.getInstrumentations()); } - void dumpComponents(PrintWriter pw, String prefix, PackageSetting ps, - String label, List<? extends PackageParser.Component<?>> list) { + void dumpComponents(PrintWriter pw, String prefix, String label, + List<? extends ParsedComponent> list) { final int size = CollectionUtils.size(list); if (size == 0) { return; } pw.print(prefix);pw.println(label); for (int i = 0; i < size; i++) { - final PackageParser.Component<?> component = list.get(i); + final ParsedComponent component = list.get(i); pw.print(prefix);pw.print(" "); pw.println(component.getComponentName().flattenToShortString()); } diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java index 648051817295..0a42ccf1c5ba 100644 --- a/services/core/java/com/android/server/pm/SharedUserSetting.java +++ b/services/core/java/com/android/server/pm/SharedUserSetting.java @@ -18,7 +18,7 @@ package com.android.server.pm; import android.annotation.Nullable; import android.content.pm.ApplicationInfo; -import android.content.pm.PackageParser; +import android.content.pm.parsing.AndroidPackage; import android.service.pm.PackageServiceDumpProto; import android.util.ArraySet; import android.util.proto.ProtoOutputStream; @@ -46,7 +46,7 @@ public final class SharedUserSetting extends SettingBase { // that all apps within the sharedUser run in the same selinux context. int seInfoTargetSdkVersion; - final ArraySet<PackageSetting> packages = new ArraySet<PackageSetting>(); + final ArraySet<PackageSetting> packages = new ArraySet<>(); final PackageSignatures signatures = new PackageSignatures(); Boolean signaturesChanged; @@ -98,7 +98,7 @@ public final class SharedUserSetting extends SettingBase { // If this is the first package added to this shared user, temporarily (until next boot) use // its targetSdkVersion when assigning seInfo for the shared user. if ((packages.size() == 0) && (packageSetting.pkg != null)) { - seInfoTargetSdkVersion = packageSetting.pkg.applicationInfo.targetSdkVersion; + seInfoTargetSdkVersion = packageSetting.pkg.getTargetSdkVersion(); } if (packages.add(packageSetting)) { setFlags(this.pkgFlags | packageSetting.pkgFlags); @@ -106,11 +106,11 @@ public final class SharedUserSetting extends SettingBase { } } - public @Nullable List<PackageParser.Package> getPackages() { + public @Nullable List<AndroidPackage> getPackages() { if (packages == null || packages.size() == 0) { return null; } - final ArrayList<PackageParser.Package> pkgList = new ArrayList<>(packages.size()); + final ArrayList<AndroidPackage> pkgList = new ArrayList<>(packages.size()); for (PackageSetting ps : packages) { if ((ps == null) || (ps.pkg == null)) { continue; @@ -131,20 +131,20 @@ public final class SharedUserSetting extends SettingBase { * restrictive selinux domain. */ public void fixSeInfoLocked() { - final List<PackageParser.Package> pkgList = getPackages(); + final List<AndroidPackage> pkgList = getPackages(); if (pkgList == null || pkgList.size() == 0) { return; } - for (PackageParser.Package pkg : pkgList) { - if (pkg.applicationInfo.targetSdkVersion < seInfoTargetSdkVersion) { - seInfoTargetSdkVersion = pkg.applicationInfo.targetSdkVersion; + for (AndroidPackage pkg : pkgList) { + if (pkg.getTargetSdkVersion() < seInfoTargetSdkVersion) { + seInfoTargetSdkVersion = pkg.getTargetSdkVersion(); } } - for (PackageParser.Package pkg : pkgList) { + for (AndroidPackage pkg : pkgList) { final boolean isPrivileged = isPrivileged() | pkg.isPrivileged(); - pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, isPrivileged, - seInfoTargetSdkVersion); + pkg.mutate().setSeInfo(SELinuxMMAC.getSeInfo(pkg, isPrivileged, + seInfoTargetSdkVersion)); } } diff --git a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java index 0a6a43543860..034c010a2ef5 100644 --- a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java +++ b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java @@ -199,7 +199,7 @@ class UserSystemPackageInstaller { final boolean changed = pmInt.setInstalled(pkg, userId, install); if (changed) { Slog.i(TAG, (install ? "Installed " : "Uninstalled ") - + pkg.packageName + " for user " + userId); + + pkg.getPackageName() + " for user " + userId); } }); } @@ -220,7 +220,7 @@ class UserSystemPackageInstaller { // Check whether all whitelisted packages are indeed on the system. for (String pkgName : allWhitelistedPackages) { - PackageParser.Package pkg = pmInt.getPackage(pkgName); + AndroidPackage pkg = pmInt.getPackage(pkgName); if (pkg == null) { Slog.w(TAG, pkgName + " is whitelisted but not present."); } else if (!pkg.isSystem()) { @@ -234,8 +234,8 @@ class UserSystemPackageInstaller { } final boolean doWtf = isEnforceMode(mode); pmInt.forEachPackage(pkg -> { - if (pkg.isSystem() && !allWhitelistedPackages.contains(pkg.manifestPackageName)) { - final String msg = "System package " + pkg.manifestPackageName + if (pkg.isSystem() && !allWhitelistedPackages.contains(pkg.getManifestPackageName())) { + final String msg = "System package " + pkg.getManifestPackageName() + " is not whitelisted using 'install-in-user-type' in SystemConfig " + "for any user types!"; if (doWtf) { @@ -344,7 +344,7 @@ class UserSystemPackageInstaller { if (shouldInstallPackage(pkg, mWhitelistedPackagesForUserTypes, whitelistedPackages, isImplicitWhitelistMode, isSystemUser)) { // Although the whitelist uses manifest names, this function returns packageNames. - installPackages.add(pkg.packageName); + installPackages.add(pkg.getPackageName()); } }); return installPackages; @@ -371,7 +371,7 @@ class UserSystemPackageInstaller { @NonNull Set<String> userWhitelist, boolean isImplicitWhitelistMode, boolean isSystemUser) { - final String pkgName = sysPkg.manifestPackageName; + final String pkgName = sysPkg.getManifestPackageName(); boolean install = (isImplicitWhitelistMode && !userTypeWhitelist.containsKey(pkgName)) || userWhitelist.contains(pkgName); diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java index cc5aec2e113e..486cfeff0739 100644 --- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java +++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java @@ -25,13 +25,13 @@ import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.content.pm.PackageParser; import android.content.pm.dex.ArtManager; import android.content.pm.dex.ArtManager.ProfileType; import android.content.pm.dex.ArtManagerInternal; import android.content.pm.dex.DexMetadataHelper; import android.content.pm.dex.ISnapshotRuntimeProfileCallback; import android.content.pm.dex.PackageOptimizationInfo; +import android.content.pm.parsing.AndroidPackage; import android.os.Binder; import android.os.Build; import android.os.Handler; @@ -390,9 +390,10 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { * - create the current primary profile to save time at app startup time. * - copy the profiles from the associated dex metadata file to the reference profile. */ - public void prepareAppProfiles(PackageParser.Package pkg, @UserIdInt int user, + public void prepareAppProfiles( + AndroidPackage pkg, @UserIdInt int user, boolean updateReferenceProfileContent) { - final int appId = UserHandle.getAppId(pkg.applicationInfo.uid); + final int appId = UserHandle.getAppId(pkg.getUid()); if (user < 0) { Slog.wtf(TAG, "Invalid user id: " + user); return; @@ -415,23 +416,24 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { dexMetadataPath = dexMetadata == null ? null : dexMetadata.getAbsolutePath(); } synchronized (mInstaller) { - boolean result = mInstaller.prepareAppProfile(pkg.packageName, user, appId, + boolean result = mInstaller.prepareAppProfile(pkg.getPackageName(), user, appId, profileName, codePath, dexMetadataPath); if (!result) { Slog.e(TAG, "Failed to prepare profile for " + - pkg.packageName + ":" + codePath); + pkg.getPackageName() + ":" + codePath); } } } } catch (InstallerException e) { - Slog.e(TAG, "Failed to prepare profile for " + pkg.packageName, e); + Slog.e(TAG, "Failed to prepare profile for " + pkg.getPackageName(), e); } } /** * Prepares the app profiles for a set of users. {@see ArtManagerService#prepareAppProfiles}. */ - public void prepareAppProfiles(PackageParser.Package pkg, int[] user, + public void prepareAppProfiles( + AndroidPackage pkg, int[] user, boolean updateReferenceProfileContent) { for (int i = 0; i < user.length; i++) { prepareAppProfiles(pkg, user[i], updateReferenceProfileContent); @@ -441,12 +443,12 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { /** * Clear the profiles for the given package. */ - public void clearAppProfiles(PackageParser.Package pkg) { + public void clearAppProfiles(AndroidPackage pkg) { try { ArrayMap<String, String> packageProfileNames = getPackageProfileNames(pkg); for (int i = packageProfileNames.size() - 1; i >= 0; i--) { String profileName = packageProfileNames.valueAt(i); - mInstaller.clearAppProfiles(pkg.packageName, profileName); + mInstaller.clearAppProfiles(pkg.getPackageName(), profileName); } } catch (InstallerException e) { Slog.w(TAG, String.valueOf(e)); @@ -456,15 +458,15 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { /** * Dumps the profiles for the given package. */ - public void dumpProfiles(PackageParser.Package pkg) { - final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); + public void dumpProfiles(AndroidPackage pkg) { + final int sharedGid = UserHandle.getSharedAppGid(pkg.getUid()); try { ArrayMap<String, String> packageProfileNames = getPackageProfileNames(pkg); for (int i = packageProfileNames.size() - 1; i >= 0; i--) { String codePath = packageProfileNames.keyAt(i); String profileName = packageProfileNames.valueAt(i); synchronized (mInstallLock) { - mInstaller.dumpProfiles(sharedGid, pkg.packageName, profileName, codePath); + mInstaller.dumpProfiles(sharedGid, pkg.getPackageName(), profileName, codePath); } } } catch (InstallerException e) { @@ -475,14 +477,13 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { /** * Compile layout resources in a given package. */ - public boolean compileLayouts(PackageParser.Package pkg) { + public boolean compileLayouts(AndroidPackage pkg) { try { - final String packageName = pkg.packageName; - final String apkPath = pkg.baseCodePath; - final ApplicationInfo appInfo = pkg.applicationInfo; - final String outDexFile = appInfo.dataDir + "/code_cache/compiled_view.dex"; - if (appInfo.isPrivilegedApp() || appInfo.isEmbeddedDexUsed() - || appInfo.isDefaultToDeviceProtectedStorage()) { + final String packageName = pkg.getPackageName(); + final String apkPath = pkg.getBaseCodePath(); + final String outDexFile = pkg.getDataDir() + "/code_cache/compiled_view.dex"; + if (pkg.isPrivileged() || pkg.isEmbeddedDexUsed() + || pkg.isDefaultToDeviceProtectedStorage()) { // Privileged apps prefer to load trusted code so they don't use compiled views. // If the app is not privileged but prefers code integrity, also avoid compiling // views. @@ -496,7 +497,7 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { try { synchronized (mInstallLock) { return mInstaller.compileLayouts(apkPath, packageName, outDexFile, - appInfo.uid); + pkg.getUid()); } } finally { Binder.restoreCallingIdentity(callingId); @@ -512,15 +513,19 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { * Build the profiles names for all the package code paths (excluding resource only paths). * Return the map [code path -> profile name]. */ - private ArrayMap<String, String> getPackageProfileNames(PackageParser.Package pkg) { + private ArrayMap<String, String> getPackageProfileNames(AndroidPackage pkg) { ArrayMap<String, String> result = new ArrayMap<>(); - if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0) { - result.put(pkg.baseCodePath, ArtManager.getProfileName(null)); + if ((pkg.getFlags() & ApplicationInfo.FLAG_HAS_CODE) != 0) { + result.put(pkg.getBaseCodePath(), ArtManager.getProfileName(null)); } - if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { - for (int i = 0; i < pkg.splitCodePaths.length; i++) { - if ((pkg.splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) { - result.put(pkg.splitCodePaths[i], ArtManager.getProfileName(pkg.splitNames[i])); + + String[] splitCodePaths = pkg.getSplitCodePaths(); + int[] splitFlags = pkg.getSplitFlags(); + String[] splitNames = pkg.getSplitNames(); + if (!ArrayUtils.isEmpty(splitCodePaths)) { + for (int i = 0; i < splitCodePaths.length; i++) { + if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) { + result.put(splitCodePaths[i], ArtManager.getProfileName(splitNames[i])); } } } diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java index 41dcaa59047b..29183bb78f07 100644 --- a/services/core/java/com/android/server/pm/dex/DexManager.java +++ b/services/core/java/com/android/server/pm/dex/DexManager.java @@ -588,7 +588,7 @@ public class DexManager { // We found the package. Now record the usage for all declared ISAs. boolean update = false; - for (String isa : getAppDexInstructionSets(info)) { + for (String isa : getAppDexInstructionSets(info.primaryCpuAbi, info.secondaryCpuAbi)) { boolean newUpdate = mPackageDexUsage.record(searchResult.mOwningPackageName, dexPath, userId, isa, isUsedByOtherApps, /*primaryOrSplit*/ false, searchResult.mOwningPackageName, diff --git a/services/core/java/com/android/server/pm/dex/DexoptUtils.java b/services/core/java/com/android/server/pm/dex/DexoptUtils.java index 5a473c1819c1..6e6b137d23a2 100644 --- a/services/core/java/com/android/server/pm/dex/DexoptUtils.java +++ b/services/core/java/com/android/server/pm/dex/DexoptUtils.java @@ -18,10 +18,12 @@ package com.android.server.pm.dex; import android.content.pm.ApplicationInfo; import android.content.pm.SharedLibraryInfo; +import android.content.pm.parsing.AndroidPackage; import android.util.Slog; import android.util.SparseArray; import com.android.internal.os.ClassLoaderFactory; +import com.android.internal.util.ArrayUtils; import java.io.File; import java.util.List; @@ -66,7 +68,7 @@ public final class DexoptUtils { * {@link android.app.LoadedApk#makePaths( * android.app.ActivityThread, boolean, ApplicationInfo, List, List)}. */ - public static String[] getClassLoaderContexts(ApplicationInfo info, + public static String[] getClassLoaderContexts(AndroidPackage pkg, List<SharedLibraryInfo> sharedLibraries, boolean[] pathsWithCode) { // The base class loader context contains only the shared library. String sharedLibrariesContext = ""; @@ -75,8 +77,8 @@ public final class DexoptUtils { } String baseApkContextClassLoader = encodeClassLoader( - "", info.classLoaderName, sharedLibrariesContext); - if (info.getSplitCodePaths() == null) { + "", pkg.getAppInfoClassLoaderName(), sharedLibrariesContext); + if (pkg.getSplitCodePaths() == null) { // The application has no splits. return new String[] {baseApkContextClassLoader}; } @@ -84,11 +86,11 @@ public final class DexoptUtils { // The application has splits. Compute their class loader contexts. // First, cache the relative paths of the splits and do some sanity checks - String[] splitRelativeCodePaths = getSplitRelativeCodePaths(info); + String[] splitRelativeCodePaths = getSplitRelativeCodePaths(pkg); // The splits have an implicit dependency on the base apk. // This means that we have to add the base apk file in addition to the shared libraries. - String baseApkName = new File(info.getBaseCodePath()).getName(); + String baseApkName = new File(pkg.getBaseCodePath()).getName(); String baseClassPath = baseApkName; // The result is stored in classLoaderContexts. @@ -97,7 +99,11 @@ public final class DexoptUtils { String[] classLoaderContexts = new String[/*base apk*/ 1 + splitRelativeCodePaths.length]; classLoaderContexts[0] = pathsWithCode[0] ? baseApkContextClassLoader : null; - if (!info.requestsIsolatedSplitLoading() || info.splitDependencies == null) { + SparseArray<int[]> splitDependencies = pkg.getSplitDependencies(); + + if (!pkg.requestsIsolatedSplitLoading() + || splitDependencies == null + || splitDependencies.size() == 0) { // If the app didn't request for the splits to be loaded in isolation or if it does not // declare inter-split dependencies, then all the splits will be loaded in the base // apk class loader (in the order of their definition). @@ -105,7 +111,7 @@ public final class DexoptUtils { for (int i = 1; i < classLoaderContexts.length; i++) { if (pathsWithCode[i]) { classLoaderContexts[i] = encodeClassLoader( - classpath, info.classLoaderName, sharedLibrariesContext); + classpath, pkg.getAppInfoClassLoaderName(), sharedLibrariesContext); } else { classLoaderContexts[i] = null; } @@ -132,11 +138,10 @@ public final class DexoptUtils { String[] splitClassLoaderEncodingCache = new String[splitRelativeCodePaths.length]; for (int i = 0; i < splitRelativeCodePaths.length; i++) { splitClassLoaderEncodingCache[i] = encodeClassLoader(splitRelativeCodePaths[i], - info.splitClassLoaderNames[i]); + pkg.getSplitClassLoaderNames()[i]); } String splitDependencyOnBase = encodeClassLoader( - baseClassPath, info.classLoaderName); - SparseArray<int[]> splitDependencies = info.splitDependencies; + baseClassPath, pkg.getClassLoaderName()); // Note that not all splits have dependencies (e.g. configuration splits) // The splits without dependencies will have classLoaderContexts[config_split_index] @@ -154,7 +159,8 @@ public final class DexoptUtils { // We also need to add the class loader of the current split which should // come first in the context. for (int i = 1; i < classLoaderContexts.length; i++) { - String splitClassLoader = encodeClassLoader("", info.splitClassLoaderNames[i - 1]); + String splitClassLoader = encodeClassLoader("", + pkg.getSplitClassLoaderNames()[i - 1]); if (pathsWithCode[i]) { // If classLoaderContexts[i] is null it means that the split does not have // any dependency. In this case its context equals its declared class loader. @@ -394,11 +400,11 @@ public final class DexoptUtils { * Returns the relative paths of the splits declared by the application {@code info}. * Assumes that the application declares a non-null array of splits. */ - private static String[] getSplitRelativeCodePaths(ApplicationInfo info) { - String baseCodePath = new File(info.getBaseCodePath()).getParent(); - String[] splitCodePaths = info.getSplitCodePaths(); - String[] splitRelativeCodePaths = new String[splitCodePaths.length]; - for (int i = 0; i < splitCodePaths.length; i++) { + private static String[] getSplitRelativeCodePaths(AndroidPackage pkg) { + String baseCodePath = new File(pkg.getBaseCodePath()).getParent(); + String[] splitCodePaths = pkg.getSplitCodePaths(); + String[] splitRelativeCodePaths = new String[ArrayUtils.size(splitCodePaths)]; + for (int i = 0; i < splitRelativeCodePaths.length; i++) { File pathFile = new File(splitCodePaths[i]); splitRelativeCodePaths[i] = pathFile.getName(); // Sanity check that the base paths of the splits are all the same. diff --git a/services/core/java/com/android/server/pm/dex/ViewCompiler.java b/services/core/java/com/android/server/pm/dex/ViewCompiler.java index 8d8e17e92b3d..b7443f36e494 100644 --- a/services/core/java/com/android/server/pm/dex/ViewCompiler.java +++ b/services/core/java/com/android/server/pm/dex/ViewCompiler.java @@ -16,10 +16,10 @@ package com.android.server.pm.dex; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageParser; +import android.content.pm.parsing.AndroidPackage; import android.os.Binder; import android.util.Log; + import com.android.internal.annotations.GuardedBy; import com.android.server.pm.Installer; @@ -33,19 +33,18 @@ public class ViewCompiler { mInstaller = installer; } - public boolean compileLayouts(PackageParser.Package pkg) { + public boolean compileLayouts(AndroidPackage pkg) { try { - final String packageName = pkg.packageName; - final String apkPath = pkg.baseCodePath; - final ApplicationInfo appInfo = pkg.applicationInfo; - final String outDexFile = appInfo.dataDir + "/code_cache/compiled_view.dex"; + final String packageName = pkg.getPackageName(); + final String apkPath = pkg.getBaseCodePath(); + final String outDexFile = pkg.getDataDir() + "/code_cache/compiled_view.dex"; Log.i("PackageManager", "Compiling layouts in " + packageName + " (" + apkPath + ") to " + outDexFile); long callingId = Binder.clearCallingIdentity(); try { synchronized (mInstallLock) { return mInstaller.compileLayouts(apkPath, packageName, outDexFile, - appInfo.uid); + pkg.getUid()); } } finally { Binder.restoreCallingIdentity(callingId); diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java index c39dcfefb2e8..cc70aa76de15 100644 --- a/services/core/java/com/android/server/pm/permission/BasePermission.java +++ b/services/core/java/com/android/server/pm/permission/BasePermission.java @@ -29,10 +29,12 @@ import static com.android.server.pm.Settings.TAG_ITEM; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; -import android.content.pm.PackageParser; -import android.content.pm.PackageParser.Permission; +import android.content.pm.PackageManagerInternal; import android.content.pm.PermissionInfo; import android.content.pm.Signature; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.ComponentParseUtils.ParsedPermission; +import android.content.pm.parsing.PackageInfoUtils; import android.os.UserHandle; import android.util.Log; import android.util.Slog; @@ -89,7 +91,7 @@ public final class BasePermission { int protectionLevel; - PackageParser.Permission perm; + ParsedPermission perm; PermissionInfo pendingPermissionInfo; @@ -113,12 +115,6 @@ public final class BasePermission { protectionLevel = PermissionInfo.PROTECTION_SIGNATURE; } - @Override - public String toString() { - return "BasePermission{" + Integer.toHexString(System.identityHashCode(this)) + " " + name - + "}"; - } - public String getName() { return name; } @@ -144,7 +140,7 @@ public final class BasePermission { this.gids = gids; this.perUser = perUser; } - public void setPermission(@Nullable Permission perm) { + public void setPermission(@Nullable ParsedPermission perm) { this.perm = perm; } public void setSourcePackageSetting(PackageSettingBase sourcePackageSetting) { @@ -165,13 +161,13 @@ public final class BasePermission { public int calculateFootprint(BasePermission perm) { if (uid == perm.uid) { - return perm.name.length() + perm.perm.info.calculateFootprint(); + return perm.name.length() + perm.perm.calculateFootprint(); } return 0; } - public boolean isPermission(Permission perm) { - return this.perm == perm; + public boolean isPermission(ParsedPermission perm) { + return Objects.equals(this.perm.className, perm.className); } public boolean isDynamic() { @@ -189,29 +185,24 @@ public final class BasePermission { } public boolean isRemoved() { - return perm != null && perm.info != null - && (perm.info.flags & PermissionInfo.FLAG_REMOVED) != 0; + return perm != null && (perm.flags & PermissionInfo.FLAG_REMOVED) != 0; } public boolean isSoftRestricted() { - return perm != null && perm.info != null - && (perm.info.flags & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0; + return perm != null && (perm.flags & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0; } public boolean isHardRestricted() { - return perm != null && perm.info != null - && (perm.info.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0; + return perm != null && (perm.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0; } public boolean isHardOrSoftRestricted() { - return perm != null && perm.info != null - && (perm.info.flags & (PermissionInfo.FLAG_HARD_RESTRICTED + return perm != null && (perm.flags & (PermissionInfo.FLAG_HARD_RESTRICTED | PermissionInfo.FLAG_SOFT_RESTRICTED)) != 0; } public boolean isImmutablyRestricted() { - return perm != null && perm.info != null - && (perm.info.flags & PermissionInfo.FLAG_IMMUTABLY_RESTRICTED) != 0; + return perm != null && (perm.flags & PermissionInfo.FLAG_IMMUTABLY_RESTRICTED) != 0; } public boolean isSignature() { @@ -300,13 +291,12 @@ public final class BasePermission { (this.protectionLevel != protectionLevel || perm == null || uid != tree.uid - || !perm.owner.equals(tree.perm.owner) - || !comparePermissionInfos(perm.info, info)); + || !Objects.equals(perm.getPackageName(), tree.perm.getPackageName()) + || !comparePermissionInfos(perm, info)); this.protectionLevel = protectionLevel; info = new PermissionInfo(info); info.protectionLevel = protectionLevel; - perm = new PackageParser.Permission(tree.perm.owner, info); - perm.info.packageName = tree.perm.info.packageName; + perm = new ParsedPermission(tree.perm); uid = tree.uid; return changed; } @@ -319,71 +309,89 @@ public final class BasePermission { final BasePermission tree = findPermissionTree(permissionTrees, name); if (tree != null && tree.perm != null) { sourcePackageSetting = tree.sourcePackageSetting; - perm = new PackageParser.Permission(tree.perm.owner, - new PermissionInfo(pendingPermissionInfo)); - perm.info.packageName = tree.perm.info.packageName; - perm.info.name = name; + perm = new ParsedPermission(tree.perm); + perm.protectionLevel = pendingPermissionInfo.protectionLevel; + perm.flags = pendingPermissionInfo.flags; + perm.setGroup(pendingPermissionInfo.group); + perm.backgroundPermission = pendingPermissionInfo.backgroundPermission; + perm.descriptionRes = pendingPermissionInfo.descriptionRes; + perm.requestRes = pendingPermissionInfo.requestRes; + perm.setPackageName(tree.perm.getPackageName()); + perm.setName(name); uid = tree.uid; } } } - static BasePermission createOrUpdate(@Nullable BasePermission bp, @NonNull Permission p, - @NonNull PackageParser.Package pkg, Collection<BasePermission> permissionTrees, + static BasePermission createOrUpdate(PackageManagerInternal packageManagerInternal, + @Nullable BasePermission bp, @NonNull ParsedPermission p, + @NonNull AndroidPackage pkg, Collection<BasePermission> permissionTrees, boolean chatty) { - final PackageSettingBase pkgSetting = (PackageSettingBase) pkg.mExtras; + final PackageSettingBase pkgSetting = + (PackageSettingBase) packageManagerInternal.getPackageSetting(pkg.getPackageName()); // Allow system apps to redefine non-system permissions - if (bp != null && !Objects.equals(bp.sourcePackageName, p.info.packageName)) { - final boolean currentOwnerIsSystem = (bp.perm != null - && bp.perm.owner.isSystem()); - if (p.owner.isSystem()) { + if (bp != null && !Objects.equals(bp.sourcePackageName, p.getPackageName())) { + final boolean currentOwnerIsSystem; + if (bp.perm == null) { + currentOwnerIsSystem = false; + } else { + AndroidPackage currentPackage = packageManagerInternal.getPackage( + bp.perm.getPackageName()); + if (currentPackage == null) { + currentOwnerIsSystem = false; + } else { + currentOwnerIsSystem = currentPackage.isSystem(); + } + } + + if (pkg.isSystem()) { if (bp.type == BasePermission.TYPE_BUILTIN && bp.perm == null) { // It's a built-in permission and no owner, take ownership now + p.flags |= PermissionInfo.FLAG_INSTALLED; bp.sourcePackageSetting = pkgSetting; bp.perm = p; - bp.uid = pkg.applicationInfo.uid; - bp.sourcePackageName = p.info.packageName; - p.info.flags |= PermissionInfo.FLAG_INSTALLED; + bp.uid = pkg.getUid(); + bp.sourcePackageName = p.getPackageName(); } else if (!currentOwnerIsSystem) { - String msg = "New decl " + p.owner + " of permission " - + p.info.name + " is system; overriding " + bp.sourcePackageName; + String msg = "New decl " + pkg + " of permission " + + p.getName() + " is system; overriding " + bp.sourcePackageName; PackageManagerService.reportSettingsProblem(Log.WARN, msg); bp = null; } } } if (bp == null) { - bp = new BasePermission(p.info.name, p.info.packageName, TYPE_NORMAL); + bp = new BasePermission(p.getName(), p.getPackageName(), TYPE_NORMAL); } StringBuilder r = null; if (bp.perm == null) { if (bp.sourcePackageName == null - || bp.sourcePackageName.equals(p.info.packageName)) { - final BasePermission tree = findPermissionTree(permissionTrees, p.info.name); + || bp.sourcePackageName.equals(p.getPackageName())) { + final BasePermission tree = findPermissionTree(permissionTrees, p.getName()); if (tree == null - || tree.sourcePackageName.equals(p.info.packageName)) { + || tree.sourcePackageName.equals(p.getPackageName())) { + p.flags |= PermissionInfo.FLAG_INSTALLED; bp.sourcePackageSetting = pkgSetting; bp.perm = p; - bp.uid = pkg.applicationInfo.uid; - bp.sourcePackageName = p.info.packageName; - p.info.flags |= PermissionInfo.FLAG_INSTALLED; + bp.uid = pkg.getUid(); + bp.sourcePackageName = p.getPackageName(); if (chatty) { if (r == null) { r = new StringBuilder(256); } else { r.append(' '); } - r.append(p.info.name); + r.append(p.getName()); } } else { - Slog.w(TAG, "Permission " + p.info.name + " from package " - + p.info.packageName + " ignored: base tree " + Slog.w(TAG, "Permission " + p.getName() + " from package " + + p.getPackageName() + " ignored: base tree " + tree.name + " is from package " + tree.sourcePackageName); } } else { - Slog.w(TAG, "Permission " + p.info.name + " from package " - + p.info.packageName + " ignored: original from " + Slog.w(TAG, "Permission " + p.getName() + " from package " + + p.getPackageName() + " ignored: original from " + bp.sourcePackageName); } } else if (chatty) { @@ -393,10 +401,10 @@ public final class BasePermission { r.append(' '); } r.append("DUP:"); - r.append(p.info.name); + r.append(p.getName()); } - if (bp.perm == p) { - bp.protectionLevel = p.info.protectionLevel; + if (bp.perm != null && Objects.equals(bp.perm.className, p.className)) { + bp.protectionLevel = p.protectionLevel; } if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) { Log.d(TAG, " Permissions: " + r); @@ -420,17 +428,17 @@ public final class BasePermission { throw new SecurityException("No permission tree found for " + permName); } - public void enforceDeclaredUsedAndRuntimeOrDevelopment(PackageParser.Package pkg) { - final PackageSetting pkgSetting = (PackageSetting) pkg.mExtras; + public void enforceDeclaredUsedAndRuntimeOrDevelopment(AndroidPackage pkg, + PackageSetting pkgSetting) { final PermissionsState permsState = pkgSetting.getPermissionsState(); - int index = pkg.requestedPermissions.indexOf(name); + int index = pkg.getRequestedPermissions().indexOf(name); if (!permsState.hasRequestedPermission(name) && index == -1) { - throw new SecurityException("Package " + pkg.packageName + throw new SecurityException("Package " + pkg.getPackageName() + " has not requested permission " + name); } if (!isRuntime() && !isDevelopment()) { - throw new SecurityException("Permission " + name - + " requested by " + pkg.packageName + " is not a changeable permission type"); + throw new SecurityException("Permission " + name + " requested by " + + pkg.getPackageName() + " is not a changeable permission type"); } } @@ -448,12 +456,12 @@ public final class BasePermission { public @Nullable PermissionInfo generatePermissionInfo(@NonNull String groupName, int flags) { if (groupName == null) { - if (perm == null || perm.info.group == null) { + if (perm == null || perm.getGroup() == null) { return generatePermissionInfo(protectionLevel, flags); } } else { - if (perm != null && groupName.equals(perm.info.group)) { - return PackageParser.generatePermissionInfo(perm, flags); + if (perm != null && groupName.equals(perm.getGroup())) { + return PackageInfoUtils.generatePermissionInfo(perm, flags); } } return null; @@ -463,8 +471,8 @@ public final class BasePermission { PermissionInfo permissionInfo; if (perm != null) { final boolean protectionLevelChanged = protectionLevel != adjustedProtectionLevel; - permissionInfo = PackageParser.generatePermissionInfo(perm, flags); - if (protectionLevelChanged && permissionInfo == perm.info) { + permissionInfo = PackageInfoUtils.generatePermissionInfo(perm, flags); + if (protectionLevelChanged) { // if we return different protection level, don't use the cached info permissionInfo = new PermissionInfo(permissionInfo); permissionInfo.protectionLevel = adjustedProtectionLevel; @@ -544,14 +552,18 @@ public final class BasePermission { serializer.attribute(null, "protection", Integer.toString(protectionLevel)); } if (type == BasePermission.TYPE_DYNAMIC) { - final PermissionInfo pi = perm != null ? perm.info : pendingPermissionInfo; - if (pi != null) { + if (perm != null || pendingPermissionInfo != null) { serializer.attribute(null, "type", "dynamic"); - if (pi.icon != 0) { - serializer.attribute(null, "icon", Integer.toString(pi.icon)); + int icon = perm != null ? perm.icon : pendingPermissionInfo.icon; + CharSequence nonLocalizedLabel = perm != null + ? perm.nonLocalizedLabel + : pendingPermissionInfo.nonLocalizedLabel; + + if (icon != 0) { + serializer.attribute(null, "icon", Integer.toString(icon)); } - if (pi.nonLocalizedLabel != null) { - serializer.attribute(null, "label", pi.nonLocalizedLabel.toString()); + if (nonLocalizedLabel != null) { + serializer.attribute(null, "label", nonLocalizedLabel.toString()); } } } @@ -571,14 +583,14 @@ public final class BasePermission { return s1.equals(s2); } - private static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) { + private static boolean comparePermissionInfos(ParsedPermission pi1, PermissionInfo pi2) { if (pi1.icon != pi2.icon) return false; if (pi1.logo != pi2.logo) return false; if (pi1.protectionLevel != pi2.protectionLevel) return false; - if (!compareStrings(pi1.name, pi2.name)) return false; + if (!compareStrings(pi1.getName(), pi2.name)) return false; if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false; // We'll take care of setting this one. - if (!compareStrings(pi1.packageName, pi2.packageName)) return false; + if (!compareStrings(pi1.getPackageName(), pi2.packageName)) return false; // These are not currently stored in settings. //if (!compareStrings(pi1.group, pi2.group)) return false; //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false; @@ -614,9 +626,9 @@ public final class BasePermission { pw.println(PermissionInfo.protectionToString(protectionLevel)); if (perm != null) { pw.print(" perm="); pw.println(perm); - if ((perm.info.flags & PermissionInfo.FLAG_INSTALLED) == 0 - || (perm.info.flags & PermissionInfo.FLAG_REMOVED) != 0) { - pw.print(" flags=0x"); pw.println(Integer.toHexString(perm.info.flags)); + if ((perm.flags & PermissionInfo.FLAG_INSTALLED) == 0 + || (perm.flags & PermissionInfo.FLAG_REMOVED) != 0) { + pw.print(" flags=0x"); pw.println(Integer.toHexString(perm.flags)); } } if (sourcePackageSetting != null) { @@ -628,4 +640,20 @@ public final class BasePermission { } return true; } + + @Override + public String toString() { + return "BasePermission{" + + "name='" + name + '\'' + + ", type=" + type + + ", sourcePackageName='" + sourcePackageName + '\'' + + ", sourcePackageSetting=" + sourcePackageSetting + + ", protectionLevel=" + protectionLevel + + ", perm=" + perm + + ", pendingPermissionInfo=" + pendingPermissionInfo + + ", uid=" + uid + + ", gids=" + Arrays.toString(gids) + + ", perUser=" + perUser + + '}'; + } } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 2ffba45be4a3..369e7bb21773 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -63,10 +63,13 @@ import android.content.pm.PackageManager.PermissionInfoFlags; import android.content.pm.PackageManager.PermissionWhitelistFlags; import android.content.pm.PackageManagerInternal; import android.content.pm.PackageParser; -import android.content.pm.PackageParser.Package; import android.content.pm.ParceledListSlice; import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.ComponentParseUtils.ParsedPermission; +import android.content.pm.parsing.ComponentParseUtils.ParsedPermissionGroup; +import android.content.pm.parsing.PackageInfoUtils; import android.content.pm.permission.SplitPermissionInfoParcelable; import android.metrics.LogMaker; import android.os.Binder; @@ -419,7 +422,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } - @Nullable BasePermission getPermission(String permName) { + @Nullable + BasePermission getPermission(String permName) { synchronized (mLock) { return mSettings.getPermissionLocked(permName); } @@ -453,10 +457,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { } synchronized (mLock) { final int n = mSettings.mPermissionGroups.size(); - final ArrayList<PermissionGroupInfo> out = - new ArrayList<PermissionGroupInfo>(n); - for (PackageParser.PermissionGroup pg : mSettings.mPermissionGroups.values()) { - out.add(PackageParser.generatePermissionGroupInfo(pg, flags)); + final ArrayList<PermissionGroupInfo> out = new ArrayList<>(n); + for (ParsedPermissionGroup pg : mSettings.mPermissionGroups.values()) { + out.add(PackageInfoUtils.generatePermissionGroupInfo(pg, flags)); } return new ParceledListSlice<>(out); } @@ -472,7 +475,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { return null; } synchronized (mLock) { - return PackageParser.generatePermissionGroupInfo( + return PackageInfoUtils.generatePermissionGroupInfo( mSettings.mPermissionGroups.get(groupName), flags); } } @@ -596,8 +599,13 @@ public class PermissionManagerService extends IPermissionManager.Stub { false, // requirePermissionWhenSameUser "getPermissionFlags"); - final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName); - if (pkg == null || pkg.mExtras == null) { + final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName); + if (pkg == null) { + return 0; + } + final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( + pkg.getPackageName()); + if (ps == null) { return 0; } synchronized (mLock) { @@ -608,7 +616,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) { return 0; } - final PackageSetting ps = (PackageSetting) pkg.mExtras; PermissionsState permissionsState = ps.getPermissionsState(); return permissionsState.getPermissionFlags(permName, userId); } @@ -695,8 +702,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { flagValues &= ~PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION; } - final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName); - if (pkg == null || pkg.mExtras == null) { + final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName); + final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( + packageName); + if (pkg == null || ps == null) { Log.e(TAG, "Unknown package: " + packageName); return; } @@ -712,7 +721,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { throw new IllegalArgumentException("Unknown permission: " + permName); } - final PackageSetting ps = (PackageSetting) pkg.mExtras; final PermissionsState permissionsState = ps.getPermissionsState(); final boolean hadState = permissionsState.getRuntimePermissionState(permName, userId) != null; @@ -725,11 +733,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { // Install and runtime permissions are stored in different places, // so figure out what permission changed and persist the change. if (permissionsState.getInstallPermissionState(permName) != null) { - callback.onInstallPermissionUpdatedNotifyListener(pkg.applicationInfo.uid); + callback.onInstallPermissionUpdatedNotifyListener(pkg.getUid()); } else if (permissionsState.getRuntimePermissionState(permName, userId) != null || hadState) { - callback.onPermissionUpdatedNotifyListener(new int[] { userId }, false, - pkg.applicationInfo.uid); + callback.onPermissionUpdatedNotifyListener(new int[]{userId}, false, + pkg.getUid()); } } } @@ -761,18 +769,16 @@ public class PermissionManagerService extends IPermissionManager.Stub { ? flagValues : flagValues & ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED; final boolean[] changed = new boolean[1]; - mPackageManagerInt.forEachPackage(new Consumer<PackageParser.Package>() { - @Override - public void accept(Package pkg) { - final PackageSetting ps = (PackageSetting) pkg.mExtras; - if (ps == null) { - return; - } - final PermissionsState permissionsState = ps.getPermissionsState(); - changed[0] |= permissionsState.updatePermissionFlagsForAllPermissions( - userId, effectiveFlagMask, effectiveFlagValues); - mOnPermissionChangeListeners.onPermissionsChanged(pkg.applicationInfo.uid); + mPackageManagerInt.forEachPackage(pkg -> { + final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( + pkg.getPackageName()); + if (ps == null) { + return; } + final PermissionsState permissionsState = ps.getPermissionsState(); + changed[0] |= permissionsState.updatePermissionFlagsForAllPermissions( + userId, effectiveFlagMask, effectiveFlagValues); + mOnPermissionChangeListeners.onPermissionsChanged(pkg.getUid()); }); if (changed[0]) { @@ -812,7 +818,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { private int checkPermissionInternal(@NonNull Package pkg, boolean isPackageExplicit, @NonNull String permissionName, @UserIdInt int userId) { final int callingUid = getCallingUid(); - if (isPackageExplicit || pkg.mSharedUserId == null) { + if (isPackageExplicit || pkg.getSharedUserId() == null) { if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) { return PackageManager.PERMISSION_DENIED; } @@ -822,8 +828,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } - final int uid = UserHandle.getUid(userId, pkg.applicationInfo.uid); - final PackageSetting ps = (PackageSetting) pkg.mExtras; + final int uid = UserHandle.getUid(userId, pkg.getUid()); + final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( + pkg.getPackageName()); if (ps == null) { return PackageManager.PERMISSION_DENIED; } @@ -953,7 +960,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { "getWhitelistedRestrictedPermissions for user " + userId); } - final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName); + final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName); if (pkg == null) { return null; } @@ -986,7 +993,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { final long identity = Binder.clearCallingIdentity(); try { final PermissionsState permissionsState = - PackageManagerServiceUtils.getPermissionsState(pkg); + PackageManagerServiceUtils.getPermissionsState(mPackageManagerInt, pkg); if (permissionsState == null) { return null; } @@ -1004,9 +1011,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { ArrayList<String> whitelistedPermissions = null; - final int permissionCount = pkg.requestedPermissions.size(); + final int permissionCount = ArrayUtils.size(pkg.getRequestedPermissions()); for (int i = 0; i < permissionCount; i++) { - final String permissionName = pkg.requestedPermissions.get(i); + final String permissionName = pkg.getRequestedPermissions().get(i); final int currentFlags = permissionsState.getPermissionFlags(permissionName, userId); if ((currentFlags & queryFlags) != 0) { @@ -1103,7 +1110,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { "setWhitelistedRestrictedPermissions for user " + userId); } - final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName); + final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName); if (pkg == null) { return false; } @@ -1132,7 +1139,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS); } final List<String> whitelistedPermissions = - getWhitelistedRestrictedPermissions(pkg.packageName, flags, userId); + getWhitelistedRestrictedPermissions(pkg.getPackageName(), flags, userId); if (permissions == null || permissions.isEmpty()) { if (whitelistedPermissions == null || whitelistedPermissions.isEmpty()) { return true; @@ -1206,8 +1213,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { false, // requirePermissionWhenSameUser "grantRuntimePermission"); - final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName); - if (pkg == null || pkg.mExtras == null) { + final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName); + final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( + packageName); + if (pkg == null || ps == null) { Log.e(TAG, "Unknown package: " + packageName); return; } @@ -1222,21 +1231,19 @@ public class PermissionManagerService extends IPermissionManager.Stub { throw new IllegalArgumentException("Unknown package: " + packageName); } - bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg); + bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg, ps); // If a permission review is required for legacy apps we represent // their permissions as always granted runtime ones since we need // to keep the review required permission flag per user while an // install permission's state is shared across all users. - if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M + if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M && bp.isRuntime()) { return; } - final int uid = UserHandle.getUid(userId, - UserHandle.getAppId(pkg.applicationInfo.uid)); + final int uid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.getUid())); - final PackageSetting ps = (PackageSetting) pkg.mExtras; final PermissionsState permissionsState = ps.getPermissionsState(); final int flags = permissionsState.getPermissionFlags(permName, userId); @@ -1259,7 +1266,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { } if (bp.isSoftRestricted() && !SoftRestrictedPermissionPolicy.forPermission(mContext, - pkg.applicationInfo, UserHandle.of(userId), permName).mayGrantPermission()) { + pkg.toAppInfo(), UserHandle.of(userId), permName).mayGrantPermission()) { Log.e(TAG, "Cannot grant soft restricted permission " + permName + " for package " + packageName); return; @@ -1282,7 +1289,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { + permName + " for package " + packageName); } - if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { + if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M) { Slog.w(TAG, "Cannot grant runtime permission to a legacy app"); return; } @@ -1295,7 +1302,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: { if (callback != null) { - callback.onGidsChanged(UserHandle.getAppId(pkg.applicationInfo.uid), userId); + callback.onGidsChanged(UserHandle.getAppId(pkg.getUid()), userId); } } break; @@ -1368,8 +1375,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { false, // requirePermissionWhenSameUser "revokeRuntimePermission"); - final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName); - if (pkg == null || pkg.mExtras == null) { + final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName); + final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( + packageName); + if (pkg == null || ps == null) { Log.e(TAG, "Unknown package: " + packageName); return; } @@ -1381,18 +1390,17 @@ public class PermissionManagerService extends IPermissionManager.Stub { throw new IllegalArgumentException("Unknown permission: " + permName); } - bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg); + bp.enforceDeclaredUsedAndRuntimeOrDevelopment(pkg, ps); // If a permission review is required for legacy apps we represent // their permissions as always granted runtime ones since we need // to keep the review required permission flag per user while an // install permission's state is shared across all users. - if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M + if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M && bp.isRuntime()) { return; } - final PackageSetting ps = (PackageSetting) pkg.mExtras; final PermissionsState permissionsState = ps.getPermissionsState(); final int flags = permissionsState.getPermissionFlags(permName, userId); @@ -1435,7 +1443,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (callback != null) { callback.onPermissionRevoked(UserHandle.getUid(userId, - UserHandle.getAppId(pkg.applicationInfo.uid)), userId); + UserHandle.getAppId(pkg.getUid())), userId); } if (bp.isRuntime()) { @@ -1460,7 +1468,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { StorageManager.UUID_PRIVATE_INTERNAL, false, mDefaultPermissionCallback); for (final int userId : UserManagerService.getInstance().getUserIds()) { mPackageManagerInt.forEachPackage( - (PackageParser.Package pkg) -> resetRuntimePermissionsInternal(pkg, userId)); + (AndroidPackage pkg) -> resetRuntimePermissionsInternal(pkg, userId)); } } @@ -1471,9 +1479,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { * @param userId The device user for which to do a reset. */ @GuardedBy("mLock") - private void resetRuntimePermissionsInternal(final PackageParser.Package pkg, + private void resetRuntimePermissionsInternal(final AndroidPackage pkg, final int userId) { - final String packageName = pkg.packageName; + final String packageName = pkg.getPackageName(); // These are flags that can change base on user actions. final int userSettableMask = FLAG_PERMISSION_USER_SET @@ -1485,7 +1493,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { | FLAG_PERMISSION_POLICY_FIXED; // Delay and combine non-async permission callbacks - final int permissionCount = pkg.requestedPermissions.size(); + final int permissionCount = ArrayUtils.size(pkg.getRequestedPermissions()); final boolean[] permissionRemoved = new boolean[1]; final ArraySet<Long> revokedPermissions = new ArraySet<>(); final IntArray syncUpdatedUsers = new IntArray(permissionCount); @@ -1552,7 +1560,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { }; for (int i = 0; i < permissionCount; i++) { - final String permName = pkg.requestedPermissions.get(i); + final String permName = pkg.getRequestedPermissions().get(i); final BasePermission bp; synchronized (mLock) { bp = mSettings.getPermissionLocked(permName); @@ -1567,7 +1575,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { // If shared user we just reset the state to which only this app contributed. final String sharedUserId = - mPackageManagerInt.getSharedUserIdForPackage(pkg.packageName); + mPackageManagerInt.getSharedUserIdForPackage(pkg.getPackageName()); final String[] pkgNames = mPackageManagerInt.getPackagesForSharedUserId(sharedUserId, userId); if (pkgNames != null && pkgNames.length > 0) { @@ -1575,10 +1583,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { final int packageCount = pkgNames.length; for (int j = 0; j < packageCount; j++) { final String sharedPkgName = pkgNames[j]; - final PackageParser.Package sharedPkg = + final AndroidPackage sharedPkg = mPackageManagerInt.getPackage(sharedPkgName); - if (sharedPkg != null && !sharedPkg.packageName.equals(packageName) - && sharedPkg.requestedPermissions.contains(permName)) { + if (sharedPkg != null && !sharedPkg.getPackageName().equals(packageName) + && sharedPkg.getRequestedPermissions().contains(permName)) { used = true; break; } @@ -1999,15 +2007,16 @@ public class PermissionManagerService extends IPermissionManager.Stub { return protectionLevel; } // Normalize package name to handle renamed packages and static libs - final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName); + final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName); if (pkg == null) { return protectionLevel; } - if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.O) { + if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.O) { return protectionLevelMasked; } // Apps that target O see flags for all protection levels. - final PackageSetting ps = (PackageSetting) pkg.mExtras; + final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( + pkg.getPackageName()); if (ps == null) { return protectionLevel; } @@ -2028,35 +2037,35 @@ public class PermissionManagerService extends IPermissionManager.Stub { * @param permissionCallback Callback for permission changed */ private void revokeRuntimePermissionsIfGroupChanged( - @NonNull PackageParser.Package newPackage, - @NonNull PackageParser.Package oldPackage, + @NonNull AndroidPackage newPackage, + @NonNull AndroidPackage oldPackage, @NonNull ArrayList<String> allPackageNames, @NonNull PermissionCallback permissionCallback) { - final int numOldPackagePermissions = oldPackage.permissions.size(); + final int numOldPackagePermissions = ArrayUtils.size(oldPackage.getPermissions()); final ArrayMap<String, String> oldPermissionNameToGroupName = new ArrayMap<>(numOldPackagePermissions); for (int i = 0; i < numOldPackagePermissions; i++) { - final PackageParser.Permission permission = oldPackage.permissions.get(i); + final ParsedPermission permission = oldPackage.getPermissions().get(i); - if (permission.group != null) { - oldPermissionNameToGroupName.put(permission.info.name, - permission.group.info.name); + if (permission.parsedPermissionGroup != null) { + oldPermissionNameToGroupName.put(permission.getName(), + permission.parsedPermissionGroup.getName()); } } final int callingUid = Binder.getCallingUid(); - final int numNewPackagePermissions = newPackage.permissions.size(); + final int numNewPackagePermissions = ArrayUtils.size(newPackage.getPermissions()); for (int newPermissionNum = 0; newPermissionNum < numNewPackagePermissions; newPermissionNum++) { - final PackageParser.Permission newPermission = - newPackage.permissions.get(newPermissionNum); - final int newProtection = newPermission.info.getProtection(); + final ParsedPermission newPermission = + newPackage.getPermissions().get(newPermissionNum); + final int newProtection = newPermission.getProtection(); if ((newProtection & PermissionInfo.PROTECTION_DANGEROUS) != 0) { - final String permissionName = newPermission.info.name; - final String newPermissionGroupName = - newPermission.group == null ? null : newPermission.group.info.name; + final String permissionName = newPermission.getName(); + final String newPermissionGroupName = newPermission.parsedPermissionGroup == null + ? null : newPermission.parsedPermissionGroup.getName(); final String oldPermissionGroupName = oldPermissionNameToGroupName.get( permissionName); @@ -2074,7 +2083,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { userId); if (permissionState == PackageManager.PERMISSION_GRANTED) { EventLog.writeEvent(0x534e4554, "72710897", - newPackage.applicationInfo.uid, + newPackage.getUid(), "Revoking permission " + permissionName + " from package " + packageName + " as the group changed from " + oldPermissionGroupName + @@ -2095,54 +2104,56 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } - private void addAllPermissions(PackageParser.Package pkg, boolean chatty) { - final int N = pkg.permissions.size(); + private void addAllPermissions(AndroidPackage pkg, boolean chatty) { + final int N = ArrayUtils.size(pkg.getPermissions()); for (int i=0; i<N; i++) { - PackageParser.Permission p = pkg.permissions.get(i); + ParsedPermission p = pkg.getPermissions().get(i); // Assume by default that we did not install this permission into the system. - p.info.flags &= ~PermissionInfo.FLAG_INSTALLED; + p.flags &= ~PermissionInfo.FLAG_INSTALLED; synchronized (PermissionManagerService.this.mLock) { // Now that permission groups have a special meaning, we ignore permission // groups for legacy apps to prevent unexpected behavior. In particular, // permissions for one app being granted to someone just because they happen // to be in a group defined by another app (before this had no implications). - if (pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) { - p.group = mSettings.mPermissionGroups.get(p.info.group); + if (pkg.getTargetSdkVersion() > Build.VERSION_CODES.LOLLIPOP_MR1) { + p.parsedPermissionGroup = mSettings.mPermissionGroups.get(p.getGroup()); // Warn for a permission in an unknown group. if (DEBUG_PERMISSIONS - && p.info.group != null && p.group == null) { - Slog.i(TAG, "Permission " + p.info.name + " from package " - + p.info.packageName + " in an unknown group " + p.info.group); + && p.getGroup() != null && p.parsedPermissionGroup == null) { + Slog.i(TAG, "Permission " + p.getName() + " from package " + + p.getPackageName() + " in an unknown group " + p.getGroup()); } } if (p.tree) { final BasePermission bp = BasePermission.createOrUpdate( - mSettings.getPermissionTreeLocked(p.info.name), p, pkg, + mPackageManagerInt, + mSettings.getPermissionTreeLocked(p.getName()), p, pkg, mSettings.getAllPermissionTreesLocked(), chatty); - mSettings.putPermissionTreeLocked(p.info.name, bp); + mSettings.putPermissionTreeLocked(p.getName(), bp); } else { final BasePermission bp = BasePermission.createOrUpdate( - mSettings.getPermissionLocked(p.info.name), + mPackageManagerInt, + mSettings.getPermissionLocked(p.getName()), p, pkg, mSettings.getAllPermissionTreesLocked(), chatty); - mSettings.putPermissionLocked(p.info.name, bp); + mSettings.putPermissionLocked(p.getName(), bp); } } } } - private void addAllPermissionGroups(PackageParser.Package pkg, boolean chatty) { - final int N = pkg.permissionGroups.size(); + private void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) { + final int N = ArrayUtils.size(pkg.getPermissionGroups()); StringBuilder r = null; for (int i=0; i<N; i++) { - final PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i); - final PackageParser.PermissionGroup cur = mSettings.mPermissionGroups.get(pg.info.name); - final String curPackageName = (cur == null) ? null : cur.info.packageName; - final boolean isPackageUpdate = pg.info.packageName.equals(curPackageName); + final ParsedPermissionGroup pg = pkg.getPermissionGroups().get(i); + final ParsedPermissionGroup cur = mSettings.mPermissionGroups.get(pg.getName()); + final String curPackageName = (cur == null) ? null : cur.getPackageName(); + final boolean isPackageUpdate = pg.getPackageName().equals(curPackageName); if (cur == null || isPackageUpdate) { - mSettings.mPermissionGroups.put(pg.info.name, pg); + mSettings.mPermissionGroups.put(pg.getName(), pg); if (chatty && DEBUG_PACKAGE_SCANNING) { if (r == null) { r = new StringBuilder(256); @@ -2152,12 +2163,12 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (isPackageUpdate) { r.append("UPD:"); } - r.append(pg.info.name); + r.append(pg.getName()); } } else { - Slog.w(TAG, "Permission group " + pg.info.name + " from package " - + pg.info.packageName + " ignored: original from " - + cur.info.packageName); + Slog.w(TAG, "Permission group " + pg.getName() + " from package " + + pg.getPackageName() + " ignored: original from " + + cur.getPackageName()); if (chatty && DEBUG_PACKAGE_SCANNING) { if (r == null) { r = new StringBuilder(256); @@ -2165,7 +2176,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { r.append(' '); } r.append("DUP:"); - r.append(pg.info.name); + r.append(pg.getName()); } } } @@ -2175,15 +2186,15 @@ public class PermissionManagerService extends IPermissionManager.Stub { } - private void removeAllPermissions(PackageParser.Package pkg, boolean chatty) { + private void removeAllPermissions(AndroidPackage pkg, boolean chatty) { synchronized (mLock) { - int N = pkg.permissions.size(); + int N = ArrayUtils.size(pkg.getPermissions()); StringBuilder r = null; for (int i=0; i<N; i++) { - PackageParser.Permission p = pkg.permissions.get(i); - BasePermission bp = (BasePermission) mSettings.mPermissions.get(p.info.name); + ParsedPermission p = pkg.getPermissions().get(i); + BasePermission bp = mSettings.mPermissions.get(p.getName()); if (bp == null) { - bp = mSettings.mPermissionTrees.get(p.info.name); + bp = mSettings.mPermissionTrees.get(p.getName()); } if (bp != null && bp.isPermission(p)) { bp.setPermission(null); @@ -2193,14 +2204,14 @@ public class PermissionManagerService extends IPermissionManager.Stub { } else { r.append(' '); } - r.append(p.info.name); + r.append(p.getName()); } } if (p.isAppOp()) { ArraySet<String> appOpPkgs = - mSettings.mAppOpPermissionPackages.get(p.info.name); + mSettings.mAppOpPermissionPackages.get(p.getName()); if (appOpPkgs != null) { - appOpPkgs.remove(pkg.packageName); + appOpPkgs.remove(pkg.getPackageName()); } } } @@ -2208,14 +2219,14 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (DEBUG_REMOVE) Log.d(TAG, " Permissions: " + r); } - N = pkg.requestedPermissions.size(); + N = pkg.getRequestedPermissions().size(); r = null; for (int i=0; i<N; i++) { - String perm = pkg.requestedPermissions.get(i); + String perm = pkg.getRequestedPermissions().get(i); if (mSettings.isPermissionAppOp(perm)) { ArraySet<String> appOpPkgs = mSettings.mAppOpPermissionPackages.get(perm); if (appOpPkgs != null) { - appOpPkgs.remove(pkg.packageName); + appOpPkgs.remove(pkg.getPackageName()); if (appOpPkgs.isEmpty()) { mSettings.mAppOpPermissionPackages.remove(perm); } @@ -2244,7 +2255,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { * @param packageOfInterest If this is the name of {@code pkg} add extra logging * @param callback Result call back */ - private void restorePermissionState(@NonNull PackageParser.Package pkg, boolean replace, + private void restorePermissionState(@NonNull AndroidPackage pkg, boolean replace, @Nullable String packageOfInterest, @Nullable PermissionCallback callback) { // IMPORTANT: There are two types of permissions: install and runtime. // Install time permissions are granted when the app is installed to @@ -2257,7 +2268,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { // being upgraded to target a newer SDK, in which case dangerous permissions // are transformed from install time to runtime ones. - final PackageSetting ps = (PackageSetting) pkg.mExtras; + final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( + pkg.getPackageName()); if (ps == null) { return; } @@ -2298,23 +2310,25 @@ public class PermissionManagerService extends IPermissionManager.Stub { synchronized (mLock) { ArraySet<String> newImplicitPermissions = new ArraySet<>(); - final int N = pkg.requestedPermissions.size(); + final int N = pkg.getRequestedPermissions().size(); for (int i = 0; i < N; i++) { - final String permName = pkg.requestedPermissions.get(i); + final String permName = pkg.getRequestedPermissions().get(i); final BasePermission bp = mSettings.getPermissionLocked(permName); final boolean appSupportsRuntimePermissions = - pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M; + pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M; String upgradedActivityRecognitionPermission = null; if (DEBUG_INSTALL) { - Log.i(TAG, "Package " + pkg.packageName + " checking " + permName + ": " + bp); + Log.i(TAG, "Package " + pkg.getPackageName() + + " checking " + permName + ": " + bp); } if (bp == null || bp.getSourcePackageSetting() == null) { - if (packageOfInterest == null || packageOfInterest.equals(pkg.packageName)) { + if (packageOfInterest == null || packageOfInterest.equals( + pkg.getPackageName())) { if (DEBUG_PERMISSIONS) { Slog.i(TAG, "Unknown permission " + permName - + " in package " + pkg.packageName); + + " in package " + pkg.getPackageName()); } } continue; @@ -2323,14 +2337,14 @@ public class PermissionManagerService extends IPermissionManager.Stub { // Cache newImplicitPermissions before modifing permissionsState as for the shared // uids the original and new state are the same object if (!origPermissions.hasRequestedPermission(permName) - && (pkg.implicitPermissions.contains(permName) + && (pkg.getImplicitPermissions().contains(permName) || (permName.equals(Manifest.permission.ACTIVITY_RECOGNITION)))) { - if (pkg.implicitPermissions.contains(permName)) { + if (pkg.getImplicitPermissions().contains(permName)) { // If permName is an implicit permission, try to auto-grant newImplicitPermissions.add(permName); if (DEBUG_PERMISSIONS) { - Slog.i(TAG, permName + " is newly added for " + pkg.packageName); + Slog.i(TAG, permName + " is newly added for " + pkg.getPackageName()); } } else { // Special case for Activity Recognition permission. Even if AR permission @@ -2353,7 +2367,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (DEBUG_PERMISSIONS) { Slog.i(TAG, permName + " is newly added for " - + pkg.packageName); + + pkg.getPackageName()); } break; } @@ -2362,10 +2376,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { } // Limit ephemeral apps to ephemeral allowed permissions. - if (pkg.applicationInfo.isInstantApp() && !bp.isInstant()) { + if (pkg.isInstantApp() && !bp.isInstant()) { if (DEBUG_PERMISSIONS) { Log.i(TAG, "Denying non-ephemeral permission " + bp.getName() - + " for package " + pkg.packageName); + + " for package " + pkg.getPackageName()); } continue; } @@ -2373,7 +2387,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (bp.isRuntimeOnly() && !appSupportsRuntimePermissions) { if (DEBUG_PERMISSIONS) { Log.i(TAG, "Denying runtime-only permission " + bp.getName() - + " for package " + pkg.packageName); + + " for package " + pkg.getPackageName()); } continue; } @@ -2384,7 +2398,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { // Keep track of app op permissions. if (bp.isAppOp()) { - mSettings.addAppOpPackage(perm, pkg.packageName); + mSettings.addAppOpPackage(perm, pkg.getPackageName()); } if (bp.isNormal()) { @@ -2410,7 +2424,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (DEBUG_PERMISSIONS) { Slog.i(TAG, "Considering granting permission " + perm + " to package " - + pkg.packageName); + + pkg.getPackageName()); } if (grant != GRANT_DENIED) { @@ -2696,10 +2710,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { default: { if (packageOfInterest == null - || packageOfInterest.equals(pkg.packageName)) { + || packageOfInterest.equals(pkg.getPackageName())) { if (DEBUG_PERMISSIONS) { Slog.i(TAG, "Not granting permission " + perm - + " to package " + pkg.packageName + + " to package " + pkg.getPackageName() + " because it was previously installed without"); } } @@ -2714,9 +2728,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { changedInstallPermission = true; if (DEBUG_PERMISSIONS) { Slog.i(TAG, "Un-granting permission " + perm - + " from package " + pkg.packageName + + " from package " + pkg.getPackageName() + " (protectionLevel=" + bp.getProtectionLevel() - + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags) + + " flags=0x" + Integer.toHexString(pkg.getFlags()) + ")"); } } else if (bp.isAppOp()) { @@ -2724,11 +2738,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { // not to be granted, there is a UI for the user to decide. if (DEBUG_PERMISSIONS && (packageOfInterest == null - || packageOfInterest.equals(pkg.packageName))) { + || packageOfInterest.equals(pkg.getPackageName()))) { Slog.i(TAG, "Not granting permission " + perm - + " to package " + pkg.packageName + + " to package " + pkg.getPackageName() + " (protectionLevel=" + bp.getProtectionLevel() - + " flags=0x" + Integer.toHexString(pkg.applicationInfo.flags) + + " flags=0x" + Integer.toHexString(pkg.getFlags()) + ")"); } } @@ -2758,7 +2772,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { } for (int userId : updatedUserIds) { - notifyRuntimePermissionStateChanged(pkg.packageName, userId); + notifyRuntimePermissionStateChanged(pkg.getPackageName(), userId); } } @@ -2774,10 +2788,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { * @return The updated value of the {@code updatedUserIds} parameter */ private @NonNull int[] revokePermissionsNoLongerImplicitLocked( - @NonNull PermissionsState ps, @NonNull PackageParser.Package pkg, + @NonNull PermissionsState ps, @NonNull AndroidPackage pkg, @NonNull int[] updatedUserIds) { - String pkgName = pkg.packageName; - boolean supportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion + String pkgName = pkg.getPackageName(); + boolean supportsRuntimePermissions = pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M; int[] users = UserManagerService.getInstance().getUserIds(); @@ -2786,7 +2800,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { int userId = users[i]; for (String permission : ps.getPermissions(userId)) { - if (!pkg.implicitPermissions.contains(permission)) { + if (!pkg.getImplicitPermissions().contains(permission)) { if (!ps.hasInstallPermission(permission)) { int flags = ps.getRuntimePermissionState(permission, userId).getFlags(); @@ -2836,9 +2850,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { */ private void inheritPermissionStateToNewImplicitPermissionLocked( @NonNull ArraySet<String> sourcePerms, @NonNull String newPerm, - @NonNull PermissionsState ps, @NonNull PackageParser.Package pkg, + @NonNull PermissionsState ps, @NonNull AndroidPackage pkg, @UserIdInt int userId) { - String pkgName = pkg.packageName; + String pkgName = pkg.getPackageName(); boolean isGranted = false; int flags = 0; @@ -2885,10 +2899,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { * @return The ids of the users that are changed */ private @NonNull int[] checkIfLegacyStorageOpsNeedToBeUpdated( - @NonNull PackageParser.Package pkg, boolean replace, @NonNull int[] updatedUserIds) { - if (replace && pkg.applicationInfo.hasRequestedLegacyExternalStorage() && ( - pkg.requestedPermissions.contains(READ_EXTERNAL_STORAGE) - || pkg.requestedPermissions.contains(WRITE_EXTERNAL_STORAGE))) { + @NonNull AndroidPackage pkg, boolean replace, @NonNull int[] updatedUserIds) { + if (replace && pkg.hasRequestedLegacyExternalStorage() && ( + pkg.getRequestedPermissions().contains(READ_EXTERNAL_STORAGE) + || pkg.getRequestedPermissions().contains(WRITE_EXTERNAL_STORAGE))) { return UserManagerService.getInstance().getUserIds(); } @@ -2907,10 +2921,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { */ private @NonNull int[] setInitialGrantForNewImplicitPermissionsLocked( @NonNull PermissionsState origPs, - @NonNull PermissionsState ps, @NonNull PackageParser.Package pkg, + @NonNull PermissionsState ps, @NonNull AndroidPackage pkg, @NonNull ArraySet<String> newImplicitPermissions, @NonNull int[] updatedUserIds) { - String pkgName = pkg.packageName; + String pkgName = pkg.getPackageName(); ArrayMap<String, ArraySet<String>> newToSplitPerms = new ArrayMap<>(); final List<SplitPermissionInfoParcelable> permissionList = getSplitPermissions(); @@ -2990,17 +3004,17 @@ public class PermissionManagerService extends IPermissionManager.Stub { SystemConfig.getInstance().getSplitPermissions()); } - private boolean isNewPlatformPermissionForPackage(String perm, PackageParser.Package pkg) { + private boolean isNewPlatformPermissionForPackage(String perm, AndroidPackage pkg) { boolean allowed = false; final int NP = PackageParser.NEW_PERMISSIONS.length; for (int ip=0; ip<NP; ip++) { final PackageParser.NewPermissionInfo npi = PackageParser.NEW_PERMISSIONS[ip]; if (npi.name.equals(perm) - && pkg.applicationInfo.targetSdkVersion < npi.sdkVersion) { + && pkg.getTargetSdkVersion() < npi.sdkVersion) { allowed = true; Log.i(TAG, "Auto-granting " + perm + " to old pkg " - + pkg.packageName); + + pkg.getPackageName()); break; } } @@ -3014,29 +3028,26 @@ public class PermissionManagerService extends IPermissionManager.Stub { * * <p>This handles parent/child apps. */ - private boolean hasPrivappWhitelistEntry(String perm, PackageParser.Package pkg) { - ArraySet<String> wlPermissions = null; + private boolean hasPrivappWhitelistEntry(String perm, AndroidPackage pkg) { + ArraySet<String> wlPermissions; if (pkg.isVendor()) { wlPermissions = - SystemConfig.getInstance().getVendorPrivAppPermissions(pkg.packageName); + SystemConfig.getInstance().getVendorPrivAppPermissions(pkg.getPackageName()); } else if (pkg.isProduct()) { wlPermissions = - SystemConfig.getInstance().getProductPrivAppPermissions(pkg.packageName); + SystemConfig.getInstance().getProductPrivAppPermissions(pkg.getPackageName()); } else if (pkg.isSystemExt()) { wlPermissions = SystemConfig.getInstance().getSystemExtPrivAppPermissions( - pkg.packageName); + pkg.getPackageName()); } else { - wlPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg.packageName); + wlPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg.getPackageName()); } - // Let's check if this package is whitelisted... - boolean whitelisted = wlPermissions != null && wlPermissions.contains(perm); - // If it's not, we'll also tail-recurse to the parent. - return whitelisted || - pkg.parentPackage != null && hasPrivappWhitelistEntry(perm, pkg.parentPackage); + + return wlPermissions != null && wlPermissions.contains(perm); } - private boolean grantSignaturePermission(String perm, PackageParser.Package pkg, + private boolean grantSignaturePermission(String perm, AndroidPackage pkg, BasePermission bp, PermissionsState origPermissions) { boolean oemPermission = bp.isOEM(); boolean vendorPrivilegedPermission = bp.isVendorPrivileged(); @@ -3044,7 +3055,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { boolean privappPermissionsDisable = RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE; boolean platformPermission = PLATFORM_PACKAGE_NAME.equals(bp.getSourcePackageName()); - boolean platformPackage = PLATFORM_PACKAGE_NAME.equals(pkg.packageName); + boolean platformPackage = PLATFORM_PACKAGE_NAME.equals(pkg.getPackageName()); if (!privappPermissionsDisable && privilegedPermission && pkg.isPrivileged() && !platformPackage && platformPermission) { if (!hasPrivappWhitelistEntry(perm, pkg)) { @@ -3054,22 +3065,22 @@ public class PermissionManagerService extends IPermissionManager.Stub { ArraySet<String> deniedPermissions = null; if (pkg.isVendor()) { deniedPermissions = SystemConfig.getInstance() - .getVendorPrivAppDenyPermissions(pkg.packageName); + .getVendorPrivAppDenyPermissions(pkg.getPackageName()); } else if (pkg.isProduct()) { deniedPermissions = SystemConfig.getInstance() - .getProductPrivAppDenyPermissions(pkg.packageName); + .getProductPrivAppDenyPermissions(pkg.getPackageName()); } else if (pkg.isSystemExt()) { deniedPermissions = SystemConfig.getInstance() - .getSystemExtPrivAppDenyPermissions(pkg.packageName); + .getSystemExtPrivAppDenyPermissions(pkg.getPackageName()); } else { deniedPermissions = SystemConfig.getInstance() - .getPrivAppDenyPermissions(pkg.packageName); + .getPrivAppDenyPermissions(pkg.getPackageName()); } final boolean permissionViolation = deniedPermissions == null || !deniedPermissions.contains(perm); if (permissionViolation) { Slog.w(TAG, "Privileged permission " + perm + " for package " - + pkg.packageName + " (" + pkg.codePath + + pkg.getPackageName() + " (" + pkg.getCodePath() + ") not in privapp-permissions whitelist"); if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) { @@ -3077,7 +3088,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { mPrivappPermissionsViolations = new ArraySet<>(); } mPrivappPermissionsViolations.add( - pkg.packageName + " (" + pkg.codePath + "): " + perm); + pkg.getPackageName() + " (" + pkg.getCodePath() + "): " + perm); } } else { return false; @@ -3102,24 +3113,23 @@ public class PermissionManagerService extends IPermissionManager.Stub { // package, and the defining package still trusts the old certificate for permissions // - or it shares the above relationships with the system package boolean allowed = - pkg.mSigningDetails.hasAncestorOrSelf( + pkg.getSigningDetails().hasAncestorOrSelf( bp.getSourcePackageSetting().getSigningDetails()) || bp.getSourcePackageSetting().getSigningDetails().checkCapability( - pkg.mSigningDetails, + pkg.getSigningDetails(), PackageParser.SigningDetails.CertCapabilities.PERMISSION) - || pkg.mSigningDetails.hasAncestorOrSelf(systemPackage.mSigningDetails) - || systemPackage.mSigningDetails.checkCapability( - pkg.mSigningDetails, + || pkg.getSigningDetails().hasAncestorOrSelf(systemPackage.getSigningDetails()) + || systemPackage.getSigningDetails().checkCapability( + pkg.getSigningDetails(), PackageParser.SigningDetails.CertCapabilities.PERMISSION); if (!allowed && (privilegedPermission || oemPermission)) { if (pkg.isSystem()) { // For updated system applications, a privileged/oem permission // is granted only if it had been defined by the original application. if (pkg.isUpdatedSystemApp()) { - final PackageParser.Package disabledPkg = - mPackageManagerInt.getDisabledSystemPackage(pkg.packageName); - final PackageSetting disabledPs = - (disabledPkg != null) ? (PackageSetting) disabledPkg.mExtras : null; + final PackageSetting disabledPs = (PackageSetting) mPackageManagerInt + .getDisabledSystemPackage(pkg.getPackageName()); + final AndroidPackage disabledPkg = disabledPs == null ? null : disabledPs.pkg; if (disabledPs != null && disabledPs.getPermissionsState().hasInstallPermission(perm)) { // If the original was granted this permission, we take @@ -3144,40 +3154,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { && canGrantOemPermission(disabledPs, perm)))) { allowed = true; } - // Also if a privileged parent package on the system image or any of - // its children requested a privileged/oem permission, the updated child - // packages can also get the permission. - if (pkg.parentPackage != null) { - final PackageParser.Package disabledParentPkg = mPackageManagerInt - .getDisabledSystemPackage(pkg.parentPackage.packageName); - final PackageSetting disabledParentPs = (disabledParentPkg != null) - ? (PackageSetting) disabledParentPkg.mExtras : null; - if (disabledParentPkg != null - && ((privilegedPermission && disabledParentPs.isPrivileged()) - || (oemPermission && disabledParentPs.isOem()))) { - if (isPackageRequestingPermission(disabledParentPkg, perm) - && canGrantOemPermission(disabledParentPs, perm)) { - allowed = true; - } else if (disabledParentPkg.childPackages != null) { - for (PackageParser.Package disabledChildPkg - : disabledParentPkg.childPackages) { - final PackageSetting disabledChildPs = - (disabledChildPkg != null) - ? (PackageSetting) disabledChildPkg.mExtras - : null; - if (isPackageRequestingPermission(disabledChildPkg, perm) - && canGrantOemPermission( - disabledChildPs, perm)) { - allowed = true; - break; - } - } - } - } - } } } else { - final PackageSetting ps = (PackageSetting) pkg.mExtras; + final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( + pkg.getPackageName()); allowed = (privilegedPermission && pkg.isPrivileged()) || (oemPermission && pkg.isOem() && canGrantOemPermission(ps, perm)); @@ -3188,7 +3168,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (allowed && privilegedPermission && !vendorPrivilegedPermission && pkg.isVendor()) { Slog.w(TAG, "Permission " + perm + " cannot be granted to privileged vendor apk " - + pkg.packageName + " because it isn't a 'vendorPrivileged' permission."); + + pkg.getPackageName() + + " because it isn't a 'vendorPrivileged' permission."); allowed = false; } } @@ -3196,7 +3177,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (!allowed) { if (!allowed && bp.isPre23() - && pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) { + && pkg.getTargetSdkVersion() < Build.VERSION_CODES.M) { // If this was a previously normal/dangerous permission that got moved // to a system permission as part of the runtime permission redesign, then // we still want to blindly grant it to old apps. @@ -3310,26 +3291,27 @@ public class PermissionManagerService extends IPermissionManager.Stub { return Boolean.TRUE == granted; } - private boolean isPermissionsReviewRequired(@NonNull PackageParser.Package pkg, + private boolean isPermissionsReviewRequired(@NonNull AndroidPackage pkg, @UserIdInt int userId) { // Permission review applies only to apps not supporting the new permission model. - if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M) { + if (pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M) { return false; } // Legacy apps have the permission and get user consent on launch. - if (pkg.mExtras == null) { + final PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( + pkg.getPackageName()); + if (ps == null) { return false; } - final PackageSetting ps = (PackageSetting) pkg.mExtras; final PermissionsState permissionsState = ps.getPermissionsState(); return permissionsState.isPermissionReviewRequired(userId); } - private boolean isPackageRequestingPermission(PackageParser.Package pkg, String permission) { - final int permCount = pkg.requestedPermissions.size(); + private boolean isPackageRequestingPermission(AndroidPackage pkg, String permission) { + final int permCount = pkg.getRequestedPermissions().size(); for (int j = 0; j < permCount; j++) { - String requestedPermission = pkg.requestedPermissions.get(j); + String requestedPermission = pkg.getRequestedPermissions().get(j); if (permission.equals(requestedPermission)) { return true; } @@ -3337,41 +3319,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { return false; } - @GuardedBy("mLock") - private void grantRuntimePermissionsGrantedToDisabledPackageLocked( - PackageParser.Package pkg, int callingUid, PermissionCallback callback) { - if (pkg.parentPackage == null) { - return; - } - if (pkg.requestedPermissions == null) { - return; - } - final PackageParser.Package disabledPkg = - mPackageManagerInt.getDisabledSystemPackage(pkg.parentPackage.packageName); - if (disabledPkg == null || disabledPkg.mExtras == null) { - return; - } - final PackageSetting disabledPs = (PackageSetting) disabledPkg.mExtras; - if (!disabledPs.isPrivileged() || disabledPs.hasChildPackages()) { - return; - } - final int permCount = pkg.requestedPermissions.size(); - for (int i = 0; i < permCount; i++) { - String permission = pkg.requestedPermissions.get(i); - BasePermission bp = mSettings.getPermissionLocked(permission); - if (bp == null || !(bp.isRuntime() || bp.isDevelopment())) { - continue; - } - for (int userId : mUserManagerInt.getUserIds()) { - if (disabledPs.getPermissionsState().hasRuntimePermission(permission, userId)) { - grantRuntimePermissionInternal( - permission, pkg.packageName, false, callingUid, userId, callback); - } - } - } - } - - private void grantRequestedRuntimePermissions(PackageParser.Package pkg, int[] userIds, + private void grantRequestedRuntimePermissions(AndroidPackage pkg, int[] userIds, String[] grantedPermissions, int callingUid, PermissionCallback callback) { for (int userId : userIds) { grantRequestedRuntimePermissionsForUser(pkg, userId, grantedPermissions, callingUid, @@ -3379,9 +3327,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } - private void grantRequestedRuntimePermissionsForUser(PackageParser.Package pkg, int userId, + private void grantRequestedRuntimePermissionsForUser(AndroidPackage pkg, int userId, String[] grantedPermissions, int callingUid, PermissionCallback callback) { - PackageSetting ps = (PackageSetting) pkg.mExtras; + PackageSetting ps = (PackageSetting) mPackageManagerInt.getPackageSetting( + pkg.getPackageName()); if (ps == null) { return; } @@ -3394,12 +3343,12 @@ public class PermissionManagerService extends IPermissionManager.Stub { final int compatFlags = PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED | PackageManager.FLAG_PERMISSION_REVOKED_COMPAT; - final boolean supportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion + final boolean supportsRuntimePermissions = pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M; - final boolean instantApp = mPackageManagerInt.isInstantApp(pkg.packageName, userId); + final boolean instantApp = mPackageManagerInt.isInstantApp(pkg.getPackageName(), userId); - for (String permission : pkg.requestedPermissions) { + for (String permission : pkg.getRequestedPermissions()) { final BasePermission bp; synchronized (mLock) { bp = mSettings.getPermissionLocked(permission); @@ -3413,14 +3362,14 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (supportsRuntimePermissions) { // Installer cannot change immutable permissions. if ((flags & immutableFlags) == 0) { - grantRuntimePermissionInternal(permission, pkg.packageName, false, + grantRuntimePermissionInternal(permission, pkg.getPackageName(), false, callingUid, userId, callback); } } else { // In permission review mode we clear the review flag and the revoked compat // flag when we are asked to install the app with all permissions granted. if ((flags & compatFlags) != 0) { - updatePermissionFlagsInternal(permission, pkg.packageName, compatFlags, + updatePermissionFlagsInternal(permission, pkg.getPackageName(), compatFlags, 0, callingUid, userId, false, callback); } } @@ -3428,11 +3377,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } - private void setWhitelistedRestrictedPermissionsForUser(@NonNull PackageParser.Package pkg, + private void setWhitelistedRestrictedPermissionsForUser(@NonNull AndroidPackage pkg, @UserIdInt int userId, @Nullable List<String> permissions, int callingUid, @PermissionWhitelistFlags int whitelistFlags, PermissionCallback callback) { final PermissionsState permissionsState = - PackageManagerServiceUtils.getPermissionsState(pkg); + PackageManagerServiceUtils.getPermissionsState(mPackageManagerInt, pkg); if (permissionsState == null) { return; } @@ -3440,9 +3389,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { ArraySet<String> oldGrantedRestrictedPermissions = null; boolean updatePermissions = false; - final int permissionCount = pkg.requestedPermissions.size(); + final int permissionCount = pkg.getRequestedPermissions().size(); for (int i = 0; i < permissionCount; i++) { - final String permissionName = pkg.requestedPermissions.get(i); + final String permissionName = pkg.getRequestedPermissions().get(i); final BasePermission bp = mSettings.getPermissionLocked(permissionName); @@ -3518,19 +3467,19 @@ public class PermissionManagerService extends IPermissionManager.Stub { // If we are whitelisting an app that does not support runtime permissions // we need to make sure it goes through the permission review UI at launch. - if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M + if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M && !wasWhitelisted && isWhitelisted) { mask |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; newFlags |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; } - updatePermissionFlagsInternal(permissionName, pkg.packageName, mask, newFlags, + updatePermissionFlagsInternal(permissionName, pkg.getPackageName(), mask, newFlags, callingUid, userId, false, null /*callback*/); } if (updatePermissions) { // Update permission of this app to take into account the new whitelist state. - restorePermissionState(pkg, false, pkg.packageName, callback); + restorePermissionState(pkg, false, pkg.getPackageName(), callback); // If this resulted in losing a permission we need to kill the app. if (oldGrantedRestrictedPermissions != null) { @@ -3539,9 +3488,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { final String permission = oldGrantedRestrictedPermissions.valueAt(i); // Sometimes we create a new permission state instance during update. final PermissionsState newPermissionsState = - PackageManagerServiceUtils.getPermissionsState(pkg); + PackageManagerServiceUtils.getPermissionsState(mPackageManagerInt, pkg); if (!newPermissionsState.hasPermission(permission, userId)) { - callback.onPermissionRevoked(pkg.applicationInfo.uid, userId); + callback.onPermissionRevoked(pkg.getUid(), userId); break; } } @@ -3554,17 +3503,17 @@ public class PermissionManagerService extends IPermissionManager.Stub { SharedUserSetting suSetting, int[] allUserIds) { // Collect all used permissions in the UID final ArraySet<String> usedPermissions = new ArraySet<>(); - final List<PackageParser.Package> pkgList = suSetting.getPackages(); + final List<AndroidPackage> pkgList = suSetting.getPackages(); if (pkgList == null || pkgList.size() == 0) { return EmptyArray.INT; } - for (PackageParser.Package pkg : pkgList) { - if (pkg.requestedPermissions == null) { + for (AndroidPackage pkg : pkgList) { + if (pkg.getRequestedPermissions() == null) { continue; } - final int requestedPermCount = pkg.requestedPermissions.size(); + final int requestedPermCount = pkg.getRequestedPermissions().size(); for (int j = 0; j < requestedPermCount; j++) { - String permission = pkg.requestedPermissions.get(j); + String permission = pkg.getRequestedPermissions().get(j); BasePermission bp = mSettings.getPermissionLocked(permission); if (bp != null) { usedPermissions.add(permission); @@ -3626,18 +3575,12 @@ public class PermissionManagerService extends IPermissionManager.Stub { * @param allPackages All currently known packages * @param callback Callback to call after permission changes */ - private void updatePermissions(@NonNull String packageName, @Nullable PackageParser.Package pkg, + private void updatePermissions(@NonNull String packageName, @Nullable AndroidPackage pkg, @NonNull PermissionCallback callback) { final int flags = (pkg != null ? UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG : 0); updatePermissions( packageName, pkg, getVolumeUuidForPackage(pkg), flags, callback); - if (pkg != null && pkg.childPackages != null) { - for (PackageParser.Package childPkg : pkg.childPackages) { - updatePermissions(childPkg.packageName, childPkg, - getVolumeUuidForPackage(childPkg), flags, callback); - } - } } /** @@ -3673,10 +3616,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { // Only system declares background permissions, hence mapping does never change. mBackgroundPermissions = new ArrayMap<>(); for (BasePermission bp : mSettings.getAllPermissionsLocked()) { - if (bp.perm != null && bp.perm.info != null - && bp.perm.info.backgroundPermission != null) { + if (bp.perm != null && bp.perm.backgroundPermission != null) { String fgPerm = bp.name; - String bgPerm = bp.perm.info.backgroundPermission; + String bgPerm = bp.perm.backgroundPermission; List<String> fgPerms = mBackgroundPermissions.get(bgPerm); if (fgPerms == null) { @@ -3737,7 +3679,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { * @param callback Callback to call after permission changes */ private void updatePermissions(final @Nullable String changingPkgName, - final @Nullable PackageParser.Package changingPkg, + final @Nullable AndroidPackage changingPkg, final @Nullable String replaceVolumeUuid, @UpdatePermissionFlags int flags, final @Nullable PermissionCallback callback) { @@ -3770,7 +3712,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { // Now update the permissions for all packages. if ((flags & UPDATE_PERMISSIONS_ALL) != 0) { final boolean replaceAll = ((flags & UPDATE_PERMISSIONS_REPLACE_ALL) != 0); - mPackageManagerInt.forEachPackage((Package pkg) -> { + mPackageManagerInt.forEachPackage((AndroidPackage pkg) -> { if (pkg == changingPkg) { return; } @@ -3809,7 +3751,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { * @return {@code true} if a permission source package might have changed */ private boolean updatePermissionSourcePackage(@Nullable String packageName, - @Nullable PackageParser.Package pkg, + @Nullable AndroidPackage pkg, final @Nullable PermissionCallback callback) { boolean changed = false; @@ -3832,8 +3774,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) { final int userId = userIds[userIdNum]; - mPackageManagerInt.forEachPackage((Package p) -> { - final String pName = p.packageName; + mPackageManagerInt.forEachPackage((AndroidPackage p) -> { + final String pName = p.getPackageName(); final ApplicationInfo appInfo = mPackageManagerInt.getApplicationInfo(pName, 0, Process.SYSTEM_UID, UserHandle.USER_SYSTEM); @@ -3878,11 +3820,13 @@ public class PermissionManagerService extends IPermissionManager.Stub { } if (needsUpdate != null) { for (final BasePermission bp : needsUpdate) { - final PackageParser.Package sourcePkg = + final AndroidPackage sourcePkg = mPackageManagerInt.getPackage(bp.getSourcePackageName()); + final PackageSetting sourcePs = + (PackageSetting) mPackageManagerInt.getPackageSetting( + bp.getSourcePackageName()); synchronized (mLock) { - if (sourcePkg != null && sourcePkg.mExtras != null) { - final PackageSetting sourcePs = (PackageSetting) sourcePkg.mExtras; + if (sourcePkg != null && sourcePs != null) { if (bp.getSourcePackageSetting() == null) { bp.setSourcePackageSetting(sourcePs); } @@ -3915,7 +3859,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { * @return {@code true} if a permission tree ownership might have changed */ private boolean updatePermissionTreeSourcePackage(@Nullable String packageName, - @Nullable PackageParser.Package pkg) { + @Nullable AndroidPackage pkg) { boolean changed = false; Set<BasePermission> needsUpdate = null; @@ -3941,11 +3885,13 @@ public class PermissionManagerService extends IPermissionManager.Stub { } if (needsUpdate != null) { for (final BasePermission bp : needsUpdate) { - final PackageParser.Package sourcePkg = + final AndroidPackage sourcePkg = mPackageManagerInt.getPackage(bp.getSourcePackageName()); + final PackageSetting sourcePs = + (PackageSetting) mPackageManagerInt.getPackageSetting( + bp.getSourcePackageName()); synchronized (mLock) { - if (sourcePkg != null && sourcePkg.mExtras != null) { - final PackageSetting sourcePs = (PackageSetting) sourcePkg.mExtras; + if (sourcePkg != null && sourcePs != null) { if (bp.getSourcePackageSetting() == null) { bp.setSourcePackageSetting(sourcePs); } @@ -4068,24 +4014,28 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } - private static String getVolumeUuidForPackage(PackageParser.Package pkg) { + private static String getVolumeUuidForPackage(AndroidPackage pkg) { if (pkg == null) { return StorageManager.UUID_PRIVATE_INTERNAL; } if (pkg.isExternal()) { - if (TextUtils.isEmpty(pkg.volumeUuid)) { + if (TextUtils.isEmpty(pkg.getVolumeUuid())) { return StorageManager.UUID_PRIMARY_PHYSICAL; } else { - return pkg.volumeUuid; + return pkg.getVolumeUuid(); } } else { return StorageManager.UUID_PRIVATE_INTERNAL; } } - private static boolean hasPermission(PackageParser.Package pkgInfo, String permName) { - for (int i=pkgInfo.permissions.size()-1; i>=0; i--) { - if (pkgInfo.permissions.get(i).info.name.equals(permName)) { + private static boolean hasPermission(AndroidPackage pkg, String permName) { + if (pkg.getPermissions() == null) { + return false; + } + + for (int i = pkg.getPermissions().size() - 1; i >= 0; i--) { + if (pkg.getPermissions().get(i).getName().equals(permName)) { return true; } } @@ -4124,37 +4074,39 @@ public class PermissionManagerService extends IPermissionManager.Stub { PermissionManagerService.this.systemReady(); } @Override - public boolean isPermissionsReviewRequired(@NonNull Package pkg, @UserIdInt int userId) { + public boolean isPermissionsReviewRequired(@NonNull AndroidPackage pkg, + @UserIdInt int userId) { return PermissionManagerService.this.isPermissionsReviewRequired(pkg, userId); } + @Override public void revokeRuntimePermissionsIfGroupChanged( - @NonNull PackageParser.Package newPackage, - @NonNull PackageParser.Package oldPackage, + @NonNull AndroidPackage newPackage, + @NonNull AndroidPackage oldPackage, @NonNull ArrayList<String> allPackageNames) { PermissionManagerService.this.revokeRuntimePermissionsIfGroupChanged(newPackage, oldPackage, allPackageNames, mDefaultPermissionCallback); } @Override - public void addAllPermissions(Package pkg, boolean chatty) { + public void addAllPermissions(AndroidPackage pkg, boolean chatty) { PermissionManagerService.this.addAllPermissions(pkg, chatty); } @Override - public void addAllPermissionGroups(Package pkg, boolean chatty) { + public void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) { PermissionManagerService.this.addAllPermissionGroups(pkg, chatty); } @Override - public void removeAllPermissions(Package pkg, boolean chatty) { + public void removeAllPermissions(AndroidPackage pkg, boolean chatty) { PermissionManagerService.this.removeAllPermissions(pkg, chatty); } @Override - public void grantRequestedRuntimePermissions(PackageParser.Package pkg, int[] userIds, + public void grantRequestedRuntimePermissions(AndroidPackage pkg, int[] userIds, String[] grantedPermissions, int callingUid) { PermissionManagerService.this.grantRequestedRuntimePermissions( pkg, userIds, grantedPermissions, callingUid, mDefaultPermissionCallback); } @Override - public void setWhitelistedRestrictedPermissions(@NonNull PackageParser.Package pkg, + public void setWhitelistedRestrictedPermissions(@NonNull AndroidPackage pkg, @NonNull int[] userIds, @Nullable List<String> permissions, int callingUid, @PackageManager.PermissionWhitelistFlags int flags) { for (int userId : userIds) { @@ -4169,13 +4121,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { packageName, permissions, flags, userId); } @Override - public void grantRuntimePermissionsGrantedToDisabledPackage(PackageParser.Package pkg, - int callingUid) { - PermissionManagerService.this.grantRuntimePermissionsGrantedToDisabledPackageLocked( - pkg, callingUid, mDefaultPermissionCallback); - } - @Override - public void updatePermissions(@NonNull String packageName, @Nullable Package pkg) { + public void updatePermissions(@NonNull String packageName, @Nullable AndroidPackage pkg) { PermissionManagerService.this .updatePermissions(packageName, pkg, mDefaultPermissionCallback); } @@ -4185,13 +4131,13 @@ public class PermissionManagerService extends IPermissionManager.Stub { .updateAllPermissions(volumeUuid, sdkUpdated, mDefaultPermissionCallback); } @Override - public void resetRuntimePermissions(Package pkg, int userId) { + public void resetRuntimePermissions(AndroidPackage pkg, int userId) { PermissionManagerService.this.resetRuntimePermissionsInternal(pkg, userId); } @Override public void resetAllRuntimePermissions(final int userId) { mPackageManagerInt.forEachPackage( - (PackageParser.Package pkg) -> resetRuntimePermissionsInternal(pkg, userId)); + (AndroidPackage pkg) -> resetRuntimePermissionsInternal(pkg, userId)); } @Override public String[] getAppOpPermissionPackages(String permName, int callingUid) { diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java index fb5c6fddedc6..0f22619fafa6 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java @@ -21,8 +21,8 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.content.pm.PackageManager; -import android.content.pm.PackageParser; import android.content.pm.PermissionInfo; +import android.content.pm.parsing.AndroidPackage; import android.permission.PermissionManagerInternal; import java.util.ArrayList; @@ -175,16 +175,14 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager public abstract void systemReady(); - public abstract boolean isPermissionsReviewRequired(@NonNull PackageParser.Package pkg, + public abstract boolean isPermissionsReviewRequired(@NonNull AndroidPackage pkg, @UserIdInt int userId); - public abstract void grantRuntimePermissionsGrantedToDisabledPackage( - @NonNull PackageParser.Package pkg, int callingUid); public abstract void grantRequestedRuntimePermissions( - @NonNull PackageParser.Package pkg, @NonNull int[] userIds, + @NonNull AndroidPackage pkg, @NonNull int[] userIds, @NonNull String[] grantedPermissions, int callingUid); public abstract void setWhitelistedRestrictedPermissions( - @NonNull PackageParser.Package pkg, @NonNull int[] userIds, + @NonNull AndroidPackage pkg, @NonNull int[] userIds, @NonNull List<String> permissions, int callingUid, @PackageManager.PermissionWhitelistFlags int whitelistFlags); /** Sets the whitelisted, restricted permissions for the given package. */ @@ -206,7 +204,7 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager * @param callback Callback to call after permission changes */ public abstract void updatePermissions(@NonNull String packageName, - @Nullable PackageParser.Package pkg); + @Nullable AndroidPackage pkg); /** * Update all permissions for all apps. @@ -226,7 +224,7 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager * Resets any user permission state changes (eg. permissions and flags) of all * packages installed for the given user. * - * @see #resetRuntimePermissions(android.content.pm.PackageParser.Package, int) + * @see #resetRuntimePermissions(AndroidPackage, int) */ public abstract void resetAllRuntimePermissions(@UserIdInt int userId); @@ -234,7 +232,7 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager * Resets any user permission state changes (eg. permissions and flags) of the * specified package for the given user. */ - public abstract void resetRuntimePermissions(@NonNull PackageParser.Package pkg, + public abstract void resetRuntimePermissions(@NonNull AndroidPackage pkg, @UserIdInt int userId); /** @@ -247,8 +245,8 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager * @param allPackageNames All packages */ public abstract void revokeRuntimePermissionsIfGroupChanged( - @NonNull PackageParser.Package newPackage, - @NonNull PackageParser.Package oldPackage, + @NonNull AndroidPackage newPackage, + @NonNull AndroidPackage oldPackage, @NonNull ArrayList<String> allPackageNames); /** @@ -257,9 +255,9 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager * NOTE: argument {@code groupTEMP} is temporary until mPermissionGroups is moved to * the permission settings. */ - public abstract void addAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty); - public abstract void addAllPermissionGroups(@NonNull PackageParser.Package pkg, boolean chatty); - public abstract void removeAllPermissions(@NonNull PackageParser.Package pkg, boolean chatty); + public abstract void addAllPermissions(@NonNull AndroidPackage pkg, boolean chatty); + public abstract void addAllPermissionGroups(@NonNull AndroidPackage pkg, boolean chatty); + public abstract void removeAllPermissions(@NonNull AndroidPackage pkg, boolean chatty); /** Retrieve the packages that have requested the given app op permission */ public abstract @Nullable String[] getAppOpPermissionPackages( diff --git a/services/core/java/com/android/server/pm/permission/PermissionSettings.java b/services/core/java/com/android/server/pm/permission/PermissionSettings.java index 3d8cf2ddc2cc..254b720c57a0 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionSettings.java +++ b/services/core/java/com/android/server/pm/permission/PermissionSettings.java @@ -18,7 +18,7 @@ package com.android.server.pm.permission; import android.annotation.NonNull; import android.annotation.Nullable; -import android.content.pm.PackageParser; +import android.content.pm.parsing.ComponentParseUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; @@ -65,8 +65,8 @@ public class PermissionSettings { * name to permission group object. */ @GuardedBy("mLock") - final ArrayMap<String, PackageParser.PermissionGroup> mPermissionGroups = - new ArrayMap<String, PackageParser.PermissionGroup>(); + final ArrayMap<String, ComponentParseUtils.ParsedPermissionGroup> mPermissionGroups = + new ArrayMap<>(); /** * Set of packages that request a particular app op. The mapping is from permission diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java index 9b9f93f7b5c4..5f39f51f9a42 100644 --- a/services/core/java/com/android/server/policy/PermissionPolicyService.java +++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java @@ -37,8 +37,8 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; import android.content.pm.PackageManagerInternal.PackageListObserver; -import android.content.pm.PackageParser; import android.content.pm.PermissionInfo; +import android.content.pm.parsing.AndroidPackage; import android.os.Build; import android.os.Process; import android.os.RemoteException; @@ -357,10 +357,10 @@ public final class PermissionPolicyService extends SystemService { pkg.sharedUserId, userId); if (sharedPkgNames != null) { for (String sharedPkgName : sharedPkgNames) { - final PackageParser.Package sharedPkg = packageManagerInternal + final AndroidPackage sharedPkg = packageManagerInternal .getPackage(sharedPkgName); if (sharedPkg != null) { - synchroniser.addPackage(sharedPkg.packageName); + synchroniser.addPackage(sharedPkg.getPackageName()); } } } @@ -377,7 +377,8 @@ public final class PermissionPolicyService extends SystemService { PackageManagerInternal.class); final PermissionToOpSynchroniser synchronizer = new PermissionToOpSynchroniser( getUserContext(getContext(), UserHandle.of(userId))); - packageManagerInternal.forEachPackage((pkg) -> synchronizer.addPackage(pkg.packageName)); + packageManagerInternal.forEachPackage( + (pkg) -> synchronizer.addPackage(pkg.getPackageName())); synchronizer.syncPackages(); } diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java index aac0f906feaa..a4eef9bf8d2e 100644 --- a/services/core/java/com/android/server/role/RoleManagerService.java +++ b/services/core/java/com/android/server/role/RoleManagerService.java @@ -308,12 +308,12 @@ public class RoleManagerService extends SystemService implements RoleUserState.C ByteArrayOutputStream out = new ByteArrayOutputStream(); pm.forEachInstalledPackage(FunctionalUtils.uncheckExceptions(pkg -> { - out.write(pkg.packageName.getBytes()); + out.write(pkg.getPackageName().getBytes()); out.write(BitUtils.toBytes(pkg.getLongVersionCode())); - out.write(pm.getApplicationEnabledState(pkg.packageName, userId)); + out.write(pm.getApplicationEnabledState(pkg.getPackageName(), userId)); ArraySet<String> enabledComponents = - pm.getEnabledComponents(pkg.packageName, userId); + pm.getEnabledComponents(pkg.getPackageName(), userId); int numComponents = CollectionUtils.size(enabledComponents); out.write(numComponents); for (int i = 0; i < numComponents; i++) { @@ -321,12 +321,12 @@ public class RoleManagerService extends SystemService implements RoleUserState.C } ArraySet<String> disabledComponents = - pm.getDisabledComponents(pkg.packageName, userId); + pm.getDisabledComponents(pkg.getPackageName(), userId); numComponents = CollectionUtils.size(disabledComponents); for (int i = 0; i < numComponents; i++) { out.write(disabledComponents.valueAt(i).getBytes()); } - for (Signature signature : pkg.mSigningDetails.signatures) { + for (Signature signature : pkg.getSigningDetails().signatures) { out.write(signature.toByteArray()); } }), userId); diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java index f6fb6e23ccfb..9d2a4603d748 100644 --- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java @@ -26,7 +26,6 @@ import static org.mockito.Mockito.when; import android.annotation.Nullable; import android.content.Intent; import android.content.IntentFilter; -import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageParser; import android.os.Build; @@ -51,17 +50,29 @@ public class AppsFilterTest { private ArrayMap<String, PackageSetting> mExisting = new ArrayMap<>(); - private static PackageBuilder pkg(String packageName) { - return new PackageBuilder(packageName) - .setApplicationInfoTargetSdkVersion(Build.VERSION_CODES.R); + private static ParsingPackage pkg(String packageName) { + return PackageImpl.forParsing(packageName) + .setTargetSdkVersion(Build.VERSION_CODES.R); } - private static PackageBuilder pkg(String packageName, Intent... queries) { - return pkg(packageName).setQueriesIntents(queries); + private static ParsingPackage pkg(String packageName, Intent... queries) { + ParsingPackage pkg = pkg(packageName); + if (queries != null) { + for (Intent intent : queries) { + pkg.addQueriesIntent(intent); + } + } + return pkg; } - private static PackageBuilder pkg(String packageName, String... queriesPackages) { - return pkg(packageName).setQueriesPackages(queriesPackages); + private static ParsingPackage pkg(String packageName, String... queriesPackages) { + ParsingPackage pkg = pkg(packageName); + if (queriesPackages != null) { + for (String queryPackageName : queriesPackages) { + pkg.addQueriesPackage(queryPackageName); + } + } + return pkg; } private static PackageBuilder pkg(String packageName, IntentFilter... filters) { @@ -89,7 +100,9 @@ public class AppsFilterTest { return info; }); } - return packageBuilder; + + return pkg(packageName) + .addActivity(activity); } @Before @@ -98,7 +111,7 @@ public class AppsFilterTest { MockitoAnnotations.initMocks(this); when(mFeatureConfigMock.isGloballyEnabled()).thenReturn(true); - when(mFeatureConfigMock.packageIsEnabled(any(PackageParser.Package.class))) + when(mFeatureConfigMock.packageIsEnabled(any(AndroidPackage.class))) .thenReturn(true); } @@ -238,7 +251,7 @@ public class AppsFilterTest { @Test public void testNoQueries_FeatureOff_DoesntFilter() { - when(mFeatureConfigMock.packageIsEnabled(any(PackageParser.Package.class))) + when(mFeatureConfigMock.packageIsEnabled(any(AndroidPackage.class))) .thenReturn(false); final AppsFilter appsFilter = new AppsFilter(mFeatureConfigMock, new String[]{}, false); diff --git a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java index fec3267c2649..0273a1c5d86e 100644 --- a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java @@ -19,17 +19,17 @@ package com.android.server.pm; import android.content.pm.PackageParser; import android.content.pm.Signature; +import android.test.AndroidTestCase; import android.util.ArrayMap; import android.util.ArraySet; import android.util.LongSparseArray; + import com.android.internal.util.ArrayUtils; import java.io.File; import java.io.IOException; -import java.security.cert.CertificateException; import java.security.PublicKey; - -import android.test.AndroidTestCase; +import java.security.cert.CertificateException; public class KeySetManagerServiceTest extends AndroidTestCase { @@ -39,7 +39,7 @@ public class KeySetManagerServiceTest extends AndroidTestCase { public PackageSetting generateFakePackageSetting(String name) { return new PackageSetting(name, name, new File(mContext.getCacheDir(), "fakeCodePath"), new File(mContext.getCacheDir(), "fakeResPath"), "", "", "", - "", 1, 0, 0, null, null, 0 /*sharedUserId*/, null /*usesStaticLibraries*/, + "", 1, 0, 0, 0 /*sharedUserId*/, null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); } diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageBuilder.java b/services/tests/servicestests/src/com/android/server/pm/PackageBuilder.java deleted file mode 100644 index c38672cfc93c..000000000000 --- a/services/tests/servicestests/src/com/android/server/pm/PackageBuilder.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * 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 com.android.server.pm; - -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.pm.PackageParser; - -import com.android.internal.util.ArrayUtils; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; - -class PackageBuilder { - final PackageParser.Package mPkg; - - PackageBuilder(String packageName) { - mPkg = new PackageParser.Package(packageName); - } - - PackageBuilder setApplicationInfoCodePath(String codePath) { - mPkg.applicationInfo.setCodePath(codePath); - return this; - } - - PackageBuilder setApplicationInfoResourcePath(String resourcePath) { - mPkg.applicationInfo.setResourcePath(resourcePath); - return this; - } - - PackageBuilder setCodePath(String codePath) { - mPkg.codePath = codePath; - return this; - } - - PackageBuilder setBaseCodePath(String baseCodePath) { - mPkg.baseCodePath = baseCodePath; - return this; - } - - PackageBuilder addUsesStaticLibrary(String name, long version) { - mPkg.usesStaticLibraries = ArrayUtils.add(mPkg.usesStaticLibraries, name); - mPkg.usesStaticLibrariesVersions = - ArrayUtils.appendLong(mPkg.usesStaticLibrariesVersions, version); - return this; - } - - PackageBuilder setApplicationInfoNativeLibraryRootDir(String dir) { - mPkg.applicationInfo.nativeLibraryRootDir = dir; - return this; - } - - PackageBuilder setStaticSharedLib(String staticSharedLibName, long staticSharedLibVersion) { - mPkg.staticSharedLibVersion = staticSharedLibVersion; - mPkg.staticSharedLibName = staticSharedLibName; - return this; - } - - PackageBuilder setManifestPackageName(String manifestPackageName) { - mPkg.manifestPackageName = manifestPackageName; - return this; - } - - PackageBuilder setVersionCodeMajor(int versionCodeMajor) { - mPkg.mVersionCodeMajor = versionCodeMajor; - return this; - } - - PackageBuilder setVersionCode(int versionCode) { - mPkg.mVersionCode = versionCode; - return this; - } - - PackageBuilder addSplitCodePath(String splitCodePath) { - mPkg.splitCodePaths = - ArrayUtils.appendElement(String.class, mPkg.splitCodePaths, splitCodePath); - return this; - } - - PackageBuilder setApplicationInfoVolumeUuid(String volumeUuid) { - mPkg.applicationInfo.volumeUuid = volumeUuid; - return this; - } - - PackageBuilder addLibraryName(String libraryName) { - mPkg.libraryNames = ArrayUtils.add(mPkg.libraryNames, libraryName); - return this; - } - - PackageBuilder setRealPackageName(String realPackageName) { - mPkg.mRealPackage = realPackageName; - return this; - } - - PackageBuilder setCpuAbiOVerride(String cpuAbiOverride) { - mPkg.cpuAbiOverride = cpuAbiOverride; - return this; - } - - PackageBuilder addPermissionRequest(String permissionName) { - mPkg.requestedPermissions.add(permissionName); - return this; - } - - PackageParser.Package build() { - return mPkg; - } - - public PackageBuilder addApplicationInfoFlag(int flag) { - mPkg.applicationInfo.flags |= flag; - return this; - } - - public PackageBuilder setApplicationInfoTargetSdkVersion(int versionCode) { - mPkg.applicationInfo.targetSdkVersion = versionCode; - return this; - } - - public PackageBuilder setQueriesIntents(Collection<Intent> queriesIntents) { - mPkg.mQueriesIntents = new ArrayList<>(queriesIntents); - return this; - } - - public PackageBuilder setQueriesIntents(Intent... intents) { - return setQueriesIntents(Arrays.asList(intents)); - } - - public PackageBuilder setQueriesPackages(Collection<String> queriesPackages) { - mPkg.mQueriesPackages = new ArrayList<>(queriesPackages); - return this; - } - - public PackageBuilder setQueriesPackages(String... queriesPackages) { - return setQueriesPackages(Arrays.asList(queriesPackages)); - } - - public PackageBuilder setForceQueryable(boolean forceQueryable) { - mPkg.mForceQueryable = forceQueryable; - return this; - } - - public interface ParseComponentArgsCreator { - PackageParser.ParseComponentArgs create(PackageParser.Package pkg); - } - - public PackageBuilder addActivity(ParseComponentArgsCreator argsCreator, ActivityInfo info) { - mPkg.activities.add(new PackageParser.Activity(argsCreator.create(mPkg), info)); - return this; - } - - public interface ActivityIntentInfoCreator { - PackageParser.ActivityIntentInfo create(PackageParser.Activity activity); - } - - public PackageBuilder addActivityIntentInfo( - int activityIndex, ActivityIntentInfoCreator creator) { - final PackageParser.Activity activity = mPkg.activities.get(activityIndex); - activity.intents.add(creator.create(activity)); - return this; - } -} diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java index 0a310d193675..85840e135909 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java @@ -87,7 +87,7 @@ public class PackageManagerServiceTest { setting = new PackageSetting("name", "realName", new File("codePath"), new File("resourcePath"), "legacyNativeLibraryPathString", "primaryCpuAbiString", "secondaryCpuAbiString", - "cpuAbiOverrideString", 0, 0, 0, "parentPackageName", null, 0, + "cpuAbiOverrideString", 0, 0, 0, 0, null, null); pri.populateUsers(new int[] { 1, 2, 3, 4, 5 diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java index 1106be2d5f6b..8329227360e7 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java @@ -403,10 +403,6 @@ public class PackageManagerSettingsTests { private static final String PACKAGE_NAME = "com.android.bar"; private static final String REAL_PACKAGE_NAME = "com.android.foo"; - private static final String PARENT_PACKAGE_NAME = "com.android.bar.parent"; - private static final String CHILD_PACKAGE_NAME_01 = "com.android.bar.child01"; - private static final String CHILD_PACKAGE_NAME_02 = "com.android.bar.child02"; - private static final String CHILD_PACKAGE_NAME_03 = "com.android.bar.child03"; private static final File INITIAL_CODE_PATH = new File(InstrumentationRegistry.getContext().getFilesDir(), "com.android.bar-1"); private static final File UPDATED_CODE_PATH = @@ -416,10 +412,6 @@ public class PackageManagerSettingsTests { @Test public void testPackageStateCopy01() { - final List<String> childPackageNames = new ArrayList<>(); - childPackageNames.add(CHILD_PACKAGE_NAME_01); - childPackageNames.add(CHILD_PACKAGE_NAME_02); - childPackageNames.add(CHILD_PACKAGE_NAME_03); final PackageSetting origPkgSetting01 = new PackageSetting( PACKAGE_NAME, REAL_PACKAGE_NAME, @@ -432,8 +424,6 @@ public class PackageManagerSettingsTests { INITIAL_VERSION_CODE, ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_HAS_CODE, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED|ApplicationInfo.PRIVATE_FLAG_HIDDEN, - PARENT_PACKAGE_NAME, - childPackageNames, 0, null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); @@ -443,10 +433,6 @@ public class PackageManagerSettingsTests { @Test public void testPackageStateCopy02() { - final List<String> childPackageNames = new ArrayList<>(); - childPackageNames.add(CHILD_PACKAGE_NAME_01); - childPackageNames.add(CHILD_PACKAGE_NAME_02); - childPackageNames.add(CHILD_PACKAGE_NAME_03); final PackageSetting origPkgSetting01 = new PackageSetting( PACKAGE_NAME /*pkgName*/, REAL_PACKAGE_NAME /*realPkgName*/, @@ -459,8 +445,6 @@ public class PackageManagerSettingsTests { INITIAL_VERSION_CODE, ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_HAS_CODE, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED|ApplicationInfo.PRIVATE_FLAG_HIDDEN, - PARENT_PACKAGE_NAME, - childPackageNames, 0, null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); @@ -476,8 +460,6 @@ public class PackageManagerSettingsTests { UPDATED_VERSION_CODE, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, - null /*parentPkgName*/, - null /*childPkgNames*/, 0, null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); @@ -505,7 +487,6 @@ public class PackageManagerSettingsTests { "armeabi" /*secondaryCpuAbi*/, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, - null /*childPkgNames*/, UserManagerService.getInstance(), null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); @@ -539,7 +520,6 @@ public class PackageManagerSettingsTests { "armeabi" /*secondaryCpuAbi*/, ApplicationInfo.FLAG_SYSTEM /*pkgFlags*/, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED /*pkgPrivateFlags*/, - null /*childPkgNames*/, UserManagerService.getInstance(), null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); @@ -579,7 +559,6 @@ public class PackageManagerSettingsTests { "armeabi" /*secondaryCpuAbi*/, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, - null /*childPkgNames*/, UserManagerService.getInstance(), null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); @@ -612,8 +591,6 @@ public class PackageManagerSettingsTests { false /*allowInstall*/, false /*instantApp*/, false /*virtualPreload*/, - null /*parentPkgName*/, - null /*childPkgNames*/, UserManagerService.getInstance(), null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); @@ -653,8 +630,6 @@ public class PackageManagerSettingsTests { true /*allowInstall*/, false /*instantApp*/, false /*virtualPreload*/, - null /*parentPkgName*/, - null /*childPkgNames*/, UserManagerService.getInstance(), null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); @@ -700,8 +675,6 @@ public class PackageManagerSettingsTests { false /*allowInstall*/, false /*instantApp*/, false /*virtualPreload*/, - null /*parentPkgName*/, - null /*childPkgNames*/, UserManagerService.getInstance(), null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); @@ -744,8 +717,6 @@ public class PackageManagerSettingsTests { false /*allowInstall*/, false /*instantApp*/, false /*virtualPreload*/, - null /*parentPkgName*/, - null /*childPkgNames*/, UserManagerService.getInstance(), null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); @@ -802,9 +773,6 @@ public class PackageManagerSettingsTests { private void verifySettingCopy(PackageSetting origPkgSetting, PackageSetting testPkgSetting) { assertThat(origPkgSetting, is(not(testPkgSetting))); assertThat(origPkgSetting.appId, is(testPkgSetting.appId)); - // different but equal objects - assertNotSame(origPkgSetting.childPackageNames, testPkgSetting.childPackageNames); - assertThat(origPkgSetting.childPackageNames, is(testPkgSetting.childPackageNames)); assertSame(origPkgSetting.codePath, testPkgSetting.codePath); assertThat(origPkgSetting.codePath, is(testPkgSetting.codePath)); assertSame(origPkgSetting.codePathString, testPkgSetting.codePathString); @@ -828,8 +796,6 @@ public class PackageManagerSettingsTests { // mOldCodePaths is _not_ copied // assertNotSame(origPkgSetting.mOldCodePaths, testPkgSetting.mOldCodePaths); // assertThat(origPkgSetting.mOldCodePaths, is(not(testPkgSetting.mOldCodePaths))); - assertSame(origPkgSetting.parentPackageName, testPkgSetting.parentPackageName); - assertThat(origPkgSetting.parentPackageName, is(testPkgSetting.parentPackageName)); assertSame(origPkgSetting.pkg, testPkgSetting.pkg); // No equals() method for this object // assertThat(origPkgSetting.pkg, is(testPkgSetting.pkg)); @@ -881,8 +847,6 @@ public class PackageManagerSettingsTests { INITIAL_VERSION_CODE, pkgFlags, 0 /*privateFlags*/, - null /*parentPackageName*/, - null /*childPackageNames*/, sharedUserId, null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); @@ -901,8 +865,6 @@ public class PackageManagerSettingsTests { INITIAL_VERSION_CODE, 0, 0 /*privateFlags*/, - null /*parentPackageName*/, - null /*childPackageNames*/, 0, null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/); diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java index e33d8ca66ed0..162092b5040a 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java @@ -15,35 +15,49 @@ */ package com.android.server.pm; -import static android.content.res.Resources.ID_NULL; - +import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; -import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.ConfigurationInfo; import android.content.pm.FeatureGroupInfo; import android.content.pm.FeatureInfo; -import android.content.pm.InstrumentationInfo; +import android.content.pm.PackageInfo; import android.content.pm.PackageParser; +import android.content.pm.PackageUserState; import android.content.pm.ProviderInfo; import android.content.pm.ServiceInfo; import android.content.pm.SharedLibraryInfo; import android.content.pm.Signature; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.ComponentParseUtils; +import android.content.pm.parsing.ComponentParseUtils.ParsedActivity; +import android.content.pm.parsing.ComponentParseUtils.ParsedComponent; +import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation; +import android.content.pm.parsing.ComponentParseUtils.ParsedIntentInfo; +import android.content.pm.parsing.ComponentParseUtils.ParsedPermission; +import android.content.pm.parsing.ComponentParseUtils.ParsedPermissionGroup; +import android.content.pm.parsing.ComponentParseUtils.ParsedProvider; +import android.content.pm.parsing.ComponentParseUtils.ParsedService; +import android.content.pm.parsing.PackageImpl; +import android.content.pm.parsing.PackageInfoUtils; +import android.content.pm.parsing.ParsedPackage; +import android.content.pm.parsing.ParsingPackage; import android.os.Bundle; import android.os.Parcel; import android.platform.test.annotations.Presubmit; -import android.util.ArrayMap; import android.util.ArraySet; import androidx.test.filters.MediumTest; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.internal.util.ArrayUtils; + import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -57,6 +71,7 @@ import java.lang.reflect.Field; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -64,6 +79,9 @@ import java.util.Set; @RunWith(AndroidJUnit4.class) @MediumTest public class PackageParserTest { + // TODO(b/135203078): Update this test with all fields and validate equality. Initial change + // was just migrating to new interfaces. Consider adding actual equals() methods. + @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder(); @@ -79,12 +97,12 @@ public class PackageParserTest { @Test public void testParse_noCache() throws Exception { PackageParser pp = new CachePackageNameParser(); - PackageParser.Package pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, + ParsedPackage pkg = pp.parseParsedPackage(FRAMEWORK, 0 /* parseFlags */, false /* useCaches */); assertNotNull(pkg); pp.setCacheDir(mTmpDir); - pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, + pkg = pp.parseParsedPackage(FRAMEWORK, 0 /* parseFlags */, false /* useCaches */); assertNotNull(pkg); @@ -99,27 +117,27 @@ public class PackageParserTest { pp.setCacheDir(mTmpDir); // The first parse will write this package to the cache. - pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, true /* useCaches */); + pp.parseParsedPackage(FRAMEWORK, 0 /* parseFlags */, true /* useCaches */); // Now attempt to parse the package again, should return the // cached result. - PackageParser.Package pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, + ParsedPackage pkg = pp.parseParsedPackage(FRAMEWORK, 0 /* parseFlags */, true /* useCaches */); - assertEquals("cache_android", pkg.packageName); + assertEquals("cache_android", pkg.getPackageName()); // Try again, with useCaches == false, shouldn't return the parsed // result. - pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, false /* useCaches */); - assertEquals("android", pkg.packageName); + pkg = pp.parseParsedPackage(FRAMEWORK, 0 /* parseFlags */, false /* useCaches */); + assertEquals("android", pkg.getPackageName()); // We haven't set a cache directory here : the parse should still succeed, // just not using the cached results. pp = new CachePackageNameParser(); - pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, true /* useCaches */); - assertEquals("android", pkg.packageName); + pkg = pp.parseParsedPackage(FRAMEWORK, 0 /* parseFlags */, true /* useCaches */); + assertEquals("android", pkg.getPackageName()); - pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, false /* useCaches */); - assertEquals("android", pkg.packageName); + pkg = pp.parseParsedPackage(FRAMEWORK, 0 /* parseFlags */, false /* useCaches */); + assertEquals("android", pkg.getPackageName()); } @Test @@ -127,14 +145,14 @@ public class PackageParserTest { PackageParser pp = new PackageParser(); pp.setCacheDir(mTmpDir); - PackageParser.Package pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, - true /* useCaches */); + ParsedPackage pkg = pp.parseParsedPackage(FRAMEWORK, 0 /* parseFlags */, + true /* useCaches */); Parcel p = Parcel.obtain(); pkg.writeToParcel(p, 0 /* flags */); p.setDataPosition(0); - PackageParser.Package deserialized = new PackageParser.Package(p); + ParsedPackage deserialized = new PackageImpl(p); assertPackagesEqual(pkg, deserialized); } @@ -143,46 +161,52 @@ public class PackageParserTest { @SmallTest @Presubmit public void test_roundTripKnownFields() throws Exception { - PackageParser.Package pkg = new PackageParser.Package("foo"); + ParsingPackage pkg = PackageImpl.forParsing("foo"); setKnownFields(pkg); Parcel p = Parcel.obtain(); pkg.writeToParcel(p, 0 /* flags */); p.setDataPosition(0); - PackageParser.Package deserialized = new PackageParser.Package(p); + ParsedPackage deserialized = new PackageImpl(p); assertAllFieldsExist(deserialized); } @Test public void test_stringInterning() throws Exception { - PackageParser.Package pkg = new PackageParser.Package("foo"); + ParsingPackage pkg = PackageImpl.forParsing("foo"); setKnownFields(pkg); Parcel p = Parcel.obtain(); pkg.writeToParcel(p, 0 /* flags */); p.setDataPosition(0); - PackageParser.Package deserialized = new PackageParser.Package(p); + ParsingPackage deserialized = new PackageImpl(p); p.setDataPosition(0); - PackageParser.Package deserialized2 = new PackageParser.Package(p); - - assertSame(deserialized.packageName, deserialized2.packageName); - assertSame(deserialized.applicationInfo.permission, - deserialized2.applicationInfo.permission); - assertSame(deserialized.requestedPermissions.get(0), - deserialized2.requestedPermissions.get(0)); - assertSame(deserialized.protectedBroadcasts.get(0), - deserialized2.protectedBroadcasts.get(0)); - assertSame(deserialized.usesLibraries.get(0), - deserialized2.usesLibraries.get(0)); - assertSame(deserialized.usesOptionalLibraries.get(0), - deserialized2.usesOptionalLibraries.get(0)); - assertSame(deserialized.mVersionName, deserialized2.mVersionName); - assertSame(deserialized.mSharedUserId, deserialized2.mSharedUserId); - } + ParsingPackage deserialized2 = new PackageImpl(p); + assertSame(deserialized.getPackageName(), deserialized2.getPackageName()); + assertSame(deserialized.getPermission(), + deserialized2.getPermission()); + assertSame(deserialized.getRequestedPermissions().get(0), + deserialized2.getRequestedPermissions().get(0)); + + List<String> protectedBroadcastsOne = new ArrayList<>(1); + protectedBroadcastsOne.addAll(deserialized.getProtectedBroadcasts()); + + List<String> protectedBroadcastsTwo = new ArrayList<>(1); + protectedBroadcastsTwo.addAll(deserialized2.getProtectedBroadcasts()); + + assertSame(protectedBroadcastsOne.get(0), protectedBroadcastsTwo.get(0)); + + assertSame(deserialized.getUsesLibraries().get(0), + deserialized2.getUsesLibraries().get(0)); + assertSame(deserialized.getUsesOptionalLibraries().get(0), + deserialized2.getUsesOptionalLibraries().get(0)); + assertSame(deserialized.getVersionName(), deserialized2.getVersionName()); + assertSame(deserialized.getSharedUserId(), deserialized2.getSharedUserId()); + } /** * A trivial subclass of package parser that only caches the package name, and throws away @@ -190,107 +214,111 @@ public class PackageParserTest { */ public static class CachePackageNameParser extends PackageParser { @Override - public byte[] toCacheEntry(Package pkg) { - return ("cache_" + pkg.packageName).getBytes(StandardCharsets.UTF_8); + public byte[] toCacheEntry(ParsedPackage pkg) { + return ("cache_" + pkg.getPackageName()).getBytes(StandardCharsets.UTF_8); } @Override - public Package fromCacheEntry(byte[] cacheEntry) { - return new Package(new String(cacheEntry, StandardCharsets.UTF_8)); + public ParsedPackage fromCacheEntry(byte[] cacheEntry) { + return PackageImpl.forParsing(new String(cacheEntry, StandardCharsets.UTF_8)) + .hideAsParsed(); } } // NOTE: The equality assertions below are based on code autogenerated by IntelliJ. - public static void assertPackagesEqual(PackageParser.Package a, PackageParser.Package b) { - assertEquals(a.baseRevisionCode, b.baseRevisionCode); - assertEquals(a.baseHardwareAccelerated, b.baseHardwareAccelerated); - assertEquals(a.mVersionCode, b.mVersionCode); - assertEquals(a.mSharedUserLabel, b.mSharedUserLabel); - assertEquals(a.mPreferredOrder, b.mPreferredOrder); - assertEquals(a.installLocation, b.installLocation); - assertEquals(a.coreApp, b.coreApp); - assertEquals(a.mRequiredForAllUsers, b.mRequiredForAllUsers); - assertEquals(a.mCompileSdkVersion, b.mCompileSdkVersion); - assertEquals(a.mCompileSdkVersionCodename, b.mCompileSdkVersionCodename); - assertEquals(a.use32bitAbi, b.use32bitAbi); - assertEquals(a.packageName, b.packageName); - assertTrue(Arrays.equals(a.splitNames, b.splitNames)); - assertEquals(a.volumeUuid, b.volumeUuid); - assertEquals(a.codePath, b.codePath); - assertEquals(a.baseCodePath, b.baseCodePath); - assertTrue(Arrays.equals(a.splitCodePaths, b.splitCodePaths)); - assertTrue(Arrays.equals(a.splitRevisionCodes, b.splitRevisionCodes)); - assertTrue(Arrays.equals(a.splitFlags, b.splitFlags)); - assertTrue(Arrays.equals(a.splitPrivateFlags, b.splitPrivateFlags)); - assertApplicationInfoEqual(a.applicationInfo, b.applicationInfo); - - assertEquals(a.permissions.size(), b.permissions.size()); - for (int i = 0; i < a.permissions.size(); ++i) { - assertPermissionsEqual(a.permissions.get(i), b.permissions.get(i)); - assertSame(a.permissions.get(i).owner, a); - assertSame(b.permissions.get(i).owner, b); + public static void assertPackagesEqual(AndroidPackage a, AndroidPackage b) { + assertEquals(a.getBaseRevisionCode(), b.getBaseRevisionCode()); + assertEquals(a.isBaseHardwareAccelerated(), b.isBaseHardwareAccelerated()); + assertEquals(a.getVersionCode(), b.getVersionCode()); + assertEquals(a.getSharedUserLabel(), b.getSharedUserLabel()); + assertEquals(a.getPreferredOrder(), b.getPreferredOrder()); + assertEquals(a.getInstallLocation(), b.getInstallLocation()); + assertEquals(a.isCoreApp(), b.isCoreApp()); + assertEquals(a.isRequiredForAllUsers(), b.isRequiredForAllUsers()); + assertEquals(a.getCompileSdkVersion(), b.getCompileSdkVersion()); + assertEquals(a.getCompileSdkVersionCodeName(), b.getCompileSdkVersionCodeName()); + assertEquals(a.isUse32BitAbi(), b.isUse32BitAbi()); + assertEquals(a.getPackageName(), b.getPackageName()); + assertArrayEquals(a.getSplitNames(), b.getSplitNames()); + assertEquals(a.getVolumeUuid(), b.getVolumeUuid()); + assertEquals(a.getCodePath(), b.getCodePath()); + assertEquals(a.getBaseCodePath(), b.getBaseCodePath()); + assertArrayEquals(a.getSplitCodePaths(), b.getSplitCodePaths()); + assertArrayEquals(a.getSplitRevisionCodes(), b.getSplitRevisionCodes()); + assertArrayEquals(a.getSplitFlags(), b.getSplitFlags()); + + PackageInfo aInfo = PackageInfoUtils.generate(a, new int[]{}, 0, 0, 0, + Collections.emptySet(), new PackageUserState(), 0); + PackageInfo bInfo = PackageInfoUtils.generate(b, new int[]{}, 0, 0, 0, + Collections.emptySet(), new PackageUserState(), 0); + assertApplicationInfoEqual(aInfo.applicationInfo, bInfo.applicationInfo); + + assertEquals(ArrayUtils.size(a.getPermissions()), ArrayUtils.size(b.getPermissions())); + for (int i = 0; i < ArrayUtils.size(a.getPermissions()); ++i) { + assertPermissionsEqual(a.getPermissions().get(i), b.getPermissions().get(i)); } - assertEquals(a.permissionGroups.size(), b.permissionGroups.size()); - for (int i = 0; i < a.permissionGroups.size(); ++i) { - assertPermissionGroupsEqual(a.permissionGroups.get(i), b.permissionGroups.get(i)); + assertEquals(ArrayUtils.size(a.getPermissionGroups()), + ArrayUtils.size(b.getPermissionGroups())); + for (int i = 0; i < a.getPermissionGroups().size(); ++i) { + assertPermissionGroupsEqual(a.getPermissionGroups().get(i), + b.getPermissionGroups().get(i)); } - assertEquals(a.activities.size(), b.activities.size()); - for (int i = 0; i < a.activities.size(); ++i) { - assertActivitiesEqual(a.activities.get(i), b.activities.get(i)); + assertEquals(ArrayUtils.size(a.getActivities()), ArrayUtils.size(b.getActivities())); + for (int i = 0; i < ArrayUtils.size(a.getActivities()); ++i) { + assertActivitiesEqual(a, a.getActivities().get(i), b, b.getActivities().get(i)); } - assertEquals(a.receivers.size(), b.receivers.size()); - for (int i = 0; i < a.receivers.size(); ++i) { - assertActivitiesEqual(a.receivers.get(i), b.receivers.get(i)); + assertEquals(ArrayUtils.size(a.getReceivers()), ArrayUtils.size(b.getReceivers())); + for (int i = 0; i < ArrayUtils.size(a.getReceivers()); ++i) { + assertActivitiesEqual(a, a.getReceivers().get(i), b, b.getReceivers().get(i)); } - assertEquals(a.providers.size(), b.providers.size()); - for (int i = 0; i < a.providers.size(); ++i) { - assertProvidersEqual(a.providers.get(i), b.providers.get(i)); + assertEquals(ArrayUtils.size(a.getProviders()), ArrayUtils.size(b.getProviders())); + for (int i = 0; i < ArrayUtils.size(a.getProviders()); ++i) { + assertProvidersEqual(a, a.getProviders().get(i), b, b.getProviders().get(i)); } - assertEquals(a.services.size(), b.services.size()); - for (int i = 0; i < a.services.size(); ++i) { - assertServicesEqual(a.services.get(i), b.services.get(i)); + assertEquals(ArrayUtils.size(a.getServices()), ArrayUtils.size(b.getServices())); + for (int i = 0; i < ArrayUtils.size(a.getServices()); ++i) { + assertServicesEqual(a, a.getServices().get(i), b, b.getServices().get(i)); } - assertEquals(a.instrumentation.size(), b.instrumentation.size()); - for (int i = 0; i < a.instrumentation.size(); ++i) { - assertInstrumentationEqual(a.instrumentation.get(i), b.instrumentation.get(i)); + assertEquals(ArrayUtils.size(a.getInstrumentations()), + ArrayUtils.size(b.getInstrumentations())); + for (int i = 0; i < ArrayUtils.size(a.getInstrumentations()); ++i) { + assertInstrumentationEqual(a.getInstrumentations().get(i), + b.getInstrumentations().get(i)); } - assertEquals(a.requestedPermissions, b.requestedPermissions); - assertEquals(a.protectedBroadcasts, b.protectedBroadcasts); - assertEquals(a.parentPackage, b.parentPackage); - assertEquals(a.childPackages, b.childPackages); - assertEquals(a.libraryNames, b.libraryNames); - assertEquals(a.usesLibraries, b.usesLibraries); - assertEquals(a.usesOptionalLibraries, b.usesOptionalLibraries); - assertTrue(Arrays.equals(a.usesLibraryFiles, b.usesLibraryFiles)); - assertEquals(a.mOriginalPackages, b.mOriginalPackages); - assertEquals(a.mRealPackage, b.mRealPackage); - assertEquals(a.mAdoptPermissions, b.mAdoptPermissions); - assertBundleApproximateEquals(a.mAppMetaData, b.mAppMetaData); - assertEquals(a.mVersionName, b.mVersionName); - assertEquals(a.mSharedUserId, b.mSharedUserId); - assertTrue(Arrays.equals(a.mSigningDetails.signatures, b.mSigningDetails.signatures)); - assertTrue(Arrays.equals(a.mLastPackageUsageTimeInMills, b.mLastPackageUsageTimeInMills)); - assertEquals(a.mExtras, b.mExtras); - assertEquals(a.mRestrictedAccountType, b.mRestrictedAccountType); - assertEquals(a.mRequiredAccountType, b.mRequiredAccountType); - assertEquals(a.mOverlayTarget, b.mOverlayTarget); - assertEquals(a.mOverlayTargetName, b.mOverlayTargetName); - assertEquals(a.mOverlayCategory, b.mOverlayCategory); - assertEquals(a.mOverlayPriority, b.mOverlayPriority); - assertEquals(a.mOverlayIsStatic, b.mOverlayIsStatic); - assertEquals(a.mSigningDetails.publicKeys, b.mSigningDetails.publicKeys); - assertEquals(a.mUpgradeKeySets, b.mUpgradeKeySets); - assertEquals(a.mKeySetMapping, b.mKeySetMapping); - assertEquals(a.cpuAbiOverride, b.cpuAbiOverride); - assertTrue(Arrays.equals(a.restrictUpdateHash, b.restrictUpdateHash)); + assertEquals(a.getRequestedPermissions(), b.getRequestedPermissions()); + assertEquals(a.getProtectedBroadcasts(), b.getProtectedBroadcasts()); + assertEquals(a.getLibraryNames(), b.getLibraryNames()); + assertEquals(a.getUsesLibraries(), b.getUsesLibraries()); + assertEquals(a.getUsesOptionalLibraries(), b.getUsesOptionalLibraries()); + assertArrayEquals(a.getUsesLibraryFiles(), b.getUsesLibraryFiles()); + assertEquals(a.getOriginalPackages(), b.getOriginalPackages()); + assertEquals(a.getRealPackage(), b.getRealPackage()); + assertEquals(a.getAdoptPermissions(), b.getAdoptPermissions()); + assertBundleApproximateEquals(a.getAppMetaData(), b.getAppMetaData()); + assertEquals(a.getVersionName(), b.getVersionName()); + assertEquals(a.getSharedUserId(), b.getSharedUserId()); + assertArrayEquals(a.getSigningDetails().signatures, b.getSigningDetails().signatures); + assertArrayEquals(a.getLastPackageUsageTimeInMills(), b.getLastPackageUsageTimeInMills()); + assertEquals(a.getRestrictedAccountType(), b.getRestrictedAccountType()); + assertEquals(a.getRequiredAccountType(), b.getRequiredAccountType()); + assertEquals(a.getOverlayTarget(), b.getOverlayTarget()); + assertEquals(a.getOverlayTargetName(), b.getOverlayTargetName()); + assertEquals(a.getOverlayCategory(), b.getOverlayCategory()); + assertEquals(a.getOverlayPriority(), b.getOverlayPriority()); + assertEquals(a.isOverlayIsStatic(), b.isOverlayIsStatic()); + assertEquals(a.getSigningDetails().publicKeys, b.getSigningDetails().publicKeys); + assertEquals(a.getUpgradeKeySets(), b.getUpgradeKeySets()); + assertEquals(a.getKeySetMapping(), b.getKeySetMapping()); + assertEquals(a.getCpuAbiOverride(), b.getCpuAbiOverride()); + assertArrayEquals(a.getRestrictUpdateHash(), b.getRestrictUpdateHash()); } private static void assertBundleApproximateEquals(Bundle a, Bundle b) { @@ -305,10 +333,10 @@ public class PackageParserTest { assertEquals(a.toString(), b.toString()); } - private static void assertComponentsEqual(PackageParser.Component<?> a, - PackageParser.Component<?> b) { + private static void assertComponentsEqual(ParsedComponent<?> a, + ParsedComponent<?> b) { assertEquals(a.className, b.className); - assertBundleApproximateEquals(a.metaData, b.metaData); + assertBundleApproximateEquals(a.getMetaData(), b.getMetaData()); assertEquals(a.getComponentName(), b.getComponentName()); if (a.intents != null && b.intents != null) { @@ -318,80 +346,104 @@ public class PackageParserTest { } for (int i = 0; i < a.intents.size(); ++i) { - PackageParser.IntentInfo aIntent = a.intents.get(i); - PackageParser.IntentInfo bIntent = b.intents.get(i); + ParsedIntentInfo aIntent = a.intents.get(i); + ParsedIntentInfo bIntent = b.intents.get(i); assertEquals(aIntent.hasDefault, bIntent.hasDefault); assertEquals(aIntent.labelRes, bIntent.labelRes); assertEquals(aIntent.nonLocalizedLabel, bIntent.nonLocalizedLabel); assertEquals(aIntent.icon, bIntent.icon); - assertEquals(aIntent.logo, bIntent.logo); - assertEquals(aIntent.banner, bIntent.banner); - assertEquals(aIntent.preferred, bIntent.preferred); } } - private static void assertPermissionsEqual(PackageParser.Permission a, - PackageParser.Permission b) { + private static void assertPermissionsEqual(ParsedPermission a, + ParsedPermission b) { assertComponentsEqual(a, b); assertEquals(a.tree, b.tree); // Verify basic flags in PermissionInfo to make sure they're consistent. We don't perform // a full structural equality here because the code that serializes them isn't parser // specific and is tested elsewhere. - assertEquals(a.info.protectionLevel, b.info.protectionLevel); - assertEquals(a.info.group, b.info.group); - assertEquals(a.info.flags, b.info.flags); + assertEquals(a.getProtection(), b.getProtection()); + assertEquals(a.getGroup(), b.getGroup()); + assertEquals(a.flags, b.flags); - if (a.group != null && b.group != null) { - assertPermissionGroupsEqual(a.group, b.group); - } else if (a.group != null || b.group != null) { + if (a.parsedPermissionGroup != null && b.parsedPermissionGroup != null) { + assertPermissionGroupsEqual(a.parsedPermissionGroup, b.parsedPermissionGroup); + } else if (a.parsedPermissionGroup != null || b.parsedPermissionGroup != null) { throw new AssertionError(); } } - private static void assertInstrumentationEqual(PackageParser.Instrumentation a, - PackageParser.Instrumentation b) { + private static void assertInstrumentationEqual(ParsedInstrumentation a, + ParsedInstrumentation b) { assertComponentsEqual(a, b); // Sanity check for InstrumentationInfo. - assertEquals(a.info.targetPackage, b.info.targetPackage); - assertEquals(a.info.targetProcesses, b.info.targetProcesses); - assertEquals(a.info.sourceDir, b.info.sourceDir); - assertEquals(a.info.publicSourceDir, b.info.publicSourceDir); + assertEquals(a.getTargetPackage(), b.getTargetPackage()); + assertEquals(a.getTargetProcesses(), b.getTargetProcesses()); + assertEquals(a.sourceDir, b.sourceDir); + assertEquals(a.publicSourceDir, b.publicSourceDir); } - private static void assertServicesEqual(PackageParser.Service a, PackageParser.Service b) { + private static void assertServicesEqual( + AndroidPackage aPkg, + ParsedService a, + AndroidPackage bPkg, + ParsedService b + ) { assertComponentsEqual(a, b); // Sanity check for ServiceInfo. - assertApplicationInfoEqual(a.info.applicationInfo, b.info.applicationInfo); - assertEquals(a.info.name, b.info.name); + ServiceInfo aInfo = PackageInfoUtils.generateServiceInfo(aPkg, a, 0, new PackageUserState(), + 0); + ServiceInfo bInfo = PackageInfoUtils.generateServiceInfo(bPkg, b, 0, new PackageUserState(), + 0); + assertApplicationInfoEqual(aInfo.applicationInfo, bInfo.applicationInfo); + assertEquals(a.getName(), b.getName()); } - private static void assertProvidersEqual(PackageParser.Provider a, PackageParser.Provider b) { + private static void assertProvidersEqual( + AndroidPackage aPkg, + ParsedProvider a, + AndroidPackage bPkg, + ParsedProvider b + ) { assertComponentsEqual(a, b); // Sanity check for ProviderInfo - assertApplicationInfoEqual(a.info.applicationInfo, b.info.applicationInfo); - assertEquals(a.info.name, b.info.name); + ProviderInfo aInfo = PackageInfoUtils.generateProviderInfo(aPkg, a, 0, + new PackageUserState(), 0); + ProviderInfo bInfo = PackageInfoUtils.generateProviderInfo(bPkg, b, 0, + new PackageUserState(), 0); + assertApplicationInfoEqual(aInfo.applicationInfo, bInfo.applicationInfo); + assertEquals(a.getName(), b.getName()); } - private static void assertActivitiesEqual(PackageParser.Activity a, PackageParser.Activity b) { + private static void assertActivitiesEqual( + AndroidPackage aPkg, + ParsedActivity a, + AndroidPackage bPkg, + ParsedActivity b + ) { assertComponentsEqual(a, b); // Sanity check for ActivityInfo. - assertApplicationInfoEqual(a.info.applicationInfo, b.info.applicationInfo); - assertEquals(a.info.name, b.info.name); + ActivityInfo aInfo = PackageInfoUtils.generateActivityInfo(aPkg, a, 0, + new PackageUserState(), 0); + ActivityInfo bInfo = PackageInfoUtils.generateActivityInfo(bPkg, b, 0, + new PackageUserState(), 0); + assertApplicationInfoEqual(aInfo.applicationInfo, bInfo.applicationInfo); + assertEquals(a.getName(), b.getName()); } - private static void assertPermissionGroupsEqual(PackageParser.PermissionGroup a, - PackageParser.PermissionGroup b) { + private static void assertPermissionGroupsEqual(ParsedPermissionGroup a, + ParsedPermissionGroup b) { assertComponentsEqual(a, b); // Sanity check for PermissionGroupInfo. - assertEquals(a.info.name, b.info.name); - assertEquals(a.info.descriptionRes, b.info.descriptionRes); + assertEquals(a.getName(), b.getName()); + assertEquals(a.descriptionRes, b.descriptionRes); } private static void assertApplicationInfoEqual(ApplicationInfo a, ApplicationInfo that) { @@ -424,11 +476,11 @@ public class PackageParserTest { assertEquals(a.scanPublicSourceDir, that.scanPublicSourceDir); assertEquals(a.sourceDir, that.sourceDir); assertEquals(a.publicSourceDir, that.publicSourceDir); - assertTrue(Arrays.equals(a.splitSourceDirs, that.splitSourceDirs)); - assertTrue(Arrays.equals(a.splitPublicSourceDirs, that.splitPublicSourceDirs)); - assertTrue(Arrays.equals(a.resourceDirs, that.resourceDirs)); + assertArrayEquals(a.splitSourceDirs, that.splitSourceDirs); + assertArrayEquals(a.splitPublicSourceDirs, that.splitPublicSourceDirs); + assertArrayEquals(a.resourceDirs, that.resourceDirs); assertEquals(a.seInfo, that.seInfo); - assertTrue(Arrays.equals(a.sharedLibraryFiles, that.sharedLibraryFiles)); + assertArrayEquals(a.sharedLibraryFiles, that.sharedLibraryFiles); assertEquals(a.dataDir, that.dataDir); assertEquals(a.deviceProtectedDataDir, that.deviceProtectedDataDir); assertEquals(a.credentialProtectedDataDir, that.credentialProtectedDataDir); @@ -439,132 +491,93 @@ public class PackageParserTest { assertEquals(a.secondaryCpuAbi, that.secondaryCpuAbi); } - public static void setKnownFields(PackageParser.Package pkg) { - pkg.baseRevisionCode = 100; - pkg.baseHardwareAccelerated = true; - pkg.mVersionCode = 100; - pkg.mSharedUserLabel = 100; - pkg.mPreferredOrder = 100; - pkg.installLocation = 100; - pkg.coreApp = true; - pkg.mRequiredForAllUsers = true; - pkg.use32bitAbi = true; - pkg.packageName = "foo"; - pkg.splitNames = new String[] { "foo2" }; - pkg.volumeUuid = "foo3"; - pkg.codePath = "foo4"; - pkg.baseCodePath = "foo5"; - pkg.splitCodePaths = new String[] { "foo6" }; - pkg.splitRevisionCodes = new int[] { 100 }; - pkg.splitFlags = new int[] { 100 }; - pkg.splitPrivateFlags = new int[] { 100 }; - pkg.applicationInfo = new ApplicationInfo(); - - pkg.permissions.add(new PackageParser.Permission(pkg, (String) null)); - pkg.permissionGroups.add(new PackageParser.PermissionGroup(pkg, ID_NULL, ID_NULL, ID_NULL)); - - final PackageParser.ParseComponentArgs dummy = new PackageParser.ParseComponentArgs( - pkg, new String[1], 0, 0, 0, 0, 0, 0, null, 0, 0, 0); - - pkg.activities.add(new PackageParser.Activity(dummy, new ActivityInfo())); - pkg.receivers.add(new PackageParser.Activity(dummy, new ActivityInfo())); - pkg.providers.add(new PackageParser.Provider(dummy, new ProviderInfo())); - pkg.services.add(new PackageParser.Service(dummy, new ServiceInfo())); - pkg.instrumentation.add(new PackageParser.Instrumentation(dummy, new InstrumentationInfo())); - pkg.requestedPermissions.add("foo7"); - pkg.implicitPermissions.add("foo25"); - - pkg.protectedBroadcasts = new ArrayList<>(); - pkg.protectedBroadcasts.add("foo8"); - - pkg.parentPackage = new PackageParser.Package("foo9"); - - pkg.childPackages = new ArrayList<>(); - pkg.childPackages.add(new PackageParser.Package("bar")); - - pkg.staticSharedLibName = "foo23"; - pkg.staticSharedLibVersion = 100; - pkg.usesStaticLibraries = new ArrayList<>(); - pkg.usesStaticLibraries.add("foo23"); - pkg.usesStaticLibrariesCertDigests = new String[1][]; - pkg.usesStaticLibrariesCertDigests[0] = new String[] { "digest" }; - pkg.usesStaticLibrariesVersions = new long[] { 100 }; - - pkg.libraryNames = new ArrayList<>(); - pkg.libraryNames.add("foo10"); - - pkg.usesLibraries = new ArrayList<>(); - pkg.usesLibraries.add("foo11"); - - pkg.usesOptionalLibraries = new ArrayList<>(); - pkg.usesOptionalLibraries.add("foo12"); - - pkg.usesLibraryFiles = new String[] { "foo13"}; - - pkg.usesLibraryInfos = new ArrayList<>(); - pkg.usesLibraryInfos.add( - new SharedLibraryInfo(null, null, null, null, 0L, 0, null, null, null)); - - pkg.mOriginalPackages = new ArrayList<>(); - pkg.mOriginalPackages.add("foo14"); - - pkg.mRealPackage = "foo15"; - - pkg.mAdoptPermissions = new ArrayList<>(); - pkg.mAdoptPermissions.add("foo16"); - - pkg.mAppMetaData = new Bundle(); - pkg.mVersionName = "foo17"; - pkg.mSharedUserId = "foo18"; - pkg.mSigningDetails = - new PackageParser.SigningDetails( - new Signature[] { new Signature(new byte[16]) }, - 2, - new ArraySet<>(), - null); - pkg.mExtras = new Bundle(); - pkg.mRestrictedAccountType = "foo19"; - pkg.mRequiredAccountType = "foo20"; - pkg.mOverlayTarget = "foo21"; - pkg.mOverlayPriority = 100; - pkg.mUpgradeKeySets = new ArraySet<>(); - pkg.mKeySetMapping = new ArrayMap<>(); - pkg.cpuAbiOverride = "foo22"; - pkg.restrictUpdateHash = new byte[16]; - - pkg.preferredActivityFilters = new ArrayList<>(); - pkg.preferredActivityFilters.add(new PackageParser.ActivityIntentInfo( - new PackageParser.Activity(dummy, new ActivityInfo()))); - - pkg.configPreferences = new ArrayList<>(); - pkg.configPreferences.add(new ConfigurationInfo()); - - pkg.reqFeatures = new ArrayList<>(); - pkg.reqFeatures.add(new FeatureInfo()); - - pkg.featureGroups = new ArrayList<>(); - pkg.featureGroups.add(new FeatureGroupInfo()); - - pkg.mCompileSdkVersionCodename = "foo23"; - pkg.mCompileSdkVersion = 100; - pkg.mVersionCodeMajor = 100; - - pkg.mOverlayCategory = "foo24"; - pkg.mOverlayIsStatic = true; - pkg.mOverlayTargetName = "foo26"; - - pkg.baseHardwareAccelerated = true; - pkg.coreApp = true; - pkg.mRequiredForAllUsers = true; - pkg.visibleToInstantApps = true; - pkg.use32bitAbi = true; - pkg.mForceQueryable = true; - pkg.mQueriesPackages = new ArrayList<>(Arrays.asList("foo27")); - pkg.mQueriesIntents = new ArrayList<>(Arrays.asList(new Intent("foo28"))); + public static void setKnownFields(ParsingPackage pkg) { + Bundle bundle = new Bundle(); + bundle.putString("key", "value"); + + ParsedPermission permission = new ParsedPermission(); + permission.parsedPermissionGroup = new ParsedPermissionGroup(); + + pkg.setBaseRevisionCode(100) + .setBaseHardwareAccelerated(true) + .setSharedUserLabel(100) + .setPreferredOrder(100) + .setInstallLocation(100) + .setRequiredForAllUsers(true) + .asSplit( + new String[]{"foo2"}, + new String[]{"foo6"}, + new int[]{100}, + null + ) + .setUse32BitAbi(true) + .setVolumeUuid("foo3") + .setCodePath("foo4") + .addPermission(permission) + .addPermissionGroup(new ParsedPermissionGroup()) + .addActivity(new ParsedActivity()) + .addReceiver(new ParsedActivity()) + .addProvider(new ParsedProvider()) + .addService(new ParsedService()) + .addInstrumentation(new ParsedInstrumentation()) + .addRequestedPermission("foo7") + .addImplicitPermission("foo25") + .addProtectedBroadcast("foo8") + .setStaticSharedLibName("foo23") + .setStaticSharedLibVersion(100) + .addUsesStaticLibrary("foo23") + .addUsesStaticLibraryCertDigests(new String[]{"digest"}) + .addUsesStaticLibraryVersion(100) + .addLibraryName("foo10") + .addUsesLibrary("foo11") + .addUsesOptionalLibrary("foo12") + .addOriginalPackage("foo14") + .setRealPackage("foo15") + .addAdoptPermission("foo16") + .setAppMetaData(bundle) + .setVersionName("foo17") + .setSharedUserId("foo18") + .setSigningDetails( + new PackageParser.SigningDetails( + new Signature[]{new Signature(new byte[16])}, + 2, + new ArraySet<>(), + null) + ) + .setRestrictedAccountType("foo19") + .setRequiredAccountType("foo20") + .setOverlayTarget("foo21") + .setOverlayPriority(100) + .setUpgradeKeySets(new ArraySet<>()) + .addPreferredActivityFilter( + new ComponentParseUtils.ParsedActivityIntentInfo("foo", "className")) + .addConfigPreference(new ConfigurationInfo()) + .addReqFeature(new FeatureInfo()) + .addFeatureGroup(new FeatureGroupInfo()) + .setCompileSdkVersionCodename("foo23") + .setCompileSdkVersion(100) + .setOverlayCategory("foo24") + .setOverlayIsStatic(true) + .setOverlayTargetName("foo26") + .setVisibleToInstantApps(true) + .setSplitHasCode(0, true) + .hideAsParsed() + .setBaseCodePath("foo5") + .setVersionCode(100) + .setCpuAbiOverride("foo22") + .setRestrictUpdateHash(new byte[16]) + .setVersionCodeMajor(100) + .setCoreApp(true) + .hideAsFinal() + .mutate() + .setUsesLibraryInfos(Arrays.asList( + new SharedLibraryInfo(null, null, null, null, 0L, 0, null, null, null) + )) + .setUsesLibraryFiles(new String[]{"foo13"}); } - private static void assertAllFieldsExist(PackageParser.Package pkg) throws Exception { - Field[] fields = PackageParser.Package.class.getDeclaredFields(); + private static void assertAllFieldsExist(ParsedPackage pkg) throws Exception { + Field[] fields = ParsedPackage.class.getDeclaredFields(); Set<String> nonSerializedFields = new HashSet<>(); nonSerializedFields.add("mExtras"); @@ -601,7 +614,7 @@ public class PackageParserTest { } else if (fieldType == boolean.class) { // boolean fields: Check that they're set to true. boolean value = (boolean) f.get(pkg); - assertEquals("Bad value for field: " + f, true, value); + assertTrue("Bad value for field: " + f, value); } else { // All other fields: Check that they're set. Object o = f.get(pkg); diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java index 8d476f6e9318..374e13a2a13a 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java @@ -16,12 +16,11 @@ package com.android.server.pm; -import android.content.pm.PackageParser; import android.content.pm.PackageUserState; +import android.content.pm.parsing.AndroidPackage; import android.util.SparseArray; import java.io.File; -import java.util.List; class PackageSettingBuilder { private String mName; @@ -35,8 +34,6 @@ class PackageSettingBuilder { private long mPVersionCode; private int mPkgFlags; private int mPrivateFlags; - private String mParentPackageName; - private List<String> mChildPackageNames; private int mSharedUserId; private String[] mUsesStaticLibraries; private long[] mUsesStaticLibrariesVersions; @@ -45,7 +42,7 @@ class PackageSettingBuilder { private PackageParser.Package mPkg; private int mAppId; - public PackageSettingBuilder setPackage(PackageParser.Package pkg) { + public PackageSettingBuilder setPackage(AndroidPackage pkg) { this.mPkg = pkg; return this; } @@ -111,16 +108,6 @@ class PackageSettingBuilder { return this; } - public PackageSettingBuilder setParentPackageName(String parentPackageName) { - this.mParentPackageName = parentPackageName; - return this; - } - - public PackageSettingBuilder setChildPackageNames(List<String> childPackageNames) { - this.mChildPackageNames = childPackageNames; - return this; - } - public PackageSettingBuilder setSharedUserId(int sharedUserId) { this.mSharedUserId = sharedUserId; return this; @@ -154,9 +141,8 @@ class PackageSettingBuilder { final PackageSetting packageSetting = new PackageSetting(mName, mRealName, new File(mCodePath), new File(mResourcePath), mLegacyNativeLibraryPathString, mPrimaryCpuAbiString, mSecondaryCpuAbiString, - mCpuAbiOverrideString, mPVersionCode, mPkgFlags, mPrivateFlags, mParentPackageName, - mChildPackageNames, mSharedUserId, mUsesStaticLibraries, - mUsesStaticLibrariesVersions); + mCpuAbiOverrideString, mPVersionCode, mPkgFlags, mPrivateFlags, mSharedUserId, + mUsesStaticLibraries, mUsesStaticLibrariesVersions); packageSetting.pkg = mPkg; packageSetting.appId = mAppId; packageSetting.volumeUuid = this.mVolumeUuid; diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageSignaturesTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageSignaturesTest.java index d3a77d3e80f1..04e769d7dcfb 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageSignaturesTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageSignaturesTest.java @@ -16,8 +16,8 @@ package com.android.server.pm; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -467,8 +467,7 @@ public class PackageSignaturesTest { File appPath = new File("/data/app/app"); PackageSetting result = new PackageSetting("test.app", null, appPath, appPath, "/data/app/app", null, null, null, - 1, 940097092, 0, null, - null, 0 /*userId*/, null, null); + 1, 940097092, 0, 0 /*userId*/, null, null); return result; } } diff --git a/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java index 41489dc42a6a..a0efc8a03719 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java @@ -17,6 +17,7 @@ package com.android.server.pm; import android.content.pm.PackageParser; +import android.content.pm.parsing.ParsedPackage; import android.util.Log; import androidx.test.runner.AndroidJUnit4; @@ -74,7 +75,7 @@ public class ParallelPackageParserTest { } @Override - protected PackageParser.Package parsePackage(PackageParser packageParser, File scanFile, + protected ParsedPackage parsePackage(PackageParser packageParser, File scanFile, int parseFlags) throws PackageParser.PackageParserException { // Do not actually parse the package for testing return null; diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanRequestBuilder.java b/services/tests/servicestests/src/com/android/server/pm/ScanRequestBuilder.java index 34a3f860496a..11f154be688b 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ScanRequestBuilder.java +++ b/services/tests/servicestests/src/com/android/server/pm/ScanRequestBuilder.java @@ -16,12 +16,13 @@ package com.android.server.pm; -import android.content.pm.PackageParser; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.ParsedPackage; import android.os.UserHandle; class ScanRequestBuilder { - private final PackageParser.Package mPkg; - private PackageParser.Package mOldPkg; + private final ParsedPackage mPkg; + private AndroidPackage mOldPkg; private SharedUserSetting mSharedUserSetting; private PackageSetting mPkgSetting; private PackageSetting mDisabledPkgSetting; @@ -32,11 +33,11 @@ class ScanRequestBuilder { private UserHandle mUser; private boolean mIsPlatformPackage; - ScanRequestBuilder(PackageParser.Package pkg) { + ScanRequestBuilder(ParsedPackage pkg) { this.mPkg = pkg; } - public ScanRequestBuilder setOldPkg(PackageParser.Package oldPkg) { + public ScanRequestBuilder setOldPkg(AndroidPackage oldPkg) { this.mOldPkg = oldPkg; return this; } diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java index 74ef034082a0..997348dc4b3b 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java @@ -35,13 +35,17 @@ import static org.junit.Assert.assertNotSame; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.Manifest; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; -import android.content.pm.PackageParser; import android.content.pm.SharedLibraryInfo; +import android.content.pm.parsing.PackageImpl; +import android.content.pm.parsing.ParsedPackage; +import android.content.pm.parsing.ParsingPackage; +import android.content.res.TypedArray; import android.os.Environment; import android.os.UserHandle; import android.os.UserManagerInternal; @@ -60,6 +64,7 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import java.io.File; +import java.util.UUID; @RunWith(MockitoJUnitRunner.class) @Presubmit @@ -68,6 +73,9 @@ public class ScanTests { private static final String DUMMY_PACKAGE_NAME = "some.app.to.test"; + private static final UUID UUID_ONE = UUID.randomUUID(); + private static final UUID UUID_TWO = UUID.randomUUID(); + @Mock PackageAbiHelper mMockPackageAbiHelper; @Mock @@ -92,25 +100,25 @@ public class ScanTests { @Before public void setupDefaultAbiBehavior() throws Exception { when(mMockPackageAbiHelper.derivePackageAbi( - any(PackageParser.Package.class), nullable(String.class), anyBoolean())) + any(ParsedPackage.class), nullable(String.class), anyBoolean())) .thenReturn(new Pair<>( new PackageAbiHelper.Abis("derivedPrimary", "derivedSecondary"), new PackageAbiHelper.NativeLibraryPaths( "derivedRootDir", true, "derivedNativeDir", "derivedNativeDir2"))); when(mMockPackageAbiHelper.getNativeLibraryPaths( - any(PackageParser.Package.class), any(File.class))) + any(ParsedPackage.class), any(File.class))) .thenReturn(new PackageAbiHelper.NativeLibraryPaths( "getRootDir", true, "getNativeDir", "getNativeDir2" )); when(mMockPackageAbiHelper.getBundledAppAbis( - any(PackageParser.Package.class))) + any(ParsedPackage.class))) .thenReturn(new PackageAbiHelper.Abis("bundledPrimary", "bundledSecondary")); } @Test public void newInstallSimpleAllNominal() throws Exception { final PackageManagerService.ScanRequest scanRequest = - createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME).build()) + createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME)) .addScanFlag(PackageManagerService.SCAN_NEW_INSTALL) .addScanFlag(PackageManagerService.SCAN_AS_FULL_APP) .build(); @@ -128,7 +136,7 @@ public class ScanTests { when(mMockUserManager.getUserIds()).thenReturn(userIds); final PackageManagerService.ScanRequest scanRequest = - createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME).build()) + createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME)) .setRealPkgName(null) .addScanFlag(PackageManagerService.SCAN_NEW_INSTALL) .addScanFlag(PackageManagerService.SCAN_AS_FULL_APP) @@ -143,7 +151,7 @@ public class ScanTests { @Test public void installRealPackageName() throws Exception { final PackageManagerService.ScanRequest scanRequest = - createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME).build()) + createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME)) .setRealPkgName("com.package.real") .build(); @@ -154,7 +162,7 @@ public class ScanTests { final PackageManagerService.ScanRequest scanRequestNoRealPkg = createBasicScanRequestBuilder( createBasicPackage(DUMMY_PACKAGE_NAME) - .setRealPackageName("com.package.real").build()) + .setRealPackage("com.package.real")) .build(); final PackageManagerService.ScanResult scanResultNoReal = executeScan(scanRequestNoRealPkg); @@ -170,7 +178,7 @@ public class ScanTests { .setSecondaryCpuAbiString("secondaryCpuAbi") .build(); final PackageManagerService.ScanRequest scanRequest = - createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME).build()) + createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME)) .addScanFlag(PackageManagerService.SCAN_AS_FULL_APP) .setPkgSetting(pkgSetting) .build(); @@ -202,7 +210,7 @@ public class ScanTests { .build(); final PackageManagerService.ScanRequest scanRequest = - createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME).build()) + createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME)) .setPkgSetting(existingPkgSetting) .build(); @@ -214,17 +222,18 @@ public class ScanTests { @Test public void installStaticSharedLibrary() throws Exception { - final PackageParser.Package pkg = createBasicPackage("static.lib.pkg.123") - .setStaticSharedLib("static.lib", 123L) - .setManifestPackageName("static.lib.pkg") + final ParsedPackage pkg = createBasicPackage("static.lib.pkg") + .setStaticSharedLibName("static.lib") + .setStaticSharedLibVersion(123L) + .hideAsParsed() + .setPackageName("static.lib.pkg.123") .setVersionCodeMajor(1) .setVersionCode(234) .setBaseCodePath("/some/path.apk") - .addSplitCodePath("/some/other/path.apk") - .build(); + .setSplitCodePaths(new String[] {"/some/other/path.apk"}); - final PackageManagerService.ScanRequest scanRequest = new ScanRequestBuilder( - pkg).setUser(UserHandle.of(0)).build(); + final PackageManagerService.ScanRequest scanRequest = new ScanRequestBuilder(pkg) + .setUser(UserHandle.of(0)).build(); final PackageManagerService.ScanResult scanResult = executeScan(scanRequest); @@ -245,15 +254,14 @@ public class ScanTests { @Test public void installDynamicLibraries() throws Exception { - final PackageParser.Package pkg = createBasicPackage("dynamic.lib.pkg") - .setManifestPackageName("dynamic.lib.pkg") + final ParsedPackage pkg = createBasicPackage("dynamic.lib.pkg") .addLibraryName("liba") .addLibraryName("libb") + .hideAsParsed() .setVersionCodeMajor(1) .setVersionCode(234) .setBaseCodePath("/some/path.apk") - .addSplitCodePath("/some/other/path.apk") - .build(); + .setSplitCodePaths(new String[] {"/some/other/path.apk"}); final PackageManagerService.ScanRequest scanRequest = new ScanRequestBuilder(pkg).setUser(UserHandle.of(0)).build(); @@ -295,15 +303,15 @@ public class ScanTests { .setVolumeUuid("someUuid") .build(); - final PackageParser.Package basicPackage = createBasicPackage(DUMMY_PACKAGE_NAME) - .setApplicationInfoVolumeUuid("someNewUuid") - .build(); + final ParsedPackage basicPackage = createBasicPackage(DUMMY_PACKAGE_NAME) + .hideAsParsed() + .setApplicationVolumeUuid(UUID_TWO.toString()); final PackageManagerService.ScanResult scanResult = executeScan( new ScanRequestBuilder(basicPackage).setPkgSetting(pkgSetting).build()); - assertThat(scanResult.pkgSetting.volumeUuid, is("someNewUuid")); + assertThat(scanResult.pkgSetting.volumeUuid, is(UUID_TWO.toString())); } @Test @@ -311,10 +319,10 @@ public class ScanTests { final PackageSetting pkgSetting = createBasicPackageSettingBuilder(DUMMY_PACKAGE_NAME).build(); - final PackageParser.Package basicPackage = + final ParsedPackage basicPackage = createBasicPackage(DUMMY_PACKAGE_NAME) - .setCpuAbiOVerride("testOverride") - .build(); + .hideAsParsed() + .setCpuAbiOverride("testOverride"); final PackageManagerService.ScanResult scanResult = executeScan(new ScanRequestBuilder( @@ -331,9 +339,9 @@ public class ScanTests { final PackageSetting originalPkgSetting = createBasicPackageSettingBuilder("original.package").build(); - final PackageParser.Package basicPackage = + final ParsedPackage basicPackage = createBasicPackage(DUMMY_PACKAGE_NAME) - .build(); + .hideAsParsed(); final PackageManagerService.ScanResult result = @@ -341,7 +349,7 @@ public class ScanTests { .setOriginalPkgSetting(originalPkgSetting) .build()); - assertThat(result.request.pkg.packageName, is("original.package")); + assertThat(result.request.parsedPackage.getPackageName(), is("original.package")); } @Test @@ -354,7 +362,7 @@ public class ScanTests { .build(); final PackageManagerService.ScanRequest scanRequest = - createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME).build()) + createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME)) .setPkgSetting(existingPkgSetting) .addScanFlag(SCAN_AS_FULL_APP) .build(); @@ -375,7 +383,7 @@ public class ScanTests { .build(); final PackageManagerService.ScanRequest scanRequest = - createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME).build()) + createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME)) .setPkgSetting(existingPkgSetting) .addScanFlag(SCAN_AS_INSTANT_APP) .build(); @@ -394,7 +402,7 @@ public class ScanTests { .build(); final PackageManagerService.ScanRequest scanRequest = - createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME).build()) + createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME)) .setPkgSetting(existingPkgSetting) .setDisabledPkgSetting(existingPkgSetting) .addScanFlag(SCAN_NEW_INSTALL) @@ -402,15 +410,14 @@ public class ScanTests { final PackageManagerService.ScanResult scanResult = executeScan(scanRequest); - assertThat(scanResult.request.pkg.applicationInfo.flags, + assertThat(scanResult.request.parsedPackage.getFlags(), hasFlag(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)); } @Test public void factoryTestFlagSet() throws Exception { - final PackageParser.Package basicPackage = createBasicPackage(DUMMY_PACKAGE_NAME) - .addPermissionRequest(Manifest.permission.FACTORY_TEST) - .build(); + final ParsingPackage basicPackage = createBasicPackage(DUMMY_PACKAGE_NAME) + .addRequestedPermission(Manifest.permission.FACTORY_TEST); final PackageManagerService.ScanResult scanResult = PackageManagerService.scanPackageOnlyLI( createBasicScanRequestBuilder(basicPackage).build(), @@ -418,15 +425,15 @@ public class ScanTests { true /*isUnderFactoryTest*/, System.currentTimeMillis()); - assertThat(scanResult.request.pkg.applicationInfo.flags, + assertThat(scanResult.request.parsedPackage.getFlags(), hasFlag(ApplicationInfo.FLAG_FACTORY_TEST)); } @Test public void scanSystemApp_isOrphanedTrue() throws Exception { - final PackageParser.Package pkg = createBasicPackage(DUMMY_PACKAGE_NAME) - .addApplicationInfoFlag(ApplicationInfo.FLAG_SYSTEM) - .build(); + final ParsedPackage pkg = createBasicPackage(DUMMY_PACKAGE_NAME) + .hideAsParsed() + .setSystem(true); final PackageManagerService.ScanRequest scanRequest = createBasicScanRequestBuilder(pkg) @@ -481,22 +488,29 @@ public class ScanTests { .setResourcePath(createResourcePath(packageName)); } - private static ScanRequestBuilder createBasicScanRequestBuilder(PackageParser.Package pkg) { - return new ScanRequestBuilder(pkg) + private static ScanRequestBuilder createBasicScanRequestBuilder(ParsingPackage pkg) { + return new ScanRequestBuilder(pkg.hideAsParsed()) .setUser(UserHandle.of(0)); } + private static ScanRequestBuilder createBasicScanRequestBuilder(ParsedPackage pkg) { + return new ScanRequestBuilder(pkg) + .setUser(UserHandle.of(0)); + } - private static PackageBuilder createBasicPackage(String packageName) { - return new PackageBuilder(packageName) + private static ParsingPackage createBasicPackage(String packageName) { + // TODO(b/135203078): Make this use PackageImpl.forParsing and separate the steps + return new PackageImpl(packageName, null, mock(TypedArray.class), false) .setCodePath("/data/tmp/randompath") .setApplicationInfoCodePath(createCodePath(packageName)) .setApplicationInfoResourcePath(createResourcePath(packageName)) - .setApplicationInfoVolumeUuid("volumeUuid") + .setApplicationVolumeUuid(UUID_ONE.toString()) .setBaseCodePath("/data/tmp/randompath/base.apk") - .addUsesStaticLibrary("some.static.library", 234L) - .addUsesStaticLibrary("some.other.static.library", 456L) - .setApplicationInfoNativeLibraryRootDir("/data/tmp/randompath/base.apk:/lib") + .addUsesStaticLibrary("some.static.library") + .addUsesStaticLibraryVersion(234L) + .addUsesStaticLibrary("some.other.static.library") + .addUsesStaticLibraryVersion(456L) + .setNativeLibraryRootDir("/data/tmp/randompath/base.apk:/lib") .setVersionCodeMajor(1) .setVersionCode(2345); } @@ -508,20 +522,18 @@ public class ScanTests { final PackageSetting pkgSetting = scanResult.pkgSetting; assertBasicPackageSetting(scanResult, packageName, isInstant, pkgSetting); - final ApplicationInfo applicationInfo = pkgSetting.pkg.applicationInfo; + final ApplicationInfo applicationInfo = pkgSetting.pkg.toAppInfo(); assertBasicApplicationInfo(scanResult, applicationInfo); - } private static void assertBasicPackageSetting(PackageManagerService.ScanResult scanResult, String packageName, boolean isInstant, PackageSetting pkgSetting) { - assertThat(pkgSetting.pkg.packageName, is(packageName)); + assertThat(pkgSetting.pkg.getPackageName(), is(packageName)); assertThat(pkgSetting.getInstantApp(0), is(isInstant)); assertThat(pkgSetting.usesStaticLibraries, arrayContaining("some.static.library", "some.other.static.library")); assertThat(pkgSetting.usesStaticLibrariesVersions, is(new long[]{234L, 456L})); - assertThat(pkgSetting.pkg, is(scanResult.request.pkg)); - assertThat(pkgSetting.pkg.mExtras, is(pkgSetting)); + assertThat(pkgSetting.pkg, is(scanResult.request.parsedPackage)); assertThat(pkgSetting.codePath, is(new File(createCodePath(packageName)))); assertThat(pkgSetting.resourcePath, is(new File(createResourcePath(packageName)))); assertThat(pkgSetting.versionCode, is(PackageInfo.composeLongVersionCode(1, 2345))); @@ -529,20 +541,21 @@ public class ScanTests { private static void assertBasicApplicationInfo(PackageManagerService.ScanResult scanResult, ApplicationInfo applicationInfo) { - assertThat(applicationInfo.processName, is(scanResult.request.pkg.packageName)); + assertThat(applicationInfo.processName, + is(scanResult.request.parsedPackage.getPackageName())); final int uid = applicationInfo.uid; assertThat(UserHandle.getUserId(uid), is(UserHandle.USER_SYSTEM)); final String calculatedCredentialId = Environment.getDataUserCePackageDirectory( applicationInfo.volumeUuid, UserHandle.USER_SYSTEM, - scanResult.request.pkg.packageName).getAbsolutePath(); + scanResult.request.parsedPackage.getPackageName()).getAbsolutePath(); assertThat(applicationInfo.credentialProtectedDataDir, is(calculatedCredentialId)); assertThat(applicationInfo.dataDir, is(applicationInfo.credentialProtectedDataDir)); } private static void assertAbiAndPathssDerived(PackageManagerService.ScanResult scanResult) { - final ApplicationInfo applicationInfo = scanResult.pkgSetting.pkg.applicationInfo; + final ApplicationInfo applicationInfo = scanResult.pkgSetting.pkg.toAppInfo(); assertThat(applicationInfo.primaryCpuAbi, is("derivedPrimary")); assertThat(applicationInfo.secondaryCpuAbi, is("derivedSecondary")); @@ -554,7 +567,7 @@ public class ScanTests { } private static void assertPathsNotDerived(PackageManagerService.ScanResult scanResult) { - final ApplicationInfo applicationInfo = scanResult.pkgSetting.pkg.applicationInfo; + final ApplicationInfo applicationInfo = scanResult.pkgSetting.pkg.toAppInfo(); assertThat(applicationInfo.nativeLibraryRootDir, is("getRootDir")); assertThat(scanResult.pkgSetting.legacyNativeLibraryPathString, is("getRootDir")); assertThat(applicationInfo.nativeLibraryRootRequiresIsa, is(true)); diff --git a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java index 790f2b47cdd5..0b0f6a7c2191 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java @@ -37,8 +37,9 @@ import static org.junit.Assert.fail; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.content.pm.PackageParser; import android.content.pm.UserInfo; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.PackageImpl; import android.os.Looper; import android.os.SystemProperties; import android.os.UserManager; diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java index 3a55c2290157..66a4946ecc20 100644 --- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java @@ -22,8 +22,11 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import android.content.pm.ApplicationInfo; import android.content.pm.SharedLibraryInfo; +import android.content.pm.parsing.AndroidPackage; +import android.content.pm.parsing.PackageImpl; +import android.content.pm.parsing.ParsedPackage; +import android.content.pm.parsing.ParsingPackage; import android.util.SparseArray; import androidx.test.filters.SmallTest; @@ -51,17 +54,18 @@ public class DexoptUtilsTest { DelegateLastClassLoader.class.getName(); private static class TestData { - ApplicationInfo info; + AndroidPackage pkg; boolean[] pathsWithCode; } private TestData createMockApplicationInfo(String baseClassLoader, boolean addSplits, - boolean addSplitDependencies) { - ApplicationInfo ai = new ApplicationInfo(); + boolean addSplitDependencies, boolean isolatedSplitLoading) { String codeDir = "/data/app/mock.android.com"; - ai.setBaseCodePath(codeDir + "/base.dex"); - ai.classLoaderName = baseClassLoader; - ai.privateFlags = ai.privateFlags | ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING; + ParsingPackage parsingPackage = PackageImpl.forParsing("mock.android.com") + .setClassLoaderName(baseClassLoader); + + parsingPackage.setIsolatedSplitLoading(isolatedSplitLoading); + boolean[] pathsWithCode; if (!addSplits) { pathsWithCode = new boolean[] {true}; @@ -70,7 +74,7 @@ public class DexoptUtilsTest { Arrays.fill(pathsWithCode, true); pathsWithCode[7] = false; // config split - ai.setSplitCodePaths(new String[]{ + String[] splitCodePaths = new String[]{ codeDir + "/base-1.dex", codeDir + "/base-2.dex", codeDir + "/base-3.dex", @@ -78,32 +82,51 @@ public class DexoptUtilsTest { codeDir + "/base-5.dex", codeDir + "/base-6.dex", codeDir + "/config-split-7.dex", - codeDir + "/feature-no-deps.dex"}); - - ai.splitClassLoaderNames = new String[]{ - DELEGATE_LAST_CLASS_LOADER_NAME, - DELEGATE_LAST_CLASS_LOADER_NAME, - PATH_CLASS_LOADER_NAME, - DEX_CLASS_LOADER_NAME, - PATH_CLASS_LOADER_NAME, - null, // A null class loader name should default to PathClassLoader. - null, // The config split gets a null class loader. - null}; // The feature split with no dependency and no specified class loader. + codeDir + "/feature-no-deps.dex" + }; + + String[] splitNames = new String[splitCodePaths.length]; + int[] splitRevisionCodes = new int[splitCodePaths.length]; + SparseArray<int[]> splitDependencies = null; + if (addSplitDependencies) { - ai.splitDependencies = new SparseArray<>(ai.splitClassLoaderNames.length + 1); - ai.splitDependencies.put(0, new int[] {-1}); // base has no dependency - ai.splitDependencies.put(1, new int[] {2}); // split 1 depends on 2 - ai.splitDependencies.put(2, new int[] {4}); // split 2 depends on 4 - ai.splitDependencies.put(3, new int[] {4}); // split 3 depends on 4 - ai.splitDependencies.put(4, new int[] {0}); // split 4 depends on base - ai.splitDependencies.put(5, new int[] {0}); // split 5 depends on base - ai.splitDependencies.put(6, new int[] {5}); // split 6 depends on 5 + splitDependencies = new SparseArray<>(splitCodePaths.length); + splitDependencies.put(0, new int[] {-1}); // base has no dependency + splitDependencies.put(1, new int[] {2}); // split 1 depends on 2 + splitDependencies.put(2, new int[] {4}); // split 2 depends on 4 + splitDependencies.put(3, new int[] {4}); // split 3 depends on 4 + splitDependencies.put(4, new int[] {0}); // split 4 depends on base + splitDependencies.put(5, new int[] {0}); // split 5 depends on base + splitDependencies.put(6, new int[] {5}); // split 6 depends on 5 // Do not add the config split to the dependency list. // Do not add the feature split with no dependency to the dependency list. } + + parsingPackage + .asSplit( + splitNames, + splitCodePaths, + splitRevisionCodes, + splitDependencies + ) + .setSplitClassLoaderName(0, DELEGATE_LAST_CLASS_LOADER_NAME) + .setSplitClassLoaderName(1, DELEGATE_LAST_CLASS_LOADER_NAME) + .setSplitClassLoaderName(2, PATH_CLASS_LOADER_NAME) + .setSplitClassLoaderName(3, DEX_CLASS_LOADER_NAME) + .setSplitClassLoaderName(4, PATH_CLASS_LOADER_NAME) + // A null class loader name should default to PathClassLoader + .setSplitClassLoaderName(5, null) + // The config split gets a null class loader + .setSplitClassLoaderName(6, null) + // The feature split with no dependency and no specified class loader. + .setSplitClassLoaderName(7, null); } + + ParsedPackage parsedPackage = parsingPackage.hideAsParsed() + .setBaseCodePath(codeDir + "/base.dex"); + TestData data = new TestData(); - data.info = ai; + data.pkg = parsedPackage.hideAsFinal(); data.pathsWithCode = pathsWithCode; return data; } @@ -118,11 +141,11 @@ public class DexoptUtilsTest { @Test public void testSplitChain() { - TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, true, true); + TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, true, true, true); List<SharedLibraryInfo> sharedLibrary = createMockSharedLibrary(new String[] {"a.dex", "b.dex"}); String[] contexts = DexoptUtils.getClassLoaderContexts( - data.info, sharedLibrary, data.pathsWithCode); + data.pkg, sharedLibrary, data.pathsWithCode); assertEquals(9, contexts.length); assertEquals("PCL[]{PCL[a.dex:b.dex]}", contexts[0]); @@ -139,11 +162,11 @@ public class DexoptUtilsTest { @Test public void testSplitChainNoSplitDependencies() { - TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, true, false); + TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, true, false, true); List<SharedLibraryInfo> sharedLibrary = createMockSharedLibrary(new String[] {"a.dex", "b.dex"}); String[] contexts = DexoptUtils.getClassLoaderContexts( - data.info, sharedLibrary, data.pathsWithCode); + data.pkg, sharedLibrary, data.pathsWithCode); assertEquals(9, contexts.length); assertEquals("PCL[]{PCL[a.dex:b.dex]}", contexts[0]); @@ -167,11 +190,9 @@ public class DexoptUtilsTest { @Test public void testSplitChainNoIsolationNoSharedLibrary() { - TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, true, true); - data.info.privateFlags = data.info.privateFlags - & (~ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING); + TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, true, true, false); String[] contexts = DexoptUtils.getClassLoaderContexts( - data.info, null, data.pathsWithCode); + data.pkg, null, data.pathsWithCode); assertEquals(9, contexts.length); assertEquals("PCL[]", contexts[0]); @@ -192,9 +213,9 @@ public class DexoptUtilsTest { @Test public void testSplitChainNoSharedLibraries() { TestData data = createMockApplicationInfo( - DELEGATE_LAST_CLASS_LOADER_NAME, true, true); + DELEGATE_LAST_CLASS_LOADER_NAME, true, true, true); String[] contexts = DexoptUtils.getClassLoaderContexts( - data.info, null, data.pathsWithCode); + data.pkg, null, data.pathsWithCode); assertEquals(9, contexts.length); assertEquals("DLC[]", contexts[0]); @@ -211,11 +232,11 @@ public class DexoptUtilsTest { @Test public void testSplitChainWithNullPrimaryClassLoader() { // A null classLoaderName should mean PathClassLoader. - TestData data = createMockApplicationInfo(null, true, true); + TestData data = createMockApplicationInfo(null, true, true, true); List<SharedLibraryInfo> sharedLibrary = createMockSharedLibrary(new String[] {"a.dex", "b.dex"}); String[] contexts = DexoptUtils.getClassLoaderContexts( - data.info, sharedLibrary, data.pathsWithCode); + data.pkg, sharedLibrary, data.pathsWithCode); assertEquals(9, contexts.length); assertEquals("PCL[]{PCL[a.dex:b.dex]}", contexts[0]); @@ -233,11 +254,11 @@ public class DexoptUtilsTest { @Test public void tesNoSplits() { - TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, false, false); + TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, false, false, true); List<SharedLibraryInfo> sharedLibrary = createMockSharedLibrary(new String[] {"a.dex", "b.dex"}); String[] contexts = DexoptUtils.getClassLoaderContexts( - data.info, sharedLibrary, data.pathsWithCode); + data.pkg, sharedLibrary, data.pathsWithCode); assertEquals(1, contexts.length); assertEquals("PCL[]{PCL[a.dex:b.dex]}", contexts[0]); @@ -245,11 +266,11 @@ public class DexoptUtilsTest { @Test public void tesNoSplitsNullClassLoaderName() { - TestData data = createMockApplicationInfo(null, false, false); + TestData data = createMockApplicationInfo(null, false, false, true); List<SharedLibraryInfo> sharedLibrary = createMockSharedLibrary(new String[] {"a.dex", "b.dex"}); String[] contexts = DexoptUtils.getClassLoaderContexts( - data.info, sharedLibrary, data.pathsWithCode); + data.pkg, sharedLibrary, data.pathsWithCode); assertEquals(1, contexts.length); assertEquals("PCL[]{PCL[a.dex:b.dex]}", contexts[0]); @@ -258,11 +279,11 @@ public class DexoptUtilsTest { @Test public void tesNoSplitDelegateLast() { TestData data = createMockApplicationInfo( - DELEGATE_LAST_CLASS_LOADER_NAME, false, false); + DELEGATE_LAST_CLASS_LOADER_NAME, false, false, true); List<SharedLibraryInfo> sharedLibrary = createMockSharedLibrary(new String[] {"a.dex", "b.dex"}); String[] contexts = DexoptUtils.getClassLoaderContexts( - data.info, sharedLibrary, data.pathsWithCode); + data.pkg, sharedLibrary, data.pathsWithCode); assertEquals(1, contexts.length); assertEquals("DLC[]{PCL[a.dex:b.dex]}", contexts[0]); @@ -270,9 +291,9 @@ public class DexoptUtilsTest { @Test public void tesNoSplitsNoSharedLibraries() { - TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, false, false); + TestData data = createMockApplicationInfo(PATH_CLASS_LOADER_NAME, false, false, true); String[] contexts = DexoptUtils.getClassLoaderContexts( - data.info, null, data.pathsWithCode); + data.pkg, null, data.pathsWithCode); assertEquals(1, contexts.length); assertEquals("PCL[]", contexts[0]); @@ -281,9 +302,9 @@ public class DexoptUtilsTest { @Test public void tesNoSplitDelegateLastNoSharedLibraries() { TestData data = createMockApplicationInfo( - DELEGATE_LAST_CLASS_LOADER_NAME, false, false); + DELEGATE_LAST_CLASS_LOADER_NAME, false, false, true); String[] contexts = DexoptUtils.getClassLoaderContexts( - data.info, null, data.pathsWithCode); + data.pkg, null, data.pathsWithCode); assertEquals(1, contexts.length); assertEquals("DLC[]", contexts[0]); @@ -291,13 +312,13 @@ public class DexoptUtilsTest { @Test public void testContextWithNoCode() { - TestData data = createMockApplicationInfo(null, true, false); + TestData data = createMockApplicationInfo(null, true, false, true); Arrays.fill(data.pathsWithCode, false); List<SharedLibraryInfo> sharedLibrary = createMockSharedLibrary(new String[] {"a.dex", "b.dex"}); String[] contexts = DexoptUtils.getClassLoaderContexts( - data.info, sharedLibrary, data.pathsWithCode); + data.pkg, sharedLibrary, data.pathsWithCode); assertEquals(9, contexts.length); assertEquals(null, contexts[0]); @@ -312,12 +333,12 @@ public class DexoptUtilsTest { @Test public void testContextBaseNoCode() { - TestData data = createMockApplicationInfo(null, true, true); + TestData data = createMockApplicationInfo(null, true, true, true); data.pathsWithCode[0] = false; List<SharedLibraryInfo> sharedLibrary = createMockSharedLibrary(new String[] {"a.dex", "b.dex"}); String[] contexts = DexoptUtils.getClassLoaderContexts( - data.info, sharedLibrary, data.pathsWithCode); + data.pkg, sharedLibrary, data.pathsWithCode); assertEquals(9, contexts.length); assertEquals(null, contexts[0]); |