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