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