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

Commit 09341a5e authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Fix RRO loading from inside APEXes." am: de3baffb am: 23cd20c9

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1830600

Change-Id: I2d2fdda8b4f0fc6f4c9b32ca3e2e1c810b3d5384
parents 50ccf043 23cd20c9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -294,6 +294,7 @@ java_defaults {
    srcs: [
        ":framework-non-updatable-sources",
        "core/java/**/*.logtags",
        ":apex-info-list",
    ],
    aidl: {
        generate_get_transaction_name: true,
+49 −6
Original line number Diff line number Diff line
@@ -25,17 +25,22 @@ import android.os.Trace;
import android.util.ArrayMap;
import android.util.Log;

import com.android.apex.ApexInfo;
import com.android.apex.XmlParser;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.om.OverlayConfigParser.OverlayPartition;
import com.android.internal.content.om.OverlayConfigParser.ParsedConfiguration;
import com.android.internal.content.om.OverlayScanner.ParsedOverlayInfo;
import com.android.internal.util.Preconditions;
import com.android.internal.util.function.TriConsumer;

import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.function.BiConsumer;
import java.util.List;
import java.util.function.Supplier;

/**
@@ -73,7 +78,7 @@ public class OverlayConfig {
    public interface PackageProvider {

        /** Performs the given action for each package. */
        void forEachPackage(BiConsumer<ParsingPackageRead, Boolean> p);
        void forEachPackage(TriConsumer<ParsingPackageRead, Boolean, File> p);
    }

    private static final Comparator<ParsedConfiguration> sStaticOverlayComparator = (c1, c2) -> {
@@ -115,6 +120,8 @@ public class OverlayConfig {
                            p)));
        }

        ArrayMap<Integer, List<String>> activeApexesPerPartition = getActiveApexes(partitions);

        boolean foundConfigFile = false;
        ArrayList<ParsedOverlayInfo> packageManagerOverlayInfos = null;

