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

Commit 0c8b3a73 authored by Philip P. Moltmann's avatar Philip P. Moltmann Committed by Automerger Merge Worker
Browse files

Merge changes from topic "MarkAPKInUpdateApexAsUpdatedSystemApp" into rvc-dev...

Merge changes from topic "MarkAPKInUpdateApexAsUpdatedSystemApp" into rvc-dev am: 8df5b601 am: 787bf232 am: a770021a

Change-Id: I0620d95725cba1d0ae74b52988cbdea5a8a326ed
parents 43e77bcd a770021a
Loading
Loading
Loading
Loading
+185 −123
Original line number Diff line number Diff line
@@ -16,22 +16,22 @@

package com.android.server.pm;

import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.apex.ApexInfo;
import android.apex.ApexInfoList;
import android.apex.ApexSessionInfo;
import android.apex.ApexSessionParams;
import android.apex.IApexService;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.parsing.PackageInfoWithoutStateUtils;
import android.os.Environment;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -44,8 +44,9 @@ import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.server.pm.parsing.PackageParser2;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.utils.TimingsTraceAndSlog;

@@ -61,7 +62,9 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

/**
@@ -72,7 +75,7 @@ public abstract class ApexManager {

    private static final String TAG = "ApexManager";

    static final int MATCH_ACTIVE_PACKAGE = 1 << 0;
    public static final int MATCH_ACTIVE_PACKAGE = 1 << 0;
    static final int MATCH_FACTORY_PACKAGE = 1 << 1;

    private static final Singleton<ApexManager> sApexManagerSingleton =
@@ -139,7 +142,14 @@ public abstract class ApexManager {
     */
    public abstract List<ActiveApexInfo> getActiveApexInfos();

    abstract void systemReady(Context context);
    /**
     * Called by package manager service to scan apex package files when device boots up.
     *
     * @param packageParser The package parser which supports caches.
     * @param executorService An executor to support parallel package parsing.
     */
    abstract void scanApexPackagesTraced(@NonNull PackageParser2 packageParser,
            @NonNull ExecutorService executorService);

    /**
     * Retrieves information about an APEX package.
@@ -154,7 +164,7 @@ public abstract class ApexManager {
     *         is not found.
     */
    @Nullable
    abstract PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags);
    public abstract PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags);

    /**
     * Retrieves information about all active APEX packages.
@@ -188,6 +198,27 @@ public abstract class ApexManager {
     */
    abstract boolean isApexPackage(String packageName);

    /**
     * Whether the APEX package is pre-installed or not.
     *
     * @param packageInfo the package to check
     * @return {@code true} if this package is pre-installed, {@code false} otherwise.
     */
    public static boolean isFactory(@NonNull PackageInfo packageInfo) {
        return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
    }

    /**
     * Returns the active apex package's name that contains the (apk) package.
     *
     * @param containedPackage The (apk) package that might be in a apex
     * @return the apex package's name of {@code null} if the {@code containedPackage} is not inside
     *         any apex.
     */
    @Nullable
    public abstract String getActiveApexPackageNameContainingPackage(
            @NonNull AndroidPackage containedPackage);

    /**
     * Retrieves information about an apexd staged session i.e. the internal state used by apexd to
     * track the different states of a session.
@@ -342,7 +373,7 @@ public abstract class ApexManager {
         * difference between {@code packageName} and {@code apexModuleName}.
         */
        @GuardedBy("mLock")
        private Map<String, List<String>> mApksInApex = new ArrayMap<>();
        private ArrayMap<String, List<String>> mApksInApex = new ArrayMap<>();

        @GuardedBy("mLock")
        private List<PackageInfo> mAllPackagesCache;
