blob: ee6aec2910aa7ed9566dce5fd4b4d521b1b8ddb0 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
17package android.content.res;
18
19import android.os.ParcelFileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.util.Log;
Adam Lesinskide898ff2014-01-29 18:20:45 -080021import android.util.SparseArray;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.util.TypedValue;
23
24import java.io.FileNotFoundException;
25import java.io.IOException;
26import java.io.InputStream;
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -080027import java.util.HashMap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028
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 */
Jeff Sharkeyda96e132014-07-15 14:54:09 -070036public final class AssetManager implements AutoCloseable {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037 /* 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";
Joe Onorato43a17652011-04-06 19:22:23 -070061 private static final boolean localLOGV = false || false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -080063 private static final boolean DEBUG_REFS = false;
64
Dianne Hackborn60d7db42009-11-16 17:16:26 -080065 private static final Object sSync = new Object();
Xavier Ducrohet7f9f99ea2011-08-11 10:16:17 -070066 /*package*/ static AssetManager sSystem = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067
Dianne Hackborn60d7db42009-11-16 17:16:26 -080068 private final TypedValue mValue = new TypedValue();
69 private final long[] mOffsets = new long[2];
70
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071 // For communication with native code.
Ashok Bhat896043d2014-01-17 16:02:38 +000072 private long mObject;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073
74 private StringBlock mStringBlocks[] = null;
75
76 private int mNumRefs = 1;
77 private boolean mOpen = true;
Ashok Bhat896043d2014-01-17 16:02:38 +000078 private HashMap<Long, RuntimeException> mRefStacks;
Dianne Hackborn60d7db42009-11-16 17:16:26 -080079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 /**
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 */
87 public AssetManager() {
Dianne Hackborn60d7db42009-11-16 17:16:26 -080088 synchronized (this) {
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -080089 if (DEBUG_REFS) {
90 mNumRefs = 0;
91 incRefsLocked(this.hashCode());
92 }
Mårten Kongstad48d22322014-01-31 14:43:27 +010093 init(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094 if (localLOGV) Log.v(TAG, "New asset manager: " + this);
95 ensureSystemAssets();
96 }
97 }
98
99 private static void ensureSystemAssets() {
Dianne Hackborn60d7db42009-11-16 17:16:26 -0800100 synchronized (sSync) {
101 if (sSystem == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 AssetManager system = new AssetManager(true);
Martin Kosiba7df36252014-01-16 16:25:56 +0000103 system.makeStringBlocks(null);
Dianne Hackborn60d7db42009-11-16 17:16:26 -0800104 sSystem = system;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105 }
106 }
107 }
108
109 private AssetManager(boolean isSystem) {
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -0800110 if (DEBUG_REFS) {
111 synchronized (this) {
112 mNumRefs = 0;
113 incRefsLocked(this.hashCode());
114 }
115 }
Mårten Kongstad48d22322014-01-31 14:43:27 +0100116 init(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117 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 */
125 public static AssetManager getSystem() {
126 ensureSystemAssets();
Dianne Hackborn60d7db42009-11-16 17:16:26 -0800127 return sSystem;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128 }
129
130 /**
131 * Close this asset manager.
132 */
133 public void close() {
Dianne Hackborn60d7db42009-11-16 17:16:26 -0800134 synchronized(this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 //System.out.println("Release: num=" + mNumRefs
136 // + ", released=" + mReleased);
137 if (mOpen) {
138 mOpen = false;
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -0800139 decRefsLocked(this.hashCode());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 }
141 }
142 }
143
144 /**
145 * Retrieve the string value associated with a particular resource
146 * identifier for the current configuration / skin.
147 */
148 /*package*/ final CharSequence getResourceText(int ident) {
Dianne Hackborn60d7db42009-11-16 17:16:26 -0800149 synchronized (this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 TypedValue tmpValue = mValue;
Kenny Root55fc8502010-10-28 14:47:01 -0700151 int block = loadResourceValue(ident, (short) 0, tmpValue, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 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 */
166 /*package*/ final CharSequence getResourceBagText(int ident, int bagEntryId) {
Dianne Hackborn60d7db42009-11-16 17:16:26 -0800167 synchronized (this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168 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 */
185 /*package*/ final String[] getResourceStringArray(final int id) {
186 String[] retArray = getArrayStringResource(id);
187 return retArray;
188 }
189
190
191 /*package*/ final boolean getResourceValue(int ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700192 int density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193 TypedValue outValue,
194 boolean resolveRefs)
195 {
Kenny Root55fc8502010-10-28 14:47:01 -0700196 int block = loadResourceValue(ident, (short) density, outValue, resolveRefs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 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
Ashok Bhat896043d2014-01-17 16:02:38 +0000227 /*package*/ final boolean getThemeValue(long theme, int ident,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 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();
Jozef BABJAK41a5ed72011-04-19 12:28:22 +0200237 blocks = mStringBlocks;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 }
239 outValue.string = blocks[block].get(outValue.data);
240 return true;
241 }
242 return false;
243 }
244
245 /*package*/ final void ensureStringBlocks() {
246 if (mStringBlocks == null) {
Dianne Hackborn60d7db42009-11-16 17:16:26 -0800247 synchronized (this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 if (mStringBlocks == null) {
Martin Kosiba7df36252014-01-16 16:25:56 +0000249 makeStringBlocks(sSystem.mStringBlocks);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250 }
251 }
252 }
253 }
254
Martin Kosiba7df36252014-01-16 16:25:56 +0000255 /*package*/ final void makeStringBlocks(StringBlock[] seed) {
256 final int seedNum = (seed != null) ? seed.length : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 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++) {
Martin Kosiba7df36252014-01-16 16:25:56 +0000262 if (i < seedNum) {
263 mStringBlocks[i] = seed[i];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 } else {
265 mStringBlocks[i] = new StringBlock(getNativeStringBlock(i), true);
266 }
267 }
268 }
269
Adam Lesinskide898ff2014-01-29 18:20:45 -0800270 /*package*/ final CharSequence getPooledStringForCookie(int cookie, int id) {
271 // Cookies map to string blocks starting at 1.
272 return mStringBlocks[cookie - 1].get(id);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273 }
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 */
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 */
307 public final InputStream open(String fileName, int accessMode)
308 throws IOException {
Dianne Hackborn60d7db42009-11-16 17:16:26 -0800309 synchronized (this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310 if (!mOpen) {
311 throw new RuntimeException("Assetmanager has been closed");
312 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000313 long asset = openAsset(fileName, accessMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 if (asset != 0) {
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -0800315 AssetInputStream res = new AssetInputStream(asset);
316 incRefsLocked(res.hashCode());
317 return res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318 }
319 }
320 throw new FileNotFoundException("Asset file: " + fileName);
321 }
322
323 public final AssetFileDescriptor openFd(String fileName)
324 throws IOException {
Dianne Hackborn60d7db42009-11-16 17:16:26 -0800325 synchronized (this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800326 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 */
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 */
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 */
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 */
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 */
399 public final InputStream openNonAsset(int cookie, String fileName, int accessMode)
400 throws IOException {
Dianne Hackborn60d7db42009-11-16 17:16:26 -0800401 synchronized (this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 if (!mOpen) {
403 throw new RuntimeException("Assetmanager has been closed");
404 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000405 long asset = openNonAssetNative(cookie, fileName, accessMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406 if (asset != 0) {
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -0800407 AssetInputStream res = new AssetInputStream(asset);
408 incRefsLocked(res.hashCode());
409 return res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 }
411 }
412 throw new FileNotFoundException("Asset absolute file: " + fileName);
413 }
414
415 public final AssetFileDescriptor openNonAssetFd(String fileName)
416 throws IOException {
417 return openNonAssetFd(0, fileName);
418 }
419
420 public final AssetFileDescriptor openNonAssetFd(int cookie,
421 String fileName) throws IOException {
Dianne Hackborn60d7db42009-11-16 17:16:26 -0800422 synchronized (this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 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 */
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 */
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 */
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 */
479 /*package*/ final XmlBlock openXmlBlockAsset(int cookie, String fileName)
480 throws IOException {
Dianne Hackborn60d7db42009-11-16 17:16:26 -0800481 synchronized (this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482 if (!mOpen) {
483 throw new RuntimeException("Assetmanager has been closed");
484 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000485 long xmlBlock = openXmlAssetNative(cookie, fileName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 if (xmlBlock != 0) {
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -0800487 XmlBlock res = new XmlBlock(this, xmlBlock);
488 incRefsLocked(res.hashCode());
489 return res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490 }
491 }
492 throw new FileNotFoundException("Asset XML file: " + fileName);
493 }
494
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -0800495 /*package*/ void xmlBlockGone(int id) {
Dianne Hackborn60d7db42009-11-16 17:16:26 -0800496 synchronized (this) {
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -0800497 decRefsLocked(id);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800498 }
499 }
500
Ashok Bhat896043d2014-01-17 16:02:38 +0000501 /*package*/ final long createTheme() {
Dianne Hackborn60d7db42009-11-16 17:16:26 -0800502 synchronized (this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 if (!mOpen) {
504 throw new RuntimeException("Assetmanager has been closed");
505 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000506 long res = newTheme();
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -0800507 incRefsLocked(res);
508 return res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800509 }
510 }
511
Ashok Bhat896043d2014-01-17 16:02:38 +0000512 /*package*/ final void releaseTheme(long theme) {
Dianne Hackborn60d7db42009-11-16 17:16:26 -0800513 synchronized (this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800514 deleteTheme(theme);
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -0800515 decRefsLocked(theme);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800516 }
517 }
518
519 protected void finalize() throws Throwable {
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -0800520 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 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534 }
535
536 public final class AssetInputStream extends InputStream {
Narayan Kamath2ba4eff2014-01-16 19:00:32 +0000537 /**
538 * @hide
539 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540 public final int getAssetInt() {
Narayan Kamath2d19d202014-02-25 15:48:07 +0000541 throw new UnsupportedOperationException();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 }
Ashok Bhata0545dd2014-01-14 10:52:35 +0000543 /**
544 * @hide
545 */
546 public final long getNativeAsset() {
547 return mAsset;
548 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000549 private AssetInputStream(long asset)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 {
551 mAsset = asset;
552 mLength = getAssetLength(asset);
553 }
554 public final int read() throws IOException {
555 return readAssetChar(mAsset);
556 }
557 public final boolean markSupported() {
558 return true;
559 }
560 public final int available() throws IOException {
561 long len = getAssetRemainingLength(mAsset);
562 return len > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)len;
563 }
564 public final void close() throws IOException {
Dianne Hackborn60d7db42009-11-16 17:16:26 -0800565 synchronized (AssetManager.this) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800566 if (mAsset != 0) {
567 destroyAsset(mAsset);
568 mAsset = 0;
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -0800569 decRefsLocked(hashCode());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570 }
571 }
572 }
573 public final void mark(int readlimit) {
574 mMarkPos = seekAsset(mAsset, 0, 0);
575 }
576 public final void reset() throws IOException {
577 seekAsset(mAsset, mMarkPos, -1);
578 }
579 public final int read(byte[] b) throws IOException {
580 return readAsset(mAsset, b, 0, b.length);
581 }
582 public final int read(byte[] b, int off, int len) throws IOException {
583 return readAsset(mAsset, b, off, len);
584 }
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
596 protected void finalize() throws Throwable
597 {
598 close();
599 }
600
Ashok Bhat896043d2014-01-17 16:02:38 +0000601 private long mAsset;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602 private long mLength;
603 private long mMarkPos;
604 }
605
606 /**
607 * Add an additional set of assets to the asset manager. This can be
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -0700608 * either a directory or ZIP file. Not for use by applications. Returns
609 * the cookie of the added asset, or 0 on failure.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610 * {@hide}
611 */
Dianne Hackbornf7be4802013-04-12 14:52:58 -0700612 public final int addAssetPath(String path) {
Tao Baia6d7e3f2015-09-01 18:49:54 -0700613 return addAssetPathInternal(path, false);
614 }
615
616 /**
617 * Add an application assets to the asset manager and loading it as shared library.
618 * This can be either a directory or ZIP file. Not for use by applications. Returns
619 * the cookie of the added asset, or 0 on failure.
620 * {@hide}
621 */
622 public final int addAssetPathAsSharedLibrary(String path) {
623 return addAssetPathInternal(path, true);
624 }
625
626 private final int addAssetPathInternal(String path, boolean appAsLib) {
Martin Kosiba7df36252014-01-16 16:25:56 +0000627 synchronized (this) {
Tao Baia6d7e3f2015-09-01 18:49:54 -0700628 int res = addAssetPathNative(path, appAsLib);
Martin Kosiba7df36252014-01-16 16:25:56 +0000629 makeStringBlocks(mStringBlocks);
630 return res;
631 }
Dianne Hackbornf7be4802013-04-12 14:52:58 -0700632 }
633
Tao Baia6d7e3f2015-09-01 18:49:54 -0700634 private native final int addAssetPathNative(String path, boolean appAsLib);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800635
Mårten Kongstad48d22322014-01-31 14:43:27 +0100636 /**
637 * Add a set of assets to overlay an already added set of assets.
638 *
639 * This is only intended for application resources. System wide resources
640 * are handled before any Java code is executed.
641 *
642 * {@hide}
643 */
Mårten Kongstad30113132014-11-07 10:52:17 +0100644
645 public final int addOverlayPath(String idmapPath) {
646 synchronized (this) {
647 int res = addOverlayPathNative(idmapPath);
648 makeStringBlocks(mStringBlocks);
649 return res;
650 }
651 }
652
653 /**
654 * See addOverlayPath.
655 *
656 * {@hide}
657 */
658 public native final int addOverlayPathNative(String idmapPath);
Mårten Kongstad48d22322014-01-31 14:43:27 +0100659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800660 /**
Kenny Root3a198332010-01-21 15:51:48 -0800661 * Add multiple sets of assets to the asset manager at once. See
662 * {@link #addAssetPath(String)} for more information. Returns array of
663 * cookies for each added asset with 0 indicating failure, or null if
664 * the input array of paths is null.
665 * {@hide}
666 */
667 public final int[] addAssetPaths(String[] paths) {
668 if (paths == null) {
669 return null;
670 }
671
672 int[] cookies = new int[paths.length];
673 for (int i = 0; i < paths.length; i++) {
674 cookies[i] = addAssetPath(paths[i]);
675 }
676
677 return cookies;
678 }
679
680 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 * Determine whether the state in this asset manager is up-to-date with
682 * the files on the filesystem. If false is returned, you need to
683 * instantiate a new AssetManager class to see the new data.
684 * {@hide}
685 */
686 public native final boolean isUpToDate();
687
688 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689 * Get the locales that this asset manager contains data for.
Narayan Kamath11bce122014-11-12 13:28:20 +0000690 *
691 * <p>On SDK 21 (Android 5.0: Lollipop) and above, Locale strings are valid
692 * <a href="https://tools.ietf.org/html/bcp47">BCP-47</a> language tags and can be
693 * parsed using {@link java.util.Locale#forLanguageTag(String)}.
694 *
695 * <p>On SDK 20 (Android 4.4W: Kitkat for watches) and below, locale strings
696 * are of the form {@code ll_CC} where {@code ll} is a two letter language code,
697 * and {@code CC} is a two letter country code.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800698 */
699 public native final String[] getLocales();
700
Roozbeh Pournader1c686f22015-12-18 14:22:14 -0800701 /**
702 * Same as getLocales(), except that locales that are only provided by the system (i.e. those
703 * present in framework-res.apk or its overlays) will not be listed.
704 *
705 * For example, if the "system" assets support English, French, and German, and the additional
706 * assets support Cherokee and French, getLocales() would return
707 * [Cherokee, English, French, German], while getNonSystemLocales() would return
708 * [Cherokee, French].
709 * {@hide}
710 */
711 public native final String[] getNonSystemLocales();
712
Filip Gruszczynski23493322015-07-29 17:02:59 -0700713 /** {@hide} */
714 public native final Configuration[] getSizeConfigurations();
715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 /**
717 * Change the configuation used when retrieving resources. Not for use by
718 * applications.
719 * {@hide}
720 */
721 public native final void setConfiguration(int mcc, int mnc, String locale,
722 int orientation, int touchscreen, int density, int keyboard,
723 int keyboardHidden, int navigation, int screenWidth, int screenHeight,
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700724 int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp,
725 int screenLayout, int uiMode, int majorVersion);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800726
727 /**
728 * Retrieve the resource identifier for the given resource name.
729 */
730 /*package*/ native final int getResourceIdentifier(String type,
731 String name,
732 String defPackage);
733
734 /*package*/ native final String getResourceName(int resid);
735 /*package*/ native final String getResourcePackageName(int resid);
736 /*package*/ native final String getResourceTypeName(int resid);
737 /*package*/ native final String getResourceEntryName(int resid);
738
Ashok Bhat896043d2014-01-17 16:02:38 +0000739 private native final long openAsset(String fileName, int accessMode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800740 private final native ParcelFileDescriptor openAssetFd(String fileName,
741 long[] outOffsets) throws IOException;
Ashok Bhat896043d2014-01-17 16:02:38 +0000742 private native final long openNonAssetNative(int cookie, String fileName,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 int accessMode);
744 private native ParcelFileDescriptor openNonAssetFdNative(int cookie,
745 String fileName, long[] outOffsets) throws IOException;
Ashok Bhat896043d2014-01-17 16:02:38 +0000746 private native final void destroyAsset(long asset);
747 private native final int readAssetChar(long asset);
748 private native final int readAsset(long asset, byte[] b, int off, int len);
749 private native final long seekAsset(long asset, long offset, int whence);
750 private native final long getAssetLength(long asset);
751 private native final long getAssetRemainingLength(long asset);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752
753 /** Returns true if the resource was found, filling in mRetStringBlock and
754 * mRetData. */
Kenny Root55fc8502010-10-28 14:47:01 -0700755 private native final int loadResourceValue(int ident, short density, TypedValue outValue,
756 boolean resolve);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800757 /** Returns true if the resource was found, filling in mRetStringBlock and
758 * mRetData. */
759 private native final int loadResourceBagValue(int ident, int bagEntryId, TypedValue outValue,
760 boolean resolve);
Dianne Hackborn0d221012009-07-29 15:41:19 -0700761 /*package*/ static final int STYLE_NUM_ENTRIES = 6;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800762 /*package*/ static final int STYLE_TYPE = 0;
763 /*package*/ static final int STYLE_DATA = 1;
764 /*package*/ static final int STYLE_ASSET_COOKIE = 2;
765 /*package*/ static final int STYLE_RESOURCE_ID = 3;
766 /*package*/ static final int STYLE_CHANGING_CONFIGURATIONS = 4;
Dianne Hackborn0d221012009-07-29 15:41:19 -0700767 /*package*/ static final int STYLE_DENSITY = 5;
Ashok Bhat896043d2014-01-17 16:02:38 +0000768 /*package*/ native static final boolean applyStyle(long theme,
769 int defStyleAttr, int defStyleRes, long xmlParser,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770 int[] inAttrs, int[] outValues, int[] outIndices);
Alan Viverette52b999f2014-03-24 18:00:26 -0700771 /*package*/ native static final boolean resolveAttrs(long theme,
772 int defStyleAttr, int defStyleRes, int[] inValues,
773 int[] inAttrs, int[] outValues, int[] outIndices);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774 /*package*/ native final boolean retrieveAttributes(
Ashok Bhat896043d2014-01-17 16:02:38 +0000775 long xmlParser, int[] inAttrs, int[] outValues, int[] outIndices);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 /*package*/ native final int getArraySize(int resource);
777 /*package*/ native final int retrieveArray(int resource, int[] outValues);
778 private native final int getStringBlockCount();
Ashok Bhat896043d2014-01-17 16:02:38 +0000779 private native final long getNativeStringBlock(int block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780
781 /**
782 * {@hide}
783 */
784 public native final String getCookieName(int cookie);
785
786 /**
787 * {@hide}
788 */
Adam Lesinskide898ff2014-01-29 18:20:45 -0800789 public native final SparseArray<String> getAssignedPackageIdentifiers();
790
791 /**
792 * {@hide}
793 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800794 public native static final int getGlobalAssetCount();
795
796 /**
797 * {@hide}
798 */
Dianne Hackborn82e1ee92009-08-11 18:56:41 -0700799 public native static final String getAssetAllocations();
800
801 /**
802 * {@hide}
803 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800804 public native static final int getGlobalAssetManagerCount();
805
Ashok Bhat896043d2014-01-17 16:02:38 +0000806 private native final long newTheme();
807 private native final void deleteTheme(long theme);
808 /*package*/ native static final void applyThemeStyle(long theme, int styleRes, boolean force);
809 /*package*/ native static final void copyTheme(long dest, long source);
Alan Viverettee54d2452015-05-06 10:41:43 -0700810 /*package*/ native static final void clearTheme(long theme);
Ashok Bhat896043d2014-01-17 16:02:38 +0000811 /*package*/ native static final int loadThemeAttributeValue(long theme, int ident,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812 TypedValue outValue,
813 boolean resolve);
Ashok Bhat896043d2014-01-17 16:02:38 +0000814 /*package*/ native static final void dumpTheme(long theme, int priority, String tag, String prefix);
Alan Viverettec1d52792015-05-05 09:49:03 -0700815 /*package*/ native static final int getThemeChangingConfigurations(long theme);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816
Ashok Bhat896043d2014-01-17 16:02:38 +0000817 private native final long openXmlAssetNative(int cookie, String fileName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800818
819 private native final String[] getArrayStringResource(int arrayRes);
820 private native final int[] getArrayStringInfo(int arrayRes);
821 /*package*/ native final int[] getArrayIntResource(int arrayRes);
Jon Miranda042ad632014-09-03 17:57:35 -0700822 /*package*/ native final int[] getStyleAttributes(int themeRes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800823
Mårten Kongstad48d22322014-01-31 14:43:27 +0100824 private native final void init(boolean isSystem);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800825 private native final void destroy();
826
Ashok Bhat896043d2014-01-17 16:02:38 +0000827 private final void incRefsLocked(long id) {
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -0800828 if (DEBUG_REFS) {
829 if (mRefStacks == null) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000830 mRefStacks = new HashMap<Long, RuntimeException>();
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -0800831 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000832 RuntimeException ex = new RuntimeException();
833 ex.fillInStackTrace();
834 mRefStacks.put(id, ex);
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -0800835 }
836 mNumRefs++;
837 }
838
Ashok Bhat896043d2014-01-17 16:02:38 +0000839 private final void decRefsLocked(long id) {
Dianne Hackbornc3b91fd2010-02-23 17:25:30 -0800840 if (DEBUG_REFS && mRefStacks != null) {
841 mRefStacks.remove(id);
842 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800843 mNumRefs--;
844 //System.out.println("Dec streams: mNumRefs=" + mNumRefs
845 // + " mReleased=" + mReleased);
846 if (mNumRefs == 0) {
847 destroy();
848 }
849 }
850}