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.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.StringRes; 24 import android.content.res.Configuration.NativeConfig; 25 import android.os.ParcelFileDescriptor; 26 import android.util.Log; 27 import android.util.SparseArray; 28 import android.util.TypedValue; 29 30 import java.io.FileNotFoundException; 31 import java.io.IOException; 32 import java.io.InputStream; 33 import java.util.HashMap; 34 35 /** 36 * Provides access to an application's raw asset files; see {@link Resources} 37 * for the way most applications will want to retrieve their resource data. 38 * This class presents a lower-level API that allows you to open and read raw 39 * files that have been bundled with the application as a simple stream of 40 * bytes. 41 */ 42 public final class AssetManager implements AutoCloseable { 43 /* modes used when opening an asset */ 44 45 /** 46 * Mode for {@link #open(String, int)}: no specific information about how 47 * data will be accessed. 48 */ 49 public static final int ACCESS_UNKNOWN = 0; 50 /** 51 * Mode for {@link #open(String, int)}: Read chunks, and seek forward and 52 * backward. 53 */ 54 public static final int ACCESS_RANDOM = 1; 55 /** 56 * Mode for {@link #open(String, int)}: Read sequentially, with an 57 * occasional forward seek. 58 */ 59 public static final int ACCESS_STREAMING = 2; 60 /** 61 * Mode for {@link #open(String, int)}: Attempt to load contents into 62 * memory, for fast small reads. 63 */ 64 public static final int ACCESS_BUFFER = 3; 65 66 private static final String TAG = "AssetManager"; 67 private static final boolean localLOGV = false || false; 68 69 private static final boolean DEBUG_REFS = false; 70 71 private static final Object sSync = new Object(); 72 /*package*/ static AssetManager sSystem = null; 73 74 private final TypedValue mValue = new TypedValue(); 75 private final long[] mOffsets = new long[2]; 76 77 // For communication with native code. 78 private long mObject; 79 80 private StringBlock mStringBlocks[] = null; 81 82 private int mNumRefs = 1; 83 private boolean mOpen = true; 84 private HashMap<Long, RuntimeException> mRefStacks; 85 86 /** 87 * Create a new AssetManager containing only the basic system assets. 88 * Applications will not generally use this method, instead retrieving the 89 * appropriate asset manager with {@link Resources#getAssets}. Not for 90 * use by applications. 91 * {@hide} 92 */ AssetManager()93 public AssetManager() { 94 synchronized (this) { 95 if (DEBUG_REFS) { 96 mNumRefs = 0; 97 incRefsLocked(this.hashCode()); 98 } 99 init(false); 100 if (localLOGV) Log.v(TAG, "New asset manager: " + this); 101 ensureSystemAssets(); 102 } 103 } 104 ensureSystemAssets()105 private static void ensureSystemAssets() { 106 synchronized (sSync) { 107 if (sSystem == null) { 108 AssetManager system = new AssetManager(true); 109 system.makeStringBlocks(null); 110 sSystem = system; 111 } 112 } 113 } 114 AssetManager(boolean isSystem)115 private AssetManager(boolean isSystem) { 116 if (DEBUG_REFS) { 117 synchronized (this) { 118 mNumRefs = 0; 119 incRefsLocked(this.hashCode()); 120 } 121 } 122 init(true); 123 if (localLOGV) Log.v(TAG, "New asset manager: " + this); 124 } 125 126 /** 127 * Return a global shared asset manager that provides access to only 128 * system assets (no application assets). 129 * {@hide} 130 */ getSystem()131 public static AssetManager getSystem() { 132 ensureSystemAssets(); 133 return sSystem; 134 } 135 136 /** 137 * Close this asset manager. 138 */ close()139 public void close() { 140 synchronized(this) { 141 //System.out.println("Release: num=" + mNumRefs 142 // + ", released=" + mReleased); 143 if (mOpen) { 144 mOpen = false; 145 decRefsLocked(this.hashCode()); 146 } 147 } 148 } 149 150 /** 151 * Retrieves the string value associated with a particular resource 152 * identifier for the current configuration. 153 * 154 * @param resId the resource identifier to load 155 * @return the string value, or {@code null} 156 */ 157 @Nullable getResourceText(@tringRes int resId)158 final CharSequence getResourceText(@StringRes int resId) { 159 synchronized (this) { 160 final TypedValue outValue = mValue; 161 if (getResourceValue(resId, 0, outValue, true)) { 162 return outValue.coerceToString(); 163 } 164 return null; 165 } 166 } 167 168 /** 169 * Retrieves the string value associated with a particular resource 170 * identifier for the current configuration. 171 * 172 * @param resId the resource identifier to load 173 * @param bagEntryId 174 * @return the string value, or {@code null} 175 */ 176 @Nullable getResourceBagText(@tringRes int resId, int bagEntryId)177 final CharSequence getResourceBagText(@StringRes int resId, int bagEntryId) { 178 synchronized (this) { 179 final TypedValue outValue = mValue; 180 final int block = loadResourceBagValue(resId, bagEntryId, outValue, true); 181 if (block < 0) { 182 return null; 183 } 184 if (outValue.type == TypedValue.TYPE_STRING) { 185 return mStringBlocks[block].get(outValue.data); 186 } 187 return outValue.coerceToString(); 188 } 189 } 190 191 /** 192 * Retrieves the string array associated with a particular resource 193 * identifier for the current configuration. 194 * 195 * @param resId the resource identifier of the string array 196 * @return the string array, or {@code null} 197 */ 198 @Nullable getResourceStringArray(@rrayRes int resId)199 final String[] getResourceStringArray(@ArrayRes int resId) { 200 return getArrayStringResource(resId); 201 } 202 203 /** 204 * Populates {@code outValue} with the data associated a particular 205 * resource identifier for the current configuration. 206 * 207 * @param resId the resource identifier to load 208 * @param densityDpi the density bucket for which to load the resource 209 * @param outValue the typed value in which to put the data 210 * @param resolveRefs {@code true} to resolve references, {@code false} 211 * to leave them unresolved 212 * @return {@code true} if the data was loaded into {@code outValue}, 213 * {@code false} otherwise 214 */ getResourceValue(@nyRes int resId, int densityDpi, @NonNull TypedValue outValue, boolean resolveRefs)215 final boolean getResourceValue(@AnyRes int resId, int densityDpi, @NonNull TypedValue outValue, 216 boolean resolveRefs) { 217 final int block = loadResourceValue(resId, (short) densityDpi, outValue, resolveRefs); 218 if (block < 0) { 219 return false; 220 } 221 if (outValue.type == TypedValue.TYPE_STRING) { 222 outValue.string = mStringBlocks[block].get(outValue.data); 223 } 224 return true; 225 } 226 227 /** 228 * Retrieve the text array associated with a particular resource 229 * identifier. 230 * 231 * @param resId the resource id of the string array 232 */ getResourceTextArray(@rrayRes int resId)233 final CharSequence[] getResourceTextArray(@ArrayRes int resId) { 234 final int[] rawInfoArray = getArrayStringInfo(resId); 235 final int rawInfoArrayLen = rawInfoArray.length; 236 final int infoArrayLen = rawInfoArrayLen / 2; 237 int block; 238 int index; 239 final CharSequence[] retArray = new CharSequence[infoArrayLen]; 240 for (int i = 0, j = 0; i < rawInfoArrayLen; i = i + 2, j++) { 241 block = rawInfoArray[i]; 242 index = rawInfoArray[i + 1]; 243 retArray[j] = index >= 0 ? mStringBlocks[block].get(index) : null; 244 } 245 return retArray; 246 } 247 248 /** 249 * Populates {@code outValue} with the data associated with a particular 250 * resource identifier for the current configuration. Resolves theme 251 * attributes against the specified theme. 252 * 253 * @param theme the native pointer of the theme 254 * @param resId the resource identifier to load 255 * @param outValue the typed value in which to put the data 256 * @param resolveRefs {@code true} to resolve references, {@code false} 257 * to leave them unresolved 258 * @return {@code true} if the data was loaded into {@code outValue}, 259 * {@code false} otherwise 260 */ getThemeValue(long theme, @AnyRes int resId, @NonNull TypedValue outValue, boolean resolveRefs)261 final boolean getThemeValue(long theme, @AnyRes int resId, @NonNull TypedValue outValue, 262 boolean resolveRefs) { 263 final int block = loadThemeAttributeValue(theme, resId, outValue, resolveRefs); 264 if (block < 0) { 265 return false; 266 } 267 if (outValue.type == TypedValue.TYPE_STRING) { 268 final StringBlock[] blocks = ensureStringBlocks(); 269 outValue.string = blocks[block].get(outValue.data); 270 } 271 return true; 272 } 273 274 /** 275 * Ensures the string blocks are loaded. 276 * 277 * @return the string blocks 278 */ 279 @NonNull ensureStringBlocks()280 final StringBlock[] ensureStringBlocks() { 281 synchronized (this) { 282 if (mStringBlocks == null) { 283 makeStringBlocks(sSystem.mStringBlocks); 284 } 285 return mStringBlocks; 286 } 287 } 288 makeStringBlocks(StringBlock[] seed)289 /*package*/ final void makeStringBlocks(StringBlock[] seed) { 290 final int seedNum = (seed != null) ? seed.length : 0; 291 final int num = getStringBlockCount(); 292 mStringBlocks = new StringBlock[num]; 293 if (localLOGV) Log.v(TAG, "Making string blocks for " + this 294 + ": " + num); 295 for (int i=0; i<num; i++) { 296 if (i < seedNum) { 297 mStringBlocks[i] = seed[i]; 298 } else { 299 mStringBlocks[i] = new StringBlock(getNativeStringBlock(i), true); 300 } 301 } 302 } 303 getPooledStringForCookie(int cookie, int id)304 /*package*/ final CharSequence getPooledStringForCookie(int cookie, int id) { 305 // Cookies map to string blocks starting at 1. 306 return mStringBlocks[cookie - 1].get(id); 307 } 308 309 /** 310 * Open an asset using ACCESS_STREAMING mode. This provides access to 311 * files that have been bundled with an application as assets -- that is, 312 * files placed in to the "assets" directory. 313 * 314 * @param fileName The name of the asset to open. This name can be 315 * hierarchical. 316 * 317 * @see #open(String, int) 318 * @see #list 319 */ open(String fileName)320 public final InputStream open(String fileName) throws IOException { 321 return open(fileName, ACCESS_STREAMING); 322 } 323 324 /** 325 * Open an asset using an explicit access mode, returning an InputStream to 326 * read its contents. This provides access to files that have been bundled 327 * with an application as assets -- that is, files placed in to the 328 * "assets" directory. 329 * 330 * @param fileName The name of the asset to open. This name can be 331 * hierarchical. 332 * @param accessMode Desired access mode for retrieving the data. 333 * 334 * @see #ACCESS_UNKNOWN 335 * @see #ACCESS_STREAMING 336 * @see #ACCESS_RANDOM 337 * @see #ACCESS_BUFFER 338 * @see #open(String) 339 * @see #list 340 */ open(String fileName, int accessMode)341 public final InputStream open(String fileName, int accessMode) 342 throws IOException { 343 synchronized (this) { 344 if (!mOpen) { 345 throw new RuntimeException("Assetmanager has been closed"); 346 } 347 long asset = openAsset(fileName, accessMode); 348 if (asset != 0) { 349 AssetInputStream res = new AssetInputStream(asset); 350 incRefsLocked(res.hashCode()); 351 return res; 352 } 353 } 354 throw new FileNotFoundException("Asset file: " + fileName); 355 } 356 openFd(String fileName)357 public final AssetFileDescriptor openFd(String fileName) 358 throws IOException { 359 synchronized (this) { 360 if (!mOpen) { 361 throw new RuntimeException("Assetmanager has been closed"); 362 } 363 ParcelFileDescriptor pfd = openAssetFd(fileName, mOffsets); 364 if (pfd != null) { 365 return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]); 366 } 367 } 368 throw new FileNotFoundException("Asset file: " + fileName); 369 } 370 371 /** 372 * Return a String array of all the assets at the given path. 373 * 374 * @param path A relative path within the assets, i.e., "docs/home.html". 375 * 376 * @return String[] Array of strings, one for each asset. These file 377 * names are relative to 'path'. You can open the file by 378 * concatenating 'path' and a name in the returned string (via 379 * File) and passing that to open(). 380 * 381 * @see #open 382 */ list(String path)383 public native final String[] list(String path) 384 throws IOException; 385 386 /** 387 * {@hide} 388 * Open a non-asset file as an asset using ACCESS_STREAMING mode. This 389 * provides direct access to all of the files included in an application 390 * package (not only its assets). Applications should not normally use 391 * this. 392 * 393 * @see #open(String) 394 */ openNonAsset(String fileName)395 public final InputStream openNonAsset(String fileName) throws IOException { 396 return openNonAsset(0, fileName, ACCESS_STREAMING); 397 } 398 399 /** 400 * {@hide} 401 * Open a non-asset file as an asset using a specific access mode. This 402 * provides direct access to all of the files included in an application 403 * package (not only its assets). Applications should not normally use 404 * this. 405 * 406 * @see #open(String, int) 407 */ openNonAsset(String fileName, int accessMode)408 public final InputStream openNonAsset(String fileName, int accessMode) 409 throws IOException { 410 return openNonAsset(0, fileName, accessMode); 411 } 412 413 /** 414 * {@hide} 415 * Open a non-asset in a specified package. Not for use by applications. 416 * 417 * @param cookie Identifier of the package to be opened. 418 * @param fileName Name of the asset to retrieve. 419 */ openNonAsset(int cookie, String fileName)420 public final InputStream openNonAsset(int cookie, String fileName) 421 throws IOException { 422 return openNonAsset(cookie, fileName, ACCESS_STREAMING); 423 } 424 425 /** 426 * {@hide} 427 * Open a non-asset in a specified package. Not for use by applications. 428 * 429 * @param cookie Identifier of the package to be opened. 430 * @param fileName Name of the asset to retrieve. 431 * @param accessMode Desired access mode for retrieving the data. 432 */ openNonAsset(int cookie, String fileName, int accessMode)433 public final InputStream openNonAsset(int cookie, String fileName, int accessMode) 434 throws IOException { 435 synchronized (this) { 436 if (!mOpen) { 437 throw new RuntimeException("Assetmanager has been closed"); 438 } 439 long asset = openNonAssetNative(cookie, fileName, accessMode); 440 if (asset != 0) { 441 AssetInputStream res = new AssetInputStream(asset); 442 incRefsLocked(res.hashCode()); 443 return res; 444 } 445 } 446 throw new FileNotFoundException("Asset absolute file: " + fileName); 447 } 448 openNonAssetFd(String fileName)449 public final AssetFileDescriptor openNonAssetFd(String fileName) 450 throws IOException { 451 return openNonAssetFd(0, fileName); 452 } 453 openNonAssetFd(int cookie, String fileName)454 public final AssetFileDescriptor openNonAssetFd(int cookie, 455 String fileName) throws IOException { 456 synchronized (this) { 457 if (!mOpen) { 458 throw new RuntimeException("Assetmanager has been closed"); 459 } 460 ParcelFileDescriptor pfd = openNonAssetFdNative(cookie, 461 fileName, mOffsets); 462 if (pfd != null) { 463 return new AssetFileDescriptor(pfd, mOffsets[0], mOffsets[1]); 464 } 465 } 466 throw new FileNotFoundException("Asset absolute file: " + fileName); 467 } 468 469 /** 470 * Retrieve a parser for a compiled XML file. 471 * 472 * @param fileName The name of the file to retrieve. 473 */ openXmlResourceParser(String fileName)474 public final XmlResourceParser openXmlResourceParser(String fileName) 475 throws IOException { 476 return openXmlResourceParser(0, fileName); 477 } 478 479 /** 480 * Retrieve a parser for a compiled XML file. 481 * 482 * @param cookie Identifier of the package to be opened. 483 * @param fileName The name of the file to retrieve. 484 */ openXmlResourceParser(int cookie, String fileName)485 public final XmlResourceParser openXmlResourceParser(int cookie, 486 String fileName) throws IOException { 487 XmlBlock block = openXmlBlockAsset(cookie, fileName); 488 XmlResourceParser rp = block.newParser(); 489 block.close(); 490 return rp; 491 } 492 493 /** 494 * {@hide} 495 * Retrieve a non-asset as a compiled XML file. Not for use by 496 * applications. 497 * 498 * @param fileName The name of the file to retrieve. 499 */ openXmlBlockAsset(String fileName)500 /*package*/ final XmlBlock openXmlBlockAsset(String fileName) 501 throws IOException { 502 return openXmlBlockAsset(0, fileName); 503 } 504 505 /** 506 * {@hide} 507 * Retrieve a non-asset as a compiled XML file. Not for use by 508 * applications. 509 * 510 * @param cookie Identifier of the package to be opened. 511 * @param fileName Name of the asset to retrieve. 512 */ openXmlBlockAsset(int cookie, String fileName)513 /*package*/ final XmlBlock openXmlBlockAsset(int cookie, String fileName) 514 throws IOException { 515 synchronized (this) { 516 if (!mOpen) { 517 throw new RuntimeException("Assetmanager has been closed"); 518 } 519 long xmlBlock = openXmlAssetNative(cookie, fileName); 520 if (xmlBlock != 0) { 521 XmlBlock res = new XmlBlock(this, xmlBlock); 522 incRefsLocked(res.hashCode()); 523 return res; 524 } 525 } 526 throw new FileNotFoundException("Asset XML file: " + fileName); 527 } 528 xmlBlockGone(int id)529 /*package*/ void xmlBlockGone(int id) { 530 synchronized (this) { 531 decRefsLocked(id); 532 } 533 } 534 createTheme()535 /*package*/ final long createTheme() { 536 synchronized (this) { 537 if (!mOpen) { 538 throw new RuntimeException("Assetmanager has been closed"); 539 } 540 long res = newTheme(); 541 incRefsLocked(res); 542 return res; 543 } 544 } 545 releaseTheme(long theme)546 /*package*/ final void releaseTheme(long theme) { 547 synchronized (this) { 548 deleteTheme(theme); 549 decRefsLocked(theme); 550 } 551 } 552 finalize()553 protected void finalize() throws Throwable { 554 try { 555 if (DEBUG_REFS && mNumRefs != 0) { 556 Log.w(TAG, "AssetManager " + this 557 + " finalized with non-zero refs: " + mNumRefs); 558 if (mRefStacks != null) { 559 for (RuntimeException e : mRefStacks.values()) { 560 Log.w(TAG, "Reference from here", e); 561 } 562 } 563 } 564 destroy(); 565 } finally { 566 super.finalize(); 567 } 568 } 569 570 public final class AssetInputStream extends InputStream { 571 /** 572 * @hide 573 */ getAssetInt()574 public final int getAssetInt() { 575 throw new UnsupportedOperationException(); 576 } 577 /** 578 * @hide 579 */ getNativeAsset()580 public final long getNativeAsset() { 581 return mAsset; 582 } AssetInputStream(long asset)583 private AssetInputStream(long asset) 584 { 585 mAsset = asset; 586 mLength = getAssetLength(asset); 587 } read()588 public final int read() throws IOException { 589 return readAssetChar(mAsset); 590 } markSupported()591 public final boolean markSupported() { 592 return true; 593 } available()594 public final int available() throws IOException { 595 long len = getAssetRemainingLength(mAsset); 596 return len > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)len; 597 } close()598 public final void close() throws IOException { 599 synchronized (AssetManager.this) { 600 if (mAsset != 0) { 601 destroyAsset(mAsset); 602 mAsset = 0; 603 decRefsLocked(hashCode()); 604 } 605 } 606 } mark(int readlimit)607 public final void mark(int readlimit) { 608 mMarkPos = seekAsset(mAsset, 0, 0); 609 } reset()610 public final void reset() throws IOException { 611 seekAsset(mAsset, mMarkPos, -1); 612 } read(byte[] b)613 public final int read(byte[] b) throws IOException { 614 return readAsset(mAsset, b, 0, b.length); 615 } read(byte[] b, int off, int len)616 public final int read(byte[] b, int off, int len) throws IOException { 617 return readAsset(mAsset, b, off, len); 618 } skip(long n)619 public final long skip(long n) throws IOException { 620 long pos = seekAsset(mAsset, 0, 0); 621 if ((pos+n) > mLength) { 622 n = mLength-pos; 623 } 624 if (n > 0) { 625 seekAsset(mAsset, n, 0); 626 } 627 return n; 628 } 629 finalize()630 protected void finalize() throws Throwable 631 { 632 close(); 633 } 634 635 private long mAsset; 636 private long mLength; 637 private long mMarkPos; 638 } 639 640 /** 641 * Add an additional set of assets to the asset manager. This can be 642 * either a directory or ZIP file. Not for use by applications. Returns 643 * the cookie of the added asset, or 0 on failure. 644 * {@hide} 645 */ addAssetPath(String path)646 public final int addAssetPath(String path) { 647 return addAssetPathInternal(path, false); 648 } 649 650 /** 651 * Add an application assets to the asset manager and loading it as shared library. 652 * This can be either a directory or ZIP file. Not for use by applications. Returns 653 * the cookie of the added asset, or 0 on failure. 654 * {@hide} 655 */ addAssetPathAsSharedLibrary(String path)656 public final int addAssetPathAsSharedLibrary(String path) { 657 return addAssetPathInternal(path, true); 658 } 659 addAssetPathInternal(String path, boolean appAsLib)660 private final int addAssetPathInternal(String path, boolean appAsLib) { 661 synchronized (this) { 662 int res = addAssetPathNative(path, appAsLib); 663 makeStringBlocks(mStringBlocks); 664 return res; 665 } 666 } 667 addAssetPathNative(String path, boolean appAsLib)668 private native final int addAssetPathNative(String path, boolean appAsLib); 669 670 /** 671 * Add a set of assets to overlay an already added set of assets. 672 * 673 * This is only intended for application resources. System wide resources 674 * are handled before any Java code is executed. 675 * 676 * {@hide} 677 */ 678 addOverlayPath(String idmapPath)679 public final int addOverlayPath(String idmapPath) { 680 synchronized (this) { 681 int res = addOverlayPathNative(idmapPath); 682 makeStringBlocks(mStringBlocks); 683 return res; 684 } 685 } 686 687 /** 688 * See addOverlayPath. 689 * 690 * {@hide} 691 */ addOverlayPathNative(String idmapPath)692 public native final int addOverlayPathNative(String idmapPath); 693 694 /** 695 * Add multiple sets of assets to the asset manager at once. See 696 * {@link #addAssetPath(String)} for more information. Returns array of 697 * cookies for each added asset with 0 indicating failure, or null if 698 * the input array of paths is null. 699 * {@hide} 700 */ addAssetPaths(String[] paths)701 public final int[] addAssetPaths(String[] paths) { 702 if (paths == null) { 703 return null; 704 } 705 706 int[] cookies = new int[paths.length]; 707 for (int i = 0; i < paths.length; i++) { 708 cookies[i] = addAssetPath(paths[i]); 709 } 710 711 return cookies; 712 } 713 714 /** 715 * Determine whether the state in this asset manager is up-to-date with 716 * the files on the filesystem. If false is returned, you need to 717 * instantiate a new AssetManager class to see the new data. 718 * {@hide} 719 */ isUpToDate()720 public native final boolean isUpToDate(); 721 722 /** 723 * Get the locales that this asset manager contains data for. 724 * 725 * <p>On SDK 21 (Android 5.0: Lollipop) and above, Locale strings are valid 726 * <a href="https://tools.ietf.org/html/bcp47">BCP-47</a> language tags and can be 727 * parsed using {@link java.util.Locale#forLanguageTag(String)}. 728 * 729 * <p>On SDK 20 (Android 4.4W: Kitkat for watches) and below, locale strings 730 * are of the form {@code ll_CC} where {@code ll} is a two letter language code, 731 * and {@code CC} is a two letter country code. 732 */ getLocales()733 public native final String[] getLocales(); 734 735 /** 736 * Same as getLocales(), except that locales that are only provided by the system (i.e. those 737 * present in framework-res.apk or its overlays) will not be listed. 738 * 739 * For example, if the "system" assets support English, French, and German, and the additional 740 * assets support Cherokee and French, getLocales() would return 741 * [Cherokee, English, French, German], while getNonSystemLocales() would return 742 * [Cherokee, French]. 743 * {@hide} 744 */ getNonSystemLocales()745 public native final String[] getNonSystemLocales(); 746 747 /** {@hide} */ getSizeConfigurations()748 public native final Configuration[] getSizeConfigurations(); 749 750 /** 751 * Change the configuation used when retrieving resources. Not for use by 752 * applications. 753 * {@hide} 754 */ setConfiguration(int mcc, int mnc, 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 majorVersion)755 public native final void setConfiguration(int mcc, int mnc, String locale, 756 int orientation, int touchscreen, int density, int keyboard, 757 int keyboardHidden, int navigation, int screenWidth, int screenHeight, 758 int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp, 759 int screenLayout, int uiMode, int majorVersion); 760 761 /** 762 * Retrieve the resource identifier for the given resource name. 763 */ getResourceIdentifier(String type, String name, String defPackage)764 /*package*/ native final int getResourceIdentifier(String type, 765 String name, 766 String defPackage); 767 getResourceName(int resid)768 /*package*/ native final String getResourceName(int resid); getResourcePackageName(int resid)769 /*package*/ native final String getResourcePackageName(int resid); getResourceTypeName(int resid)770 /*package*/ native final String getResourceTypeName(int resid); getResourceEntryName(int resid)771 /*package*/ native final String getResourceEntryName(int resid); 772 openAsset(String fileName, int accessMode)773 private native final long openAsset(String fileName, int accessMode); openAssetFd(String fileName, long[] outOffsets)774 private final native ParcelFileDescriptor openAssetFd(String fileName, 775 long[] outOffsets) throws IOException; openNonAssetNative(int cookie, String fileName, int accessMode)776 private native final long openNonAssetNative(int cookie, String fileName, 777 int accessMode); openNonAssetFdNative(int cookie, String fileName, long[] outOffsets)778 private native ParcelFileDescriptor openNonAssetFdNative(int cookie, 779 String fileName, long[] outOffsets) throws IOException; destroyAsset(long asset)780 private native final void destroyAsset(long asset); readAssetChar(long asset)781 private native final int readAssetChar(long asset); readAsset(long asset, byte[] b, int off, int len)782 private native final int readAsset(long asset, byte[] b, int off, int len); seekAsset(long asset, long offset, int whence)783 private native final long seekAsset(long asset, long offset, int whence); getAssetLength(long asset)784 private native final long getAssetLength(long asset); getAssetRemainingLength(long asset)785 private native final long getAssetRemainingLength(long asset); 786 787 /** Returns true if the resource was found, filling in mRetStringBlock and 788 * mRetData. */ loadResourceValue(int ident, short density, TypedValue outValue, boolean resolve)789 private native final int loadResourceValue(int ident, short density, TypedValue outValue, 790 boolean resolve); 791 /** Returns true if the resource was found, filling in mRetStringBlock and 792 * mRetData. */ loadResourceBagValue(int ident, int bagEntryId, TypedValue outValue, boolean resolve)793 private native final int loadResourceBagValue(int ident, int bagEntryId, TypedValue outValue, 794 boolean resolve); 795 /*package*/ static final int STYLE_NUM_ENTRIES = 6; 796 /*package*/ static final int STYLE_TYPE = 0; 797 /*package*/ static final int STYLE_DATA = 1; 798 /*package*/ static final int STYLE_ASSET_COOKIE = 2; 799 /*package*/ static final int STYLE_RESOURCE_ID = 3; 800 801 /* Offset within typed data array for native changingConfigurations. */ 802 static final int STYLE_CHANGING_CONFIGURATIONS = 4; 803 804 /*package*/ static final int STYLE_DENSITY = 5; applyStyle(long theme, int defStyleAttr, int defStyleRes, long xmlParser, int[] inAttrs, int[] outValues, int[] outIndices)805 /*package*/ native static final boolean applyStyle(long theme, 806 int defStyleAttr, int defStyleRes, long xmlParser, 807 int[] inAttrs, int[] outValues, int[] outIndices); resolveAttrs(long theme, int defStyleAttr, int defStyleRes, int[] inValues, int[] inAttrs, int[] outValues, int[] outIndices)808 /*package*/ native static final boolean resolveAttrs(long theme, 809 int defStyleAttr, int defStyleRes, int[] inValues, 810 int[] inAttrs, int[] outValues, int[] outIndices); retrieveAttributes( long xmlParser, int[] inAttrs, int[] outValues, int[] outIndices)811 /*package*/ native final boolean retrieveAttributes( 812 long xmlParser, int[] inAttrs, int[] outValues, int[] outIndices); getArraySize(int resource)813 /*package*/ native final int getArraySize(int resource); retrieveArray(int resource, int[] outValues)814 /*package*/ native final int retrieveArray(int resource, int[] outValues); getStringBlockCount()815 private native final int getStringBlockCount(); getNativeStringBlock(int block)816 private native final long getNativeStringBlock(int block); 817 818 /** 819 * {@hide} 820 */ getCookieName(int cookie)821 public native final String getCookieName(int cookie); 822 823 /** 824 * {@hide} 825 */ getAssignedPackageIdentifiers()826 public native final SparseArray<String> getAssignedPackageIdentifiers(); 827 828 /** 829 * {@hide} 830 */ getGlobalAssetCount()831 public native static final int getGlobalAssetCount(); 832 833 /** 834 * {@hide} 835 */ getAssetAllocations()836 public native static final String getAssetAllocations(); 837 838 /** 839 * {@hide} 840 */ getGlobalAssetManagerCount()841 public native static final int getGlobalAssetManagerCount(); 842 newTheme()843 private native final long newTheme(); deleteTheme(long theme)844 private native final void deleteTheme(long theme); applyThemeStyle(long theme, int styleRes, boolean force)845 /*package*/ native static final void applyThemeStyle(long theme, int styleRes, boolean force); copyTheme(long dest, long source)846 /*package*/ native static final void copyTheme(long dest, long source); clearTheme(long theme)847 /*package*/ native static final void clearTheme(long theme); loadThemeAttributeValue(long theme, int ident, TypedValue outValue, boolean resolve)848 /*package*/ native static final int loadThemeAttributeValue(long theme, int ident, 849 TypedValue outValue, 850 boolean resolve); dumpTheme(long theme, int priority, String tag, String prefix)851 /*package*/ native static final void dumpTheme(long theme, int priority, String tag, String prefix); getThemeChangingConfigurations(long theme)852 /*package*/ native static final @NativeConfig int getThemeChangingConfigurations(long theme); 853 openXmlAssetNative(int cookie, String fileName)854 private native final long openXmlAssetNative(int cookie, String fileName); 855 getArrayStringResource(int arrayRes)856 private native final String[] getArrayStringResource(int arrayRes); getArrayStringInfo(int arrayRes)857 private native final int[] getArrayStringInfo(int arrayRes); getArrayIntResource(int arrayRes)858 /*package*/ native final int[] getArrayIntResource(int arrayRes); getStyleAttributes(int themeRes)859 /*package*/ native final int[] getStyleAttributes(int themeRes); 860 init(boolean isSystem)861 private native final void init(boolean isSystem); destroy()862 private native final void destroy(); 863 incRefsLocked(long id)864 private final void incRefsLocked(long id) { 865 if (DEBUG_REFS) { 866 if (mRefStacks == null) { 867 mRefStacks = new HashMap<Long, RuntimeException>(); 868 } 869 RuntimeException ex = new RuntimeException(); 870 ex.fillInStackTrace(); 871 mRefStacks.put(id, ex); 872 } 873 mNumRefs++; 874 } 875 decRefsLocked(long id)876 private final void decRefsLocked(long id) { 877 if (DEBUG_REFS && mRefStacks != null) { 878 mRefStacks.remove(id); 879 } 880 mNumRefs--; 881 //System.out.println("Dec streams: mNumRefs=" + mNumRefs 882 // + " mReleased=" + mReleased); 883 if (mNumRefs == 0) { 884 destroy(); 885 } 886 } 887 } 888