blob: 21b4c3bcc5dfc8f5fe7ed7c9f6baefed1c5a2200 [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>
Adam Lesinskia7d1d732014-10-01 18:24:54 -070033#include <androidfw/AttributeFinder.h>
Mathias Agopianb13b9bd2012-02-17 18:27:36 -080034#include <androidfw/ResourceTypes.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035
Mårten Kongstad48d22322014-01-31 14:43:27 +010036#include <private/android_filesystem_config.h> // for AID_SYSTEM
37
Andreas Gampe987f79f2014-11-18 17:29:46 -080038#include "core_jni_helpers.h"
39
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040#include <stdio.h>
Mårten Kongstad48d22322014-01-31 14:43:27 +010041#include <sys/types.h>
42#include <sys/wait.h>
43
44#include <linux/capability.h>
45extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
46extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
47
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048
49namespace android {
50
Andreas Gampe0f0b4912014-11-12 08:03:48 -080051static const bool kThrowOnBadId = false;
52static const bool kDebugStyles = false;
53
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054// ----------------------------------------------------------------------------
55
56static struct typedvalue_offsets_t
57{
58 jfieldID mType;
59 jfieldID mData;
60 jfieldID mString;
61 jfieldID mAssetCookie;
62 jfieldID mResourceId;
63 jfieldID mChangingConfigurations;
64 jfieldID mDensity;
65} gTypedValueOffsets;
66
67static struct assetfiledescriptor_offsets_t
68{
69 jfieldID mFd;
70 jfieldID mStartOffset;
71 jfieldID mLength;
72} gAssetFileDescriptorOffsets;
73
74static struct assetmanager_offsets_t
75{
76 jfieldID mObject;
77} gAssetManagerOffsets;
78
Adam Lesinskide898ff2014-01-29 18:20:45 -080079static struct sparsearray_offsets_t
80{
81 jclass classObject;
82 jmethodID constructor;
83 jmethodID put;
84} gSparseArrayOffsets;
85
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086jclass g_stringClass = NULL;
87
88// ----------------------------------------------------------------------------
89
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090enum {
Dianne Hackborn0d221012009-07-29 15:41:19 -070091 STYLE_NUM_ENTRIES = 6,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092 STYLE_TYPE = 0,
93 STYLE_DATA = 1,
94 STYLE_ASSET_COOKIE = 2,
95 STYLE_RESOURCE_ID = 3,
Dianne Hackborn0d221012009-07-29 15:41:19 -070096 STYLE_CHANGING_CONFIGURATIONS = 4,
97 STYLE_DENSITY = 5
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098};
99
100static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
101 const Res_value& value, uint32_t ref, ssize_t block,
102 uint32_t typeSpecFlags, ResTable_config* config = NULL);
103
104jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
105 const Res_value& value, uint32_t ref, ssize_t block,
106 uint32_t typeSpecFlags, ResTable_config* config)
107{
108 env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
109 env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
Ashok Bhat896043d2014-01-17 16:02:38 +0000110 static_cast<jint>(table->getTableCookie(block)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
112 env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
113 env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
114 env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
115 typeSpecFlags);
116 if (config != NULL) {
117 env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
118 }
119 return block;
120}
121
Mårten Kongstad48d22322014-01-31 14:43:27 +0100122// This is called by zygote (running as user root) as part of preloadResources.
123static void verifySystemIdmaps()
124{
125 pid_t pid;
126 char system_id[10];
127
128 snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
129
130 switch (pid = fork()) {
131 case -1:
132 ALOGE("failed to fork for idmap: %s", strerror(errno));
133 break;
134 case 0: // child
135 {
136 struct __user_cap_header_struct capheader;
137 struct __user_cap_data_struct capdata;
138
139 memset(&capheader, 0, sizeof(capheader));
140 memset(&capdata, 0, sizeof(capdata));
141
142 capheader.version = _LINUX_CAPABILITY_VERSION;
143 capheader.pid = 0;
144
145 if (capget(&capheader, &capdata) != 0) {
146 ALOGE("capget: %s\n", strerror(errno));
147 exit(1);
148 }
149
150 capdata.effective = capdata.permitted;
151 if (capset(&capheader, &capdata) != 0) {
152 ALOGE("capset: %s\n", strerror(errno));
153 exit(1);
154 }
155
156 if (setgid(AID_SYSTEM) != 0) {
157 ALOGE("setgid: %s\n", strerror(errno));
158 exit(1);
159 }
160
161 if (setuid(AID_SYSTEM) != 0) {
162 ALOGE("setuid: %s\n", strerror(errno));
163 exit(1);
164 }
165
166 execl(AssetManager::IDMAP_BIN, AssetManager::IDMAP_BIN, "--scan",
167 AssetManager::OVERLAY_DIR, AssetManager::TARGET_PACKAGE_NAME,
168 AssetManager::TARGET_APK_PATH, AssetManager::IDMAP_DIR, (char*)NULL);
169 ALOGE("failed to execl for idmap: %s", strerror(errno));
170 exit(1); // should never get here
171 }
172 break;
173 default: // parent
174 waitpid(pid, NULL, 0);
175 break;
176 }
177}
178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179// ----------------------------------------------------------------------------
180
181// this guy is exported to other jni routines
182AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
183{
Ashok Bhat896043d2014-01-17 16:02:38 +0000184 jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
185 AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 if (am != NULL) {
187 return am;
188 }
189 jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
190 return NULL;
191}
192
Ashok Bhat896043d2014-01-17 16:02:38 +0000193static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 jstring fileName, jint mode)
195{
196 AssetManager* am = assetManagerForJavaObject(env, clazz);
197 if (am == NULL) {
198 return 0;
199 }
200
Steve Block71f2cf12011-10-20 11:56:00 +0100201 ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202
Elliott Hughes69a017b2011-04-08 14:10:28 -0700203 ScopedUtfChars fileName8(env, fileName);
204 if (fileName8.c_str() == NULL) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000205 jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 return -1;
207 }
208
209 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
210 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700211 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 return -1;
213 }
214
Elliott Hughes69a017b2011-04-08 14:10:28 -0700215 Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216
217 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700218 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 return -1;
220 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221
222 //printf("Created Asset Stream: %p\n", a);
223
Ashok Bhat896043d2014-01-17 16:02:38 +0000224 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225}
226
227static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
228{
Kenny Rootddb76c42010-11-24 12:56:06 -0800229 off64_t startOffset, length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 int fd = a->openFileDescriptor(&startOffset, &length);
231 delete a;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 if (fd < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700234 jniThrowException(env, "java/io/FileNotFoundException",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 "This file can not be opened as a file descriptor; it is probably compressed");
236 return NULL;
237 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
240 if (offsets == NULL) {
241 close(fd);
242 return NULL;
243 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245 offsets[0] = startOffset;
246 offsets[1] = length;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700249
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700250 jobject fileDesc = jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 if (fileDesc == NULL) {
252 close(fd);
253 return NULL;
254 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 return newParcelFileDescriptor(env, fileDesc);
257}
258
259static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
260 jstring fileName, jlongArray outOffsets)
261{
262 AssetManager* am = assetManagerForJavaObject(env, clazz);
263 if (am == NULL) {
264 return NULL;
265 }
266
Steve Block71f2cf12011-10-20 11:56:00 +0100267 ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268
Elliott Hughes69a017b2011-04-08 14:10:28 -0700269 ScopedUtfChars fileName8(env, fileName);
270 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 return NULL;
272 }
273
Elliott Hughes69a017b2011-04-08 14:10:28 -0700274 Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275
276 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700277 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 return NULL;
279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280
281 //printf("Created Asset Stream: %p\n", a);
282
283 return returnParcelFileDescriptor(env, a, outOffsets);
284}
285
Ashok Bhat896043d2014-01-17 16:02:38 +0000286static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 jint cookie,
288 jstring fileName,
289 jint mode)
290{
291 AssetManager* am = assetManagerForJavaObject(env, clazz);
292 if (am == NULL) {
293 return 0;
294 }
295
Steve Block71f2cf12011-10-20 11:56:00 +0100296 ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297
Elliott Hughes69a017b2011-04-08 14:10:28 -0700298 ScopedUtfChars fileName8(env, fileName);
299 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300 return -1;
301 }
302
303 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
304 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700305 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 return -1;
307 }
308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800309 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000310 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
311 (Asset::AccessMode)mode)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700312 : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313
314 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700315 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 return -1;
317 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318
319 //printf("Created Asset Stream: %p\n", a);
320
Ashok Bhat896043d2014-01-17 16:02:38 +0000321 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322}
323
324static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
325 jint cookie,
326 jstring fileName,
327 jlongArray outOffsets)
328{
329 AssetManager* am = assetManagerForJavaObject(env, clazz);
330 if (am == NULL) {
331 return NULL;
332 }
333
Steve Block71f2cf12011-10-20 11:56:00 +0100334 ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800335
Elliott Hughes69a017b2011-04-08 14:10:28 -0700336 ScopedUtfChars fileName8(env, fileName);
337 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800338 return NULL;
339 }
340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000342 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700343 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344
345 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700346 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 return NULL;
348 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349
350 //printf("Created Asset Stream: %p\n", a);
351
352 return returnParcelFileDescriptor(env, a, outOffsets);
353}
354
355static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
356 jstring fileName)
357{
358 AssetManager* am = assetManagerForJavaObject(env, clazz);
359 if (am == NULL) {
360 return NULL;
361 }
362
Elliott Hughes69a017b2011-04-08 14:10:28 -0700363 ScopedUtfChars fileName8(env, fileName);
364 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365 return NULL;
366 }
367
Elliott Hughes69a017b2011-04-08 14:10:28 -0700368 AssetDir* dir = am->openDir(fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369
370 if (dir == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700371 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800372 return NULL;
373 }
374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800375 size_t N = dir->getFileCount();
376
377 jobjectArray array = env->NewObjectArray(dir->getFileCount(),
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +0100378 g_stringClass, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800380 delete dir;
381 return NULL;
382 }
383
384 for (size_t i=0; i<N; i++) {
385 const String8& name = dir->getFileName(i);
386 jstring str = env->NewStringUTF(name.string());
387 if (str == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388 delete dir;
389 return NULL;
390 }
391 env->SetObjectArrayElement(array, i, str);
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700392 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800393 }
394
395 delete dir;
396
397 return array;
398}
399
400static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000401 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402{
Ashok Bhat896043d2014-01-17 16:02:38 +0000403 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800404
405 //printf("Destroying Asset Stream: %p\n", a);
406
407 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700408 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 return;
410 }
411
412 delete a;
413}
414
415static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000416 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417{
Ashok Bhat896043d2014-01-17 16:02:38 +0000418 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419
420 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700421 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 return -1;
423 }
424
425 uint8_t b;
426 ssize_t res = a->read(&b, 1);
427 return res == 1 ? b : -1;
428}
429
430static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000431 jlong assetHandle, jbyteArray bArray,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 jint off, jint len)
433{
Ashok Bhat896043d2014-01-17 16:02:38 +0000434 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435
436 if (a == NULL || bArray == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700437 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 return -1;
439 }
440
441 if (len == 0) {
442 return 0;
443 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445 jsize bLen = env->GetArrayLength(bArray);
446 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700447 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 return -1;
449 }
450
451 jbyte* b = env->GetByteArrayElements(bArray, NULL);
452 ssize_t res = a->read(b+off, len);
453 env->ReleaseByteArrayElements(bArray, b, 0);
454
Ashok Bhat896043d2014-01-17 16:02:38 +0000455 if (res > 0) return static_cast<jint>(res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456
457 if (res < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700458 jniThrowException(env, "java/io/IOException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459 }
460 return -1;
461}
462
463static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000464 jlong assetHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800465 jlong offset, jint whence)
466{
Ashok Bhat896043d2014-01-17 16:02:38 +0000467 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800468
469 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700470 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800471 return -1;
472 }
473
474 return a->seek(
475 offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
476}
477
478static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000479 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480{
Ashok Bhat896043d2014-01-17 16:02:38 +0000481 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482
483 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700484 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800485 return -1;
486 }
487
488 return a->getLength();
489}
490
491static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000492 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493{
Ashok Bhat896043d2014-01-17 16:02:38 +0000494 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495
496 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700497 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800498 return -1;
499 }
500
501 return a->getRemainingLength();
502}
503
504static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
505 jstring path)
506{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700507 ScopedUtfChars path8(env, path);
508 if (path8.c_str() == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800509 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 }
511
512 AssetManager* am = assetManagerForJavaObject(env, clazz);
513 if (am == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800514 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800515 }
516
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000517 int32_t cookie;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700518 bool res = am->addAssetPath(String8(path8.c_str()), &cookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000520 return (res) ? static_cast<jint>(cookie) : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800521}
522
Mårten Kongstad48d22322014-01-31 14:43:27 +0100523static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
524 jstring idmapPath)
525{
526 ScopedUtfChars idmapPath8(env, idmapPath);
527 if (idmapPath8.c_str() == NULL) {
528 return 0;
529 }
530
531 AssetManager* am = assetManagerForJavaObject(env, clazz);
532 if (am == NULL) {
533 return 0;
534 }
535
536 int32_t cookie;
537 bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
538
539 return (res) ? (jint)cookie : 0;
540}
541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
543{
544 AssetManager* am = assetManagerForJavaObject(env, clazz);
545 if (am == NULL) {
546 return JNI_TRUE;
547 }
548 return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
549}
550
551static void android_content_AssetManager_setLocale(JNIEnv* env, jobject clazz,
552 jstring locale)
553{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700554 ScopedUtfChars locale8(env, locale);
555 if (locale8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 return;
557 }
558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800559 AssetManager* am = assetManagerForJavaObject(env, clazz);
560 if (am == NULL) {
561 return;
562 }
563
Elliott Hughes69a017b2011-04-08 14:10:28 -0700564 am->setLocale(locale8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800565}
566
567static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
568{
569 Vector<String8> locales;
570
571 AssetManager* am = assetManagerForJavaObject(env, clazz);
572 if (am == NULL) {
573 return NULL;
574 }
575
576 am->getLocales(&locales);
577
578 const int N = locales.size();
579
580 jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
581 if (result == NULL) {
582 return NULL;
583 }
584
585 for (int i=0; i<N; i++) {
Gilles Debunne0db187a2010-08-27 11:51:34 -0700586 jstring str = env->NewStringUTF(locales[i].string());
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700587 if (str == NULL) {
588 return NULL;
589 }
590 env->SetObjectArrayElement(result, i, str);
591 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800592 }
593
594 return result;
595}
596
597static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
598 jint mcc, jint mnc,
599 jstring locale, jint orientation,
600 jint touchscreen, jint density,
601 jint keyboard, jint keyboardHidden,
602 jint navigation,
603 jint screenWidth, jint screenHeight,
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700604 jint smallestScreenWidthDp,
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700605 jint screenWidthDp, jint screenHeightDp,
Tobias Haamel27b28b32010-02-09 23:09:17 +0100606 jint screenLayout, jint uiMode,
607 jint sdkVersion)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800608{
609 AssetManager* am = assetManagerForJavaObject(env, clazz);
610 if (am == NULL) {
611 return;
612 }
613
614 ResTable_config config;
615 memset(&config, 0, sizeof(config));
Elliott Hughes69a017b2011-04-08 14:10:28 -0700616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800617 const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619 config.mcc = (uint16_t)mcc;
620 config.mnc = (uint16_t)mnc;
621 config.orientation = (uint8_t)orientation;
622 config.touchscreen = (uint8_t)touchscreen;
623 config.density = (uint16_t)density;
624 config.keyboard = (uint8_t)keyboard;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700625 config.inputFlags = (uint8_t)keyboardHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 config.navigation = (uint8_t)navigation;
627 config.screenWidth = (uint16_t)screenWidth;
628 config.screenHeight = (uint16_t)screenHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700629 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700630 config.screenWidthDp = (uint16_t)screenWidthDp;
631 config.screenHeightDp = (uint16_t)screenHeightDp;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700632 config.screenLayout = (uint8_t)screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100633 config.uiMode = (uint8_t)uiMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 config.sdkVersion = (uint16_t)sdkVersion;
635 config.minorVersion = 0;
636 am->setConfiguration(config, locale8);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800638 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
639}
640
641static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
642 jstring name,
643 jstring defType,
644 jstring defPackage)
645{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700646 ScopedStringChars name16(env, name);
647 if (name16.get() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648 return 0;
649 }
650
651 AssetManager* am = assetManagerForJavaObject(env, clazz);
652 if (am == NULL) {
653 return 0;
654 }
655
Dan Albert66987492014-11-20 11:41:21 -0800656 const char16_t* defType16 = reinterpret_cast<const char16_t*>(defType)
657 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defType, NULL))
658 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800659 jsize defTypeLen = defType
660 ? env->GetStringLength(defType) : 0;
Dan Albert66987492014-11-20 11:41:21 -0800661 const char16_t* defPackage16 = reinterpret_cast<const char16_t*>(defPackage)
662 ? reinterpret_cast<const char16_t*>(env->GetStringChars(defPackage,
663 NULL))
664 : NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800665 jsize defPackageLen = defPackage
666 ? env->GetStringLength(defPackage) : 0;
667
668 jint ident = am->getResources().identifierForName(
Dan Albert66987492014-11-20 11:41:21 -0800669 reinterpret_cast<const char16_t*>(name16.get()), name16.size(),
670 defType16, defTypeLen, defPackage16, defPackageLen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800671
672 if (defPackage16) {
Dan Albert66987492014-11-20 11:41:21 -0800673 env->ReleaseStringChars(defPackage,
674 reinterpret_cast<const jchar*>(defPackage16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800675 }
676 if (defType16) {
Dan Albert66987492014-11-20 11:41:21 -0800677 env->ReleaseStringChars(defType,
678 reinterpret_cast<const jchar*>(defType16));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800679 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800680
681 return ident;
682}
683
684static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
685 jint resid)
686{
687 AssetManager* am = assetManagerForJavaObject(env, clazz);
688 if (am == NULL) {
689 return NULL;
690 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700691
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800692 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700693 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 return NULL;
695 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 String16 str;
698 if (name.package != NULL) {
699 str.setTo(name.package, name.packageLen);
700 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700701 if (name.type8 != NULL || name.type != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702 if (str.size() > 0) {
703 char16_t div = ':';
704 str.append(&div, 1);
705 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700706 if (name.type8 != NULL) {
707 str.append(String16(name.type8, name.typeLen));
708 } else {
709 str.append(name.type, name.typeLen);
710 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700712 if (name.name8 != NULL || name.name != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800713 if (str.size() > 0) {
714 char16_t div = '/';
715 str.append(&div, 1);
716 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700717 if (name.name8 != NULL) {
718 str.append(String16(name.name8, name.nameLen));
719 } else {
720 str.append(name.name, name.nameLen);
721 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800722 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800724 return env->NewString((const jchar*)str.string(), str.size());
725}
726
727static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
728 jint resid)
729{
730 AssetManager* am = assetManagerForJavaObject(env, clazz);
731 if (am == NULL) {
732 return NULL;
733 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700736 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800737 return NULL;
738 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800740 if (name.package != NULL) {
741 return env->NewString((const jchar*)name.package, name.packageLen);
742 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744 return NULL;
745}
746
747static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
748 jint resid)
749{
750 AssetManager* am = assetManagerForJavaObject(env, clazz);
751 if (am == NULL) {
752 return NULL;
753 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700754
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700756 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800757 return NULL;
758 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700759
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700760 if (name.type8 != NULL) {
761 return env->NewStringUTF(name.type8);
762 }
763
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800764 if (name.type != NULL) {
765 return env->NewString((const jchar*)name.type, name.typeLen);
766 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700767
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800768 return NULL;
769}
770
771static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
772 jint resid)
773{
774 AssetManager* am = assetManagerForJavaObject(env, clazz);
775 if (am == NULL) {
776 return NULL;
777 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700780 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800781 return NULL;
782 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700783
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700784 if (name.name8 != NULL) {
785 return env->NewStringUTF(name.name8);
786 }
787
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800788 if (name.name != NULL) {
789 return env->NewString((const jchar*)name.name, name.nameLen);
790 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792 return NULL;
793}
794
795static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
796 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700797 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 jobject outValue,
799 jboolean resolve)
800{
Dianne Hackborn1f7d3072013-02-11 17:03:32 -0800801 if (outValue == NULL) {
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800802 jniThrowNullPointerException(env, "outValue");
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700803 return 0;
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 AssetManager* am = assetManagerForJavaObject(env, clazz);
806 if (am == NULL) {
807 return 0;
808 }
809 const ResTable& res(am->getResources());
810
811 Res_value value;
812 ResTable_config config;
813 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700814 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800815 if (kThrowOnBadId) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800816 if (block == BAD_INDEX) {
817 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
818 return 0;
819 }
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800820 }
821 uint32_t ref = ident;
822 if (resolve) {
823 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
824 if (kThrowOnBadId) {
825 if (block == BAD_INDEX) {
826 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
827 return 0;
828 }
829 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800830 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000831 if (block >= 0) {
832 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
833 }
834
835 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800836}
837
838static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
839 jint ident, jint bagEntryId,
840 jobject outValue, jboolean resolve)
841{
842 AssetManager* am = assetManagerForJavaObject(env, clazz);
843 if (am == NULL) {
844 return 0;
845 }
846 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700847
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800848 // Now lock down the resource object and start pulling stuff from it.
849 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -0700850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800851 ssize_t block = -1;
852 Res_value value;
853
854 const ResTable::bag_entry* entry = NULL;
855 uint32_t typeSpecFlags;
856 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
857
858 for (ssize_t i=0; i<entryCount; i++) {
859 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
860 block = entry->stringBlock;
861 value = entry->map.value;
862 }
863 entry++;
864 }
865
866 res.unlock();
867
868 if (block < 0) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000869 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800870 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872 uint32_t ref = ident;
873 if (resolve) {
874 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800875 if (kThrowOnBadId) {
876 if (block == BAD_INDEX) {
877 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
878 return 0;
879 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800880 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000882 if (block >= 0) {
883 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
884 }
885
886 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800887}
888
889static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
890{
891 AssetManager* am = assetManagerForJavaObject(env, clazz);
892 if (am == NULL) {
893 return 0;
894 }
895 return am->getResources().getTableCount();
896}
897
Ashok Bhat896043d2014-01-17 16:02:38 +0000898static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800899 jint block)
900{
901 AssetManager* am = assetManagerForJavaObject(env, clazz);
902 if (am == NULL) {
903 return 0;
904 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000905 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906}
907
908static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
909 jint cookie)
910{
911 AssetManager* am = assetManagerForJavaObject(env, clazz);
912 if (am == NULL) {
913 return NULL;
914 }
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000915 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800916 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700917 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800918 return NULL;
919 }
920 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921 return str;
922}
923
Adam Lesinskide898ff2014-01-29 18:20:45 -0800924static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
925{
926 AssetManager* am = assetManagerForJavaObject(env, clazz);
927 if (am == NULL) {
928 return 0;
929 }
930
931 const ResTable& res = am->getResources();
932
933 jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
934 gSparseArrayOffsets.constructor);
935 const size_t N = res.getBasePackageCount();
936 for (size_t i = 0; i < N; i++) {
937 const String16 name = res.getBasePackageName(i);
Dan Albert66987492014-11-20 11:41:21 -0800938 env->CallVoidMethod(
939 sparseArray, gSparseArrayOffsets.put,
940 static_cast<jint>(res.getBasePackageId(i)),
941 env->NewString(reinterpret_cast<const jchar*>(name.string()),
942 name.size()));
Adam Lesinskide898ff2014-01-29 18:20:45 -0800943 }
944 return sparseArray;
945}
946
Ashok Bhat896043d2014-01-17 16:02:38 +0000947static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948{
949 AssetManager* am = assetManagerForJavaObject(env, clazz);
950 if (am == NULL) {
951 return 0;
952 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000953 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954}
955
956static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000957 jlong themeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800958{
Ashok Bhat896043d2014-01-17 16:02:38 +0000959 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960 delete theme;
961}
962
963static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000964 jlong themeHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800965 jint styleRes,
966 jboolean force)
967{
Ashok Bhat896043d2014-01-17 16:02:38 +0000968 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800969 theme->applyStyle(styleRes, force ? true : false);
970}
971
972static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000973 jlong destHandle, jlong srcHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974{
Ashok Bhat896043d2014-01-17 16:02:38 +0000975 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
976 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977 dest->setTo(*src);
978}
979
980static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +0000981 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800982{
Ashok Bhat896043d2014-01-17 16:02:38 +0000983 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 const ResTable& res(theme->getResTable());
985
986 Res_value value;
987 // XXX value could be different in different configs!
988 uint32_t typeSpecFlags = 0;
989 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
990 uint32_t ref = 0;
991 if (resolve) {
992 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800993 if (kThrowOnBadId) {
994 if (block == BAD_INDEX) {
995 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
996 return 0;
997 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800998 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 }
1000 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
1001}
1002
1003static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001004 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 jstring tag, jstring prefix)
1006{
Ashok Bhat896043d2014-01-17 16:02:38 +00001007 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001008 const ResTable& res(theme->getResTable());
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001009 (void)res;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 // XXX Need to use params.
1012 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013}
1014
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001015class XmlAttributeFinder : public BackTrackingAttributeFinder<XmlAttributeFinder, jsize> {
1016public:
1017 XmlAttributeFinder(const ResXMLParser* parser)
1018 : BackTrackingAttributeFinder(0, parser != NULL ? parser->getAttributeCount() : 0)
1019 , mParser(parser) {}
1020
1021 inline uint32_t getAttribute(jsize index) const {
1022 return mParser->getAttributeNameResID(index);
1023 }
1024
1025private:
1026 const ResXMLParser* mParser;
1027};
1028
1029class BagAttributeFinder : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
1030public:
1031 BagAttributeFinder(const ResTable::bag_entry* start, const ResTable::bag_entry* end)
1032 : BackTrackingAttributeFinder(start, end) {}
1033
1034 inline uint32_t getAttribute(const ResTable::bag_entry* entry) const {
1035 return entry->map.name.ident;
1036 }
1037};
1038
Alan Viverette52b999f2014-03-24 18:00:26 -07001039static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1040 jlong themeToken,
1041 jint defStyleAttr,
1042 jint defStyleRes,
1043 jintArray inValues,
1044 jintArray attrs,
1045 jintArray outValues,
1046 jintArray outIndices)
1047{
1048 if (themeToken == 0) {
1049 jniThrowNullPointerException(env, "theme token");
1050 return JNI_FALSE;
1051 }
1052 if (attrs == NULL) {
1053 jniThrowNullPointerException(env, "attrs");
1054 return JNI_FALSE;
1055 }
1056 if (outValues == NULL) {
1057 jniThrowNullPointerException(env, "out values");
1058 return JNI_FALSE;
1059 }
1060
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001061 if (kDebugStyles) {
1062 ALOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x",
1063 themeToken, defStyleAttr, defStyleRes);
1064 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001065
1066 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1067 const ResTable& res = theme->getResTable();
1068 ResTable_config config;
1069 Res_value value;
1070
1071 const jsize NI = env->GetArrayLength(attrs);
1072 const jsize NV = env->GetArrayLength(outValues);
1073 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1074 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1075 return JNI_FALSE;
1076 }
1077
1078 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1079 if (src == NULL) {
1080 return JNI_FALSE;
1081 }
1082
1083 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1084 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1085
1086 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1087 jint* dest = baseDest;
1088 if (dest == NULL) {
1089 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1090 return JNI_FALSE;
1091 }
1092
1093 jint* indices = NULL;
1094 int indicesIdx = 0;
1095 if (outIndices != NULL) {
1096 if (env->GetArrayLength(outIndices) > NI) {
1097 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1098 }
1099 }
1100
1101 // Load default style from attribute, if specified...
1102 uint32_t defStyleBagTypeSetFlags = 0;
1103 if (defStyleAttr != 0) {
1104 Res_value value;
1105 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1106 if (value.dataType == Res_value::TYPE_REFERENCE) {
1107 defStyleRes = value.data;
1108 }
1109 }
1110 }
1111
1112 // Now lock down the resource object and start pulling stuff from it.
1113 res.lock();
1114
1115 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001116 const ResTable::bag_entry* defStyleStart = NULL;
Alan Viverette52b999f2014-03-24 18:00:26 -07001117 uint32_t defStyleTypeSetFlags = 0;
1118 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001119 ? res.getBagLocked(defStyleRes, &defStyleStart, &defStyleTypeSetFlags) : -1;
Alan Viverette52b999f2014-03-24 18:00:26 -07001120 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001121 const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
1122 BagAttributeFinder defStyleAttrFinder(defStyleStart, defStyleEnd);
Alan Viverette52b999f2014-03-24 18:00:26 -07001123
1124 // Now iterate through all of the attributes that the client has requested,
1125 // filling in each with whatever data we can find.
1126 ssize_t block = 0;
1127 uint32_t typeSetFlags;
1128 for (jsize ii=0; ii<NI; ii++) {
1129 const uint32_t curIdent = (uint32_t)src[ii];
1130
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001131 if (kDebugStyles) {
1132 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1133 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001134
1135 // Try to find a value for this attribute... we prioritize values
1136 // coming from, first XML attributes, then XML style, then default
1137 // style, and finally the theme.
1138 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001139 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001140 typeSetFlags = 0;
1141 config.density = 0;
1142
1143 // Retrieve the current input value if available.
1144 if (NSV > 0 && srcValues[ii] != 0) {
1145 block = -1;
1146 value.dataType = Res_value::TYPE_ATTRIBUTE;
1147 value.data = srcValues[ii];
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001148 if (kDebugStyles) {
1149 ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
1150 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001151 }
1152
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001153 if (value.dataType == Res_value::TYPE_NULL) {
1154 const ResTable::bag_entry* const defStyleEntry = defStyleAttrFinder.find(curIdent);
1155 if (defStyleEntry != defStyleEnd) {
1156 block = defStyleEntry->stringBlock;
Alan Viverette52b999f2014-03-24 18:00:26 -07001157 typeSetFlags = defStyleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001158 value = defStyleEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001159 if (kDebugStyles) {
1160 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1161 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001162 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001163 }
1164
1165 uint32_t resid = 0;
1166 if (value.dataType != Res_value::TYPE_NULL) {
1167 // Take care of resolving the found resource to its final value.
1168 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1169 &resid, &typeSetFlags, &config);
1170 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001171 if (kDebugStyles) {
1172 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1173 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001174 } else {
1175 // If we still don't have a value for this attribute, try to find
1176 // it in the theme!
1177 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1178 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001179 if (kDebugStyles) {
1180 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1181 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001182 newBlock = res.resolveReference(&value, block, &resid,
1183 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001184 if (kThrowOnBadId) {
1185 if (newBlock == BAD_INDEX) {
1186 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1187 return JNI_FALSE;
1188 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001189 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001190 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001191 if (kDebugStyles) {
1192 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1193 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001194 }
1195 }
1196
1197 // Deal with the special @null value -- it turns back to TYPE_NULL.
1198 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001199 if (kDebugStyles) {
1200 ALOGI("-> Setting to @null!");
1201 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001202 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001203 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001204 block = -1;
1205 }
1206
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001207 if (kDebugStyles) {
1208 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
1209 value.data);
1210 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001211
1212 // Write the final value back to Java.
1213 dest[STYLE_TYPE] = value.dataType;
1214 dest[STYLE_DATA] = value.data;
1215 dest[STYLE_ASSET_COOKIE] =
1216 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1217 dest[STYLE_RESOURCE_ID] = resid;
1218 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1219 dest[STYLE_DENSITY] = config.density;
1220
1221 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1222 indicesIdx++;
1223 indices[indicesIdx] = ii;
1224 }
1225
1226 dest += STYLE_NUM_ENTRIES;
1227 }
1228
1229 res.unlock();
1230
1231 if (indices != NULL) {
1232 indices[0] = indicesIdx;
1233 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1234 }
1235 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1236 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1237 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1238
1239 return JNI_TRUE;
1240}
1241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001242static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001243 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001244 jint defStyleAttr,
1245 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +00001246 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001247 jintArray attrs,
1248 jintArray outValues,
1249 jintArray outIndices)
1250{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001251 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001252 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001253 return JNI_FALSE;
1254 }
1255 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001256 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001257 return JNI_FALSE;
1258 }
1259 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001260 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001261 return JNI_FALSE;
1262 }
1263
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001264 if (kDebugStyles) {
1265 ALOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x xml=0x%x",
1266 themeToken, defStyleAttr, defStyleRes, xmlParserToken);
1267 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001268
Ashok Bhat896043d2014-01-17 16:02:38 +00001269 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001270 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001271 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001272 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001273 Res_value value;
1274
1275 const jsize NI = env->GetArrayLength(attrs);
1276 const jsize NV = env->GetArrayLength(outValues);
1277 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001278 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001279 return JNI_FALSE;
1280 }
1281
1282 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1283 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001284 return JNI_FALSE;
1285 }
1286
1287 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1288 jint* dest = baseDest;
1289 if (dest == NULL) {
1290 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001291 return JNI_FALSE;
1292 }
1293
1294 jint* indices = NULL;
1295 int indicesIdx = 0;
1296 if (outIndices != NULL) {
1297 if (env->GetArrayLength(outIndices) > NI) {
1298 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1299 }
1300 }
1301
1302 // Load default style from attribute, if specified...
1303 uint32_t defStyleBagTypeSetFlags = 0;
1304 if (defStyleAttr != 0) {
1305 Res_value value;
1306 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1307 if (value.dataType == Res_value::TYPE_REFERENCE) {
1308 defStyleRes = value.data;
1309 }
1310 }
1311 }
1312
1313 // Retrieve the style class associated with the current XML tag.
1314 int style = 0;
1315 uint32_t styleBagTypeSetFlags = 0;
1316 if (xmlParser != NULL) {
1317 ssize_t idx = xmlParser->indexOfStyle();
1318 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1319 if (value.dataType == value.TYPE_ATTRIBUTE) {
1320 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1321 value.dataType = Res_value::TYPE_NULL;
1322 }
1323 }
1324 if (value.dataType == value.TYPE_REFERENCE) {
1325 style = value.data;
1326 }
1327 }
1328 }
1329
1330 // Now lock down the resource object and start pulling stuff from it.
1331 res.lock();
1332
1333 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001334 const ResTable::bag_entry* defStyleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001335 uint32_t defStyleTypeSetFlags = 0;
1336 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001337 ? res.getBagLocked(defStyleRes, &defStyleAttrStart, &defStyleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001338 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001339 const ResTable::bag_entry* const defStyleAttrEnd = defStyleAttrStart + (bagOff >= 0 ? bagOff : 0);
1340 BagAttributeFinder defStyleAttrFinder(defStyleAttrStart, defStyleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001341
1342 // Retrieve the style class bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001343 const ResTable::bag_entry* styleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001344 uint32_t styleTypeSetFlags = 0;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001345 bagOff = style != 0 ? res.getBagLocked(style, &styleAttrStart, &styleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001346 styleTypeSetFlags |= styleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001347 const ResTable::bag_entry* const styleAttrEnd = styleAttrStart + (bagOff >= 0 ? bagOff : 0);
1348 BagAttributeFinder styleAttrFinder(styleAttrStart, styleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349
1350 // Retrieve the XML attributes, if requested.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 static const ssize_t kXmlBlock = 0x10000000;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001352 XmlAttributeFinder xmlAttrFinder(xmlParser);
1353 const jsize xmlAttrEnd = xmlParser != NULL ? xmlParser->getAttributeCount() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001354
1355 // Now iterate through all of the attributes that the client has requested,
1356 // filling in each with whatever data we can find.
1357 ssize_t block = 0;
1358 uint32_t typeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001359 for (jsize ii = 0; ii < NI; ii++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001360 const uint32_t curIdent = (uint32_t)src[ii];
1361
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001362 if (kDebugStyles) {
1363 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1364 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001366 // Try to find a value for this attribute... we prioritize values
1367 // coming from, first XML attributes, then XML style, then default
1368 // style, and finally the theme.
1369 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001370 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001371 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001372 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001374 // Walk through the xml attributes looking for the requested attribute.
1375 const jsize xmlAttrIdx = xmlAttrFinder.find(curIdent);
1376 if (xmlAttrIdx != xmlAttrEnd) {
1377 // We found the attribute we were looking for.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001378 block = kXmlBlock;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001379 xmlParser->getAttributeValue(xmlAttrIdx, &value);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001380 if (kDebugStyles) {
1381 ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
1382 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001383 }
1384
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001385 if (value.dataType == Res_value::TYPE_NULL) {
1386 // Walk through the style class values looking for the requested attribute.
1387 const ResTable::bag_entry* const styleAttrEntry = styleAttrFinder.find(curIdent);
1388 if (styleAttrEntry != styleAttrEnd) {
1389 // We found the attribute we were looking for.
1390 block = styleAttrEntry->stringBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001391 typeSetFlags = styleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001392 value = styleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001393 if (kDebugStyles) {
1394 ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
1395 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001397 }
1398
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001399 if (value.dataType == Res_value::TYPE_NULL) {
1400 // Walk through the default style values looking for the requested attribute.
1401 const ResTable::bag_entry* const defStyleAttrEntry = defStyleAttrFinder.find(curIdent);
1402 if (defStyleAttrEntry != defStyleAttrEnd) {
1403 // We found the attribute we were looking for.
1404 block = defStyleAttrEntry->stringBlock;
1405 typeSetFlags = styleTypeSetFlags;
1406 value = defStyleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001407 if (kDebugStyles) {
1408 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1409 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001410 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001411 }
1412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413 uint32_t resid = 0;
1414 if (value.dataType != Res_value::TYPE_NULL) {
1415 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001416 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1417 &resid, &typeSetFlags, &config);
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001418 if (newBlock >= 0) {
1419 block = newBlock;
1420 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001421
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001422 if (kDebugStyles) {
1423 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001425 } else {
1426 // If we still don't have a value for this attribute, try to find
1427 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001428 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1429 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001430 if (kDebugStyles) {
1431 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1432 }
Dianne Hackborn0d221012009-07-29 15:41:19 -07001433 newBlock = res.resolveReference(&value, block, &resid,
1434 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001435 if (kThrowOnBadId) {
1436 if (newBlock == BAD_INDEX) {
1437 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1438 return JNI_FALSE;
1439 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001440 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001441
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001442 if (newBlock >= 0) {
1443 block = newBlock;
1444 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001445
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001446 if (kDebugStyles) {
1447 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 }
1450 }
1451
1452 // Deal with the special @null value -- it turns back to TYPE_NULL.
1453 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001454 if (kDebugStyles) {
1455 ALOGI("-> Setting to @null!");
1456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001458 value.data = Res_value::DATA_NULL_UNDEFINED;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001459 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 }
1461
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001462 if (kDebugStyles) {
1463 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
1464 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001465
1466 // Write the final value back to Java.
1467 dest[STYLE_TYPE] = value.dataType;
1468 dest[STYLE_DATA] = value.data;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001469 dest[STYLE_ASSET_COOKIE] = block != kXmlBlock ?
1470 static_cast<jint>(res.getTableCookie(block)) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001471 dest[STYLE_RESOURCE_ID] = resid;
1472 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001473 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001475 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1476 indicesIdx++;
1477 indices[indicesIdx] = ii;
1478 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480 dest += STYLE_NUM_ENTRIES;
1481 }
1482
1483 res.unlock();
1484
1485 if (indices != NULL) {
1486 indices[0] = indicesIdx;
1487 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1488 }
1489 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1490 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1491
1492 return JNI_TRUE;
1493}
1494
1495static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001496 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 jintArray attrs,
1498 jintArray outValues,
1499 jintArray outIndices)
1500{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001501 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001502 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001503 return JNI_FALSE;
1504 }
1505 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001506 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001507 return JNI_FALSE;
1508 }
1509 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001510 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 return JNI_FALSE;
1512 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001514 AssetManager* am = assetManagerForJavaObject(env, clazz);
1515 if (am == NULL) {
1516 return JNI_FALSE;
1517 }
1518 const ResTable& res(am->getResources());
1519 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001520 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523 const jsize NI = env->GetArrayLength(attrs);
1524 const jsize NV = env->GetArrayLength(outValues);
1525 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001526 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001527 return JNI_FALSE;
1528 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1531 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 return JNI_FALSE;
1533 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001535 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1536 jint* dest = baseDest;
1537 if (dest == NULL) {
1538 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 return JNI_FALSE;
1540 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 jint* indices = NULL;
1543 int indicesIdx = 0;
1544 if (outIndices != NULL) {
1545 if (env->GetArrayLength(outIndices) > NI) {
1546 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1547 }
1548 }
1549
1550 // Now lock down the resource object and start pulling stuff from it.
1551 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001552
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 // Retrieve the XML attributes, if requested.
1554 const jsize NX = xmlParser->getAttributeCount();
1555 jsize ix=0;
1556 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001559
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560 // Now iterate through all of the attributes that the client has requested,
1561 // filling in each with whatever data we can find.
1562 ssize_t block = 0;
1563 uint32_t typeSetFlags;
1564 for (jsize ii=0; ii<NI; ii++) {
1565 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 // Try to find a value for this attribute...
1568 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001569 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001571 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001572
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001573 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001574 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 ix++;
1576 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1577 }
1578 // Retrieve the current XML attribute if it matches, and step to next.
1579 if (ix < NX && curIdent == curXmlAttr) {
1580 block = kXmlBlock;
1581 xmlParser->getAttributeValue(ix, &value);
1582 ix++;
1583 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1584 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1587 uint32_t resid = 0;
1588 if (value.dataType != Res_value::TYPE_NULL) {
1589 // Take care of resolving the found resource to its final value.
1590 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001591 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1592 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001593 if (kThrowOnBadId) {
1594 if (newBlock == BAD_INDEX) {
1595 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1596 return JNI_FALSE;
1597 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001598 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 if (newBlock >= 0) block = newBlock;
1600 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001602 // Deal with the special @null value -- it turns back to TYPE_NULL.
1603 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1604 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001605 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001608 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 // Write the final value back to Java.
1611 dest[STYLE_TYPE] = value.dataType;
1612 dest[STYLE_DATA] = value.data;
1613 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001614 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615 dest[STYLE_RESOURCE_ID] = resid;
1616 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001617 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1620 indicesIdx++;
1621 indices[indicesIdx] = ii;
1622 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001623
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001624 dest += STYLE_NUM_ENTRIES;
1625 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001627 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 if (indices != NULL) {
1630 indices[0] = indicesIdx;
1631 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1632 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1635 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001636
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 return JNI_TRUE;
1638}
1639
1640static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1641 jint id)
1642{
1643 AssetManager* am = assetManagerForJavaObject(env, clazz);
1644 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001645 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 }
1647 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 res.lock();
1650 const ResTable::bag_entry* defStyleEnt = NULL;
1651 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1652 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001653
Ashok Bhat896043d2014-01-17 16:02:38 +00001654 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001655}
1656
1657static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1658 jint id,
1659 jintArray outValues)
1660{
1661 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001662 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001663 return JNI_FALSE;
1664 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001666 AssetManager* am = assetManagerForJavaObject(env, clazz);
1667 if (am == NULL) {
1668 return JNI_FALSE;
1669 }
1670 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001671 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672 Res_value value;
1673 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001676
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001677 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1678 jint* dest = baseDest;
1679 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001680 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001681 return JNI_FALSE;
1682 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684 // Now lock down the resource object and start pulling stuff from it.
1685 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001686
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 const ResTable::bag_entry* arrayEnt = NULL;
1688 uint32_t arrayTypeSetFlags = 0;
1689 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1690 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1691 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 int i = 0;
1694 uint32_t typeSetFlags;
1695 while (i < NV && arrayEnt < endArrayEnt) {
1696 block = arrayEnt->stringBlock;
1697 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001698 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 uint32_t resid = 0;
1702 if (value.dataType != Res_value::TYPE_NULL) {
1703 // Take care of resolving the found resource to its final value.
1704 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001705 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1706 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001707 if (kThrowOnBadId) {
1708 if (newBlock == BAD_INDEX) {
1709 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1710 return JNI_FALSE;
1711 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 if (newBlock >= 0) block = newBlock;
1714 }
1715
1716 // Deal with the special @null value -- it turns back to TYPE_NULL.
1717 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1718 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001719 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 }
1721
1722 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1723
1724 // Write the final value back to Java.
1725 dest[STYLE_TYPE] = value.dataType;
1726 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001727 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728 dest[STYLE_RESOURCE_ID] = resid;
1729 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001730 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 dest += STYLE_NUM_ENTRIES;
1732 i+= STYLE_NUM_ENTRIES;
1733 arrayEnt++;
1734 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001740 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001742 return i;
1743}
1744
Ashok Bhat896043d2014-01-17 16:02:38 +00001745static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001746 jint cookie,
1747 jstring fileName)
1748{
1749 AssetManager* am = assetManagerForJavaObject(env, clazz);
1750 if (am == NULL) {
1751 return 0;
1752 }
1753
Steve Block71f2cf12011-10-20 11:56:00 +01001754 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001755
Elliott Hughes69a017b2011-04-08 14:10:28 -07001756 ScopedUtfChars fileName8(env, fileName);
1757 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001758 return 0;
1759 }
1760
Adam Lesinskide898ff2014-01-29 18:20:45 -08001761 int32_t assetCookie = static_cast<int32_t>(cookie);
1762 Asset* a = assetCookie
1763 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1764 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765
1766 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001767 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 return 0;
1769 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770
Adam Lesinskide898ff2014-01-29 18:20:45 -08001771 const DynamicRefTable* dynamicRefTable =
1772 am->getResources().getDynamicRefTableForCookie(assetCookie);
1773 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1775 a->close();
1776 delete a;
1777
1778 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001779 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 return 0;
1781 }
1782
Ashok Bhat896043d2014-01-17 16:02:38 +00001783 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784}
1785
1786static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1787 jint arrayResId)
1788{
1789 AssetManager* am = assetManagerForJavaObject(env, clazz);
1790 if (am == NULL) {
1791 return NULL;
1792 }
1793 const ResTable& res(am->getResources());
1794
1795 const ResTable::bag_entry* startOfBag;
1796 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1797 if (N < 0) {
1798 return NULL;
1799 }
1800
1801 jintArray array = env->NewIntArray(N * 2);
1802 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001803 res.unlockBag(startOfBag);
1804 return NULL;
1805 }
1806
1807 Res_value value;
1808 const ResTable::bag_entry* bag = startOfBag;
1809 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1810 jint stringIndex = -1;
1811 jint stringBlock = 0;
1812 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 // Take care of resolving the found resource to its final value.
1815 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1816 if (value.dataType == Res_value::TYPE_STRING) {
1817 stringIndex = value.data;
1818 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001819
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001820 if (kThrowOnBadId) {
1821 if (stringBlock == BAD_INDEX) {
1822 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1823 return array;
1824 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001825 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001827 //todo: It might be faster to allocate a C array to contain
1828 // the blocknums and indices, put them in there and then
1829 // do just one SetIntArrayRegion()
1830 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1831 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1832 j = j + 2;
1833 }
1834 res.unlockBag(startOfBag);
1835 return array;
1836}
1837
1838static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1839 jint arrayResId)
1840{
1841 AssetManager* am = assetManagerForJavaObject(env, clazz);
1842 if (am == NULL) {
1843 return NULL;
1844 }
1845 const ResTable& res(am->getResources());
1846
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 const ResTable::bag_entry* startOfBag;
1848 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1849 if (N < 0) {
1850 return NULL;
1851 }
1852
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001853 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001854 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001855 res.unlockBag(startOfBag);
1856 return NULL;
1857 }
1858
1859 Res_value value;
1860 const ResTable::bag_entry* bag = startOfBag;
1861 size_t strLen = 0;
1862 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1863 value = bag->map.value;
1864 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001866 // Take care of resolving the found resource to its final value.
1867 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001868 if (kThrowOnBadId) {
1869 if (block == BAD_INDEX) {
1870 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1871 return array;
1872 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001873 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001874 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001875 const ResStringPool* pool = res.getTableStringBlock(block);
1876 const char* str8 = pool->string8At(value.data, &strLen);
1877 if (str8 != NULL) {
1878 str = env->NewStringUTF(str8);
1879 } else {
1880 const char16_t* str16 = pool->stringAt(value.data, &strLen);
Dan Albert66987492014-11-20 11:41:21 -08001881 str = env->NewString(reinterpret_cast<const jchar*>(str16),
1882 strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001883 }
1884
1885 // If one of our NewString{UTF} calls failed due to memory, an
1886 // exception will be pending.
1887 if (env->ExceptionCheck()) {
1888 res.unlockBag(startOfBag);
1889 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001890 }
Kenny Root780d2a12010-02-22 22:36:26 -08001891
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001892 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001893
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001894 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1895 // If we have a large amount of strings in our array, we might
1896 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001897 env->DeleteLocalRef(str);
1898 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001899 }
1900 res.unlockBag(startOfBag);
1901 return array;
1902}
1903
1904static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1905 jint arrayResId)
1906{
1907 AssetManager* am = assetManagerForJavaObject(env, clazz);
1908 if (am == NULL) {
1909 return NULL;
1910 }
1911 const ResTable& res(am->getResources());
1912
1913 const ResTable::bag_entry* startOfBag;
1914 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1915 if (N < 0) {
1916 return NULL;
1917 }
1918
1919 jintArray array = env->NewIntArray(N);
1920 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001921 res.unlockBag(startOfBag);
1922 return NULL;
1923 }
1924
1925 Res_value value;
1926 const ResTable::bag_entry* bag = startOfBag;
1927 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1928 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 // Take care of resolving the found resource to its final value.
1931 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001932 if (kThrowOnBadId) {
1933 if (block == BAD_INDEX) {
1934 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1935 return array;
1936 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001937 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001938 if (value.dataType >= Res_value::TYPE_FIRST_INT
1939 && value.dataType <= Res_value::TYPE_LAST_INT) {
1940 int intVal = value.data;
1941 env->SetIntArrayRegion(array, i, 1, &intVal);
1942 }
1943 }
1944 res.unlockBag(startOfBag);
1945 return array;
1946}
1947
Jon Miranda042ad632014-09-03 17:57:35 -07001948static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
1949 jint styleId)
1950{
1951 AssetManager* am = assetManagerForJavaObject(env, clazz);
1952 if (am == NULL) {
1953 return NULL;
1954 }
1955 const ResTable& res(am->getResources());
1956
1957 const ResTable::bag_entry* startOfBag;
1958 const ssize_t N = res.lockBag(styleId, &startOfBag);
1959 if (N < 0) {
1960 return NULL;
1961 }
1962
1963 jintArray array = env->NewIntArray(N);
1964 if (array == NULL) {
1965 res.unlockBag(startOfBag);
1966 return NULL;
1967 }
1968
Jon Miranda042ad632014-09-03 17:57:35 -07001969 const ResTable::bag_entry* bag = startOfBag;
1970 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1971 int resourceId = bag->map.name.ident;
1972 env->SetIntArrayRegion(array, i, 1, &resourceId);
1973 }
1974 res.unlockBag(startOfBag);
1975 return array;
1976}
1977
Mårten Kongstad48d22322014-01-31 14:43:27 +01001978static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001979{
Mårten Kongstad48d22322014-01-31 14:43:27 +01001980 if (isSystem) {
1981 verifySystemIdmaps();
1982 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001983 AssetManager* am = new AssetManager();
1984 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001985 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001986 return;
1987 }
1988
1989 am->addDefaultAssets();
1990
Steve Block71f2cf12011-10-20 11:56:00 +01001991 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00001992 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001993}
1994
1995static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
1996{
1997 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00001998 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01001999 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002000 if (am != NULL) {
2001 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00002002 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002003 }
2004}
2005
2006static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
2007{
2008 return Asset::getGlobalCount();
2009}
2010
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002011static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
2012{
2013 String8 alloc = Asset::getAssetAllocations();
2014 if (alloc.length() <= 0) {
2015 return NULL;
2016 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07002017
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002018 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002019 return str;
2020}
2021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002022static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
2023{
2024 return AssetManager::getGlobalCount();
2025}
2026
2027// ----------------------------------------------------------------------------
2028
2029/*
2030 * JNI registration.
2031 */
2032static JNINativeMethod gAssetManagerMethods[] = {
2033 /* name, signature, funcPtr */
2034
2035 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00002036 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002037 (void*) android_content_AssetManager_openAsset },
2038 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2039 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00002040 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002041 (void*) android_content_AssetManager_openNonAssetNative },
2042 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2043 (void*) android_content_AssetManager_openNonAssetFdNative },
2044 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
2045 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00002046 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002047 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002048 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002049 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00002050 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002051 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002052 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002053 (void*) android_content_AssetManager_seekAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002054 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055 (void*) android_content_AssetManager_getAssetLength },
Ashok Bhat896043d2014-01-17 16:02:38 +00002056 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002057 (void*) android_content_AssetManager_getAssetRemainingLength },
Dianne Hackbornf7be4802013-04-12 14:52:58 -07002058 { "addAssetPathNative", "(Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002059 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad48d22322014-01-31 14:43:27 +01002060 { "addOverlayPath", "(Ljava/lang/String;)I",
2061 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002062 { "isUpToDate", "()Z",
2063 (void*) android_content_AssetManager_isUpToDate },
2064
2065 // Resources.
2066 { "setLocale", "(Ljava/lang/String;)V",
2067 (void*) android_content_AssetManager_setLocale },
2068 { "getLocales", "()[Ljava/lang/String;",
2069 (void*) android_content_AssetManager_getLocales },
Dianne Hackborn69cb8752011-05-19 18:13:32 -07002070 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002071 (void*) android_content_AssetManager_setConfiguration },
2072 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
2073 (void*) android_content_AssetManager_getResourceIdentifier },
2074 { "getResourceName","(I)Ljava/lang/String;",
2075 (void*) android_content_AssetManager_getResourceName },
2076 { "getResourcePackageName","(I)Ljava/lang/String;",
2077 (void*) android_content_AssetManager_getResourcePackageName },
2078 { "getResourceTypeName","(I)Ljava/lang/String;",
2079 (void*) android_content_AssetManager_getResourceTypeName },
2080 { "getResourceEntryName","(I)Ljava/lang/String;",
2081 (void*) android_content_AssetManager_getResourceEntryName },
Kenny Root55fc8502010-10-28 14:47:01 -07002082 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002083 (void*) android_content_AssetManager_loadResourceValue },
2084 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
2085 (void*) android_content_AssetManager_loadResourceBagValue },
2086 { "getStringBlockCount","()I",
2087 (void*) android_content_AssetManager_getStringBlockCount },
Ashok Bhat896043d2014-01-17 16:02:38 +00002088 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002089 (void*) android_content_AssetManager_getNativeStringBlock },
2090 { "getCookieName","(I)Ljava/lang/String;",
2091 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002092 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2093 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002094
2095 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002096 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002097 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002098 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002099 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002100 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002101 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002102 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002103 (void*) android_content_AssetManager_copyTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002104 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002105 (void*) android_content_AssetManager_loadThemeAttributeValue },
Ashok Bhat896043d2014-01-17 16:02:38 +00002106 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002107 (void*) android_content_AssetManager_dumpTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002108 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109 (void*) android_content_AssetManager_applyStyle },
Alan Viverette607bd842014-09-12 12:36:35 -07002110 { "resolveAttrs","(JII[I[I[I[I)Z",
2111 (void*) android_content_AssetManager_resolveAttrs },
Ashok Bhat896043d2014-01-17 16:02:38 +00002112 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002113 (void*) android_content_AssetManager_retrieveAttributes },
2114 { "getArraySize","(I)I",
2115 (void*) android_content_AssetManager_getArraySize },
2116 { "retrieveArray","(I[I)I",
2117 (void*) android_content_AssetManager_retrieveArray },
2118
2119 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002120 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002121 (void*) android_content_AssetManager_openXmlAssetNative },
2122
2123 // Arrays.
2124 { "getArrayStringResource","(I)[Ljava/lang/String;",
2125 (void*) android_content_AssetManager_getArrayStringResource },
2126 { "getArrayStringInfo","(I)[I",
2127 (void*) android_content_AssetManager_getArrayStringInfo },
2128 { "getArrayIntResource","(I)[I",
2129 (void*) android_content_AssetManager_getArrayIntResource },
Jon Miranda042ad632014-09-03 17:57:35 -07002130 { "getStyleAttributes","(I)[I",
2131 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002132
2133 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002134 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002135 (void*) android_content_AssetManager_init },
2136 { "destroy", "()V",
2137 (void*) android_content_AssetManager_destroy },
2138 { "getGlobalAssetCount", "()I",
2139 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002140 { "getAssetAllocations", "()Ljava/lang/String;",
2141 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142 { "getGlobalAssetManagerCount", "()I",
Andreas Gampe32812612014-11-11 00:16:00 -08002143 (void*) android_content_AssetManager_getGlobalAssetManagerCount },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002144};
2145
2146int register_android_content_AssetManager(JNIEnv* env)
2147{
Andreas Gampe987f79f2014-11-18 17:29:46 -08002148 jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
2149 gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
2150 gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
2151 gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
2152 "Ljava/lang/CharSequence;");
2153 gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
2154 gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
2155 gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
2156 "changingConfigurations", "I");
2157 gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002158
Andreas Gampe987f79f2014-11-18 17:29:46 -08002159 jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
2160 gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
2161 "Landroid/os/ParcelFileDescriptor;");
2162 gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
2163 gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002164
Andreas Gampe987f79f2014-11-18 17:29:46 -08002165 jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
2166 gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002167
Andreas Gampe987f79f2014-11-18 17:29:46 -08002168 jclass stringClass = FindClassOrDie(env, "java/lang/String");
2169 g_stringClass = MakeGlobalRefOrDie(env, stringClass);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002170
Andreas Gampe987f79f2014-11-18 17:29:46 -08002171 jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
2172 gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
2173 gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
2174 "<init>", "()V");
2175 gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
2176 "(ILjava/lang/Object;)V");
Adam Lesinskide898ff2014-01-29 18:20:45 -08002177
Andreas Gampe987f79f2014-11-18 17:29:46 -08002178 return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
2179 NELEM(gAssetManagerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002180}
2181
2182}; // namespace android