summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Priyanka Advani (xWF) <padvani@google.com> 2024-10-31 15:54:06 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-10-31 15:54:06 +0000
commitbf79bd207badd6aef636714a17f2bc5f7c3f5e35 (patch)
treeeadf7063d512bb9abf08e598e7528ca9f5eed241
parent25e8d87e241516bea579a2c30f1de967012deeb4 (diff)
parent6cd8e946030f5567d5cf5b5a743e11a7c5f21e38 (diff)
Merge "Revert "Enable color resources loader to be created using FRRO"" into main
-rw-r--r--core/java/android/content/om/OverlayManager.java5
-rw-r--r--core/java/android/content/om/OverlayManagerTransaction.java15
-rw-r--r--core/java/android/content/res/AssetManager.java5
-rw-r--r--core/java/android/content/res/loader/ResourcesProvider.java2
-rw-r--r--core/java/android/widget/RemoteViews.java109
-rw-r--r--core/java/com/android/internal/content/om/OverlayConfig.java3
-rw-r--r--core/java/com/android/internal/content/om/OverlayManagerImpl.java20
-rw-r--r--core/tests/overlaytests/device_self_targeting/src/com/android/overlaytest/OverlayManagerImplTest.java15
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.
*
* <p>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<Request> mRequests = new ArrayList<>();
- private boolean mSelfTargeting = false;
/**
* Request that an overlay package be enabled and change its loading
@@ -247,18 +246,6 @@ public final class OverlayManagerTransaction implements Parcelable {
}
/**
- * 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 e6eec3760804..9b6311f35d17 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;
@@ -8552,8 +8552,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;
@@ -8587,6 +8591,44 @@ public class RemoteViews implements Parcelable, Filter {
}
/**
+ * 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.
*
* @param context Context of the view hosting the widget.
@@ -8597,38 +8639,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<String> idmapPaths = new ArrayList<>();
final ArrayList<IdmapInvocation> 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
@@ -210,6 +210,21 @@ public class OverlayManagerImplTest {
}
@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<OverlayInfo> overlayInfos =
mOverlayManagerImpl.getOverlayInfosForTarget(mContext.getPackageName());