Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b8974d3 authored by Hai Zhang's avatar Hai Zhang
Browse files

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
parent 0b0e7b4f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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

+33 −0
Original line number Diff line number Diff line
@@ -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.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
@@ -115,6 +122,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;
@@ -2045,6 +2053,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);
+2 −26
Original line number Diff line number Diff line
@@ -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.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.Rect;
@@ -82,7 +76,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;
@@ -6751,25 +6744,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");
    }

    /**
+38 −32
Original line number Diff line number Diff line
@@ -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,16 +239,19 @@ 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() {
        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.
                        // 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;
                    }

@@ -257,7 +261,8 @@ public class ParsingPackageUtils {
                            @NonNull String baseApkPath,
                            @NonNull String path,
                            @NonNull TypedArray manifestArray, boolean isCoreApp) {
                return new ParsingPackageImpl(packageName, baseApkPath, path, manifestArray);
                        return new ParsingPackageImpl(packageName, baseApkPath, path,
                                manifestArray);
                    }
                });
        try {
@@ -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())) {
+3 −1
Original line number Diff line number Diff line
@@ -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());
        }
Loading