Loading apct-tests/perftests/packagemanager/Android.bp +5 −1 Original line number Diff line number Diff line Loading @@ -10,7 +10,10 @@ package { android_test { name: "PackageManagerPerfTests", srcs: ["src/**/*.java"], srcs: [ "src/**/*.java", "src/**/*.kt", ], static_libs: [ "platform-compat-test-rules", Loading @@ -21,6 +24,7 @@ android_test { "apct-perftests-utils", "collector-device-lib-platform", "cts-install-lib-java", "services.core", ], libs: ["android.test.base"], Loading apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt→apct-tests/perftests/packagemanager/src/android/os/PackageParsingPerfTest.kt +18 −9 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * Copyright (C) 2022 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. Loading @@ -19,9 +19,6 @@ package android.os import android.content.pm.PackageParser import android.content.pm.PackageParserCacheHelper.ReadHelper import android.content.pm.PackageParserCacheHelper.WriteHelper import android.content.pm.parsing.ParsingPackageImpl import android.content.pm.parsing.ParsingPackageRead import android.content.pm.parsing.ParsingPackageUtils import android.content.pm.parsing.result.ParseInput import android.content.pm.parsing.result.ParseTypeImpl import android.content.res.TypedArray Loading @@ -29,6 +26,8 @@ import android.perftests.utils.BenchmarkState import android.perftests.utils.PerfStatusReporter import androidx.test.filters.LargeTest import com.android.internal.util.ConcurrentUtils import com.android.server.pm.pkg.parsing.ParsingPackageImpl import com.android.server.pm.pkg.parsing.ParsingPackageUtils import libcore.io.IoUtils import org.junit.Rule import org.junit.Test Loading @@ -42,7 +41,7 @@ import java.util.concurrent.TimeUnit @LargeTest @RunWith(Parameterized::class) class PackageParsingPerfTest { public class PackageParsingPerfTest { companion object { private const val PARALLEL_QUEUE_CAPACITY = 10 Loading Loading @@ -196,8 +195,12 @@ class PackageParsingPerfTest { // For testing, just disable enforcement to avoid hooking up to compat framework ParseTypeImpl(ParseInput.Callback { _, _, _ -> false }) } val parser = ParsingPackageUtils(false, null, null, emptyList(), object : ParsingPackageUtils.Callback { val parser = ParsingPackageUtils(false, null, null, emptyList(), object : ParsingPackageUtils.Callback { override fun hasFeature(feature: String) = true override fun startParsingPackage( Loading @@ -206,7 +209,12 @@ class PackageParsingPerfTest { path: String, manifestArray: TypedArray, isCoreApp: Boolean ) = ParsingPackageImpl(packageName, baseApkPath, path, manifestArray) ) = ParsingPackageImpl( packageName, baseApkPath, path, manifestArray ) }) override fun parseImpl(file: File) = Loading Loading @@ -268,6 +276,7 @@ class PackageParsingPerfTest { * Re-implementation of the server side PackageCacher, as it's inaccessible here. */ class PackageCacher2(cacheDir: File) : PackageCacher<ParsingPackageImpl>(cacheDir) { override fun fromParcel(parcel: Parcel) = ParsingPackageImpl(parcel) override fun fromParcel(parcel: Parcel) = ParsingPackageImpl(parcel) } } core/java/android/app/ApplicationPackageManager.java +1 −37 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageInstaller; import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; import android.content.pm.PackageParser; import android.content.pm.ParceledListSlice; import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; Loading @@ -73,12 +74,6 @@ import android.content.pm.SuspendDialogInfo; import android.content.pm.VerifierDeviceIdentity; import android.content.pm.VersionedPackage; import android.content.pm.dex.ArtManager; import android.content.pm.parsing.PackageInfoWithoutStateUtils; import android.content.pm.parsing.ParsingPackage; import android.content.pm.parsing.ParsingPackageUtils; import android.content.pm.parsing.result.ParseInput; import android.content.pm.parsing.result.ParseResult; import android.content.pm.parsing.result.ParseTypeImpl; import android.content.pm.pkg.FrameworkPackageUserState; import android.content.res.Configuration; import android.content.res.Resources; Loading Loading @@ -2335,37 +2330,6 @@ public class ApplicationPackageManager extends PackageManager { return info.loadLabel(this); } @Nullable public PackageInfo getPackageArchiveInfo(@NonNull String archiveFilePath, int flags) { return getPackageArchiveInfo(archiveFilePath, PackageInfoFlags.of(flags)); } @Nullable public PackageInfo getPackageArchiveInfo(@NonNull String archiveFilePath, PackageInfoFlags flags) { long flagsBits = flags.getValue(); if ((flagsBits & (PackageManager.MATCH_DIRECT_BOOT_UNAWARE | PackageManager.MATCH_DIRECT_BOOT_AWARE)) == 0) { // Caller expressed no opinion about what encryption // aware/unaware components they want to see, so match both flagsBits |= PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE; } boolean collectCertificates = (flagsBits & PackageManager.GET_SIGNATURES) != 0 || (flagsBits & PackageManager.GET_SIGNING_CERTIFICATES) != 0; ParseInput input = ParseTypeImpl.forParsingWithoutPlatformCompat().reset(); ParseResult<ParsingPackage> result = ParsingPackageUtils.parseDefault(input, new File(archiveFilePath), 0, getPermissionManager().getSplitPermissions(), collectCertificates); if (result.isError()) { return null; } return PackageInfoWithoutStateUtils.generate(result.getResult(), null, flagsBits, 0, 0, null, FrameworkPackageUserState.DEFAULT, UserHandle.getCallingUserId()); } @Override public int installExistingPackage(String packageName) throws NameNotFoundException { return installExistingPackage(packageName, INSTALL_REASON_UNKNOWN); Loading core/java/android/content/pm/PackageManager.java +26 −4 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; import android.content.pm.dex.ArtManager; import android.content.pm.pkg.FrameworkPackageUserState; import android.content.pm.verify.domain.DomainVerificationManager; import android.content.res.Configuration; import android.content.res.Resources; Loading Loading @@ -88,6 +89,7 @@ import com.android.internal.util.DataClass; import dalvik.system.VMRuntime; import java.io.File; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.security.cert.Certificate; Loading Loading @@ -7891,8 +7893,7 @@ public abstract class PackageManager { @Deprecated @Nullable public PackageInfo getPackageArchiveInfo(@NonNull String archiveFilePath, int flags) { throw new UnsupportedOperationException( "getPackageArchiveInfo() not implemented in subclass"); return getPackageArchiveInfo(archiveFilePath, PackageInfoFlags.of(flags)); } /** Loading @@ -7901,8 +7902,29 @@ public abstract class PackageManager { @Nullable public PackageInfo getPackageArchiveInfo(@NonNull String archiveFilePath, @NonNull PackageInfoFlags flags) { throw new UnsupportedOperationException( "getPackageArchiveInfo() not implemented in subclass"); long flagsBits = flags.getValue(); final PackageParser parser = new PackageParser(); parser.setCallback(new PackageParser.CallbackImpl(this)); final File apkFile = new File(archiveFilePath); try { if ((flagsBits & (MATCH_DIRECT_BOOT_UNAWARE | MATCH_DIRECT_BOOT_AWARE)) != 0) { // Caller expressed an explicit opinion about what encryption // aware/unaware components they want to see, so fall through and // give them what they want } else { // Caller expressed no opinion, so match everything flagsBits |= MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE; } PackageParser.Package pkg = parser.parsePackage(apkFile, 0, false); if ((flagsBits & GET_SIGNATURES) != 0) { PackageParser.collectCertificates(pkg, false /* skipVerify */); } return PackageParser.generatePackageInfo(pkg, null, (int) flagsBits, 0, 0, null, FrameworkPackageUserState.DEFAULT); } catch (PackageParser.PackageParserException e) { return null; } } /** Loading core/java/android/content/pm/PackageParser.java +206 −13 Original line number Diff line number Diff line /* * Copyright (C) 2007 The Android Open Source Project * Copyright (C) 2022 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. Loading Loading @@ -37,6 +37,8 @@ import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTEN 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.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS; import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS; 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; Loading @@ -55,11 +57,9 @@ import android.content.ComponentName; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.overlay.OverlayPaths; import android.content.pm.parsing.ParsingPackageUtils; import android.content.pm.pkg.FrameworkPackageUserState; import android.content.pm.pkg.PackageUserStateUtils; import android.content.pm.parsing.result.ParseResult; import android.content.pm.parsing.result.ParseTypeImpl; import android.content.pm.pkg.FrameworkPackageUserState; import android.content.res.ApkAssets; import android.content.res.AssetManager; import android.content.res.Configuration; Loading @@ -68,6 +68,7 @@ import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.os.Build; import android.os.Bundle; import android.os.Debug; import android.os.FileUtils; import android.os.Parcel; import android.os.Parcelable; Loading @@ -83,6 +84,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.AttributeSet; import android.util.Base64; import android.util.DebugUtils; import android.util.DisplayMetrics; import android.util.IntArray; import android.util.Log; Loading Loading @@ -128,6 +130,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; Loading @@ -148,7 +151,7 @@ import java.util.UUID; * </ul> * * @deprecated This class is mostly unused and no new changes should be added to it. Use * {@link android.content.pm.parsing.ParsingPackageUtils} and related parsing v2 infrastructure in * ParsingPackageUtils and related parsing v2 infrastructure in * the core/services parsing subpackages. Or for a quick parse of a provided APK, use * {@link PackageManager#getPackageArchiveInfo(String, int)}. * Loading Loading @@ -655,7 +658,7 @@ public class PackageParser { // If available for the target user, or trying to match uninstalled packages and it's // a system app. return PackageUserStateUtils.isAvailable(state, flags) return isAvailable(state, flags) || (appInfo != null && appInfo.isSystemApp() && ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0 || (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0)); Loading Loading @@ -765,7 +768,7 @@ public class PackageParser { final ActivityInfo[] res = new ActivityInfo[N]; for (int i = 0; i < N; i++) { final Activity a = p.activities.get(i); if (PackageUserStateUtils.isMatch(state, a.info, flags)) { if (isMatch(state, a.info, flags)) { if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(a.className)) { continue; } Loading @@ -782,7 +785,7 @@ public class PackageParser { final ActivityInfo[] res = new ActivityInfo[N]; for (int i = 0; i < N; i++) { final Activity a = p.receivers.get(i); if (PackageUserStateUtils.isMatch(state, a.info, flags)) { if (isMatch(state, a.info, flags)) { res[num++] = generateActivityInfo(a, flags, state, userId); } } Loading @@ -796,7 +799,7 @@ public class PackageParser { final ServiceInfo[] res = new ServiceInfo[N]; for (int i = 0; i < N; i++) { final Service s = p.services.get(i); if (PackageUserStateUtils.isMatch(state, s.info, flags)) { if (isMatch(state, s.info, flags)) { res[num++] = generateServiceInfo(s, flags, state, userId); } } Loading @@ -810,7 +813,7 @@ public class PackageParser { final ProviderInfo[] res = new ProviderInfo[N]; for (int i = 0; i < N; i++) { final Provider pr = p.providers.get(i); if (PackageUserStateUtils.isMatch(state, pr.info, flags)) { if (isMatch(state, pr.info, flags)) { res[num++] = generateProviderInfo(pr, flags, state, userId); } } Loading Loading @@ -7428,7 +7431,7 @@ public class PackageParser { mCompileSdkVersionCodename = dest.readString(); mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot); mKeySetMapping = ParsingPackageUtils.readKeySetMapping(dest); mKeySetMapping = readKeySetMapping(dest); cpuAbiOverride = dest.readString(); use32bitAbi = (dest.readInt() == 1); Loading Loading @@ -7554,7 +7557,7 @@ public class PackageParser { dest.writeInt(mCompileSdkVersion); dest.writeString(mCompileSdkVersionCodename); dest.writeArraySet(mUpgradeKeySets); ParsingPackageUtils.writeKeySetMapping(dest, mKeySetMapping); writeKeySetMapping(dest, mKeySetMapping); dest.writeString(cpuAbiOverride); dest.writeInt(use32bitAbi ? 1 : 0); dest.writeByteArray(restrictUpdateHash); Loading Loading @@ -7977,7 +7980,7 @@ public class PackageParser { if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) { ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName); } ai.seInfoUser = SELinuxUtil.getSeinfoUser(state); ai.seInfoUser = getSeinfoUser(state); final OverlayPaths overlayPaths = state.getAllOverlayPaths(); if (overlayPaths != null) { ai.resourceDirs = overlayPaths.getResourceDirs().toArray(new String[0]); Loading Loading @@ -9074,4 +9077,194 @@ public class PackageParser { return mCachedSplitApks[0][0]; } } public static boolean isMatch(@NonNull FrameworkPackageUserState state, ComponentInfo componentInfo, long flags) { return isMatch(state, componentInfo.applicationInfo.isSystemApp(), componentInfo.applicationInfo.enabled, componentInfo.enabled, componentInfo.directBootAware, componentInfo.name, flags); } public static boolean isMatch(@NonNull FrameworkPackageUserState state, boolean isSystem, boolean isPackageEnabled, ComponentInfo component, long flags) { return isMatch(state, isSystem, isPackageEnabled, component.isEnabled(), component.directBootAware, component.name, flags); } /** * Test if the given component is considered installed, enabled and a match for the given * flags. * * <p> * 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 static boolean isMatch(@NonNull FrameworkPackageUserState state, boolean isSystem, boolean isPackageEnabled, boolean isComponentEnabled, boolean isComponentDirectBootAware, String componentName, long flags) { final boolean matchUninstalled = (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0; if (!isAvailable(state, flags) && !(isSystem && matchUninstalled)) { return reportIfDebug(false, flags); } if (!isEnabled(state, isPackageEnabled, isComponentEnabled, componentName, flags)) { return reportIfDebug(false, flags); } if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) { if (!isSystem) { return reportIfDebug(false, flags); } } final boolean matchesUnaware = ((flags & PackageManager.MATCH_DIRECT_BOOT_UNAWARE) != 0) && !isComponentDirectBootAware; final boolean matchesAware = ((flags & PackageManager.MATCH_DIRECT_BOOT_AWARE) != 0) && isComponentDirectBootAware; return reportIfDebug(matchesUnaware || matchesAware, flags); } public static boolean isAvailable(@NonNull FrameworkPackageUserState state, long flags) { // True if it is installed for this user and it is not hidden. If it is hidden, // still return true if the caller requested MATCH_UNINSTALLED_PACKAGES final boolean matchAnyUser = (flags & PackageManager.MATCH_ANY_USER) != 0; final boolean matchUninstalled = (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0; return matchAnyUser || (state.isInstalled() && (!state.isHidden() || matchUninstalled)); } public static boolean reportIfDebug(boolean result, long flags) { if (DEBUG_PARSER && !result) { Slog.i(TAG, "No match!; flags: " + DebugUtils.flagsToString(PackageManager.class, "MATCH_", flags) + " " + Debug.getCaller()); } return result; } public static boolean isEnabled(@NonNull FrameworkPackageUserState state, ComponentInfo componentInfo, long flags) { return isEnabled(state, componentInfo.applicationInfo.enabled, componentInfo.enabled, componentInfo.name, flags); } public static boolean isEnabled(@NonNull FrameworkPackageUserState state, boolean isPackageEnabled, ComponentInfo parsedComponent, long flags) { return isEnabled(state, isPackageEnabled, parsedComponent.isEnabled(), parsedComponent.name, flags); } /** * Test if the given component is considered enabled. */ public static boolean isEnabled(@NonNull FrameworkPackageUserState state, boolean isPackageEnabled, boolean isComponentEnabled, String componentName, long flags) { if ((flags & MATCH_DISABLED_COMPONENTS) != 0) { return true; } // First check if the overall package is disabled; if the package is // enabled then fall through to check specific component switch (state.getEnabledState()) { case PackageManager.COMPONENT_ENABLED_STATE_DISABLED: case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER: return false; case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED: if ((flags & MATCH_DISABLED_UNTIL_USED_COMPONENTS) == 0) { return false; } // fallthrough case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT: if (!isPackageEnabled) { return false; } // fallthrough case PackageManager.COMPONENT_ENABLED_STATE_ENABLED: break; } // Check if component has explicit state before falling through to // the manifest default if (state.isComponentEnabled(componentName)) { return true; } else if (state.isComponentDisabled(componentName)) { return false; } return isComponentEnabled; } /** * Writes the keyset mapping to the provided package. {@code null} mappings are permitted. */ public static void writeKeySetMapping(@NonNull Parcel dest, @NonNull Map<String, ArraySet<PublicKey>> keySetMapping) { if (keySetMapping == null) { dest.writeInt(-1); return; } final int N = keySetMapping.size(); dest.writeInt(N); for (String key : keySetMapping.keySet()) { dest.writeString(key); ArraySet<PublicKey> keys = keySetMapping.get(key); if (keys == null) { dest.writeInt(-1); continue; } final int M = keys.size(); dest.writeInt(M); for (int j = 0; j < M; j++) { dest.writeSerializable(keys.valueAt(j)); } } } /** * Reads a keyset mapping from the given parcel at the given data position. May return * {@code null} if the serialized mapping was {@code null}. */ @NonNull public static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(@NonNull Parcel in) { final int N = in.readInt(); if (N == -1) { return null; } ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>(); for (int i = 0; i < N; ++i) { String key = in.readString(); final int M = in.readInt(); if (M == -1) { keySetMapping.put(key, null); continue; } ArraySet<PublicKey> keys = new ArraySet<>(M); for (int j = 0; j < M; ++j) { PublicKey pk = in.readSerializable(PublicKey.class.getClassLoader(), PublicKey.class); keys.add(pk); } keySetMapping.put(key, keys); } return keySetMapping; } public static String getSeinfoUser(FrameworkPackageUserState userState) { if (userState.isInstantApp()) { return ":ephemeralapp:complete"; } return ":complete"; } } Loading
apct-tests/perftests/packagemanager/Android.bp +5 −1 Original line number Diff line number Diff line Loading @@ -10,7 +10,10 @@ package { android_test { name: "PackageManagerPerfTests", srcs: ["src/**/*.java"], srcs: [ "src/**/*.java", "src/**/*.kt", ], static_libs: [ "platform-compat-test-rules", Loading @@ -21,6 +24,7 @@ android_test { "apct-perftests-utils", "collector-device-lib-platform", "cts-install-lib-java", "services.core", ], libs: ["android.test.base"], Loading
apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt→apct-tests/perftests/packagemanager/src/android/os/PackageParsingPerfTest.kt +18 −9 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * Copyright (C) 2022 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. Loading @@ -19,9 +19,6 @@ package android.os import android.content.pm.PackageParser import android.content.pm.PackageParserCacheHelper.ReadHelper import android.content.pm.PackageParserCacheHelper.WriteHelper import android.content.pm.parsing.ParsingPackageImpl import android.content.pm.parsing.ParsingPackageRead import android.content.pm.parsing.ParsingPackageUtils import android.content.pm.parsing.result.ParseInput import android.content.pm.parsing.result.ParseTypeImpl import android.content.res.TypedArray Loading @@ -29,6 +26,8 @@ import android.perftests.utils.BenchmarkState import android.perftests.utils.PerfStatusReporter import androidx.test.filters.LargeTest import com.android.internal.util.ConcurrentUtils import com.android.server.pm.pkg.parsing.ParsingPackageImpl import com.android.server.pm.pkg.parsing.ParsingPackageUtils import libcore.io.IoUtils import org.junit.Rule import org.junit.Test Loading @@ -42,7 +41,7 @@ import java.util.concurrent.TimeUnit @LargeTest @RunWith(Parameterized::class) class PackageParsingPerfTest { public class PackageParsingPerfTest { companion object { private const val PARALLEL_QUEUE_CAPACITY = 10 Loading Loading @@ -196,8 +195,12 @@ class PackageParsingPerfTest { // For testing, just disable enforcement to avoid hooking up to compat framework ParseTypeImpl(ParseInput.Callback { _, _, _ -> false }) } val parser = ParsingPackageUtils(false, null, null, emptyList(), object : ParsingPackageUtils.Callback { val parser = ParsingPackageUtils(false, null, null, emptyList(), object : ParsingPackageUtils.Callback { override fun hasFeature(feature: String) = true override fun startParsingPackage( Loading @@ -206,7 +209,12 @@ class PackageParsingPerfTest { path: String, manifestArray: TypedArray, isCoreApp: Boolean ) = ParsingPackageImpl(packageName, baseApkPath, path, manifestArray) ) = ParsingPackageImpl( packageName, baseApkPath, path, manifestArray ) }) override fun parseImpl(file: File) = Loading Loading @@ -268,6 +276,7 @@ class PackageParsingPerfTest { * Re-implementation of the server side PackageCacher, as it's inaccessible here. */ class PackageCacher2(cacheDir: File) : PackageCacher<ParsingPackageImpl>(cacheDir) { override fun fromParcel(parcel: Parcel) = ParsingPackageImpl(parcel) override fun fromParcel(parcel: Parcel) = ParsingPackageImpl(parcel) } }
core/java/android/app/ApplicationPackageManager.java +1 −37 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageInstaller; import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; import android.content.pm.PackageParser; import android.content.pm.ParceledListSlice; import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; Loading @@ -73,12 +74,6 @@ import android.content.pm.SuspendDialogInfo; import android.content.pm.VerifierDeviceIdentity; import android.content.pm.VersionedPackage; import android.content.pm.dex.ArtManager; import android.content.pm.parsing.PackageInfoWithoutStateUtils; import android.content.pm.parsing.ParsingPackage; import android.content.pm.parsing.ParsingPackageUtils; import android.content.pm.parsing.result.ParseInput; import android.content.pm.parsing.result.ParseResult; import android.content.pm.parsing.result.ParseTypeImpl; import android.content.pm.pkg.FrameworkPackageUserState; import android.content.res.Configuration; import android.content.res.Resources; Loading Loading @@ -2335,37 +2330,6 @@ public class ApplicationPackageManager extends PackageManager { return info.loadLabel(this); } @Nullable public PackageInfo getPackageArchiveInfo(@NonNull String archiveFilePath, int flags) { return getPackageArchiveInfo(archiveFilePath, PackageInfoFlags.of(flags)); } @Nullable public PackageInfo getPackageArchiveInfo(@NonNull String archiveFilePath, PackageInfoFlags flags) { long flagsBits = flags.getValue(); if ((flagsBits & (PackageManager.MATCH_DIRECT_BOOT_UNAWARE | PackageManager.MATCH_DIRECT_BOOT_AWARE)) == 0) { // Caller expressed no opinion about what encryption // aware/unaware components they want to see, so match both flagsBits |= PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE; } boolean collectCertificates = (flagsBits & PackageManager.GET_SIGNATURES) != 0 || (flagsBits & PackageManager.GET_SIGNING_CERTIFICATES) != 0; ParseInput input = ParseTypeImpl.forParsingWithoutPlatformCompat().reset(); ParseResult<ParsingPackage> result = ParsingPackageUtils.parseDefault(input, new File(archiveFilePath), 0, getPermissionManager().getSplitPermissions(), collectCertificates); if (result.isError()) { return null; } return PackageInfoWithoutStateUtils.generate(result.getResult(), null, flagsBits, 0, 0, null, FrameworkPackageUserState.DEFAULT, UserHandle.getCallingUserId()); } @Override public int installExistingPackage(String packageName) throws NameNotFoundException { return installExistingPackage(packageName, INSTALL_REASON_UNKNOWN); Loading
core/java/android/content/pm/PackageManager.java +26 −4 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; import android.content.pm.dex.ArtManager; import android.content.pm.pkg.FrameworkPackageUserState; import android.content.pm.verify.domain.DomainVerificationManager; import android.content.res.Configuration; import android.content.res.Resources; Loading Loading @@ -88,6 +89,7 @@ import com.android.internal.util.DataClass; import dalvik.system.VMRuntime; import java.io.File; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.security.cert.Certificate; Loading Loading @@ -7891,8 +7893,7 @@ public abstract class PackageManager { @Deprecated @Nullable public PackageInfo getPackageArchiveInfo(@NonNull String archiveFilePath, int flags) { throw new UnsupportedOperationException( "getPackageArchiveInfo() not implemented in subclass"); return getPackageArchiveInfo(archiveFilePath, PackageInfoFlags.of(flags)); } /** Loading @@ -7901,8 +7902,29 @@ public abstract class PackageManager { @Nullable public PackageInfo getPackageArchiveInfo(@NonNull String archiveFilePath, @NonNull PackageInfoFlags flags) { throw new UnsupportedOperationException( "getPackageArchiveInfo() not implemented in subclass"); long flagsBits = flags.getValue(); final PackageParser parser = new PackageParser(); parser.setCallback(new PackageParser.CallbackImpl(this)); final File apkFile = new File(archiveFilePath); try { if ((flagsBits & (MATCH_DIRECT_BOOT_UNAWARE | MATCH_DIRECT_BOOT_AWARE)) != 0) { // Caller expressed an explicit opinion about what encryption // aware/unaware components they want to see, so fall through and // give them what they want } else { // Caller expressed no opinion, so match everything flagsBits |= MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE; } PackageParser.Package pkg = parser.parsePackage(apkFile, 0, false); if ((flagsBits & GET_SIGNATURES) != 0) { PackageParser.collectCertificates(pkg, false /* skipVerify */); } return PackageParser.generatePackageInfo(pkg, null, (int) flagsBits, 0, 0, null, FrameworkPackageUserState.DEFAULT); } catch (PackageParser.PackageParserException e) { return null; } } /** Loading
core/java/android/content/pm/PackageParser.java +206 −13 Original line number Diff line number Diff line /* * Copyright (C) 2007 The Android Open Source Project * Copyright (C) 2022 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. Loading Loading @@ -37,6 +37,8 @@ import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTEN 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.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS; import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS; 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; Loading @@ -55,11 +57,9 @@ import android.content.ComponentName; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.overlay.OverlayPaths; import android.content.pm.parsing.ParsingPackageUtils; import android.content.pm.pkg.FrameworkPackageUserState; import android.content.pm.pkg.PackageUserStateUtils; import android.content.pm.parsing.result.ParseResult; import android.content.pm.parsing.result.ParseTypeImpl; import android.content.pm.pkg.FrameworkPackageUserState; import android.content.res.ApkAssets; import android.content.res.AssetManager; import android.content.res.Configuration; Loading @@ -68,6 +68,7 @@ import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.os.Build; import android.os.Bundle; import android.os.Debug; import android.os.FileUtils; import android.os.Parcel; import android.os.Parcelable; Loading @@ -83,6 +84,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.AttributeSet; import android.util.Base64; import android.util.DebugUtils; import android.util.DisplayMetrics; import android.util.IntArray; import android.util.Log; Loading Loading @@ -128,6 +130,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; Loading @@ -148,7 +151,7 @@ import java.util.UUID; * </ul> * * @deprecated This class is mostly unused and no new changes should be added to it. Use * {@link android.content.pm.parsing.ParsingPackageUtils} and related parsing v2 infrastructure in * ParsingPackageUtils and related parsing v2 infrastructure in * the core/services parsing subpackages. Or for a quick parse of a provided APK, use * {@link PackageManager#getPackageArchiveInfo(String, int)}. * Loading Loading @@ -655,7 +658,7 @@ public class PackageParser { // If available for the target user, or trying to match uninstalled packages and it's // a system app. return PackageUserStateUtils.isAvailable(state, flags) return isAvailable(state, flags) || (appInfo != null && appInfo.isSystemApp() && ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0 || (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0)); Loading Loading @@ -765,7 +768,7 @@ public class PackageParser { final ActivityInfo[] res = new ActivityInfo[N]; for (int i = 0; i < N; i++) { final Activity a = p.activities.get(i); if (PackageUserStateUtils.isMatch(state, a.info, flags)) { if (isMatch(state, a.info, flags)) { if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(a.className)) { continue; } Loading @@ -782,7 +785,7 @@ public class PackageParser { final ActivityInfo[] res = new ActivityInfo[N]; for (int i = 0; i < N; i++) { final Activity a = p.receivers.get(i); if (PackageUserStateUtils.isMatch(state, a.info, flags)) { if (isMatch(state, a.info, flags)) { res[num++] = generateActivityInfo(a, flags, state, userId); } } Loading @@ -796,7 +799,7 @@ public class PackageParser { final ServiceInfo[] res = new ServiceInfo[N]; for (int i = 0; i < N; i++) { final Service s = p.services.get(i); if (PackageUserStateUtils.isMatch(state, s.info, flags)) { if (isMatch(state, s.info, flags)) { res[num++] = generateServiceInfo(s, flags, state, userId); } } Loading @@ -810,7 +813,7 @@ public class PackageParser { final ProviderInfo[] res = new ProviderInfo[N]; for (int i = 0; i < N; i++) { final Provider pr = p.providers.get(i); if (PackageUserStateUtils.isMatch(state, pr.info, flags)) { if (isMatch(state, pr.info, flags)) { res[num++] = generateProviderInfo(pr, flags, state, userId); } } Loading Loading @@ -7428,7 +7431,7 @@ public class PackageParser { mCompileSdkVersionCodename = dest.readString(); mUpgradeKeySets = (ArraySet<String>) dest.readArraySet(boot); mKeySetMapping = ParsingPackageUtils.readKeySetMapping(dest); mKeySetMapping = readKeySetMapping(dest); cpuAbiOverride = dest.readString(); use32bitAbi = (dest.readInt() == 1); Loading Loading @@ -7554,7 +7557,7 @@ public class PackageParser { dest.writeInt(mCompileSdkVersion); dest.writeString(mCompileSdkVersionCodename); dest.writeArraySet(mUpgradeKeySets); ParsingPackageUtils.writeKeySetMapping(dest, mKeySetMapping); writeKeySetMapping(dest, mKeySetMapping); dest.writeString(cpuAbiOverride); dest.writeInt(use32bitAbi ? 1 : 0); dest.writeByteArray(restrictUpdateHash); Loading Loading @@ -7977,7 +7980,7 @@ public class PackageParser { if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) { ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName); } ai.seInfoUser = SELinuxUtil.getSeinfoUser(state); ai.seInfoUser = getSeinfoUser(state); final OverlayPaths overlayPaths = state.getAllOverlayPaths(); if (overlayPaths != null) { ai.resourceDirs = overlayPaths.getResourceDirs().toArray(new String[0]); Loading Loading @@ -9074,4 +9077,194 @@ public class PackageParser { return mCachedSplitApks[0][0]; } } public static boolean isMatch(@NonNull FrameworkPackageUserState state, ComponentInfo componentInfo, long flags) { return isMatch(state, componentInfo.applicationInfo.isSystemApp(), componentInfo.applicationInfo.enabled, componentInfo.enabled, componentInfo.directBootAware, componentInfo.name, flags); } public static boolean isMatch(@NonNull FrameworkPackageUserState state, boolean isSystem, boolean isPackageEnabled, ComponentInfo component, long flags) { return isMatch(state, isSystem, isPackageEnabled, component.isEnabled(), component.directBootAware, component.name, flags); } /** * Test if the given component is considered installed, enabled and a match for the given * flags. * * <p> * 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 static boolean isMatch(@NonNull FrameworkPackageUserState state, boolean isSystem, boolean isPackageEnabled, boolean isComponentEnabled, boolean isComponentDirectBootAware, String componentName, long flags) { final boolean matchUninstalled = (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0; if (!isAvailable(state, flags) && !(isSystem && matchUninstalled)) { return reportIfDebug(false, flags); } if (!isEnabled(state, isPackageEnabled, isComponentEnabled, componentName, flags)) { return reportIfDebug(false, flags); } if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) { if (!isSystem) { return reportIfDebug(false, flags); } } final boolean matchesUnaware = ((flags & PackageManager.MATCH_DIRECT_BOOT_UNAWARE) != 0) && !isComponentDirectBootAware; final boolean matchesAware = ((flags & PackageManager.MATCH_DIRECT_BOOT_AWARE) != 0) && isComponentDirectBootAware; return reportIfDebug(matchesUnaware || matchesAware, flags); } public static boolean isAvailable(@NonNull FrameworkPackageUserState state, long flags) { // True if it is installed for this user and it is not hidden. If it is hidden, // still return true if the caller requested MATCH_UNINSTALLED_PACKAGES final boolean matchAnyUser = (flags & PackageManager.MATCH_ANY_USER) != 0; final boolean matchUninstalled = (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0; return matchAnyUser || (state.isInstalled() && (!state.isHidden() || matchUninstalled)); } public static boolean reportIfDebug(boolean result, long flags) { if (DEBUG_PARSER && !result) { Slog.i(TAG, "No match!; flags: " + DebugUtils.flagsToString(PackageManager.class, "MATCH_", flags) + " " + Debug.getCaller()); } return result; } public static boolean isEnabled(@NonNull FrameworkPackageUserState state, ComponentInfo componentInfo, long flags) { return isEnabled(state, componentInfo.applicationInfo.enabled, componentInfo.enabled, componentInfo.name, flags); } public static boolean isEnabled(@NonNull FrameworkPackageUserState state, boolean isPackageEnabled, ComponentInfo parsedComponent, long flags) { return isEnabled(state, isPackageEnabled, parsedComponent.isEnabled(), parsedComponent.name, flags); } /** * Test if the given component is considered enabled. */ public static boolean isEnabled(@NonNull FrameworkPackageUserState state, boolean isPackageEnabled, boolean isComponentEnabled, String componentName, long flags) { if ((flags & MATCH_DISABLED_COMPONENTS) != 0) { return true; } // First check if the overall package is disabled; if the package is // enabled then fall through to check specific component switch (state.getEnabledState()) { case PackageManager.COMPONENT_ENABLED_STATE_DISABLED: case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER: return false; case PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED: if ((flags & MATCH_DISABLED_UNTIL_USED_COMPONENTS) == 0) { return false; } // fallthrough case PackageManager.COMPONENT_ENABLED_STATE_DEFAULT: if (!isPackageEnabled) { return false; } // fallthrough case PackageManager.COMPONENT_ENABLED_STATE_ENABLED: break; } // Check if component has explicit state before falling through to // the manifest default if (state.isComponentEnabled(componentName)) { return true; } else if (state.isComponentDisabled(componentName)) { return false; } return isComponentEnabled; } /** * Writes the keyset mapping to the provided package. {@code null} mappings are permitted. */ public static void writeKeySetMapping(@NonNull Parcel dest, @NonNull Map<String, ArraySet<PublicKey>> keySetMapping) { if (keySetMapping == null) { dest.writeInt(-1); return; } final int N = keySetMapping.size(); dest.writeInt(N); for (String key : keySetMapping.keySet()) { dest.writeString(key); ArraySet<PublicKey> keys = keySetMapping.get(key); if (keys == null) { dest.writeInt(-1); continue; } final int M = keys.size(); dest.writeInt(M); for (int j = 0; j < M; j++) { dest.writeSerializable(keys.valueAt(j)); } } } /** * Reads a keyset mapping from the given parcel at the given data position. May return * {@code null} if the serialized mapping was {@code null}. */ @NonNull public static ArrayMap<String, ArraySet<PublicKey>> readKeySetMapping(@NonNull Parcel in) { final int N = in.readInt(); if (N == -1) { return null; } ArrayMap<String, ArraySet<PublicKey>> keySetMapping = new ArrayMap<>(); for (int i = 0; i < N; ++i) { String key = in.readString(); final int M = in.readInt(); if (M == -1) { keySetMapping.put(key, null); continue; } ArraySet<PublicKey> keys = new ArraySet<>(M); for (int j = 0; j < M; ++j) { PublicKey pk = in.readSerializable(PublicKey.class.getClassLoader(), PublicKey.class); keys.add(pk); } keySetMapping.put(key, keys); } return keySetMapping; } public static String getSeinfoUser(FrameworkPackageUserState userState) { if (userState.isInstantApp()) { return ":ephemeralapp:complete"; } return ":complete"; } }