blob: aaceb4b011e0b85d1e7a983c1480cc2bddb18c69 [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**
Elliott Hughes69a017b2011-04-08 14:10:28 -07005** 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008**
Elliott Hughes69a017b2011-04-08 14:10:28 -07009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010**
Elliott Hughes69a017b2011-04-08 14:10:28 -070011** 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015** limitations under the License.
16*/
17
18#define LOG_TAG "asset"
19
20#include <android_runtime/android_util_AssetManager.h>
21
Dan Albert46d84442014-11-18 16:07:51 -080022#include <inttypes.h>
23#include <linux/capability.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024#include <stdio.h>
Mårten Kongstad48d22322014-01-31 14:43:27 +010025#include <sys/types.h>
26#include <sys/wait.h>
27
Dan Albert46d84442014-11-18 16:07:51 -080028#include <private/android_filesystem_config.h> // for AID_SYSTEM
29
30#include "JNIHelp.h"
31#include "ScopedStringChars.h"
32#include "ScopedUtfChars.h"
33#include "android_runtime/AndroidRuntime.h"
34#include "android_util_Binder.h"
35#include "androidfw/Asset.h"
36#include "androidfw/AssetManager.h"
37#include "androidfw/ResourceTypes.h"
38#include "core_jni_helpers.h"
39#include "jni.h"
40#include "utils/Log.h"
41#include "utils/misc.h"
42
Mårten Kongstad48d22322014-01-31 14:43:27 +010043extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
44extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
45
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046
47namespace android {
48
Andreas Gampe0f0b4912014-11-12 08:03:48 -080049static const bool kThrowOnBadId = false;
50static const bool kDebugStyles = false;
51
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052// ----------------------------------------------------------------------------
53
54static struct typedvalue_offsets_t
55{
56 jfieldID mType;
57 jfieldID mData;
58 jfieldID mString;
59 jfieldID mAssetCookie;
60 jfieldID mResourceId;
61 jfieldID mChangingConfigurations;
62 jfieldID mDensity;
63} gTypedValueOffsets;
64
65static struct assetfiledescriptor_offsets_t
66{
67 jfieldID mFd;
68 jfieldID mStartOffset;
69 jfieldID mLength;
70} gAssetFileDescriptorOffsets;
71
72static struct assetmanager_offsets_t
73{
74 jfieldID mObject;
75} gAssetManagerOffsets;
76
Adam Lesinskide898ff2014-01-29 18:20:45 -080077static struct sparsearray_offsets_t
78{
79 jclass classObject;
80 jmethodID constructor;
81 jmethodID put;
82} gSparseArrayOffsets;
83
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084jclass g_stringClass = NULL;
85
86// ----------------------------------------------------------------------------
87
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088enum {
Dianne Hackborn0d221012009-07-29 15:41:19 -070089 STYLE_NUM_ENTRIES = 6,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 STYLE_TYPE = 0,
91 STYLE_DATA = 1,
92 STYLE_ASSET_COOKIE = 2,
93 STYLE_RESOURCE_ID = 3,
Dianne Hackborn0d221012009-07-29 15:41:19 -070094 STYLE_CHANGING_CONFIGURATIONS = 4,
95 STYLE_DENSITY = 5
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096};
97
98static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
99 const Res_value& value, uint32_t ref, ssize_t block,
100 uint32_t typeSpecFlags, ResTable_config* config = NULL);
101
102jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
103 const Res_value& value, uint32_t ref, ssize_t block,
104 uint32_t typeSpecFlags, ResTable_config* config)
105{
106 env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
107 env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
Ashok Bhat896043d2014-01-17 16:02:38 +0000108 static_cast<jint>(table->getTableCookie(block)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109 env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
110 env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
111 env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
112 env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
113 typeSpecFlags);
114 if (config != NULL) {
115 env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
116 }
117 return block;
118}
119
Mårten Kongstad48d22322014-01-31 14:43:27 +0100120// This is called by zygote (running as user root) as part of preloadResources.
121static void verifySystemIdmaps()
122{
123 pid_t pid;
124 char system_id[10];
125
126 snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
127
128 switch (pid = fork()) {
129 case -1:
130 ALOGE("failed to fork for idmap: %s", strerror(errno));
131 break;
132 case 0: // child
133 {
134 struct __user_cap_header_struct capheader;
135 struct __user_cap_data_struct capdata;
136
137 memset(&capheader, 0, sizeof(capheader));
138 memset(&capdata, 0, sizeof(capdata));
139
140 capheader.version = _LINUX_CAPABILITY_VERSION;
141 capheader.pid = 0;
142
143 if (capget(&capheader, &capdata) != 0) {
144 ALOGE("capget: %s\n", strerror(errno));
145 exit(1);
146 }
147
148 capdata.effective = capdata.permitted;
149 if (capset(&capheader, &capdata) != 0) {
150 ALOGE("capset: %s\n", strerror(errno));
151 exit(1);
152 }
153
154 if (setgid(AID_SYSTEM) != 0) {
155 ALOGE("setgid: %s\n", strerror(errno));
156 exit(1);
157 }
158
159 if (setuid(AID_SYSTEM) != 0) {
160 ALOGE("setuid: %s\n", strerror(errno));
161 exit(1);
162 }
163
164 execl(AssetManager::IDMAP_BIN, AssetManager::IDMAP_BIN, "--scan",
165 AssetManager::OVERLAY_DIR, AssetManager::TARGET_PACKAGE_NAME,
166 AssetManager::TARGET_APK_PATH, AssetManager::IDMAP_DIR, (char*)NULL);
167 ALOGE("failed to execl for idmap: %s", strerror(errno));
168 exit(1); // should never get here
169 }
170 break;
171 default: // parent
172 waitpid(pid, NULL, 0);
173 break;
174 }
175}
176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177// ----------------------------------------------------------------------------
178
179// this guy is exported to other jni routines
180AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
181{
Ashok Bhat896043d2014-01-17 16:02:38 +0000182 jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
183 AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 if (am != NULL) {
185 return am;
186 }
187 jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
188 return NULL;
189}
190
Ashok Bhat896043d2014-01-17 16:02:38 +0000191static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 jstring fileName, jint mode)
193{
194 AssetManager* am = assetManagerForJavaObject(env, clazz);
195 if (am == NULL) {
196 return 0;
197 }
198
Steve Block71f2cf12011-10-20 11:56:00 +0100199 ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200
Elliott Hughes69a017b2011-04-08 14:10:28 -0700201 ScopedUtfChars fileName8(env, fileName);
202 if (fileName8.c_str() == NULL) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000203 jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 return -1;
205 }
206
207 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
208 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700209 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 return -1;
211 }
212
Elliott Hughes69a017b2011-04-08 14:10:28 -0700213 Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214
215 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700216 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 return -1;
218 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219
220 //printf("Created Asset Stream: %p\n", a);
221
Ashok Bhat896043d2014-01-17 16:02:38 +0000222 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223}
224
225static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
226{
Kenny Rootddb76c42010-11-24 12:56:06 -0800227 off64_t startOffset, length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 int fd = a->openFileDescriptor(&startOffset, &length);
229 delete a;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 if (fd < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700232 jniThrowException(env, "java/io/FileNotFoundException",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 "This file can not be opened as a file descriptor; it is probably compressed");
234 return NULL;
235 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
238 if (offsets == NULL) {
239 close(fd);
240 return NULL;
241 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243 offsets[0] = startOffset;
244 offsets[1] = length;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700247
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700248 jobject fileDesc = jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 if (fileDesc == NULL) {
250 close(fd);
251 return NULL;
252 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 return newParcelFileDescriptor(env, fileDesc);
255}
256
257static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
258 jstring fileName, jlongArray outOffsets)
259{
260 AssetManager* am = assetManagerForJavaObject(env, clazz);
261 if (am == NULL) {
262 return NULL;
263 }
264
Steve Block71f2cf12011-10-20 11:56:00 +0100265 ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266
Elliott Hughes69a017b2011-04-08 14:10:28 -0700267 ScopedUtfChars fileName8(env, fileName);
268 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 return NULL;
270 }
271
Elliott Hughes69a017b2011-04-08 14:10:28 -0700272 Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273
274 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700275 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 return NULL;
277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278
279 //printf("Created Asset Stream: %p\n", a);
280
281 return returnParcelFileDescriptor(env, a, outOffsets);
282}
283
Ashok Bhat896043d2014-01-17 16:02:38 +0000284static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285 jint cookie,
286 jstring fileName,
287 jint mode)
288{
289 AssetManager* am = assetManagerForJavaObject(env, clazz);
290 if (am == NULL) {
291 return 0;
292 }
293
Steve Block71f2cf12011-10-20 11:56:00 +0100294 ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295
Elliott Hughes69a017b2011-04-08 14:10:28 -0700296 ScopedUtfChars fileName8(env, fileName);
297 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298 return -1;
299 }
300
301 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
302 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700303 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 return -1;
305 }
306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000308 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
309 (Asset::AccessMode)mode)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700310 : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311
312 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700313 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 return -1;
315 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316
317 //printf("Created Asset Stream: %p\n", a);
318
Ashok Bhat896043d2014-01-17 16:02:38 +0000319 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320}
321
322static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
323 jint cookie,
324 jstring fileName,
325 jlongArray outOffsets)
326{
327 AssetManager* am = assetManagerForJavaObject(env, clazz);
328 if (am == NULL) {
329 return NULL;
330 }
331
Steve Block71f2cf12011-10-20 11:56:00 +0100332 ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333
Elliott Hughes69a017b2011-04-08 14:10:28 -0700334 ScopedUtfChars fileName8(env, fileName);
335 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 return NULL;
337 }
338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000340 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700341 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342
343 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700344 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800345 return NULL;
346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347
348 //printf("Created Asset Stream: %p\n", a);
349
350 return returnParcelFileDescriptor(env, a, outOffsets);
351}
352
353static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
354 jstring fileName)
355{
356 AssetManager* am = assetManagerForJavaObject(env, clazz);
357 if (am == NULL) {
358 return NULL;
359 }
360
Elliott Hughes69a017b2011-04-08 14:10:28 -0700361 ScopedUtfChars fileName8(env, fileName);
362 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 return NULL;
364 }
365
Elliott Hughes69a017b2011-04-08 14:10:28 -0700366 AssetDir* dir = am->openDir(fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800367
368 if (dir == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700369 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 return NULL;
371 }
372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800373 size_t N = dir->getFileCount();
374
375 jobjectArray array = env->NewObjectArray(dir->getFileCount(),
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +0100376 g_stringClass, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 delete dir;
379 return NULL;
380 }
381
382 for (size_t i=0; i<N; i++) {
383 const String8& name = dir->getFileName(i);
384 jstring str = env->NewStringUTF(name.string());
385 if (str == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 delete dir;
387 return NULL;
388 }
389 env->SetObjectArrayElement(array, i, str);
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700390 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 }
392
393 delete dir;
394
395 return array;
396}
397
398static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000399 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400{
Ashok Bhat896043d2014-01-17 16:02:38 +0000401 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402
403 //printf("Destroying Asset Stream: %p\n", a);
404
405 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700406 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 return;
408 }
409
410 delete a;
411}
412
413static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000414 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415{
Ashok Bhat896043d2014-01-17 16:02:38 +0000416 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417
418 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700419 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420 return -1;
421 }
422
423 uint8_t b;
424 ssize_t res = a->read(&b, 1);
425 return res == 1 ? b : -1;
426}
427
428static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000429 jlong assetHandle, jbyteArray bArray,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430 jint off, jint len)
431{
Ashok Bhat896043d2014-01-17 16:02:38 +0000432 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433
434 if (a == NULL || bArray == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700435 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 return -1;
437 }
438
439 if (len == 0) {
440 return 0;
441 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 jsize bLen = env->GetArrayLength(bArray);
444 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700445 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 return -1;
447 }
448
449 jbyte* b = env->GetByteArrayElements(bArray, NULL);
450 ssize_t res = a->read(b+off, len);
451 env->ReleaseByteArrayElements(bArray, b, 0);
452
Ashok Bhat896043d2014-01-17 16:02:38 +0000453 if (res > 0) return static_cast<jint>(res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454
455 if (res < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700456 jniThrowException(env, "java/io/IOException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 }
458 return -1;
459}
460
461static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000462 jlong assetHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 jlong offset, jint whence)
464{
Ashok Bhat896043d2014-01-17 16:02:38 +0000465 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466
467 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700468 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800469 return -1;
470 }
471
472 return a->seek(
473 offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
474}
475
476static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000477 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478{
Ashok Bhat896043d2014-01-17 16:02:38 +0000479 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480
481 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700482 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800483 return -1;
484 }
485
486 return a->getLength();
487}
488
489static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000490 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800491{
Ashok Bhat896043d2014-01-17 16:02:38 +0000492 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493
494 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700495 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800496 return -1;
497 }
498
499 return a->getRemainingLength();
500}
501
502static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
503 jstring path)
504{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700505 ScopedUtfChars path8(env, path);
506 if (path8.c_str() == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800507 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508 }
509
510 AssetManager* am = assetManagerForJavaObject(env, clazz);
511 if (am == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800512 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800513 }
514
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000515 int32_t cookie;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700516 bool res = am->addAssetPath(String8(path8.c_str()), &cookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000518 return (res) ? static_cast<jint>(cookie) : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519}
520
Mårten Kongstad48d22322014-01-31 14:43:27 +0100521static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
522 jstring idmapPath)
523{
524 ScopedUtfChars idmapPath8(env, idmapPath);
525 if (idmapPath8.c_str() == NULL) {
526 return 0;
527 }
528
529 AssetManager* am = assetManagerForJavaObject(env, clazz);
530 if (am == NULL) {
531 return 0;
532 }
533
534 int32_t cookie;
535 bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
536
537 return (res) ? (jint)cookie : 0;
538}
539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
541{
542 AssetManager* am = assetManagerForJavaObject(env, clazz);
543 if (am == NULL) {
544 return JNI_TRUE;
545 }
546 return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
547}
548
549static void android_content_AssetManager_setLocale(JNIEnv* env, jobject clazz,
550 jstring locale)
551{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700552 ScopedUtfChars locale8(env, locale);
553 if (locale8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 return;
555 }
556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 AssetManager* am = assetManagerForJavaObject(env, clazz);
558 if (am == NULL) {
559 return;
560 }
561
Elliott Hughes69a017b2011-04-08 14:10:28 -0700562 am->setLocale(locale8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563}
564
565static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
566{
567 Vector<String8> locales;
568
569 AssetManager* am = assetManagerForJavaObject(env, clazz);
570 if (am == NULL) {
571 return NULL;
572 }
573
574 am->getLocales(&locales);
575
576 const int N = locales.size();
577
578 jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
579 if (result == NULL) {
580 return NULL;
581 }
582
583 for (int i=0; i<N; i++) {
Gilles Debunne0db187a2010-08-27 11:51:34 -0700584 jstring str = env->NewStringUTF(locales[i].string());
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700585 if (str == NULL) {
586 return NULL;
587 }
588 env->SetObjectArrayElement(result, i, str);
589 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590 }
591
592 return result;
593}
594
595static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
596 jint mcc, jint mnc,
597 jstring locale, jint orientation,
598 jint touchscreen, jint density,
599 jint keyboard, jint keyboardHidden,
600 jint navigation,
601 jint screenWidth, jint screenHeight,
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700602 jint smallestScreenWidthDp,
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700603 jint screenWidthDp, jint screenHeightDp,
Tobias Haamel27b28b32010-02-09 23:09:17 +0100604 jint screenLayout, jint uiMode,
605 jint sdkVersion)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800606{
607 AssetManager* am = assetManagerForJavaObject(env, clazz);
608 if (am == NULL) {
609 return;
610 }
611
612 ResTable_config config;
613 memset(&config, 0, sizeof(config));
Elliott Hughes69a017b2011-04-08 14:10:28 -0700614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800615 const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800617 config.mcc = (uint16_t)mcc;
618 config.mnc = (uint16_t)mnc;
619 config.orientation = (uint8_t)orientation;
620 config.touchscreen = (uint8_t)touchscreen;
621 config.density = (uint16_t)density;
622 config.keyboard = (uint8_t)keyboard;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700623 config.inputFlags = (uint8_t)keyboardHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624 config.navigation = (uint8_t)navigation;
625 config.screenWidth = (uint16_t)screenWidth;
626 config.screenHeight = (uint16_t)screenHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700627 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700628 config.screenWidthDp = (uint16_t)screenWidthDp;
629 config.screenHeightDp = (uint16_t)screenHeightDp;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700630 config.screenLayout = (uint8_t)screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100631 config.uiMode = (uint8_t)uiMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800632 config.sdkVersion = (uint16_t)sdkVersion;
633 config.minorVersion = 0;
634 am->setConfiguration(config, locale8);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
637}
638
639static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
640 jstring name,
641 jstring defType,
642 jstring defPackage)
643{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700644 ScopedStringChars name16(env, name);
645 if (name16.get() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 return 0;
647 }
648
649 AssetManager* am = assetManagerForJavaObject(env, clazz);
650 if (am == NULL) {
651 return 0;
652 }
653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800654 const char16_t* defType16 = defType
655 ? env->GetStringChars(defType, NULL) : NULL;
656 jsize defTypeLen = defType
657 ? env->GetStringLength(defType) : 0;
658 const char16_t* defPackage16 = defPackage
659 ? env->GetStringChars(defPackage, NULL) : NULL;
660 jsize defPackageLen = defPackage
661 ? env->GetStringLength(defPackage) : 0;
662
663 jint ident = am->getResources().identifierForName(
Elliott Hughes69a017b2011-04-08 14:10:28 -0700664 name16.get(), name16.size(), defType16, defTypeLen, defPackage16, defPackageLen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800665
666 if (defPackage16) {
667 env->ReleaseStringChars(defPackage, defPackage16);
668 }
669 if (defType16) {
670 env->ReleaseStringChars(defType, defType16);
671 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672
673 return ident;
674}
675
676static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
677 jint resid)
678{
679 AssetManager* am = assetManagerForJavaObject(env, clazz);
680 if (am == NULL) {
681 return NULL;
682 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700685 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800686 return NULL;
687 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689 String16 str;
690 if (name.package != NULL) {
691 str.setTo(name.package, name.packageLen);
692 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700693 if (name.type8 != NULL || name.type != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 if (str.size() > 0) {
695 char16_t div = ':';
696 str.append(&div, 1);
697 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700698 if (name.type8 != NULL) {
699 str.append(String16(name.type8, name.typeLen));
700 } else {
701 str.append(name.type, name.typeLen);
702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700704 if (name.name8 != NULL || name.name != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705 if (str.size() > 0) {
706 char16_t div = '/';
707 str.append(&div, 1);
708 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700709 if (name.name8 != NULL) {
710 str.append(String16(name.name8, name.nameLen));
711 } else {
712 str.append(name.name, name.nameLen);
713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800714 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 return env->NewString((const jchar*)str.string(), str.size());
717}
718
719static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
720 jint resid)
721{
722 AssetManager* am = assetManagerForJavaObject(env, clazz);
723 if (am == NULL) {
724 return NULL;
725 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800727 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700728 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 return NULL;
730 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 if (name.package != NULL) {
733 return env->NewString((const jchar*)name.package, name.packageLen);
734 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736 return NULL;
737}
738
739static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
740 jint resid)
741{
742 AssetManager* am = assetManagerForJavaObject(env, clazz);
743 if (am == NULL) {
744 return NULL;
745 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700748 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800749 return NULL;
750 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700751
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700752 if (name.type8 != NULL) {
753 return env->NewStringUTF(name.type8);
754 }
755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 if (name.type != NULL) {
757 return env->NewString((const jchar*)name.type, name.typeLen);
758 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 return NULL;
761}
762
763static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
764 jint resid)
765{
766 AssetManager* am = assetManagerForJavaObject(env, clazz);
767 if (am == NULL) {
768 return NULL;
769 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700770
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800771 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700772 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773 return NULL;
774 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700775
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700776 if (name.name8 != NULL) {
777 return env->NewStringUTF(name.name8);
778 }
779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 if (name.name != NULL) {
781 return env->NewString((const jchar*)name.name, name.nameLen);
782 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 return NULL;
785}
786
787static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
788 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700789 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790 jobject outValue,
791 jboolean resolve)
792{
Dianne Hackborn1f7d3072013-02-11 17:03:32 -0800793 if (outValue == NULL) {
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800794 jniThrowNullPointerException(env, "outValue");
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700795 return 0;
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800796 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 AssetManager* am = assetManagerForJavaObject(env, clazz);
798 if (am == NULL) {
799 return 0;
800 }
801 const ResTable& res(am->getResources());
802
803 Res_value value;
804 ResTable_config config;
805 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700806 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800807 if (kThrowOnBadId) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800808 if (block == BAD_INDEX) {
809 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
810 return 0;
811 }
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800812 }
813 uint32_t ref = ident;
814 if (resolve) {
815 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
816 if (kThrowOnBadId) {
817 if (block == BAD_INDEX) {
818 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
819 return 0;
820 }
821 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000823 if (block >= 0) {
824 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
825 }
826
827 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828}
829
830static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
831 jint ident, jint bagEntryId,
832 jobject outValue, jboolean resolve)
833{
834 AssetManager* am = assetManagerForJavaObject(env, clazz);
835 if (am == NULL) {
836 return 0;
837 }
838 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 // Now lock down the resource object and start pulling stuff from it.
841 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -0700842
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800843 ssize_t block = -1;
844 Res_value value;
845
846 const ResTable::bag_entry* entry = NULL;
847 uint32_t typeSpecFlags;
848 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
849
850 for (ssize_t i=0; i<entryCount; i++) {
851 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
852 block = entry->stringBlock;
853 value = entry->map.value;
854 }
855 entry++;
856 }
857
858 res.unlock();
859
860 if (block < 0) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000861 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800862 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 uint32_t ref = ident;
865 if (resolve) {
866 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800867 if (kThrowOnBadId) {
868 if (block == BAD_INDEX) {
869 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
870 return 0;
871 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800872 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000874 if (block >= 0) {
875 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
876 }
877
878 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879}
880
881static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
882{
883 AssetManager* am = assetManagerForJavaObject(env, clazz);
884 if (am == NULL) {
885 return 0;
886 }
887 return am->getResources().getTableCount();
888}
889
Ashok Bhat896043d2014-01-17 16:02:38 +0000890static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800891 jint block)
892{
893 AssetManager* am = assetManagerForJavaObject(env, clazz);
894 if (am == NULL) {
895 return 0;
896 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000897 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800898}
899
900static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
901 jint cookie)
902{
903 AssetManager* am = assetManagerForJavaObject(env, clazz);
904 if (am == NULL) {
905 return NULL;
906 }
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000907 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800908 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700909 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 return NULL;
911 }
912 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913 return str;
914}
915
Adam Lesinskide898ff2014-01-29 18:20:45 -0800916static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
917{
918 AssetManager* am = assetManagerForJavaObject(env, clazz);
919 if (am == NULL) {
920 return 0;
921 }
922
923 const ResTable& res = am->getResources();
924
925 jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
926 gSparseArrayOffsets.constructor);
927 const size_t N = res.getBasePackageCount();
928 for (size_t i = 0; i < N; i++) {
929 const String16 name = res.getBasePackageName(i);
930 env->CallVoidMethod(sparseArray, gSparseArrayOffsets.put, (jint) res.getBasePackageId(i),
931 env->NewString(name, name.size()));
932 }
933 return sparseArray;
934}
935
Ashok Bhat896043d2014-01-17 16:02:38 +0000936static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800937{
938 AssetManager* am = assetManagerForJavaObject(env, clazz);
939 if (am == NULL) {
940 return 0;
941 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000942 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800943}
944
945static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000946 jlong themeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947{
Ashok Bhat896043d2014-01-17 16:02:38 +0000948 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949 delete theme;
950}
951
952static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000953 jlong themeHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 jint styleRes,
955 jboolean force)
956{
Ashok Bhat896043d2014-01-17 16:02:38 +0000957 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800958 theme->applyStyle(styleRes, force ? true : false);
959}
960
961static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000962 jlong destHandle, jlong srcHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800963{
Ashok Bhat896043d2014-01-17 16:02:38 +0000964 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
965 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800966 dest->setTo(*src);
967}
968
969static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +0000970 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971{
Ashok Bhat896043d2014-01-17 16:02:38 +0000972 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 const ResTable& res(theme->getResTable());
974
975 Res_value value;
976 // XXX value could be different in different configs!
977 uint32_t typeSpecFlags = 0;
978 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
979 uint32_t ref = 0;
980 if (resolve) {
981 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800982 if (kThrowOnBadId) {
983 if (block == BAD_INDEX) {
984 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
985 return 0;
986 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800987 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 }
989 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
990}
991
992static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000993 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 jstring tag, jstring prefix)
995{
Ashok Bhat896043d2014-01-17 16:02:38 +0000996 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 const ResTable& res(theme->getResTable());
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800998 (void)res;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700999
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 // XXX Need to use params.
1001 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002}
1003
Alan Viverette52b999f2014-03-24 18:00:26 -07001004static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1005 jlong themeToken,
1006 jint defStyleAttr,
1007 jint defStyleRes,
1008 jintArray inValues,
1009 jintArray attrs,
1010 jintArray outValues,
1011 jintArray outIndices)
1012{
1013 if (themeToken == 0) {
1014 jniThrowNullPointerException(env, "theme token");
1015 return JNI_FALSE;
1016 }
1017 if (attrs == NULL) {
1018 jniThrowNullPointerException(env, "attrs");
1019 return JNI_FALSE;
1020 }
1021 if (outValues == NULL) {
1022 jniThrowNullPointerException(env, "out values");
1023 return JNI_FALSE;
1024 }
1025
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001026 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001027 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x "
1028 "defStyleRes=0x%x", themeToken, defStyleAttr, defStyleRes);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001029 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001030
1031 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1032 const ResTable& res = theme->getResTable();
1033 ResTable_config config;
1034 Res_value value;
1035
1036 const jsize NI = env->GetArrayLength(attrs);
1037 const jsize NV = env->GetArrayLength(outValues);
1038 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1039 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1040 return JNI_FALSE;
1041 }
1042
1043 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1044 if (src == NULL) {
1045 return JNI_FALSE;
1046 }
1047
1048 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1049 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1050
1051 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1052 jint* dest = baseDest;
1053 if (dest == NULL) {
1054 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1055 return JNI_FALSE;
1056 }
1057
1058 jint* indices = NULL;
1059 int indicesIdx = 0;
1060 if (outIndices != NULL) {
1061 if (env->GetArrayLength(outIndices) > NI) {
1062 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1063 }
1064 }
1065
1066 // Load default style from attribute, if specified...
1067 uint32_t defStyleBagTypeSetFlags = 0;
1068 if (defStyleAttr != 0) {
1069 Res_value value;
1070 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1071 if (value.dataType == Res_value::TYPE_REFERENCE) {
1072 defStyleRes = value.data;
1073 }
1074 }
1075 }
1076
1077 // Now lock down the resource object and start pulling stuff from it.
1078 res.lock();
1079
1080 // Retrieve the default style bag, if requested.
1081 const ResTable::bag_entry* defStyleEnt = NULL;
1082 uint32_t defStyleTypeSetFlags = 0;
1083 ssize_t bagOff = defStyleRes != 0
1084 ? res.getBagLocked(defStyleRes, &defStyleEnt, &defStyleTypeSetFlags) : -1;
1085 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
1086 const ResTable::bag_entry* endDefStyleEnt = defStyleEnt +
1087 (bagOff >= 0 ? bagOff : 0);;
1088
1089 // Now iterate through all of the attributes that the client has requested,
1090 // filling in each with whatever data we can find.
1091 ssize_t block = 0;
1092 uint32_t typeSetFlags;
1093 for (jsize ii=0; ii<NI; ii++) {
1094 const uint32_t curIdent = (uint32_t)src[ii];
1095
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001096 if (kDebugStyles) {
1097 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1098 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001099
1100 // Try to find a value for this attribute... we prioritize values
1101 // coming from, first XML attributes, then XML style, then default
1102 // style, and finally the theme.
1103 value.dataType = Res_value::TYPE_NULL;
1104 value.data = 0;
1105 typeSetFlags = 0;
1106 config.density = 0;
1107
1108 // Retrieve the current input value if available.
1109 if (NSV > 0 && srcValues[ii] != 0) {
1110 block = -1;
1111 value.dataType = Res_value::TYPE_ATTRIBUTE;
1112 value.data = srcValues[ii];
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001113 if (kDebugStyles) {
1114 ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
1115 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001116 }
1117
1118 // Skip through the default style values until the end or the next possible match.
1119 while (defStyleEnt < endDefStyleEnt && curIdent > defStyleEnt->map.name.ident) {
1120 defStyleEnt++;
1121 }
1122 // Retrieve the current default style attribute if it matches, and step to next.
1123 if (defStyleEnt < endDefStyleEnt && curIdent == defStyleEnt->map.name.ident) {
1124 if (value.dataType == Res_value::TYPE_NULL) {
1125 block = defStyleEnt->stringBlock;
1126 typeSetFlags = defStyleTypeSetFlags;
1127 value = defStyleEnt->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001128 if (kDebugStyles) {
1129 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1130 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001131 }
1132 defStyleEnt++;
1133 }
1134
1135 uint32_t resid = 0;
1136 if (value.dataType != Res_value::TYPE_NULL) {
1137 // Take care of resolving the found resource to its final value.
1138 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1139 &resid, &typeSetFlags, &config);
1140 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001141 if (kDebugStyles) {
1142 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1143 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001144 } else {
1145 // If we still don't have a value for this attribute, try to find
1146 // it in the theme!
1147 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1148 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001149 if (kDebugStyles) {
1150 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1151 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001152 newBlock = res.resolveReference(&value, block, &resid,
1153 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001154 if (kThrowOnBadId) {
1155 if (newBlock == BAD_INDEX) {
1156 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1157 return JNI_FALSE;
1158 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001159 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001160 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001161 if (kDebugStyles) {
1162 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1163 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001164 }
1165 }
1166
1167 // Deal with the special @null value -- it turns back to TYPE_NULL.
1168 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001169 if (kDebugStyles) {
1170 ALOGI("-> Setting to @null!");
1171 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001172 value.dataType = Res_value::TYPE_NULL;
1173 block = -1;
1174 }
1175
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001176 if (kDebugStyles) {
1177 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
1178 value.data);
1179 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001180
1181 // Write the final value back to Java.
1182 dest[STYLE_TYPE] = value.dataType;
1183 dest[STYLE_DATA] = value.data;
1184 dest[STYLE_ASSET_COOKIE] =
1185 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1186 dest[STYLE_RESOURCE_ID] = resid;
1187 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1188 dest[STYLE_DENSITY] = config.density;
1189
1190 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1191 indicesIdx++;
1192 indices[indicesIdx] = ii;
1193 }
1194
1195 dest += STYLE_NUM_ENTRIES;
1196 }
1197
1198 res.unlock();
1199
1200 if (indices != NULL) {
1201 indices[0] = indicesIdx;
1202 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1203 }
1204 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1205 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1206 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1207
1208 return JNI_TRUE;
1209}
1210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001211static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001212 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001213 jint defStyleAttr,
1214 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +00001215 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001216 jintArray attrs,
1217 jintArray outValues,
1218 jintArray outIndices)
1219{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001220 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001221 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001222 return JNI_FALSE;
1223 }
1224 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001225 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001226 return JNI_FALSE;
1227 }
1228 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001229 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001230 return JNI_FALSE;
1231 }
1232
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001233 if (kDebugStyles) {
Dan Albert46d84442014-11-18 16:07:51 -08001234 ALOGI("APPLY STYLE: theme=0x%" PRIx64 " defStyleAttr=0x%x defStyleRes=0x%x "
1235 "xml=0x%" PRIx64, themeToken, defStyleAttr, defStyleRes,
1236 xmlParserToken);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001237 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001238
Ashok Bhat896043d2014-01-17 16:02:38 +00001239 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001240 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001241 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001242 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 Res_value value;
1244
1245 const jsize NI = env->GetArrayLength(attrs);
1246 const jsize NV = env->GetArrayLength(outValues);
1247 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001248 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249 return JNI_FALSE;
1250 }
1251
1252 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1253 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001254 return JNI_FALSE;
1255 }
1256
1257 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1258 jint* dest = baseDest;
1259 if (dest == NULL) {
1260 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001261 return JNI_FALSE;
1262 }
1263
1264 jint* indices = NULL;
1265 int indicesIdx = 0;
1266 if (outIndices != NULL) {
1267 if (env->GetArrayLength(outIndices) > NI) {
1268 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1269 }
1270 }
1271
1272 // Load default style from attribute, if specified...
1273 uint32_t defStyleBagTypeSetFlags = 0;
1274 if (defStyleAttr != 0) {
1275 Res_value value;
1276 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1277 if (value.dataType == Res_value::TYPE_REFERENCE) {
1278 defStyleRes = value.data;
1279 }
1280 }
1281 }
1282
1283 // Retrieve the style class associated with the current XML tag.
1284 int style = 0;
1285 uint32_t styleBagTypeSetFlags = 0;
1286 if (xmlParser != NULL) {
1287 ssize_t idx = xmlParser->indexOfStyle();
1288 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1289 if (value.dataType == value.TYPE_ATTRIBUTE) {
1290 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1291 value.dataType = Res_value::TYPE_NULL;
1292 }
1293 }
1294 if (value.dataType == value.TYPE_REFERENCE) {
1295 style = value.data;
1296 }
1297 }
1298 }
1299
1300 // Now lock down the resource object and start pulling stuff from it.
1301 res.lock();
1302
1303 // Retrieve the default style bag, if requested.
1304 const ResTable::bag_entry* defStyleEnt = NULL;
1305 uint32_t defStyleTypeSetFlags = 0;
1306 ssize_t bagOff = defStyleRes != 0
1307 ? res.getBagLocked(defStyleRes, &defStyleEnt, &defStyleTypeSetFlags) : -1;
1308 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
1309 const ResTable::bag_entry* endDefStyleEnt = defStyleEnt +
1310 (bagOff >= 0 ? bagOff : 0);
1311
1312 // Retrieve the style class bag, if requested.
1313 const ResTable::bag_entry* styleEnt = NULL;
1314 uint32_t styleTypeSetFlags = 0;
1315 bagOff = style != 0 ? res.getBagLocked(style, &styleEnt, &styleTypeSetFlags) : -1;
1316 styleTypeSetFlags |= styleBagTypeSetFlags;
1317 const ResTable::bag_entry* endStyleEnt = styleEnt +
1318 (bagOff >= 0 ? bagOff : 0);
1319
1320 // Retrieve the XML attributes, if requested.
1321 const jsize NX = xmlParser ? xmlParser->getAttributeCount() : 0;
1322 jsize ix=0;
1323 uint32_t curXmlAttr = xmlParser ? xmlParser->getAttributeNameResID(ix) : 0;
1324
1325 static const ssize_t kXmlBlock = 0x10000000;
1326
1327 // Now iterate through all of the attributes that the client has requested,
1328 // filling in each with whatever data we can find.
1329 ssize_t block = 0;
1330 uint32_t typeSetFlags;
1331 for (jsize ii=0; ii<NI; ii++) {
1332 const uint32_t curIdent = (uint32_t)src[ii];
1333
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001334 if (kDebugStyles) {
1335 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1336 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001338 // Try to find a value for this attribute... we prioritize values
1339 // coming from, first XML attributes, then XML style, then default
1340 // style, and finally the theme.
1341 value.dataType = Res_value::TYPE_NULL;
1342 value.data = 0;
1343 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001344 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001345
1346 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001347 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348 ix++;
1349 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1350 }
1351 // Retrieve the current XML attribute if it matches, and step to next.
1352 if (ix < NX && curIdent == curXmlAttr) {
1353 block = kXmlBlock;
1354 xmlParser->getAttributeValue(ix, &value);
1355 ix++;
1356 curXmlAttr = xmlParser->getAttributeNameResID(ix);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001357 if (kDebugStyles) {
1358 ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
1359 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001360 }
1361
1362 // Skip through the style values until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001363 while (styleEnt < endStyleEnt && curIdent > styleEnt->map.name.ident) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001364 styleEnt++;
1365 }
1366 // Retrieve the current style attribute if it matches, and step to next.
1367 if (styleEnt < endStyleEnt && curIdent == styleEnt->map.name.ident) {
1368 if (value.dataType == Res_value::TYPE_NULL) {
1369 block = styleEnt->stringBlock;
1370 typeSetFlags = styleTypeSetFlags;
1371 value = styleEnt->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001372 if (kDebugStyles) {
1373 ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
1374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 }
1376 styleEnt++;
1377 }
1378
1379 // Skip through the default style values until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001380 while (defStyleEnt < endDefStyleEnt && curIdent > defStyleEnt->map.name.ident) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 defStyleEnt++;
1382 }
1383 // Retrieve the current default style attribute if it matches, and step to next.
1384 if (defStyleEnt < endDefStyleEnt && curIdent == defStyleEnt->map.name.ident) {
1385 if (value.dataType == Res_value::TYPE_NULL) {
1386 block = defStyleEnt->stringBlock;
1387 typeSetFlags = defStyleTypeSetFlags;
1388 value = defStyleEnt->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001389 if (kDebugStyles) {
1390 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 }
1393 defStyleEnt++;
1394 }
1395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 uint32_t resid = 0;
1397 if (value.dataType != Res_value::TYPE_NULL) {
1398 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001399 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1400 &resid, &typeSetFlags, &config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001401 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001402 if (kDebugStyles) {
1403 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1404 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001405 } else {
1406 // If we still don't have a value for this attribute, try to find
1407 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1409 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001410 if (kDebugStyles) {
1411 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1412 }
Dianne Hackborn0d221012009-07-29 15:41:19 -07001413 newBlock = res.resolveReference(&value, block, &resid,
1414 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001415 if (kThrowOnBadId) {
1416 if (newBlock == BAD_INDEX) {
1417 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1418 return JNI_FALSE;
1419 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001420 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001421 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001422 if (kDebugStyles) {
1423 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001425 }
1426 }
1427
1428 // Deal with the special @null value -- it turns back to TYPE_NULL.
1429 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001430 if (kDebugStyles) {
1431 ALOGI("-> Setting to @null!");
1432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001433 value.dataType = Res_value::TYPE_NULL;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001434 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001435 }
1436
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001437 if (kDebugStyles) {
1438 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
1439 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440
1441 // Write the final value back to Java.
1442 dest[STYLE_TYPE] = value.dataType;
1443 dest[STYLE_DATA] = value.data;
1444 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001445 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001446 dest[STYLE_RESOURCE_ID] = resid;
1447 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001448 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001449
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001450 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1451 indicesIdx++;
1452 indices[indicesIdx] = ii;
1453 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455 dest += STYLE_NUM_ENTRIES;
1456 }
1457
1458 res.unlock();
1459
1460 if (indices != NULL) {
1461 indices[0] = indicesIdx;
1462 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1463 }
1464 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1465 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1466
1467 return JNI_TRUE;
1468}
1469
1470static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001471 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001472 jintArray attrs,
1473 jintArray outValues,
1474 jintArray outIndices)
1475{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001476 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001477 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001478 return JNI_FALSE;
1479 }
1480 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001481 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001482 return JNI_FALSE;
1483 }
1484 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001485 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 return JNI_FALSE;
1487 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001488
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001489 AssetManager* am = assetManagerForJavaObject(env, clazz);
1490 if (am == NULL) {
1491 return JNI_FALSE;
1492 }
1493 const ResTable& res(am->getResources());
1494 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001495 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001498 const jsize NI = env->GetArrayLength(attrs);
1499 const jsize NV = env->GetArrayLength(outValues);
1500 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001501 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 return JNI_FALSE;
1503 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001504
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1506 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 return JNI_FALSE;
1508 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1511 jint* dest = baseDest;
1512 if (dest == NULL) {
1513 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001514 return JNI_FALSE;
1515 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 jint* indices = NULL;
1518 int indicesIdx = 0;
1519 if (outIndices != NULL) {
1520 if (env->GetArrayLength(outIndices) > NI) {
1521 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1522 }
1523 }
1524
1525 // Now lock down the resource object and start pulling stuff from it.
1526 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528 // Retrieve the XML attributes, if requested.
1529 const jsize NX = xmlParser->getAttributeCount();
1530 jsize ix=0;
1531 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001532
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001533 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001535 // Now iterate through all of the attributes that the client has requested,
1536 // filling in each with whatever data we can find.
1537 ssize_t block = 0;
1538 uint32_t typeSetFlags;
1539 for (jsize ii=0; ii<NI; ii++) {
1540 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 // Try to find a value for this attribute...
1543 value.dataType = Res_value::TYPE_NULL;
1544 value.data = 0;
1545 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001546 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001549 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550 ix++;
1551 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1552 }
1553 // Retrieve the current XML attribute if it matches, and step to next.
1554 if (ix < NX && curIdent == curXmlAttr) {
1555 block = kXmlBlock;
1556 xmlParser->getAttributeValue(ix, &value);
1557 ix++;
1558 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1559 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001560
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001561 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1562 uint32_t resid = 0;
1563 if (value.dataType != Res_value::TYPE_NULL) {
1564 // Take care of resolving the found resource to its final value.
1565 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001566 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1567 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001568 if (kThrowOnBadId) {
1569 if (newBlock == BAD_INDEX) {
1570 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1571 return JNI_FALSE;
1572 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001573 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001574 if (newBlock >= 0) block = newBlock;
1575 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001577 // Deal with the special @null value -- it turns back to TYPE_NULL.
1578 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1579 value.dataType = Res_value::TYPE_NULL;
1580 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001583
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001584 // Write the final value back to Java.
1585 dest[STYLE_TYPE] = value.dataType;
1586 dest[STYLE_DATA] = value.data;
1587 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001588 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 dest[STYLE_RESOURCE_ID] = resid;
1590 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001591 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001593 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1594 indicesIdx++;
1595 indices[indicesIdx] = ii;
1596 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001597
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598 dest += STYLE_NUM_ENTRIES;
1599 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001600
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001603 if (indices != NULL) {
1604 indices[0] = indicesIdx;
1605 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1606 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001608 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1609 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 return JNI_TRUE;
1612}
1613
1614static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1615 jint id)
1616{
1617 AssetManager* am = assetManagerForJavaObject(env, clazz);
1618 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001619 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001620 }
1621 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623 res.lock();
1624 const ResTable::bag_entry* defStyleEnt = NULL;
1625 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1626 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001627
Ashok Bhat896043d2014-01-17 16:02:38 +00001628 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629}
1630
1631static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1632 jint id,
1633 jintArray outValues)
1634{
1635 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001636 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 return JNI_FALSE;
1638 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001640 AssetManager* am = assetManagerForJavaObject(env, clazz);
1641 if (am == NULL) {
1642 return JNI_FALSE;
1643 }
1644 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001645 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 Res_value value;
1647 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001651 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1652 jint* dest = baseDest;
1653 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001654 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001655 return JNI_FALSE;
1656 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001657
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658 // Now lock down the resource object and start pulling stuff from it.
1659 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001660
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001661 const ResTable::bag_entry* arrayEnt = NULL;
1662 uint32_t arrayTypeSetFlags = 0;
1663 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1664 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1665 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001666
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001667 int i = 0;
1668 uint32_t typeSetFlags;
1669 while (i < NV && arrayEnt < endArrayEnt) {
1670 block = arrayEnt->stringBlock;
1671 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001672 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 uint32_t resid = 0;
1676 if (value.dataType != Res_value::TYPE_NULL) {
1677 // Take care of resolving the found resource to its final value.
1678 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001679 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1680 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001681 if (kThrowOnBadId) {
1682 if (newBlock == BAD_INDEX) {
1683 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1684 return JNI_FALSE;
1685 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 if (newBlock >= 0) block = newBlock;
1688 }
1689
1690 // Deal with the special @null value -- it turns back to TYPE_NULL.
1691 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1692 value.dataType = Res_value::TYPE_NULL;
1693 }
1694
1695 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1696
1697 // Write the final value back to Java.
1698 dest[STYLE_TYPE] = value.dataType;
1699 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001700 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 dest[STYLE_RESOURCE_ID] = resid;
1702 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001703 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 dest += STYLE_NUM_ENTRIES;
1705 i+= STYLE_NUM_ENTRIES;
1706 arrayEnt++;
1707 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001711 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001715 return i;
1716}
1717
Ashok Bhat896043d2014-01-17 16:02:38 +00001718static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001719 jint cookie,
1720 jstring fileName)
1721{
1722 AssetManager* am = assetManagerForJavaObject(env, clazz);
1723 if (am == NULL) {
1724 return 0;
1725 }
1726
Steve Block71f2cf12011-10-20 11:56:00 +01001727 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728
Elliott Hughes69a017b2011-04-08 14:10:28 -07001729 ScopedUtfChars fileName8(env, fileName);
1730 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 return 0;
1732 }
1733
Adam Lesinskide898ff2014-01-29 18:20:45 -08001734 int32_t assetCookie = static_cast<int32_t>(cookie);
1735 Asset* a = assetCookie
1736 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1737 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738
1739 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001740 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001741 return 0;
1742 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001743
Adam Lesinskide898ff2014-01-29 18:20:45 -08001744 const DynamicRefTable* dynamicRefTable =
1745 am->getResources().getDynamicRefTableForCookie(assetCookie);
1746 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1748 a->close();
1749 delete a;
1750
1751 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001752 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 return 0;
1754 }
1755
Ashok Bhat896043d2014-01-17 16:02:38 +00001756 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001757}
1758
1759static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1760 jint arrayResId)
1761{
1762 AssetManager* am = assetManagerForJavaObject(env, clazz);
1763 if (am == NULL) {
1764 return NULL;
1765 }
1766 const ResTable& res(am->getResources());
1767
1768 const ResTable::bag_entry* startOfBag;
1769 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1770 if (N < 0) {
1771 return NULL;
1772 }
1773
1774 jintArray array = env->NewIntArray(N * 2);
1775 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001776 res.unlockBag(startOfBag);
1777 return NULL;
1778 }
1779
1780 Res_value value;
1781 const ResTable::bag_entry* bag = startOfBag;
1782 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1783 jint stringIndex = -1;
1784 jint stringBlock = 0;
1785 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 // Take care of resolving the found resource to its final value.
1788 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1789 if (value.dataType == Res_value::TYPE_STRING) {
1790 stringIndex = value.data;
1791 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001792
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001793 if (kThrowOnBadId) {
1794 if (stringBlock == BAD_INDEX) {
1795 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1796 return array;
1797 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001798 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001800 //todo: It might be faster to allocate a C array to contain
1801 // the blocknums and indices, put them in there and then
1802 // do just one SetIntArrayRegion()
1803 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1804 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1805 j = j + 2;
1806 }
1807 res.unlockBag(startOfBag);
1808 return array;
1809}
1810
1811static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1812 jint arrayResId)
1813{
1814 AssetManager* am = assetManagerForJavaObject(env, clazz);
1815 if (am == NULL) {
1816 return NULL;
1817 }
1818 const ResTable& res(am->getResources());
1819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 const ResTable::bag_entry* startOfBag;
1821 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1822 if (N < 0) {
1823 return NULL;
1824 }
1825
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001826 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001827 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001828 res.unlockBag(startOfBag);
1829 return NULL;
1830 }
1831
1832 Res_value value;
1833 const ResTable::bag_entry* bag = startOfBag;
1834 size_t strLen = 0;
1835 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1836 value = bag->map.value;
1837 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001838
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 // Take care of resolving the found resource to its final value.
1840 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001841 if (kThrowOnBadId) {
1842 if (block == BAD_INDEX) {
1843 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1844 return array;
1845 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001846 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001848 const ResStringPool* pool = res.getTableStringBlock(block);
1849 const char* str8 = pool->string8At(value.data, &strLen);
1850 if (str8 != NULL) {
1851 str = env->NewStringUTF(str8);
1852 } else {
1853 const char16_t* str16 = pool->stringAt(value.data, &strLen);
1854 str = env->NewString(str16, strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001855 }
1856
1857 // If one of our NewString{UTF} calls failed due to memory, an
1858 // exception will be pending.
1859 if (env->ExceptionCheck()) {
1860 res.unlockBag(startOfBag);
1861 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001862 }
Kenny Root780d2a12010-02-22 22:36:26 -08001863
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001864 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001865
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001866 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1867 // If we have a large amount of strings in our array, we might
1868 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001869 env->DeleteLocalRef(str);
1870 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001871 }
1872 res.unlockBag(startOfBag);
1873 return array;
1874}
1875
1876static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1877 jint arrayResId)
1878{
1879 AssetManager* am = assetManagerForJavaObject(env, clazz);
1880 if (am == NULL) {
1881 return NULL;
1882 }
1883 const ResTable& res(am->getResources());
1884
1885 const ResTable::bag_entry* startOfBag;
1886 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1887 if (N < 0) {
1888 return NULL;
1889 }
1890
1891 jintArray array = env->NewIntArray(N);
1892 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001893 res.unlockBag(startOfBag);
1894 return NULL;
1895 }
1896
1897 Res_value value;
1898 const ResTable::bag_entry* bag = startOfBag;
1899 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1900 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001902 // Take care of resolving the found resource to its final value.
1903 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001904 if (kThrowOnBadId) {
1905 if (block == BAD_INDEX) {
1906 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1907 return array;
1908 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001909 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001910 if (value.dataType >= Res_value::TYPE_FIRST_INT
1911 && value.dataType <= Res_value::TYPE_LAST_INT) {
1912 int intVal = value.data;
1913 env->SetIntArrayRegion(array, i, 1, &intVal);
1914 }
1915 }
1916 res.unlockBag(startOfBag);
1917 return array;
1918}
1919
Jon Miranda042ad632014-09-03 17:57:35 -07001920static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
1921 jint styleId)
1922{
1923 AssetManager* am = assetManagerForJavaObject(env, clazz);
1924 if (am == NULL) {
1925 return NULL;
1926 }
1927 const ResTable& res(am->getResources());
1928
1929 const ResTable::bag_entry* startOfBag;
1930 const ssize_t N = res.lockBag(styleId, &startOfBag);
1931 if (N < 0) {
1932 return NULL;
1933 }
1934
1935 jintArray array = env->NewIntArray(N);
1936 if (array == NULL) {
1937 res.unlockBag(startOfBag);
1938 return NULL;
1939 }
1940
Jon Miranda042ad632014-09-03 17:57:35 -07001941 const ResTable::bag_entry* bag = startOfBag;
1942 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1943 int resourceId = bag->map.name.ident;
1944 env->SetIntArrayRegion(array, i, 1, &resourceId);
1945 }
1946 res.unlockBag(startOfBag);
1947 return array;
1948}
1949
Mårten Kongstad48d22322014-01-31 14:43:27 +01001950static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001951{
Mårten Kongstad48d22322014-01-31 14:43:27 +01001952 if (isSystem) {
1953 verifySystemIdmaps();
1954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001955 AssetManager* am = new AssetManager();
1956 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001957 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001958 return;
1959 }
1960
1961 am->addDefaultAssets();
1962
Steve Block71f2cf12011-10-20 11:56:00 +01001963 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00001964 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001965}
1966
1967static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
1968{
1969 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00001970 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01001971 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001972 if (am != NULL) {
1973 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00001974 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001975 }
1976}
1977
1978static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
1979{
1980 return Asset::getGlobalCount();
1981}
1982
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001983static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
1984{
1985 String8 alloc = Asset::getAssetAllocations();
1986 if (alloc.length() <= 0) {
1987 return NULL;
1988 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001989
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001990 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001991 return str;
1992}
1993
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001994static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
1995{
1996 return AssetManager::getGlobalCount();
1997}
1998
1999// ----------------------------------------------------------------------------
2000
2001/*
2002 * JNI registration.
2003 */
2004static JNINativeMethod gAssetManagerMethods[] = {
2005 /* name, signature, funcPtr */
2006
2007 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00002008 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002009 (void*) android_content_AssetManager_openAsset },
2010 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2011 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00002012 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002013 (void*) android_content_AssetManager_openNonAssetNative },
2014 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2015 (void*) android_content_AssetManager_openNonAssetFdNative },
2016 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
2017 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00002018 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002019 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002020 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002021 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00002022 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002023 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002024 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002025 (void*) android_content_AssetManager_seekAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002026 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002027 (void*) android_content_AssetManager_getAssetLength },
Ashok Bhat896043d2014-01-17 16:02:38 +00002028 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002029 (void*) android_content_AssetManager_getAssetRemainingLength },
Dianne Hackbornf7be4802013-04-12 14:52:58 -07002030 { "addAssetPathNative", "(Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002031 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad48d22322014-01-31 14:43:27 +01002032 { "addOverlayPath", "(Ljava/lang/String;)I",
2033 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002034 { "isUpToDate", "()Z",
2035 (void*) android_content_AssetManager_isUpToDate },
2036
2037 // Resources.
2038 { "setLocale", "(Ljava/lang/String;)V",
2039 (void*) android_content_AssetManager_setLocale },
2040 { "getLocales", "()[Ljava/lang/String;",
2041 (void*) android_content_AssetManager_getLocales },
Dianne Hackborn69cb8752011-05-19 18:13:32 -07002042 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002043 (void*) android_content_AssetManager_setConfiguration },
2044 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
2045 (void*) android_content_AssetManager_getResourceIdentifier },
2046 { "getResourceName","(I)Ljava/lang/String;",
2047 (void*) android_content_AssetManager_getResourceName },
2048 { "getResourcePackageName","(I)Ljava/lang/String;",
2049 (void*) android_content_AssetManager_getResourcePackageName },
2050 { "getResourceTypeName","(I)Ljava/lang/String;",
2051 (void*) android_content_AssetManager_getResourceTypeName },
2052 { "getResourceEntryName","(I)Ljava/lang/String;",
2053 (void*) android_content_AssetManager_getResourceEntryName },
Kenny Root55fc8502010-10-28 14:47:01 -07002054 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055 (void*) android_content_AssetManager_loadResourceValue },
2056 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
2057 (void*) android_content_AssetManager_loadResourceBagValue },
2058 { "getStringBlockCount","()I",
2059 (void*) android_content_AssetManager_getStringBlockCount },
Ashok Bhat896043d2014-01-17 16:02:38 +00002060 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002061 (void*) android_content_AssetManager_getNativeStringBlock },
2062 { "getCookieName","(I)Ljava/lang/String;",
2063 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002064 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2065 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002066
2067 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002068 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002069 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002070 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002071 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002072 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002073 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002074 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002075 (void*) android_content_AssetManager_copyTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002076 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002077 (void*) android_content_AssetManager_loadThemeAttributeValue },
Ashok Bhat896043d2014-01-17 16:02:38 +00002078 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002079 (void*) android_content_AssetManager_dumpTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002080 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002081 (void*) android_content_AssetManager_applyStyle },
Alan Viverette607bd842014-09-12 12:36:35 -07002082 { "resolveAttrs","(JII[I[I[I[I)Z",
2083 (void*) android_content_AssetManager_resolveAttrs },
Ashok Bhat896043d2014-01-17 16:02:38 +00002084 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002085 (void*) android_content_AssetManager_retrieveAttributes },
2086 { "getArraySize","(I)I",
2087 (void*) android_content_AssetManager_getArraySize },
2088 { "retrieveArray","(I[I)I",
2089 (void*) android_content_AssetManager_retrieveArray },
2090
2091 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002092 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002093 (void*) android_content_AssetManager_openXmlAssetNative },
2094
2095 // Arrays.
2096 { "getArrayStringResource","(I)[Ljava/lang/String;",
2097 (void*) android_content_AssetManager_getArrayStringResource },
2098 { "getArrayStringInfo","(I)[I",
2099 (void*) android_content_AssetManager_getArrayStringInfo },
2100 { "getArrayIntResource","(I)[I",
2101 (void*) android_content_AssetManager_getArrayIntResource },
Jon Miranda042ad632014-09-03 17:57:35 -07002102 { "getStyleAttributes","(I)[I",
2103 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002104
2105 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002106 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002107 (void*) android_content_AssetManager_init },
2108 { "destroy", "()V",
2109 (void*) android_content_AssetManager_destroy },
2110 { "getGlobalAssetCount", "()I",
2111 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002112 { "getAssetAllocations", "()Ljava/lang/String;",
2113 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002114 { "getGlobalAssetManagerCount", "()I",
Andreas Gampe32812612014-11-11 00:16:00 -08002115 (void*) android_content_AssetManager_getGlobalAssetManagerCount },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002116};
2117
2118int register_android_content_AssetManager(JNIEnv* env)
2119{
Andreas Gampe987f79f2014-11-18 17:29:46 -08002120 jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
2121 gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
2122 gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
2123 gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
2124 "Ljava/lang/CharSequence;");
2125 gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
2126 gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
2127 gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
2128 "changingConfigurations", "I");
2129 gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002130
Andreas Gampe987f79f2014-11-18 17:29:46 -08002131 jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
2132 gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
2133 "Landroid/os/ParcelFileDescriptor;");
2134 gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
2135 gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002136
Andreas Gampe987f79f2014-11-18 17:29:46 -08002137 jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
2138 gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002139
Andreas Gampe987f79f2014-11-18 17:29:46 -08002140 jclass stringClass = FindClassOrDie(env, "java/lang/String");
2141 g_stringClass = MakeGlobalRefOrDie(env, stringClass);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142
Andreas Gampe987f79f2014-11-18 17:29:46 -08002143 jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
2144 gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
2145 gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
2146 "<init>", "()V");
2147 gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
2148 "(ILjava/lang/Object;)V");
Adam Lesinskide898ff2014-01-29 18:20:45 -08002149
Andreas Gampe987f79f2014-11-18 17:29:46 -08002150 return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
2151 NELEM(gAssetManagerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002152}
2153
2154}; // namespace android