diff options
author | Hai Zhang <zhanghai@google.com> | 2021-01-27 14:39:33 -0800 |
---|---|---|
committer | Hai Zhang <zhanghai@google.com> | 2021-02-02 11:42:40 -0800 |
commit | f61f4fb849297eb9415242a907ab9f1369b2d428 (patch) | |
tree | 2264120273fb1920e0bea9780a351603ea3a544a | |
parent | b23f6d71eea725045dd1c4bef9e2fc98b0ecfa8e (diff) |
Pass in split permissions to ParsingPackageUtils.
Similar to passing in display metrics. We can use
ActivityThread.currentApplication() as the context for getting
PermissionManager in system server process because it will be created
early in ActivityThread.attach() before any custom logic can run, but
it becomes a problem for apps because they can run their own logic by
overriding Application.attachBaseContext() and do things there before
ActivityThread.currentApplication() becomes non-null.
So pass in the split permissions explicitly as an external dependency
for ParsingPackageUtils, and move the getPackageArchiveInfo()
implementation from PackageManager to ApplicationPackageManager to
utilize the context there. PackageParser2 can get the split
permissions internally because it's only used in system server.
Fixes: 178155985
Test: manual
Change-Id: I8213cf752e16b08328ad1150b2639da18c5d0e83
(cherry picked from commit 7b8974d375c74ff228d71b1f038f48cfb46c6d7c)
8 files changed, 89 insertions, 65 deletions
diff --git a/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt b/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt index 9e519f7afb93..1d94d7e8eca2 100644 --- a/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt +++ b/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt @@ -178,7 +178,7 @@ class PackageParsingPerfTest { // For testing, just disable enforcement to avoid hooking up to compat framework ParseTypeImpl(ParseInput.Callback { _, _, _ -> false }) } - val parser = ParsingPackageUtils(false, null, null, + val parser = ParsingPackageUtils(false, null, null, emptyList(), object : ParsingPackageUtils.Callback { override fun hasFeature(feature: String) = true diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 7e7f887766e2..b51d4ac8c988 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -59,6 +59,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.PackageUserState; import android.content.pm.ParceledListSlice; import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; @@ -70,6 +71,12 @@ 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.res.Configuration; import android.content.res.Resources; import android.content.res.XmlResourceParser; @@ -116,6 +123,7 @@ import dalvik.system.VMRuntime; import libcore.util.EmptyArray; +import java.io.File; import java.lang.ref.WeakReference; import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; @@ -2055,6 +2063,31 @@ public class ApplicationPackageManager extends PackageManager { return info.loadLabel(this); } + @Nullable + public PackageInfo getPackageArchiveInfo(@NonNull String archiveFilePath, + @PackageInfoFlags int flags) { + if ((flags & (PackageManager.MATCH_DIRECT_BOOT_UNAWARE + | PackageManager.MATCH_DIRECT_BOOT_AWARE)) == 0) { + // Caller expressed no opinion about what encryption + // aware/unaware components they want to see, so match both + flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE + | PackageManager.MATCH_DIRECT_BOOT_UNAWARE; + } + + boolean collectCertificates = (flags & PackageManager.GET_SIGNATURES) != 0 + || (flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0; + + ParseInput input = ParseTypeImpl.forParsingWithoutPlatformCompat().reset(); + ParseResult<ParsingPackage> result = ParsingPackageUtils.parseDefault(input, + new File(archiveFilePath), 0, getPermissionManager().getSplitPermissions(), + collectCertificates); + if (result.isError()) { + return null; + } + return PackageInfoWithoutStateUtils.generate(result.getResult(), null, flags, 0, 0, null, + new PackageUserState(), UserHandle.getCallingUserId()); + } + @Override public int installExistingPackage(String packageName) throws NameNotFoundException { return installExistingPackage(packageName, INSTALL_REASON_UNKNOWN); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 72fb1cae3871..e01e530a8b97 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -48,12 +48,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; 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.res.Configuration; import android.content.res.Resources; import android.content.res.XmlResourceParser; @@ -83,7 +77,6 @@ import com.android.internal.util.ArrayUtils; import dalvik.system.VMRuntime; -import java.io.File; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.security.cert.Certificate; @@ -6791,25 +6784,8 @@ public abstract class PackageManager { @Nullable public PackageInfo getPackageArchiveInfo(@NonNull String archiveFilePath, @PackageInfoFlags int flags) { - if ((flags & (PackageManager.MATCH_DIRECT_BOOT_UNAWARE - | PackageManager.MATCH_DIRECT_BOOT_AWARE)) == 0) { - // Caller expressed no opinion about what encryption - // aware/unaware components they want to see, so match both - flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE - | PackageManager.MATCH_DIRECT_BOOT_UNAWARE; - } - - boolean collectCertificates = (flags & PackageManager.GET_SIGNATURES) != 0 - || (flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0; - - ParseInput input = ParseTypeImpl.forParsingWithoutPlatformCompat().reset(); - ParseResult<ParsingPackage> result = ParsingPackageUtils.parseDefault(input, - new File(archiveFilePath), 0, collectCertificates); - if (result.isError()) { - return null; - } - return PackageInfoWithoutStateUtils.generate(result.getResult(), null, flags, 0, 0, null, - new PackageUserState(), UserHandle.getCallingUserId()); + throw new UnsupportedOperationException( + "getPackageArchiveInfo() not implemented in subclass"); } /** diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java index b054304bbe74..8fbf2879bc27 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java @@ -34,7 +34,6 @@ import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StyleableRes; -import android.app.ActivityThread; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; @@ -222,13 +221,15 @@ public class ParsingPackageUtils { private static final int MAX_FILE_NAME_SIZE = 223; /** - * @see #parseDefault(ParseInput, File, int, boolean) + * @see #parseDefault(ParseInput, File, int, List, boolean) */ @NonNull public static ParseResult<ParsingPackage> parseDefaultOneTime(File file, - @ParseFlags int parseFlags, boolean collectCertificates) { + @ParseFlags int parseFlags, + @NonNull List<PermissionManager.SplitPermissionInfo> splitPermissions, + boolean collectCertificates) { ParseInput input = ParseTypeImpl.forDefaultParsing().reset(); - return parseDefault(input, file, parseFlags, collectCertificates); + return parseDefault(input, file, parseFlags, splitPermissions, collectCertificates); } /** @@ -238,28 +239,32 @@ public class ParsingPackageUtils { */ @NonNull public static ParseResult<ParsingPackage> parseDefault(ParseInput input, File file, - @ParseFlags int parseFlags, boolean collectCertificates) { + @ParseFlags int parseFlags, + @NonNull List<PermissionManager.SplitPermissionInfo> splitPermissions, + boolean collectCertificates) { ParseResult<ParsingPackage> result; - ParsingPackageUtils parser = new ParsingPackageUtils(false, null, null, new Callback() { - @Override - public boolean hasFeature(String feature) { - // Assume the device doesn't support anything. This will affect permission parsing - // and will force <uses-permission/> declarations to include all requiredNotFeature - // permissions and exclude all requiredFeature permissions. This mirrors the old - // behavior. - return false; - } - - @Override - public ParsingPackage startParsingPackage( - @NonNull String packageName, - @NonNull String baseApkPath, - @NonNull String path, - @NonNull TypedArray manifestArray, boolean isCoreApp) { - return new ParsingPackageImpl(packageName, baseApkPath, path, manifestArray); - } - }); + ParsingPackageUtils parser = new ParsingPackageUtils(false, null, null, splitPermissions, + new Callback() { + @Override + public boolean hasFeature(String feature) { + // Assume the device doesn't support anything. This will affect permission + // parsing and will force <uses-permission/> declarations to include all + // requiredNotFeature permissions and exclude all requiredFeature + // permissions. This mirrors the old behavior. + return false; + } + + @Override + public ParsingPackage startParsingPackage( + @NonNull String packageName, + @NonNull String baseApkPath, + @NonNull String path, + @NonNull TypedArray manifestArray, boolean isCoreApp) { + return new ParsingPackageImpl(packageName, baseApkPath, path, + manifestArray); + } + }); try { result = parser.parsePackage(input, file, parseFlags); if (result.isError()) { @@ -290,13 +295,18 @@ public class ParsingPackageUtils { private boolean mOnlyCoreApps; private String[] mSeparateProcesses; private DisplayMetrics mDisplayMetrics; + @NonNull + private List<PermissionManager.SplitPermissionInfo> mSplitPermissionInfos; private Callback mCallback; public ParsingPackageUtils(boolean onlyCoreApps, String[] separateProcesses, - DisplayMetrics displayMetrics, @NonNull Callback callback) { + DisplayMetrics displayMetrics, + @NonNull List<PermissionManager.SplitPermissionInfo> splitPermissions, + @NonNull Callback callback) { mOnlyCoreApps = onlyCoreApps; mSeparateProcesses = separateProcesses; mDisplayMetrics = displayMetrics; + mSplitPermissionInfos = splitPermissions; mCallback = callback; } @@ -2743,14 +2753,10 @@ public class ParsingPackageUtils { } } - private static void convertSplitPermissions(ParsingPackage pkg) { - final List<PermissionManager.SplitPermissionInfo> splitPermissions = - ActivityThread.currentApplication().getSystemService(PermissionManager.class) - .getSplitPermissions(); - - final int listSize = splitPermissions.size(); + private void convertSplitPermissions(ParsingPackage pkg) { + final int listSize = mSplitPermissionInfos.size(); for (int is = 0; is < listSize; is++) { - final PermissionManager.SplitPermissionInfo spi = splitPermissions.get(is); + final PermissionManager.SplitPermissionInfo spi = mSplitPermissionInfos.get(is); List<String> requestedPermissions = pkg.getRequestedPermissions(); if (pkg.getTargetSdkVersion() >= spi.getTargetSdk() || !requestedPermissions.contains(spi.getSplitPermission())) { diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java index 88faa0a49c9c..57c0be5007b8 100644 --- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java +++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java @@ -78,6 +78,7 @@ import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -334,7 +335,8 @@ public class PackageManagerTests extends AndroidTestCase { private ParsingPackage parsePackage(Uri packageURI) { final String archiveFilePath = packageURI.getPath(); ParseResult<ParsingPackage> result = ParsingPackageUtils.parseDefaultOneTime( - new File(archiveFilePath), 0 /*flags*/, false /*collectCertificates*/); + new File(archiveFilePath), 0 /*flags*/, Collections.emptyList(), + false /*collectCertificates*/); if (result.isError()) { throw new IllegalStateException(result.getErrorMessage(), result.getException()); } diff --git a/services/core/java/com/android/server/pm/parsing/PackageParser2.java b/services/core/java/com/android/server/pm/parsing/PackageParser2.java index 851ddd1eae48..e8be9b6fd82d 100644 --- a/services/core/java/com/android/server/pm/parsing/PackageParser2.java +++ b/services/core/java/com/android/server/pm/parsing/PackageParser2.java @@ -19,6 +19,7 @@ package com.android.server.pm.parsing; import android.annotation.AnyThread; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.ActivityThread; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageParser; @@ -33,6 +34,7 @@ import android.content.res.TypedArray; import android.os.Build; import android.os.ServiceManager; import android.os.SystemClock; +import android.permission.PermissionManager; import android.util.DisplayMetrics; import android.util.Slog; @@ -42,6 +44,7 @@ import com.android.server.pm.parsing.pkg.PackageImpl; import com.android.server.pm.parsing.pkg.ParsedPackage; import java.io.File; +import java.util.List; /** * The v2 of {@link PackageParser} for use when parsing is initiated in the server and must @@ -118,10 +121,15 @@ public class PackageParser2 implements AutoCloseable { displayMetrics.setToDefaults(); } + PermissionManager permissionManager = ActivityThread.currentApplication() + .getSystemService(PermissionManager.class); + List<PermissionManager.SplitPermissionInfo> splitPermissions = permissionManager + .getSplitPermissions(); + mCacher = cacheDir == null ? null : new PackageCacher(cacheDir); parsingUtils = new ParsingPackageUtils(onlyCoreApps, separateProcesses, displayMetrics, - callback); + splitPermissions, callback); ParseInput.Callback enforcementCallback = (changeId, packageName, targetSdkVersion) -> { ApplicationInfo appInfo = mSharedAppInfo.get(); diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java index bb223b33d8aa..fb13d8707a44 100644 --- a/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java @@ -55,6 +55,7 @@ import org.junit.runner.RunWith; import java.io.File; import java.io.InputStream; +import java.util.Collections; import java.util.function.Function; /** @@ -523,7 +524,7 @@ public class PackageParserLegacyCoreTest { int flags = PackageManager.GET_META_DATA | PackageManager.GET_SIGNING_CERTIFICATES; ParseResult<ParsingPackage> result = ParsingPackageUtils.parseDefaultOneTime(apexFile, - flags, false /*collectCertificates*/); + flags, Collections.emptyList(), false /*collectCertificates*/); if (result.isError()) { throw new IllegalStateException(result.getErrorMessage(), result.getException()); } diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParsingDeferErrorTest.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParsingDeferErrorTest.kt index d8910dec0bcc..4dc9a90bf57c 100644 --- a/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParsingDeferErrorTest.kt +++ b/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParsingDeferErrorTest.kt @@ -19,12 +19,10 @@ package com.android.server.pm.parsing import android.annotation.RawRes import android.content.Context import android.content.pm.parsing.ParsingPackage -import android.content.pm.parsing.ParsingPackageImpl import android.content.pm.parsing.ParsingPackageUtils import android.content.pm.parsing.result.ParseInput import android.content.pm.parsing.result.ParseInput.DeferredError import android.content.pm.parsing.result.ParseResult -import android.content.res.TypedArray import android.os.Build import androidx.test.InstrumentationRegistry import com.android.frameworks.servicestests.R @@ -130,7 +128,7 @@ class PackageParsingDeferErrorTest { input.copyTo(output) } } - return ParsingPackageUtils.parseDefaultOneTime(file, 0 /*flags*/, + return ParsingPackageUtils.parseDefaultOneTime(file, 0 /*flags*/, emptyList(), false /*collectCertificates*/) } } |