blob: b1c0738c6c541fc791847d66d53ec3bf7bc19240 [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
22#include "jni.h"
23#include "JNIHelp.h"
Elliott Hughes69a017b2011-04-08 14:10:28 -070024#include "ScopedStringChars.h"
25#include "ScopedUtfChars.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026#include "android_util_Binder.h"
27#include <utils/misc.h>
28#include <android_runtime/AndroidRuntime.h>
29#include <utils/Log.h>
30
Mathias Agopianb13b9bd2012-02-17 18:27:36 -080031#include <androidfw/Asset.h>
32#include <androidfw/AssetManager.h>
33#include <androidfw/ResourceTypes.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034
Mårten Kongstad48d22322014-01-31 14:43:27 +010035#include <private/android_filesystem_config.h> // for AID_SYSTEM
36
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037#include <stdio.h>
Mårten Kongstad48d22322014-01-31 14:43:27 +010038#include <sys/types.h>
39#include <sys/wait.h>
40
41#include <linux/capability.h>
42extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
43extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
44
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045
46namespace android {
47
Andreas Gampe0f0b4912014-11-12 08:03:48 -080048static const bool kThrowOnBadId = false;
49static const bool kDebugStyles = false;
50
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051// ----------------------------------------------------------------------------
52
53static struct typedvalue_offsets_t
54{
55 jfieldID mType;
56 jfieldID mData;
57 jfieldID mString;
58 jfieldID mAssetCookie;
59 jfieldID mResourceId;
60 jfieldID mChangingConfigurations;
61 jfieldID mDensity;
62} gTypedValueOffsets;
63
64static struct assetfiledescriptor_offsets_t
65{
66 jfieldID mFd;
67 jfieldID mStartOffset;
68 jfieldID mLength;
69} gAssetFileDescriptorOffsets;
70
71static struct assetmanager_offsets_t
72{
73 jfieldID mObject;
74} gAssetManagerOffsets;
75
Adam Lesinskide898ff2014-01-29 18:20:45 -080076static struct sparsearray_offsets_t
77{
78 jclass classObject;
79 jmethodID constructor;
80 jmethodID put;
81} gSparseArrayOffsets;
82
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083jclass g_stringClass = NULL;
84
85// ----------------------------------------------------------------------------
86
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087enum {
Dianne Hackborn0d221012009-07-29 15:41:19 -070088 STYLE_NUM_ENTRIES = 6,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089 STYLE_TYPE = 0,
90 STYLE_DATA = 1,
91 STYLE_ASSET_COOKIE = 2,
92 STYLE_RESOURCE_ID = 3,
Dianne Hackborn0d221012009-07-29 15:41:19 -070093 STYLE_CHANGING_CONFIGURATIONS = 4,
94 STYLE_DENSITY = 5
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095};
96
97static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
98 const Res_value& value, uint32_t ref, ssize_t block,
99 uint32_t typeSpecFlags, ResTable_config* config = NULL);
100
101jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
102 const Res_value& value, uint32_t ref, ssize_t block,
103 uint32_t typeSpecFlags, ResTable_config* config)
104{
105 env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
106 env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
Ashok Bhat896043d2014-01-17 16:02:38 +0000107 static_cast<jint>(table->getTableCookie(block)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108 env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
109 env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
110 env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
111 env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
112 typeSpecFlags);
113 if (config != NULL) {
114 env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
115 }
116 return block;
117}
118
Mårten Kongstad48d22322014-01-31 14:43:27 +0100119// This is called by zygote (running as user root) as part of preloadResources.
120static void verifySystemIdmaps()
121{
122 pid_t pid;
123 char system_id[10];
124
125 snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
126
127 switch (pid = fork()) {
128 case -1:
129 ALOGE("failed to fork for idmap: %s", strerror(errno));
130 break;
131 case 0: // child
132 {
133 struct __user_cap_header_struct capheader;
134 struct __user_cap_data_struct capdata;
135
136 memset(&capheader, 0, sizeof(capheader));
137 memset(&capdata, 0, sizeof(capdata));
138
139 capheader.version = _LINUX_CAPABILITY_VERSION;
140 capheader.pid = 0;
141
142 if (capget(&capheader, &capdata) != 0) {
143 ALOGE("capget: %s\n", strerror(errno));
144 exit(1);
145 }
146
147 capdata.effective = capdata.permitted;
148 if (capset(&capheader, &capdata) != 0) {
149 ALOGE("capset: %s\n", strerror(errno));
150 exit(1);
151 }
152
153 if (setgid(AID_SYSTEM) != 0) {
154 ALOGE("setgid: %s\n", strerror(errno));
155 exit(1);
156 }
157
158 if (setuid(AID_SYSTEM) != 0) {
159 ALOGE("setuid: %s\n", strerror(errno));
160 exit(1);
161 }
162
163 execl(AssetManager::IDMAP_BIN, AssetManager::IDMAP_BIN, "--scan",
164 AssetManager::OVERLAY_DIR, AssetManager::TARGET_PACKAGE_NAME,
165 AssetManager::TARGET_APK_PATH, AssetManager::IDMAP_DIR, (char*)NULL);
166 ALOGE("failed to execl for idmap: %s", strerror(errno));
167 exit(1); // should never get here
168 }
169 break;
170 default: // parent
171 waitpid(pid, NULL, 0);
172 break;
173 }
174}
175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176// ----------------------------------------------------------------------------
177
178// this guy is exported to other jni routines
179AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
180{
Ashok Bhat896043d2014-01-17 16:02:38 +0000181 jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
182 AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 if (am != NULL) {
184 return am;
185 }
186 jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
187 return NULL;
188}
189
Ashok Bhat896043d2014-01-17 16:02:38 +0000190static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191 jstring fileName, jint mode)
192{
193 AssetManager* am = assetManagerForJavaObject(env, clazz);
194 if (am == NULL) {
195 return 0;
196 }
197
Steve Block71f2cf12011-10-20 11:56:00 +0100198 ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199
Elliott Hughes69a017b2011-04-08 14:10:28 -0700200 ScopedUtfChars fileName8(env, fileName);
201 if (fileName8.c_str() == NULL) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000202 jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 return -1;
204 }
205
206 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
207 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700208 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 return -1;
210 }
211
Elliott Hughes69a017b2011-04-08 14:10:28 -0700212 Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213
214 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700215 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 return -1;
217 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218
219 //printf("Created Asset Stream: %p\n", a);
220
Ashok Bhat896043d2014-01-17 16:02:38 +0000221 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222}
223
224static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
225{
Kenny Rootddb76c42010-11-24 12:56:06 -0800226 off64_t startOffset, length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 int fd = a->openFileDescriptor(&startOffset, &length);
228 delete a;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 if (fd < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700231 jniThrowException(env, "java/io/FileNotFoundException",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 "This file can not be opened as a file descriptor; it is probably compressed");
233 return NULL;
234 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700235
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800236 jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
237 if (offsets == NULL) {
238 close(fd);
239 return NULL;
240 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800242 offsets[0] = startOffset;
243 offsets[1] = length;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245 env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700246
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700247 jobject fileDesc = jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 if (fileDesc == NULL) {
249 close(fd);
250 return NULL;
251 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 return newParcelFileDescriptor(env, fileDesc);
254}
255
256static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
257 jstring fileName, jlongArray outOffsets)
258{
259 AssetManager* am = assetManagerForJavaObject(env, clazz);
260 if (am == NULL) {
261 return NULL;
262 }
263
Steve Block71f2cf12011-10-20 11:56:00 +0100264 ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265
Elliott Hughes69a017b2011-04-08 14:10:28 -0700266 ScopedUtfChars fileName8(env, fileName);
267 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 return NULL;
269 }
270
Elliott Hughes69a017b2011-04-08 14:10:28 -0700271 Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272
273 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700274 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 return NULL;
276 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277
278 //printf("Created Asset Stream: %p\n", a);
279
280 return returnParcelFileDescriptor(env, a, outOffsets);
281}
282
Ashok Bhat896043d2014-01-17 16:02:38 +0000283static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284 jint cookie,
285 jstring fileName,
286 jint mode)
287{
288 AssetManager* am = assetManagerForJavaObject(env, clazz);
289 if (am == NULL) {
290 return 0;
291 }
292
Steve Block71f2cf12011-10-20 11:56:00 +0100293 ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294
Elliott Hughes69a017b2011-04-08 14:10:28 -0700295 ScopedUtfChars fileName8(env, fileName);
296 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 return -1;
298 }
299
300 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
301 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700302 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 return -1;
304 }
305
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000307 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
308 (Asset::AccessMode)mode)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700309 : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310
311 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700312 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 return -1;
314 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315
316 //printf("Created Asset Stream: %p\n", a);
317
Ashok Bhat896043d2014-01-17 16:02:38 +0000318 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800319}
320
321static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
322 jint cookie,
323 jstring fileName,
324 jlongArray outOffsets)
325{
326 AssetManager* am = assetManagerForJavaObject(env, clazz);
327 if (am == NULL) {
328 return NULL;
329 }
330
Steve Block71f2cf12011-10-20 11:56:00 +0100331 ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800332
Elliott Hughes69a017b2011-04-08 14:10:28 -0700333 ScopedUtfChars fileName8(env, fileName);
334 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800335 return NULL;
336 }
337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800338 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000339 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700340 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341
342 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700343 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344 return NULL;
345 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346
347 //printf("Created Asset Stream: %p\n", a);
348
349 return returnParcelFileDescriptor(env, a, outOffsets);
350}
351
352static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
353 jstring fileName)
354{
355 AssetManager* am = assetManagerForJavaObject(env, clazz);
356 if (am == NULL) {
357 return NULL;
358 }
359
Elliott Hughes69a017b2011-04-08 14:10:28 -0700360 ScopedUtfChars fileName8(env, fileName);
361 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 return NULL;
363 }
364
Elliott Hughes69a017b2011-04-08 14:10:28 -0700365 AssetDir* dir = am->openDir(fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800366
367 if (dir == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700368 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 return NULL;
370 }
371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800372 size_t N = dir->getFileCount();
373
374 jobjectArray array = env->NewObjectArray(dir->getFileCount(),
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +0100375 g_stringClass, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 delete dir;
378 return NULL;
379 }
380
381 for (size_t i=0; i<N; i++) {
382 const String8& name = dir->getFileName(i);
383 jstring str = env->NewStringUTF(name.string());
384 if (str == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 delete dir;
386 return NULL;
387 }
388 env->SetObjectArrayElement(array, i, str);
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700389 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390 }
391
392 delete dir;
393
394 return array;
395}
396
397static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000398 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800399{
Ashok Bhat896043d2014-01-17 16:02:38 +0000400 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401
402 //printf("Destroying Asset Stream: %p\n", a);
403
404 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700405 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406 return;
407 }
408
409 delete a;
410}
411
412static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000413 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414{
Ashok Bhat896043d2014-01-17 16:02:38 +0000415 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416
417 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700418 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 return -1;
420 }
421
422 uint8_t b;
423 ssize_t res = a->read(&b, 1);
424 return res == 1 ? b : -1;
425}
426
427static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000428 jlong assetHandle, jbyteArray bArray,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 jint off, jint len)
430{
Ashok Bhat896043d2014-01-17 16:02:38 +0000431 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432
433 if (a == NULL || bArray == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700434 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 return -1;
436 }
437
438 if (len == 0) {
439 return 0;
440 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 jsize bLen = env->GetArrayLength(bArray);
443 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700444 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445 return -1;
446 }
447
448 jbyte* b = env->GetByteArrayElements(bArray, NULL);
449 ssize_t res = a->read(b+off, len);
450 env->ReleaseByteArrayElements(bArray, b, 0);
451
Ashok Bhat896043d2014-01-17 16:02:38 +0000452 if (res > 0) return static_cast<jint>(res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453
454 if (res < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700455 jniThrowException(env, "java/io/IOException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 }
457 return -1;
458}
459
460static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000461 jlong assetHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800462 jlong offset, jint whence)
463{
Ashok Bhat896043d2014-01-17 16:02:38 +0000464 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800465
466 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700467 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468 return -1;
469 }
470
471 return a->seek(
472 offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
473}
474
475static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000476 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800477{
Ashok Bhat896043d2014-01-17 16:02:38 +0000478 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479
480 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700481 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482 return -1;
483 }
484
485 return a->getLength();
486}
487
488static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000489 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490{
Ashok Bhat896043d2014-01-17 16:02:38 +0000491 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800492
493 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700494 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 return -1;
496 }
497
498 return a->getRemainingLength();
499}
500
501static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
502 jstring path)
503{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700504 ScopedUtfChars path8(env, path);
505 if (path8.c_str() == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800506 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 }
508
509 AssetManager* am = assetManagerForJavaObject(env, clazz);
510 if (am == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800511 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512 }
513
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000514 int32_t cookie;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700515 bool res = am->addAssetPath(String8(path8.c_str()), &cookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800516
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000517 return (res) ? static_cast<jint>(cookie) : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518}
519
Mårten Kongstad48d22322014-01-31 14:43:27 +0100520static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
521 jstring idmapPath)
522{
523 ScopedUtfChars idmapPath8(env, idmapPath);
524 if (idmapPath8.c_str() == NULL) {
525 return 0;
526 }
527
528 AssetManager* am = assetManagerForJavaObject(env, clazz);
529 if (am == NULL) {
530 return 0;
531 }
532
533 int32_t cookie;
534 bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
535
536 return (res) ? (jint)cookie : 0;
537}
538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800539static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
540{
541 AssetManager* am = assetManagerForJavaObject(env, clazz);
542 if (am == NULL) {
543 return JNI_TRUE;
544 }
545 return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
546}
547
548static void android_content_AssetManager_setLocale(JNIEnv* env, jobject clazz,
549 jstring locale)
550{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700551 ScopedUtfChars locale8(env, locale);
552 if (locale8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553 return;
554 }
555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 AssetManager* am = assetManagerForJavaObject(env, clazz);
557 if (am == NULL) {
558 return;
559 }
560
Elliott Hughes69a017b2011-04-08 14:10:28 -0700561 am->setLocale(locale8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800562}
563
564static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
565{
566 Vector<String8> locales;
567
568 AssetManager* am = assetManagerForJavaObject(env, clazz);
569 if (am == NULL) {
570 return NULL;
571 }
572
573 am->getLocales(&locales);
574
575 const int N = locales.size();
576
577 jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
578 if (result == NULL) {
579 return NULL;
580 }
581
582 for (int i=0; i<N; i++) {
Gilles Debunne0db187a2010-08-27 11:51:34 -0700583 jstring str = env->NewStringUTF(locales[i].string());
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700584 if (str == NULL) {
585 return NULL;
586 }
587 env->SetObjectArrayElement(result, i, str);
588 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800589 }
590
591 return result;
592}
593
594static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
595 jint mcc, jint mnc,
596 jstring locale, jint orientation,
597 jint touchscreen, jint density,
598 jint keyboard, jint keyboardHidden,
599 jint navigation,
600 jint screenWidth, jint screenHeight,
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700601 jint smallestScreenWidthDp,
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700602 jint screenWidthDp, jint screenHeightDp,
Tobias Haamel27b28b32010-02-09 23:09:17 +0100603 jint screenLayout, jint uiMode,
604 jint sdkVersion)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800605{
606 AssetManager* am = assetManagerForJavaObject(env, clazz);
607 if (am == NULL) {
608 return;
609 }
610
611 ResTable_config config;
612 memset(&config, 0, sizeof(config));
Elliott Hughes69a017b2011-04-08 14:10:28 -0700613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800614 const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700615
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 config.mcc = (uint16_t)mcc;
617 config.mnc = (uint16_t)mnc;
618 config.orientation = (uint8_t)orientation;
619 config.touchscreen = (uint8_t)touchscreen;
620 config.density = (uint16_t)density;
621 config.keyboard = (uint8_t)keyboard;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700622 config.inputFlags = (uint8_t)keyboardHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 config.navigation = (uint8_t)navigation;
624 config.screenWidth = (uint16_t)screenWidth;
625 config.screenHeight = (uint16_t)screenHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700626 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700627 config.screenWidthDp = (uint16_t)screenWidthDp;
628 config.screenHeightDp = (uint16_t)screenHeightDp;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700629 config.screenLayout = (uint8_t)screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100630 config.uiMode = (uint8_t)uiMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800631 config.sdkVersion = (uint16_t)sdkVersion;
632 config.minorVersion = 0;
633 am->setConfiguration(config, locale8);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800635 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
636}
637
638static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
639 jstring name,
640 jstring defType,
641 jstring defPackage)
642{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700643 ScopedStringChars name16(env, name);
644 if (name16.get() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645 return 0;
646 }
647
648 AssetManager* am = assetManagerForJavaObject(env, clazz);
649 if (am == NULL) {
650 return 0;
651 }
652
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653 const char16_t* defType16 = defType
654 ? env->GetStringChars(defType, NULL) : NULL;
655 jsize defTypeLen = defType
656 ? env->GetStringLength(defType) : 0;
657 const char16_t* defPackage16 = defPackage
658 ? env->GetStringChars(defPackage, NULL) : NULL;
659 jsize defPackageLen = defPackage
660 ? env->GetStringLength(defPackage) : 0;
661
662 jint ident = am->getResources().identifierForName(
Elliott Hughes69a017b2011-04-08 14:10:28 -0700663 name16.get(), name16.size(), defType16, defTypeLen, defPackage16, defPackageLen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664
665 if (defPackage16) {
666 env->ReleaseStringChars(defPackage, defPackage16);
667 }
668 if (defType16) {
669 env->ReleaseStringChars(defType, defType16);
670 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800671
672 return ident;
673}
674
675static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
676 jint resid)
677{
678 AssetManager* am = assetManagerForJavaObject(env, clazz);
679 if (am == NULL) {
680 return NULL;
681 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800683 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700684 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685 return NULL;
686 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700687
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800688 String16 str;
689 if (name.package != NULL) {
690 str.setTo(name.package, name.packageLen);
691 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700692 if (name.type8 != NULL || name.type != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800693 if (str.size() > 0) {
694 char16_t div = ':';
695 str.append(&div, 1);
696 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700697 if (name.type8 != NULL) {
698 str.append(String16(name.type8, name.typeLen));
699 } else {
700 str.append(name.type, name.typeLen);
701 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700703 if (name.name8 != NULL || name.name != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704 if (str.size() > 0) {
705 char16_t div = '/';
706 str.append(&div, 1);
707 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700708 if (name.name8 != NULL) {
709 str.append(String16(name.name8, name.nameLen));
710 } else {
711 str.append(name.name, name.nameLen);
712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800713 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800715 return env->NewString((const jchar*)str.string(), str.size());
716}
717
718static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
719 jint resid)
720{
721 AssetManager* am = assetManagerForJavaObject(env, clazz);
722 if (am == NULL) {
723 return NULL;
724 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800726 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700727 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800728 return NULL;
729 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800731 if (name.package != NULL) {
732 return env->NewString((const jchar*)name.package, name.packageLen);
733 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735 return NULL;
736}
737
738static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
739 jint resid)
740{
741 AssetManager* am = assetManagerForJavaObject(env, clazz);
742 if (am == NULL) {
743 return NULL;
744 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700745
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800746 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700747 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748 return NULL;
749 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700750
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700751 if (name.type8 != NULL) {
752 return env->NewStringUTF(name.type8);
753 }
754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 if (name.type != NULL) {
756 return env->NewString((const jchar*)name.type, name.typeLen);
757 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700758
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 return NULL;
760}
761
762static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
763 jint resid)
764{
765 AssetManager* am = assetManagerForJavaObject(env, clazz);
766 if (am == NULL) {
767 return NULL;
768 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800770 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700771 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 return NULL;
773 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700774
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700775 if (name.name8 != NULL) {
776 return env->NewStringUTF(name.name8);
777 }
778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779 if (name.name != NULL) {
780 return env->NewString((const jchar*)name.name, name.nameLen);
781 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700782
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800783 return NULL;
784}
785
786static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
787 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700788 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789 jobject outValue,
790 jboolean resolve)
791{
Dianne Hackborn1f7d3072013-02-11 17:03:32 -0800792 if (outValue == NULL) {
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800793 jniThrowNullPointerException(env, "outValue");
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700794 return 0;
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800795 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800796 AssetManager* am = assetManagerForJavaObject(env, clazz);
797 if (am == NULL) {
798 return 0;
799 }
800 const ResTable& res(am->getResources());
801
802 Res_value value;
803 ResTable_config config;
804 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700805 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800806 if (kThrowOnBadId) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800807 if (block == BAD_INDEX) {
808 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
809 return 0;
810 }
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800811 }
812 uint32_t ref = ident;
813 if (resolve) {
814 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
815 if (kThrowOnBadId) {
816 if (block == BAD_INDEX) {
817 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
818 return 0;
819 }
820 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800821 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000822 if (block >= 0) {
823 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
824 }
825
826 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827}
828
829static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
830 jint ident, jint bagEntryId,
831 jobject outValue, jboolean resolve)
832{
833 AssetManager* am = assetManagerForJavaObject(env, clazz);
834 if (am == NULL) {
835 return 0;
836 }
837 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700838
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800839 // Now lock down the resource object and start pulling stuff from it.
840 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -0700841
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800842 ssize_t block = -1;
843 Res_value value;
844
845 const ResTable::bag_entry* entry = NULL;
846 uint32_t typeSpecFlags;
847 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
848
849 for (ssize_t i=0; i<entryCount; i++) {
850 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
851 block = entry->stringBlock;
852 value = entry->map.value;
853 }
854 entry++;
855 }
856
857 res.unlock();
858
859 if (block < 0) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000860 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800861 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800863 uint32_t ref = ident;
864 if (resolve) {
865 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800866 if (kThrowOnBadId) {
867 if (block == BAD_INDEX) {
868 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
869 return 0;
870 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800871 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000873 if (block >= 0) {
874 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
875 }
876
877 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878}
879
880static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
881{
882 AssetManager* am = assetManagerForJavaObject(env, clazz);
883 if (am == NULL) {
884 return 0;
885 }
886 return am->getResources().getTableCount();
887}
888
Ashok Bhat896043d2014-01-17 16:02:38 +0000889static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890 jint block)
891{
892 AssetManager* am = assetManagerForJavaObject(env, clazz);
893 if (am == NULL) {
894 return 0;
895 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000896 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897}
898
899static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
900 jint cookie)
901{
902 AssetManager* am = assetManagerForJavaObject(env, clazz);
903 if (am == NULL) {
904 return NULL;
905 }
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000906 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800907 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700908 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800909 return NULL;
910 }
911 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800912 return str;
913}
914
Adam Lesinskide898ff2014-01-29 18:20:45 -0800915static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
916{
917 AssetManager* am = assetManagerForJavaObject(env, clazz);
918 if (am == NULL) {
919 return 0;
920 }
921
922 const ResTable& res = am->getResources();
923
924 jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
925 gSparseArrayOffsets.constructor);
926 const size_t N = res.getBasePackageCount();
927 for (size_t i = 0; i < N; i++) {
928 const String16 name = res.getBasePackageName(i);
929 env->CallVoidMethod(sparseArray, gSparseArrayOffsets.put, (jint) res.getBasePackageId(i),
930 env->NewString(name, name.size()));
931 }
932 return sparseArray;
933}
934
Ashok Bhat896043d2014-01-17 16:02:38 +0000935static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936{
937 AssetManager* am = assetManagerForJavaObject(env, clazz);
938 if (am == NULL) {
939 return 0;
940 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000941 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800942}
943
944static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000945 jlong themeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946{
Ashok Bhat896043d2014-01-17 16:02:38 +0000947 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 delete theme;
949}
950
951static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000952 jlong themeHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 jint styleRes,
954 jboolean force)
955{
Ashok Bhat896043d2014-01-17 16:02:38 +0000956 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800957 theme->applyStyle(styleRes, force ? true : false);
958}
959
960static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000961 jlong destHandle, jlong srcHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800962{
Ashok Bhat896043d2014-01-17 16:02:38 +0000963 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
964 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800965 dest->setTo(*src);
966}
967
968static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +0000969 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970{
Ashok Bhat896043d2014-01-17 16:02:38 +0000971 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972 const ResTable& res(theme->getResTable());
973
974 Res_value value;
975 // XXX value could be different in different configs!
976 uint32_t typeSpecFlags = 0;
977 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
978 uint32_t ref = 0;
979 if (resolve) {
980 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800981 if (kThrowOnBadId) {
982 if (block == BAD_INDEX) {
983 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
984 return 0;
985 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800986 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 }
988 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
989}
990
991static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000992 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 jstring tag, jstring prefix)
994{
Ashok Bhat896043d2014-01-17 16:02:38 +0000995 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800996 const ResTable& res(theme->getResTable());
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800997 (void)res;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700998
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 // XXX Need to use params.
1000 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001}
1002
Alan Viverette52b999f2014-03-24 18:00:26 -07001003static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1004 jlong themeToken,
1005 jint defStyleAttr,
1006 jint defStyleRes,
1007 jintArray inValues,
1008 jintArray attrs,
1009 jintArray outValues,
1010 jintArray outIndices)
1011{
1012 if (themeToken == 0) {
1013 jniThrowNullPointerException(env, "theme token");
1014 return JNI_FALSE;
1015 }
1016 if (attrs == NULL) {
1017 jniThrowNullPointerException(env, "attrs");
1018 return JNI_FALSE;
1019 }
1020 if (outValues == NULL) {
1021 jniThrowNullPointerException(env, "out values");
1022 return JNI_FALSE;
1023 }
1024
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001025 if (kDebugStyles) {
1026 ALOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x",
1027 themeToken, defStyleAttr, defStyleRes);
1028 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001029
1030 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1031 const ResTable& res = theme->getResTable();
1032 ResTable_config config;
1033 Res_value value;
1034
1035 const jsize NI = env->GetArrayLength(attrs);
1036 const jsize NV = env->GetArrayLength(outValues);
1037 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1038 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1039 return JNI_FALSE;
1040 }
1041
1042 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1043 if (src == NULL) {
1044 return JNI_FALSE;
1045 }
1046
1047 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1048 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1049
1050 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1051 jint* dest = baseDest;
1052 if (dest == NULL) {
1053 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1054 return JNI_FALSE;
1055 }
1056
1057 jint* indices = NULL;
1058 int indicesIdx = 0;
1059 if (outIndices != NULL) {
1060 if (env->GetArrayLength(outIndices) > NI) {
1061 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1062 }
1063 }
1064
1065 // Load default style from attribute, if specified...
1066 uint32_t defStyleBagTypeSetFlags = 0;
1067 if (defStyleAttr != 0) {
1068 Res_value value;
1069 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1070 if (value.dataType == Res_value::TYPE_REFERENCE) {
1071 defStyleRes = value.data;
1072 }
1073 }
1074 }
1075
1076 // Now lock down the resource object and start pulling stuff from it.
1077 res.lock();
1078
1079 // Retrieve the default style bag, if requested.
1080 const ResTable::bag_entry* defStyleEnt = NULL;
1081 uint32_t defStyleTypeSetFlags = 0;
1082 ssize_t bagOff = defStyleRes != 0
1083 ? res.getBagLocked(defStyleRes, &defStyleEnt, &defStyleTypeSetFlags) : -1;
1084 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
1085 const ResTable::bag_entry* endDefStyleEnt = defStyleEnt +
1086 (bagOff >= 0 ? bagOff : 0);;
1087
1088 // Now iterate through all of the attributes that the client has requested,
1089 // filling in each with whatever data we can find.
1090 ssize_t block = 0;
1091 uint32_t typeSetFlags;
1092 for (jsize ii=0; ii<NI; ii++) {
1093 const uint32_t curIdent = (uint32_t)src[ii];
1094
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001095 if (kDebugStyles) {
1096 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1097 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001098
1099 // Try to find a value for this attribute... we prioritize values
1100 // coming from, first XML attributes, then XML style, then default
1101 // style, and finally the theme.
1102 value.dataType = Res_value::TYPE_NULL;
1103 value.data = 0;
1104 typeSetFlags = 0;
1105 config.density = 0;
1106
1107 // Retrieve the current input value if available.
1108 if (NSV > 0 && srcValues[ii] != 0) {
1109 block = -1;
1110 value.dataType = Res_value::TYPE_ATTRIBUTE;
1111 value.data = srcValues[ii];
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001112 if (kDebugStyles) {
1113 ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
1114 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001115 }
1116
1117 // Skip through the default style values until the end or the next possible match.
1118 while (defStyleEnt < endDefStyleEnt && curIdent > defStyleEnt->map.name.ident) {
1119 defStyleEnt++;
1120 }
1121 // Retrieve the current default style attribute if it matches, and step to next.
1122 if (defStyleEnt < endDefStyleEnt && curIdent == defStyleEnt->map.name.ident) {
1123 if (value.dataType == Res_value::TYPE_NULL) {
1124 block = defStyleEnt->stringBlock;
1125 typeSetFlags = defStyleTypeSetFlags;
1126 value = defStyleEnt->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001127 if (kDebugStyles) {
1128 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1129 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001130 }
1131 defStyleEnt++;
1132 }
1133
1134 uint32_t resid = 0;
1135 if (value.dataType != Res_value::TYPE_NULL) {
1136 // Take care of resolving the found resource to its final value.
1137 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1138 &resid, &typeSetFlags, &config);
1139 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001140 if (kDebugStyles) {
1141 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1142 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001143 } else {
1144 // If we still don't have a value for this attribute, try to find
1145 // it in the theme!
1146 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1147 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001148 if (kDebugStyles) {
1149 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1150 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001151 newBlock = res.resolveReference(&value, block, &resid,
1152 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001153 if (kThrowOnBadId) {
1154 if (newBlock == BAD_INDEX) {
1155 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1156 return JNI_FALSE;
1157 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001158 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001159 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001160 if (kDebugStyles) {
1161 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1162 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001163 }
1164 }
1165
1166 // Deal with the special @null value -- it turns back to TYPE_NULL.
1167 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001168 if (kDebugStyles) {
1169 ALOGI("-> Setting to @null!");
1170 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001171 value.dataType = Res_value::TYPE_NULL;
1172 block = -1;
1173 }
1174
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001175 if (kDebugStyles) {
1176 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
1177 value.data);
1178 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001179
1180 // Write the final value back to Java.
1181 dest[STYLE_TYPE] = value.dataType;
1182 dest[STYLE_DATA] = value.data;
1183 dest[STYLE_ASSET_COOKIE] =
1184 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1185 dest[STYLE_RESOURCE_ID] = resid;
1186 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1187 dest[STYLE_DENSITY] = config.density;
1188
1189 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1190 indicesIdx++;
1191 indices[indicesIdx] = ii;
1192 }
1193
1194 dest += STYLE_NUM_ENTRIES;
1195 }
1196
1197 res.unlock();
1198
1199 if (indices != NULL) {
1200 indices[0] = indicesIdx;
1201 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1202 }
1203 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1204 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1205 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1206
1207 return JNI_TRUE;
1208}
1209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001210static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001211 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212 jint defStyleAttr,
1213 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +00001214 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001215 jintArray attrs,
1216 jintArray outValues,
1217 jintArray outIndices)
1218{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001219 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001220 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001221 return JNI_FALSE;
1222 }
1223 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001224 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001225 return JNI_FALSE;
1226 }
1227 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001228 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001229 return JNI_FALSE;
1230 }
1231
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001232 if (kDebugStyles) {
1233 ALOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x xml=0x%x",
1234 themeToken, defStyleAttr, defStyleRes, xmlParserToken);
1235 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001236
Ashok Bhat896043d2014-01-17 16:02:38 +00001237 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001239 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001240 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001241 Res_value value;
1242
1243 const jsize NI = env->GetArrayLength(attrs);
1244 const jsize NV = env->GetArrayLength(outValues);
1245 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001246 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001247 return JNI_FALSE;
1248 }
1249
1250 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1251 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001252 return JNI_FALSE;
1253 }
1254
1255 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1256 jint* dest = baseDest;
1257 if (dest == NULL) {
1258 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259 return JNI_FALSE;
1260 }
1261
1262 jint* indices = NULL;
1263 int indicesIdx = 0;
1264 if (outIndices != NULL) {
1265 if (env->GetArrayLength(outIndices) > NI) {
1266 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1267 }
1268 }
1269
1270 // Load default style from attribute, if specified...
1271 uint32_t defStyleBagTypeSetFlags = 0;
1272 if (defStyleAttr != 0) {
1273 Res_value value;
1274 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1275 if (value.dataType == Res_value::TYPE_REFERENCE) {
1276 defStyleRes = value.data;
1277 }
1278 }
1279 }
1280
1281 // Retrieve the style class associated with the current XML tag.
1282 int style = 0;
1283 uint32_t styleBagTypeSetFlags = 0;
1284 if (xmlParser != NULL) {
1285 ssize_t idx = xmlParser->indexOfStyle();
1286 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1287 if (value.dataType == value.TYPE_ATTRIBUTE) {
1288 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1289 value.dataType = Res_value::TYPE_NULL;
1290 }
1291 }
1292 if (value.dataType == value.TYPE_REFERENCE) {
1293 style = value.data;
1294 }
1295 }
1296 }
1297
1298 // Now lock down the resource object and start pulling stuff from it.
1299 res.lock();
1300
1301 // Retrieve the default style bag, if requested.
1302 const ResTable::bag_entry* defStyleEnt = NULL;
1303 uint32_t defStyleTypeSetFlags = 0;
1304 ssize_t bagOff = defStyleRes != 0
1305 ? res.getBagLocked(defStyleRes, &defStyleEnt, &defStyleTypeSetFlags) : -1;
1306 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
1307 const ResTable::bag_entry* endDefStyleEnt = defStyleEnt +
1308 (bagOff >= 0 ? bagOff : 0);
1309
1310 // Retrieve the style class bag, if requested.
1311 const ResTable::bag_entry* styleEnt = NULL;
1312 uint32_t styleTypeSetFlags = 0;
1313 bagOff = style != 0 ? res.getBagLocked(style, &styleEnt, &styleTypeSetFlags) : -1;
1314 styleTypeSetFlags |= styleBagTypeSetFlags;
1315 const ResTable::bag_entry* endStyleEnt = styleEnt +
1316 (bagOff >= 0 ? bagOff : 0);
1317
1318 // Retrieve the XML attributes, if requested.
1319 const jsize NX = xmlParser ? xmlParser->getAttributeCount() : 0;
1320 jsize ix=0;
1321 uint32_t curXmlAttr = xmlParser ? xmlParser->getAttributeNameResID(ix) : 0;
1322
1323 static const ssize_t kXmlBlock = 0x10000000;
1324
1325 // Now iterate through all of the attributes that the client has requested,
1326 // filling in each with whatever data we can find.
1327 ssize_t block = 0;
1328 uint32_t typeSetFlags;
1329 for (jsize ii=0; ii<NI; ii++) {
1330 const uint32_t curIdent = (uint32_t)src[ii];
1331
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001332 if (kDebugStyles) {
1333 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1334 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001336 // Try to find a value for this attribute... we prioritize values
1337 // coming from, first XML attributes, then XML style, then default
1338 // style, and finally the theme.
1339 value.dataType = Res_value::TYPE_NULL;
1340 value.data = 0;
1341 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001342 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001343
1344 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001345 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001346 ix++;
1347 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1348 }
1349 // Retrieve the current XML attribute if it matches, and step to next.
1350 if (ix < NX && curIdent == curXmlAttr) {
1351 block = kXmlBlock;
1352 xmlParser->getAttributeValue(ix, &value);
1353 ix++;
1354 curXmlAttr = xmlParser->getAttributeNameResID(ix);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001355 if (kDebugStyles) {
1356 ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
1357 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 }
1359
1360 // Skip through the style values until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001361 while (styleEnt < endStyleEnt && curIdent > styleEnt->map.name.ident) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362 styleEnt++;
1363 }
1364 // Retrieve the current style attribute if it matches, and step to next.
1365 if (styleEnt < endStyleEnt && curIdent == styleEnt->map.name.ident) {
1366 if (value.dataType == Res_value::TYPE_NULL) {
1367 block = styleEnt->stringBlock;
1368 typeSetFlags = styleTypeSetFlags;
1369 value = styleEnt->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001370 if (kDebugStyles) {
1371 ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
1372 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 }
1374 styleEnt++;
1375 }
1376
1377 // Skip through the default style values until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001378 while (defStyleEnt < endDefStyleEnt && curIdent > defStyleEnt->map.name.ident) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379 defStyleEnt++;
1380 }
1381 // Retrieve the current default style attribute if it matches, and step to next.
1382 if (defStyleEnt < endDefStyleEnt && curIdent == defStyleEnt->map.name.ident) {
1383 if (value.dataType == Res_value::TYPE_NULL) {
1384 block = defStyleEnt->stringBlock;
1385 typeSetFlags = defStyleTypeSetFlags;
1386 value = defStyleEnt->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001387 if (kDebugStyles) {
1388 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1389 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390 }
1391 defStyleEnt++;
1392 }
1393
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001394 uint32_t resid = 0;
1395 if (value.dataType != Res_value::TYPE_NULL) {
1396 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001397 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1398 &resid, &typeSetFlags, &config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001399 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001400 if (kDebugStyles) {
1401 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001403 } else {
1404 // If we still don't have a value for this attribute, try to find
1405 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001406 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1407 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001408 if (kDebugStyles) {
1409 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1410 }
Dianne Hackborn0d221012009-07-29 15:41:19 -07001411 newBlock = res.resolveReference(&value, block, &resid,
1412 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001413 if (kThrowOnBadId) {
1414 if (newBlock == BAD_INDEX) {
1415 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1416 return JNI_FALSE;
1417 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001418 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001419 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001420 if (kDebugStyles) {
1421 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1422 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 }
1424 }
1425
1426 // Deal with the special @null value -- it turns back to TYPE_NULL.
1427 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001428 if (kDebugStyles) {
1429 ALOGI("-> Setting to @null!");
1430 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001431 value.dataType = Res_value::TYPE_NULL;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001432 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001433 }
1434
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001435 if (kDebugStyles) {
1436 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
1437 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001438
1439 // Write the final value back to Java.
1440 dest[STYLE_TYPE] = value.dataType;
1441 dest[STYLE_DATA] = value.data;
1442 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001443 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001444 dest[STYLE_RESOURCE_ID] = resid;
1445 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001446 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001447
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1449 indicesIdx++;
1450 indices[indicesIdx] = ii;
1451 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001453 dest += STYLE_NUM_ENTRIES;
1454 }
1455
1456 res.unlock();
1457
1458 if (indices != NULL) {
1459 indices[0] = indicesIdx;
1460 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1461 }
1462 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1463 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1464
1465 return JNI_TRUE;
1466}
1467
1468static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001469 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 jintArray attrs,
1471 jintArray outValues,
1472 jintArray outIndices)
1473{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001474 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001475 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001476 return JNI_FALSE;
1477 }
1478 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001479 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001480 return JNI_FALSE;
1481 }
1482 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001483 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 return JNI_FALSE;
1485 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001486
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 AssetManager* am = assetManagerForJavaObject(env, clazz);
1488 if (am == NULL) {
1489 return JNI_FALSE;
1490 }
1491 const ResTable& res(am->getResources());
1492 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001493 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 const jsize NI = env->GetArrayLength(attrs);
1497 const jsize NV = env->GetArrayLength(outValues);
1498 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001499 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 return JNI_FALSE;
1501 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001503 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1504 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 return JNI_FALSE;
1506 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001507
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1509 jint* dest = baseDest;
1510 if (dest == NULL) {
1511 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 return JNI_FALSE;
1513 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 jint* indices = NULL;
1516 int indicesIdx = 0;
1517 if (outIndices != NULL) {
1518 if (env->GetArrayLength(outIndices) > NI) {
1519 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1520 }
1521 }
1522
1523 // Now lock down the resource object and start pulling stuff from it.
1524 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001526 // Retrieve the XML attributes, if requested.
1527 const jsize NX = xmlParser->getAttributeCount();
1528 jsize ix=0;
1529 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001532
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001533 // Now iterate through all of the attributes that the client has requested,
1534 // filling in each with whatever data we can find.
1535 ssize_t block = 0;
1536 uint32_t typeSetFlags;
1537 for (jsize ii=0; ii<NI; ii++) {
1538 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001540 // Try to find a value for this attribute...
1541 value.dataType = Res_value::TYPE_NULL;
1542 value.data = 0;
1543 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001544 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001546 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001547 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 ix++;
1549 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1550 }
1551 // Retrieve the current XML attribute if it matches, and step to next.
1552 if (ix < NX && curIdent == curXmlAttr) {
1553 block = kXmlBlock;
1554 xmlParser->getAttributeValue(ix, &value);
1555 ix++;
1556 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1557 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1560 uint32_t resid = 0;
1561 if (value.dataType != Res_value::TYPE_NULL) {
1562 // Take care of resolving the found resource to its final value.
1563 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001564 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1565 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001566 if (kThrowOnBadId) {
1567 if (newBlock == BAD_INDEX) {
1568 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1569 return JNI_FALSE;
1570 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001571 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 if (newBlock >= 0) block = newBlock;
1573 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001574
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 // Deal with the special @null value -- it turns back to TYPE_NULL.
1576 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1577 value.dataType = Res_value::TYPE_NULL;
1578 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 // Write the final value back to Java.
1583 dest[STYLE_TYPE] = value.dataType;
1584 dest[STYLE_DATA] = value.data;
1585 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001586 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 dest[STYLE_RESOURCE_ID] = resid;
1588 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001589 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1592 indicesIdx++;
1593 indices[indicesIdx] = ii;
1594 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001595
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 dest += STYLE_NUM_ENTRIES;
1597 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001600
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 if (indices != NULL) {
1602 indices[0] = indicesIdx;
1603 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1604 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001605
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1607 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001608
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001609 return JNI_TRUE;
1610}
1611
1612static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1613 jint id)
1614{
1615 AssetManager* am = assetManagerForJavaObject(env, clazz);
1616 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001617 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 }
1619 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001621 res.lock();
1622 const ResTable::bag_entry* defStyleEnt = NULL;
1623 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1624 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001625
Ashok Bhat896043d2014-01-17 16:02:38 +00001626 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001627}
1628
1629static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1630 jint id,
1631 jintArray outValues)
1632{
1633 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001634 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 return JNI_FALSE;
1636 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638 AssetManager* am = assetManagerForJavaObject(env, clazz);
1639 if (am == NULL) {
1640 return JNI_FALSE;
1641 }
1642 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001643 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001644 Res_value value;
1645 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001646
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1650 jint* dest = baseDest;
1651 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001652 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001653 return JNI_FALSE;
1654 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001656 // Now lock down the resource object and start pulling stuff from it.
1657 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001659 const ResTable::bag_entry* arrayEnt = NULL;
1660 uint32_t arrayTypeSetFlags = 0;
1661 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1662 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1663 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001664
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001665 int i = 0;
1666 uint32_t typeSetFlags;
1667 while (i < NV && arrayEnt < endArrayEnt) {
1668 block = arrayEnt->stringBlock;
1669 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001670 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001671 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 uint32_t resid = 0;
1674 if (value.dataType != Res_value::TYPE_NULL) {
1675 // Take care of resolving the found resource to its final value.
1676 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001677 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1678 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001679 if (kThrowOnBadId) {
1680 if (newBlock == BAD_INDEX) {
1681 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1682 return JNI_FALSE;
1683 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001684 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 if (newBlock >= 0) block = newBlock;
1686 }
1687
1688 // Deal with the special @null value -- it turns back to TYPE_NULL.
1689 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1690 value.dataType = Res_value::TYPE_NULL;
1691 }
1692
1693 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1694
1695 // Write the final value back to Java.
1696 dest[STYLE_TYPE] = value.dataType;
1697 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001698 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 dest[STYLE_RESOURCE_ID] = resid;
1700 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001701 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 dest += STYLE_NUM_ENTRIES;
1703 i+= STYLE_NUM_ENTRIES;
1704 arrayEnt++;
1705 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001707 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001711 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 return i;
1714}
1715
Ashok Bhat896043d2014-01-17 16:02:38 +00001716static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001717 jint cookie,
1718 jstring fileName)
1719{
1720 AssetManager* am = assetManagerForJavaObject(env, clazz);
1721 if (am == NULL) {
1722 return 0;
1723 }
1724
Steve Block71f2cf12011-10-20 11:56:00 +01001725 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001726
Elliott Hughes69a017b2011-04-08 14:10:28 -07001727 ScopedUtfChars fileName8(env, fileName);
1728 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001729 return 0;
1730 }
1731
Adam Lesinskide898ff2014-01-29 18:20:45 -08001732 int32_t assetCookie = static_cast<int32_t>(cookie);
1733 Asset* a = assetCookie
1734 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1735 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736
1737 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001738 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 return 0;
1740 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001741
Adam Lesinskide898ff2014-01-29 18:20:45 -08001742 const DynamicRefTable* dynamicRefTable =
1743 am->getResources().getDynamicRefTableForCookie(assetCookie);
1744 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1746 a->close();
1747 delete a;
1748
1749 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001750 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001751 return 0;
1752 }
1753
Ashok Bhat896043d2014-01-17 16:02:38 +00001754 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001755}
1756
1757static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1758 jint arrayResId)
1759{
1760 AssetManager* am = assetManagerForJavaObject(env, clazz);
1761 if (am == NULL) {
1762 return NULL;
1763 }
1764 const ResTable& res(am->getResources());
1765
1766 const ResTable::bag_entry* startOfBag;
1767 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1768 if (N < 0) {
1769 return NULL;
1770 }
1771
1772 jintArray array = env->NewIntArray(N * 2);
1773 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 res.unlockBag(startOfBag);
1775 return NULL;
1776 }
1777
1778 Res_value value;
1779 const ResTable::bag_entry* bag = startOfBag;
1780 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1781 jint stringIndex = -1;
1782 jint stringBlock = 0;
1783 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001784
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001785 // Take care of resolving the found resource to its final value.
1786 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1787 if (value.dataType == Res_value::TYPE_STRING) {
1788 stringIndex = value.data;
1789 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001790
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001791 if (kThrowOnBadId) {
1792 if (stringBlock == BAD_INDEX) {
1793 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1794 return array;
1795 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001796 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001797
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001798 //todo: It might be faster to allocate a C array to contain
1799 // the blocknums and indices, put them in there and then
1800 // do just one SetIntArrayRegion()
1801 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1802 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1803 j = j + 2;
1804 }
1805 res.unlockBag(startOfBag);
1806 return array;
1807}
1808
1809static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1810 jint arrayResId)
1811{
1812 AssetManager* am = assetManagerForJavaObject(env, clazz);
1813 if (am == NULL) {
1814 return NULL;
1815 }
1816 const ResTable& res(am->getResources());
1817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 const ResTable::bag_entry* startOfBag;
1819 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1820 if (N < 0) {
1821 return NULL;
1822 }
1823
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001824 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001825 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001826 res.unlockBag(startOfBag);
1827 return NULL;
1828 }
1829
1830 Res_value value;
1831 const ResTable::bag_entry* bag = startOfBag;
1832 size_t strLen = 0;
1833 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1834 value = bag->map.value;
1835 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001836
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001837 // Take care of resolving the found resource to its final value.
1838 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001839 if (kThrowOnBadId) {
1840 if (block == BAD_INDEX) {
1841 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1842 return array;
1843 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001845 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001846 const ResStringPool* pool = res.getTableStringBlock(block);
1847 const char* str8 = pool->string8At(value.data, &strLen);
1848 if (str8 != NULL) {
1849 str = env->NewStringUTF(str8);
1850 } else {
1851 const char16_t* str16 = pool->stringAt(value.data, &strLen);
1852 str = env->NewString(str16, strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001853 }
1854
1855 // If one of our NewString{UTF} calls failed due to memory, an
1856 // exception will be pending.
1857 if (env->ExceptionCheck()) {
1858 res.unlockBag(startOfBag);
1859 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001860 }
Kenny Root780d2a12010-02-22 22:36:26 -08001861
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001862 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001863
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001864 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1865 // If we have a large amount of strings in our array, we might
1866 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001867 env->DeleteLocalRef(str);
1868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001869 }
1870 res.unlockBag(startOfBag);
1871 return array;
1872}
1873
1874static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1875 jint arrayResId)
1876{
1877 AssetManager* am = assetManagerForJavaObject(env, clazz);
1878 if (am == NULL) {
1879 return NULL;
1880 }
1881 const ResTable& res(am->getResources());
1882
1883 const ResTable::bag_entry* startOfBag;
1884 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1885 if (N < 0) {
1886 return NULL;
1887 }
1888
1889 jintArray array = env->NewIntArray(N);
1890 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001891 res.unlockBag(startOfBag);
1892 return NULL;
1893 }
1894
1895 Res_value value;
1896 const ResTable::bag_entry* bag = startOfBag;
1897 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1898 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001899
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001900 // Take care of resolving the found resource to its final value.
1901 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001902 if (kThrowOnBadId) {
1903 if (block == BAD_INDEX) {
1904 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1905 return array;
1906 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001907 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001908 if (value.dataType >= Res_value::TYPE_FIRST_INT
1909 && value.dataType <= Res_value::TYPE_LAST_INT) {
1910 int intVal = value.data;
1911 env->SetIntArrayRegion(array, i, 1, &intVal);
1912 }
1913 }
1914 res.unlockBag(startOfBag);
1915 return array;
1916}
1917
Jon Miranda042ad632014-09-03 17:57:35 -07001918static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
1919 jint styleId)
1920{
1921 AssetManager* am = assetManagerForJavaObject(env, clazz);
1922 if (am == NULL) {
1923 return NULL;
1924 }
1925 const ResTable& res(am->getResources());
1926
1927 const ResTable::bag_entry* startOfBag;
1928 const ssize_t N = res.lockBag(styleId, &startOfBag);
1929 if (N < 0) {
1930 return NULL;
1931 }
1932
1933 jintArray array = env->NewIntArray(N);
1934 if (array == NULL) {
1935 res.unlockBag(startOfBag);
1936 return NULL;
1937 }
1938
Jon Miranda042ad632014-09-03 17:57:35 -07001939 const ResTable::bag_entry* bag = startOfBag;
1940 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1941 int resourceId = bag->map.name.ident;
1942 env->SetIntArrayRegion(array, i, 1, &resourceId);
1943 }
1944 res.unlockBag(startOfBag);
1945 return array;
1946}
1947
Mårten Kongstad48d22322014-01-31 14:43:27 +01001948static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001949{
Mårten Kongstad48d22322014-01-31 14:43:27 +01001950 if (isSystem) {
1951 verifySystemIdmaps();
1952 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001953 AssetManager* am = new AssetManager();
1954 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001955 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001956 return;
1957 }
1958
1959 am->addDefaultAssets();
1960
Steve Block71f2cf12011-10-20 11:56:00 +01001961 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00001962 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001963}
1964
1965static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
1966{
1967 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00001968 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01001969 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001970 if (am != NULL) {
1971 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00001972 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001973 }
1974}
1975
1976static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
1977{
1978 return Asset::getGlobalCount();
1979}
1980
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001981static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
1982{
1983 String8 alloc = Asset::getAssetAllocations();
1984 if (alloc.length() <= 0) {
1985 return NULL;
1986 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001987
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001988 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001989 return str;
1990}
1991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001992static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
1993{
1994 return AssetManager::getGlobalCount();
1995}
1996
1997// ----------------------------------------------------------------------------
1998
1999/*
2000 * JNI registration.
2001 */
2002static JNINativeMethod gAssetManagerMethods[] = {
2003 /* name, signature, funcPtr */
2004
2005 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00002006 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002007 (void*) android_content_AssetManager_openAsset },
2008 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2009 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00002010 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002011 (void*) android_content_AssetManager_openNonAssetNative },
2012 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2013 (void*) android_content_AssetManager_openNonAssetFdNative },
2014 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
2015 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00002016 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002017 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002018 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002019 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00002020 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002021 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002022 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002023 (void*) android_content_AssetManager_seekAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002024 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002025 (void*) android_content_AssetManager_getAssetLength },
Ashok Bhat896043d2014-01-17 16:02:38 +00002026 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002027 (void*) android_content_AssetManager_getAssetRemainingLength },
Dianne Hackbornf7be4802013-04-12 14:52:58 -07002028 { "addAssetPathNative", "(Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002029 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad48d22322014-01-31 14:43:27 +01002030 { "addOverlayPath", "(Ljava/lang/String;)I",
2031 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002032 { "isUpToDate", "()Z",
2033 (void*) android_content_AssetManager_isUpToDate },
2034
2035 // Resources.
2036 { "setLocale", "(Ljava/lang/String;)V",
2037 (void*) android_content_AssetManager_setLocale },
2038 { "getLocales", "()[Ljava/lang/String;",
2039 (void*) android_content_AssetManager_getLocales },
Dianne Hackborn69cb8752011-05-19 18:13:32 -07002040 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002041 (void*) android_content_AssetManager_setConfiguration },
2042 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
2043 (void*) android_content_AssetManager_getResourceIdentifier },
2044 { "getResourceName","(I)Ljava/lang/String;",
2045 (void*) android_content_AssetManager_getResourceName },
2046 { "getResourcePackageName","(I)Ljava/lang/String;",
2047 (void*) android_content_AssetManager_getResourcePackageName },
2048 { "getResourceTypeName","(I)Ljava/lang/String;",
2049 (void*) android_content_AssetManager_getResourceTypeName },
2050 { "getResourceEntryName","(I)Ljava/lang/String;",
2051 (void*) android_content_AssetManager_getResourceEntryName },
Kenny Root55fc8502010-10-28 14:47:01 -07002052 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002053 (void*) android_content_AssetManager_loadResourceValue },
2054 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
2055 (void*) android_content_AssetManager_loadResourceBagValue },
2056 { "getStringBlockCount","()I",
2057 (void*) android_content_AssetManager_getStringBlockCount },
Ashok Bhat896043d2014-01-17 16:02:38 +00002058 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002059 (void*) android_content_AssetManager_getNativeStringBlock },
2060 { "getCookieName","(I)Ljava/lang/String;",
2061 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002062 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2063 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002064
2065 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002066 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002067 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002068 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002069 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002070 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002071 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002072 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002073 (void*) android_content_AssetManager_copyTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002074 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002075 (void*) android_content_AssetManager_loadThemeAttributeValue },
Ashok Bhat896043d2014-01-17 16:02:38 +00002076 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002077 (void*) android_content_AssetManager_dumpTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002078 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002079 (void*) android_content_AssetManager_applyStyle },
Alan Viverette607bd842014-09-12 12:36:35 -07002080 { "resolveAttrs","(JII[I[I[I[I)Z",
2081 (void*) android_content_AssetManager_resolveAttrs },
Ashok Bhat896043d2014-01-17 16:02:38 +00002082 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002083 (void*) android_content_AssetManager_retrieveAttributes },
2084 { "getArraySize","(I)I",
2085 (void*) android_content_AssetManager_getArraySize },
2086 { "retrieveArray","(I[I)I",
2087 (void*) android_content_AssetManager_retrieveArray },
2088
2089 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002090 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002091 (void*) android_content_AssetManager_openXmlAssetNative },
2092
2093 // Arrays.
2094 { "getArrayStringResource","(I)[Ljava/lang/String;",
2095 (void*) android_content_AssetManager_getArrayStringResource },
2096 { "getArrayStringInfo","(I)[I",
2097 (void*) android_content_AssetManager_getArrayStringInfo },
2098 { "getArrayIntResource","(I)[I",
2099 (void*) android_content_AssetManager_getArrayIntResource },
Jon Miranda042ad632014-09-03 17:57:35 -07002100 { "getStyleAttributes","(I)[I",
2101 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002102
2103 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002104 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002105 (void*) android_content_AssetManager_init },
2106 { "destroy", "()V",
2107 (void*) android_content_AssetManager_destroy },
2108 { "getGlobalAssetCount", "()I",
2109 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002110 { "getAssetAllocations", "()Ljava/lang/String;",
2111 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002112 { "getGlobalAssetManagerCount", "()I",
Andreas Gampe32812612014-11-11 00:16:00 -08002113 (void*) android_content_AssetManager_getGlobalAssetManagerCount },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002114};
2115
2116int register_android_content_AssetManager(JNIEnv* env)
2117{
2118 jclass typedValue = env->FindClass("android/util/TypedValue");
2119 LOG_FATAL_IF(typedValue == NULL, "Unable to find class android/util/TypedValue");
2120 gTypedValueOffsets.mType
2121 = env->GetFieldID(typedValue, "type", "I");
2122 LOG_FATAL_IF(gTypedValueOffsets.mType == NULL, "Unable to find TypedValue.type");
2123 gTypedValueOffsets.mData
2124 = env->GetFieldID(typedValue, "data", "I");
2125 LOG_FATAL_IF(gTypedValueOffsets.mData == NULL, "Unable to find TypedValue.data");
2126 gTypedValueOffsets.mString
2127 = env->GetFieldID(typedValue, "string", "Ljava/lang/CharSequence;");
2128 LOG_FATAL_IF(gTypedValueOffsets.mString == NULL, "Unable to find TypedValue.string");
2129 gTypedValueOffsets.mAssetCookie
2130 = env->GetFieldID(typedValue, "assetCookie", "I");
2131 LOG_FATAL_IF(gTypedValueOffsets.mAssetCookie == NULL, "Unable to find TypedValue.assetCookie");
2132 gTypedValueOffsets.mResourceId
2133 = env->GetFieldID(typedValue, "resourceId", "I");
2134 LOG_FATAL_IF(gTypedValueOffsets.mResourceId == NULL, "Unable to find TypedValue.resourceId");
2135 gTypedValueOffsets.mChangingConfigurations
2136 = env->GetFieldID(typedValue, "changingConfigurations", "I");
2137 LOG_FATAL_IF(gTypedValueOffsets.mChangingConfigurations == NULL, "Unable to find TypedValue.changingConfigurations");
2138 gTypedValueOffsets.mDensity = env->GetFieldID(typedValue, "density", "I");
2139 LOG_FATAL_IF(gTypedValueOffsets.mDensity == NULL, "Unable to find TypedValue.density");
2140
2141 jclass assetFd = env->FindClass("android/content/res/AssetFileDescriptor");
2142 LOG_FATAL_IF(assetFd == NULL, "Unable to find class android/content/res/AssetFileDescriptor");
2143 gAssetFileDescriptorOffsets.mFd
2144 = env->GetFieldID(assetFd, "mFd", "Landroid/os/ParcelFileDescriptor;");
2145 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mFd == NULL, "Unable to find AssetFileDescriptor.mFd");
2146 gAssetFileDescriptorOffsets.mStartOffset
2147 = env->GetFieldID(assetFd, "mStartOffset", "J");
2148 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mStartOffset == NULL, "Unable to find AssetFileDescriptor.mStartOffset");
2149 gAssetFileDescriptorOffsets.mLength
2150 = env->GetFieldID(assetFd, "mLength", "J");
2151 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mLength == NULL, "Unable to find AssetFileDescriptor.mLength");
2152
2153 jclass assetManager = env->FindClass("android/content/res/AssetManager");
2154 LOG_FATAL_IF(assetManager == NULL, "Unable to find class android/content/res/AssetManager");
2155 gAssetManagerOffsets.mObject
Ashok Bhat896043d2014-01-17 16:02:38 +00002156 = env->GetFieldID(assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002157 LOG_FATAL_IF(gAssetManagerOffsets.mObject == NULL, "Unable to find AssetManager.mObject");
2158
Carl Shapiroc1318ba2011-03-03 14:22:28 -08002159 jclass stringClass = env->FindClass("java/lang/String");
2160 LOG_FATAL_IF(stringClass == NULL, "Unable to find class java/lang/String");
2161 g_stringClass = (jclass)env->NewGlobalRef(stringClass);
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01002162 LOG_FATAL_IF(g_stringClass == NULL, "Unable to create global reference for class java/lang/String");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002163
Adam Lesinskide898ff2014-01-29 18:20:45 -08002164 jclass sparseArrayClass = env->FindClass("android/util/SparseArray");
2165 LOG_FATAL_IF(sparseArrayClass == NULL, "Unable to find class android/util/SparseArray");
2166 gSparseArrayOffsets.classObject = (jclass) env->NewGlobalRef(sparseArrayClass);
2167 gSparseArrayOffsets.constructor =
2168 env->GetMethodID(gSparseArrayOffsets.classObject, "<init>", "()V");
2169 LOG_FATAL_IF(gSparseArrayOffsets.constructor == NULL, "Unable to find SparseArray.<init>()");
2170 gSparseArrayOffsets.put =
2171 env->GetMethodID(gSparseArrayOffsets.classObject, "put", "(ILjava/lang/Object;)V");
2172 LOG_FATAL_IF(gSparseArrayOffsets.put == NULL, "Unable to find SparseArray.put(int, V)");
2173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002174 return AndroidRuntime::registerNativeMethods(env,
2175 "android/content/res/AssetManager", gAssetManagerMethods, NELEM(gAssetManagerMethods));
2176}
2177
2178}; // namespace android