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

Commit f61f4fb8 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
(cherry picked from commit 7b8974d3)
parent b23f6d71
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -178,7 +178,7 @@ class PackageParsingPerfTest {
            // For testing, just disable enforcement to avoid hooking up to compat framework
            // For testing, just disable enforcement to avoid hooking up to compat framework
            ParseTypeImpl(ParseInput.Callback { _, _, _ -> false })
            ParseTypeImpl(ParseInput.Callback { _, _, _ -> false })
        }
        }
        val parser = ParsingPackageUtils(false, null, null,
        val parser = ParsingPackageUtils(false, null, null, emptyList(),
            object : ParsingPackageUtils.Callback {
            object : ParsingPackageUtils.Callback {
                override fun hasFeature(feature: String) = true
                override fun hasFeature(feature: String) = true


+33 −0
Original line number Original line Diff line number Diff line
@@ -59,6 +59,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageUserState;
import android.content.pm.ParceledListSlice;
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.content.pm.PermissionInfo;
@@ -70,6 +71,12 @@ import android.content.pm.SuspendDialogInfo;
import android.content.pm.VerifierDeviceIdentity;
import android.content.pm.VerifierDeviceIdentity;
import android.content.pm.VersionedPackage;
import android.content.pm.VersionedPackage;
import android.content.pm.dex.ArtManager;
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.Configuration;
import android.content.res.Resources;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.content.res.XmlResourceParser;
@@ -116,6 +123,7 @@ import dalvik.system.VMRuntime;


import libcore.util.EmptyArray;
import libcore.util.EmptyArray;


import java.io.File;
import java.lang.ref.WeakReference;
import java.lang.ref.WeakReference;
import java.security.cert.Certificate;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateEncodingException;
@@ -2055,6 +2063,31 @@ public class ApplicationPackageManager extends PackageManager {
        return info.loadLabel(this);
        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
    @Override
    public int installExistingPackage(String packageName) throws NameNotFoundException {
    public int installExistingPackage(String packageName) throws NameNotFoundException {
        return installExistingPackage(packageName, INSTALL_REASON_UNKNOWN);
        return installExistingPackage(packageName, INSTALL_REASON_UNKNOWN);
+2 −26
Original line number Original line Diff line number Diff line
@@ -48,12 +48,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.IntentSender;
import android.content.pm.dex.ArtManager;
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.Configuration;
import android.content.res.Resources;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.content.res.XmlResourceParser;
@@ -83,7 +77,6 @@ import com.android.internal.util.ArrayUtils;


import dalvik.system.VMRuntime;
import dalvik.system.VMRuntime;


import java.io.File;
import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
import java.security.cert.Certificate;
import java.security.cert.Certificate;
@@ -6791,25 +6784,8 @@ public abstract class PackageManager {
    @Nullable
    @Nullable
    public PackageInfo getPackageArchiveInfo(@NonNull String archiveFilePath,
    public PackageInfo getPackageArchiveInfo(@NonNull String archiveFilePath,
            @PackageInfoFlags int flags) {
            @PackageInfoFlags int flags) {
        if ((flags & (PackageManager.MATCH_DIRECT_BOOT_UNAWARE
        throw new UnsupportedOperationException(
                | PackageManager.MATCH_DIRECT_BOOT_AWARE)) == 0) {
                "getPackageArchiveInfo() not implemented in subclass");
            // 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());
    }
    }


    /**
    /**
+38 −32
Original line number Original line Diff line number Diff line
@@ -34,7 +34,6 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.StyleableRes;
import android.annotation.StyleableRes;
import android.app.ActivityThread;
import android.content.Intent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.ApplicationInfo;
@@ -222,13 +221,15 @@ public class ParsingPackageUtils {
    private static final int MAX_FILE_NAME_SIZE = 223;
    private static final int MAX_FILE_NAME_SIZE = 223;


    /**
    /**
     * @see #parseDefault(ParseInput, File, int, boolean)
     * @see #parseDefault(ParseInput, File, int, List, boolean)
     */
     */
    @NonNull
    @NonNull
    public static ParseResult<ParsingPackage> parseDefaultOneTime(File file,
    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();
        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
    @NonNull
    public static ParseResult<ParsingPackage> parseDefault(ParseInput input, File file,
    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;
        ParseResult<ParsingPackage> result;


        ParsingPackageUtils parser = new ParsingPackageUtils(false, null, null, new Callback() {
        ParsingPackageUtils parser = new ParsingPackageUtils(false, null, null, splitPermissions,
                new Callback() {
                    @Override
                    @Override
                    public boolean hasFeature(String feature) {
                    public boolean hasFeature(String feature) {
                // Assume the device doesn't support anything. This will affect permission parsing
                        // Assume the device doesn't support anything. This will affect permission
                // and will force <uses-permission/> declarations to include all requiredNotFeature
                        // parsing and will force <uses-permission/> declarations to include all
                // permissions and exclude all requiredFeature permissions. This mirrors the old
                        // requiredNotFeature permissions and exclude all requiredFeature
                // behavior.
                        // permissions. This mirrors the old behavior.
                        return false;
                        return false;
                    }
                    }


@@ -257,7 +261,8 @@ public class ParsingPackageUtils {
                            @NonNull String baseApkPath,
                            @NonNull String baseApkPath,
                            @NonNull String path,
                            @NonNull String path,
                            @NonNull TypedArray manifestArray, boolean isCoreApp) {
                            @NonNull TypedArray manifestArray, boolean isCoreApp) {
                return new ParsingPackageImpl(packageName, baseApkPath, path, manifestArray);
                        return new ParsingPackageImpl(packageName, baseApkPath, path,
                                manifestArray);
                    }
                    }
                });
                });
        try {
        try {
@@ -290,13 +295,18 @@ public class ParsingPackageUtils {
    private boolean mOnlyCoreApps;
    private boolean mOnlyCoreApps;
    private String[] mSeparateProcesses;
    private String[] mSeparateProcesses;
    private DisplayMetrics mDisplayMetrics;
    private DisplayMetrics mDisplayMetrics;
    @NonNull
    private List<PermissionManager.SplitPermissionInfo> mSplitPermissionInfos;
    private Callback mCallback;
    private Callback mCallback;


    public ParsingPackageUtils(boolean onlyCoreApps, String[] separateProcesses,
    public ParsingPackageUtils(boolean onlyCoreApps, String[] separateProcesses,
            DisplayMetrics displayMetrics, @NonNull Callback callback) {
            DisplayMetrics displayMetrics,
            @NonNull List<PermissionManager.SplitPermissionInfo> splitPermissions,
            @NonNull Callback callback) {
        mOnlyCoreApps = onlyCoreApps;
        mOnlyCoreApps = onlyCoreApps;
        mSeparateProcesses = separateProcesses;
        mSeparateProcesses = separateProcesses;
        mDisplayMetrics = displayMetrics;
        mDisplayMetrics = displayMetrics;
        mSplitPermissionInfos = splitPermissions;
        mCallback = callback;
        mCallback = callback;
    }
    }


@@ -2743,14 +2753,10 @@ public class ParsingPackageUtils {
        }
        }
    }
    }


    private static void convertSplitPermissions(ParsingPackage pkg) {
    private void convertSplitPermissions(ParsingPackage pkg) {
        final List<PermissionManager.SplitPermissionInfo> splitPermissions =
        final int listSize = mSplitPermissionInfos.size();
                ActivityThread.currentApplication().getSystemService(PermissionManager.class)
                        .getSplitPermissions();

        final int listSize = splitPermissions.size();
        for (int is = 0; is < listSize; is++) {
        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();
            List<String> requestedPermissions = pkg.getRequestedPermissions();
            if (pkg.getTargetSdkVersion() >= spi.getTargetSdk()
            if (pkg.getTargetSdkVersion() >= spi.getTargetSdk()
                    || !requestedPermissions.contains(spi.getSplitPermission())) {
                    || !requestedPermissions.contains(spi.getSplitPermission())) {
+3 −1
Original line number Original line Diff line number Diff line
@@ -78,6 +78,7 @@ import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardCopyOption;
import java.util.Collections;
import java.util.HashSet;
import java.util.HashSet;
import java.util.List;
import java.util.List;
import java.util.Set;
import java.util.Set;
@@ -334,7 +335,8 @@ public class PackageManagerTests extends AndroidTestCase {
    private ParsingPackage parsePackage(Uri packageURI) {
    private ParsingPackage parsePackage(Uri packageURI) {
        final String archiveFilePath = packageURI.getPath();
        final String archiveFilePath = packageURI.getPath();
        ParseResult<ParsingPackage> result = ParsingPackageUtils.parseDefaultOneTime(
        ParseResult<ParsingPackage> result = ParsingPackageUtils.parseDefaultOneTime(
                new File(archiveFilePath), 0 /*flags*/, false /*collectCertificates*/);
                new File(archiveFilePath), 0 /*flags*/, Collections.emptyList(),
                false /*collectCertificates*/);
        if (result.isError()) {
        if (result.isError()) {
            throw new IllegalStateException(result.getErrorMessage(), result.getException());
            throw new IllegalStateException(result.getErrorMessage(), result.getException());
        }
        }
Loading