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