• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.content.om;
18 
19 import android.annotation.FlaggedApi;
20 import android.annotation.IntDef;
21 import android.annotation.IntRange;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.content.res.AssetFileDescriptor;
25 import android.os.FabricatedOverlayInternal;
26 import android.os.FabricatedOverlayInternalEntry;
27 import android.os.ParcelFileDescriptor;
28 import android.text.TextUtils;
29 import android.util.TypedValue;
30 
31 import com.android.internal.content.om.OverlayManagerImpl;
32 import com.android.internal.util.Preconditions;
33 
34 import java.lang.annotation.Retention;
35 import java.lang.annotation.RetentionPolicy;
36 import java.util.ArrayList;
37 import java.util.Objects;
38 
39 /**
40  * FabricatedOverlay describes the content of Fabricated Runtime Resource Overlay (FRRO) that is
41  * used to overlay the app's resources. The app should register the {@link FabricatedOverlay}
42  * instance in an {@link OverlayManagerTransaction} by calling {@link
43  * OverlayManagerTransaction#registerFabricatedOverlay(FabricatedOverlay)}. The FRRO is
44  * created once the transaction is committed successfully.
45  *
46  * <p>The app creates a FabricatedOverlay to describe the how to overlay string, integer, and file
47  * type resources. Before creating any frro, please define a target overlayable in {@code
48  * res/values/overlayable.xml} that describes what kind of resources can be overlaid, what kind of
49  * roles or applications can overlay the resources. Here is an example.
50  *
51  * <pre>{@code
52  * <overlayable name="SignatureOverlayable" actor="overlay://theme">
53  *     <!-- The app with the same signature can overlay the below resources -->
54  *     <policy type="signature">
55  *         <item type="color" name="mycolor" />
56  *         <item type="string" name="mystring" />
57  *     </policy>
58  * </overlayable>
59  * }</pre>
60  *
61  * <p>The overlay must assign the target overlayable name just like the above example by calling
62  * {@link #setTargetOverlayable(String)}. Here is an example:
63  *
64  * <pre>{@code
65  * FabricatedOverlay fabricatedOverlay = new FabricatedOverlay("overlay_name",
66  *                                                             context.getPackageName());
67  * fabricatedOverlay.setTargetOverlayable("SignatureOverlayable")
68  * fabricatedOverlay.setResourceValue("mycolor", TypedValue.TYPE_INT_COLOR_ARGB8, Color.White)
69  * fabricatedOverlay.setResourceValue("mystring", TypedValue.TYPE_STRING, "Hello")
70  * }</pre>
71  *
72  * <p>The app can create any {@link FabricatedOverlay} instance by calling the following APIs.
73  *
74  * <ul>
75  *   <li>{@link #setTargetOverlayable(String)}
76  *   <li>{@link #setResourceValue(String, int, int, String)}
77  *   <li>{@link #setResourceValue(String, int, String, String)}
78  *   <li>{@link #setResourceValue(String, ParcelFileDescriptor, String)}
79  * </ul>
80  *
81  * @see OverlayManager
82  * @see OverlayManagerTransaction
83  */
84 public class FabricatedOverlay {
85 
86     /**
87      * Retrieves the identifier for this fabricated overlay.
88      * @return the overlay identifier
89      */
90     @NonNull
getIdentifier()91     public OverlayIdentifier getIdentifier() {
92         return new OverlayIdentifier(
93                 mOverlay.packageName, TextUtils.nullIfEmpty(mOverlay.overlayName));
94     }
95 
96     /**
97      * The builder of Fabricated Runtime Resource Overlays(FRROs).
98      *
99      * Fabricated overlays are enabled, disabled, and reordered just like normal overlays. The
100      * overlayable policies a fabricated overlay fulfills are the same policies the creator of the
101      * overlay fulfill. For example, a fabricated overlay created by a platform signed package on
102      * the system partition would fulfil the {@code system} and {@code signature} policies.
103      *
104      * The owner of a fabricated overlay is the UID that created it. Overlays commit to the overlay
105      * manager persist across reboots. When the UID is uninstalled, its fabricated overlays are
106      * wiped.
107      *
108      * Processes with {@code android.Manifest.permission#CHANGE_OVERLAY_PACKAGES} can manage normal
109      * overlays and fabricated overlays.
110      *
111      * @see FabricatedOverlay
112      * @see OverlayManagerTransaction.Builder#registerFabricatedOverlay(FabricatedOverlay)
113      * @hide
114      */
115     public static final class Builder {
116         private final String mOwningPackage;
117         private final String mName;
118         private final String mTargetPackage;
119         private String mTargetOverlayable = "";
120         private final ArrayList<FabricatedOverlayInternalEntry> mEntries = new ArrayList<>();
121 
122         /**
123          * Constructs a build for a fabricated overlay.
124          *
125          * @param owningPackage the name of the package that owns the fabricated overlay (must
126          *                      be a package name of this UID).
127          * @param name a name used to uniquely identify the fabricated overlay owned by
128          *             {@param owningPackageName}
129          * @param targetPackage the name of the package to overlay
130          */
Builder(@onNull String owningPackage, @NonNull String name, @NonNull String targetPackage)131         public Builder(@NonNull String owningPackage, @NonNull String name,
132                 @NonNull String targetPackage) {
133             Preconditions.checkStringNotEmpty(owningPackage,
134                     "'owningPackage' must not be empty nor null");
135             Preconditions.checkStringNotEmpty(name,
136                     "'name'' must not be empty nor null");
137             Preconditions.checkStringNotEmpty(targetPackage,
138                     "'targetPackage' must not be empty nor null");
139 
140             mOwningPackage = owningPackage;
141             mName = name;
142             mTargetPackage = targetPackage;
143         }
144 
145         /**
146          * Sets the name of the target overlayable to be overlaid.
147          *
148          * <p>The target package defines may define several overlayables. The
149          * {@link FabricatedOverlay} should specify which overlayable to be overlaid.
150          *
151          * <p>The target overlayable should be defined in {@code <overlayable>} and pass the value
152          * of its {@code name} attribute as the parameter.
153          *
154          * @param targetOverlayable is a name of the overlayable resources set
155          * @hide
156          */
157         @NonNull
setTargetOverlayable(@ullable String targetOverlayable)158         public Builder setTargetOverlayable(@Nullable String targetOverlayable) {
159             mTargetOverlayable = TextUtils.emptyIfNull(targetOverlayable);
160             return this;
161         }
162 
163         /**
164          * Sets the value of the fabricated overlay for the integer-like types.
165          *
166          * @param resourceName name of the target resource to overlay (in the form
167          *     [package]:type/entry)
168          * @param dataType the data type of the new value
169          * @param value the unsigned 32 bit integer representing the new value
170          * @return the builder itself
171          * @see #setResourceValue(String, int, int, String)
172          * @see android.util.TypedValue#TYPE_INT_COLOR_ARGB8 android.util.TypedValue#type
173          * @deprecated Framework should use {@link FabricatedOverlay#setResourceValue(String, int,
174                        int, String)} instead.
175          * @hide
176          */
177         @Deprecated(since = "Please use FabricatedOverlay#setResourceValue instead")
178         @NonNull
setResourceValue( @onNull String resourceName, @IntRange(from = TypedValue.TYPE_FIRST_INT, to = TypedValue.TYPE_LAST_INT) int dataType, int value)179         public Builder setResourceValue(
180                 @NonNull String resourceName,
181                 @IntRange(from = TypedValue.TYPE_FIRST_INT, to = TypedValue.TYPE_LAST_INT)
182                         int dataType,
183                 int value) {
184             return setResourceValue(resourceName, dataType, value, null /* configuration */);
185         }
186 
187         /**
188          * Sets the value of the fabricated overlay for the integer-like types with the
189          * configuration.
190          *
191          * @param resourceName name of the target resource to overlay (in the form
192          *     [package]:type/entry)
193          * @param dataType the data type of the new value
194          * @param value the unsigned 32 bit integer representing the new value
195          * @param configuration The string representation of the config this overlay is enabled for
196          * @return the builder itself
197          * @see android.util.TypedValue#TYPE_INT_COLOR_ARGB8 android.util.TypedValue#type
198          * @deprecated Framework should use {@link FabricatedOverlay#setResourceValue(String, int,
199                        int, String)} instead.
200          * @hide
201          */
202         @Deprecated(since = "Please use FabricatedOverlay#setResourceValue instead")
203         @NonNull
setResourceValue( @onNull String resourceName, @IntRange(from = TypedValue.TYPE_FIRST_INT, to = TypedValue.TYPE_LAST_INT) int dataType, int value, @Nullable String configuration)204         public Builder setResourceValue(
205                 @NonNull String resourceName,
206                 @IntRange(from = TypedValue.TYPE_FIRST_INT, to = TypedValue.TYPE_LAST_INT)
207                         int dataType,
208                 int value,
209                 @Nullable String configuration) {
210             ensureValidResourceName(resourceName);
211             mEntries.add(generateFabricatedOverlayInternalEntry(resourceName, dataType, value,
212                     configuration));
213             return this;
214         }
215 
216         /**
217          * Sets the value of the fabricated overlay for the string-like type.
218          *
219          * @param resourceName name of the target resource to overlay (in the form
220          *     [package]:type/entry)
221          * @param dataType the data type of the new value
222          * @param value the string representing the new value
223          * @return the builder itself
224          * @see android.util.TypedValue#TYPE_STRING android.util.TypedValue#type
225          * @deprecated Framework should use {@link FabricatedOverlay#setResourceValue(String, int,
226                        String, String)} instead.
227          * @hide
228          */
229         @Deprecated(since = "Please use FabricatedOverlay#setResourceValue instead")
230         @NonNull
setResourceValue( @onNull String resourceName, @StringTypeOverlayResource int dataType, @NonNull String value)231         public Builder setResourceValue(
232                 @NonNull String resourceName,
233                 @StringTypeOverlayResource int dataType,
234                 @NonNull String value) {
235             return setResourceValue(resourceName, dataType, value, null /* configuration */);
236         }
237 
238         /**
239          * Sets the value of the fabricated overlay for the string-like type with the configuration.
240          *
241          * @param resourceName name of the target resource to overlay (in the form
242          *     [package]:type/entry)
243          * @param dataType the data type of the new value
244          * @param value the string representing the new value
245          * @param configuration The string representation of the config this overlay is enabled for
246          * @return the builder itself
247          * @see android.util.TypedValue#TYPE_STRING android.util.TypedValue#type
248          * @deprecated Framework should use {@link FabricatedOverlay#setResourceValue(String, int,
249                        String, String)} instead.
250          * @hide
251          */
252         @Deprecated(since = "Please use FabricatedOverlay#setResourceValue instead")
253         @NonNull
setResourceValue( @onNull String resourceName, @StringTypeOverlayResource int dataType, @NonNull String value, @Nullable String configuration)254         public Builder setResourceValue(
255                 @NonNull String resourceName,
256                 @StringTypeOverlayResource int dataType,
257                 @NonNull String value,
258                 @Nullable String configuration) {
259             ensureValidResourceName(resourceName);
260             mEntries.add(generateFabricatedOverlayInternalEntry(resourceName, dataType, value,
261                     configuration));
262             return this;
263         }
264 
265         /**
266          * Sets the value of the fabricated overlay for the file descriptor type.
267          *
268          * @param resourceName name of the target resource to overlay (in the form
269          *     [package]:type/entry)
270          * @param value the file descriptor whose contents are the value of the frro
271          * @param configuration The string representation of the config this overlay is enabled for
272          * @return the builder itself
273          * @deprecated Framework should use {@link FabricatedOverlay#setResourceValue(String,
274                 ParcelFileDescriptor, String)} instead.
275          * @hide
276          */
277         @Deprecated(since = "Please use FabricatedOverlay#setResourceValue instead")
278         @NonNull
setResourceValue( @onNull String resourceName, @NonNull ParcelFileDescriptor value, @Nullable String configuration)279         public Builder setResourceValue(
280                 @NonNull String resourceName,
281                 @NonNull ParcelFileDescriptor value,
282                 @Nullable String configuration) {
283             ensureValidResourceName(resourceName);
284             mEntries.add(generateFabricatedOverlayInternalEntry(
285                     resourceName, value, configuration, false));
286             return this;
287         }
288 
289         /**
290          * Sets the value of the fabricated overlay for the file descriptor type.
291          *
292          * @param resourceName name of the target resource to overlay (in the form
293          *     [package]:type/entry)
294          * @param value the file descriptor whose contents are the value of the frro
295          * @param configuration The string representation of the config this overlay is enabled for
296          * @return the builder itself
297          * @deprecated Framework should use {@link FabricatedOverlay#setResourceValue(String,
298                 ParcelFileDescriptor, String)} instead.
299          * @hide
300          */
301         @Deprecated(since = "Please use FabricatedOverlay#setResourceValue instead")
302         @NonNull
setResourceValue( @onNull String resourceName, @NonNull AssetFileDescriptor value, @Nullable String configuration)303         public Builder setResourceValue(
304                 @NonNull String resourceName,
305                 @NonNull AssetFileDescriptor value,
306                 @Nullable String configuration) {
307             ensureValidResourceName(resourceName);
308             mEntries.add(
309                     generateFabricatedOverlayInternalEntry(resourceName, value, configuration));
310             return this;
311         }
312 
313         /**
314          * Builds an immutable fabricated overlay.
315          *
316          * @return the fabricated overlay
317          * @hide
318          */
319         @NonNull
build()320         public FabricatedOverlay build() {
321             return new FabricatedOverlay(
322                     generateFabricatedOverlayInternal(mOwningPackage, mName, mTargetPackage,
323                             mTargetOverlayable, mEntries));
324         }
325     }
326 
generateFabricatedOverlayInternal( @onNull String owningPackage, @NonNull String overlayName, @NonNull String targetPackageName, @Nullable String targetOverlayable, @NonNull ArrayList<FabricatedOverlayInternalEntry> entries)327     private static FabricatedOverlayInternal generateFabricatedOverlayInternal(
328             @NonNull String owningPackage, @NonNull String overlayName,
329             @NonNull String targetPackageName, @Nullable String targetOverlayable,
330             @NonNull ArrayList<FabricatedOverlayInternalEntry> entries) {
331         final FabricatedOverlayInternal overlay = new FabricatedOverlayInternal();
332         overlay.packageName = owningPackage;
333         overlay.overlayName = overlayName;
334         overlay.targetPackageName = targetPackageName;
335         overlay.targetOverlayable = TextUtils.emptyIfNull(targetOverlayable);
336         overlay.entries = new ArrayList<>();
337         overlay.entries.addAll(entries);
338         return overlay;
339     }
340 
341     final FabricatedOverlayInternal mOverlay;
FabricatedOverlay(FabricatedOverlayInternal overlay)342     private FabricatedOverlay(FabricatedOverlayInternal overlay) {
343         mOverlay = overlay;
344     }
345 
346     /**
347      * Create a fabricated overlay to overlay on the specified package.
348      *
349      * @param overlayName a name used to uniquely identify the fabricated overlay owned by the
350      *                   caller itself.
351      * @param targetPackage the name of the package to be overlaid
352      */
FabricatedOverlay(@onNull String overlayName, @NonNull String targetPackage)353     public FabricatedOverlay(@NonNull String overlayName, @NonNull String targetPackage) {
354         this(generateFabricatedOverlayInternal(
355                 "" /* owningPackage, The package name is filled commitment */,
356                 OverlayManagerImpl.checkOverlayNameValid(overlayName),
357                 Preconditions.checkStringNotEmpty(targetPackage,
358                         "'targetPackage' must not be empty nor null"),
359                 null /* targetOverlayable */,
360                 new ArrayList<>()));
361     }
362 
363     /**
364      * Set the package that owns the overlay
365      *
366      * @param owningPackage the package that should own the overlay.
367      * @hide
368      */
setOwningPackage(@onNull String owningPackage)369     public void setOwningPackage(@NonNull String owningPackage) {
370         mOverlay.packageName = owningPackage;
371     }
372 
373     /**
374      * Set the target overlayable name of the overlay
375      *
376      * The target package defines may define several overlayables. The {@link FabricatedOverlay}
377      * should specify which overlayable to be overlaid.
378      *
379      * @param targetOverlayable the overlayable name defined in target package.
380      */
setTargetOverlayable(@ullable String targetOverlayable)381     public void setTargetOverlayable(@Nullable String targetOverlayable) {
382         mOverlay.targetOverlayable = TextUtils.emptyIfNull(targetOverlayable);
383     }
384 
385     /**
386      * Return the target overlayable name of the overlay
387      *
388      * The target package defines may define several overlayables. The {@link FabricatedOverlay}
389      * should specify which overlayable to be overlaid.
390      *
391      * @return the target overlayable name.
392      * @hide
393      */
394     @Nullable
getTargetOverlayable()395     public String getTargetOverlayable() {
396         return mOverlay.targetOverlayable;
397     }
398 
399     /**
400      * Ensure the resource name is in the form [package]:type/entry.
401      *
402      * @param name name of the target resource to overlay (in the form [package]:type/entry)
403      * @return the valid name
404      */
ensureValidResourceName(@onNull String name)405     private static String ensureValidResourceName(@NonNull String name) {
406         Objects.requireNonNull(name);
407         final int slashIndex = name.indexOf('/'); /* must contain '/' */
408         final int colonIndex = name.indexOf(':'); /* ':' should before '/' if ':' exist */
409 
410         // The minimum length of resource type is "id".
411         Preconditions.checkArgument(
412                 slashIndex >= 0 /* It must contain the type name */
413                         && colonIndex != 0 /* 0 means the package name is empty */
414                         && (slashIndex - colonIndex) > 2 /* The shortest length of type is "id" */,
415                 "\"%s\" is invalid resource name",
416                 name);
417         return name;
418     }
419 
420     @NonNull
generateFabricatedOverlayInternalEntry( @onNull String resourceName, @IntRange(from = TypedValue.TYPE_FIRST_INT, to = TypedValue.TYPE_LAST_INT) int dataType, int value, @Nullable String configuration)421     private static FabricatedOverlayInternalEntry generateFabricatedOverlayInternalEntry(
422             @NonNull String resourceName,
423             @IntRange(from = TypedValue.TYPE_FIRST_INT, to = TypedValue.TYPE_LAST_INT) int dataType,
424             int value, @Nullable String configuration) {
425         final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry();
426         entry.resourceName = resourceName;
427         entry.dataType =
428                 Preconditions.checkArgumentInRange(
429                         dataType,
430                         TypedValue.TYPE_FIRST_INT,
431                         TypedValue.TYPE_LAST_INT,
432                         "dataType");
433         entry.data = value;
434         entry.configuration = configuration;
435         return entry;
436     }
437 
438     @NonNull
generateFabricatedOverlayInternalEntry( @onNull String resourceName, @StringTypeOverlayResource int dataType, @NonNull String value, @Nullable String configuration)439     private static FabricatedOverlayInternalEntry generateFabricatedOverlayInternalEntry(
440             @NonNull String resourceName, @StringTypeOverlayResource int dataType,
441             @NonNull String value, @Nullable String configuration) {
442         final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry();
443         entry.resourceName = resourceName;
444         entry.dataType =
445                 Preconditions.checkArgumentInRange(
446                         dataType, TypedValue.TYPE_STRING, TypedValue.TYPE_FRACTION, "dataType");
447         entry.stringData = Objects.requireNonNull(value);
448         entry.configuration = configuration;
449         return entry;
450     }
451 
452     @NonNull
generateFabricatedOverlayInternalEntry( @onNull String resourceName, @NonNull ParcelFileDescriptor parcelFileDescriptor, @Nullable String configuration, boolean isNinePatch)453     private static FabricatedOverlayInternalEntry generateFabricatedOverlayInternalEntry(
454             @NonNull String resourceName, @NonNull ParcelFileDescriptor parcelFileDescriptor,
455             @Nullable String configuration, boolean isNinePatch) {
456         final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry();
457         entry.resourceName = resourceName;
458         entry.binaryData = Objects.requireNonNull(parcelFileDescriptor);
459         entry.configuration = configuration;
460         entry.binaryDataOffset = 0;
461         entry.binaryDataSize = parcelFileDescriptor.getStatSize();
462         entry.isNinePatch = isNinePatch;
463         return entry;
464     }
465 
466     @NonNull
generateFabricatedOverlayInternalEntry( @onNull String resourceName, @NonNull AssetFileDescriptor assetFileDescriptor, @Nullable String configuration)467     private static FabricatedOverlayInternalEntry generateFabricatedOverlayInternalEntry(
468             @NonNull String resourceName, @NonNull AssetFileDescriptor assetFileDescriptor,
469             @Nullable String configuration) {
470         final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry();
471         entry.resourceName = resourceName;
472         entry.binaryData = Objects.requireNonNull(assetFileDescriptor.getParcelFileDescriptor());
473         entry.binaryDataOffset = assetFileDescriptor.getStartOffset();
474         entry.binaryDataSize = assetFileDescriptor.getLength();
475         entry.configuration = configuration;
476         return entry;
477     }
478 
479     @NonNull
generateFabricatedOverlayInternalEntry( @onNull String resourceName, float dimensionValue, @TypedValue.ComplexDimensionUnit int dimensionUnit, @Nullable String configuration)480     private static FabricatedOverlayInternalEntry generateFabricatedOverlayInternalEntry(
481             @NonNull String resourceName, float dimensionValue,
482             @TypedValue.ComplexDimensionUnit int dimensionUnit, @Nullable String configuration) {
483         final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry();
484         entry.resourceName = resourceName;
485         entry.dataType = TypedValue.TYPE_DIMENSION;
486         Preconditions.checkArgumentInRange(dimensionUnit,
487                 TypedValue.COMPLEX_UNIT_PX, TypedValue.COMPLEX_UNIT_MM, "dimensionUnit");
488         entry.data = TypedValue.createComplexDimension(dimensionValue, dimensionUnit);
489         entry.configuration = configuration;
490         return entry;
491     }
492 
493     @NonNull
generateFabricatedOverlayInternalEntry( @onNull String resourceName, float value, @Nullable String configuration)494     private static FabricatedOverlayInternalEntry generateFabricatedOverlayInternalEntry(
495             @NonNull String resourceName, float value, @Nullable String configuration) {
496         final FabricatedOverlayInternalEntry entry = new FabricatedOverlayInternalEntry();
497         entry.resourceName = resourceName;
498         entry.dataType = TypedValue.TYPE_FLOAT;
499         entry.data = Float.floatToIntBits(value);
500         entry.configuration = configuration;
501         return entry;
502     }
503 
504     /**
505      * Sets the resource value in the fabricated overlay for the integer-like types with the
506      * configuration.
507      *
508      * @param resourceName name of the target resource to overlay (in the form
509      *     [package]:type/entry)
510      * @param dataType the data type of the new value
511      * @param value the integer representing the new value
512      * @param configuration The string representation of the config this overlay is enabled for
513      * @see android.util.TypedValue#TYPE_INT_COLOR_ARGB8 android.util.TypedValue#type
514      */
515     @NonNull
setResourceValue( @onNull String resourceName, @IntRange(from = TypedValue.TYPE_FIRST_INT, to = TypedValue.TYPE_LAST_INT) int dataType, int value, @Nullable String configuration)516     public void setResourceValue(
517             @NonNull String resourceName,
518             @IntRange(from = TypedValue.TYPE_FIRST_INT, to = TypedValue.TYPE_LAST_INT) int dataType,
519             int value,
520             @Nullable String configuration) {
521         ensureValidResourceName(resourceName);
522         mOverlay.entries.add(generateFabricatedOverlayInternalEntry(resourceName, dataType, value,
523                 configuration));
524     }
525 
526     /** @hide */
527     @IntDef(
528             prefix = {"OVERLAY_TYPE"},
529             value = {
530                     TypedValue.TYPE_STRING,
531             })
532     @Retention(RetentionPolicy.SOURCE)
533     public @interface StringTypeOverlayResource {}
534 
535     /**
536      * Sets the resource value in the fabricated overlay for the string-like type with the
537      * configuration.
538      *
539      * @param resourceName name of the target resource to overlay (in the form
540      *     [package]:type/entry)
541      * @param dataType the data type of the new value
542      * @param value the string representing the new value
543      * @param configuration The string representation of the config this overlay is enabled for
544      * @see android.util.TypedValue#TYPE_STRING android.util.TypedValue#type
545      */
546     @NonNull
setResourceValue( @onNull String resourceName, @StringTypeOverlayResource int dataType, @NonNull String value, @Nullable String configuration)547     public void setResourceValue(
548             @NonNull String resourceName,
549             @StringTypeOverlayResource int dataType,
550             @NonNull String value,
551             @Nullable String configuration) {
552         ensureValidResourceName(resourceName);
553         mOverlay.entries.add(generateFabricatedOverlayInternalEntry(resourceName, dataType, value,
554                 configuration));
555     }
556 
557     /**
558      * Sets the resource value in the fabricated overlay for the file descriptor type with the
559      * configuration.
560      *
561      * @param resourceName name of the target resource to overlay (in the form
562      *     [package]:type/entry)
563      * @param value the file descriptor whose contents are the value of the frro
564      * @param configuration The string representation of the config this overlay is enabled for
565      */
566     @NonNull
setResourceValue( @onNull String resourceName, @NonNull ParcelFileDescriptor value, @Nullable String configuration)567     public void setResourceValue(
568             @NonNull String resourceName,
569             @NonNull ParcelFileDescriptor value,
570             @Nullable String configuration) {
571         ensureValidResourceName(resourceName);
572         mOverlay.entries.add(
573                 generateFabricatedOverlayInternalEntry(resourceName, value, configuration, false));
574     }
575 
576     /**
577      * Sets the resource value in the fabricated overlay from a nine patch.
578      *
579      * @param resourceName name of the target resource to overlay (in the form
580      *     [package]:type/entry)
581      * @param value the file descriptor whose contents are the value of the frro
582      * @param configuration The string representation of the config this overlay is enabled for
583      */
584     @NonNull
585     @FlaggedApi(android.content.res.Flags.FLAG_NINE_PATCH_FRRO)
setNinePatchResourceValue( @onNull String resourceName, @NonNull ParcelFileDescriptor value, @Nullable String configuration)586     public void setNinePatchResourceValue(
587             @NonNull String resourceName,
588             @NonNull ParcelFileDescriptor value,
589             @Nullable String configuration) {
590         ensureValidResourceName(resourceName);
591         mOverlay.entries.add(
592                 generateFabricatedOverlayInternalEntry(resourceName, value, configuration, true));
593     }
594 
595     /**
596      * Sets the resource value in the fabricated overlay for the file descriptor type with the
597      * configuration.
598      *
599      * @param resourceName name of the target resource to overlay (in the form
600      *     [package]:type/entry)
601      * @param value the file descriptor whose contents are the value of the frro
602      * @param configuration The string representation of the config this overlay is enabled for
603      */
604     @NonNull
605     @FlaggedApi(android.content.res.Flags.FLAG_ASSET_FILE_DESCRIPTOR_FRRO)
setResourceValue( @onNull String resourceName, @NonNull AssetFileDescriptor value, @Nullable String configuration)606     public void setResourceValue(
607             @NonNull String resourceName,
608             @NonNull AssetFileDescriptor value,
609             @Nullable String configuration) {
610         ensureValidResourceName(resourceName);
611         mOverlay.entries.add(
612                 generateFabricatedOverlayInternalEntry(resourceName, value, configuration));
613     }
614 
615     /**
616      * Sets the resource value in the fabricated overlay for the dimension type with the
617      * configuration.
618      *
619      * @param resourceName name of the target resource to overlay (in the form
620      *     [package]:type/entry)
621      * @param dimensionValue the float representing the dimension value
622      * @param dimensionUnit the integer representing the dimension unit
623      * @param configuration The string representation of the config this overlay is enabled for
624      */
625     @FlaggedApi(android.content.res.Flags.FLAG_DIMENSION_FRRO)
setResourceValue( @onNull String resourceName, float dimensionValue, @TypedValue.ComplexDimensionUnit int dimensionUnit, @Nullable String configuration)626     public void setResourceValue(
627             @NonNull String resourceName,
628             float dimensionValue,
629             @TypedValue.ComplexDimensionUnit int dimensionUnit,
630             @Nullable String configuration) {
631         ensureValidResourceName(resourceName);
632         mOverlay.entries.add(generateFabricatedOverlayInternalEntry(resourceName, dimensionValue,
633                 dimensionUnit, configuration));
634     }
635 
636     /**
637      * Sets the resource value in the fabricated overlay for the float type with the
638      * configuration.
639      *
640      * @param resourceName name of the target resource to overlay (in the form
641      *     [package]:type/entry)
642      * @param value the float representing the new value
643      * @param configuration The string representation of the config this overlay is enabled for
644      * @throws IllegalArgumentException If the resource name is invalid
645      */
646     @FlaggedApi(android.content.res.Flags.FLAG_DIMENSION_FRRO)
setResourceValue( @onNull String resourceName, float value, @Nullable String configuration)647     public void setResourceValue(
648             @NonNull String resourceName,
649             float value,
650             @Nullable String configuration) {
651         ensureValidResourceName(resourceName);
652         mOverlay.entries.add(generateFabricatedOverlayInternalEntry(resourceName, value,
653                 configuration));
654     }
655 }
656