1 /* //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
20 #include <android_runtime/android_util_AssetManager.h>
21
22 #include <inttypes.h>
23 #include <linux/capability.h>
24 #include <stdio.h>
25 #include <sys/types.h>
26 #include <sys/wait.h>
27 #include <sys/stat.h>
28 #include <sys/system_properties.h>
29
30 #include <private/android_filesystem_config.h> // for AID_SYSTEM
31
32 #include "androidfw/Asset.h"
33 #include "androidfw/AssetManager.h"
34 #include "androidfw/AttributeResolution.h"
35 #include "androidfw/ResourceTypes.h"
36 #include "android_runtime/AndroidRuntime.h"
37 #include "android_util_Binder.h"
38 #include "core_jni_helpers.h"
39 #include "jni.h"
40 #include <nativehelper/JNIHelp.h>
41 #include <nativehelper/ScopedStringChars.h>
42 #include <nativehelper/ScopedUtfChars.h>
43 #include "utils/Log.h"
44 #include "utils/misc.h"
45 #include "utils/String8.h"
46
47 extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
48 extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
49
50
51 namespace android {
52
53 static const bool kThrowOnBadId = false;
54
55 // ----------------------------------------------------------------------------
56
57 static struct typedvalue_offsets_t
58 {
59 jfieldID mType;
60 jfieldID mData;
61 jfieldID mString;
62 jfieldID mAssetCookie;
63 jfieldID mResourceId;
64 jfieldID mChangingConfigurations;
65 jfieldID mDensity;
66 } gTypedValueOffsets;
67
68 static struct assetfiledescriptor_offsets_t
69 {
70 jfieldID mFd;
71 jfieldID mStartOffset;
72 jfieldID mLength;
73 } gAssetFileDescriptorOffsets;
74
75 static struct assetmanager_offsets_t
76 {
77 jfieldID mObject;
78 } gAssetManagerOffsets;
79
80 static struct sparsearray_offsets_t
81 {
82 jclass classObject;
83 jmethodID constructor;
84 jmethodID put;
85 } gSparseArrayOffsets;
86
87 static struct configuration_offsets_t
88 {
89 jclass classObject;
90 jmethodID constructor;
91 jfieldID mSmallestScreenWidthDpOffset;
92 jfieldID mScreenWidthDpOffset;
93 jfieldID mScreenHeightDpOffset;
94 } gConfigurationOffsets;
95
96 jclass g_stringClass = NULL;
97
98 // ----------------------------------------------------------------------------
99
100 static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
101 const Res_value& value, uint32_t ref, ssize_t block,
102 uint32_t typeSpecFlags, ResTable_config* config = NULL);
103
copyValue(JNIEnv * env,jobject outValue,const ResTable * table,const Res_value & value,uint32_t ref,ssize_t block,uint32_t typeSpecFlags,ResTable_config * config)104 jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
105 const Res_value& value, uint32_t ref, ssize_t block,
106 uint32_t typeSpecFlags, ResTable_config* config)
107 {
108 env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
109 env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
110 static_cast<jint>(table->getTableCookie(block)));
111 env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
112 env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
113 env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
114 env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
115 typeSpecFlags);
116 if (config != NULL) {
117 env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
118 }
119 return block;
120 }
121
122 // This is called by zygote (running as user root) as part of preloadResources.
verifySystemIdmaps()123 static void verifySystemIdmaps()
124 {
125 pid_t pid;
126 char system_id[10];
127
128 snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
129
130 switch (pid = fork()) {
131 case -1:
132 ALOGE("failed to fork for idmap: %s", strerror(errno));
133 break;
134 case 0: // child
135 {
136 struct __user_cap_header_struct capheader;
137 struct __user_cap_data_struct capdata;
138
139 memset(&capheader, 0, sizeof(capheader));
140 memset(&capdata, 0, sizeof(capdata));
141
142 capheader.version = _LINUX_CAPABILITY_VERSION;
143 capheader.pid = 0;
144
145 if (capget(&capheader, &capdata) != 0) {
146 ALOGE("capget: %s\n", strerror(errno));
147 exit(1);
148 }
149
150 capdata.effective = capdata.permitted;
151 if (capset(&capheader, &capdata) != 0) {
152 ALOGE("capset: %s\n", strerror(errno));
153 exit(1);
154 }
155
156 if (setgid(AID_SYSTEM) != 0) {
157 ALOGE("setgid: %s\n", strerror(errno));
158 exit(1);
159 }
160
161 if (setuid(AID_SYSTEM) != 0) {
162 ALOGE("setuid: %s\n", strerror(errno));
163 exit(1);
164 }
165
166 // Generic idmap parameters
167 const char* argv[8];
168 int argc = 0;
169 struct stat st;
170
171 memset(argv, NULL, sizeof(argv));
172 argv[argc++] = AssetManager::IDMAP_BIN;
173 argv[argc++] = "--scan";
174 argv[argc++] = AssetManager::TARGET_PACKAGE_NAME;
175 argv[argc++] = AssetManager::TARGET_APK_PATH;
176 argv[argc++] = AssetManager::IDMAP_DIR;
177
178 // Directories to scan for overlays: if OVERLAY_THEME_DIR_PROPERTY is defined,
179 // use OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to OVERLAY_DIR.
180 char subdir[PROP_VALUE_MAX];
181 int len = __system_property_get(AssetManager::OVERLAY_THEME_DIR_PROPERTY, subdir);
182 if (len > 0) {
183 String8 overlayPath = String8(AssetManager::OVERLAY_DIR) + "/" + subdir;
184 if (stat(overlayPath.string(), &st) == 0) {
185 argv[argc++] = overlayPath.string();
186 }
187 }
188 if (stat(AssetManager::OVERLAY_DIR, &st) == 0) {
189 argv[argc++] = AssetManager::OVERLAY_DIR;
190 }
191
192 // Finally, invoke idmap (if any overlay directory exists)
193 if (argc > 5) {
194 execv(AssetManager::IDMAP_BIN, (char* const*)argv);
195 ALOGE("failed to execv for idmap: %s", strerror(errno));
196 exit(1); // should never get here
197 } else {
198 exit(0);
199 }
200 }
201 break;
202 default: // parent
203 waitpid(pid, NULL, 0);
204 break;
205 }
206 }
207
208 // ----------------------------------------------------------------------------
209
210 // this guy is exported to other jni routines
assetManagerForJavaObject(JNIEnv * env,jobject obj)211 AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
212 {
213 jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
214 AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
215 if (am != NULL) {
216 return am;
217 }
218 jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
219 return NULL;
220 }
221
android_content_AssetManager_openAsset(JNIEnv * env,jobject clazz,jstring fileName,jint mode)222 static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
223 jstring fileName, jint mode)
224 {
225 AssetManager* am = assetManagerForJavaObject(env, clazz);
226 if (am == NULL) {
227 return 0;
228 }
229
230 ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
231
232 ScopedUtfChars fileName8(env, fileName);
233 if (fileName8.c_str() == NULL) {
234 jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
235 return -1;
236 }
237
238 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
239 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
240 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
241 return -1;
242 }
243
244 Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
245
246 if (a == NULL) {
247 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
248 return -1;
249 }
250
251 //printf("Created Asset Stream: %p\n", a);
252
253 return reinterpret_cast<jlong>(a);
254 }
255
returnParcelFileDescriptor(JNIEnv * env,Asset * a,jlongArray outOffsets)256 static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
257 {
258 off64_t startOffset, length;
259 int fd = a->openFileDescriptor(&startOffset, &length);
260 delete a;
261
262 if (fd < 0) {
263 jniThrowException(env, "java/io/FileNotFoundException",
264 "This file can not be opened as a file descriptor; it is probably compressed");
265 return NULL;
266 }
267
268 jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
269 if (offsets == NULL) {
270 close(fd);
271 return NULL;
272 }
273
274 offsets[0] = startOffset;
275 offsets[1] = length;
276
277 env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
278
279 jobject fileDesc = jniCreateFileDescriptor(env, fd);
280 if (fileDesc == NULL) {
281 close(fd);
282 return NULL;
283 }
284
285 return newParcelFileDescriptor(env, fileDesc);
286 }
287
android_content_AssetManager_openAssetFd(JNIEnv * env,jobject clazz,jstring fileName,jlongArray outOffsets)288 static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
289 jstring fileName, jlongArray outOffsets)
290 {
291 AssetManager* am = assetManagerForJavaObject(env, clazz);
292 if (am == NULL) {
293 return NULL;
294 }
295
296 ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
297
298 ScopedUtfChars fileName8(env, fileName);
299 if (fileName8.c_str() == NULL) {
300 return NULL;
301 }
302
303 Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
304
305 if (a == NULL) {
306 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
307 return NULL;
308 }
309
310 //printf("Created Asset Stream: %p\n", a);
311
312 return returnParcelFileDescriptor(env, a, outOffsets);
313 }
314
android_content_AssetManager_openNonAssetNative(JNIEnv * env,jobject clazz,jint cookie,jstring fileName,jint mode)315 static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
316 jint cookie,
317 jstring fileName,
318 jint mode)
319 {
320 AssetManager* am = assetManagerForJavaObject(env, clazz);
321 if (am == NULL) {
322 return 0;
323 }
324
325 ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
326
327 ScopedUtfChars fileName8(env, fileName);
328 if (fileName8.c_str() == NULL) {
329 return -1;
330 }
331
332 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
333 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
334 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
335 return -1;
336 }
337
338 Asset* a = cookie
339 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
340 (Asset::AccessMode)mode)
341 : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
342
343 if (a == NULL) {
344 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
345 return -1;
346 }
347
348 //printf("Created Asset Stream: %p\n", a);
349
350 return reinterpret_cast<jlong>(a);
351 }
352
android_content_AssetManager_openNonAssetFdNative(JNIEnv * env,jobject clazz,jint cookie,jstring fileName,jlongArray outOffsets)353 static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
354 jint cookie,
355 jstring fileName,
356 jlongArray outOffsets)
357 {
358 AssetManager* am = assetManagerForJavaObject(env, clazz);
359 if (am == NULL) {
360 return NULL;
361 }
362
363 ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
364
365 ScopedUtfChars fileName8(env, fileName);
366 if (fileName8.c_str() == NULL) {
367 return NULL;
368 }
369
370 Asset* a = cookie
371 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
372 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
373
374 if (a == NULL) {
375 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
376 return NULL;
377 }
378
379 //printf("Created Asset Stream: %p\n", a);
380
381 return returnParcelFileDescriptor(env, a, outOffsets);
382 }
383
android_content_AssetManager_list(JNIEnv * env,jobject clazz,jstring fileName)384 static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
385 jstring fileName)
386 {
387 AssetManager* am = assetManagerForJavaObject(env, clazz);
388 if (am == NULL) {
389 return NULL;
390 }
391
392 ScopedUtfChars fileName8(env, fileName);
393 if (fileName8.c_str() == NULL) {
394 return NULL;
395 }
396
397 AssetDir* dir = am->openDir(fileName8.c_str());
398
399 if (dir == NULL) {
400 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
401 return NULL;
402 }
403
404 size_t N = dir->getFileCount();
405
406 jobjectArray array = env->NewObjectArray(dir->getFileCount(),
407 g_stringClass, NULL);
408 if (array == NULL) {
409 delete dir;
410 return NULL;
411 }
412
413 for (size_t i=0; i<N; i++) {
414 const String8& name = dir->getFileName(i);
415 jstring str = env->NewStringUTF(name.string());
416 if (str == NULL) {
417 delete dir;
418 return NULL;
419 }
420 env->SetObjectArrayElement(array, i, str);
421 env->DeleteLocalRef(str);
422 }
423
424 delete dir;
425
426 return array;
427 }
428
android_content_AssetManager_destroyAsset(JNIEnv * env,jobject clazz,jlong assetHandle)429 static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
430 jlong assetHandle)
431 {
432 Asset* a = reinterpret_cast<Asset*>(assetHandle);
433
434 //printf("Destroying Asset Stream: %p\n", a);
435
436 if (a == NULL) {
437 jniThrowNullPointerException(env, "asset");
438 return;
439 }
440
441 delete a;
442 }
443
android_content_AssetManager_readAssetChar(JNIEnv * env,jobject clazz,jlong assetHandle)444 static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
445 jlong assetHandle)
446 {
447 Asset* a = reinterpret_cast<Asset*>(assetHandle);
448
449 if (a == NULL) {
450 jniThrowNullPointerException(env, "asset");
451 return -1;
452 }
453
454 uint8_t b;
455 ssize_t res = a->read(&b, 1);
456 return res == 1 ? b : -1;
457 }
458
android_content_AssetManager_readAsset(JNIEnv * env,jobject clazz,jlong assetHandle,jbyteArray bArray,jint off,jint len)459 static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
460 jlong assetHandle, jbyteArray bArray,
461 jint off, jint len)
462 {
463 Asset* a = reinterpret_cast<Asset*>(assetHandle);
464
465 if (a == NULL || bArray == NULL) {
466 jniThrowNullPointerException(env, "asset");
467 return -1;
468 }
469
470 if (len == 0) {
471 return 0;
472 }
473
474 jsize bLen = env->GetArrayLength(bArray);
475 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
476 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
477 return -1;
478 }
479
480 jbyte* b = env->GetByteArrayElements(bArray, NULL);
481 ssize_t res = a->read(b+off, len);
482 env->ReleaseByteArrayElements(bArray, b, 0);
483
484 if (res > 0) return static_cast<jint>(res);
485
486 if (res < 0) {
487 jniThrowException(env, "java/io/IOException", "");
488 }
489 return -1;
490 }
491
android_content_AssetManager_seekAsset(JNIEnv * env,jobject clazz,jlong assetHandle,jlong offset,jint whence)492 static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
493 jlong assetHandle,
494 jlong offset, jint whence)
495 {
496 Asset* a = reinterpret_cast<Asset*>(assetHandle);
497
498 if (a == NULL) {
499 jniThrowNullPointerException(env, "asset");
500 return -1;
501 }
502
503 return a->seek(
504 offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
505 }
506
android_content_AssetManager_getAssetLength(JNIEnv * env,jobject clazz,jlong assetHandle)507 static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
508 jlong assetHandle)
509 {
510 Asset* a = reinterpret_cast<Asset*>(assetHandle);
511
512 if (a == NULL) {
513 jniThrowNullPointerException(env, "asset");
514 return -1;
515 }
516
517 return a->getLength();
518 }
519
android_content_AssetManager_getAssetRemainingLength(JNIEnv * env,jobject clazz,jlong assetHandle)520 static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
521 jlong assetHandle)
522 {
523 Asset* a = reinterpret_cast<Asset*>(assetHandle);
524
525 if (a == NULL) {
526 jniThrowNullPointerException(env, "asset");
527 return -1;
528 }
529
530 return a->getRemainingLength();
531 }
532
android_content_AssetManager_addAssetPath(JNIEnv * env,jobject clazz,jstring path,jboolean appAsLib)533 static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
534 jstring path, jboolean appAsLib)
535 {
536 ScopedUtfChars path8(env, path);
537 if (path8.c_str() == NULL) {
538 return 0;
539 }
540
541 AssetManager* am = assetManagerForJavaObject(env, clazz);
542 if (am == NULL) {
543 return 0;
544 }
545
546 int32_t cookie;
547 bool res = am->addAssetPath(String8(path8.c_str()), &cookie, appAsLib);
548
549 return (res) ? static_cast<jint>(cookie) : 0;
550 }
551
android_content_AssetManager_addOverlayPath(JNIEnv * env,jobject clazz,jstring idmapPath)552 static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
553 jstring idmapPath)
554 {
555 ScopedUtfChars idmapPath8(env, idmapPath);
556 if (idmapPath8.c_str() == NULL) {
557 return 0;
558 }
559
560 AssetManager* am = assetManagerForJavaObject(env, clazz);
561 if (am == NULL) {
562 return 0;
563 }
564
565 int32_t cookie;
566 bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
567
568 return (res) ? (jint)cookie : 0;
569 }
570
android_content_AssetManager_isUpToDate(JNIEnv * env,jobject clazz)571 static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
572 {
573 AssetManager* am = assetManagerForJavaObject(env, clazz);
574 if (am == NULL) {
575 return JNI_TRUE;
576 }
577 return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
578 }
579
getLocales(JNIEnv * env,jobject clazz,bool includeSystemLocales)580 static jobjectArray getLocales(JNIEnv* env, jobject clazz, bool includeSystemLocales)
581 {
582 Vector<String8> locales;
583
584 AssetManager* am = assetManagerForJavaObject(env, clazz);
585 if (am == NULL) {
586 return NULL;
587 }
588
589 am->getLocales(&locales, includeSystemLocales);
590
591 const int N = locales.size();
592
593 jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
594 if (result == NULL) {
595 return NULL;
596 }
597
598 for (int i=0; i<N; i++) {
599 jstring str = env->NewStringUTF(locales[i].string());
600 if (str == NULL) {
601 return NULL;
602 }
603 env->SetObjectArrayElement(result, i, str);
604 env->DeleteLocalRef(str);
605 }
606
607 return result;
608 }
609
android_content_AssetManager_getLocales(JNIEnv * env,jobject clazz)610 static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
611 {
612 return getLocales(env, clazz, true /* include system locales */);
613 }
614
android_content_AssetManager_getNonSystemLocales(JNIEnv * env,jobject clazz)615 static jobjectArray android_content_AssetManager_getNonSystemLocales(JNIEnv* env, jobject clazz)
616 {
617 return getLocales(env, clazz, false /* don't include system locales */);
618 }
619
constructConfigurationObject(JNIEnv * env,const ResTable_config & config)620 static jobject constructConfigurationObject(JNIEnv* env, const ResTable_config& config) {
621 jobject result = env->NewObject(gConfigurationOffsets.classObject,
622 gConfigurationOffsets.constructor);
623 if (result == NULL) {
624 return NULL;
625 }
626
627 env->SetIntField(result, gConfigurationOffsets.mSmallestScreenWidthDpOffset,
628 config.smallestScreenWidthDp);
629 env->SetIntField(result, gConfigurationOffsets.mScreenWidthDpOffset, config.screenWidthDp);
630 env->SetIntField(result, gConfigurationOffsets.mScreenHeightDpOffset, config.screenHeightDp);
631
632 return result;
633 }
634
getSizeConfigurationsInternal(JNIEnv * env,const Vector<ResTable_config> & configs)635 static jobjectArray getSizeConfigurationsInternal(JNIEnv* env,
636 const Vector<ResTable_config>& configs) {
637 const int N = configs.size();
638 jobjectArray result = env->NewObjectArray(N, gConfigurationOffsets.classObject, NULL);
639 if (result == NULL) {
640 return NULL;
641 }
642
643 for (int i=0; i<N; i++) {
644 jobject config = constructConfigurationObject(env, configs[i]);
645 if (config == NULL) {
646 env->DeleteLocalRef(result);
647 return NULL;
648 }
649
650 env->SetObjectArrayElement(result, i, config);
651 env->DeleteLocalRef(config);
652 }
653
654 return result;
655 }
656
android_content_AssetManager_getSizeConfigurations(JNIEnv * env,jobject clazz)657 static jobjectArray android_content_AssetManager_getSizeConfigurations(JNIEnv* env, jobject clazz) {
658 AssetManager* am = assetManagerForJavaObject(env, clazz);
659 if (am == NULL) {
660 return NULL;
661 }
662
663 const ResTable& res(am->getResources());
664 Vector<ResTable_config> configs;
665 res.getConfigurations(&configs, false /* ignoreMipmap */, true /* ignoreAndroidPackage */);
666
667 return getSizeConfigurationsInternal(env, configs);
668 }
669
android_content_AssetManager_setConfiguration(JNIEnv * env,jobject clazz,jint mcc,jint mnc,jstring locale,jint orientation,jint touchscreen,jint density,jint keyboard,jint keyboardHidden,jint navigation,jint screenWidth,jint screenHeight,jint smallestScreenWidthDp,jint screenWidthDp,jint screenHeightDp,jint screenLayout,jint uiMode,jint colorMode,jint sdkVersion)670 static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
671 jint mcc, jint mnc,
672 jstring locale, jint orientation,
673 jint touchscreen, jint density,
674 jint keyboard, jint keyboardHidden,
675 jint navigation,
676 jint screenWidth, jint screenHeight,
677 jint smallestScreenWidthDp,
678 jint screenWidthDp, jint screenHeightDp,
679 jint screenLayout, jint uiMode,
680 jint colorMode, jint sdkVersion)
681 {
682 AssetManager* am = assetManagerForJavaObject(env, clazz);
683 if (am == NULL) {
684 return;
685 }
686
687 ResTable_config config;
688 memset(&config, 0, sizeof(config));
689
690 const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
691
692 // Constants duplicated from Java class android.content.res.Configuration.
693 static const jint kScreenLayoutRoundMask = 0x300;
694 static const jint kScreenLayoutRoundShift = 8;
695
696 config.mcc = (uint16_t)mcc;
697 config.mnc = (uint16_t)mnc;
698 config.orientation = (uint8_t)orientation;
699 config.touchscreen = (uint8_t)touchscreen;
700 config.density = (uint16_t)density;
701 config.keyboard = (uint8_t)keyboard;
702 config.inputFlags = (uint8_t)keyboardHidden;
703 config.navigation = (uint8_t)navigation;
704 config.screenWidth = (uint16_t)screenWidth;
705 config.screenHeight = (uint16_t)screenHeight;
706 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
707 config.screenWidthDp = (uint16_t)screenWidthDp;
708 config.screenHeightDp = (uint16_t)screenHeightDp;
709 config.screenLayout = (uint8_t)screenLayout;
710 config.uiMode = (uint8_t)uiMode;
711 config.colorMode = (uint8_t)colorMode;
712 config.sdkVersion = (uint16_t)sdkVersion;
713 config.minorVersion = 0;
714
715 // In Java, we use a 32bit integer for screenLayout, while we only use an 8bit integer
716 // in C++. We must extract the round qualifier out of the Java screenLayout and put it
717 // into screenLayout2.
718 config.screenLayout2 =
719 (uint8_t)((screenLayout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift);
720
721 am->setConfiguration(config, locale8);
722
723 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
724 }
725
android_content_AssetManager_getResourceIdentifier(JNIEnv * env,jobject clazz,jstring name,jstring defType,jstring defPackage)726 static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
727 jstring name,
728 jstring defType,
729 jstring defPackage)
730 {
731 ScopedStringChars name16(env, name);
732 if (name16.get() == NULL) {
733 return 0;
734 }
735
736 AssetManager* am = assetManagerForJavaObject(env, clazz);
737 if (am == NULL) {
738 return 0;
739 }
740
741 const char16_t* defType16 = reinterpret_cast<const char16_t*>(defType)
742 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defType, NULL))
743 : NULL;
744 jsize defTypeLen = defType
745 ? env->GetStringLength(defType) : 0;
746 const char16_t* defPackage16 = reinterpret_cast<const char16_t*>(defPackage)
747 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defPackage,
748 NULL))
749 : NULL;
750 jsize defPackageLen = defPackage
751 ? env->GetStringLength(defPackage) : 0;
752
753 jint ident = am->getResources().identifierForName(
754 reinterpret_cast<const char16_t*>(name16.get()), name16.size(),
755 defType16, defTypeLen, defPackage16, defPackageLen);
756
757 if (defPackage16) {
758 env->ReleaseStringChars(defPackage,
759 reinterpret_cast<const jchar*>(defPackage16));
760 }
761 if (defType16) {
762 env->ReleaseStringChars(defType,
763 reinterpret_cast<const jchar*>(defType16));
764 }
765
766 return ident;
767 }
768
android_content_AssetManager_getResourceName(JNIEnv * env,jobject clazz,jint resid)769 static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
770 jint resid)
771 {
772 AssetManager* am = assetManagerForJavaObject(env, clazz);
773 if (am == NULL) {
774 return NULL;
775 }
776
777 ResTable::resource_name name;
778 if (!am->getResources().getResourceName(resid, true, &name)) {
779 return NULL;
780 }
781
782 String16 str;
783 if (name.package != NULL) {
784 str.setTo(name.package, name.packageLen);
785 }
786 if (name.type8 != NULL || name.type != NULL) {
787 if (str.size() > 0) {
788 char16_t div = ':';
789 str.append(&div, 1);
790 }
791 if (name.type8 != NULL) {
792 str.append(String16(name.type8, name.typeLen));
793 } else {
794 str.append(name.type, name.typeLen);
795 }
796 }
797 if (name.name8 != NULL || name.name != NULL) {
798 if (str.size() > 0) {
799 char16_t div = '/';
800 str.append(&div, 1);
801 }
802 if (name.name8 != NULL) {
803 str.append(String16(name.name8, name.nameLen));
804 } else {
805 str.append(name.name, name.nameLen);
806 }
807 }
808
809 return env->NewString((const jchar*)str.string(), str.size());
810 }
811
android_content_AssetManager_getResourcePackageName(JNIEnv * env,jobject clazz,jint resid)812 static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
813 jint resid)
814 {
815 AssetManager* am = assetManagerForJavaObject(env, clazz);
816 if (am == NULL) {
817 return NULL;
818 }
819
820 ResTable::resource_name name;
821 if (!am->getResources().getResourceName(resid, true, &name)) {
822 return NULL;
823 }
824
825 if (name.package != NULL) {
826 return env->NewString((const jchar*)name.package, name.packageLen);
827 }
828
829 return NULL;
830 }
831
android_content_AssetManager_getResourceTypeName(JNIEnv * env,jobject clazz,jint resid)832 static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
833 jint resid)
834 {
835 AssetManager* am = assetManagerForJavaObject(env, clazz);
836 if (am == NULL) {
837 return NULL;
838 }
839
840 ResTable::resource_name name;
841 if (!am->getResources().getResourceName(resid, true, &name)) {
842 return NULL;
843 }
844
845 if (name.type8 != NULL) {
846 return env->NewStringUTF(name.type8);
847 }
848
849 if (name.type != NULL) {
850 return env->NewString((const jchar*)name.type, name.typeLen);
851 }
852
853 return NULL;
854 }
855
android_content_AssetManager_getResourceEntryName(JNIEnv * env,jobject clazz,jint resid)856 static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
857 jint resid)
858 {
859 AssetManager* am = assetManagerForJavaObject(env, clazz);
860 if (am == NULL) {
861 return NULL;
862 }
863
864 ResTable::resource_name name;
865 if (!am->getResources().getResourceName(resid, true, &name)) {
866 return NULL;
867 }
868
869 if (name.name8 != NULL) {
870 return env->NewStringUTF(name.name8);
871 }
872
873 if (name.name != NULL) {
874 return env->NewString((const jchar*)name.name, name.nameLen);
875 }
876
877 return NULL;
878 }
879
android_content_AssetManager_loadResourceValue(JNIEnv * env,jobject clazz,jint ident,jshort density,jobject outValue,jboolean resolve)880 static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
881 jint ident,
882 jshort density,
883 jobject outValue,
884 jboolean resolve)
885 {
886 if (outValue == NULL) {
887 jniThrowNullPointerException(env, "outValue");
888 return 0;
889 }
890 AssetManager* am = assetManagerForJavaObject(env, clazz);
891 if (am == NULL) {
892 return 0;
893 }
894 const ResTable& res(am->getResources());
895
896 Res_value value;
897 ResTable_config config;
898 uint32_t typeSpecFlags;
899 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
900 if (kThrowOnBadId) {
901 if (block == BAD_INDEX) {
902 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
903 return 0;
904 }
905 }
906 uint32_t ref = ident;
907 if (resolve) {
908 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
909 if (kThrowOnBadId) {
910 if (block == BAD_INDEX) {
911 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
912 return 0;
913 }
914 }
915 }
916 if (block >= 0) {
917 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
918 }
919
920 return static_cast<jint>(block);
921 }
922
android_content_AssetManager_loadResourceBagValue(JNIEnv * env,jobject clazz,jint ident,jint bagEntryId,jobject outValue,jboolean resolve)923 static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
924 jint ident, jint bagEntryId,
925 jobject outValue, jboolean resolve)
926 {
927 AssetManager* am = assetManagerForJavaObject(env, clazz);
928 if (am == NULL) {
929 return 0;
930 }
931 const ResTable& res(am->getResources());
932
933 // Now lock down the resource object and start pulling stuff from it.
934 res.lock();
935
936 ssize_t block = -1;
937 Res_value value;
938
939 const ResTable::bag_entry* entry = NULL;
940 uint32_t typeSpecFlags;
941 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
942
943 for (ssize_t i=0; i<entryCount; i++) {
944 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
945 block = entry->stringBlock;
946 value = entry->map.value;
947 }
948 entry++;
949 }
950
951 res.unlock();
952
953 if (block < 0) {
954 return static_cast<jint>(block);
955 }
956
957 uint32_t ref = ident;
958 if (resolve) {
959 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
960 if (kThrowOnBadId) {
961 if (block == BAD_INDEX) {
962 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
963 return 0;
964 }
965 }
966 }
967 if (block >= 0) {
968 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
969 }
970
971 return static_cast<jint>(block);
972 }
973
android_content_AssetManager_getStringBlockCount(JNIEnv * env,jobject clazz)974 static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
975 {
976 AssetManager* am = assetManagerForJavaObject(env, clazz);
977 if (am == NULL) {
978 return 0;
979 }
980 return am->getResources().getTableCount();
981 }
982
android_content_AssetManager_getNativeStringBlock(JNIEnv * env,jobject clazz,jint block)983 static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
984 jint block)
985 {
986 AssetManager* am = assetManagerForJavaObject(env, clazz);
987 if (am == NULL) {
988 return 0;
989 }
990 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
991 }
992
android_content_AssetManager_getCookieName(JNIEnv * env,jobject clazz,jint cookie)993 static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
994 jint cookie)
995 {
996 AssetManager* am = assetManagerForJavaObject(env, clazz);
997 if (am == NULL) {
998 return NULL;
999 }
1000 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
1001 if (name.length() == 0) {
1002 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
1003 return NULL;
1004 }
1005 jstring str = env->NewStringUTF(name.string());
1006 return str;
1007 }
1008
android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv * env,jobject clazz)1009 static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
1010 {
1011 AssetManager* am = assetManagerForJavaObject(env, clazz);
1012 if (am == NULL) {
1013 return 0;
1014 }
1015
1016 const ResTable& res = am->getResources();
1017
1018 jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
1019 gSparseArrayOffsets.constructor);
1020 const size_t N = res.getBasePackageCount();
1021 for (size_t i = 0; i < N; i++) {
1022 const String16 name = res.getBasePackageName(i);
1023 env->CallVoidMethod(
1024 sparseArray, gSparseArrayOffsets.put,
1025 static_cast<jint>(res.getBasePackageId(i)),
1026 env->NewString(reinterpret_cast<const jchar*>(name.string()),
1027 name.size()));
1028 }
1029 return sparseArray;
1030 }
1031
android_content_AssetManager_newTheme(JNIEnv * env,jobject clazz)1032 static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
1033 {
1034 AssetManager* am = assetManagerForJavaObject(env, clazz);
1035 if (am == NULL) {
1036 return 0;
1037 }
1038 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
1039 }
1040
android_content_AssetManager_deleteTheme(JNIEnv * env,jobject clazz,jlong themeHandle)1041 static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
1042 jlong themeHandle)
1043 {
1044 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1045 delete theme;
1046 }
1047
android_content_AssetManager_applyThemeStyle(JNIEnv * env,jobject clazz,jlong themeHandle,jint styleRes,jboolean force)1048 static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
1049 jlong themeHandle,
1050 jint styleRes,
1051 jboolean force)
1052 {
1053 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1054 theme->applyStyle(styleRes, force ? true : false);
1055 }
1056
android_content_AssetManager_copyTheme(JNIEnv * env,jobject clazz,jlong destHandle,jlong srcHandle)1057 static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
1058 jlong destHandle, jlong srcHandle)
1059 {
1060 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
1061 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
1062 dest->setTo(*src);
1063 }
1064
android_content_AssetManager_clearTheme(JNIEnv * env,jobject clazz,jlong themeHandle)1065 static void android_content_AssetManager_clearTheme(JNIEnv* env, jobject clazz, jlong themeHandle)
1066 {
1067 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1068 theme->clear();
1069 }
1070
android_content_AssetManager_loadThemeAttributeValue(JNIEnv * env,jobject clazz,jlong themeHandle,jint ident,jobject outValue,jboolean resolve)1071 static jint android_content_AssetManager_loadThemeAttributeValue(
1072 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
1073 {
1074 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1075 const ResTable& res(theme->getResTable());
1076
1077 Res_value value;
1078 // XXX value could be different in different configs!
1079 uint32_t typeSpecFlags = 0;
1080 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
1081 uint32_t ref = 0;
1082 if (resolve) {
1083 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
1084 if (kThrowOnBadId) {
1085 if (block == BAD_INDEX) {
1086 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1087 return 0;
1088 }
1089 }
1090 }
1091 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
1092 }
1093
android_content_AssetManager_getThemeChangingConfigurations(JNIEnv * env,jobject clazz,jlong themeHandle)1094 static jint android_content_AssetManager_getThemeChangingConfigurations(JNIEnv* env, jobject clazz,
1095 jlong themeHandle)
1096 {
1097 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1098 return theme->getChangingConfigurations();
1099 }
1100
android_content_AssetManager_dumpTheme(JNIEnv * env,jobject clazz,jlong themeHandle,jint pri,jstring tag,jstring prefix)1101 static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
1102 jlong themeHandle, jint pri,
1103 jstring tag, jstring prefix)
1104 {
1105 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
1106 const ResTable& res(theme->getResTable());
1107 (void)res;
1108
1109 // XXX Need to use params.
1110 theme->dumpToLog();
1111 }
1112
android_content_AssetManager_resolveAttrs(JNIEnv * env,jobject clazz,jlong themeToken,jint defStyleAttr,jint defStyleRes,jintArray inValues,jintArray attrs,jintArray outValues,jintArray outIndices)1113 static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1114 jlong themeToken,
1115 jint defStyleAttr,
1116 jint defStyleRes,
1117 jintArray inValues,
1118 jintArray attrs,
1119 jintArray outValues,
1120 jintArray outIndices)
1121 {
1122 if (themeToken == 0) {
1123 jniThrowNullPointerException(env, "theme token");
1124 return JNI_FALSE;
1125 }
1126 if (attrs == NULL) {
1127 jniThrowNullPointerException(env, "attrs");
1128 return JNI_FALSE;
1129 }
1130 if (outValues == NULL) {
1131 jniThrowNullPointerException(env, "out values");
1132 return JNI_FALSE;
1133 }
1134
1135 const jsize NI = env->GetArrayLength(attrs);
1136 const jsize NV = env->GetArrayLength(outValues);
1137 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1138 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1139 return JNI_FALSE;
1140 }
1141
1142 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1143 if (src == NULL) {
1144 return JNI_FALSE;
1145 }
1146
1147 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1148 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1149
1150 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1151 if (baseDest == NULL) {
1152 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1153 return JNI_FALSE;
1154 }
1155
1156 jint* indices = NULL;
1157 if (outIndices != NULL) {
1158 if (env->GetArrayLength(outIndices) > NI) {
1159 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1160 }
1161 }
1162
1163 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1164 bool result = ResolveAttrs(theme, defStyleAttr, defStyleRes,
1165 (uint32_t*) srcValues, NSV,
1166 (uint32_t*) src, NI,
1167 (uint32_t*) baseDest,
1168 (uint32_t*) indices);
1169
1170 if (indices != NULL) {
1171 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1172 }
1173 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1174 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1175 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1176 return result ? JNI_TRUE : JNI_FALSE;
1177 }
1178
android_content_AssetManager_applyStyle(JNIEnv * env,jobject,jlong themeToken,jint defStyleAttr,jint defStyleRes,jlong xmlParserToken,jintArray attrsObj,jint length,jlong outValuesAddress,jlong outIndicesAddress)1179 static void android_content_AssetManager_applyStyle(JNIEnv* env, jobject, jlong themeToken,
1180 jint defStyleAttr, jint defStyleRes, jlong xmlParserToken, jintArray attrsObj, jint length,
1181 jlong outValuesAddress, jlong outIndicesAddress) {
1182 jint* attrs = env->GetIntArrayElements(attrsObj, 0);
1183 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1184 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
1185 uint32_t* outValues = reinterpret_cast<uint32_t*>(static_cast<uintptr_t>(outValuesAddress));
1186 uint32_t* outIndices = reinterpret_cast<uint32_t*>(static_cast<uintptr_t>(outIndicesAddress));
1187 ApplyStyle(theme, xmlParser, defStyleAttr, defStyleRes,
1188 reinterpret_cast<const uint32_t*>(attrs), length, outValues, outIndices);
1189 env->ReleaseIntArrayElements(attrsObj, attrs, JNI_ABORT);
1190 }
1191
android_content_AssetManager_retrieveAttributes(JNIEnv * env,jobject clazz,jlong xmlParserToken,jintArray attrs,jintArray outValues,jintArray outIndices)1192 static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
1193 jlong xmlParserToken,
1194 jintArray attrs,
1195 jintArray outValues,
1196 jintArray outIndices)
1197 {
1198 if (xmlParserToken == 0) {
1199 jniThrowNullPointerException(env, "xmlParserToken");
1200 return JNI_FALSE;
1201 }
1202 if (attrs == NULL) {
1203 jniThrowNullPointerException(env, "attrs");
1204 return JNI_FALSE;
1205 }
1206 if (outValues == NULL) {
1207 jniThrowNullPointerException(env, "out values");
1208 return JNI_FALSE;
1209 }
1210
1211 AssetManager* am = assetManagerForJavaObject(env, clazz);
1212 if (am == NULL) {
1213 return JNI_FALSE;
1214 }
1215 const ResTable& res(am->getResources());
1216 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
1217
1218 const jsize NI = env->GetArrayLength(attrs);
1219 const jsize NV = env->GetArrayLength(outValues);
1220 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1221 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1222 return JNI_FALSE;
1223 }
1224
1225 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1226 if (src == NULL) {
1227 return JNI_FALSE;
1228 }
1229
1230 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1231 if (baseDest == NULL) {
1232 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1233 return JNI_FALSE;
1234 }
1235
1236 jint* indices = NULL;
1237 if (outIndices != NULL) {
1238 if (env->GetArrayLength(outIndices) > NI) {
1239 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1240 }
1241 }
1242
1243 bool result = RetrieveAttributes(&res, xmlParser,
1244 (uint32_t*) src, NI,
1245 (uint32_t*) baseDest,
1246 (uint32_t*) indices);
1247
1248 if (indices != NULL) {
1249 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1250 }
1251 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1252 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1253 return result ? JNI_TRUE : JNI_FALSE;
1254 }
1255
android_content_AssetManager_getArraySize(JNIEnv * env,jobject clazz,jint id)1256 static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1257 jint id)
1258 {
1259 AssetManager* am = assetManagerForJavaObject(env, clazz);
1260 if (am == NULL) {
1261 return 0;
1262 }
1263 const ResTable& res(am->getResources());
1264
1265 res.lock();
1266 const ResTable::bag_entry* defStyleEnt = NULL;
1267 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1268 res.unlock();
1269
1270 return static_cast<jint>(bagOff);
1271 }
1272
android_content_AssetManager_retrieveArray(JNIEnv * env,jobject clazz,jint id,jintArray outValues)1273 static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1274 jint id,
1275 jintArray outValues)
1276 {
1277 if (outValues == NULL) {
1278 jniThrowNullPointerException(env, "out values");
1279 return JNI_FALSE;
1280 }
1281
1282 AssetManager* am = assetManagerForJavaObject(env, clazz);
1283 if (am == NULL) {
1284 return JNI_FALSE;
1285 }
1286 const ResTable& res(am->getResources());
1287 ResTable_config config;
1288 Res_value value;
1289 ssize_t block;
1290
1291 const jsize NV = env->GetArrayLength(outValues);
1292
1293 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1294 jint* dest = baseDest;
1295 if (dest == NULL) {
1296 jniThrowException(env, "java/lang/OutOfMemoryError", "");
1297 return JNI_FALSE;
1298 }
1299
1300 // Now lock down the resource object and start pulling stuff from it.
1301 res.lock();
1302
1303 const ResTable::bag_entry* arrayEnt = NULL;
1304 uint32_t arrayTypeSetFlags = 0;
1305 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1306 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1307 (bagOff >= 0 ? bagOff : 0);
1308
1309 int i = 0;
1310 uint32_t typeSetFlags;
1311 while (i < NV && arrayEnt < endArrayEnt) {
1312 block = arrayEnt->stringBlock;
1313 typeSetFlags = arrayTypeSetFlags;
1314 config.density = 0;
1315 value = arrayEnt->map.value;
1316
1317 uint32_t resid = 0;
1318 if (value.dataType != Res_value::TYPE_NULL) {
1319 // Take care of resolving the found resource to its final value.
1320 //printf("Resolving attribute reference\n");
1321 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1322 &typeSetFlags, &config);
1323 if (kThrowOnBadId) {
1324 if (newBlock == BAD_INDEX) {
1325 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1326 return JNI_FALSE;
1327 }
1328 }
1329 if (newBlock >= 0) block = newBlock;
1330 }
1331
1332 // Deal with the special @null value -- it turns back to TYPE_NULL.
1333 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1334 value.dataType = Res_value::TYPE_NULL;
1335 value.data = Res_value::DATA_NULL_UNDEFINED;
1336 }
1337
1338 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1339
1340 // Write the final value back to Java.
1341 dest[STYLE_TYPE] = value.dataType;
1342 dest[STYLE_DATA] = value.data;
1343 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
1344 dest[STYLE_RESOURCE_ID] = resid;
1345 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1346 dest[STYLE_DENSITY] = config.density;
1347 dest += STYLE_NUM_ENTRIES;
1348 i+= STYLE_NUM_ENTRIES;
1349 arrayEnt++;
1350 }
1351
1352 i /= STYLE_NUM_ENTRIES;
1353
1354 res.unlock();
1355
1356 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1357
1358 return i;
1359 }
1360
android_content_AssetManager_openXmlAssetNative(JNIEnv * env,jobject clazz,jint cookie,jstring fileName)1361 static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
1362 jint cookie,
1363 jstring fileName)
1364 {
1365 AssetManager* am = assetManagerForJavaObject(env, clazz);
1366 if (am == NULL) {
1367 return 0;
1368 }
1369
1370 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
1371
1372 ScopedUtfChars fileName8(env, fileName);
1373 if (fileName8.c_str() == NULL) {
1374 return 0;
1375 }
1376
1377 int32_t assetCookie = static_cast<int32_t>(cookie);
1378 Asset* a = assetCookie
1379 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1380 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
1381
1382 if (a == NULL) {
1383 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
1384 return 0;
1385 }
1386
1387 const DynamicRefTable* dynamicRefTable =
1388 am->getResources().getDynamicRefTableForCookie(assetCookie);
1389 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
1390 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1391 a->close();
1392 delete a;
1393
1394 if (err != NO_ERROR) {
1395 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
1396 return 0;
1397 }
1398
1399 return reinterpret_cast<jlong>(block);
1400 }
1401
android_content_AssetManager_getArrayStringInfo(JNIEnv * env,jobject clazz,jint arrayResId)1402 static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1403 jint arrayResId)
1404 {
1405 AssetManager* am = assetManagerForJavaObject(env, clazz);
1406 if (am == NULL) {
1407 return NULL;
1408 }
1409 const ResTable& res(am->getResources());
1410
1411 const ResTable::bag_entry* startOfBag;
1412 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1413 if (N < 0) {
1414 return NULL;
1415 }
1416
1417 jintArray array = env->NewIntArray(N * 2);
1418 if (array == NULL) {
1419 res.unlockBag(startOfBag);
1420 return NULL;
1421 }
1422
1423 Res_value value;
1424 const ResTable::bag_entry* bag = startOfBag;
1425 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1426 jint stringIndex = -1;
1427 jint stringBlock = 0;
1428 value = bag->map.value;
1429
1430 // Take care of resolving the found resource to its final value.
1431 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1432 if (value.dataType == Res_value::TYPE_STRING) {
1433 stringIndex = value.data;
1434 }
1435
1436 if (kThrowOnBadId) {
1437 if (stringBlock == BAD_INDEX) {
1438 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1439 return array;
1440 }
1441 }
1442
1443 //todo: It might be faster to allocate a C array to contain
1444 // the blocknums and indices, put them in there and then
1445 // do just one SetIntArrayRegion()
1446 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1447 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1448 j = j + 2;
1449 }
1450 res.unlockBag(startOfBag);
1451 return array;
1452 }
1453
android_content_AssetManager_getArrayStringResource(JNIEnv * env,jobject clazz,jint arrayResId)1454 static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1455 jint arrayResId)
1456 {
1457 AssetManager* am = assetManagerForJavaObject(env, clazz);
1458 if (am == NULL) {
1459 return NULL;
1460 }
1461 const ResTable& res(am->getResources());
1462
1463 const ResTable::bag_entry* startOfBag;
1464 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1465 if (N < 0) {
1466 return NULL;
1467 }
1468
1469 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
1470 if (env->ExceptionCheck()) {
1471 res.unlockBag(startOfBag);
1472 return NULL;
1473 }
1474
1475 Res_value value;
1476 const ResTable::bag_entry* bag = startOfBag;
1477 size_t strLen = 0;
1478 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1479 value = bag->map.value;
1480 jstring str = NULL;
1481
1482 // Take care of resolving the found resource to its final value.
1483 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
1484 if (kThrowOnBadId) {
1485 if (block == BAD_INDEX) {
1486 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1487 return array;
1488 }
1489 }
1490 if (value.dataType == Res_value::TYPE_STRING) {
1491 const ResStringPool* pool = res.getTableStringBlock(block);
1492 const char* str8 = pool->string8At(value.data, &strLen);
1493 if (str8 != NULL) {
1494 str = env->NewStringUTF(str8);
1495 } else {
1496 const char16_t* str16 = pool->stringAt(value.data, &strLen);
1497 str = env->NewString(reinterpret_cast<const jchar*>(str16),
1498 strLen);
1499 }
1500
1501 // If one of our NewString{UTF} calls failed due to memory, an
1502 // exception will be pending.
1503 if (env->ExceptionCheck()) {
1504 res.unlockBag(startOfBag);
1505 return NULL;
1506 }
1507
1508 env->SetObjectArrayElement(array, i, str);
1509
1510 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1511 // If we have a large amount of strings in our array, we might
1512 // overflow the local reference table of the VM.
1513 env->DeleteLocalRef(str);
1514 }
1515 }
1516 res.unlockBag(startOfBag);
1517 return array;
1518 }
1519
android_content_AssetManager_getArrayIntResource(JNIEnv * env,jobject clazz,jint arrayResId)1520 static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1521 jint arrayResId)
1522 {
1523 AssetManager* am = assetManagerForJavaObject(env, clazz);
1524 if (am == NULL) {
1525 return NULL;
1526 }
1527 const ResTable& res(am->getResources());
1528
1529 const ResTable::bag_entry* startOfBag;
1530 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1531 if (N < 0) {
1532 return NULL;
1533 }
1534
1535 jintArray array = env->NewIntArray(N);
1536 if (array == NULL) {
1537 res.unlockBag(startOfBag);
1538 return NULL;
1539 }
1540
1541 Res_value value;
1542 const ResTable::bag_entry* bag = startOfBag;
1543 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1544 value = bag->map.value;
1545
1546 // Take care of resolving the found resource to its final value.
1547 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
1548 if (kThrowOnBadId) {
1549 if (block == BAD_INDEX) {
1550 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1551 return array;
1552 }
1553 }
1554 if (value.dataType >= Res_value::TYPE_FIRST_INT
1555 && value.dataType <= Res_value::TYPE_LAST_INT) {
1556 int intVal = value.data;
1557 env->SetIntArrayRegion(array, i, 1, &intVal);
1558 }
1559 }
1560 res.unlockBag(startOfBag);
1561 return array;
1562 }
1563
android_content_AssetManager_getStyleAttributes(JNIEnv * env,jobject clazz,jint styleId)1564 static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
1565 jint styleId)
1566 {
1567 AssetManager* am = assetManagerForJavaObject(env, clazz);
1568 if (am == NULL) {
1569 return NULL;
1570 }
1571 const ResTable& res(am->getResources());
1572
1573 const ResTable::bag_entry* startOfBag;
1574 const ssize_t N = res.lockBag(styleId, &startOfBag);
1575 if (N < 0) {
1576 return NULL;
1577 }
1578
1579 jintArray array = env->NewIntArray(N);
1580 if (array == NULL) {
1581 res.unlockBag(startOfBag);
1582 return NULL;
1583 }
1584
1585 const ResTable::bag_entry* bag = startOfBag;
1586 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1587 int resourceId = bag->map.name.ident;
1588 env->SetIntArrayRegion(array, i, 1, &resourceId);
1589 }
1590 res.unlockBag(startOfBag);
1591 return array;
1592 }
1593
android_content_AssetManager_init(JNIEnv * env,jobject clazz,jboolean isSystem)1594 static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
1595 {
1596 if (isSystem) {
1597 verifySystemIdmaps();
1598 }
1599 AssetManager* am = new AssetManager();
1600 if (am == NULL) {
1601 jniThrowException(env, "java/lang/OutOfMemoryError", "");
1602 return;
1603 }
1604
1605 am->addDefaultAssets();
1606
1607 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
1608 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
1609 }
1610
android_content_AssetManager_destroy(JNIEnv * env,jobject clazz)1611 static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
1612 {
1613 AssetManager* am = (AssetManager*)
1614 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
1615 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
1616 if (am != NULL) {
1617 delete am;
1618 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
1619 }
1620 }
1621
android_content_AssetManager_getGlobalAssetCount(JNIEnv * env,jobject clazz)1622 static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
1623 {
1624 return Asset::getGlobalCount();
1625 }
1626
android_content_AssetManager_getAssetAllocations(JNIEnv * env,jobject clazz)1627 static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
1628 {
1629 String8 alloc = Asset::getAssetAllocations();
1630 if (alloc.length() <= 0) {
1631 return NULL;
1632 }
1633
1634 jstring str = env->NewStringUTF(alloc.string());
1635 return str;
1636 }
1637
android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv * env,jobject clazz)1638 static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
1639 {
1640 return AssetManager::getGlobalCount();
1641 }
1642
1643 // ----------------------------------------------------------------------------
1644
1645 /*
1646 * JNI registration.
1647 */
1648 static const JNINativeMethod gAssetManagerMethods[] = {
1649 /* name, signature, funcPtr */
1650
1651 // Basic asset stuff.
1652 { "openAsset", "(Ljava/lang/String;I)J",
1653 (void*) android_content_AssetManager_openAsset },
1654 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
1655 (void*) android_content_AssetManager_openAssetFd },
1656 { "openNonAssetNative", "(ILjava/lang/String;I)J",
1657 (void*) android_content_AssetManager_openNonAssetNative },
1658 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
1659 (void*) android_content_AssetManager_openNonAssetFdNative },
1660 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
1661 (void*) android_content_AssetManager_list },
1662 { "destroyAsset", "(J)V",
1663 (void*) android_content_AssetManager_destroyAsset },
1664 { "readAssetChar", "(J)I",
1665 (void*) android_content_AssetManager_readAssetChar },
1666 { "readAsset", "(J[BII)I",
1667 (void*) android_content_AssetManager_readAsset },
1668 { "seekAsset", "(JJI)J",
1669 (void*) android_content_AssetManager_seekAsset },
1670 { "getAssetLength", "(J)J",
1671 (void*) android_content_AssetManager_getAssetLength },
1672 { "getAssetRemainingLength", "(J)J",
1673 (void*) android_content_AssetManager_getAssetRemainingLength },
1674 { "addAssetPathNative", "(Ljava/lang/String;Z)I",
1675 (void*) android_content_AssetManager_addAssetPath },
1676 { "addOverlayPathNative", "(Ljava/lang/String;)I",
1677 (void*) android_content_AssetManager_addOverlayPath },
1678 { "isUpToDate", "()Z",
1679 (void*) android_content_AssetManager_isUpToDate },
1680
1681 // Resources.
1682 { "getLocales", "()[Ljava/lang/String;",
1683 (void*) android_content_AssetManager_getLocales },
1684 { "getNonSystemLocales", "()[Ljava/lang/String;",
1685 (void*) android_content_AssetManager_getNonSystemLocales },
1686 { "getSizeConfigurations", "()[Landroid/content/res/Configuration;",
1687 (void*) android_content_AssetManager_getSizeConfigurations },
1688 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIIII)V",
1689 (void*) android_content_AssetManager_setConfiguration },
1690 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
1691 (void*) android_content_AssetManager_getResourceIdentifier },
1692 { "getResourceName","(I)Ljava/lang/String;",
1693 (void*) android_content_AssetManager_getResourceName },
1694 { "getResourcePackageName","(I)Ljava/lang/String;",
1695 (void*) android_content_AssetManager_getResourcePackageName },
1696 { "getResourceTypeName","(I)Ljava/lang/String;",
1697 (void*) android_content_AssetManager_getResourceTypeName },
1698 { "getResourceEntryName","(I)Ljava/lang/String;",
1699 (void*) android_content_AssetManager_getResourceEntryName },
1700 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
1701 (void*) android_content_AssetManager_loadResourceValue },
1702 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
1703 (void*) android_content_AssetManager_loadResourceBagValue },
1704 { "getStringBlockCount","()I",
1705 (void*) android_content_AssetManager_getStringBlockCount },
1706 { "getNativeStringBlock","(I)J",
1707 (void*) android_content_AssetManager_getNativeStringBlock },
1708 { "getCookieName","(I)Ljava/lang/String;",
1709 (void*) android_content_AssetManager_getCookieName },
1710 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
1711 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
1712
1713 // Themes.
1714 { "newTheme", "()J",
1715 (void*) android_content_AssetManager_newTheme },
1716 { "deleteTheme", "(J)V",
1717 (void*) android_content_AssetManager_deleteTheme },
1718 { "applyThemeStyle", "(JIZ)V",
1719 (void*) android_content_AssetManager_applyThemeStyle },
1720 { "copyTheme", "(JJ)V",
1721 (void*) android_content_AssetManager_copyTheme },
1722 { "clearTheme", "(J)V",
1723 (void*) android_content_AssetManager_clearTheme },
1724 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
1725 (void*) android_content_AssetManager_loadThemeAttributeValue },
1726 { "getThemeChangingConfigurations", "(J)I",
1727 (void*) android_content_AssetManager_getThemeChangingConfigurations },
1728 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
1729 (void*) android_content_AssetManager_dumpTheme },
1730 { "applyStyle","(JIIJ[IIJJ)V",
1731 (void*) android_content_AssetManager_applyStyle },
1732 { "resolveAttrs","(JII[I[I[I[I)Z",
1733 (void*) android_content_AssetManager_resolveAttrs },
1734 { "retrieveAttributes","(J[I[I[I)Z",
1735 (void*) android_content_AssetManager_retrieveAttributes },
1736 { "getArraySize","(I)I",
1737 (void*) android_content_AssetManager_getArraySize },
1738 { "retrieveArray","(I[I)I",
1739 (void*) android_content_AssetManager_retrieveArray },
1740
1741 // XML files.
1742 { "openXmlAssetNative", "(ILjava/lang/String;)J",
1743 (void*) android_content_AssetManager_openXmlAssetNative },
1744
1745 // Arrays.
1746 { "getArrayStringResource","(I)[Ljava/lang/String;",
1747 (void*) android_content_AssetManager_getArrayStringResource },
1748 { "getArrayStringInfo","(I)[I",
1749 (void*) android_content_AssetManager_getArrayStringInfo },
1750 { "getArrayIntResource","(I)[I",
1751 (void*) android_content_AssetManager_getArrayIntResource },
1752 { "getStyleAttributes","(I)[I",
1753 (void*) android_content_AssetManager_getStyleAttributes },
1754
1755 // Bookkeeping.
1756 { "init", "(Z)V",
1757 (void*) android_content_AssetManager_init },
1758 { "destroy", "()V",
1759 (void*) android_content_AssetManager_destroy },
1760 { "getGlobalAssetCount", "()I",
1761 (void*) android_content_AssetManager_getGlobalAssetCount },
1762 { "getAssetAllocations", "()Ljava/lang/String;",
1763 (void*) android_content_AssetManager_getAssetAllocations },
1764 { "getGlobalAssetManagerCount", "()I",
1765 (void*) android_content_AssetManager_getGlobalAssetManagerCount },
1766 };
1767
register_android_content_AssetManager(JNIEnv * env)1768 int register_android_content_AssetManager(JNIEnv* env)
1769 {
1770 jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
1771 gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
1772 gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
1773 gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
1774 "Ljava/lang/CharSequence;");
1775 gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
1776 gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
1777 gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
1778 "changingConfigurations", "I");
1779 gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
1780
1781 jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
1782 gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
1783 "Landroid/os/ParcelFileDescriptor;");
1784 gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
1785 gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
1786
1787 jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
1788 gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
1789
1790 jclass stringClass = FindClassOrDie(env, "java/lang/String");
1791 g_stringClass = MakeGlobalRefOrDie(env, stringClass);
1792
1793 jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
1794 gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
1795 gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
1796 "<init>", "()V");
1797 gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
1798 "(ILjava/lang/Object;)V");
1799
1800 jclass configurationClass = FindClassOrDie(env, "android/content/res/Configuration");
1801 gConfigurationOffsets.classObject = MakeGlobalRefOrDie(env, configurationClass);
1802 gConfigurationOffsets.constructor = GetMethodIDOrDie(env, configurationClass,
1803 "<init>", "()V");
1804 gConfigurationOffsets.mSmallestScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
1805 "smallestScreenWidthDp", "I");
1806 gConfigurationOffsets.mScreenWidthDpOffset = GetFieldIDOrDie(env, configurationClass,
1807 "screenWidthDp", "I");
1808 gConfigurationOffsets.mScreenHeightDpOffset = GetFieldIDOrDie(env, configurationClass,
1809 "screenHeightDp", "I");
1810
1811 return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
1812 NELEM(gAssetManagerMethods));
1813 }
1814
1815 }; // namespace android
1816