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

Commit ee4a564d authored by Ryan Mitchell's avatar Ryan Mitchell
Browse files

Allow for overlaying dynamic shared libraries

Overlays targeting shared libraries should be loaded into the
resources of every target that depends on the shared library.

Static shared libraries are currently not supported because overlays
should override all versions of static shared libraries and there is
not currently support for an overlay targeting multiple APKs.

Also created a test instrumentation and host test suite for testing
overlays and packages on the system image.

Bug: 140790224
Test: atest OverlayRemountedTest
Change-Id: I20a217b6368d6cf92b2b9f46908fd58012933f72
parent fe50d739
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -33,6 +33,8 @@ namespace android::idmap2 {

namespace {

#define REWRITE_PACKAGE(resid, package_id) \
  (((resid)&0x00ffffffU) | (((uint32_t)(package_id)) << 24U))
#define EXTRACT_PACKAGE(resid) ((0xff000000 & (resid)) >> 24)

std::string ConcatPolicies(const std::vector<std::string>& policies) {
@@ -154,6 +156,7 @@ Result<ResourceMapping> ResourceMapping::CreateResourceMapping(const AssetManage
    return Error("root element is not <overlay> tag");
  }

  const uint8_t target_package_id = target_package->GetPackageId();
  const uint8_t overlay_package_id = overlay_package->GetPackageId();
  auto overlay_it_end = root_it.end();
  for (auto overlay_it = root_it.begin(); overlay_it != overlay_it_end; ++overlay_it) {
@@ -187,6 +190,9 @@ Result<ResourceMapping> ResourceMapping::CreateResourceMapping(const AssetManage
      continue;
    }

    // Retrieve the compile-time resource id of the target resource.
    target_id = REWRITE_PACKAGE(target_id, target_package_id);

    if (overlay_resource->dataType == Res_value::TYPE_STRING) {
      overlay_resource->data += string_pool_offset;
    }
@@ -214,6 +220,7 @@ Result<ResourceMapping> ResourceMapping::CreateResourceMappingLegacy(
    const AssetManager2* target_am, const AssetManager2* overlay_am,
    const LoadedPackage* target_package, const LoadedPackage* overlay_package) {
  ResourceMapping resource_mapping;
  const uint8_t target_package_id = target_package->GetPackageId();
  const auto end = overlay_package->end();
  for (auto iter = overlay_package->begin(); iter != end; ++iter) {
    const ResourceId overlay_resid = *iter;
@@ -225,11 +232,14 @@ Result<ResourceMapping> ResourceMapping::CreateResourceMappingLegacy(
    // Find the resource with the same type and entry name within the target package.
    const std::string full_name =
        base::StringPrintf("%s:%s", target_package->GetPackageName().c_str(), name->c_str());
    const ResourceId target_resource = target_am->GetResourceId(full_name);
    ResourceId target_resource = target_am->GetResourceId(full_name);
    if (target_resource == 0U) {
      continue;
    }

    // Retrieve the compile-time resource id of the target resource.
    target_resource = REWRITE_PACKAGE(target_resource, target_package_id);

    resource_mapping.AddMapping(target_resource, Res_value::TYPE_REFERENCE, overlay_resid,
                                /* rewrite_overlay_reference */ false);
  }
+13 −13
Original line number Diff line number Diff line
@@ -482,19 +482,6 @@ public class ResourcesManager {
            }
        }

        if (key.mOverlayDirs != null) {
            for (final String idmapPath : key.mOverlayDirs) {
                try {
                    builder.addApkAssets(loadApkAssets(idmapPath, false /*sharedLib*/,
                            true /*overlay*/));
                } catch (IOException e) {
                    Log.w(TAG, "failed to add overlay path " + idmapPath);

                    // continue.
                }
            }
        }

        if (key.mLibDirs != null) {
            for (final String libDir : key.mLibDirs) {
                if (libDir.endsWith(".apk")) {
@@ -513,6 +500,19 @@ public class ResourcesManager {
            }
        }

        if (key.mOverlayDirs != null) {
            for (final String idmapPath : key.mOverlayDirs) {
                try {
                    builder.addApkAssets(loadApkAssets(idmapPath, false /*sharedLib*/,
                            true /*overlay*/));
                } catch (IOException e) {
                    Log.w(TAG, "failed to add overlay path " + idmapPath);

                    // continue.
                }
            }
        }

        return builder.build();
    }

+1 −1
Original line number Diff line number Diff line
@@ -7803,7 +7803,7 @@ public class PackageParser {
            ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
        }
        ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
        ai.resourceDirs = state.overlayPaths;
        ai.resourceDirs = state.getAllOverlayPaths();
        ai.icon = (sUseRoundIcon && ai.roundIconRes != 0) ? ai.roundIconRes : ai.iconRes;
    }

+61 −1
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ import org.xmlpull.v1.XmlSerializer;

import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;

/**
@@ -77,7 +79,9 @@ public class PackageUserState {
    public ArraySet<String> disabledComponents;
    public ArraySet<String> enabledComponents;

    public String[] overlayPaths;
    private String[] overlayPaths;
    private ArrayMap<String, String[]> sharedLibraryOverlayPaths; // Lib name to overlay paths
    private String[] cachedOverlayPaths;

    @UnsupportedAppUsage
    public PackageUserState() {
@@ -112,9 +116,33 @@ public class PackageUserState {
        enabledComponents = ArrayUtils.cloneOrNull(o.enabledComponents);
        overlayPaths =
            o.overlayPaths == null ? null : Arrays.copyOf(o.overlayPaths, o.overlayPaths.length);
        if (o.sharedLibraryOverlayPaths != null) {
            sharedLibraryOverlayPaths = new ArrayMap<>(o.sharedLibraryOverlayPaths);
        }
        harmfulAppWarning = o.harmfulAppWarning;
    }

    public String[] getOverlayPaths() {
        return overlayPaths;
    }

    public void setOverlayPaths(String[] paths) {
        overlayPaths = paths;
        cachedOverlayPaths = null;
    }

    public Map<String, String[]> getSharedLibraryOverlayPaths() {
        return sharedLibraryOverlayPaths;
    }

    public void setSharedLibraryOverlayPaths(String library, String[] paths) {
        if (sharedLibraryOverlayPaths == null) {
            sharedLibraryOverlayPaths = new ArrayMap<>();
        }
        sharedLibraryOverlayPaths.put(library, paths);
        cachedOverlayPaths = null;
    }

    /**
     * Test if this package is installed.
     */
@@ -235,6 +263,38 @@ public class PackageUserState {
        return isComponentEnabled;
    }

    public String[] getAllOverlayPaths() {
        if (overlayPaths == null && sharedLibraryOverlayPaths == null) {
            return null;
        }

        if (cachedOverlayPaths != null) {
            return cachedOverlayPaths;
        }

        final LinkedHashSet<String> paths = new LinkedHashSet<>();
        if (overlayPaths != null) {
            final int N = overlayPaths.length;
            for (int i = 0; i < N; i++) {
                paths.add(overlayPaths[i]);
            }
        }

        if (sharedLibraryOverlayPaths != null) {
            for (String[] libOverlayPaths : sharedLibraryOverlayPaths.values()) {
                if (libOverlayPaths != null) {
                    final int N = libOverlayPaths.length;
                    for (int i = 0; i < N; i++) {
                        paths.add(libOverlayPaths[i]);
                    }
                }
            }
        }

        cachedOverlayPaths = paths.toArray(new String[0]);
        return cachedOverlayPaths;
    }

    @Override
    final public boolean equals(Object obj) {
        if (!(obj instanceof PackageUserState)) {
+3 −1
Original line number Diff line number Diff line
@@ -41,9 +41,11 @@ import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation;
import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
import android.content.pm.parsing.ComponentParseUtils.ParsedPermissionGroup;
import android.util.ArraySet;

import com.android.internal.util.ArrayUtils;

import java.util.LinkedHashSet;
import java.util.Set;

/** @hide */
@@ -545,7 +547,7 @@ public class PackageInfoUtils {
            ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
        }
        ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
        ai.resourceDirs = state.overlayPaths;
        ai.resourceDirs = state.getAllOverlayPaths();
        ai.icon = (PackageParser.sUseRoundIcon && ai.roundIconRes != 0)
                ? ai.roundIconRes : ai.iconRes;
    }
Loading