1 /* 2 * Copyright (C) 2006 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.res; 18 19 import android.annotation.AnyRes; 20 import android.annotation.ArrayRes; 21 import android.annotation.AttrRes; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.StringRes; 25 import android.annotation.StyleRes; 26 import android.content.pm.ActivityInfo; 27 import android.content.res.Configuration.NativeConfig; 28 import android.os.ParcelFileDescriptor; 29 import android.util.ArraySet; 30 import android.util.Log; 31 import android.util.SparseArray; 32 import android.util.TypedValue; 33 34 import com.android.internal.annotations.GuardedBy; 35 import com.android.internal.util.Preconditions; 36 37 import libcore.io.IoUtils; 38 39 import java.io.BufferedReader; 40 import java.io.FileInputStream; 41 import java.io.FileNotFoundException; 42 import java.io.IOException; 43 import java.io.InputStream; 44 import java.io.InputStreamReader; 45 import java.nio.channels.FileLock; 46 import java.util.ArrayList; 47 import java.util.Arrays; 48 import java.util.HashMap; 49 50 /** 51 * Provides access to an application's raw asset files; see {@link Resources} 52 * for the way most applications will want to retrieve their resource data. 53 * This class presents a lower-level API that allows you to open and read raw 54 * files that have been bundled with the application as a simple stream of 55 * bytes. 56 */ 57 public final class AssetManager implements AutoCloseable { 58 private static final String TAG = "AssetManager"; 59 private static final boolean DEBUG_REFS = false; 60 61 private static final String FRAMEWORK_APK_PATH = "/system/framework/framework-res.apk"; 62 63 private static final Object sSync = new Object(); 64 65 private static final ApkAssets[] sEmptyApkAssets = new ApkAssets[0]; 66 67 // Not private for LayoutLib's BridgeAssetManager. 68 @GuardedBy("sSync") static AssetManager sSystem = null; 69 70 @GuardedBy("sSync") private static ApkAssets[] sSystemApkAssets = new ApkAssets[0]; 71 @GuardedBy("sSync") private static ArraySet<ApkAssets> sSystemApkAssetsSet; 72 73 /** 74 * Mode for {@link #open(String, int)}: no specific information about how 75 * data will be accessed. 76 */ 77 public static final int ACCESS_UNKNOWN = 0; 78 /** 79 * Mode for {@link #open(String, int)}: Read chunks, and seek forward and 80 * backward. 81 */ 82 public static final int ACCESS_RANDOM = 1; 83 /** 84 * Mode for {@link #open(String, int)}: Read sequentially, with an 85 * occasional forward seek. 86 */ 87 public static final int ACCESS_STREAMING = 2; 88 /** 89 * Mode for {@link #open(String, int)}: Attempt to load contents into 90 * memory, for fast small reads. 91 */ 92 public static final int ACCESS_BUFFER = 3; 93 94 @GuardedBy("this") private final TypedValue mValue = new TypedValue(); 95 @GuardedBy("this") private final long[] mOffsets = new long[2]; 96 97 // Pointer to native implementation, stuffed inside a long. 98 @GuardedBy("this") private long mObject; 99 100 // The loaded asset paths. 101 @GuardedBy("this") private ApkAssets[] mApkAssets; 102 103 // Debug/reference counting implementation. 104 @GuardedBy("this") private boolean mOpen = true; 105 @GuardedBy("this") private int mNumRefs = 1; 106 @GuardedBy("this") private HashMap<Long, RuntimeException> mRefStacks; 107 108 /** 109 * A Builder class that helps create an AssetManager with only a single invocation of 110 * {@link AssetManager#setApkAssets(ApkAssets[], boolean)}. Without using this builder, 111 * AssetManager must ensure there are system ApkAssets loaded at all times, which when combined 112 * with the user's call to add additional ApkAssets, results in multiple calls to 113 * {@link AssetManager#setApkAssets(ApkAssets[], boolean)}. 114 * @hide 115 */ 116 public static class Builder { 117 private ArrayList<ApkAssets> mUserApkAssets = new ArrayList<>(); 118 addApkAssets(ApkAssets apkAssets)119 public Builder addApkAssets(ApkAssets apkAssets) { 120 mUserApkAssets.add(apkAssets); 121 return this; 122 } 123 build()124 public AssetManager build() { 125 // Retrieving the system ApkAssets forces their creation as well. 126 final ApkAssets[] systemApkAssets = getSystem().getApkAssets(); 127 128 final int totalApkAssetCount = systemApkAssets.length + mUserApkAssets.size(); 129 final ApkAssets[] apkAssets = new ApkAssets[totalApkAssetCount]; 130 131 System.arraycopy(systemApkAssets, 0, apkAssets, 0, systemApkAssets.length); 132 133 final int userApkAssetCount = mUserApkAssets.size(); 134 for (int i = 0; i < userApkAssetCount; i++) { 135 apkAssets[i + systemApkAssets.length] = mUserApkAssets.get(i); 136 } 137 138 // Calling this constructor prevents creation of system ApkAssets, which we took care 139 // of in this Builder. 140 final AssetManager assetManager = new AssetManager(false /*sentinel*/); 141 assetManager.mApkAssets = apkAssets; 142 AssetManager.nativeSetApkAssets(assetManager.mObject, apkAssets, 143 false /*invalidateCaches*/); 144 return assetManager; 145 } 146 } 147 148 /** 149 * Create a new AssetManager containing only the basic system assets. 150 * Applications will not generally use this method, instead retrieving the 151 * appropriate asset manager with {@link Resources#getAssets}. Not for 152 * use by applications. 153 * @hide 154 */ AssetManager()155 public AssetManager() { 156 final ApkAssets[] assets; 157 synchronized (sSync) { 158 createSystemAssetsInZygoteLocked(); 159 assets = sSystemApkAssets; 160 } 161 162 mObject = nativeCreate(); 163 if (DEBUG_REFS) { 164 mNumRefs = 0; 165 incRefsLocked(hashCode()); 166 } 167 168 // Always set the framework resources. 169 setApkAssets(assets, false /*invalidateCaches*/); 170 } 171 172 /** 173 * Private constructor that doesn't call ensureSystemAssets. 174 * Used for the creation of system assets. 175 */ 176 @SuppressWarnings("unused") AssetManager(boolean sentinel)177 private AssetManager(boolean sentinel) { 178 mObject = nativeCreate(); 179 if (DEBUG_REFS) { 180 mNumRefs = 0; 181 incRefsLocked(hashCode()); 182 } 183 } 184 185 /** 186 * This must be called from Zygote so that system assets are shared by all applications. 187 */ 188 @GuardedBy("sSync") createSystemAssetsInZygoteLocked()189 private static void createSystemAssetsInZygoteLocked() { 190 if (sSystem != null) { 191 return; 192 } 193 194 // Make sure that all IDMAPs are up to date. 195 nativeVerifySystemIdmaps(); 196 197 try { 198 final ArrayList<ApkAssets> apkAssets = new ArrayList<>(); 199 apkAssets.add(ApkAssets.loadFromPath(FRAMEWORK_APK_PATH, true /*system*/)); 200 loadStaticRuntimeOverlays(apkAssets); 201 202 sSystemApkAssetsSet = new ArraySet<>(apkAssets); 203 sSystemApkAssets = apkAssets.toArray(new ApkAssets[apkAssets.size()]); 204 sSystem = new AssetManager(true /*sentinel*/); 205 sSystem.setApkAssets(sSystemApkAssets, false /*invalidateCaches*/); 206 } catch (IOException e) { 207 throw new IllegalStateException("Failed to create system AssetManager", e); 208 } 209 } 210 211 /** 212 * Loads the static runtime overlays declared in /data/resource-cache/overlays.list. 213 * Throws an exception if the file is corrupt or if loading the APKs referenced by the file 214 * fails. Returns quietly if the overlays.list file doesn't exist. 215 * @param outApkAssets The list to fill with the loaded ApkAssets. 216 */ loadStaticRuntimeOverlays(ArrayList<ApkAssets> outApkAssets)217 private static void loadStaticRuntimeOverlays(ArrayList<ApkAssets> outApkAssets) 218 throws IOException { 219 final FileInputStream fis; 220 try { 221 fis = new FileInputStream("/data/resource-cache/overlays.list"); 222 } catch (FileNotFoundException e) { 223 // We might not have any overlays, this is fine. We catch here since ApkAssets 224 // loading can also fail with the same exception, which we would want to propagate. 225 Log.i(TAG, "no overlays.list file found"); 226 return; 227 } 228 229 try { 230 // Acquire a lock so that any idmap scanning doesn't impact the current set. 231 // The order of this try-with-resources block matters. We must release the lock, and 232 // then close the file streams when exiting the block. 233 try (final BufferedReader br = new BufferedReader(new InputStreamReader(fis)); 234 final FileLock flock = fis.getChannel().lock(0, Long.MAX_VALUE, true /*shared*/)) { 235 for (String line; (line = br.readLine()) != null; ) { 236 final String idmapPath = line.split(" ")[1]; 237 outApkAssets.add(ApkAssets.loadOverlayFromPath(idmapPath, true /*system*/)); 238 } 239 } 240 } finally { 241 // When BufferedReader is closed above, FileInputStream is closed as well. But let's be 242 // paranoid. 243 IoUtils.closeQuietly(fis); 244 } 245 } 246 247 /** 248 * Return a global shared asset manager that provides access to only 249 * system assets (no application assets). 250 * @hide 251 */ getSystem()252 public static AssetManager getSystem() { 253 synchronized (sSync) { 254 createSystemAssetsInZygoteLocked(); 255 return sSystem; 256 } 257 } 258 259 /** 260 * Close this asset manager. 261 */ 262 @Override close()263 public void close() { 264 synchronized (this) { 265 if (!mOpen) { 266 return; 267 } 268 269 mOpen = false; 270 decRefsLocked(hashCode()); 271 } 272 } 273 274 /** 275 * Changes the asset paths in this AssetManager. This replaces the {@link #addAssetPath(String)} 276 * family of methods. 277 * 278 * @param apkAssets The new set of paths. 279 * @param invalidateCaches Whether to invalidate any caches. This should almost always be true. 280 * Set this to false if you are appending new resources 281 * (not new configurations). 282 * @hide 283 */ setApkAssets(@onNull ApkAssets[] apkAssets, boolean invalidateCaches)284 public void setApkAssets(@NonNull ApkAssets[] apkAssets, boolean invalidateCaches) { 285 Preconditions.checkNotNull(apkAssets, "apkAssets"); 286 287 ApkAssets[] newApkAssets = new ApkAssets[sSystemApkAssets.length + apkAssets.length]; 288 289 // Copy the system assets first. 290 System.arraycopy(sSystemApkAssets, 0, newApkAssets, 0, sSystemApkAssets.length); 291 292 // Copy the given ApkAssets if they are not already in the system list. 293 int newLength = sSystemApkAssets.length; 294 for (ApkAssets apkAsset : apkAssets) { 295 if (!sSystemApkAssetsSet.contains(apkAsset)) { 296 newApkAssets[newLength++] = apkAsset; 297 } 298 } 299 300 // Truncate if necessary. 301 if (newLength != newApkAssets.length) { 302 newApkAssets = Arrays.copyOf(newApkAssets, newLength); 303 } 304 305 synchronized (this) { 306 ensureOpenLocked(); 307 mApkAssets = newApkAssets; 308 nativeSetApkAssets(mObject, mApkAssets, invalidateCaches); 309 if (invalidateCaches) { 310 // Invalidate all caches. 311 invalidateCachesLocked(-1); 312 } 313 } 314 } 315 316 /** 317 * Invalidates the caches in this AssetManager according to the bitmask `diff`. 318 * 319 * @param diff The bitmask of changes generated by {@link Configuration#diff(Configuration)}. 320 * @see ActivityInfo.Config 321 */ invalidateCachesLocked(int diff)322 private void invalidateCachesLocked(int diff) { 323 // TODO(adamlesinski): Currently there are no caches to invalidate in Java code. 324 } 325 326 /** 327 * Returns the set of ApkAssets loaded by this AssetManager. If the AssetManager is closed, this 328 * returns a 0-length array. 329 * @hide 330 */ getApkAssets()331 public @NonNull ApkAssets[] getApkAssets() { 332 synchronized (this) { 333 if (mOpen) { 334 return mApkAssets; 335 } 336 } 337 return sEmptyApkAssets; 338 } 339 340 /** 341 * Returns a cookie for use with the other APIs of AssetManager. 342 * @return 0 if the path was not found, otherwise a positive integer cookie representing 343 * this path in the AssetManager. 344 * @hide 345 */ findCookieForPath(@onNull String path)346 public int findCookieForPath(@NonNull String path) { 347 Preconditions.checkNotNull(path, "path"); 348 synchronized (this) { 349 ensureValidLocked(); 350 final int count = mApkAssets.length; 351 for (int i = 0; i < count; i++) { 352 if (path.equals(mApkAssets[i].getAssetPath())) { 353 return i + 1; 354 } 355 } 356 } 357 return 0; 358 } 359 360 /** 361 * @deprecated Use {@link #setApkAssets(ApkAssets[], boolean)} 362 * @hide 363 */ 364 @Deprecated addAssetPath(String path)365 public int addAssetPath(String path) { 366 return addAssetPathInternal(path, false /*overlay*/, false /*appAsLib*/); 367 } 368 369 /** 370 * @deprecated Use {@link #setApkAssets(ApkAssets[], boolean)} 371 * @hide 372 */ 373 @Deprecated addAssetPathAsSharedLibrary(String path)374 public int addAssetPathAsSharedLibrary(String path) { 375 return addAssetPathInternal(path, false /*overlay*/, true /*appAsLib*/); 376 } 377 378 /** 379 * @deprecated Use {@link #setApkAssets(ApkAssets[], boolean)} 380 * @hide 381 */ 382 @Deprecated addOverlayPath(String path)383 public int addOverlayPath(String path) { 384 return addAssetPathInternal(path, true /*overlay*/, false /*appAsLib*/); 385 } 386 addAssetPathInternal(String path, boolean overlay, boolean appAsLib)387 private int addAssetPathInternal(String path, boolean overlay, boolean appAsLib) { 388 Preconditions.checkNotNull(path, "path"); 389 synchronized (this) { 390 ensureOpenLocked(); 391 final int count = mApkAssets.length; 392 393 // See if we already have it loaded. 394 for (int i = 0; i < count; i++) { 395 if (mApkAssets[i].getAssetPath().equals(path)) { 396 return i + 1; 397 } 398 } 399 400 final ApkAssets assets; 401 try { 402 if (overlay) { 403 // TODO(b/70343104): This hardcoded path will be removed once 404 // addAssetPathInternal is deleted. 405 final String idmapPath = "/data/resource-cache/" 406 + path.substring(1).replace('/', '@') 407 + "@idmap"; 408 assets = ApkAssets.loadOverlayFromPath(idmapPath, false /*system*/); 409 } else { 410 assets = ApkAssets.loadFromPath(path, false /*system*/, appAsLib); 411 } 412 } catch (IOException e) { 413 return 0; 414 } 415 416 mApkAssets = Arrays.copyOf(mApkAssets, count + 1); 417 mApkAssets[count] = assets; 418 nativeSetApkAssets(mObject, mApkAssets, true); 419 invalidateCachesLocked(-1); 420 return count + 1; 421 } 422 } 423 424 /** 425 * Ensures that the native implementation has not been destroyed. 426 * The AssetManager may have been closed, but references to it still exist 427 * and therefore the native implementation is not destroyed. 428 */ 429 @GuardedBy("this") ensureValidLocked()430 private void ensureValidLocked() { 431 if (mObject == 0) { 432 throw new RuntimeException("AssetManager has been destroyed"); 433 } 434 } 435 436 /** 437 * Ensures that the AssetManager has not been explicitly closed. If this method passes, 438 * then this implies that ensureValidLocked() also passes. 439 */ 440 @GuardedBy("this") ensureOpenLocked()441 private void ensureOpenLocked() { 442 // If mOpen is true, this implies that mObject != 0. 443 if (!mOpen) { 444 throw new RuntimeException("AssetManager has been closed"); 445 } 446 } 447 448 /** 449 * Populates {@code outValue} with the data associated a particular 450 * resource identifier for the current configuration. 451 * 452 * @param resId the resource identifier to load 453 * @param densityDpi the density bucket for which to load the resource 454 * @param outValue the typed value in which to put the data 455 * @param resolveRefs {@code true} to resolve references, {@code false} 456 * to leave them unresolved 457 * @return {@code true} if the data was loaded into {@code outValue}, 458 * {@code false} otherwise 459 */ getResourceValue(@nyRes int resId, int densityDpi, @NonNull TypedValue outValue, boolean resolveRefs)460 boolean getResourceValue(@AnyRes int resId, int densityDpi, @NonNull TypedValue outValue, 461 boolean resolveRefs) { 462 Preconditions.checkNotNull(outValue, "outValue"); 463 synchronized (this) { 464 ensureValidLocked(); 465 final int cookie = nativeGetResourceValue( 466 mObject, resId, (short) densityDpi, outValue, resolveRefs); 467 if (cookie <= 0) { 468 return false; 469 } 470 471 // Convert the changing configurations flags populated by native code. 472 outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava( 473 outValue.changingConfigurations); 474 475 if (outValue.type == TypedValue.TYPE_STRING) { 476 outValue.string = mApkAssets[cookie - 1].getStringFromPool(outValue.data); 477 } 478 return true; 479 } 480 } 481 482 /** 483 * Retrieves the string value associated with a particular resource 484 * identifier for the current configuration. 485 * 486 * @param resId the resource identifier to load 487 * @return the string value, or {@code null} 488 */ getResourceText(@tringRes int resId)489 @Nullable CharSequence getResourceText(@StringRes int resId) { 490 synchronized (this) { 491 final TypedValue outValue = mValue; 492 if (getResourceValue(resId, 0, outValue, true)) { 493 return outValue.coerceToString(); 494 } 495 return null; 496 } 497 } 498 499 /** 500 * Retrieves the string value associated with a particular resource 501 * identifier for the current configuration. 502 * 503 * @param resId the resource identifier to load 504 * @param bagEntryId the index into the bag to load 505 * @return the string value, or {@code null} 506 */ getResourceBagText(@tringRes int resId, int bagEntryId)507 @Nullable CharSequence getResourceBagText(@StringRes int resId, int bagEntryId) { 508 synchronized (this) { 509 ensureValidLocked(); 510 final TypedValue outValue = mValue; 511 final int cookie = nativeGetResourceBagValue(mObject, resId, bagEntryId, outValue); 512 if (cookie <= 0) { 513 return null; 514 } 515 516 // Convert the changing configurations flags populated by native code. 517 outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava( 518 outValue.changingConfigurations); 519 520 if (outValue.type == TypedValue.TYPE_STRING) { 521 return mApkAssets[cookie - 1].getStringFromPool(outValue.data); 522 } 523 return outValue.coerceToString(); 524 } 525 } 526 getResourceArraySize(@rrayRes int resId)527 int getResourceArraySize(@ArrayRes int resId) { 528 synchronized (this) { 529 ensureValidLocked(); 530 return nativeGetResourceArraySize(mObject, resId); 531 } 532 } 533 534 /** 535 * Populates `outData` with array elements of `resId`. `outData` is normally 536 * used with 537 * {@link TypedArray}. 538 * 539 * Each logical element in `outData` is {@link TypedArray#STYLE_NUM_ENTRIES} 540 * long, 541 * with the indices of the data representing the type, value, asset cookie, 542 * resource ID, 543 * configuration change mask, and density of the element. 544 * 545 * @param resId The resource ID of an array resource. 546 * @param outData The array to populate with data. 547 * @return The length of the array. 548 * 549 * @see TypedArray#STYLE_TYPE 550 * @see TypedArray#STYLE_DATA 551 * @see TypedArray#STYLE_ASSET_COOKIE 552 * @see TypedArray#STYLE_RESOURCE_ID 553 * @see TypedArray#STYLE_CHANGING_CONFIGURATIONS 554 * @see TypedArray#STYLE_DENSITY 555 */ getResourceArray(@rrayRes int resId, @NonNull int[] outData)556 int getResourceArray(@ArrayRes int resId, @NonNull int[] outData) { 557 Preconditions.checkNotNull(outData, "outData"); 558 synchronized (this) { 559 ensureValidLocked(); 560 return nativeGetResourceArray(mObject, resId, outData); 561 } 562 } 563 564 /** 565 * Retrieves the string array associated with a particular resource 566 * identifier for the current configuration. 567 * 568 * @param resId the resource identifier of the string array 569 * @return the string array, or {@code null} 570 */ getResourceStringArray(@rrayRes int resId)571 @Nullable String[] getResourceStringArray(@ArrayRes int resId) { 572 synchronized (this) { 573 ensureValidLocked(); 574 return nativeGetResourceStringArray(mObject, resId); 575 } 576 } 577 578 /** 579 * Retrieve the text array associated with a particular resource 580 * identifier. 581 * 582 * @param resId the resource id of the string array 583 */ getResourceTextArray(@rrayRes int resId)584 @Nullable CharSequence[] getResourceTextArray(@ArrayRes int resId) { 585 synchronized (this) { 586 ensureValidLocked(); 587 final int[] rawInfoArray = nativeGetResourceStringArrayInfo(mObject, resId); 588 if (rawInfoArray == null) { 589 return null; 590 } 591 592 final int rawInfoArrayLen = rawInfoArray.length; 593 final int infoArrayLen = rawInfoArrayLen / 2; 594 final CharSequence[] retArray = new CharSequence[infoArrayLen]; 595 for (int i = 0, j = 0; i < rawInfoArrayLen; i = i + 2, j++) { 596 int cookie = rawInfoArray[i]; 597 int index = rawInfoArray[i + 1]; 598 retArray[j] = (index >= 0 && cookie > 0) 599 ? mApkAssets[cookie - 1].getStringFromPool(index) : null; 600 } 601 return retArray; 602 } 603 } 604 getResourceIntArray(@rrayRes int resId)605 @Nullable int[] getResourceIntArray(@ArrayRes int resId) { 606 synchronized (this) { 607 ensureValidLocked(); 608 return nativeGetResourceIntArray(mObject, resId); 609 } 610 } 611 612 /** 613 * Get the attributes for a style resource. These are the <item> 614 * elements in 615 * a <style> resource. 616 * @param resId The resource ID of the style 617 * @return An array of attribute IDs. 618 */ getStyleAttributes(@tyleRes int resId)619 @AttrRes int[] getStyleAttributes(@StyleRes int resId) { 620 synchronized (this) { 621 ensureValidLocked(); 622 return nativeGetStyleAttributes(mObject, resId); 623 } 624 } 625 626 /** 627 * Populates {@code outValue} with the data associated with a particular 628 * resource identifier for the current configuration. Resolves theme 629 * attributes against the specified theme. 630 * 631 * @param theme the native pointer of the theme 632 * @param resId the resource identifier to load 633 * @param outValue the typed value in which to put the data 634 * @param resolveRefs {@code true} to resolve references, {@code false} 635 * to leave them unresolved 636 * @return {@code true} if the data was loaded into {@code outValue}, 637 * {@code false} otherwise 638 */ getThemeValue(long theme, @AnyRes int resId, @NonNull TypedValue outValue, boolean resolveRefs)639 boolean getThemeValue(long theme, @AnyRes int resId, @NonNull TypedValue outValue, 640 boolean resolveRefs) { 641 Preconditions.checkNotNull(outValue, "outValue"); 642 synchronized (this) { 643 ensureValidLocked(); 644 final int cookie = nativeThemeGetAttributeValue(mObject, theme, resId, outValue, 645 resolveRefs); 646 if (cookie <= 0) { 647 return false; 648 } 649 650 // Convert the changing configurations flags populated by native code. 651 outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava( 652 outValue.changingConfigurations); 653 654 if (outValue.type == TypedValue.TYPE_STRING) { 655 outValue.string = mApkAssets[cookie - 1].getStringFromPool(outValue.data); 656 } 657 return true; 658 } 659 } 660 dumpTheme(long theme, int priority, String tag, String prefix)661 void dumpTheme(long theme, int priority, String tag, String prefix) { 662 synchronized (this) { 663 ensureValidLocked(); 664 nativeThemeDump(mObject, theme, priority, tag, prefix); 665 } 666 } 667 getResourceName(@nyRes int resId)668 @Nullable String getResourceName(@AnyRes int resId) { 669 synchronized (this) { 670 ensureValidLocked(); 671 return nativeGetResourceName(mObject, resId); 672 } 673 } 674 getResourcePackageName(@nyRes int resId)675 @Nullable String getResourcePackageName(@AnyRes int resId) { 676 synchronized (this) { 677 ensureValidLocked(); 678 return nativeGetResourcePackageName(mObject, resId); 679 } 680 } 681 getResourceTypeName(@nyRes int resId)682 @Nullable String getResourceTypeName(@AnyRes int resId) { 683 synchronized (this) { 684 ensureValidLocked(); 685 return nativeGetResourceTypeName(mObject, resId); 686 } 687 } 688 getResourceEntryName(@nyRes int resId)689 @Nullable String getResourceEntryName(@AnyRes int resId) { 690 synchronized (this) { 691 ensureValidLocked(); 692 return nativeGetResourceEntryName(mObject, resId); 693 } 694 } 695 getResourceIdentifier(@onNull String name, @Nullable String defType, @Nullable String defPackage)696 @AnyRes int getResourceIdentifier(@NonNull String name, @Nullable String defType, 697 @Nullable String defPackage) { 698 synchronized (this) { 699 ensureValidLocked(); 700 // name is checked in JNI. 701 return nativeGetResourceIdentifier(mObject, name, defType, defPackage); 702 } 703 } 704 getPooledStringForCookie(int cookie, int id)705 CharSequence getPooledStringForCookie(int cookie, int id) { 706 // Cookies map to ApkAssets starting at 1. 707 return getApkAssets()[cookie - 1].getStringFromPool(id); 708 } 709 710 /** 711 * Open an asset using ACCESS_STREAMING mode. This provides access to 712 * files that have been bundled with an application as assets -- that is, 713 * files placed in to the "assets" directory. 714 * 715 * @param fileName The name of the asset to open. This name can be hierarchical. 716 * 717 * @see #open(String, int) 718 * @see #list 719 */ open(@onNull String fileName)720 public @NonNull InputStream open(@NonNull String fileName) throws IOException { 721 return open(fileName, ACCESS_STREAMING); 722 } 723 724 /** 725 * Open an asset using an explicit access mode, returning an InputStream to 726 * read its contents. This provides access to files that have been bundled 727 * with an application as assets -- that is, files placed in to the 728 * "assets" directory. 729 * 730 * @param fileName The name of the asset to open. This name can be hierarchical. 731 * @param accessMode Desired access mode for retrieving the data. 732 * 733 * @see #ACCESS_UNKNOWN 734 * @see #ACCESS_STREAMING 735 * @see #ACCESS_RANDOM 736 * @see #ACCESS_BUFFER 737 * @see #open(String) 738 * @see #list 739 */ open(@onNull String fileName, int accessMode)740 public @NonNull InputStream open(@NonNull String fileName, int accessMode) throws IOException { 741 Preconditions.checkNotNull(fileName, "fileName"); 742 synchronized (this) { 743 ensureOpenLocked(); 744 final long asset = nativeOpenAsset(mObject, fileName, accessMode); 745 if (asset == 0) { 746 throw new FileNotFoundException("Asset file: " + fileName); 747 } 748 final AssetInputStream assetInputStream = new AssetInputStream(asset); 749 incRefsLocked(assetInputStream.hashCode()); 750 return assetInputStream; 751 } 752 } 753 754 /** 755 * Open an uncompressed asset by mmapping it and returning an {@link AssetFileDescriptor}. 756 * This provides access to files that have been bundled with an application as assets -- that 757 * is, files placed in to the "assets" directory. 758 * 759 * The asset must be uncompressed, or an exception will be thrown. 760 * 761 * @param fileName The name of the asset to open. This name can be hierarchical. 762 * @return An open AssetFileDescriptor. 763 */ openFd(@onNull String fileName)764 public @NonNull AssetFileDescriptor openFd(@NonNull String fileName) throws IOException { 765 Preconditions.checkNotNull(fileName, "fileName"); 766 synchronized (this) { 767 ensureOpenLocked(); 768 final ParcelFileDescriptor pfd = nativeOpenAssetFd(mObject, fileName, mOffsets); 769 if (pfd == null) { 770 throw new FileNotFoundException("Asset file: " + fileName); 771 } 772 return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]); 773 } 774 } 775 776 /** 777 * Return a String array of all the assets at the given path. 778 * 779 * @param path A relative path within the assets, i.e., "docs/home.html". 780 * 781 * @return String[] Array of strings, one for each asset. These file 782 * names are relative to 'path'. You can open the file by 783 * concatenating 'path' and a name in the returned string (via 784 * File) and passing that to open(). 785 * 786 * @see #open 787 */ list(@onNull String path)788 public @Nullable String[] list(@NonNull String path) throws IOException { 789 Preconditions.checkNotNull(path, "path"); 790 synchronized (this) { 791 ensureValidLocked(); 792 return nativeList(mObject, path); 793 } 794 } 795 796 /** 797 * Open a non-asset file as an asset using ACCESS_STREAMING mode. This 798 * provides direct access to all of the files included in an application 799 * package (not only its assets). Applications should not normally use 800 * this. 801 * 802 * @param fileName Name of the asset to retrieve. 803 * 804 * @see #open(String) 805 * @hide 806 */ openNonAsset(@onNull String fileName)807 public @NonNull InputStream openNonAsset(@NonNull String fileName) throws IOException { 808 return openNonAsset(0, fileName, ACCESS_STREAMING); 809 } 810 811 /** 812 * Open a non-asset file as an asset using a specific access mode. This 813 * provides direct access to all of the files included in an application 814 * package (not only its assets). Applications should not normally use 815 * this. 816 * 817 * @param fileName Name of the asset to retrieve. 818 * @param accessMode Desired access mode for retrieving the data. 819 * 820 * @see #ACCESS_UNKNOWN 821 * @see #ACCESS_STREAMING 822 * @see #ACCESS_RANDOM 823 * @see #ACCESS_BUFFER 824 * @see #open(String, int) 825 * @hide 826 */ openNonAsset(@onNull String fileName, int accessMode)827 public @NonNull InputStream openNonAsset(@NonNull String fileName, int accessMode) 828 throws IOException { 829 return openNonAsset(0, fileName, accessMode); 830 } 831 832 /** 833 * Open a non-asset in a specified package. Not for use by applications. 834 * 835 * @param cookie Identifier of the package to be opened. 836 * @param fileName Name of the asset to retrieve. 837 * @hide 838 */ openNonAsset(int cookie, @NonNull String fileName)839 public @NonNull InputStream openNonAsset(int cookie, @NonNull String fileName) 840 throws IOException { 841 return openNonAsset(cookie, fileName, ACCESS_STREAMING); 842 } 843 844 /** 845 * Open a non-asset in a specified package. Not for use by applications. 846 * 847 * @param cookie Identifier of the package to be opened. 848 * @param fileName Name of the asset to retrieve. 849 * @param accessMode Desired access mode for retrieving the data. 850 * @hide 851 */ openNonAsset(int cookie, @NonNull String fileName, int accessMode)852 public @NonNull InputStream openNonAsset(int cookie, @NonNull String fileName, int accessMode) 853 throws IOException { 854 Preconditions.checkNotNull(fileName, "fileName"); 855 synchronized (this) { 856 ensureOpenLocked(); 857 final long asset = nativeOpenNonAsset(mObject, cookie, fileName, accessMode); 858 if (asset == 0) { 859 throw new FileNotFoundException("Asset absolute file: " + fileName); 860 } 861 final AssetInputStream assetInputStream = new AssetInputStream(asset); 862 incRefsLocked(assetInputStream.hashCode()); 863 return assetInputStream; 864 } 865 } 866 867 /** 868 * Open a non-asset as an asset by mmapping it and returning an {@link AssetFileDescriptor}. 869 * This provides direct access to all of the files included in an application 870 * package (not only its assets). Applications should not normally use this. 871 * 872 * The asset must not be compressed, or an exception will be thrown. 873 * 874 * @param fileName Name of the asset to retrieve. 875 */ openNonAssetFd(@onNull String fileName)876 public @NonNull AssetFileDescriptor openNonAssetFd(@NonNull String fileName) 877 throws IOException { 878 return openNonAssetFd(0, fileName); 879 } 880 881 /** 882 * Open a non-asset as an asset by mmapping it and returning an {@link AssetFileDescriptor}. 883 * This provides direct access to all of the files included in an application 884 * package (not only its assets). Applications should not normally use this. 885 * 886 * The asset must not be compressed, or an exception will be thrown. 887 * 888 * @param cookie Identifier of the package to be opened. 889 * @param fileName Name of the asset to retrieve. 890 */ openNonAssetFd(int cookie, @NonNull String fileName)891 public @NonNull AssetFileDescriptor openNonAssetFd(int cookie, @NonNull String fileName) 892 throws IOException { 893 Preconditions.checkNotNull(fileName, "fileName"); 894 synchronized (this) { 895 ensureOpenLocked(); 896 final ParcelFileDescriptor pfd = 897 nativeOpenNonAssetFd(mObject, cookie, fileName, mOffsets); 898 if (pfd == null) { 899 throw new FileNotFoundException("Asset absolute file: " + fileName); 900 } 901 return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]); 902 } 903 } 904 905 /** 906 * Retrieve a parser for a compiled XML file. 907 * 908 * @param fileName The name of the file to retrieve. 909 */ openXmlResourceParser(@onNull String fileName)910 public @NonNull XmlResourceParser openXmlResourceParser(@NonNull String fileName) 911 throws IOException { 912 return openXmlResourceParser(0, fileName); 913 } 914 915 /** 916 * Retrieve a parser for a compiled XML file. 917 * 918 * @param cookie Identifier of the package to be opened. 919 * @param fileName The name of the file to retrieve. 920 */ openXmlResourceParser(int cookie, @NonNull String fileName)921 public @NonNull XmlResourceParser openXmlResourceParser(int cookie, @NonNull String fileName) 922 throws IOException { 923 try (XmlBlock block = openXmlBlockAsset(cookie, fileName)) { 924 XmlResourceParser parser = block.newParser(); 925 // If openXmlBlockAsset doesn't throw, it will always return an XmlBlock object with 926 // a valid native pointer, which makes newParser always return non-null. But let's 927 // be paranoid. 928 if (parser == null) { 929 throw new AssertionError("block.newParser() returned a null parser"); 930 } 931 return parser; 932 } 933 } 934 935 /** 936 * Retrieve a non-asset as a compiled XML file. Not for use by applications. 937 * 938 * @param fileName The name of the file to retrieve. 939 * @hide 940 */ openXmlBlockAsset(@onNull String fileName)941 @NonNull XmlBlock openXmlBlockAsset(@NonNull String fileName) throws IOException { 942 return openXmlBlockAsset(0, fileName); 943 } 944 945 /** 946 * Retrieve a non-asset as a compiled XML file. Not for use by 947 * applications. 948 * 949 * @param cookie Identifier of the package to be opened. 950 * @param fileName Name of the asset to retrieve. 951 * @hide 952 */ openXmlBlockAsset(int cookie, @NonNull String fileName)953 @NonNull XmlBlock openXmlBlockAsset(int cookie, @NonNull String fileName) throws IOException { 954 Preconditions.checkNotNull(fileName, "fileName"); 955 synchronized (this) { 956 ensureOpenLocked(); 957 final long xmlBlock = nativeOpenXmlAsset(mObject, cookie, fileName); 958 if (xmlBlock == 0) { 959 throw new FileNotFoundException("Asset XML file: " + fileName); 960 } 961 final XmlBlock block = new XmlBlock(this, xmlBlock); 962 incRefsLocked(block.hashCode()); 963 return block; 964 } 965 } 966 xmlBlockGone(int id)967 void xmlBlockGone(int id) { 968 synchronized (this) { 969 decRefsLocked(id); 970 } 971 } 972 applyStyle(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes, @Nullable XmlBlock.Parser parser, @NonNull int[] inAttrs, long outValuesAddress, long outIndicesAddress)973 void applyStyle(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes, 974 @Nullable XmlBlock.Parser parser, @NonNull int[] inAttrs, long outValuesAddress, 975 long outIndicesAddress) { 976 Preconditions.checkNotNull(inAttrs, "inAttrs"); 977 synchronized (this) { 978 // Need to synchronize on AssetManager because we will be accessing 979 // the native implementation of AssetManager. 980 ensureValidLocked(); 981 nativeApplyStyle(mObject, themePtr, defStyleAttr, defStyleRes, 982 parser != null ? parser.mParseState : 0, inAttrs, outValuesAddress, 983 outIndicesAddress); 984 } 985 } 986 resolveAttrs(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes, @Nullable int[] inValues, @NonNull int[] inAttrs, @NonNull int[] outValues, @NonNull int[] outIndices)987 boolean resolveAttrs(long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes, 988 @Nullable int[] inValues, @NonNull int[] inAttrs, @NonNull int[] outValues, 989 @NonNull int[] outIndices) { 990 Preconditions.checkNotNull(inAttrs, "inAttrs"); 991 Preconditions.checkNotNull(outValues, "outValues"); 992 Preconditions.checkNotNull(outIndices, "outIndices"); 993 synchronized (this) { 994 // Need to synchronize on AssetManager because we will be accessing 995 // the native implementation of AssetManager. 996 ensureValidLocked(); 997 return nativeResolveAttrs(mObject, 998 themePtr, defStyleAttr, defStyleRes, inValues, inAttrs, outValues, outIndices); 999 } 1000 } 1001 retrieveAttributes(@onNull XmlBlock.Parser parser, @NonNull int[] inAttrs, @NonNull int[] outValues, @NonNull int[] outIndices)1002 boolean retrieveAttributes(@NonNull XmlBlock.Parser parser, @NonNull int[] inAttrs, 1003 @NonNull int[] outValues, @NonNull int[] outIndices) { 1004 Preconditions.checkNotNull(parser, "parser"); 1005 Preconditions.checkNotNull(inAttrs, "inAttrs"); 1006 Preconditions.checkNotNull(outValues, "outValues"); 1007 Preconditions.checkNotNull(outIndices, "outIndices"); 1008 synchronized (this) { 1009 // Need to synchronize on AssetManager because we will be accessing 1010 // the native implementation of AssetManager. 1011 ensureValidLocked(); 1012 return nativeRetrieveAttributes( 1013 mObject, parser.mParseState, inAttrs, outValues, outIndices); 1014 } 1015 } 1016 createTheme()1017 long createTheme() { 1018 synchronized (this) { 1019 ensureValidLocked(); 1020 long themePtr = nativeThemeCreate(mObject); 1021 incRefsLocked(themePtr); 1022 return themePtr; 1023 } 1024 } 1025 releaseTheme(long themePtr)1026 void releaseTheme(long themePtr) { 1027 synchronized (this) { 1028 nativeThemeDestroy(themePtr); 1029 decRefsLocked(themePtr); 1030 } 1031 } 1032 applyStyleToTheme(long themePtr, @StyleRes int resId, boolean force)1033 void applyStyleToTheme(long themePtr, @StyleRes int resId, boolean force) { 1034 synchronized (this) { 1035 // Need to synchronize on AssetManager because we will be accessing 1036 // the native implementation of AssetManager. 1037 ensureValidLocked(); 1038 nativeThemeApplyStyle(mObject, themePtr, resId, force); 1039 } 1040 } 1041 1042 @Override finalize()1043 protected void finalize() throws Throwable { 1044 if (DEBUG_REFS && mNumRefs != 0) { 1045 Log.w(TAG, "AssetManager " + this + " finalized with non-zero refs: " + mNumRefs); 1046 if (mRefStacks != null) { 1047 for (RuntimeException e : mRefStacks.values()) { 1048 Log.w(TAG, "Reference from here", e); 1049 } 1050 } 1051 } 1052 1053 if (mObject != 0) { 1054 nativeDestroy(mObject); 1055 } 1056 } 1057 1058 /* No Locking is needed for AssetInputStream because an AssetInputStream is not-thread 1059 safe and it does not rely on AssetManager once it has been created. It completely owns the 1060 underlying Asset. */ 1061 public final class AssetInputStream extends InputStream { 1062 private long mAssetNativePtr; 1063 private long mLength; 1064 private long mMarkPos; 1065 1066 /** 1067 * @hide 1068 */ getAssetInt()1069 public final int getAssetInt() { 1070 throw new UnsupportedOperationException(); 1071 } 1072 1073 /** 1074 * @hide 1075 */ getNativeAsset()1076 public final long getNativeAsset() { 1077 return mAssetNativePtr; 1078 } 1079 AssetInputStream(long assetNativePtr)1080 private AssetInputStream(long assetNativePtr) { 1081 mAssetNativePtr = assetNativePtr; 1082 mLength = nativeAssetGetLength(assetNativePtr); 1083 } 1084 1085 @Override read()1086 public final int read() throws IOException { 1087 ensureOpen(); 1088 return nativeAssetReadChar(mAssetNativePtr); 1089 } 1090 1091 @Override read(@onNull byte[] b)1092 public final int read(@NonNull byte[] b) throws IOException { 1093 ensureOpen(); 1094 Preconditions.checkNotNull(b, "b"); 1095 return nativeAssetRead(mAssetNativePtr, b, 0, b.length); 1096 } 1097 1098 @Override read(@onNull byte[] b, int off, int len)1099 public final int read(@NonNull byte[] b, int off, int len) throws IOException { 1100 ensureOpen(); 1101 Preconditions.checkNotNull(b, "b"); 1102 return nativeAssetRead(mAssetNativePtr, b, off, len); 1103 } 1104 1105 @Override skip(long n)1106 public final long skip(long n) throws IOException { 1107 ensureOpen(); 1108 long pos = nativeAssetSeek(mAssetNativePtr, 0, 0); 1109 if ((pos + n) > mLength) { 1110 n = mLength - pos; 1111 } 1112 if (n > 0) { 1113 nativeAssetSeek(mAssetNativePtr, n, 0); 1114 } 1115 return n; 1116 } 1117 1118 @Override available()1119 public final int available() throws IOException { 1120 ensureOpen(); 1121 final long len = nativeAssetGetRemainingLength(mAssetNativePtr); 1122 return len > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) len; 1123 } 1124 1125 @Override markSupported()1126 public final boolean markSupported() { 1127 return true; 1128 } 1129 1130 @Override mark(int readlimit)1131 public final void mark(int readlimit) { 1132 ensureOpen(); 1133 mMarkPos = nativeAssetSeek(mAssetNativePtr, 0, 0); 1134 } 1135 1136 @Override reset()1137 public final void reset() throws IOException { 1138 ensureOpen(); 1139 nativeAssetSeek(mAssetNativePtr, mMarkPos, -1); 1140 } 1141 1142 @Override close()1143 public final void close() throws IOException { 1144 if (mAssetNativePtr != 0) { 1145 nativeAssetDestroy(mAssetNativePtr); 1146 mAssetNativePtr = 0; 1147 1148 synchronized (AssetManager.this) { 1149 decRefsLocked(hashCode()); 1150 } 1151 } 1152 } 1153 1154 @Override finalize()1155 protected void finalize() throws Throwable { 1156 close(); 1157 } 1158 ensureOpen()1159 private void ensureOpen() { 1160 if (mAssetNativePtr == 0) { 1161 throw new IllegalStateException("AssetInputStream is closed"); 1162 } 1163 } 1164 } 1165 1166 /** 1167 * Determine whether the state in this asset manager is up-to-date with 1168 * the files on the filesystem. If false is returned, you need to 1169 * instantiate a new AssetManager class to see the new data. 1170 * @hide 1171 */ isUpToDate()1172 public boolean isUpToDate() { 1173 for (ApkAssets apkAssets : getApkAssets()) { 1174 if (!apkAssets.isUpToDate()) { 1175 return false; 1176 } 1177 } 1178 return true; 1179 } 1180 1181 /** 1182 * Get the locales that this asset manager contains data for. 1183 * 1184 * <p>On SDK 21 (Android 5.0: Lollipop) and above, Locale strings are valid 1185 * <a href="https://tools.ietf.org/html/bcp47">BCP-47</a> language tags and can be 1186 * parsed using {@link java.util.Locale#forLanguageTag(String)}. 1187 * 1188 * <p>On SDK 20 (Android 4.4W: Kitkat for watches) and below, locale strings 1189 * are of the form {@code ll_CC} where {@code ll} is a two letter language code, 1190 * and {@code CC} is a two letter country code. 1191 */ getLocales()1192 public String[] getLocales() { 1193 synchronized (this) { 1194 ensureValidLocked(); 1195 return nativeGetLocales(mObject, false /*excludeSystem*/); 1196 } 1197 } 1198 1199 /** 1200 * Same as getLocales(), except that locales that are only provided by the system (i.e. those 1201 * present in framework-res.apk or its overlays) will not be listed. 1202 * 1203 * For example, if the "system" assets support English, French, and German, and the additional 1204 * assets support Cherokee and French, getLocales() would return 1205 * [Cherokee, English, French, German], while getNonSystemLocales() would return 1206 * [Cherokee, French]. 1207 * @hide 1208 */ getNonSystemLocales()1209 public String[] getNonSystemLocales() { 1210 synchronized (this) { 1211 ensureValidLocked(); 1212 return nativeGetLocales(mObject, true /*excludeSystem*/); 1213 } 1214 } 1215 1216 /** 1217 * @hide 1218 */ getSizeConfigurations()1219 Configuration[] getSizeConfigurations() { 1220 synchronized (this) { 1221 ensureValidLocked(); 1222 return nativeGetSizeConfigurations(mObject); 1223 } 1224 } 1225 1226 /** 1227 * Change the configuration used when retrieving resources. Not for use by 1228 * applications. 1229 * @hide 1230 */ setConfiguration(int mcc, int mnc, @Nullable String locale, int orientation, int touchscreen, int density, int keyboard, int keyboardHidden, int navigation, int screenWidth, int screenHeight, int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp, int screenLayout, int uiMode, int colorMode, int majorVersion)1231 public void setConfiguration(int mcc, int mnc, @Nullable String locale, int orientation, 1232 int touchscreen, int density, int keyboard, int keyboardHidden, int navigation, 1233 int screenWidth, int screenHeight, int smallestScreenWidthDp, int screenWidthDp, 1234 int screenHeightDp, int screenLayout, int uiMode, int colorMode, int majorVersion) { 1235 synchronized (this) { 1236 ensureValidLocked(); 1237 nativeSetConfiguration(mObject, mcc, mnc, locale, orientation, touchscreen, density, 1238 keyboard, keyboardHidden, navigation, screenWidth, screenHeight, 1239 smallestScreenWidthDp, screenWidthDp, screenHeightDp, screenLayout, uiMode, 1240 colorMode, majorVersion); 1241 } 1242 } 1243 1244 /** 1245 * @hide 1246 */ getAssignedPackageIdentifiers()1247 public SparseArray<String> getAssignedPackageIdentifiers() { 1248 synchronized (this) { 1249 ensureValidLocked(); 1250 return nativeGetAssignedPackageIdentifiers(mObject); 1251 } 1252 } 1253 1254 @GuardedBy("this") incRefsLocked(long id)1255 private void incRefsLocked(long id) { 1256 if (DEBUG_REFS) { 1257 if (mRefStacks == null) { 1258 mRefStacks = new HashMap<>(); 1259 } 1260 RuntimeException ex = new RuntimeException(); 1261 ex.fillInStackTrace(); 1262 mRefStacks.put(id, ex); 1263 } 1264 mNumRefs++; 1265 } 1266 1267 @GuardedBy("this") decRefsLocked(long id)1268 private void decRefsLocked(long id) { 1269 if (DEBUG_REFS && mRefStacks != null) { 1270 mRefStacks.remove(id); 1271 } 1272 mNumRefs--; 1273 if (mNumRefs == 0 && mObject != 0) { 1274 nativeDestroy(mObject); 1275 mObject = 0; 1276 mApkAssets = sEmptyApkAssets; 1277 } 1278 } 1279 1280 // AssetManager setup native methods. nativeCreate()1281 private static native long nativeCreate(); nativeDestroy(long ptr)1282 private static native void nativeDestroy(long ptr); nativeSetApkAssets(long ptr, @NonNull ApkAssets[] apkAssets, boolean invalidateCaches)1283 private static native void nativeSetApkAssets(long ptr, @NonNull ApkAssets[] apkAssets, 1284 boolean invalidateCaches); nativeSetConfiguration(long ptr, int mcc, int mnc, @Nullable String locale, int orientation, int touchscreen, int density, int keyboard, int keyboardHidden, int navigation, int screenWidth, int screenHeight, int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp, int screenLayout, int uiMode, int colorMode, int majorVersion)1285 private static native void nativeSetConfiguration(long ptr, int mcc, int mnc, 1286 @Nullable String locale, int orientation, int touchscreen, int density, int keyboard, 1287 int keyboardHidden, int navigation, int screenWidth, int screenHeight, 1288 int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp, int screenLayout, 1289 int uiMode, int colorMode, int majorVersion); nativeGetAssignedPackageIdentifiers( long ptr)1290 private static native @NonNull SparseArray<String> nativeGetAssignedPackageIdentifiers( 1291 long ptr); 1292 1293 // File native methods. nativeList(long ptr, @NonNull String path)1294 private static native @Nullable String[] nativeList(long ptr, @NonNull String path) 1295 throws IOException; nativeOpenAsset(long ptr, @NonNull String fileName, int accessMode)1296 private static native long nativeOpenAsset(long ptr, @NonNull String fileName, int accessMode); nativeOpenAssetFd(long ptr, @NonNull String fileName, long[] outOffsets)1297 private static native @Nullable ParcelFileDescriptor nativeOpenAssetFd(long ptr, 1298 @NonNull String fileName, long[] outOffsets) throws IOException; nativeOpenNonAsset(long ptr, int cookie, @NonNull String fileName, int accessMode)1299 private static native long nativeOpenNonAsset(long ptr, int cookie, @NonNull String fileName, 1300 int accessMode); nativeOpenNonAssetFd(long ptr, int cookie, @NonNull String fileName, @NonNull long[] outOffsets)1301 private static native @Nullable ParcelFileDescriptor nativeOpenNonAssetFd(long ptr, int cookie, 1302 @NonNull String fileName, @NonNull long[] outOffsets) throws IOException; nativeOpenXmlAsset(long ptr, int cookie, @NonNull String fileName)1303 private static native long nativeOpenXmlAsset(long ptr, int cookie, @NonNull String fileName); 1304 1305 // Primitive resource native methods. nativeGetResourceValue(long ptr, @AnyRes int resId, short density, @NonNull TypedValue outValue, boolean resolveReferences)1306 private static native int nativeGetResourceValue(long ptr, @AnyRes int resId, short density, 1307 @NonNull TypedValue outValue, boolean resolveReferences); nativeGetResourceBagValue(long ptr, @AnyRes int resId, int bagEntryId, @NonNull TypedValue outValue)1308 private static native int nativeGetResourceBagValue(long ptr, @AnyRes int resId, int bagEntryId, 1309 @NonNull TypedValue outValue); 1310 nativeGetStyleAttributes(long ptr, @StyleRes int resId)1311 private static native @Nullable @AttrRes int[] nativeGetStyleAttributes(long ptr, 1312 @StyleRes int resId); nativeGetResourceStringArray(long ptr, @ArrayRes int resId)1313 private static native @Nullable String[] nativeGetResourceStringArray(long ptr, 1314 @ArrayRes int resId); nativeGetResourceStringArrayInfo(long ptr, @ArrayRes int resId)1315 private static native @Nullable int[] nativeGetResourceStringArrayInfo(long ptr, 1316 @ArrayRes int resId); nativeGetResourceIntArray(long ptr, @ArrayRes int resId)1317 private static native @Nullable int[] nativeGetResourceIntArray(long ptr, @ArrayRes int resId); nativeGetResourceArraySize(long ptr, @ArrayRes int resId)1318 private static native int nativeGetResourceArraySize(long ptr, @ArrayRes int resId); nativeGetResourceArray(long ptr, @ArrayRes int resId, @NonNull int[] outValues)1319 private static native int nativeGetResourceArray(long ptr, @ArrayRes int resId, 1320 @NonNull int[] outValues); 1321 1322 // Resource name/ID native methods. nativeGetResourceIdentifier(long ptr, @NonNull String name, @Nullable String defType, @Nullable String defPackage)1323 private static native @AnyRes int nativeGetResourceIdentifier(long ptr, @NonNull String name, 1324 @Nullable String defType, @Nullable String defPackage); nativeGetResourceName(long ptr, @AnyRes int resid)1325 private static native @Nullable String nativeGetResourceName(long ptr, @AnyRes int resid); nativeGetResourcePackageName(long ptr, @AnyRes int resid)1326 private static native @Nullable String nativeGetResourcePackageName(long ptr, 1327 @AnyRes int resid); nativeGetResourceTypeName(long ptr, @AnyRes int resid)1328 private static native @Nullable String nativeGetResourceTypeName(long ptr, @AnyRes int resid); nativeGetResourceEntryName(long ptr, @AnyRes int resid)1329 private static native @Nullable String nativeGetResourceEntryName(long ptr, @AnyRes int resid); nativeGetLocales(long ptr, boolean excludeSystem)1330 private static native @Nullable String[] nativeGetLocales(long ptr, boolean excludeSystem); nativeGetSizeConfigurations(long ptr)1331 private static native @Nullable Configuration[] nativeGetSizeConfigurations(long ptr); 1332 1333 // Style attribute retrieval native methods. nativeApplyStyle(long ptr, long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes, long xmlParserPtr, @NonNull int[] inAttrs, long outValuesAddress, long outIndicesAddress)1334 private static native void nativeApplyStyle(long ptr, long themePtr, @AttrRes int defStyleAttr, 1335 @StyleRes int defStyleRes, long xmlParserPtr, @NonNull int[] inAttrs, 1336 long outValuesAddress, long outIndicesAddress); nativeResolveAttrs(long ptr, long themePtr, @AttrRes int defStyleAttr, @StyleRes int defStyleRes, @Nullable int[] inValues, @NonNull int[] inAttrs, @NonNull int[] outValues, @NonNull int[] outIndices)1337 private static native boolean nativeResolveAttrs(long ptr, long themePtr, 1338 @AttrRes int defStyleAttr, @StyleRes int defStyleRes, @Nullable int[] inValues, 1339 @NonNull int[] inAttrs, @NonNull int[] outValues, @NonNull int[] outIndices); nativeRetrieveAttributes(long ptr, long xmlParserPtr, @NonNull int[] inAttrs, @NonNull int[] outValues, @NonNull int[] outIndices)1340 private static native boolean nativeRetrieveAttributes(long ptr, long xmlParserPtr, 1341 @NonNull int[] inAttrs, @NonNull int[] outValues, @NonNull int[] outIndices); 1342 1343 // Theme related native methods nativeThemeCreate(long ptr)1344 private static native long nativeThemeCreate(long ptr); nativeThemeDestroy(long themePtr)1345 private static native void nativeThemeDestroy(long themePtr); nativeThemeApplyStyle(long ptr, long themePtr, @StyleRes int resId, boolean force)1346 private static native void nativeThemeApplyStyle(long ptr, long themePtr, @StyleRes int resId, 1347 boolean force); nativeThemeCopy(long destThemePtr, long sourceThemePtr)1348 static native void nativeThemeCopy(long destThemePtr, long sourceThemePtr); nativeThemeClear(long themePtr)1349 static native void nativeThemeClear(long themePtr); nativeThemeGetAttributeValue(long ptr, long themePtr, @AttrRes int resId, @NonNull TypedValue outValue, boolean resolve)1350 private static native int nativeThemeGetAttributeValue(long ptr, long themePtr, 1351 @AttrRes int resId, @NonNull TypedValue outValue, boolean resolve); nativeThemeDump(long ptr, long themePtr, int priority, String tag, String prefix)1352 private static native void nativeThemeDump(long ptr, long themePtr, int priority, String tag, 1353 String prefix); nativeThemeGetChangingConfigurations(long themePtr)1354 static native @NativeConfig int nativeThemeGetChangingConfigurations(long themePtr); 1355 1356 // AssetInputStream related native methods. nativeAssetDestroy(long assetPtr)1357 private static native void nativeAssetDestroy(long assetPtr); nativeAssetReadChar(long assetPtr)1358 private static native int nativeAssetReadChar(long assetPtr); nativeAssetRead(long assetPtr, byte[] b, int off, int len)1359 private static native int nativeAssetRead(long assetPtr, byte[] b, int off, int len); nativeAssetSeek(long assetPtr, long offset, int whence)1360 private static native long nativeAssetSeek(long assetPtr, long offset, int whence); nativeAssetGetLength(long assetPtr)1361 private static native long nativeAssetGetLength(long assetPtr); nativeAssetGetRemainingLength(long assetPtr)1362 private static native long nativeAssetGetRemainingLength(long assetPtr); 1363 nativeVerifySystemIdmaps()1364 private static native void nativeVerifySystemIdmaps(); 1365 1366 // Global debug native methods. 1367 /** 1368 * @hide 1369 */ getGlobalAssetCount()1370 public static native int getGlobalAssetCount(); 1371 1372 /** 1373 * @hide 1374 */ getAssetAllocations()1375 public static native String getAssetAllocations(); 1376 1377 /** 1378 * @hide 1379 */ getGlobalAssetManagerCount()1380 public static native int getGlobalAssetManagerCount(); 1381 } 1382