Revert "Revert "Deprecate PackageParser#Package""
This reverts commit 8e18a0ab8980a3092d6c7e1d2edc6407655af609.
Exempt-From-Owner-Approval: Revert to re-add approved change
Change-Id: I5b5195470f365a2347cbf444cc0494d119e42ffc
diff --git a/Android.bp b/Android.bp
index 9426a9c..661b1cc 100644
--- a/Android.bp
+++ b/Android.bp
@@ -372,7 +372,7 @@
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 @@
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 0394a7a..97f009c 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -878,7 +878,7 @@
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
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
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 e724443..26193f6 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1376,7 +1376,8 @@
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/AndroidHidlUpdater.java b/core/java/android/content/pm/AndroidHidlUpdater.java
deleted file mode 100644
index d0657e5..0000000
--- a/core/java/android/content/pm/AndroidHidlUpdater.java
+++ /dev/null
@@ -1,52 +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.SharedLibraryNames.ANDROID_HIDL_BASE;
-import static android.content.pm.SharedLibraryNames.ANDROID_HIDL_MANAGER;
-
-import android.content.pm.PackageParser.Package;
-import android.os.Build;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-/**
- * Updates a package to ensure that if it targets <= P that the android.hidl.base-V1.0-java
- * and android.hidl.manager-V1.0-java libraries are included by default.
- *
- * @hide
- */
-@VisibleForTesting
-public class AndroidHidlUpdater extends PackageSharedLibraryUpdater {
-
- @Override
- public void updatePackage(Package pkg) {
- ApplicationInfo info = pkg.applicationInfo;
-
- // This was the default <= P and is maintained for backwards compatibility.
- boolean isLegacy = info.targetSdkVersion <= Build.VERSION_CODES.P;
- // Only system apps use these libraries
- boolean isSystem = info.isSystemApp() || info.isUpdatedSystemApp();
-
- if (isLegacy && isSystem) {
- prefixRequiredLibrary(pkg, ANDROID_HIDL_BASE);
- prefixRequiredLibrary(pkg, ANDROID_HIDL_MANAGER);
- } else {
- removeLibrary(pkg, ANDROID_HIDL_BASE);
- removeLibrary(pkg, ANDROID_HIDL_MANAGER);
- }
- }
-}
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index d6fb28f..aa0002d 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -373,8 +373,9 @@
/**
* 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 cf21e96..65ee1e5 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -57,6 +57,12 @@
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.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 @@
* @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 static final String ANDROID_MANIFEST_FILENAME = "AndroidManifest.xml";
/** Path prefix for apps on expanded storage */
- private static final String MNT_EXPAND = "/mnt/expand/";
+ public 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";
+ 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";
- private static final String METADATA_MAX_ASPECT_RATIO = "android.max_aspect";
+ 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 @@
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_COMPATIBLE_SCREENS);
+ CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
+ CHILD_PACKAGE_TAGS.add(TAG_FEATURE_GROUP);
+ CHILD_PACKAGE_TAGS.add(TAG_INSTRUMENTATION);
+ CHILD_PACKAGE_TAGS.add(TAG_SUPPORT_SCREENS);
+ CHILD_PACKAGE_TAGS.add(TAG_SUPPORTS_INPUT);
CHILD_PACKAGE_TAGS.add(TAG_USES_CONFIGURATION);
CHILD_PACKAGE_TAGS.add(TAG_USES_FEATURE);
- 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_SUPPORTS_INPUT);
- CHILD_PACKAGE_TAGS.add(TAG_EAT_COMMENT);
+ 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 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 @@
* @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;
- private int mParseError = PackageManager.INSTALL_SUCCEEDED;
+ public int mParseError = PackageManager.INSTALL_SUCCEEDED;
- private static boolean sCompatibilityModeEnabled = true;
- private static boolean sUseRoundIcon = false;
+ public ThreadLocal<ApkParseUtils.ParseResult> mSharedResult
+ = ThreadLocal.withInitial(ApkParseUtils.ParseResult::new);
- private static final int PARSE_DEFAULT_INSTALL_LOCATION =
+ public static boolean sCompatibilityModeEnabled = true;
+ public static boolean sUseRoundIcon = false;
+
+ 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 @@
* 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 @@
@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 @@
* 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 @@
* 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 @@
+ "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 */);
- }
-
- /**
- * 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 @@
}
@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 @@
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 @@
}
@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 @@
* 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 @@
/**
* 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 @@
* 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 @@
* 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 @@
* 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 @@
? 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
/**
* 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 @@
// 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 @@
/** 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 @@
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 @@
* 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 @@
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 @@
};
}
+ /**
+ * @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 @@
}
}
+ /**
+ * @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 @@
};
}
+ /**
+ * @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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
};
}
+ /**
+ * @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 @@
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 @@
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 @@
};
}
+ /**
+ * @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 @@
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 @@
};
}
+ /**
+ * @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 @@
return pi;
}
+ /**
+ * @deprecated use {@link ComponentParseUtils.ParsedInstrumentation}
+ */
+ @Deprecated
public final static class Instrumentation extends Component<IntentInfo> implements
Parcelable {
@UnsupportedAppUsage
@@ -8316,7 +8333,12 @@
};
}
+ /**
+ * @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 @@
return ii;
}
+ /**
+ * @deprecated use {@link ComponentParseUtils.ParsedIntentInfo}
+ */
+ @Deprecated
public static abstract class IntentInfo extends IntentFilter {
@UnsupportedAppUsage
public boolean hasDefault;
@@ -8371,8 +8397,10 @@
}
}
- 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 @@
}
}
+ /**
+ * @deprecated use {@link ComponentParseUtils.ParsedServiceIntentInfo}
+ */
+ @Deprecated
public final static class ServiceIntentInfo extends IntentInfo {
@UnsupportedAppUsage
public Service service;
@@ -8419,6 +8451,10 @@
}
}
+ /**
+ * @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/PackageSharedLibraryUpdater.java b/core/java/android/content/pm/PackageSharedLibraryUpdater.java
deleted file mode 100644
index 1565d9c..0000000
--- a/core/java/android/content/pm/PackageSharedLibraryUpdater.java
+++ /dev/null
@@ -1,101 +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 android.annotation.NonNull;
-import android.annotation.Nullable;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
-
-import java.util.ArrayList;
-
-/**
- * Base for classes that update a {@link PackageParser.Package}'s shared libraries.
- *
- * @hide
- */
-@VisibleForTesting
-public abstract class PackageSharedLibraryUpdater {
-
- /**
- * Update the package's shared libraries.
- *
- * @param pkg the package to update.
- */
- public abstract void updatePackage(PackageParser.Package pkg);
-
- static void removeLibrary(PackageParser.Package pkg, String libraryName) {
- pkg.usesLibraries = ArrayUtils.remove(pkg.usesLibraries, libraryName);
- pkg.usesOptionalLibraries =
- ArrayUtils.remove(pkg.usesOptionalLibraries, libraryName);
- }
-
- static @NonNull
- <T> ArrayList<T> prefix(@Nullable ArrayList<T> cur, T val) {
- if (cur == null) {
- cur = new ArrayList<>();
- }
- cur.add(0, val);
- return cur;
- }
-
- private static boolean isLibraryPresent(ArrayList<String> usesLibraries,
- ArrayList<String> usesOptionalLibraries, String apacheHttpLegacy) {
- return ArrayUtils.contains(usesLibraries, apacheHttpLegacy)
- || ArrayUtils.contains(usesOptionalLibraries, apacheHttpLegacy);
- }
-
- /**
- * Add an implicit dependency.
- *
- * <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 existingLibrary the existing library.
- * @param implicitDependency the implicit dependency to add
- */
- void prefixImplicitDependency(PackageParser.Package pkg, String existingLibrary,
- String implicitDependency) {
- ArrayList<String> usesLibraries = pkg.usesLibraries;
- ArrayList<String> usesOptionalLibraries = pkg.usesOptionalLibraries;
-
- if (!isLibraryPresent(usesLibraries, usesOptionalLibraries, implicitDependency)) {
- if (ArrayUtils.contains(usesLibraries, existingLibrary)) {
- prefix(usesLibraries, implicitDependency);
- } else if (ArrayUtils.contains(usesOptionalLibraries, existingLibrary)) {
- prefix(usesOptionalLibraries, implicitDependency);
- }
-
- pkg.usesLibraries = usesLibraries;
- pkg.usesOptionalLibraries = usesOptionalLibraries;
- }
- }
-
- void prefixRequiredLibrary(PackageParser.Package pkg, String libraryName) {
- ArrayList<String> usesLibraries = pkg.usesLibraries;
- ArrayList<String> usesOptionalLibraries = pkg.usesOptionalLibraries;
-
- boolean alreadyPresent = isLibraryPresent(
- usesLibraries, usesOptionalLibraries, libraryName);
- if (!alreadyPresent) {
- usesLibraries = prefix(usesLibraries, libraryName);
-
- pkg.usesLibraries = usesLibraries;
- }
- }
-}
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 5c74efb..55574c3 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_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 @@
&& (!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 @@
* 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 @@
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 @@
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 3488cc3..2863b26 100644
--- a/core/java/android/content/pm/SharedLibraryInfo.java
+++ b/core/java/android/content/pm/SharedLibraryInfo.java
@@ -20,6 +20,7 @@
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 @@
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 5d10b88..4cd201f 100644
--- a/core/java/android/content/pm/dex/DexMetadataHelper.java
+++ b/core/java/android/content/pm/dex/DexMetadataHelper.java
@@ -22,6 +22,7 @@
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 @@
*
* 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 @@
*
* @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 0000000..ab3cf7c
--- /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 0000000..bef984d
--- /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 0000000..b7595d2
--- /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 0000000..ac2e373
--- /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 0000000..0f35b27
--- /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 0000000..adf2a4f
--- /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 0000000..363cf80
--- /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 0000000..7b329eb
--- /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 0000000..05cf586
--- /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 0000000..43c1f6e
--- /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/parsing/library/AndroidHidlUpdater.java b/core/java/android/content/pm/parsing/library/AndroidHidlUpdater.java
new file mode 100644
index 0000000..81b4bc5
--- /dev/null
+++ b/core/java/android/content/pm/parsing/library/AndroidHidlUpdater.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 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.ParsedPackage;
+import android.os.Build;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Updates a package to ensure that if it targets <= P that the android.hidl.base-V1.0-java
+ * and android.hidl.manager-V1.0-java libraries are included by default.
+ *
+ * @hide
+ */
+@VisibleForTesting
+public class AndroidHidlUpdater extends PackageSharedLibraryUpdater {
+
+ @Override
+ public void updatePackage(ParsedPackage parsedPackage) {
+ // This was the default <= P and is maintained for backwards compatibility.
+ boolean isLegacy = parsedPackage.getTargetSdkVersion() <= Build.VERSION_CODES.P;
+ // Only system apps use these libraries
+ boolean isSystem = parsedPackage.isSystemApp() || parsedPackage.isUpdatedSystemApp();
+
+ if (isLegacy && isSystem) {
+ prefixRequiredLibrary(parsedPackage, ANDROID_HIDL_BASE);
+ prefixRequiredLibrary(parsedPackage, ANDROID_HIDL_MANAGER);
+ } else {
+ 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
similarity index 88%
rename from core/java/android/content/pm/AndroidTestBaseUpdater.java
rename to core/java/android/content/pm/parsing/library/AndroidTestBaseUpdater.java
index 18d3ba3..fc02a86 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 @@
}
@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 @@
// 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
similarity index 67%
rename from core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java
rename to core/java/android/content/pm/parsing/library/OrgApacheHttpLegacyUpdater.java
index 707443b..613a06b 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 @@
@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
similarity index 80%
rename from core/java/android/content/pm/PackageBackwardCompatibility.java
rename to core/java/android/content/pm/parsing/library/PackageBackwardCompatibility.java
index 4331bd4..1220fc4 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.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 @@
// 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 @@
}
/**
- * 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 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 @@
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 @@
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/parsing/library/PackageSharedLibraryUpdater.java b/core/java/android/content/pm/parsing/library/PackageSharedLibraryUpdater.java
new file mode 100644
index 0000000..8b27d14
--- /dev/null
+++ b/core/java/android/content/pm/parsing/library/PackageSharedLibraryUpdater.java
@@ -0,0 +1,97 @@
+/*
+ * 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 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 ParsedPackage}'s shared libraries.
+ *
+ * @hide
+ */
+@VisibleForTesting
+public abstract class PackageSharedLibraryUpdater {
+
+ /**
+ * Update the package's shared libraries.
+ *
+ * @param parsedPackage the package to update.
+ */
+ public abstract void updatePackage(ParsedPackage parsedPackage);
+
+ static void removeLibrary(ParsedPackage parsedPackage, String libraryName) {
+ parsedPackage.removeUsesLibrary(libraryName)
+ .removeUsesOptionalLibrary(libraryName);
+ }
+
+ static @NonNull
+ <T> ArrayList<T> prefix(@Nullable ArrayList<T> cur, T val) {
+ if (cur == null) {
+ cur = new ArrayList<>();
+ }
+ cur.add(0, val);
+ return cur;
+ }
+
+ private static boolean isLibraryPresent(List<String> usesLibraries,
+ List<String> usesOptionalLibraries, String apacheHttpLegacy) {
+ return ArrayUtils.contains(usesLibraries, apacheHttpLegacy)
+ || ArrayUtils.contains(usesOptionalLibraries, apacheHttpLegacy);
+ }
+
+ /**
+ * Add an implicit dependency.
+ *
+ * <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 parsedPackage the {@link ParsedPackage} to update.
+ * @param existingLibrary the existing library.
+ * @param implicitDependency the implicit dependency to add
+ */
+ void prefixImplicitDependency(ParsedPackage parsedPackage, String existingLibrary,
+ String implicitDependency) {
+ List<String> usesLibraries = parsedPackage.getUsesLibraries();
+ List<String> usesOptionalLibraries = parsedPackage.getUsesOptionalLibraries();
+
+ if (!isLibraryPresent(usesLibraries, usesOptionalLibraries, implicitDependency)) {
+ if (ArrayUtils.contains(usesLibraries, existingLibrary)) {
+ parsedPackage.addUsesLibrary(0, implicitDependency);
+ } else if (ArrayUtils.contains(usesOptionalLibraries, existingLibrary)) {
+ parsedPackage.addUsesOptionalLibrary(0, implicitDependency);
+ }
+ }
+ }
+
+ void prefixRequiredLibrary(ParsedPackage parsedPackage, String libraryName) {
+ List<String> usesLibraries = parsedPackage.getUsesLibraries();
+ List<String> usesOptionalLibraries = parsedPackage.getUsesOptionalLibraries();
+
+ boolean alreadyPresent = isLibraryPresent(
+ usesLibraries, usesOptionalLibraries, libraryName);
+ if (!alreadyPresent) {
+ parsedPackage.addUsesLibrary(0, libraryName);
+ }
+ }
+}
diff --git a/core/java/android/content/pm/SharedLibraryNames.java b/core/java/android/content/pm/parsing/library/SharedLibraryNames.java
similarity index 91%
rename from core/java/android/content/pm/SharedLibraryNames.java
rename to core/java/android/content/pm/parsing/library/SharedLibraryNames.java
index a607a9f..7b691c0 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 0847fbd..6709ff5 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -28,9 +28,9 @@
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 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 821022f..bc80197 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -600,6 +600,14 @@
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 a4c504b..c009f58 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -74,7 +74,6 @@
":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 249242e..0000000
--- 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 5164cae..0000000
--- 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 57afcb0..0000000
--- 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 2816865..0000000
--- 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 ffe84b7..0000000
--- 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 faa6e9c..0000000
--- 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 e89f264..0000000
--- 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 2bd40a5..0000000
--- 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 a6c4ddc..0000000
--- 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 1e721aa..0000000
--- 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 10d0551..0000000
--- 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 59f9f10..0000000
--- 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 21f6263..0000000
--- 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 b330e75..0000000
--- 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 cc48239..0000000
--- 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 03108ce..0000000
--- 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 7f817d6..0000000
--- 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 834a0bb..0000000
--- 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/PackageBackwardCompatibilityTest.java b/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java
deleted file mode 100644
index ad9814b..0000000
--- a/core/tests/coretests/src/android/content/pm/PackageBackwardCompatibilityTest.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2017 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 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 android.content.pm.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary;
-import android.os.Build;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Assume;
-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();
-
- checkBackwardsCompatibility(before, after);
- }
-
- /**
- * Detect when the android.test.base is not on the bootclasspath.
- *
- * <p>This test will be ignored when org.apache.http.legacy is not on the bootclasspath and
- * succeed otherwise. This allows a developer to ensure that the tests are being run in the
- * correct environment.
- */
- @Test
- public void detectWhenATBisOnBCP() {
- Assume.assumeTrue(PackageBackwardCompatibility.bootClassPathContainsATB());
- }
-
- /**
- * Ensures that the {@link PackageBackwardCompatibility} uses {@link OrgApacheHttpLegacyUpdater}
- * and {@link AndroidTestBaseUpdater} when necessary.
- *
- * <p>More comprehensive tests for that class can be found in
- * {@link OrgApacheHttpLegacyUpdaterTest}.
- */
- @Test
- public void targeted_at_O() {
- PackageBuilder before = builder()
- .targetSdkVersion(Build.VERSION_CODES.O);
-
- List<String> expected = new ArrayList<>();
- if (!PackageBackwardCompatibility.bootClassPathContainsATB()) {
- expected.add(ANDROID_TEST_BASE);
- }
- expected.add(ORG_APACHE_HTTP_LEGACY);
-
- PackageBuilder after = builder()
- .targetSdkVersion(Build.VERSION_CODES.O)
- .requiredLibraries(expected);
-
- checkBackwardsCompatibility(before, after);
- }
-
- /**
- * Ensures that the {@link PackageBackwardCompatibility} uses
- * {@link RemoveUnnecessaryAndroidTestBaseLibrary}
- * when necessary.
- *
- * <p>More comprehensive tests for that class can be found in
- * {@link RemoveUnnecessaryAndroidTestBaseLibraryTest}.
- */
- @Test
- public void android_test_base_in_usesLibraries() {
- Assume.assumeTrue("Test requires that "
- + ANDROID_TEST_BASE + " is on the bootclasspath",
- PackageBackwardCompatibility.bootClassPathContainsATB());
-
- 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);
- }
-
- /**
- * Ensures that the {@link PackageBackwardCompatibility} uses a
- * {@link PackageBackwardCompatibility.AndroidTestRunnerSplitUpdater}.
- *
- * <p>More comprehensive tests for that class can be found in
- * {@link AndroidTestRunnerSplitUpdaterTest}.
- */
- @Test
- public void android_test_runner_in_usesLibraries() {
- PackageBuilder before = builder().requiredLibraries(ANDROID_TEST_RUNNER);
-
- List<String> expected = new ArrayList<>();
- if (!PackageBackwardCompatibility.bootClassPathContainsATB()) {
- expected.add(ANDROID_TEST_BASE);
- }
- expected.add(ANDROID_TEST_MOCK);
- expected.add(ANDROID_TEST_RUNNER);
-
- PackageBuilder after = builder()
- .requiredLibraries(expected);
-
- checkBackwardsCompatibility(before, after);
- }
-
- private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) {
- checkBackwardsCompatibility(before, after, PackageBackwardCompatibility::getInstance);
- }
-}
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 f7544af..0000000
--- 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 5c7f2af..cb23850 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 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 @@
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 @@
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 @@
*
* 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 @@
/**
* 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());
- assertEquals(1, p.activities.size());
+ // For normal apps, a Activity that forwards to the App Details page is added.
+ assertEquals("android.app.AppDetailsActivity", p.getActivities().get(1)
+ .className);
+
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 @@
}
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 @@
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 @@
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 71a0e5e..0000000
--- 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 216b0c8..0000000
--- 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 fc60980..0000000
--- 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 49849ee..1e0bfb0 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.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 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 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 @@
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 @@
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 @@
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 @@
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 0000000..21479c0
--- /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 0000000..65ae219
--- /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 0000000..38755b9
--- /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 0000000..4c7899b
--- /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/parsing/library/PackageBackwardCompatibilityTest.java b/core/tests/coretests/src/android/content/pm/parsing/library/PackageBackwardCompatibilityTest.java
new file mode 100644
index 0000000..00d468d
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/parsing/library/PackageBackwardCompatibilityTest.java
@@ -0,0 +1,151 @@
+/*
+ * 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 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.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;
+
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@SmallTest
+@RunWith(JUnit4.class)
+public class PackageBackwardCompatibilityTest extends PackageSharedLibraryUpdaterTest {
+
+ @Test
+ public void null_usesLibraries_and_usesOptionalLibraries() {
+ 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);
+ }
+
+ /**
+ * Detect when the android.test.base is not on the bootclasspath.
+ *
+ * <p>This test will be ignored when org.apache.http.legacy is not on the bootclasspath and
+ * succeed otherwise. This allows a developer to ensure that the tests are being run in the
+ * correct environment.
+ */
+ @Test
+ public void detectWhenATBisOnBCP() {
+ Assume.assumeTrue(PackageBackwardCompatibility.bootClassPathContainsATB());
+ }
+
+ /**
+ * Ensures that the {@link PackageBackwardCompatibility} uses {@link OrgApacheHttpLegacyUpdater}
+ * and {@link AndroidTestBaseUpdater} when necessary.
+ *
+ * <p>More comprehensive tests for that class can be found in
+ * {@link OrgApacheHttpLegacyUpdaterTest}.
+ */
+ @Test
+ public void targeted_at_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);
+
+ if (!PackageBackwardCompatibility.bootClassPathContainsATB()) {
+ after.addUsesLibrary(ANDROID_TEST_BASE);
+ }
+ after.addUsesLibrary(ORG_APACHE_HTTP_LEGACY);
+
+ checkBackwardsCompatibility(before, after.hideAsParsed().hideAsFinal());
+ }
+
+ /**
+ * Ensures that the {@link PackageBackwardCompatibility} uses
+ * {@link RemoveUnnecessaryAndroidTestBaseLibrary}
+ * when necessary.
+ *
+ * <p>More comprehensive tests for that class can be found in
+ * {@link RemoveUnnecessaryAndroidTestBaseLibraryTest}.
+ */
+ @Test
+ public void android_test_base_in_usesLibraries() {
+ Assume.assumeTrue("Test requires that "
+ + ANDROID_TEST_BASE + " is on the bootclasspath",
+ PackageBackwardCompatibility.bootClassPathContainsATB());
+
+ 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.
+ AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
+ .hideAsParsed()
+ .hideAsFinal();
+
+ checkBackwardsCompatibility(before, after);
+ }
+
+ /**
+ * Ensures that the {@link PackageBackwardCompatibility} uses a
+ * {@link PackageBackwardCompatibility.AndroidTestRunnerSplitUpdater}.
+ *
+ * <p>More comprehensive tests for that class can be found in
+ * {@link AndroidTestRunnerSplitUpdaterTest}.
+ */
+ @Test
+ public void android_test_runner_in_usesLibraries() {
+ ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
+ .addUsesLibrary(ANDROID_TEST_RUNNER)
+ .hideAsParsed();
+
+ ParsingPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+ .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT);
+ if (!PackageBackwardCompatibility.bootClassPathContainsATB()) {
+ after.addUsesLibrary(ANDROID_TEST_BASE);
+ }
+ after.addUsesLibrary(ANDROID_TEST_MOCK);
+ after.addUsesLibrary(ANDROID_TEST_RUNNER);
+
+ checkBackwardsCompatibility(before, after.hideAsParsed().hideAsFinal());
+ }
+
+ 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 0000000..e7a80e1a
--- /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 0000000..fd3ba2b
--- /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 0000000..d3494d9
--- /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 de6cca5..21f5f89 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.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 @@
* @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 @@
* 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 @@
/**
* 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 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 @@
* @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 @@
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 @@
*
* @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 @@
* 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 14ef2d3a..be548a2 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.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 b1eb7e7..591f749 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 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.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 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 @@
/** 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 @@
/** 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 @@
* /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 @@
}
/** 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 @@
@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 @@
@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 @@
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 @@
@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 @@
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 @@
@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 @@
@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 @@
}
/** 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 @@
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 @@
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 @@
+ " 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 @@
}
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 @@
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 @@
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 @@
}
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 @@
}
@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 @@
} else {
r.append(' ');
}
- r.append(a.info.name);
+ r.append(a.getName());
}
}
if (DEBUG_PACKAGE_SCANNING && chatty) {
@@ -571,20 +623,17 @@
}
@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 @@
// 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 @@
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 @@
} else {
r.append(' ');
}
- r.append(p.info.name);
+ r.append(p.getName());
}
}
if (DEBUG_PACKAGE_SCANNING && chatty) {
@@ -636,13 +685,11 @@
}
@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 @@
} else {
r.append(' ');
}
- r.append(a.info.name);
+ r.append(a.getName());
}
}
if (DEBUG_PACKAGE_SCANNING && chatty) {
@@ -659,13 +706,11 @@
}
@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 @@
} else {
r.append(' ');
}
- r.append(s.info.name);
+ r.append(s.getName());
}
}
if (DEBUG_PACKAGE_SCANNING && chatty) {
@@ -681,13 +726,12 @@
}
}
-
/**
* <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 @@
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 @@
}
}
- 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 @@
/**
* 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 @@
* <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 @@
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 @@
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 @@
}
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 @@
}
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
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 @@
}
@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 @@
} 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 @@
} 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 @@
} 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 @@
} else {
r.append(' ');
}
- r.append(s.info.name);
+ r.append(s.getName());
}
}
if (DEBUG_REMOVE && chatty) {
@@ -1054,26 +1112,26 @@
}
@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 @@
}
}
- 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 @@
}
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 @@
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 @@
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 @@
@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 @@
}
@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 @@
}
@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 @@
}
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 @@
}
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 @@
}
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 @@
}
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 @@
@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 @@
@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 @@
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 @@
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 @@
@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 @@
}
@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;
}
- 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.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;
}
- final PackageParser.Provider provider = info.provider;
- PackageSetting ps = (PackageSetting) provider.owner.mExtras;
+
+ if (!sPackageManagerInternal.isEnabledAndMatches(provider, mFlags, userId)) {
+ return null;
+ }
+
+ PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting(
+ filter.getPackageName());
if (ps == null) {
return null;
}
@@ -1527,7 +1657,7 @@
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 @@
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 @@
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 @@
@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 @@
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 @@
}
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 @@
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 @@
@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 @@
}
@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;
}
- final PackageParser.Service service = info.service;
- PackageSetting ps = (PackageSetting) service.owner.mExtras;
+
+ if (!sPackageManagerInternal.isEnabledAndMatches(service, mFlags, userId)) {
+ return null;
+ }
+
+ 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 @@
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 @@
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 @@
@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 @@
}
// 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 @@
/** 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 @@
/** 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 @@
/** 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 @@
/** 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 @@
/** 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 9e04c4b..f9113fa 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.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 @@
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 @@
}
// 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 @@
}
@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 @@
// 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 @@
// 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 @@
// 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 @@
}
// 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 @@
}
@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 @@
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 @@
}
@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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
@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 @@
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 ec48713..0a065eb 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 @@
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) {
+
+ public static String[] getAppDexInstructionSets(String primaryCpuAbi, String secondaryCpuAbi) {
+ if (primaryCpuAbi != null) {
+ if (secondaryCpuAbi != null) {
return new String[] {
- VMRuntime.getInstructionSet(info.primaryCpuAbi),
- VMRuntime.getInstructionSet(info.secondaryCpuAbi) };
+ VMRuntime.getInstructionSet(primaryCpuAbi),
+ VMRuntime.getInstructionSet(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) {
- return new String[] {
- VMRuntime.getInstructionSet(ps.primaryCpuAbiString),
- VMRuntime.getInstructionSet(ps.secondaryCpuAbiString) };
- } else {
- return new String[] {
- VMRuntime.getInstructionSet(ps.primaryCpuAbiString) };
+ VMRuntime.getInstructionSet(primaryCpuAbi) };
}
}
@@ -124,4 +110,12 @@
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 a4e9d10..c97d85d 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 @@
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 @@
setState(STATE_VERIFICATION_PENDING);
}
- public ArrayList<PackageParser.ActivityIntentInfo> getFilters() {
+ public ArrayList<ComponentParseUtils.ParsedActivityIntentInfo> getFilters() {
return mFilters;
}
@@ -123,7 +123,7 @@
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 93d3b77..70c0f8d 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 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 @@
*
* 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 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 @@
* 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 @@
* 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 @@
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 f7fd1b2..673e265 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.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 @@
}
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 @@
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 d49ecdd..ae7a4a7 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 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 @@
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 @@
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 @@
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 @@
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 @@
/**
* 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 @@
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 @@
}
// 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 @@
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 c21d0cf..d7c161c 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 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 @@
* 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 @@
*/
@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 @@
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 @@
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 7e47800..66acb86 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 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 @@
@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 @@
}
@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 @@
* {@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 @@
// 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 @@
@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 @@
// 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 @@
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 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 @@
@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 @@
// 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 @@
} 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 4f7c8c8..2b42221 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 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.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 @@
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 @@
* <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 @@
* 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 @@
// 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 @@
}
}
- 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 @@
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 @@
* 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 @@
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 @@
// 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 @@
/**
* 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 @@
// 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 @@
}
/**
- * 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 @@
}
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 @@
// 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 @@
// 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 @@
* 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 @@
}
// 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 @@
* 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 883baf7..518ec50 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.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 @@
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 @@
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 031b5ce..10685b0 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 com.android.internal.util.ArrayUtils;
+import java.util.Map;
+
public class PackageKeySetData {
static final long KEYSET_UNASSIGNED = -1;
@@ -90,16 +92,13 @@
/*
* 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 3d4247e7..8fef6b9 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_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.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.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.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 @@
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 @@
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 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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
@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 @@
}
}
- 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 @@
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 @@
}
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 @@
? 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 @@
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 @@
}
// 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 @@
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 @@
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 @@
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 @@
/*
* 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 @@
// 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 @@
// 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 @@
}
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 @@
// 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 @@
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 @@
* 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 @@
}
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 @@
}
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 @@
// 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 @@
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 @@
}
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 @@
}
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 @@
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 @@
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 @@
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 @@
}
}
- 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 @@
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 @@
// 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 @@
}
// 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 @@
if (index < 0) {
continue;
}
- if (uidPs.pkg.usesStaticLibrariesVersions[index] == libraryInfo.getLongVersion()) {
+ if (uidPs.pkg.getUsesStaticLibrariesVersions()[index]
+ == libraryInfo.getLongVersion()) {
return false;
}
}
@@ -4410,13 +4436,13 @@
// 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 @@
// 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 @@
}
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 @@
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 @@
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 @@
}
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 @@
}
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 @@
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 @@
}
// 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 @@
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 @@
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 @@
@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 @@
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 @@
* 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 @@
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 @@
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 @@
list.add(ri);
}
}
- return applyPostResolutionFilter(
+
+ List<ResolveInfo> result = applyPostResolutionFilter(
list, instantAppPkgName, allowDynamicSplits, filterCallingUid, resolveForStart,
userId, intent);
+ return result;
}
// reader
@@ -6686,11 +6739,11 @@
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 @@
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 @@
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 @@
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 @@
}
} 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 @@
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 @@
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 @@
}
} 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 @@
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 @@
}
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 @@
// 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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
!= 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 @@
*/
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 @@
* @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 @@
* 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 @@
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 @@
}
// 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 @@
* <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 @@
// 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 @@
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 @@
}
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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
mSharedLibraries,
mPackages,
Collections.singletonMap(
- pkgName, getSettingsVersionForPackage(pkg)),
+ pkgName, getSettingsVersionForPackage(parsedPackage)),
Collections.singletonMap(pkgName,
getSharedLibLatestVersionSetting(scanResult))),
mSettings.mKeySetManagerService);
@@ -8925,16 +8927,17 @@
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 @@
return;
}
- List<PackageParser.Package> pkgs;
+ List<AndroidPackage> pkgs;
synchronized (mLock) {
pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this);
}
@@ -9058,8 +9061,8 @@
/*
* 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 @@
* 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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
if (DEBUG_DEXOPT) {
Log.i(TAG, "Updating app " + numberOfPackagesVisited + " of " +
- numberOfPackagesToDexopt + ": " + pkg.packageName);
+ numberOfPackagesToDexopt + ": " + pkg.getPackageName());
}
if (showDialog) {
@@ -9191,7 +9195,7 @@
dexoptFlags |= DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE;
}
int primaryDexOptStaus = performDexOptTraced(new DexoptOptions(
- pkg.packageName,
+ pkg.getPackageName(),
pkgCompilationReason,
dexoptFlags));
@@ -9235,11 +9239,11 @@
@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 @@
*/
@Override
public boolean compileLayouts(String packageName) {
- PackageParser.Package pkg;
+ AndroidPackage pkg;
synchronized (mLock) {
pkg = mPackages.get(packageName);
if (pkg == null) {
@@ -9366,7 +9370,7 @@
// 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 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 @@
// 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 @@
// 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 @@
}
return pdo.performDexOpt(p, instructionSets,
getOrCreateCompilerPackageStats(p),
- mDexManager.getPackageUseInfoOrDefault(p.packageName), options);
+ mDexManager.getPackageUseInfoOrDefault(p.getPackageName()), options);
}
/**
@@ -9480,11 +9485,11 @@
}
}
- 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 @@
}
}
- 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 @@
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 @@
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 @@
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 @@
@Override
public void dumpProfiles(String packageName) {
- PackageParser.Package pkg;
+ AndroidPackage pkg;
synchronized (mLock) {
pkg = mPackages.get(packageName);
if (pkg == null) {
@@ -9617,7 +9622,7 @@
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 void forceDexOpt(String packageName) {
enforceSystemOrRoot("forceDexOpt");
- PackageParser.Package pkg;
+ AndroidPackage pkg;
synchronized (mLock) {
pkg = mPackages.get(packageName);
if (pkg == null) {
@@ -9659,15 +9664,15 @@
}
@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 @@
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 @@
// - 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 @@
}
@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 @@
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 @@
// 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 @@
@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 @@
+ " 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 @@
// 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 @@
// 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 @@
}
@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 @@
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 @@
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 @@
}
@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 @@
@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 @@
/** 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 @@
@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 @@
*/
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 @@
&& 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 @@
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 @@
// 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 @@
* 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 @@
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 @@
// 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 @@
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 @@
}
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 @@
}
}
- 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 @@
* <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 @@
* 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 @@
// 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 @@
* <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 @@
* @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 @@
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 @@
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 @@
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 @@
}
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 @@
// 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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
}
}
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 @@
*
* @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 @@
* 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;
- }
- }
- }
+ parsedPackage
+ .clearProtectedBroadcasts()
+ .markNotActivitiesAsNotExportedIfSingleUser();
}
- if ((scanFlags & SCAN_AS_PRIVILEGED) != 0) {
- pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
- }
-
- 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;
- }
+ parsedPackage.setSignedWithPlatformKey(
+ (PLATFORM_PACKAGE_NAME.equals(parsedPackage.getPackageName())
+ || (platformPkg != null && compareSignatures(
+ platformPkg.getSigningDetails().signatures,
+ parsedPackage.getSigningDetails().signatures
+ ) == PackageManager.SIGNATURE_MATCH))
+ );
- if (!isSystemApp(pkg)) {
+ 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 @@
*
* @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 @@
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 @@
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 @@
}
// 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 @@
// 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 @@
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 @@
}
}
- // 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 @@
// 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 @@
}
// 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 @@
!= 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 @@
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 @@
// 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 @@
* 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);
- }
+ // 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<PackageParser.Package> clientLibPkgs = null;
+ 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
} 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 @@
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 @@
}
}
- 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 @@
// 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 @@
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 @@
} else {
r.append(' ');
}
- r.append(a.info.name);
+ r.append(a.getName());
}
}
if (r != null) {
@@ -11936,12 +11799,12 @@
}
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 @@
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 @@
// 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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
return -1;
}
- return pkg.applicationInfo.uid;
+ return pkg.getUid();
}
}
@@ -13347,26 +13211,33 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
if (dataOwnerPkg != null) {
if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags,
- dataOwnerPkg.applicationInfo.flags)) {
+ dataOwnerPkg.getFlags())) {
try {
checkDowngrade(dataOwnerPkg, pkgLite);
} catch (PackageManagerException e) {
@@ -14070,7 +13941,7 @@
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 @@
* 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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
}
}
- /**
- * 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
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 @@
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 @@
| (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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
// 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 @@
}
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 @@
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 @@
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 @@
: 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 @@
// 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 @@
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 @@
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 @@
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 @@
} 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 @@
| 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 @@
// 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 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 @@
this.freezer = freezer;
this.originalPs = originalPs;
this.disabledPs = disabledPs;
- this.childPackageSettings = childPackageSettings;
}
}
@@ -16154,10 +15927,10 @@
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 @@
// 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 @@
// 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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
}
}
- 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 @@
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 @@
// 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 @@
// 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 @@
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 @@
}
}
- 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 @@
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 @@
// 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 @@
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 @@
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 @@
// 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 @@
}
// 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 @@
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 @@
| (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 @@
* <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 @@
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 @@
} 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 @@
}
}
- 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 @@
(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 @@
+ " 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 @@
// 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 @@
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 @@
}
@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 @@
}
}
- 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 @@
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 @@
}
private void deleteTempPackageFiles() {
+ // TODO: Is this used?
final FilenameFilter filter =
(dir, name) -> name.startsWith("vmdl") && name.endsWith(".tmp");
}
@@ -17225,11 +16979,11 @@
});
}
- 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 @@
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 @@
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 @@
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 @@
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 @@
|| 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
deleteInstalledPackageLIF(deletedPs, true, flags, allUserHandles,
- outInfo, writeSettings, disabledPs.pkg);
+ outInfo, writeSettings);
// writer
synchronized (mLock) {
@@ -17919,16 +17644,16 @@
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 @@
/**
* 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 @@
}
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 @@
// 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 @@
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 @@
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 @@
// 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 @@
@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 @@
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 @@
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 @@
} 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 @@
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 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 @@
}
// 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 @@
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 @@
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 @@
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 @@
} 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 @@
@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 @@
}
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
}
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 @@
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 @@
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 @@
"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 @@
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 @@
* <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 @@
* 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 @@
}
}
- 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);
+ ps = mSettings.mPackages.get(pkg.getPackageName());
}
- final String volumeUuid = pkg.volumeUuid;
- final String packageName = pkg.packageName;
+ final String volumeUuid = pkg.getVolumeUuid();
+ final String packageName = pkg.getPackageName();
- ApplicationInfo app = (ps == null)
- ? pkg.applicationInfo
- : PackageParser.generateApplicationInfo(pkg, 0, ps.readUserState(userId), userId);
- if (app == null) {
- app = pkg.applicationInfo;
- }
+ final int appId = UserHandle.getAppId(pkg.getUid());
- final int appId = UserHandle.getAppId(app.uid);
+ Preconditions.checkNotNull(pkg.getSeInfo());
- Preconditions.checkNotNull(app.seInfo);
-
- 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 @@
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 @@
* 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 @@
*/
private class PackageFreezer implements AutoCloseable {
private final String mPackageName;
- private final PackageFreezer[] mChildren;
private final boolean mWeFroze;
@@ -21927,7 +21523,6 @@
*/
public PackageFreezer() {
mPackageName = null;
- mChildren = null;
mWeFroze = false;
mCloseGuard.open("close");
}
@@ -21941,18 +21536,6 @@
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 @@
if (mWeFroze) {
mFrozenPackages.remove(mPackageName);
}
-
- if (mChildren != null) {
- for (PackageFreezer freezer : mChildren) {
- freezer.close();
- }
- }
}
}
}
@@ -22035,14 +21612,14 @@
// 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 @@
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 @@
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 @@
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 @@
* @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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
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 @@
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 @@
}
@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 @@
}
@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 @@
}
}
+ @Nullable
+ @Override
+ public PackageSetting getPackageSetting(String packageName) {
+ return PackageManagerService.this.getPackageSetting(packageName);
+ }
+
@Override
public PackageList getPackageList(PackageListObserver observer) {
synchronized (mLock) {
@@ -22971,17 +22551,19 @@
}
@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 @@
@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 @@
}
@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 @@
}
@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 @@
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 @@
@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 @@
}
@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 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 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 @@
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 @@
}
@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 @@
*/
@Override
public boolean compileLayouts(String packageName) {
- PackageParser.Package pkg;
+ AndroidPackage pkg;
synchronized (mLock) {
pkg = mPackages.get(packageName);
if (pkg == null) {
@@ -23716,12 +23300,12 @@
@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 @@
}
}
- 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 @@
}
}
- 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 @@
* 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 @@
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 @@
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 @@
}
}
- 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 @@
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 @@
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 ef47410..ded9a9c 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.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 @@
// 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 @@
// 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 @@
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 @@
// 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 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 @@
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 @@
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 @@
* 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 b961096..fff404f 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.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.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 @@
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 d38dd93..bbc0dc9 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 @@
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 @@
/**
* 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 @@
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 @@
: super.getPermissionsState();
}
- public PackageParser.Package getPackage() {
- return pkg;
- }
-
public int getAppId() {
return appId;
}
@@ -132,6 +131,7 @@
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 @@
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 @@
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 @@
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 45ab357..671450d7 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.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 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 @@
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 @@
}
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 @@
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 @@
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 ac1f739..ce2c9e7 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.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.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 @@
}
@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 @@
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 @@
}
@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 @@
}
}
- 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 @@
}
String packageName = tokens[0];
- PackageParser.Package pkg = packages.get(packageName);
+ AndroidPackage pkg = packages.get(packageName);
if (pkg == null) {
continue;
}
@@ -137,12 +137,12 @@
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 @@
}
String packageName = tokens[0];
- PackageParser.Package pkg = packages.get(packageName);
+ AndroidPackage pkg = packages.get(packageName);
if (pkg == null) {
continue;
}
@@ -162,7 +162,8 @@
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 @@
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 4ff3e12..a506514 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.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 @@
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 @@
/**
* 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 @@
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 @@
}
@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 d20f20f..f4076fd 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.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 @@
* 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 @@
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 @@
/**
* 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 @@
* @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 1082eaa..40ad095 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.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.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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
@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 @@
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 @@
// 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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 6480518..0a42ccf 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 @@
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 @@
// 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 @@
// 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 @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 @@
* 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 0a6a435..034c010 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 @@
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 @@
// 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 @@
}
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 @@
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 @@
@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 cc5aec2..486cfef 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.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 @@
* - 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 @@
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 @@
/**
* 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 @@
/**
* 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 @@
/**
* 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 @@
try {
synchronized (mInstallLock) {
return mInstaller.compileLayouts(apkPath, packageName, outDexFile,
- appInfo.uid);
+ pkg.getUid());
}
} finally {
Binder.restoreCallingIdentity(callingId);
@@ -512,15 +513,19 @@
* 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 41dcaa5..29183bb 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 @@
// 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 5a473c1..6e6b137 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 @@
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 @@
* {@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 @@
}
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 @@
// 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 @@
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 @@
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 @@
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 @@
// 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 @@
* 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 8d8e17e..b7443f3 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 @@
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 c39dcfe..cc70aa7 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 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 @@
int protectionLevel;
- PackageParser.Permission perm;
+ ParsedPermission perm;
PermissionInfo pendingPermissionInfo;
@@ -113,12 +115,6 @@
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 @@
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 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 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 @@
(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 @@
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 @@
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 @@
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 @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 @@
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 @@
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 @@
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 @@
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 @@
}
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 2ffba45..369e7bb 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.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 @@
}
}
- @Nullable BasePermission getPermission(String permName) {
+ @Nullable
+ BasePermission getPermission(String permName) {
synchronized (mLock) {
return mSettings.getPermissionLocked(permName);
}
@@ -453,10 +457,9 @@
}
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 @@
return null;
}
synchronized (mLock) {
- return PackageParser.generatePermissionGroupInfo(
+ return PackageInfoUtils.generatePermissionGroupInfo(
mSettings.mPermissionGroups.get(groupName), flags);
}
}
@@ -596,8 +599,13 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
? 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 @@
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 @@
}
}
- 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 @@
"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 @@
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 @@
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 @@
"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 @@
+ 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 @@
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 @@
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 @@
}
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 @@
+ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
* @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 @@
| 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 @@
};
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 @@
// 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 @@
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 @@
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 @@
* @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 @@
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 @@
}
}
- 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 @@
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 @@
r.append(' ');
}
r.append("DUP:");
- r.append(pg.info.name);
+ r.append(pg.getName());
}
}
}
@@ -2175,15 +2186,15 @@
}
- 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 @@
} 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 @@
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 @@
* @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 @@
// 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 @@
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 @@
// 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 @@
if (DEBUG_PERMISSIONS) {
Slog.i(TAG, permName + " is newly added for "
- + pkg.packageName);
+ + pkg.getPackageName());
}
break;
}
@@ -2362,10 +2376,10 @@
}
// 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 @@
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 @@
// 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 @@
if (DEBUG_PERMISSIONS) {
Slog.i(TAG, "Considering granting permission " + perm + " to package "
- + pkg.packageName);
+ + pkg.getPackageName());
}
if (grant != GRANT_DENIED) {
@@ -2696,10 +2710,10 @@
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 @@
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 @@
// 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 @@
}
for (int userId : updatedUserIds) {
- notifyRuntimePermissionStateChanged(pkg.packageName, userId);
+ notifyRuntimePermissionStateChanged(pkg.getPackageName(), userId);
}
}
@@ -2774,10 +2788,10 @@
* @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 @@
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 @@
*/
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 @@
* @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 @@
*/
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 @@
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 @@
*
* <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 @@
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 @@
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 @@
mPrivappPermissionsViolations = new ArraySet<>();
}
mPrivappPermissionsViolations.add(
- pkg.packageName + " (" + pkg.codePath + "): " + perm);
+ pkg.getPackageName() + " (" + pkg.getCodePath() + "): " + perm);
}
} else {
return false;
@@ -3102,24 +3113,23 @@
// 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 @@
&& 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 @@
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 @@
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 @@
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 @@
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 @@
}
}
- 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 @@
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 @@
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 @@
}
}
- 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 @@
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 @@
// 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 @@
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 @@
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 @@
* @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 @@
// 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 @@
* @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 @@
// 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 @@
* @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 @@
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 @@
}
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 @@
* @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 @@
}
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 @@
}
}
- 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 @@
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 @@
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 @@
.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 fb5c6fdd..0f22619 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.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 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 @@
* @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 @@
* 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 @@
* 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 @@
* @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 @@
* 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 3d8cf2d..254b720 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 @@
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 @@
* 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 9b9f93f..5f39f51 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.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 @@
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 @@
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 aac0f90..a4eef9b 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 @@
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 @@
}
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 f6fb6e2..9d2a460 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 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 @@
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 @@
return info;
});
}
- return packageBuilder;
+
+ return pkg(packageName)
+ .addActivity(activity);
}
@Before
@@ -98,7 +111,7 @@
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 @@
@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 fec3267..0273a1c 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 @@
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 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 c38672c..0000000
--- 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 0a310d1..85840e1 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 @@
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 1106be2..8329227 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 @@
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 @@
@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 @@
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 @@
@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 @@
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 @@
UPDATED_VERSION_CODE,
0 /*pkgFlags*/,
0 /*pkgPrivateFlags*/,
- null /*parentPkgName*/,
- null /*childPkgNames*/,
0,
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/);
@@ -505,7 +487,6 @@
"armeabi" /*secondaryCpuAbi*/,
0 /*pkgFlags*/,
0 /*pkgPrivateFlags*/,
- null /*childPkgNames*/,
UserManagerService.getInstance(),
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/);
@@ -539,7 +520,6 @@
"armeabi" /*secondaryCpuAbi*/,
ApplicationInfo.FLAG_SYSTEM /*pkgFlags*/,
ApplicationInfo.PRIVATE_FLAG_PRIVILEGED /*pkgPrivateFlags*/,
- null /*childPkgNames*/,
UserManagerService.getInstance(),
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/);
@@ -579,7 +559,6 @@
"armeabi" /*secondaryCpuAbi*/,
0 /*pkgFlags*/,
0 /*pkgPrivateFlags*/,
- null /*childPkgNames*/,
UserManagerService.getInstance(),
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/);
@@ -612,8 +591,6 @@
false /*allowInstall*/,
false /*instantApp*/,
false /*virtualPreload*/,
- null /*parentPkgName*/,
- null /*childPkgNames*/,
UserManagerService.getInstance(),
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/);
@@ -653,8 +630,6 @@
true /*allowInstall*/,
false /*instantApp*/,
false /*virtualPreload*/,
- null /*parentPkgName*/,
- null /*childPkgNames*/,
UserManagerService.getInstance(),
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/);
@@ -700,8 +675,6 @@
false /*allowInstall*/,
false /*instantApp*/,
false /*virtualPreload*/,
- null /*parentPkgName*/,
- null /*childPkgNames*/,
UserManagerService.getInstance(),
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/);
@@ -744,8 +717,6 @@
false /*allowInstall*/,
false /*instantApp*/,
false /*virtualPreload*/,
- null /*parentPkgName*/,
- null /*childPkgNames*/,
UserManagerService.getInstance(),
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/);
@@ -802,9 +773,6 @@
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 @@
// 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 @@
INITIAL_VERSION_CODE,
pkgFlags,
0 /*privateFlags*/,
- null /*parentPackageName*/,
- null /*childPackageNames*/,
sharedUserId,
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/);
@@ -901,8 +865,6 @@
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 e33d8ca..162092b 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.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 @@
@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 @@
@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 @@
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 @@
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,154 +161,164 @@
@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);
+ ParsingPackage deserialized2 = new PackageImpl(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);
+ 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
* all other information.
*/
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);
+ 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());
- 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);
+ 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 @@
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 @@
}
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 @@
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 @@
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();
+ public static void setKnownFields(ParsingPackage pkg) {
+ Bundle bundle = new Bundle();
+ bundle.putString("key", "value");
- pkg.permissions.add(new PackageParser.Permission(pkg, (String) null));
- pkg.permissionGroups.add(new PackageParser.PermissionGroup(pkg, ID_NULL, ID_NULL, ID_NULL));
+ ParsedPermission permission = new ParsedPermission();
+ permission.parsedPermissionGroup = new ParsedPermissionGroup();
- 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")));
+ 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 @@
} 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 8d476f6..374e13a 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 @@
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 @@
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 @@
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 @@
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 d3a77d3..04e769d 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 @@
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 41489dc..a0efc8a 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 @@
}
@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 34a3f86..11f154b 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 @@
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 74ef034..997348d 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.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.junit.MockitoJUnitRunner;
import java.io.File;
+import java.util.UUID;
@RunWith(MockitoJUnitRunner.class)
@Presubmit
@@ -68,6 +73,9 @@
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 @@
@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 @@
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 @@
@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 @@
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 @@
.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 @@
.build();
final PackageManagerService.ScanRequest scanRequest =
- createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME).build())
+ createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME))
.setPkgSetting(existingPkgSetting)
.build();
@@ -214,17 +222,18 @@
@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 @@
@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 @@
.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 @@
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 @@
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 @@
.setOriginalPkgSetting(originalPkgSetting)
.build());
- assertThat(result.request.pkg.packageName, is("original.package"));
+ assertThat(result.request.parsedPackage.getPackageName(), is("original.package"));
}
@Test
@@ -354,7 +362,7 @@
.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 @@
.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 @@
.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 @@
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 @@
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 @@
.setResourcePath(createResourcePath(packageName));
}
- private static ScanRequestBuilder createBasicScanRequestBuilder(PackageParser.Package 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 @@
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 @@
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 @@
}
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 790f2b4..0b0f6a7 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 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 3a55c22..66a4946 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.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 @@
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 @@
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 @@
codeDir + "/base-5.dex",
codeDir + "/base-6.dex",
codeDir + "/config-split-7.dex",
- codeDir + "/feature-no-deps.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.
+ 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 @@
@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 @@
@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 @@
@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 @@
@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 @@
@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 @@
@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 @@
@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 @@
@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 @@
@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 @@
@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 @@
@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 @@
@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]);