From 6cd8e946030f5567d5cf5b5a743e11a7c5f21e38 Mon Sep 17 00:00:00 2001 From: "Priyanka Advani (xWF)" Date: Wed, 30 Oct 2024 22:46:01 +0000 Subject: Revert "Enable color resources loader to be created using FRRO" Revert submission 29910507-launcher-color-preview-fix Reason for revert: Droidmonitor created revert due to b/376534782. Will be verifying through ABTD before submission. Reverted changes: /q/submissionid:29910507-launcher-color-preview-fix Change-Id: I4f715bdcb0ba1769a16dbf1abe43c1e88fafa769 --- core/java/android/content/om/OverlayManager.java | 5 +- .../content/om/OverlayManagerTransaction.java | 15 +-- core/java/android/content/res/AssetManager.java | 5 +- .../content/res/loader/ResourcesProvider.java | 2 + core/java/android/widget/RemoteViews.java | 109 ++++++++++++++------- .../android/internal/content/om/OverlayConfig.java | 3 +- .../internal/content/om/OverlayManagerImpl.java | 20 ++-- .../overlaytest/OverlayManagerImplTest.java | 15 +++ 8 files changed, 102 insertions(+), 72 deletions(-) diff --git a/core/java/android/content/om/OverlayManager.java b/core/java/android/content/om/OverlayManager.java index 6db7dfe4f705..ed965b3d1777 100644 --- a/core/java/android/content/om/OverlayManager.java +++ b/core/java/android/content/om/OverlayManager.java @@ -78,8 +78,7 @@ public class OverlayManager { /** * Applications can use OverlayManager to create overlays to overlay on itself resources. The - * overlay target is itself, or the Android package, and the work range is only in caller - * application. + * overlay target is itself and the work range is only in caller application. * *

In {@link android.content.Context#getSystemService(String)}, it crashes because of {@link * java.lang.NullPointerException} if the parameter is OverlayManager. if the self-targeting is @@ -402,7 +401,7 @@ public class OverlayManager { } /** - * Get the related information of self-targeting overlays for {@code targetPackageName}. + * Get the related information of overlays for {@code targetPackageName}. * * @param targetPackageName the target package name * @return a list of overlay information diff --git a/core/java/android/content/om/OverlayManagerTransaction.java b/core/java/android/content/om/OverlayManagerTransaction.java index 87b2e9350aa1..becd0ea285af 100644 --- a/core/java/android/content/om/OverlayManagerTransaction.java +++ b/core/java/android/content/om/OverlayManagerTransaction.java @@ -209,7 +209,6 @@ public final class OverlayManagerTransaction implements Parcelable { */ public static final class Builder { private final List mRequests = new ArrayList<>(); - private boolean mSelfTargeting = false; /** * Request that an overlay package be enabled and change its loading @@ -246,18 +245,6 @@ public final class OverlayManagerTransaction implements Parcelable { return this; } - /** - * Request that an overlay package be self-targeting. Self-targeting overlays enable - * applications to overlay on itself resources. The overlay target is itself, or the Android - * package, and the work range is only in caller application. - * @param selfTargeting whether the overlay is self-targeting, the default is false. - * @hide - */ - public Builder setSelfTargeting(boolean selfTargeting) { - mSelfTargeting = selfTargeting; - return this; - } - /** * Registers the fabricated overlay with the overlay manager so it can be enabled and * disabled for any user. @@ -299,7 +286,7 @@ public final class OverlayManagerTransaction implements Parcelable { */ @NonNull public OverlayManagerTransaction build() { - return new OverlayManagerTransaction(mRequests, mSelfTargeting); + return new OverlayManagerTransaction(mRequests, false /* selfTargeting */); } } diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index 347bebdf46e7..6fd4d0141977 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -75,10 +75,7 @@ public final class AssetManager implements AutoCloseable { private static final String TAG = "AssetManager"; private static final boolean DEBUG_REFS = false; - /** - * @hide - */ - public static final String FRAMEWORK_APK_PATH = getFrameworkApkPath(); + private static final String FRAMEWORK_APK_PATH = getFrameworkApkPath(); private static final String FRAMEWORK_APK_PATH_DEVICE = "/system/framework/framework-res.apk"; private static final String FRAMEWORK_APK_PATH_RAVENWOOD = "ravenwood-data/framework-res.apk"; diff --git a/core/java/android/content/res/loader/ResourcesProvider.java b/core/java/android/content/res/loader/ResourcesProvider.java index 830b7e0fa2d0..b097bc0dcd8c 100644 --- a/core/java/android/content/res/loader/ResourcesProvider.java +++ b/core/java/android/content/res/loader/ResourcesProvider.java @@ -90,6 +90,8 @@ public class ResourcesProvider implements AutoCloseable, Closeable { 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 = diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index d65bf7c5e1a5..d7b5211ad9fd 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -20,7 +20,6 @@ import static android.appwidget.flags.Flags.FLAG_DRAW_DATA_PARCEL; import static android.appwidget.flags.Flags.FLAG_REMOTE_VIEWS_PROTO; import static android.appwidget.flags.Flags.drawDataParcel; import static android.appwidget.flags.Flags.remoteAdapterConversion; -import static android.util.TypedValue.TYPE_INT_COLOR_ARGB8; import static android.util.proto.ProtoInputStream.NO_MORE_FIELDS; import static android.view.inputmethod.Flags.FLAG_HOME_SCREEN_HANDWRITING_DELEGATOR; @@ -55,10 +54,6 @@ import android.content.ContextWrapper; import android.content.Intent; import android.content.IntentSender; import android.content.ServiceConnection; -import android.content.om.FabricatedOverlay; -import android.content.om.OverlayInfo; -import android.content.om.OverlayManager; -import android.content.om.OverlayManagerTransaction; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.ColorStateList; @@ -84,12 +79,14 @@ import android.os.Bundle; import android.os.CancellationSignal; import android.os.IBinder; import android.os.Parcel; +import android.os.ParcelFileDescriptor; import android.os.Parcelable; import android.os.Process; import android.os.RemoteException; import android.os.StrictMode; import android.os.Trace; import android.os.UserHandle; +import android.system.Os; import android.text.TextUtils; import android.util.ArrayMap; import android.util.DisplayMetrics; @@ -131,8 +128,11 @@ import com.android.internal.widget.remotecompose.player.RemoteComposePlayer; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.FileDescriptor; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -8546,8 +8546,12 @@ public class RemoteViews implements Parcelable, Filter { * @hide */ public static final class ColorResources { - private static final String OVERLAY_NAME = "remote_views_color_resources"; - private static final String OVERLAY_TARGET_PACKAGE_NAME = "android"; + // Set of valid colors resources. + private static final int FIRST_RESOURCE_COLOR_ID = android.R.color.system_neutral1_0; + private static final int LAST_RESOURCE_COLOR_ID = + android.R.color.system_error_1000; + // Size, in bytes, of an entry in the array of colors in an ARSC file. + private static final int ARSC_ENTRY_SIZE = 16; private final ResourcesLoader mLoader; private final SparseIntArray mColorMapping; @@ -8580,6 +8584,44 @@ public class RemoteViews implements Parcelable, Filter { return content; } + /** + * Creates the compiled resources content from the asset stored in the APK. + * + * The asset is a compiled resource with the correct resources name and correct ids, only + * the values are incorrect. The last value is at the very end of the file. The resources + * are in an array, the array's entries are 16 bytes each. We use this to work out the + * location of all the positions of the various resources. + */ + @Nullable + private static byte[] createCompiledResourcesContent(Context context, + SparseIntArray colorResources) throws IOException { + byte[] content; + try (InputStream input = context.getResources().openRawResource( + com.android.internal.R.raw.remote_views_color_resources)) { + ByteArrayOutputStream rawContent = readFileContent(input); + content = rawContent.toByteArray(); + } + int valuesOffset = + content.length - (LAST_RESOURCE_COLOR_ID & 0xffff) * ARSC_ENTRY_SIZE - 4; + if (valuesOffset < 0) { + Log.e(LOG_TAG, "ARSC file for theme colors is invalid."); + return null; + } + for (int colorRes = FIRST_RESOURCE_COLOR_ID; colorRes <= LAST_RESOURCE_COLOR_ID; + colorRes++) { + // The last 2 bytes are the index in the color array. + int index = colorRes & 0xffff; + int offset = valuesOffset + index * ARSC_ENTRY_SIZE; + int value = colorResources.get(colorRes, context.getColor(colorRes)); + // Write the 32 bit integer in little endian + for (int b = 0; b < 4; b++) { + content[offset + b] = (byte) (value & 0xff); + value >>= 8; + } + } + return content; + } + /** * Adds a resource loader for theme colors to the given context. * @@ -8591,38 +8633,31 @@ public class RemoteViews implements Parcelable, Filter { @Nullable public static ColorResources create(Context context, SparseIntArray colorMapping) { try { - String owningPackage = context.getPackageName(); - FabricatedOverlay overlay = new FabricatedOverlay.Builder(owningPackage, - OVERLAY_NAME, OVERLAY_TARGET_PACKAGE_NAME).build(); - - for (int i = 0; i < colorMapping.size(); i++) { - overlay.setResourceValue( - context.getResources().getResourceName(colorMapping.keyAt(i)), - TYPE_INT_COLOR_ARGB8, colorMapping.valueAt(i), null); - } - OverlayManager overlayManager = context.getSystemService(OverlayManager.class); - OverlayManagerTransaction.Builder transaction = - new OverlayManagerTransaction.Builder() - .registerFabricatedOverlay(overlay) - .setSelfTargeting(true); - overlayManager.commit(transaction.build()); - - OverlayInfo overlayInfo = - overlayManager.getOverlayInfosForTarget(OVERLAY_TARGET_PACKAGE_NAME) - .stream() - .filter(info -> TextUtils.equals(info.overlayName, OVERLAY_NAME) - && TextUtils.equals(info.packageName, owningPackage)) - .findFirst() - .orElse(null); - if (overlayInfo == null) { - Log.e(LOG_TAG, "Failed to get overlay info ", new Throwable()); + byte[] contentBytes = createCompiledResourcesContent(context, colorMapping); + if (contentBytes == null) { return null; } - ResourcesLoader colorsLoader = new ResourcesLoader(); - colorsLoader.addProvider(ResourcesProvider.loadOverlay(overlayInfo)); - return new ColorResources(colorsLoader, colorMapping.clone()); - } catch (Exception e) { - Log.e(LOG_TAG, "Failed to add theme color overlay into loader", e); + FileDescriptor arscFile = null; + try { + arscFile = Os.memfd_create("remote_views_theme_colors.arsc", 0 /* flags */); + // Note: This must not be closed through the OutputStream. + try (OutputStream pipeWriter = new FileOutputStream(arscFile)) { + pipeWriter.write(contentBytes); + + try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(arscFile)) { + ResourcesLoader colorsLoader = new ResourcesLoader(); + colorsLoader.addProvider(ResourcesProvider + .loadFromTable(pfd, null /* assetsProvider */)); + return new ColorResources(colorsLoader, colorMapping.clone()); + } + } + } finally { + if (arscFile != null) { + Os.close(arscFile); + } + } + } catch (Exception ex) { + Log.e(LOG_TAG, "Failed to setup the context for theme colors", ex); } return null; } diff --git a/core/java/com/android/internal/content/om/OverlayConfig.java b/core/java/com/android/internal/content/om/OverlayConfig.java index 38593b4a2a99..07e178c0ba27 100644 --- a/core/java/com/android/internal/content/om/OverlayConfig.java +++ b/core/java/com/android/internal/content/om/OverlayConfig.java @@ -19,7 +19,6 @@ package com.android.internal.content.om; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.pm.PackagePartitions; -import android.content.res.AssetManager; import android.os.Build; import android.os.Trace; import android.util.ArrayMap; @@ -534,7 +533,7 @@ public class OverlayConfig { */ @NonNull public String[] createImmutableFrameworkIdmapsInZygote() { - final String targetPath = AssetManager.FRAMEWORK_APK_PATH; + final String targetPath = "/system/framework/framework-res.apk"; final ArrayList idmapPaths = new ArrayList<>(); final ArrayList idmapInvocations = getImmutableFrameworkOverlayIdmapInvocations(); diff --git a/core/java/com/android/internal/content/om/OverlayManagerImpl.java b/core/java/com/android/internal/content/om/OverlayManagerImpl.java index fa5cf2a396b9..c4624498138d 100644 --- a/core/java/com/android/internal/content/om/OverlayManagerImpl.java +++ b/core/java/com/android/internal/content/om/OverlayManagerImpl.java @@ -35,7 +35,6 @@ import android.content.om.OverlayManagerTransaction.Request; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.parsing.FrameworkParsingPackageUtils; -import android.content.res.AssetManager; import android.os.FabricatedOverlayInfo; import android.os.FabricatedOverlayInternal; import android.os.FabricatedOverlayInternalEntry; @@ -61,8 +60,8 @@ import java.util.List; import java.util.Objects; /** - * This class provides the functionalities for managing self-targeting overlays, including - * registering an overlay, unregistering an overlay, and getting the list of overlays information. + * This class provides the functionalities of registering an overlay, unregistering an overlay, and + * getting the list of overlays information. */ public class OverlayManagerImpl { private static final String TAG = "OverlayManagerImpl"; @@ -235,17 +234,14 @@ public class OverlayManagerImpl { Preconditions.checkArgument(!entryList.isEmpty(), "overlay entries shouldn't be empty"); final String overlayName = checkOverlayNameValid(overlayInternal.overlayName); checkPackageName(overlayInternal.packageName); - Preconditions.checkStringNotEmpty(overlayInternal.targetPackageName); + checkPackageName(overlayInternal.targetPackageName); + Preconditions.checkStringNotEmpty( + overlayInternal.targetOverlayable, + "Target overlayable should be neither null nor empty string."); final ApplicationInfo applicationInfo = mContext.getApplicationInfo(); - String targetPackage = null; - if (TextUtils.equals(overlayInternal.targetPackageName, "android")) { - targetPackage = AssetManager.FRAMEWORK_APK_PATH; - } else { - targetPackage = Preconditions.checkStringNotEmpty( - applicationInfo.getBaseCodePath()); - } - + final String targetPackage = Preconditions.checkStringNotEmpty( + applicationInfo.getBaseCodePath()); final Path frroPath = mBasePath.resolve(overlayName + FRRO_EXTENSION); final Path idmapPath = mBasePath.resolve(overlayName + IDMAP_EXTENSION); diff --git a/core/tests/overlaytests/device_self_targeting/src/com/android/overlaytest/OverlayManagerImplTest.java b/core/tests/overlaytests/device_self_targeting/src/com/android/overlaytest/OverlayManagerImplTest.java index 28d6545c8a5b..40d0bef2fb0f 100644 --- a/core/tests/overlaytests/device_self_targeting/src/com/android/overlaytest/OverlayManagerImplTest.java +++ b/core/tests/overlaytests/device_self_targeting/src/com/android/overlaytest/OverlayManagerImplTest.java @@ -209,6 +209,21 @@ public class OverlayManagerImplTest { return overlayInternal; } + @Test + public void registerOverlay_forAndroidPackage_shouldFail() { + FabricatedOverlayInternal overlayInternal = + createOverlayWithName( + mOverlayName, + SYSTEM_APP_OVERLAYABLE, + "android", + List.of(Pair.create("color/white", Pair.create(null, Color.BLACK)))); + + assertThrows( + "Wrong target package name", + IllegalArgumentException.class, + () -> mOverlayManagerImpl.registerFabricatedOverlay(overlayInternal)); + } + @Test public void getOverlayInfosForTarget_defaultShouldBeZero() { List overlayInfos = -- cgit v1.2.3-59-g8ed1b