From 212f61cf586c73035b642a99167bc1c6fc88dc05 Mon Sep 17 00:00:00 2001 From: felkachang Date: Mon, 28 Nov 2022 14:29:44 +0800 Subject: [PATCH] Add a new function in ResourcesProvider for SelfTargeting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds a new function to load a SelfTargeting overlay to be a ResourcesProvider instance. If the app wants to overlay itself’s resources, the first step is to call this new function to get a ResourcesProvider instance and then add the ResourcesProvider in a ResourcesLoader instance. * ResourcesProvider#loadOverlay Test: atest \ OverlayHostTests \ OverlayDeviceTests \ SelfTargetingOverlayDeviceTests \ OverlayRemountedTest \ FrameworksServicesTests:com.android.server.om \ CtsContentTestCases:android.content.om.cts \ CtsContentTestCases:android.content.res.loader.cts \ idmap2_tests Bug: 205919743 Change-Id: Id54da44a54ee6cbc685ad486d1bf69ef388c33ae --- .../content/res/loader/ResourcesProvider.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/core/java/android/content/res/loader/ResourcesProvider.java b/core/java/android/content/res/loader/ResourcesProvider.java index 463dcaced7233..a5a1fa689f9bc 100644 --- a/core/java/android/content/res/loader/ResourcesProvider.java +++ b/core/java/android/content/res/loader/ResourcesProvider.java @@ -18,7 +18,10 @@ package android.content.res.loader; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.content.Context; +import android.content.om.OverlayInfo; +import android.content.om.OverlayManager; import android.content.pm.ApplicationInfo; import android.content.res.ApkAssets; import android.content.res.AssetFileDescriptor; @@ -27,11 +30,17 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.content.om.OverlayManagerImpl; import com.android.internal.util.ArrayUtils; +import com.android.internal.util.Preconditions; import java.io.Closeable; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Objects; /** * Provides methods to load resources data from APKs ({@code .apk}) and resources tables @@ -62,6 +71,48 @@ public class ResourcesProvider implements AutoCloseable, Closeable { assetsProvider)); } + /** + * Creates a ResourcesProvider instance from the specified overlay information. + * + *

In order to enable the registered overlays, an application can create a {@link + * ResourcesProvider} instance according to the specified {@link OverlayInfo} instance and put + * them into a {@link ResourcesLoader} instance. The application calls {@link + * android.content.res.Resources#addLoaders(ResourcesLoader...)} to load the overlays. + * + * @param overlayInfo is the information about the specified overlay + * @return the resources provider instance for the {@code overlayInfo} + * @throws IOException when the files can't be loaded. + * @see OverlayManager#getOverlayInfosForTarget(String) to get the list of overlay info. + * @hide + */ + @SuppressLint("WrongConstant") // TODO(b/238713267): ApkAssets blocks PROPERTY_LOADER + @NonNull + public static ResourcesProvider loadOverlay(@NonNull OverlayInfo overlayInfo) + throws IOException { + Objects.requireNonNull(overlayInfo); + Preconditions.checkArgument(overlayInfo.isFabricated(), "Not accepted overlay"); + Preconditions.checkStringNotEmpty( + overlayInfo.getTargetOverlayableName(), "Without overlayable name"); + final String overlayName = + OverlayManagerImpl.checkOverlayNameValid(overlayInfo.getOverlayName()); + final String path = + Preconditions.checkStringNotEmpty( + overlayInfo.getBaseCodePath(), "Invalid base path"); + + final Path frroPath = Path.of(path); + if (!Files.isRegularFile(frroPath)) { + throw new FileNotFoundException("The frro file not found"); + } + final Path idmapPath = frroPath.getParent().resolve(overlayName + ".idmap"); + if (!Files.isRegularFile(idmapPath)) { + throw new FileNotFoundException("The idmap file not found"); + } + + return new ResourcesProvider( + ApkAssets.loadOverlayFromPath( + idmapPath.toString(), 0 /* flags: self targeting overlay */)); + } + /** * Creates a ResourcesProvider from an APK ({@code .apk}) file descriptor. *