blob: 7a2d020c13fc0702c70ae0dc0eda48639ecca619 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/* //device/libs/android_runtime/android_util_AssetManager.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#define LOG_TAG "asset"
19
Dianne Hackbornb8d81672009-11-20 14:26:42 -080020#define DEBUG_STYLES(x) //x
Dianne Hackborn20cb56e2010-03-04 00:58:29 -080021#define THROW_ON_BAD_ID 0
Dianne Hackbornb8d81672009-11-20 14:26:42 -080022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023#include <android_runtime/android_util_AssetManager.h>
24
25#include "jni.h"
26#include "JNIHelp.h"
27#include "android_util_Binder.h"
28#include <utils/misc.h>
29#include <android_runtime/AndroidRuntime.h>
30#include <utils/Log.h>
31
32#include <utils/Asset.h>
33#include <utils/AssetManager.h>
34#include <utils/ResourceTypes.h>
35
36#include <stdio.h>
37
38namespace android {
39
40// ----------------------------------------------------------------------------
41
42static struct typedvalue_offsets_t
43{
44 jfieldID mType;
45 jfieldID mData;
46 jfieldID mString;
47 jfieldID mAssetCookie;
48 jfieldID mResourceId;
49 jfieldID mChangingConfigurations;
50 jfieldID mDensity;
51} gTypedValueOffsets;
52
53static struct assetfiledescriptor_offsets_t
54{
55 jfieldID mFd;
56 jfieldID mStartOffset;
57 jfieldID mLength;
58} gAssetFileDescriptorOffsets;
59
60static struct assetmanager_offsets_t
61{
62 jfieldID mObject;
63} gAssetManagerOffsets;
64
65jclass g_stringClass = NULL;
66
67// ----------------------------------------------------------------------------
68
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069enum {
Dianne Hackborn0d221012009-07-29 15:41:19 -070070 STYLE_NUM_ENTRIES = 6,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071 STYLE_TYPE = 0,
72 STYLE_DATA = 1,
73 STYLE_ASSET_COOKIE = 2,
74 STYLE_RESOURCE_ID = 3,
Dianne Hackborn0d221012009-07-29 15:41:19 -070075 STYLE_CHANGING_CONFIGURATIONS = 4,
76 STYLE_DENSITY = 5
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077};
78
79static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
80 const Res_value& value, uint32_t ref, ssize_t block,
81 uint32_t typeSpecFlags, ResTable_config* config = NULL);
82
83jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
84 const Res_value& value, uint32_t ref, ssize_t block,
85 uint32_t typeSpecFlags, ResTable_config* config)
86{
87 env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
88 env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
89 (jint)table->getTableCookie(block));
90 env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
91 env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
92 env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
93 env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
94 typeSpecFlags);
95 if (config != NULL) {
96 env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
97 }
98 return block;
99}
100
101// ----------------------------------------------------------------------------
102
103// this guy is exported to other jni routines
104AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
105{
106 AssetManager* am = (AssetManager*)env->GetIntField(obj, gAssetManagerOffsets.mObject);
107 if (am != NULL) {
108 return am;
109 }
110 jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
111 return NULL;
112}
113
114static jint android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
115 jstring fileName, jint mode)
116{
117 AssetManager* am = assetManagerForJavaObject(env, clazz);
118 if (am == NULL) {
119 return 0;
120 }
121
122 LOGV("openAsset in %p (Java object %p)\n", am, clazz);
123
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700124 if (fileName == NULL) {
125 jniThrowException(env, "java/lang/NullPointerException", "fileName");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126 return -1;
127 }
128
129 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
130 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700131 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 return -1;
133 }
134
135 const char* fileName8 = env->GetStringUTFChars(fileName, NULL);
136 Asset* a = am->open(fileName8, (Asset::AccessMode)mode);
137
138 if (a == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700139 jniThrowException(env, "java/io/FileNotFoundException", fileName8);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 env->ReleaseStringUTFChars(fileName, fileName8);
141 return -1;
142 }
143 env->ReleaseStringUTFChars(fileName, fileName8);
144
145 //printf("Created Asset Stream: %p\n", a);
146
147 return (jint)a;
148}
149
150static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
151{
Kenny Rootddb76c42010-11-24 12:56:06 -0800152 off64_t startOffset, length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 int fd = a->openFileDescriptor(&startOffset, &length);
154 delete a;
155
156 if (fd < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700157 jniThrowException(env, "java/io/FileNotFoundException",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 "This file can not be opened as a file descriptor; it is probably compressed");
159 return NULL;
160 }
161
162 jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
163 if (offsets == NULL) {
164 close(fd);
165 return NULL;
166 }
167
168 offsets[0] = startOffset;
169 offsets[1] = length;
170
171 env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
172
173 jobject fileDesc = newFileDescriptor(env, fd);
174 if (fileDesc == NULL) {
175 close(fd);
176 return NULL;
177 }
178
179 return newParcelFileDescriptor(env, fileDesc);
180}
181
182static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
183 jstring fileName, jlongArray outOffsets)
184{
185 AssetManager* am = assetManagerForJavaObject(env, clazz);
186 if (am == NULL) {
187 return NULL;
188 }
189
190 LOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
191
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700192 if (fileName == NULL) {
193 jniThrowException(env, "java/lang/NullPointerException", "fileName");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 return NULL;
195 }
196
197 const char* fileName8 = env->GetStringUTFChars(fileName, NULL);
198 Asset* a = am->open(fileName8, Asset::ACCESS_RANDOM);
199
200 if (a == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700201 jniThrowException(env, "java/io/FileNotFoundException", fileName8);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 env->ReleaseStringUTFChars(fileName, fileName8);
203 return NULL;
204 }
205 env->ReleaseStringUTFChars(fileName, fileName8);
206
207 //printf("Created Asset Stream: %p\n", a);
208
209 return returnParcelFileDescriptor(env, a, outOffsets);
210}
211
212static jint android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
213 jint cookie,
214 jstring fileName,
215 jint mode)
216{
217 AssetManager* am = assetManagerForJavaObject(env, clazz);
218 if (am == NULL) {
219 return 0;
220 }
221
222 LOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
223
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700224 if (fileName == NULL) {
225 jniThrowException(env, "java/lang/NullPointerException", "fileName");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 return -1;
227 }
228
229 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
230 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700231 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 return -1;
233 }
234
235 const char* fileName8 = env->GetStringUTFChars(fileName, NULL);
236 Asset* a = cookie
237 ? am->openNonAsset((void*)cookie, fileName8, (Asset::AccessMode)mode)
238 : am->openNonAsset(fileName8, (Asset::AccessMode)mode);
239
240 if (a == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700241 jniThrowException(env, "java/io/FileNotFoundException", fileName8);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242 env->ReleaseStringUTFChars(fileName, fileName8);
243 return -1;
244 }
245 env->ReleaseStringUTFChars(fileName, fileName8);
246
247 //printf("Created Asset Stream: %p\n", a);
248
249 return (jint)a;
250}
251
252static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
253 jint cookie,
254 jstring fileName,
255 jlongArray outOffsets)
256{
257 AssetManager* am = assetManagerForJavaObject(env, clazz);
258 if (am == NULL) {
259 return NULL;
260 }
261
262 LOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
263
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700264 if (fileName == NULL ) {
265 jniThrowException(env, "java/lang/NullPointerException", "fileName");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 return NULL;
267 }
268
269 const char* fileName8 = env->GetStringUTFChars(fileName, NULL);
270 Asset* a = cookie
271 ? am->openNonAsset((void*)cookie, fileName8, Asset::ACCESS_RANDOM)
272 : am->openNonAsset(fileName8, Asset::ACCESS_RANDOM);
273
274 if (a == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700275 jniThrowException(env, "java/io/FileNotFoundException", fileName8);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 env->ReleaseStringUTFChars(fileName, fileName8);
277 return NULL;
278 }
279 env->ReleaseStringUTFChars(fileName, fileName8);
280
281 //printf("Created Asset Stream: %p\n", a);
282
283 return returnParcelFileDescriptor(env, a, outOffsets);
284}
285
286static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
287 jstring fileName)
288{
289 AssetManager* am = assetManagerForJavaObject(env, clazz);
290 if (am == NULL) {
291 return NULL;
292 }
293
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700294 if (fileName == NULL) {
295 jniThrowException(env, "java/lang/NullPointerException", "fileName");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296 return NULL;
297 }
298
299 const char* fileName8 = env->GetStringUTFChars(fileName, NULL);
300
301 AssetDir* dir = am->openDir(fileName8);
302
303 env->ReleaseStringUTFChars(fileName, fileName8);
304
305 if (dir == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700306 jniThrowException(env, "java/io/FileNotFoundException", fileName8);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 return NULL;
308 }
309
310 jclass cls = env->FindClass("java/lang/String");
311 LOG_FATAL_IF(cls == NULL, "No string class?!?");
312 if (cls == NULL) {
313 delete dir;
314 return NULL;
315 }
316
317 size_t N = dir->getFileCount();
318
319 jobjectArray array = env->NewObjectArray(dir->getFileCount(),
320 cls, NULL);
321 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322 delete dir;
323 return NULL;
324 }
325
326 for (size_t i=0; i<N; i++) {
327 const String8& name = dir->getFileName(i);
328 jstring str = env->NewStringUTF(name.string());
329 if (str == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 delete dir;
331 return NULL;
332 }
333 env->SetObjectArrayElement(array, i, str);
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700334 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800335 }
336
337 delete dir;
338
339 return array;
340}
341
342static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
343 jint asset)
344{
345 Asset* a = (Asset*)asset;
346
347 //printf("Destroying Asset Stream: %p\n", a);
348
349 if (a == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700350 jniThrowException(env, "java/lang/NullPointerException", "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351 return;
352 }
353
354 delete a;
355}
356
357static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
358 jint asset)
359{
360 Asset* a = (Asset*)asset;
361
362 if (a == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700363 jniThrowException(env, "java/lang/NullPointerException", "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364 return -1;
365 }
366
367 uint8_t b;
368 ssize_t res = a->read(&b, 1);
369 return res == 1 ? b : -1;
370}
371
372static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
373 jint asset, jbyteArray bArray,
374 jint off, jint len)
375{
376 Asset* a = (Asset*)asset;
377
378 if (a == NULL || bArray == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700379 jniThrowException(env, "java/lang/NullPointerException", "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800380 return -1;
381 }
382
383 if (len == 0) {
384 return 0;
385 }
386
387 jsize bLen = env->GetArrayLength(bArray);
388 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700389 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390 return -1;
391 }
392
393 jbyte* b = env->GetByteArrayElements(bArray, NULL);
394 ssize_t res = a->read(b+off, len);
395 env->ReleaseByteArrayElements(bArray, b, 0);
396
397 if (res > 0) return res;
398
399 if (res < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700400 jniThrowException(env, "java/io/IOException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401 }
402 return -1;
403}
404
405static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
406 jint asset,
407 jlong offset, jint whence)
408{
409 Asset* a = (Asset*)asset;
410
411 if (a == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700412 jniThrowException(env, "java/lang/NullPointerException", "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800413 return -1;
414 }
415
416 return a->seek(
417 offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
418}
419
420static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
421 jint asset)
422{
423 Asset* a = (Asset*)asset;
424
425 if (a == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700426 jniThrowException(env, "java/lang/NullPointerException", "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800427 return -1;
428 }
429
430 return a->getLength();
431}
432
433static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
434 jint asset)
435{
436 Asset* a = (Asset*)asset;
437
438 if (a == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700439 jniThrowException(env, "java/lang/NullPointerException", "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 return -1;
441 }
442
443 return a->getRemainingLength();
444}
445
446static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
447 jstring path)
448{
449 if (path == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700450 jniThrowException(env, "java/lang/NullPointerException", "path");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800451 return JNI_FALSE;
452 }
453
454 AssetManager* am = assetManagerForJavaObject(env, clazz);
455 if (am == NULL) {
456 return JNI_FALSE;
457 }
458
459 const char* path8 = env->GetStringUTFChars(path, NULL);
460
461 void* cookie;
462 bool res = am->addAssetPath(String8(path8), &cookie);
463
464 env->ReleaseStringUTFChars(path, path8);
465
466 return (res) ? (jint)cookie : 0;
467}
468
469static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
470{
471 AssetManager* am = assetManagerForJavaObject(env, clazz);
472 if (am == NULL) {
473 return JNI_TRUE;
474 }
475 return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
476}
477
478static void android_content_AssetManager_setLocale(JNIEnv* env, jobject clazz,
479 jstring locale)
480{
481 if (locale == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700482 jniThrowException(env, "java/lang/NullPointerException", "locale");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800483 return;
484 }
485
486 const char* locale8 = env->GetStringUTFChars(locale, NULL);
487
488 AssetManager* am = assetManagerForJavaObject(env, clazz);
489 if (am == NULL) {
490 return;
491 }
492
493 am->setLocale(locale8);
494
495 env->ReleaseStringUTFChars(locale, locale8);
496}
497
498static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
499{
500 Vector<String8> locales;
501
502 AssetManager* am = assetManagerForJavaObject(env, clazz);
503 if (am == NULL) {
504 return NULL;
505 }
506
507 am->getLocales(&locales);
508
509 const int N = locales.size();
510
511 jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
512 if (result == NULL) {
513 return NULL;
514 }
515
516 for (int i=0; i<N; i++) {
Gilles Debunne0db187a2010-08-27 11:51:34 -0700517 jstring str = env->NewStringUTF(locales[i].string());
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700518 if (str == NULL) {
519 return NULL;
520 }
521 env->SetObjectArrayElement(result, i, str);
522 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523 }
524
525 return result;
526}
527
528static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
529 jint mcc, jint mnc,
530 jstring locale, jint orientation,
531 jint touchscreen, jint density,
532 jint keyboard, jint keyboardHidden,
533 jint navigation,
534 jint screenWidth, jint screenHeight,
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700535 jint screenWidthDp, jint screenHeightDp,
Tobias Haamel27b28b32010-02-09 23:09:17 +0100536 jint screenLayout, jint uiMode,
537 jint sdkVersion)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538{
539 AssetManager* am = assetManagerForJavaObject(env, clazz);
540 if (am == NULL) {
541 return;
542 }
543
544 ResTable_config config;
545 memset(&config, 0, sizeof(config));
546
547 const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
548
549 config.mcc = (uint16_t)mcc;
550 config.mnc = (uint16_t)mnc;
551 config.orientation = (uint8_t)orientation;
552 config.touchscreen = (uint8_t)touchscreen;
553 config.density = (uint16_t)density;
554 config.keyboard = (uint8_t)keyboard;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700555 config.inputFlags = (uint8_t)keyboardHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 config.navigation = (uint8_t)navigation;
557 config.screenWidth = (uint16_t)screenWidth;
558 config.screenHeight = (uint16_t)screenHeight;
Dianne Hackbornebff8f92011-05-12 18:07:47 -0700559 config.screenWidthDp = (uint16_t)screenWidthDp;
560 config.screenHeightDp = (uint16_t)screenHeightDp;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700561 config.screenLayout = (uint8_t)screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100562 config.uiMode = (uint8_t)uiMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563 config.sdkVersion = (uint16_t)sdkVersion;
564 config.minorVersion = 0;
565 am->setConfiguration(config, locale8);
566
567 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
568}
569
570static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
571 jstring name,
572 jstring defType,
573 jstring defPackage)
574{
575 if (name == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700576 jniThrowException(env, "java/lang/NullPointerException", "name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577 return 0;
578 }
579
580 AssetManager* am = assetManagerForJavaObject(env, clazz);
581 if (am == NULL) {
582 return 0;
583 }
584
585 const char16_t* name16 = env->GetStringChars(name, NULL);
586 jsize nameLen = env->GetStringLength(name);
587 const char16_t* defType16 = defType
588 ? env->GetStringChars(defType, NULL) : NULL;
589 jsize defTypeLen = defType
590 ? env->GetStringLength(defType) : 0;
591 const char16_t* defPackage16 = defPackage
592 ? env->GetStringChars(defPackage, NULL) : NULL;
593 jsize defPackageLen = defPackage
594 ? env->GetStringLength(defPackage) : 0;
595
596 jint ident = am->getResources().identifierForName(
597 name16, nameLen, defType16, defTypeLen, defPackage16, defPackageLen);
598
599 if (defPackage16) {
600 env->ReleaseStringChars(defPackage, defPackage16);
601 }
602 if (defType16) {
603 env->ReleaseStringChars(defType, defType16);
604 }
605 env->ReleaseStringChars(name, name16);
606
607 return ident;
608}
609
610static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
611 jint resid)
612{
613 AssetManager* am = assetManagerForJavaObject(env, clazz);
614 if (am == NULL) {
615 return NULL;
616 }
617
618 ResTable::resource_name name;
619 if (!am->getResources().getResourceName(resid, &name)) {
620 return NULL;
621 }
622
623 String16 str;
624 if (name.package != NULL) {
625 str.setTo(name.package, name.packageLen);
626 }
627 if (name.type != NULL) {
628 if (str.size() > 0) {
629 char16_t div = ':';
630 str.append(&div, 1);
631 }
632 str.append(name.type, name.typeLen);
633 }
634 if (name.name != NULL) {
635 if (str.size() > 0) {
636 char16_t div = '/';
637 str.append(&div, 1);
638 }
639 str.append(name.name, name.nameLen);
640 }
641
642 return env->NewString((const jchar*)str.string(), str.size());
643}
644
645static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
646 jint resid)
647{
648 AssetManager* am = assetManagerForJavaObject(env, clazz);
649 if (am == NULL) {
650 return NULL;
651 }
652
653 ResTable::resource_name name;
654 if (!am->getResources().getResourceName(resid, &name)) {
655 return NULL;
656 }
657
658 if (name.package != NULL) {
659 return env->NewString((const jchar*)name.package, name.packageLen);
660 }
661
662 return NULL;
663}
664
665static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
666 jint resid)
667{
668 AssetManager* am = assetManagerForJavaObject(env, clazz);
669 if (am == NULL) {
670 return NULL;
671 }
672
673 ResTable::resource_name name;
674 if (!am->getResources().getResourceName(resid, &name)) {
675 return NULL;
676 }
677
678 if (name.type != NULL) {
679 return env->NewString((const jchar*)name.type, name.typeLen);
680 }
681
682 return NULL;
683}
684
685static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
686 jint resid)
687{
688 AssetManager* am = assetManagerForJavaObject(env, clazz);
689 if (am == NULL) {
690 return NULL;
691 }
692
693 ResTable::resource_name name;
694 if (!am->getResources().getResourceName(resid, &name)) {
695 return NULL;
696 }
697
698 if (name.name != NULL) {
699 return env->NewString((const jchar*)name.name, name.nameLen);
700 }
701
702 return NULL;
703}
704
705static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
706 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700707 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708 jobject outValue,
709 jboolean resolve)
710{
711 AssetManager* am = assetManagerForJavaObject(env, clazz);
712 if (am == NULL) {
713 return 0;
714 }
715 const ResTable& res(am->getResources());
716
717 Res_value value;
718 ResTable_config config;
719 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700720 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800721#if THROW_ON_BAD_ID
722 if (block == BAD_INDEX) {
723 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
724 return 0;
725 }
726#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800727 uint32_t ref = ident;
728 if (resolve) {
729 block = res.resolveReference(&value, block, &ref);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800730#if THROW_ON_BAD_ID
731 if (block == BAD_INDEX) {
732 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
733 return 0;
734 }
735#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736 }
737 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config) : block;
738}
739
740static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
741 jint ident, jint bagEntryId,
742 jobject outValue, jboolean resolve)
743{
744 AssetManager* am = assetManagerForJavaObject(env, clazz);
745 if (am == NULL) {
746 return 0;
747 }
748 const ResTable& res(am->getResources());
749
750 // Now lock down the resource object and start pulling stuff from it.
751 res.lock();
752
753 ssize_t block = -1;
754 Res_value value;
755
756 const ResTable::bag_entry* entry = NULL;
757 uint32_t typeSpecFlags;
758 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
759
760 for (ssize_t i=0; i<entryCount; i++) {
761 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
762 block = entry->stringBlock;
763 value = entry->map.value;
764 }
765 entry++;
766 }
767
768 res.unlock();
769
770 if (block < 0) {
771 return block;
772 }
773
774 uint32_t ref = ident;
775 if (resolve) {
776 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800777#if THROW_ON_BAD_ID
778 if (block == BAD_INDEX) {
779 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
780 return 0;
781 }
782#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800783 }
784 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
785}
786
787static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
788{
789 AssetManager* am = assetManagerForJavaObject(env, clazz);
790 if (am == NULL) {
791 return 0;
792 }
793 return am->getResources().getTableCount();
794}
795
796static jint android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
797 jint block)
798{
799 AssetManager* am = assetManagerForJavaObject(env, clazz);
800 if (am == NULL) {
801 return 0;
802 }
803 return (jint)am->getResources().getTableStringBlock(block);
804}
805
806static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
807 jint cookie)
808{
809 AssetManager* am = assetManagerForJavaObject(env, clazz);
810 if (am == NULL) {
811 return NULL;
812 }
813 String8 name(am->getAssetPath((void*)cookie));
814 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700815 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800816 return NULL;
817 }
818 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 return str;
820}
821
822static jint android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
823{
824 AssetManager* am = assetManagerForJavaObject(env, clazz);
825 if (am == NULL) {
826 return 0;
827 }
828 return (jint)(new ResTable::Theme(am->getResources()));
829}
830
831static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
832 jint themeInt)
833{
834 ResTable::Theme* theme = (ResTable::Theme*)themeInt;
835 delete theme;
836}
837
838static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
839 jint themeInt,
840 jint styleRes,
841 jboolean force)
842{
843 ResTable::Theme* theme = (ResTable::Theme*)themeInt;
844 theme->applyStyle(styleRes, force ? true : false);
845}
846
847static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
848 jint destInt, jint srcInt)
849{
850 ResTable::Theme* dest = (ResTable::Theme*)destInt;
851 ResTable::Theme* src = (ResTable::Theme*)srcInt;
852 dest->setTo(*src);
853}
854
855static jint android_content_AssetManager_loadThemeAttributeValue(
856 JNIEnv* env, jobject clazz, jint themeInt, jint ident, jobject outValue, jboolean resolve)
857{
858 ResTable::Theme* theme = (ResTable::Theme*)themeInt;
859 const ResTable& res(theme->getResTable());
860
861 Res_value value;
862 // XXX value could be different in different configs!
863 uint32_t typeSpecFlags = 0;
864 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
865 uint32_t ref = 0;
866 if (resolve) {
867 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800868#if THROW_ON_BAD_ID
869 if (block == BAD_INDEX) {
870 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
871 return 0;
872 }
873#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 }
875 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
876}
877
878static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
879 jint themeInt, jint pri,
880 jstring tag, jstring prefix)
881{
882 ResTable::Theme* theme = (ResTable::Theme*)themeInt;
883 const ResTable& res(theme->getResTable());
884
885 if (tag == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700886 jniThrowException(env, "java/lang/NullPointerException", "tag");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800887 return;
888 }
889
890 const char* tag8 = env->GetStringUTFChars(tag, NULL);
891 const char* prefix8 = NULL;
892 if (prefix != NULL) {
893 prefix8 = env->GetStringUTFChars(prefix, NULL);
894 }
895
896 // XXX Need to use params.
897 theme->dumpToLog();
898
899 if (prefix8 != NULL) {
900 env->ReleaseStringUTFChars(prefix, prefix8);
901 }
902 env->ReleaseStringUTFChars(tag, tag8);
903}
904
905static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
906 jint themeToken,
907 jint defStyleAttr,
908 jint defStyleRes,
909 jint xmlParserToken,
910 jintArray attrs,
911 jintArray outValues,
912 jintArray outIndices)
913{
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700914 if (themeToken == 0) {
915 jniThrowException(env, "java/lang/NullPointerException", "theme token");
916 return JNI_FALSE;
917 }
918 if (attrs == NULL) {
919 jniThrowException(env, "java/lang/NullPointerException", "attrs");
920 return JNI_FALSE;
921 }
922 if (outValues == NULL) {
923 jniThrowException(env, "java/lang/NullPointerException", "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800924 return JNI_FALSE;
925 }
926
Dianne Hackbornb8d81672009-11-20 14:26:42 -0800927 DEBUG_STYLES(LOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x xml=0x%x",
928 themeToken, defStyleAttr, defStyleRes, xmlParserToken));
929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 ResTable::Theme* theme = (ResTable::Theme*)themeToken;
931 const ResTable& res = theme->getResTable();
932 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -0700933 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800934 Res_value value;
935
936 const jsize NI = env->GetArrayLength(attrs);
937 const jsize NV = env->GetArrayLength(outValues);
938 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700939 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800940 return JNI_FALSE;
941 }
942
943 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
944 if (src == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700945 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946 return JNI_FALSE;
947 }
948
949 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
950 jint* dest = baseDest;
951 if (dest == NULL) {
952 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700953 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 return JNI_FALSE;
955 }
956
957 jint* indices = NULL;
958 int indicesIdx = 0;
959 if (outIndices != NULL) {
960 if (env->GetArrayLength(outIndices) > NI) {
961 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
962 }
963 }
964
965 // Load default style from attribute, if specified...
966 uint32_t defStyleBagTypeSetFlags = 0;
967 if (defStyleAttr != 0) {
968 Res_value value;
969 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
970 if (value.dataType == Res_value::TYPE_REFERENCE) {
971 defStyleRes = value.data;
972 }
973 }
974 }
975
976 // Retrieve the style class associated with the current XML tag.
977 int style = 0;
978 uint32_t styleBagTypeSetFlags = 0;
979 if (xmlParser != NULL) {
980 ssize_t idx = xmlParser->indexOfStyle();
981 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
982 if (value.dataType == value.TYPE_ATTRIBUTE) {
983 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
984 value.dataType = Res_value::TYPE_NULL;
985 }
986 }
987 if (value.dataType == value.TYPE_REFERENCE) {
988 style = value.data;
989 }
990 }
991 }
992
993 // Now lock down the resource object and start pulling stuff from it.
994 res.lock();
995
996 // Retrieve the default style bag, if requested.
997 const ResTable::bag_entry* defStyleEnt = NULL;
998 uint32_t defStyleTypeSetFlags = 0;
999 ssize_t bagOff = defStyleRes != 0
1000 ? res.getBagLocked(defStyleRes, &defStyleEnt, &defStyleTypeSetFlags) : -1;
1001 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
1002 const ResTable::bag_entry* endDefStyleEnt = defStyleEnt +
1003 (bagOff >= 0 ? bagOff : 0);
1004
1005 // Retrieve the style class bag, if requested.
1006 const ResTable::bag_entry* styleEnt = NULL;
1007 uint32_t styleTypeSetFlags = 0;
1008 bagOff = style != 0 ? res.getBagLocked(style, &styleEnt, &styleTypeSetFlags) : -1;
1009 styleTypeSetFlags |= styleBagTypeSetFlags;
1010 const ResTable::bag_entry* endStyleEnt = styleEnt +
1011 (bagOff >= 0 ? bagOff : 0);
1012
1013 // Retrieve the XML attributes, if requested.
1014 const jsize NX = xmlParser ? xmlParser->getAttributeCount() : 0;
1015 jsize ix=0;
1016 uint32_t curXmlAttr = xmlParser ? xmlParser->getAttributeNameResID(ix) : 0;
1017
1018 static const ssize_t kXmlBlock = 0x10000000;
1019
1020 // Now iterate through all of the attributes that the client has requested,
1021 // filling in each with whatever data we can find.
1022 ssize_t block = 0;
1023 uint32_t typeSetFlags;
1024 for (jsize ii=0; ii<NI; ii++) {
1025 const uint32_t curIdent = (uint32_t)src[ii];
1026
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001027 DEBUG_STYLES(LOGI("RETRIEVING ATTR 0x%08x...", curIdent));
1028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029 // Try to find a value for this attribute... we prioritize values
1030 // coming from, first XML attributes, then XML style, then default
1031 // style, and finally the theme.
1032 value.dataType = Res_value::TYPE_NULL;
1033 value.data = 0;
1034 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001035 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001036
1037 // Skip through XML attributes until the end or the next possible match.
1038 while (ix < NX && curIdent > curXmlAttr) {
1039 ix++;
1040 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1041 }
1042 // Retrieve the current XML attribute if it matches, and step to next.
1043 if (ix < NX && curIdent == curXmlAttr) {
1044 block = kXmlBlock;
1045 xmlParser->getAttributeValue(ix, &value);
1046 ix++;
1047 curXmlAttr = xmlParser->getAttributeNameResID(ix);
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001048 DEBUG_STYLES(LOGI("-> From XML: type=0x%x, data=0x%08x",
1049 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001050 }
1051
1052 // Skip through the style values until the end or the next possible match.
1053 while (styleEnt < endStyleEnt && curIdent > styleEnt->map.name.ident) {
1054 styleEnt++;
1055 }
1056 // Retrieve the current style attribute if it matches, and step to next.
1057 if (styleEnt < endStyleEnt && curIdent == styleEnt->map.name.ident) {
1058 if (value.dataType == Res_value::TYPE_NULL) {
1059 block = styleEnt->stringBlock;
1060 typeSetFlags = styleTypeSetFlags;
1061 value = styleEnt->map.value;
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001062 DEBUG_STYLES(LOGI("-> From style: type=0x%x, data=0x%08x",
1063 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001064 }
1065 styleEnt++;
1066 }
1067
1068 // Skip through the default style values until the end or the next possible match.
1069 while (defStyleEnt < endDefStyleEnt && curIdent > defStyleEnt->map.name.ident) {
1070 defStyleEnt++;
1071 }
1072 // Retrieve the current default style attribute if it matches, and step to next.
1073 if (defStyleEnt < endDefStyleEnt && curIdent == defStyleEnt->map.name.ident) {
1074 if (value.dataType == Res_value::TYPE_NULL) {
1075 block = defStyleEnt->stringBlock;
1076 typeSetFlags = defStyleTypeSetFlags;
1077 value = defStyleEnt->map.value;
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001078 DEBUG_STYLES(LOGI("-> From def style: type=0x%x, data=0x%08x",
1079 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080 }
1081 defStyleEnt++;
1082 }
1083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 uint32_t resid = 0;
1085 if (value.dataType != Res_value::TYPE_NULL) {
1086 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001087 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1088 &resid, &typeSetFlags, &config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 if (newBlock >= 0) block = newBlock;
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001090 DEBUG_STYLES(LOGI("-> Resolved attr: type=0x%x, data=0x%08x",
1091 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 } else {
1093 // If we still don't have a value for this attribute, try to find
1094 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001095 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1096 if (newBlock >= 0) {
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001097 DEBUG_STYLES(LOGI("-> From theme: type=0x%x, data=0x%08x",
1098 value.dataType, value.data));
Dianne Hackborn0d221012009-07-29 15:41:19 -07001099 newBlock = res.resolveReference(&value, block, &resid,
1100 &typeSetFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001101#if THROW_ON_BAD_ID
1102 if (newBlock == BAD_INDEX) {
1103 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1104 return JNI_FALSE;
1105 }
1106#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 if (newBlock >= 0) block = newBlock;
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001108 DEBUG_STYLES(LOGI("-> Resolved theme: type=0x%x, data=0x%08x",
1109 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001110 }
1111 }
1112
1113 // Deal with the special @null value -- it turns back to TYPE_NULL.
1114 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001115 DEBUG_STYLES(LOGI("-> Setting to @null!"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116 value.dataType = Res_value::TYPE_NULL;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001117 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001118 }
1119
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001120 DEBUG_STYLES(LOGI("Attribute 0x%08x: type=0x%x, data=0x%08x",
1121 curIdent, value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122
1123 // Write the final value back to Java.
1124 dest[STYLE_TYPE] = value.dataType;
1125 dest[STYLE_DATA] = value.data;
1126 dest[STYLE_ASSET_COOKIE] =
1127 block != kXmlBlock ? (jint)res.getTableCookie(block) : (jint)-1;
1128 dest[STYLE_RESOURCE_ID] = resid;
1129 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001130 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131
1132 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1133 indicesIdx++;
1134 indices[indicesIdx] = ii;
1135 }
1136
1137 dest += STYLE_NUM_ENTRIES;
1138 }
1139
1140 res.unlock();
1141
1142 if (indices != NULL) {
1143 indices[0] = indicesIdx;
1144 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1145 }
1146 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1147 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1148
1149 return JNI_TRUE;
1150}
1151
1152static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
1153 jint xmlParserToken,
1154 jintArray attrs,
1155 jintArray outValues,
1156 jintArray outIndices)
1157{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001158 if (xmlParserToken == 0) {
1159 jniThrowException(env, "java/lang/NullPointerException", "xmlParserToken");
1160 return JNI_FALSE;
1161 }
1162 if (attrs == NULL) {
1163 jniThrowException(env, "java/lang/NullPointerException", "attrs");
1164 return JNI_FALSE;
1165 }
1166 if (outValues == NULL) {
1167 jniThrowException(env, "java/lang/NullPointerException", "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001168 return JNI_FALSE;
1169 }
1170
1171 AssetManager* am = assetManagerForJavaObject(env, clazz);
1172 if (am == NULL) {
1173 return JNI_FALSE;
1174 }
1175 const ResTable& res(am->getResources());
1176 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001177 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001178 Res_value value;
1179
1180 const jsize NI = env->GetArrayLength(attrs);
1181 const jsize NV = env->GetArrayLength(outValues);
1182 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001183 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001184 return JNI_FALSE;
1185 }
1186
1187 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1188 if (src == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001189 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 return JNI_FALSE;
1191 }
1192
1193 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1194 jint* dest = baseDest;
1195 if (dest == NULL) {
1196 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001197 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001198 return JNI_FALSE;
1199 }
1200
1201 jint* indices = NULL;
1202 int indicesIdx = 0;
1203 if (outIndices != NULL) {
1204 if (env->GetArrayLength(outIndices) > NI) {
1205 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1206 }
1207 }
1208
1209 // Now lock down the resource object and start pulling stuff from it.
1210 res.lock();
1211
1212 // Retrieve the XML attributes, if requested.
1213 const jsize NX = xmlParser->getAttributeCount();
1214 jsize ix=0;
1215 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
1216
1217 static const ssize_t kXmlBlock = 0x10000000;
1218
1219 // Now iterate through all of the attributes that the client has requested,
1220 // filling in each with whatever data we can find.
1221 ssize_t block = 0;
1222 uint32_t typeSetFlags;
1223 for (jsize ii=0; ii<NI; ii++) {
1224 const uint32_t curIdent = (uint32_t)src[ii];
1225
1226 // Try to find a value for this attribute...
1227 value.dataType = Res_value::TYPE_NULL;
1228 value.data = 0;
1229 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001230 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231
1232 // Skip through XML attributes until the end or the next possible match.
1233 while (ix < NX && curIdent > curXmlAttr) {
1234 ix++;
1235 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1236 }
1237 // Retrieve the current XML attribute if it matches, and step to next.
1238 if (ix < NX && curIdent == curXmlAttr) {
1239 block = kXmlBlock;
1240 xmlParser->getAttributeValue(ix, &value);
1241 ix++;
1242 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1243 }
1244
1245 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1246 uint32_t resid = 0;
1247 if (value.dataType != Res_value::TYPE_NULL) {
1248 // Take care of resolving the found resource to its final value.
1249 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001250 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1251 &typeSetFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001252#if THROW_ON_BAD_ID
1253 if (newBlock == BAD_INDEX) {
1254 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1255 return JNI_FALSE;
1256 }
1257#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001258 if (newBlock >= 0) block = newBlock;
1259 }
1260
1261 // Deal with the special @null value -- it turns back to TYPE_NULL.
1262 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1263 value.dataType = Res_value::TYPE_NULL;
1264 }
1265
1266 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1267
1268 // Write the final value back to Java.
1269 dest[STYLE_TYPE] = value.dataType;
1270 dest[STYLE_DATA] = value.data;
1271 dest[STYLE_ASSET_COOKIE] =
1272 block != kXmlBlock ? (jint)res.getTableCookie(block) : (jint)-1;
1273 dest[STYLE_RESOURCE_ID] = resid;
1274 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001275 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001276
1277 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1278 indicesIdx++;
1279 indices[indicesIdx] = ii;
1280 }
1281
1282 dest += STYLE_NUM_ENTRIES;
1283 }
1284
1285 res.unlock();
1286
1287 if (indices != NULL) {
1288 indices[0] = indicesIdx;
1289 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1290 }
1291
1292 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1293 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1294
1295 return JNI_TRUE;
1296}
1297
1298static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1299 jint id)
1300{
1301 AssetManager* am = assetManagerForJavaObject(env, clazz);
1302 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001303 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001304 }
1305 const ResTable& res(am->getResources());
1306
1307 res.lock();
1308 const ResTable::bag_entry* defStyleEnt = NULL;
1309 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1310 res.unlock();
1311
1312 return bagOff;
1313}
1314
1315static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1316 jint id,
1317 jintArray outValues)
1318{
1319 if (outValues == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001320 jniThrowException(env, "java/lang/NullPointerException", "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001321 return JNI_FALSE;
1322 }
1323
1324 AssetManager* am = assetManagerForJavaObject(env, clazz);
1325 if (am == NULL) {
1326 return JNI_FALSE;
1327 }
1328 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001329 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 Res_value value;
1331 ssize_t block;
1332
1333 const jsize NV = env->GetArrayLength(outValues);
1334
1335 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1336 jint* dest = baseDest;
1337 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001338 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001339 return JNI_FALSE;
1340 }
1341
1342 // Now lock down the resource object and start pulling stuff from it.
1343 res.lock();
1344
1345 const ResTable::bag_entry* arrayEnt = NULL;
1346 uint32_t arrayTypeSetFlags = 0;
1347 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1348 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1349 (bagOff >= 0 ? bagOff : 0);
1350
1351 int i = 0;
1352 uint32_t typeSetFlags;
1353 while (i < NV && arrayEnt < endArrayEnt) {
1354 block = arrayEnt->stringBlock;
1355 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001356 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001357 value = arrayEnt->map.value;
1358
1359 uint32_t resid = 0;
1360 if (value.dataType != Res_value::TYPE_NULL) {
1361 // Take care of resolving the found resource to its final value.
1362 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001363 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1364 &typeSetFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001365#if THROW_ON_BAD_ID
1366 if (newBlock == BAD_INDEX) {
1367 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1368 return JNI_FALSE;
1369 }
1370#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001371 if (newBlock >= 0) block = newBlock;
1372 }
1373
1374 // Deal with the special @null value -- it turns back to TYPE_NULL.
1375 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1376 value.dataType = Res_value::TYPE_NULL;
1377 }
1378
1379 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1380
1381 // Write the final value back to Java.
1382 dest[STYLE_TYPE] = value.dataType;
1383 dest[STYLE_DATA] = value.data;
1384 dest[STYLE_ASSET_COOKIE] = (jint)res.getTableCookie(block);
1385 dest[STYLE_RESOURCE_ID] = resid;
1386 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001387 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001388 dest += STYLE_NUM_ENTRIES;
1389 i+= STYLE_NUM_ENTRIES;
1390 arrayEnt++;
1391 }
1392
1393 i /= STYLE_NUM_ENTRIES;
1394
1395 res.unlock();
1396
1397 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1398
1399 return i;
1400}
1401
1402static jint android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
1403 jint cookie,
1404 jstring fileName)
1405{
1406 AssetManager* am = assetManagerForJavaObject(env, clazz);
1407 if (am == NULL) {
1408 return 0;
1409 }
1410
1411 LOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
1412
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001413 if (fileName == NULL) {
1414 jniThrowException(env, "java/lang/NullPointerException", "fileName");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001415 return 0;
1416 }
1417
1418 const char* fileName8 = env->GetStringUTFChars(fileName, NULL);
1419 Asset* a = cookie
1420 ? am->openNonAsset((void*)cookie, fileName8, Asset::ACCESS_BUFFER)
1421 : am->openNonAsset(fileName8, Asset::ACCESS_BUFFER);
1422
1423 if (a == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001424 jniThrowException(env, "java/io/FileNotFoundException", fileName8);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001425 env->ReleaseStringUTFChars(fileName, fileName8);
1426 return 0;
1427 }
1428 env->ReleaseStringUTFChars(fileName, fileName8);
1429
1430 ResXMLTree* block = new ResXMLTree();
1431 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1432 a->close();
1433 delete a;
1434
1435 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001436 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437 return 0;
1438 }
1439
1440 return (jint)block;
1441}
1442
1443static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1444 jint arrayResId)
1445{
1446 AssetManager* am = assetManagerForJavaObject(env, clazz);
1447 if (am == NULL) {
1448 return NULL;
1449 }
1450 const ResTable& res(am->getResources());
1451
1452 const ResTable::bag_entry* startOfBag;
1453 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1454 if (N < 0) {
1455 return NULL;
1456 }
1457
1458 jintArray array = env->NewIntArray(N * 2);
1459 if (array == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001460 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 res.unlockBag(startOfBag);
1462 return NULL;
1463 }
1464
1465 Res_value value;
1466 const ResTable::bag_entry* bag = startOfBag;
1467 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1468 jint stringIndex = -1;
1469 jint stringBlock = 0;
1470 value = bag->map.value;
1471
1472 // Take care of resolving the found resource to its final value.
1473 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1474 if (value.dataType == Res_value::TYPE_STRING) {
1475 stringIndex = value.data;
1476 }
1477
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001478#if THROW_ON_BAD_ID
1479 if (stringBlock == BAD_INDEX) {
1480 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1481 return array;
1482 }
1483#endif
1484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 //todo: It might be faster to allocate a C array to contain
1486 // the blocknums and indices, put them in there and then
1487 // do just one SetIntArrayRegion()
1488 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1489 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1490 j = j + 2;
1491 }
1492 res.unlockBag(startOfBag);
1493 return array;
1494}
1495
1496static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1497 jint arrayResId)
1498{
1499 AssetManager* am = assetManagerForJavaObject(env, clazz);
1500 if (am == NULL) {
1501 return NULL;
1502 }
1503 const ResTable& res(am->getResources());
1504
1505 jclass cls = env->FindClass("java/lang/String");
1506 LOG_FATAL_IF(cls == NULL, "No string class?!?");
1507 if (cls == NULL) {
1508 return NULL;
1509 }
1510
1511 const ResTable::bag_entry* startOfBag;
1512 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1513 if (N < 0) {
1514 return NULL;
1515 }
1516
1517 jobjectArray array = env->NewObjectArray(N, cls, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001518 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 res.unlockBag(startOfBag);
1520 return NULL;
1521 }
1522
1523 Res_value value;
1524 const ResTable::bag_entry* bag = startOfBag;
1525 size_t strLen = 0;
1526 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1527 value = bag->map.value;
1528 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530 // Take care of resolving the found resource to its final value.
1531 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001532#if THROW_ON_BAD_ID
1533 if (block == BAD_INDEX) {
1534 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1535 return array;
1536 }
1537#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001539 const ResStringPool* pool = res.getTableStringBlock(block);
1540 const char* str8 = pool->string8At(value.data, &strLen);
1541 if (str8 != NULL) {
1542 str = env->NewStringUTF(str8);
1543 } else {
1544 const char16_t* str16 = pool->stringAt(value.data, &strLen);
1545 str = env->NewString(str16, strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001546 }
1547
1548 // If one of our NewString{UTF} calls failed due to memory, an
1549 // exception will be pending.
1550 if (env->ExceptionCheck()) {
1551 res.unlockBag(startOfBag);
1552 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 }
Kenny Root780d2a12010-02-22 22:36:26 -08001554
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001555 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001556
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001557 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1558 // If we have a large amount of strings in our array, we might
1559 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001560 env->DeleteLocalRef(str);
1561 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001562 }
1563 res.unlockBag(startOfBag);
1564 return array;
1565}
1566
1567static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1568 jint arrayResId)
1569{
1570 AssetManager* am = assetManagerForJavaObject(env, clazz);
1571 if (am == NULL) {
1572 return NULL;
1573 }
1574 const ResTable& res(am->getResources());
1575
1576 const ResTable::bag_entry* startOfBag;
1577 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1578 if (N < 0) {
1579 return NULL;
1580 }
1581
1582 jintArray array = env->NewIntArray(N);
1583 if (array == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001584 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001585 res.unlockBag(startOfBag);
1586 return NULL;
1587 }
1588
1589 Res_value value;
1590 const ResTable::bag_entry* bag = startOfBag;
1591 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1592 value = bag->map.value;
1593
1594 // Take care of resolving the found resource to its final value.
1595 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001596#if THROW_ON_BAD_ID
1597 if (block == BAD_INDEX) {
1598 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1599 return array;
1600 }
1601#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001602 if (value.dataType >= Res_value::TYPE_FIRST_INT
1603 && value.dataType <= Res_value::TYPE_LAST_INT) {
1604 int intVal = value.data;
1605 env->SetIntArrayRegion(array, i, 1, &intVal);
1606 }
1607 }
1608 res.unlockBag(startOfBag);
1609 return array;
1610}
1611
1612static void android_content_AssetManager_init(JNIEnv* env, jobject clazz)
1613{
1614 AssetManager* am = new AssetManager();
1615 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001616 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001617 return;
1618 }
1619
1620 am->addDefaultAssets();
1621
1622 LOGV("Created AssetManager %p for Java object %p\n", am, clazz);
1623 env->SetIntField(clazz, gAssetManagerOffsets.mObject, (jint)am);
1624}
1625
1626static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
1627{
1628 AssetManager* am = (AssetManager*)
1629 (env->GetIntField(clazz, gAssetManagerOffsets.mObject));
1630 LOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
1631 if (am != NULL) {
1632 delete am;
1633 env->SetIntField(clazz, gAssetManagerOffsets.mObject, 0);
1634 }
1635}
1636
1637static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
1638{
1639 return Asset::getGlobalCount();
1640}
1641
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001642static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
1643{
1644 String8 alloc = Asset::getAssetAllocations();
1645 if (alloc.length() <= 0) {
1646 return NULL;
1647 }
1648
1649 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001650 return str;
1651}
1652
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001653static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
1654{
1655 return AssetManager::getGlobalCount();
1656}
1657
1658// ----------------------------------------------------------------------------
1659
1660/*
1661 * JNI registration.
1662 */
1663static JNINativeMethod gAssetManagerMethods[] = {
1664 /* name, signature, funcPtr */
1665
1666 // Basic asset stuff.
1667 { "openAsset", "(Ljava/lang/String;I)I",
1668 (void*) android_content_AssetManager_openAsset },
1669 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
1670 (void*) android_content_AssetManager_openAssetFd },
1671 { "openNonAssetNative", "(ILjava/lang/String;I)I",
1672 (void*) android_content_AssetManager_openNonAssetNative },
1673 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
1674 (void*) android_content_AssetManager_openNonAssetFdNative },
1675 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
1676 (void*) android_content_AssetManager_list },
1677 { "destroyAsset", "(I)V",
1678 (void*) android_content_AssetManager_destroyAsset },
1679 { "readAssetChar", "(I)I",
1680 (void*) android_content_AssetManager_readAssetChar },
1681 { "readAsset", "(I[BII)I",
1682 (void*) android_content_AssetManager_readAsset },
1683 { "seekAsset", "(IJI)J",
1684 (void*) android_content_AssetManager_seekAsset },
1685 { "getAssetLength", "(I)J",
1686 (void*) android_content_AssetManager_getAssetLength },
1687 { "getAssetRemainingLength", "(I)J",
1688 (void*) android_content_AssetManager_getAssetRemainingLength },
1689 { "addAssetPath", "(Ljava/lang/String;)I",
1690 (void*) android_content_AssetManager_addAssetPath },
1691 { "isUpToDate", "()Z",
1692 (void*) android_content_AssetManager_isUpToDate },
1693
1694 // Resources.
1695 { "setLocale", "(Ljava/lang/String;)V",
1696 (void*) android_content_AssetManager_setLocale },
1697 { "getLocales", "()[Ljava/lang/String;",
1698 (void*) android_content_AssetManager_getLocales },
Dianne Hackbornebff8f92011-05-12 18:07:47 -07001699 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 (void*) android_content_AssetManager_setConfiguration },
1701 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
1702 (void*) android_content_AssetManager_getResourceIdentifier },
1703 { "getResourceName","(I)Ljava/lang/String;",
1704 (void*) android_content_AssetManager_getResourceName },
1705 { "getResourcePackageName","(I)Ljava/lang/String;",
1706 (void*) android_content_AssetManager_getResourcePackageName },
1707 { "getResourceTypeName","(I)Ljava/lang/String;",
1708 (void*) android_content_AssetManager_getResourceTypeName },
1709 { "getResourceEntryName","(I)Ljava/lang/String;",
1710 (void*) android_content_AssetManager_getResourceEntryName },
Kenny Root55fc8502010-10-28 14:47:01 -07001711 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001712 (void*) android_content_AssetManager_loadResourceValue },
1713 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
1714 (void*) android_content_AssetManager_loadResourceBagValue },
1715 { "getStringBlockCount","()I",
1716 (void*) android_content_AssetManager_getStringBlockCount },
1717 { "getNativeStringBlock","(I)I",
1718 (void*) android_content_AssetManager_getNativeStringBlock },
1719 { "getCookieName","(I)Ljava/lang/String;",
1720 (void*) android_content_AssetManager_getCookieName },
1721
1722 // Themes.
1723 { "newTheme", "()I",
1724 (void*) android_content_AssetManager_newTheme },
1725 { "deleteTheme", "(I)V",
1726 (void*) android_content_AssetManager_deleteTheme },
1727 { "applyThemeStyle", "(IIZ)V",
1728 (void*) android_content_AssetManager_applyThemeStyle },
1729 { "copyTheme", "(II)V",
1730 (void*) android_content_AssetManager_copyTheme },
1731 { "loadThemeAttributeValue", "(IILandroid/util/TypedValue;Z)I",
1732 (void*) android_content_AssetManager_loadThemeAttributeValue },
1733 { "dumpTheme", "(IILjava/lang/String;Ljava/lang/String;)V",
1734 (void*) android_content_AssetManager_dumpTheme },
1735 { "applyStyle","(IIII[I[I[I)Z",
1736 (void*) android_content_AssetManager_applyStyle },
1737 { "retrieveAttributes","(I[I[I[I)Z",
1738 (void*) android_content_AssetManager_retrieveAttributes },
1739 { "getArraySize","(I)I",
1740 (void*) android_content_AssetManager_getArraySize },
1741 { "retrieveArray","(I[I)I",
1742 (void*) android_content_AssetManager_retrieveArray },
1743
1744 // XML files.
1745 { "openXmlAssetNative", "(ILjava/lang/String;)I",
1746 (void*) android_content_AssetManager_openXmlAssetNative },
1747
1748 // Arrays.
1749 { "getArrayStringResource","(I)[Ljava/lang/String;",
1750 (void*) android_content_AssetManager_getArrayStringResource },
1751 { "getArrayStringInfo","(I)[I",
1752 (void*) android_content_AssetManager_getArrayStringInfo },
1753 { "getArrayIntResource","(I)[I",
1754 (void*) android_content_AssetManager_getArrayIntResource },
1755
1756 // Bookkeeping.
1757 { "init", "()V",
1758 (void*) android_content_AssetManager_init },
1759 { "destroy", "()V",
1760 (void*) android_content_AssetManager_destroy },
1761 { "getGlobalAssetCount", "()I",
1762 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001763 { "getAssetAllocations", "()Ljava/lang/String;",
1764 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765 { "getGlobalAssetManagerCount", "()I",
1766 (void*) android_content_AssetManager_getGlobalAssetCount },
1767};
1768
1769int register_android_content_AssetManager(JNIEnv* env)
1770{
1771 jclass typedValue = env->FindClass("android/util/TypedValue");
1772 LOG_FATAL_IF(typedValue == NULL, "Unable to find class android/util/TypedValue");
1773 gTypedValueOffsets.mType
1774 = env->GetFieldID(typedValue, "type", "I");
1775 LOG_FATAL_IF(gTypedValueOffsets.mType == NULL, "Unable to find TypedValue.type");
1776 gTypedValueOffsets.mData
1777 = env->GetFieldID(typedValue, "data", "I");
1778 LOG_FATAL_IF(gTypedValueOffsets.mData == NULL, "Unable to find TypedValue.data");
1779 gTypedValueOffsets.mString
1780 = env->GetFieldID(typedValue, "string", "Ljava/lang/CharSequence;");
1781 LOG_FATAL_IF(gTypedValueOffsets.mString == NULL, "Unable to find TypedValue.string");
1782 gTypedValueOffsets.mAssetCookie
1783 = env->GetFieldID(typedValue, "assetCookie", "I");
1784 LOG_FATAL_IF(gTypedValueOffsets.mAssetCookie == NULL, "Unable to find TypedValue.assetCookie");
1785 gTypedValueOffsets.mResourceId
1786 = env->GetFieldID(typedValue, "resourceId", "I");
1787 LOG_FATAL_IF(gTypedValueOffsets.mResourceId == NULL, "Unable to find TypedValue.resourceId");
1788 gTypedValueOffsets.mChangingConfigurations
1789 = env->GetFieldID(typedValue, "changingConfigurations", "I");
1790 LOG_FATAL_IF(gTypedValueOffsets.mChangingConfigurations == NULL, "Unable to find TypedValue.changingConfigurations");
1791 gTypedValueOffsets.mDensity = env->GetFieldID(typedValue, "density", "I");
1792 LOG_FATAL_IF(gTypedValueOffsets.mDensity == NULL, "Unable to find TypedValue.density");
1793
1794 jclass assetFd = env->FindClass("android/content/res/AssetFileDescriptor");
1795 LOG_FATAL_IF(assetFd == NULL, "Unable to find class android/content/res/AssetFileDescriptor");
1796 gAssetFileDescriptorOffsets.mFd
1797 = env->GetFieldID(assetFd, "mFd", "Landroid/os/ParcelFileDescriptor;");
1798 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mFd == NULL, "Unable to find AssetFileDescriptor.mFd");
1799 gAssetFileDescriptorOffsets.mStartOffset
1800 = env->GetFieldID(assetFd, "mStartOffset", "J");
1801 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mStartOffset == NULL, "Unable to find AssetFileDescriptor.mStartOffset");
1802 gAssetFileDescriptorOffsets.mLength
1803 = env->GetFieldID(assetFd, "mLength", "J");
1804 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mLength == NULL, "Unable to find AssetFileDescriptor.mLength");
1805
1806 jclass assetManager = env->FindClass("android/content/res/AssetManager");
1807 LOG_FATAL_IF(assetManager == NULL, "Unable to find class android/content/res/AssetManager");
1808 gAssetManagerOffsets.mObject
1809 = env->GetFieldID(assetManager, "mObject", "I");
1810 LOG_FATAL_IF(gAssetManagerOffsets.mObject == NULL, "Unable to find AssetManager.mObject");
1811
1812 g_stringClass = env->FindClass("java/lang/String");
1813
1814 return AndroidRuntime::registerNativeMethods(env,
1815 "android/content/res/AssetManager", gAssetManagerMethods, NELEM(gAssetManagerMethods));
1816}
1817
1818}; // namespace android