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