@@ -123,7 +130,9 @@ public class OverlayConfig {
            final OverlayPartition partition = partitions.get(i);
            final OverlayScanner scanner = (scannerFactory == null) ? null : scannerFactory.get();
            final ArrayList<ParsedConfiguration> partitionOverlays =
                    OverlayConfigParser.getConfigurations(partition, scanner);
                    OverlayConfigParser.getConfigurations(partition, scanner,
                            activeApexesPerPartition.getOrDefault(partition.type,
                                    Collections.emptyList()));
            if (partitionOverlays != null) {
                foundConfigFile = true;
                overlays.addAll(partitionOverlays);
@@ -145,7 +154,8 @@ public class OverlayConfig {
                // Filter out overlays not present in the partition.
                partitionOverlayInfos = new ArrayList<>(packageManagerOverlayInfos);
                for (int j = partitionOverlayInfos.size() - 1; j >= 0; j--) {
                    if (!partition.containsFile(partitionOverlayInfos.get(j).path)) {
                    if (!partition.containsFile(partitionOverlayInfos.get(j)
                            .getOriginalPartitionPath())) {
                        partitionOverlayInfos.remove(j);
                    }
                }
@@ -292,16 +302,49 @@ public class OverlayConfig {
    private static ArrayList<ParsedOverlayInfo> getOverlayPackageInfos(
            @NonNull PackageProvider packageManager) {
        final ArrayList<ParsedOverlayInfo> overlays = new ArrayList<>();
        packageManager.forEachPackage((ParsingPackageRead p, Boolean isSystem) -> {
        packageManager.forEachPackage((ParsingPackageRead p, Boolean isSystem,
                @Nullable File preInstalledApexPath) -> {
            if (p.getOverlayTarget() != null && isSystem) {
                overlays.add(new ParsedOverlayInfo(p.getPackageName(), p.getOverlayTarget(),
                        p.getTargetSdkVersion(), p.isOverlayIsStatic(), p.getOverlayPriority(),
                        new File(p.getBaseApkPath())));
                        new File(p.getBaseApkPath()), preInstalledApexPath));
            }
        });
        return overlays;
    }

    /** Returns a map of PartitionType to List of active APEX module names. */
    @NonNull
    private static ArrayMap<Integer, List<String>> getActiveApexes(
            @NonNull List<OverlayPartition> partitions) {
        // An Overlay in an APEX, which is an update of an APEX in a given partition,
        // is considered as belonging to that partition.
        ArrayMap<Integer, List<String>> result = new ArrayMap<>();
        for (OverlayPartition partition : partitions) {
            result.put(partition.type, new ArrayList<String>());
        }
        // Read from apex-info-list because ApexManager is not accessible to zygote.
        File apexInfoList = new File("/apex/apex-info-list.xml");
        if (apexInfoList.exists() && apexInfoList.canRead()) {
            try (FileInputStream stream = new FileInputStream(apexInfoList)) {
                List<ApexInfo> apexInfos = XmlParser.readApexInfoList(stream).getApexInfo();
                for (ApexInfo info : apexInfos) {
                    if (info.getIsActive()) {
                        for (OverlayPartition partition : partitions) {
                            if (partition.containsPath(info.getPreinstalledModulePath())) {
                                result.get(partition.type).add(info.getModuleName());
                                break;
                            }
                        }
                    }
                }
            } catch (Exception e) {
                Log.w(TAG, "Error reading apex-info-list: " + e);
            }
        }
        return result;
    }

    /** Represents a single call to idmap create-multiple. */
    @VisibleForTesting
    public static class IdmapInvocation {
+12 −5
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Responsible for parsing configurations of Runtime Resource Overlays that control mutability,
@@ -192,14 +193,20 @@ final class OverlayConfigParser {
     */
    @Nullable
    static ArrayList<ParsedConfiguration> getConfigurations(
            @NonNull OverlayPartition partition, @Nullable OverlayScanner scanner) {
        if (partition.getOverlayFolder() == null) {
            return null;
        }

            @NonNull OverlayPartition partition, @Nullable OverlayScanner scanner,
            @NonNull List<String> activeApexes) {
        if (scanner != null) {
            if (partition.getOverlayFolder() != null) {
                scanner.scanDir(partition.getOverlayFolder());
            }
            for (String apex : activeApexes) {
                scanner.scanDir(new File("/apex/" + apex + "/overlay/"));
            }
        }

        if (partition.getOverlayFolder() == null) {
            return null;
        }

        final File configFile = new File(partition.getOverlayFolder(), CONFIG_DEFAULT_FILENAME);
        if (!configFile.exists()) {
+19 −4
Original line number Diff line number Diff line
@@ -47,23 +47,38 @@ public class OverlayScanner {
        public final boolean isStatic;
        public final int priority;
        public final File path;
        @Nullable public final File preInstalledApexPath;

        public ParsedOverlayInfo(String packageName, String targetPackageName,
                int targetSdkVersion, boolean isStatic, int priority, File path) {
                int targetSdkVersion, boolean isStatic, int priority, File path,
                @Nullable File preInstalledApexPath) {
            this.packageName = packageName;
            this.targetPackageName = targetPackageName;
            this.targetSdkVersion = targetSdkVersion;
            this.isStatic = isStatic;
            this.priority = priority;
            this.path = path;
            this.preInstalledApexPath = preInstalledApexPath;
        }

        @Override
        public String toString() {
            return getClass().getSimpleName() + String.format("{packageName=%s"
                            + ", targetPackageName=%s, targetSdkVersion=%s, isStatic=%s"
                            + ", priority=%s, path=%s}",
                    packageName, targetPackageName, targetSdkVersion, isStatic, priority, path);
                            + ", priority=%s, path=%s, preInstalledApexPath=%s}",
                    packageName, targetPackageName, targetSdkVersion, isStatic,
                    priority, path, preInstalledApexPath);
        }

        /**
         * Retrieves the path of the overlay in its original installation partition.
         *
         * An Overlay in an APEX, which is an update of an APEX in a given partition,
         * is considered as belonging to that partition.
         */
        @NonNull
        public File getOriginalPartitionPath() {
            return preInstalledApexPath != null ? preInstalledApexPath : path;
        }
    }

@@ -138,6 +153,6 @@ public class OverlayScanner {
        return apkLite.getTargetPackageName() == null ? null :
                new ParsedOverlayInfo(apkLite.getPackageName(), apkLite.getTargetPackageName(),
                        apkLite.getTargetSdkVersion(), apkLite.isOverlayIsStatic(),
                        apkLite.getOverlayPriority(), new File(apkLite.getPath()));
                        apkLite.getOverlayPriority(), new File(apkLite.getPath()), null);
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -138,6 +138,14 @@ bool FileDescriptorAllowlist::IsAllowed(const std::string& path) const {
        return true;
    }

    // Allow Runtime Resource Overlays inside APEXes.
    static const char* kOverlayPathSuffix = "/overlay";
    if (android::base::StartsWith(path, kApexPrefix) &&
        android::base::EndsWith(android::base::Dirname(path), kOverlayPathSuffix) &&
        android::base::EndsWith(path, kApkSuffix) && path.find("/../") == std::string::npos) {
        return true;
    }

    static const char* kOverlayIdmapPrefix = "/data/resource-cache/";
    static const char* kOverlayIdmapSuffix = ".apk@idmap";
    if (android::base::StartsWith(path, kOverlayIdmapPrefix) &&
Loading