@@ -357,7 +388,7 @@ public abstract class ApexManager {
         * the apk container to {@code apexModuleName} of the apex-payload inside.
         */
        @GuardedBy("mLock")
        private Map<String, String> mPackageNameToApexModuleName;
        private ArrayMap<String, String> mPackageNameToApexModuleName;

        ApexManagerImpl(IApexService apexService) {
            mApexService = apexService;
@@ -373,16 +404,6 @@ public abstract class ApexManager {
            return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0;
        }

        /**
         * Whether the APEX package is pre-installed or not.
         *
         * @param packageInfo the package to check
         * @return {@code true} if this package is pre-installed, {@code false} otherwise.
         */
        private static boolean isFactory(PackageInfo packageInfo) {
            return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
        }

        @Override
        public List<ActiveApexInfo> getActiveApexInfos() {
            final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing",
@@ -411,77 +432,63 @@ public abstract class ApexManager {
        }

        @Override
        void systemReady(Context context) {
            context.registerReceiver(new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    // Post populateAllPackagesCacheIfNeeded to a background thread, since it's
                    // expensive to run it in broadcast handler thread.
                    BackgroundThread.getHandler().post(() -> populateAllPackagesCacheIfNeeded());
                    context.unregisterReceiver(this);
        void scanApexPackagesTraced(@NonNull PackageParser2 packageParser,
                @NonNull ExecutorService executorService) {
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanApexPackagesTraced");
            try {
                synchronized (mLock) {
                    scanApexPackagesInternalLocked(packageParser, executorService);
                }
            }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
            } finally {
                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            }

        private void populatePackageNameToApexModuleNameIfNeeded() {
            synchronized (mLock) {
                if (mPackageNameToApexModuleName != null) {
                    return;
        }

        @GuardedBy("mLock")
        private void scanApexPackagesInternalLocked(PackageParser2 packageParser,
                ExecutorService executorService) {
            final ApexInfo[] allPkgs;
            try {
                mAllPackagesCache = new ArrayList<>();
                mPackageNameToApexModuleName = new ArrayMap<>();
                    final ApexInfo[] allPkgs = mApexService.getAllPackages();
                    for (int i = 0; i < allPkgs.length; i++) {
                        ApexInfo ai = allPkgs[i];
                        PackageParser.PackageLite pkgLite;
                        try {
                            File apexFile = new File(ai.modulePath);
                            pkgLite = PackageParser.parsePackageLite(apexFile, 0);
                        } catch (PackageParser.PackageParserException pe) {
                            throw new IllegalStateException("Unable to parse: "
                                    + ai.modulePath, pe);
                        }
                        mPackageNameToApexModuleName.put(pkgLite.packageName, ai.moduleName);
                    }
                allPkgs = mApexService.getAllPackages();
            } catch (RemoteException re) {
                    Slog.e(TAG, "Unable to retrieve packages from apexservice: ", re);
                Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString());
                throw new RuntimeException(re);
            }
            }
        }

        private void populateAllPackagesCacheIfNeeded() {
            synchronized (mLock) {
                if (mAllPackagesCache != null) {
            if (allPkgs.length == 0) {
                return;
            }
                try {
                    mAllPackagesCache = new ArrayList<>();
                    HashSet<String> activePackagesSet = new HashSet<>();
                    HashSet<String> factoryPackagesSet = new HashSet<>();
                    final ApexInfo[] allPkgs = mApexService.getAllPackages();
                    for (ApexInfo ai : allPkgs) {
                        // If the device is using flattened APEX, don't report any APEX
                        // packages since they won't be managed or updated by PackageManager.
                        if ((new File(ai.modulePath)).isDirectory()) {
                            break;
                        }
            int flags = PackageManager.GET_META_DATA
                    | PackageManager.GET_SIGNING_CERTIFICATES
                    | PackageManager.GET_SIGNATURES;
                        PackageParser.Package pkg;
                        try {
            ArrayMap<File, ApexInfo> parsingApexInfo = new ArrayMap<>();
            ParallelPackageParser parallelPackageParser =
                    new ParallelPackageParser(packageParser, executorService);

            for (ApexInfo ai : allPkgs) {
                File apexFile = new File(ai.modulePath);
                            PackageParser pp = new PackageParser();
                            pkg = pp.parsePackage(apexFile, flags, false);
                            PackageParser.collectCertificates(pkg, false);
                        } catch (PackageParser.PackageParserException pe) {
                            throw new IllegalStateException("Unable to parse: " + ai, pe);
                parallelPackageParser.submit(apexFile, flags);
                parsingApexInfo.put(apexFile, ai);
            }

                        final PackageInfo packageInfo =
                                PackageParser.generatePackageInfo(pkg, ai, flags);
            HashSet<String> activePackagesSet = new HashSet<>();
            HashSet<String> factoryPackagesSet = new HashSet<>();
            // Process results one by one
            for (int i = 0; i < parsingApexInfo.size(); i++) {
                ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
                Throwable throwable = parseResult.throwable;
                ApexInfo ai = parsingApexInfo.get(parseResult.scanFile);

                if (throwable == null) {
                    final PackageInfo packageInfo = PackageInfoWithoutStateUtils.generate(
                            parseResult.parsedPackage, ai, flags);
                    if (packageInfo == null) {
                        throw new IllegalStateException("Unable to generate package info: "
                                + ai.modulePath);
                    }
                    mAllPackagesCache.add(packageInfo);
                    mPackageNameToApexModuleName.put(packageInfo.packageName, ai.moduleName);
                    if (ai.isActive) {
                        if (activePackagesSet.contains(packageInfo.packageName)) {
                            throw new IllegalStateException(
@@ -498,17 +505,21 @@ public abstract class ApexManager {
                        }
                        factoryPackagesSet.add(packageInfo.packageName);
                    }
                    }
                } catch (RemoteException re) {
                    Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString());
                    throw new RuntimeException(re);
                } else if (throwable instanceof PackageParser.PackageParserException) {
                    throw new IllegalStateException("Unable to parse: " + ai.modulePath, throwable);
                } else {
                    throw new IllegalStateException("Unexpected exception occurred while parsing "
                            + ai.modulePath, throwable);
                }
            }
        }

        @Override
        @Nullable PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags) {
            populateAllPackagesCacheIfNeeded();
        @Nullable
        public PackageInfo getPackageInfo(String packageName,
                @PackageInfoFlags int flags) {
            Preconditions.checkState(mAllPackagesCache != null,
                    "APEX packages have not been scanned");
            boolean matchActive = (flags & MATCH_ACTIVE_PACKAGE) != 0;
            boolean matchFactory = (flags & MATCH_FACTORY_PACKAGE) != 0;
            for (PackageInfo packageInfo: mAllPackagesCache) {
@@ -525,7 +536,8 @@ public abstract class ApexManager {

        @Override
        List<PackageInfo> getActivePackages() {
            populateAllPackagesCacheIfNeeded();
            Preconditions.checkState(mAllPackagesCache != null,
                    "APEX packages have not been scanned");
            return mAllPackagesCache
                    .stream()
                    .filter(item -> isActive(item))
@@ -534,7 +546,8 @@ public abstract class ApexManager {

        @Override
        List<PackageInfo> getFactoryPackages() {
            populateAllPackagesCacheIfNeeded();
            Preconditions.checkState(mAllPackagesCache != null,
                    "APEX packages have not been scanned");
            return mAllPackagesCache
                    .stream()
                    .filter(item -> isFactory(item))
@@ -543,7 +556,8 @@ public abstract class ApexManager {

        @Override
        List<PackageInfo> getInactivePackages() {
            populateAllPackagesCacheIfNeeded();
            Preconditions.checkState(mAllPackagesCache != null,
                    "APEX packages have not been scanned");
            return mAllPackagesCache
                    .stream()
                    .filter(item -> !isActive(item))
@@ -553,7 +567,8 @@ public abstract class ApexManager {
        @Override
        boolean isApexPackage(String packageName) {
            if (!isApexSupported()) return false;
            populateAllPackagesCacheIfNeeded();
            Preconditions.checkState(mAllPackagesCache != null,
                    "APEX packages have not been scanned");
            for (PackageInfo packageInfo : mAllPackagesCache) {
                if (packageInfo.packageName.equals(packageName)) {
                    return true;
@@ -562,6 +577,36 @@ public abstract class ApexManager {
            return false;
        }

        @Override
        @Nullable
        public String getActiveApexPackageNameContainingPackage(
                @NonNull AndroidPackage containedPackage) {
            Preconditions.checkState(mPackageNameToApexModuleName != null,
                    "APEX packages have not been scanned");

            Objects.requireNonNull(containedPackage);

            synchronized (mLock) {
                int numApksInApex = mApksInApex.size();
                for (int apkInApexNum = 0; apkInApexNum < numApksInApex; apkInApexNum++) {
                    if (mApksInApex.valueAt(apkInApexNum).contains(
                            containedPackage.getPackageName())) {
                        String apexModuleName = mApksInApex.keyAt(apkInApexNum);

                        int numApexPkgs = mPackageNameToApexModuleName.size();
                        for (int apexPkgNum = 0; apexPkgNum < numApexPkgs; apexPkgNum++) {
                            if (mPackageNameToApexModuleName.valueAt(apexPkgNum).equals(
                                    apexModuleName)) {
                                return mPackageNameToApexModuleName.keyAt(apexPkgNum);
                            }
                        }
                    }
                }
            }

            return null;
        }

        @Override
        @Nullable ApexSessionInfo getStagedSessionInfo(int sessionId) {
            try {
@@ -684,8 +729,9 @@ public abstract class ApexManager {

        @Override
        List<String> getApksInApex(String apexPackageName) {
            populatePackageNameToApexModuleNameIfNeeded();
            synchronized (mLock) {
                Preconditions.checkState(mPackageNameToApexModuleName != null,
                        "APEX packages have not been scanned");
                String moduleName = mPackageNameToApexModuleName.get(apexPackageName);
                if (moduleName == null) {
                    return Collections.emptyList();
@@ -697,17 +743,19 @@ public abstract class ApexManager {
        @Override
        @Nullable
        public String getApexModuleNameForPackageName(String apexPackageName) {
            populatePackageNameToApexModuleNameIfNeeded();
            synchronized (mLock) {
                Preconditions.checkState(mPackageNameToApexModuleName != null,
                        "APEX packages have not been scanned");
                return mPackageNameToApexModuleName.get(apexPackageName);
            }
        }

        @Override
        public long snapshotCeData(int userId, int rollbackId, String apexPackageName) {
            populatePackageNameToApexModuleNameIfNeeded();
            String apexModuleName;
            synchronized (mLock) {
                Preconditions.checkState(mPackageNameToApexModuleName != null,
                        "APEX packages have not been scanned");
                apexModuleName = mPackageNameToApexModuleName.get(apexPackageName);
            }
            if (apexModuleName == null) {
@@ -724,9 +772,10 @@ public abstract class ApexManager {

        @Override
        public boolean restoreCeData(int userId, int rollbackId, String apexPackageName) {
            populatePackageNameToApexModuleNameIfNeeded();
            String apexModuleName;
            synchronized (mLock) {
                Preconditions.checkState(mPackageNameToApexModuleName != null,
                        "APEX packages have not been scanned");
                apexModuleName = mPackageNameToApexModuleName.get(apexPackageName);
            }
            if (apexModuleName == null) {
@@ -797,15 +846,7 @@ public abstract class ApexManager {
        void dump(PrintWriter pw, @Nullable String packageName) {
            final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ", 120);
            try {
                populateAllPackagesCacheIfNeeded();
                ipw.println();
                ipw.println("Active APEX packages:");
                dumpFromPackagesCache(getActivePackages(), packageName, ipw);
                ipw.println("Inactive APEX packages:");
                dumpFromPackagesCache(getInactivePackages(), packageName, ipw);
                ipw.println("Factory APEX packages:");
                dumpFromPackagesCache(getFactoryPackages(), packageName, ipw);
                ipw.increaseIndent();
                ipw.println("APEX session state:");
                ipw.increaseIndent();
                final ApexSessionInfo[] sessions = mApexService.getSessions();
@@ -834,6 +875,17 @@ public abstract class ApexManager {
                    ipw.decreaseIndent();
                }
                ipw.decreaseIndent();
                ipw.println();
                if (mAllPackagesCache == null) {
                    ipw.println("APEX packages have not been scanned");
                    return;
                }
                ipw.println("Active APEX packages:");
                dumpFromPackagesCache(getActivePackages(), packageName, ipw);
                ipw.println("Inactive APEX packages:");
                dumpFromPackagesCache(getInactivePackages(), packageName, ipw);
                ipw.println("Factory APEX packages:");
                dumpFromPackagesCache(getFactoryPackages(), packageName, ipw);
            } catch (RemoteException e) {
                ipw.println("Couldn't communicate with apexd.");
            }
@@ -879,12 +931,13 @@ public abstract class ApexManager {
        }

        @Override
        void systemReady(Context context) {
        void scanApexPackagesTraced(@NonNull PackageParser2 packageParser,
                @NonNull ExecutorService executorService) {
            // No-op
        }

        @Override
        PackageInfo getPackageInfo(String packageName, int flags) {
        public PackageInfo getPackageInfo(String packageName, int flags) {
            return null;
        }

@@ -908,6 +961,15 @@ public abstract class ApexManager {
            return false;
        }

        @Override
        @Nullable
        public String getActiveApexPackageNameContainingPackage(
                @NonNull AndroidPackage containedPackage) {
            Objects.requireNonNull(containedPackage);

            return null;
        }

        @Override
        ApexSessionInfo getStagedSessionInfo(int sessionId) {
            throw new UnsupportedOperationException();
+3 −1
Original line number Diff line number Diff line
@@ -2900,6 +2900,9 @@ public class PackageManagerService extends IPackageManager.Stub
                    mMetrics, mCacheDir, mPackageParserCallback);
            ExecutorService executorService = ParallelPackageParser.makeExecutorService();
            // Prepare apex package info before scanning APKs, these information are needed when
            // scanning apk in apex.
            mApexManager.scanApexPackagesTraced(packageParser, executorService);
            // Collect vendor/product/system_ext overlay packages. (Do this before scanning
            // any apps.)
            // For security and version matching reason, only consider overlay packages if they
@@ -20696,7 +20699,6 @@ public class PackageManagerService extends IPackageManager.Stub
        storage.registerListener(mStorageListener);
        mInstallerService.systemReady();
        mApexManager.systemReady(mContext);
        mPackageDexOptimizer.systemReady();
        mInjector.getStorageManagerInternal().addExternalStoragePolicy(
+12 −2
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.permission.PermissionManager.KILL_APP_REASON_GIDS_CHANGED;
import static android.permission.PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED;

import static com.android.server.pm.ApexManager.MATCH_ACTIVE_PACKAGE;
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
import static com.android.server.pm.PackageManagerService.DEBUG_PERMISSIONS;
@@ -130,6 +131,7 @@ import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.SystemConfig;
import com.android.server.Watchdog;
import com.android.server.pm.ApexManager;
import com.android.server.pm.PackageManagerServiceUtils;
import com.android.server.pm.PackageSetting;
import com.android.server.pm.SharedUserSetting;
@@ -3317,8 +3319,16 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        if (!privappPermissionsDisable && privilegedPermission && pkg.isPrivileged()
                && !platformPackage && platformPermission) {
            if (!hasPrivappWhitelistEntry(perm, pkg)) {
                // Only report violations for apps on system image
                if (!mSystemReady && !pkgSetting.getPkgState().isUpdatedSystemApp()) {
                ApexManager apexMgr = ApexManager.getInstance();
                String apexContainingPkg = apexMgr.getActiveApexPackageNameContainingPackage(pkg);

                // Only enforce whitelist this on boot
                if (!mSystemReady
                        // Updated system apps do not need to be whitelisted
                        && !pkgSetting.getPkgState().isUpdatedSystemApp()
                        // Apps that are in updated apexs' do not need to be whitelisted
                        && (apexContainingPkg == null || apexMgr.isFactory(
                        apexMgr.getPackageInfo(apexContainingPkg, MATCH_ACTIVE_PACKAGE)))) {
                    // it's only a reportable violation if the permission isn't explicitly denied
                    ArraySet<String> deniedPermissions = null;
                    if (pkg.isVendor()) {
+23 −0

File changed.

Preview size limit exceeded, changes collapsed.