Prepare comments and annotations for public FabricatedOverlay API
This patch adds the following items.
* FabricatedOverlay class comments.
* add a FabricatedOverlay contructor
* add a public method `setTargetOverlayable`
* add setResourceValue APIs for
* int
* String
* ParcelFileDescriptor
* comments and annotations for methods in FabricatedOverlay.
* such as nullability
Bug: 205919743
Test: atest \
OverlayHostTests \
OverlayDeviceTests \
SelfTargetingOverlayDeviceTests \
OverlayRemountedTest \
FrameworksServicesTests:com.android.server.om \
CtsContentTestCases:android.content.om.cts \
idmap2_tests
Change-Id: I689f5882fc3e1fc74a343106ef310f23a83990cf
diff --git a/core/java/android/content/om/FabricatedOverlay.java b/core/java/android/content/om/FabricatedOverlay.java
index 99fc5a3..e4936bc 100644
--- a/core/java/android/content/om/FabricatedOverlay.java
+++ b/core/java/android/content/om/FabricatedOverlay.java
@@ -35,29 +35,84 @@
import java.util.Objects;
/**
- * Fabricated Runtime Resource Overlays (FRROs) are overlays generated ar runtime.
+ * FabricatedOverlay describes the content of Fabricated Runtime Resource Overlay (FRRO) that is
+ * used to overlay the app's resources. The app should register the {@link FabricatedOverlay}
+ * instance in an {@link OverlayManagerTransaction} by calling {@link
+ * OverlayManagerTransaction#registerFabricatedOverlay(FabricatedOverlay)}. The FRRO is
+ * created once the transaction is committed successfully.
*
- * Fabricated overlays are enabled, disabled, and reordered just like normal overlays. The
- * overlayable policies a fabricated overlay fulfills are the same policies the creator of the
- * overlay fulfill. For example, a fabricated overlay created by a platform signed package on the
- * system partition would fulfil the {@code system} and {@code signature} policies.
+ * <p>The app creates a FabricatedOverlay to describe the how to overlay string, integer, and file
+ * type resources. Before creating any frro, please define a target overlayable in {@code
+ * res/values/overlayable.xml} that describes what kind of resources can be overlaid, what kind of
+ * roles or applications can overlay the resources. Here is an example.
*
- * The owner of a fabricated overlay is the UID that created it. Overlays commit to the overlay
- * manager persist across reboots. When the UID is uninstalled, its fabricated overlays are wiped.
+ * <pre>{@code
+ * <overlayable name="SignatureOverlayable" actor="overlay://theme">
+ * <!-- The app with the same signature can overlay the below resources -->
+ * <policy type="signature">
+ * <item type="color" name="mycolor" />
+ * <item type="string" name="mystring" />
+ * </policy>
+ * </overlayable>
+ * }</pre>
*
- * Processes with {@link Android.Manifest.permission.CHANGE_OVERLAY_PACKAGES} can manage normal
- * overlays and fabricated overlays.
+ * <p>The overlay must assign the target overlayable name just like the above example by calling
+ * {@link #setTargetOverlayable(String)}. Here is an example:
+ *
+ * <pre>{@code
+ * FabricatedOverlay fabricatedOverlay = new FabricatedOverlay("overlay_name",
+ * context.getPackageName());
+ * fabricatedOverlay.setTargetOverlayable("SignatureOverlayable")
+ * fabricatedOverlay.setResourceValue("mycolor", TypedValue.TYPE_INT_COLOR_ARGB8, Color.White)
+ * fabricatedOverlay.setResourceValue("mystring", TypedValue.TYPE_STRING, "Hello")
+ * }</pre>
+ *
+ * <p>The app can create any {@link FabricatedOverlay} instance by calling the following APIs.
+ *
+ * <ul>
+ * <li>{@link #setTargetOverlayable(String)}
+ * <li>{@link #setResourceValue(String, int, int, String)}
+ * <li>{@link #setResourceValue(String, int, String, String)}
+ * <li>{@link #setResourceValue(String, ParcelFileDescriptor, String)}
+ * </ul>
+ *
+ * @see OverlayManager
+ * @see OverlayManagerTransaction
* @hide
*/
public class FabricatedOverlay {
- /** Retrieves the identifier for this fabricated overlay. */
+ /**
+ * Retrieves the identifier for this fabricated overlay.
+ * @return the overlay identifier
+ *
+ * @hide
+ */
public OverlayIdentifier getIdentifier() {
return new OverlayIdentifier(
mOverlay.packageName, TextUtils.nullIfEmpty(mOverlay.overlayName));
}
- public static class Builder {
+ /**
+ * The builder of Fabricated Runtime Resource Overlays(FRROs).
+ *
+ * Fabricated overlays are enabled, disabled, and reordered just like normal overlays. The
+ * overlayable policies a fabricated overlay fulfills are the same policies the creator of the
+ * overlay fulfill. For example, a fabricated overlay created by a platform signed package on
+ * the system partition would fulfil the {@code system} and {@code signature} policies.
+ *
+ * The owner of a fabricated overlay is the UID that created it. Overlays commit to the overlay
+ * manager persist across reboots. When the UID is uninstalled, its fabricated overlays are
+ * wiped.
+ *
+ * Processes with {@code android.Manifest.permission#CHANGE_OVERLAY_PACKAGES} can manage normal
+ * overlays and fabricated overlays.
+ *
+ * @see FabricatedOverlay
+ * @see OverlayManagerTransaction.Builder#registerFabricatedOverlay(FabricatedOverlay)
+ * @hide
+ */
+ public static final class Builder {
private final String mOwningPackage;
private final String mName;
private final String mTargetPackage;
@@ -88,22 +143,16 @@
}
/**
- * Constructs a builder for building a fabricated overlay.
+ * Sets the name of the target overlayable to be overlaid.
*
- * @param name a name used to uniquely identify the fabricated overlay owned by the caller
- * itself.
- * @param targetPackage the name of the package to overlay
- */
- public Builder(@NonNull String name, @NonNull String targetPackage) {
- mName = OverlayManagerImpl.checkOverlayNameValid(name);
- mTargetPackage =
- Preconditions.checkStringNotEmpty(
- targetPackage, "'targetPackage' must not be empty nor null");
- mOwningPackage = ""; // The package name is filled in OverlayManager.commit
- }
-
- /**
- * Sets the name of the overlayable resources to overlay (can be null).
+ * <p>The target package defines may define several overlayables. The
+ * {@link FabricatedOverlay} should specify which overlayable to be overlaid.
+ *
+ * <p>The target overlayable should be defined in {@code <overlayable>} and pass the value
+ * of its {@code name} attribute as the parameter.
+ *
+ * @param targetOverlayable is a name of the overlayable resources set
+ * @hide
*/
@NonNull
public Builder setTargetOverlayable(@Nullable String targetOverlayable) {
@@ -112,27 +161,6 @@
}
/**
- * Ensure the resource name is in the form [package]:type/entry.
- *
- * @param name name of the target resource to overlay (in the form [package]:type/entry)
- * @return the valid name
- */
- private static String ensureValidResourceName(@NonNull String name) {
- Objects.requireNonNull(name);
- final int slashIndex = name.indexOf('/'); /* must contain '/' */
- final int colonIndex = name.indexOf(':'); /* ':' should before '/' if ':' exist */
-
- // The minimum length of resource type is "id".
- Preconditions.checkArgument(
- slashIndex >= 0 /* It must contain the type name */
- && colonIndex != 0 /* 0 means the package name is empty */
- && (slashIndex - colonIndex) > 2 /* The shortest length of type is "id" */,
- "\"%s\" is invalid resource name",
- name);
- return name;
- }
-
- /**
* Sets the value of the fabricated overlay for the integer-like types.
*
* @param resourceName name of the target resource to overlay (in the form
@@ -141,8 +169,12 @@
* @param value the unsigned 32 bit integer representing the new value
* @return the builder itself
* @see #setResourceValue(String, int, int, String)
- * @see android.util.TypedValue#type
+ * @see android.util.TypedValue#TYPE_INT_COLOR_ARGB8 android.util.TypedValue#type
+ * @deprecated Framework should use {@link FabricatedOverlay#setResourceValue(String, int,
+ int, String)} instead.
+ * @hide
*/
+ @Deprecated(since = "Please use FabricatedOverlay#setResourceValue instead")
@NonNull
public Builder setResourceValue(
@NonNull String resourceName,
@@ -161,8 +193,13 @@
* @param dataType the data type of the new value
* @param value the unsigned 32 bit integer representing the new value
* @param configuration The string representation of the config this overlay is enabled for
- * @see android.util.TypedValue#type
+ * @return the builder itself
+ * @see android.util.TypedValue#TYPE_INT_COLOR_ARGB8 android.util.TypedValue#type
+ * @deprecated Framework should use {@link FabricatedOverlay#setResourceValue(String, int,
+ int, String)} instead.
+ * @hide
*/
+ @Deprecated(since = "Please use FabricatedOverlay#setResourceValue instead")
@NonNull
public Builder setResourceValue(
@NonNull String resourceName,
@@ -171,30 +208,11 @@
int value,
@Nullable String configuration) {
ensureValidResourceName(resourceName);
-
- final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry();
- entry.resourceName = resourceName;
- entry.dataType =
- Preconditions.checkArgumentInRange(
- dataType,
- TypedValue.TYPE_FIRST_INT,
- TypedValue.TYPE_LAST_INT,
- "dataType");
- entry.data = value;
- entry.configuration = configuration;
- mEntries.add(entry);
+ mEntries.add(generateFabricatedOverlayInternalEntry(resourceName, dataType, value,
+ configuration));
return this;
}
- /** @hide */
- @IntDef(
- prefix = {"OVERLAY_TYPE"},
- value = {
- TypedValue.TYPE_STRING,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface StringTypeOverlayResource {}
-
/**
* Sets the value of the fabricated overlay for the string-like type.
*
@@ -203,8 +221,12 @@
* @param dataType the data type of the new value
* @param value the string representing the new value
* @return the builder itself
- * @see android.util.TypedValue#type
+ * @see android.util.TypedValue#TYPE_STRING android.util.TypedValue#type
+ * @deprecated Framework should use {@link FabricatedOverlay#setResourceValue(String, int,
+ String, String)} instead.
+ * @hide
*/
+ @Deprecated(since = "Please use FabricatedOverlay#setResourceValue instead")
@NonNull
public Builder setResourceValue(
@NonNull String resourceName,
@@ -221,8 +243,13 @@
* @param dataType the data type of the new value
* @param value the string representing the new value
* @param configuration The string representation of the config this overlay is enabled for
- * @see android.util.TypedValue#type
+ * @return the builder itself
+ * @see android.util.TypedValue#TYPE_STRING android.util.TypedValue#type
+ * @deprecated Framework should use {@link FabricatedOverlay#setResourceValue(String, int,
+ String, String)} instead.
+ * @hide
*/
+ @Deprecated(since = "Please use FabricatedOverlay#setResourceValue instead")
@NonNull
public Builder setResourceValue(
@NonNull String resourceName,
@@ -230,39 +257,32 @@
@NonNull String value,
@Nullable String configuration) {
ensureValidResourceName(resourceName);
-
- final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry();
- entry.resourceName = resourceName;
- entry.dataType =
- Preconditions.checkArgumentInRange(
- dataType, TypedValue.TYPE_STRING, TypedValue.TYPE_FRACTION, "dataType");
- entry.stringData = Objects.requireNonNull(value);
- entry.configuration = configuration;
- mEntries.add(entry);
+ mEntries.add(generateFabricatedOverlayInternalEntry(resourceName, dataType, value,
+ configuration));
return this;
}
/**
- * Sets the value of the fabricated overlay
+ * Sets the value of the fabricated overlay for the file descriptor type.
*
* @param resourceName name of the target resource to overlay (in the form
* [package]:type/entry)
* @param value the file descriptor whose contents are the value of the frro
* @param configuration The string representation of the config this overlay is enabled for
* @return the builder itself
+ * @deprecated Framework should use {@link FabricatedOverlay#setResourceValue(String,
+ ParcelFileDescriptor, String)} instead.
+ * @hide
*/
+ @Deprecated(since = "Please use FabricatedOverlay#setResourceValue instead")
@NonNull
public Builder setResourceValue(
@NonNull String resourceName,
@NonNull ParcelFileDescriptor value,
@Nullable String configuration) {
ensureValidResourceName(resourceName);
-
- final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry();
- entry.resourceName = resourceName;
- entry.binaryData = Objects.requireNonNull(value);
- entry.configuration = configuration;
- mEntries.add(entry);
+ mEntries.add(
+ generateFabricatedOverlayInternalEntry(resourceName, value, configuration));
return this;
}
@@ -270,22 +290,216 @@
* Builds an immutable fabricated overlay.
*
* @return the fabricated overlay
+ * @hide
*/
@NonNull
public FabricatedOverlay build() {
- final FabricatedOverlayInternal overlay = new FabricatedOverlayInternal();
- overlay.packageName = mOwningPackage;
- overlay.overlayName = mName;
- overlay.targetPackageName = mTargetPackage;
- overlay.targetOverlayable = mTargetOverlayable;
- overlay.entries = new ArrayList<>();
- overlay.entries.addAll(mEntries);
- return new FabricatedOverlay(overlay);
+ return new FabricatedOverlay(
+ generateFabricatedOverlayInternal(mOwningPackage, mName, mTargetPackage,
+ mTargetOverlayable, mEntries));
}
}
+ private static FabricatedOverlayInternal generateFabricatedOverlayInternal(
+ @NonNull String owningPackage, @NonNull String overlayName,
+ @NonNull String targetPackageName, @Nullable String targetOverlayable,
+ @NonNull ArrayList<FabricatedOverlayInternalEntry> entries) {
+ final FabricatedOverlayInternal overlay = new FabricatedOverlayInternal();
+ overlay.packageName = owningPackage;
+ overlay.overlayName = overlayName;
+ overlay.targetPackageName = targetPackageName;
+ overlay.targetOverlayable = TextUtils.emptyIfNull(targetOverlayable);
+ overlay.entries = new ArrayList<>();
+ overlay.entries.addAll(entries);
+ return overlay;
+ }
+
final FabricatedOverlayInternal mOverlay;
private FabricatedOverlay(FabricatedOverlayInternal overlay) {
mOverlay = overlay;
}
+
+ /**
+ * Create a fabricated overlay to overlay on the specified package.
+ *
+ * @param overlayName a name used to uniquely identify the fabricated overlay owned by the
+ * caller itself.
+ * @param targetPackage the name of the package to be overlaid
+ * @hide
+ */
+ public FabricatedOverlay(@NonNull String overlayName, @NonNull String targetPackage) {
+ this(generateFabricatedOverlayInternal(
+ "" /* owningPackage, The package name is filled commitment */,
+ OverlayManagerImpl.checkOverlayNameValid(overlayName),
+ Preconditions.checkStringNotEmpty(targetPackage,
+ "'targetPackage' must not be empty nor null"),
+ null /* targetOverlayable */,
+ new ArrayList<>()));
+ }
+
+ /**
+ * Set the target overlayable name of the overlay
+ *
+ * The target package defines may define several overlayables. The {@link FabricatedOverlay}
+ * should specify which overlayable to be overlaid.
+ *
+ * @param targetOverlayable the overlayable name defined in target package.
+ * @hide
+ */
+ public void setTargetOverlayable(@Nullable String targetOverlayable) {
+ mOverlay.targetOverlayable = TextUtils.emptyIfNull(targetOverlayable);
+ }
+
+ /**
+ * Return the target overlayable name of the overlay
+ *
+ * The target package defines may define several overlayables. The {@link FabricatedOverlay}
+ * should specify which overlayable to be overlaid.
+ *
+ * @return the target overlayable name.
+ * @hide
+ */
+ @Nullable
+ public String getTargetOverlayable() {
+ return mOverlay.targetOverlayable;
+ }
+
+ /**
+ * Ensure the resource name is in the form [package]:type/entry.
+ *
+ * @param name name of the target resource to overlay (in the form [package]:type/entry)
+ * @return the valid name
+ */
+ private static String ensureValidResourceName(@NonNull String name) {
+ Objects.requireNonNull(name);
+ final int slashIndex = name.indexOf('/'); /* must contain '/' */
+ final int colonIndex = name.indexOf(':'); /* ':' should before '/' if ':' exist */
+
+ // The minimum length of resource type is "id".
+ Preconditions.checkArgument(
+ slashIndex >= 0 /* It must contain the type name */
+ && colonIndex != 0 /* 0 means the package name is empty */
+ && (slashIndex - colonIndex) > 2 /* The shortest length of type is "id" */,
+ "\"%s\" is invalid resource name",
+ name);
+ return name;
+ }
+
+ @NonNull
+ private static FabricatedOverlayInternalEntry generateFabricatedOverlayInternalEntry(
+ @NonNull String resourceName,
+ @IntRange(from = TypedValue.TYPE_FIRST_INT, to = TypedValue.TYPE_LAST_INT) int dataType,
+ int value, @Nullable String configuration) {
+ final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry();
+ entry.resourceName = resourceName;
+ entry.dataType =
+ Preconditions.checkArgumentInRange(
+ dataType,
+ TypedValue.TYPE_FIRST_INT,
+ TypedValue.TYPE_LAST_INT,
+ "dataType");
+ entry.data = value;
+ entry.configuration = configuration;
+ return entry;
+ }
+
+ @NonNull
+ private static FabricatedOverlayInternalEntry generateFabricatedOverlayInternalEntry(
+ @NonNull String resourceName, @StringTypeOverlayResource int dataType,
+ @NonNull String value, @Nullable String configuration) {
+ final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry();
+ entry.resourceName = resourceName;
+ entry.dataType =
+ Preconditions.checkArgumentInRange(
+ dataType, TypedValue.TYPE_STRING, TypedValue.TYPE_FRACTION, "dataType");
+ entry.stringData = Objects.requireNonNull(value);
+ entry.configuration = configuration;
+ return entry;
+ }
+
+ @NonNull
+ private static FabricatedOverlayInternalEntry generateFabricatedOverlayInternalEntry(
+ @NonNull String resourceName, @NonNull ParcelFileDescriptor parcelFileDescriptor,
+ @Nullable String configuration) {
+ final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry();
+ entry.resourceName = resourceName;
+ entry.binaryData = Objects.requireNonNull(parcelFileDescriptor);
+ entry.configuration = configuration;
+ return entry;
+ }
+
+ /**
+ * Sets the resource value in the fabricated overlay for the integer-like types with the
+ * configuration.
+ *
+ * @param resourceName name of the target resource to overlay (in the form
+ * [package]:type/entry)
+ * @param dataType the data type of the new value
+ * @param value the integer representing the new value
+ * @param configuration The string representation of the config this overlay is enabled for
+ * @see android.util.TypedValue#TYPE_INT_COLOR_ARGB8 android.util.TypedValue#type
+ * @hide
+ */
+ @NonNull
+ public void setResourceValue(
+ @NonNull String resourceName,
+ @IntRange(from = TypedValue.TYPE_FIRST_INT, to = TypedValue.TYPE_LAST_INT) int dataType,
+ int value,
+ @Nullable String configuration) {
+ ensureValidResourceName(resourceName);
+ mOverlay.entries.add(generateFabricatedOverlayInternalEntry(resourceName, dataType, value,
+ configuration));
+ }
+
+ /** @hide */
+ @IntDef(
+ prefix = {"OVERLAY_TYPE"},
+ value = {
+ TypedValue.TYPE_STRING,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface StringTypeOverlayResource {}
+
+ /**
+ * Sets the resource value in the fabricated overlay for the string-like type with the
+ * configuration.
+ *
+ * @param resourceName name of the target resource to overlay (in the form
+ * [package]:type/entry)
+ * @param dataType the data type of the new value
+ * @param value the string representing the new value
+ * @param configuration The string representation of the config this overlay is enabled for
+ * @see android.util.TypedValue#TYPE_STRING android.util.TypedValue#type
+ * @hide
+ */
+ @NonNull
+ public void setResourceValue(
+ @NonNull String resourceName,
+ @StringTypeOverlayResource int dataType,
+ @NonNull String value,
+ @Nullable String configuration) {
+ ensureValidResourceName(resourceName);
+ mOverlay.entries.add(generateFabricatedOverlayInternalEntry(resourceName, dataType, value,
+ configuration));
+ }
+
+ /**
+ * Sets the resource value in the fabricated overlay for the file descriptor type with the
+ * configuration.
+ *
+ * @param resourceName name of the target resource to overlay (in the form
+ * [package]:type/entry)
+ * @param value the file descriptor whose contents are the value of the frro
+ * @param configuration The string representation of the config this overlay is enabled for
+ * @hide
+ */
+ @NonNull
+ public void setResourceValue(
+ @NonNull String resourceName,
+ @NonNull ParcelFileDescriptor value,
+ @Nullable String configuration) {
+ ensureValidResourceName(resourceName);
+ mOverlay.entries.add(
+ generateFabricatedOverlayInternalEntry(resourceName, value, configuration));
+ }
}