blob: 7162a1c721ce96a6f391fa202727a4e63dcba5f7 [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
Dianne Hackbornb8d81672009-11-20 14:26:42 -080020#define DEBUG_STYLES(x) //x
Dianne Hackborn20cb56e2010-03-04 00:58:29 -080021#define THROW_ON_BAD_ID 0
Dianne Hackbornb8d81672009-11-20 14:26:42 -080022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023#include <android_runtime/android_util_AssetManager.h>
24
25#include "jni.h"
26#include "JNIHelp.h"
Elliott Hughes69a017b2011-04-08 14:10:28 -070027#include "ScopedStringChars.h"
28#include "ScopedUtfChars.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029#include "android_util_Binder.h"
30#include <utils/misc.h>
31#include <android_runtime/AndroidRuntime.h>
32#include <utils/Log.h>
33
Mathias Agopianb13b9bd2012-02-17 18:27:36 -080034#include <androidfw/Asset.h>
35#include <androidfw/AssetManager.h>
36#include <androidfw/ResourceTypes.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037
Mårten Kongstad48d22322014-01-31 14:43:27 +010038#include <private/android_filesystem_config.h> // for AID_SYSTEM
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
51// ----------------------------------------------------------------------------
52
53static struct typedvalue_offsets_t
54{
55 jfieldID mType;
56 jfieldID mData;
57 jfieldID mString;
58 jfieldID mAssetCookie;
59 jfieldID mResourceId;
60 jfieldID mChangingConfigurations;
61 jfieldID mDensity;
62} gTypedValueOffsets;
63
64static struct assetfiledescriptor_offsets_t
65{
66 jfieldID mFd;
67 jfieldID mStartOffset;
68 jfieldID mLength;
69} gAssetFileDescriptorOffsets;
70
71static struct assetmanager_offsets_t
72{
73 jfieldID mObject;
74} gAssetManagerOffsets;
75
76jclass g_stringClass = NULL;
77
78// ----------------------------------------------------------------------------
79
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080enum {
Dianne Hackborn0d221012009-07-29 15:41:19 -070081 STYLE_NUM_ENTRIES = 6,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082 STYLE_TYPE = 0,
83 STYLE_DATA = 1,
84 STYLE_ASSET_COOKIE = 2,
85 STYLE_RESOURCE_ID = 3,
Dianne Hackborn0d221012009-07-29 15:41:19 -070086 STYLE_CHANGING_CONFIGURATIONS = 4,
87 STYLE_DENSITY = 5
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088};
89
90static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
91 const Res_value& value, uint32_t ref, ssize_t block,
92 uint32_t typeSpecFlags, ResTable_config* config = NULL);
93
94jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
95 const Res_value& value, uint32_t ref, ssize_t block,
96 uint32_t typeSpecFlags, ResTable_config* config)
97{
98 env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
99 env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
Ashok Bhat896043d2014-01-17 16:02:38 +0000100 static_cast<jint>(table->getTableCookie(block)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
102 env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
103 env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
104 env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
105 typeSpecFlags);
106 if (config != NULL) {
107 env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
108 }
109 return block;
110}
111
Mårten Kongstad48d22322014-01-31 14:43:27 +0100112// This is called by zygote (running as user root) as part of preloadResources.
113static void verifySystemIdmaps()
114{
115 pid_t pid;
116 char system_id[10];
117
118 snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
119
120 switch (pid = fork()) {
121 case -1:
122 ALOGE("failed to fork for idmap: %s", strerror(errno));
123 break;
124 case 0: // child
125 {
126 struct __user_cap_header_struct capheader;
127 struct __user_cap_data_struct capdata;
128
129 memset(&capheader, 0, sizeof(capheader));
130 memset(&capdata, 0, sizeof(capdata));
131
132 capheader.version = _LINUX_CAPABILITY_VERSION;
133 capheader.pid = 0;
134
135 if (capget(&capheader, &capdata) != 0) {
136 ALOGE("capget: %s\n", strerror(errno));
137 exit(1);
138 }
139
140 capdata.effective = capdata.permitted;
141 if (capset(&capheader, &capdata) != 0) {
142 ALOGE("capset: %s\n", strerror(errno));
143 exit(1);
144 }
145
146 if (setgid(AID_SYSTEM) != 0) {
147 ALOGE("setgid: %s\n", strerror(errno));
148 exit(1);
149 }
150
151 if (setuid(AID_SYSTEM) != 0) {
152 ALOGE("setuid: %s\n", strerror(errno));
153 exit(1);
154 }
155
156 execl(AssetManager::IDMAP_BIN, AssetManager::IDMAP_BIN, "--scan",
157 AssetManager::OVERLAY_DIR, AssetManager::TARGET_PACKAGE_NAME,
158 AssetManager::TARGET_APK_PATH, AssetManager::IDMAP_DIR, (char*)NULL);
159 ALOGE("failed to execl for idmap: %s", strerror(errno));
160 exit(1); // should never get here
161 }
162 break;
163 default: // parent
164 waitpid(pid, NULL, 0);
165 break;
166 }
167}
168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169// ----------------------------------------------------------------------------
170
171// this guy is exported to other jni routines
172AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
173{
Ashok Bhat896043d2014-01-17 16:02:38 +0000174 jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
175 AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176 if (am != NULL) {
177 return am;
178 }
179 jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
180 return NULL;
181}
182
Ashok Bhat896043d2014-01-17 16:02:38 +0000183static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 jstring fileName, jint mode)
185{
186 AssetManager* am = assetManagerForJavaObject(env, clazz);
187 if (am == NULL) {
188 return 0;
189 }
190
Steve Block71f2cf12011-10-20 11:56:00 +0100191 ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192
Elliott Hughes69a017b2011-04-08 14:10:28 -0700193 ScopedUtfChars fileName8(env, fileName);
194 if (fileName8.c_str() == NULL) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000195 jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 return -1;
197 }
198
199 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
200 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700201 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 return -1;
203 }
204
Elliott Hughes69a017b2011-04-08 14:10:28 -0700205 Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206
207 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700208 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 return -1;
210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211
212 //printf("Created Asset Stream: %p\n", a);
213
Ashok Bhat896043d2014-01-17 16:02:38 +0000214 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215}
216
217static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
218{
Kenny Rootddb76c42010-11-24 12:56:06 -0800219 off64_t startOffset, length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 int fd = a->openFileDescriptor(&startOffset, &length);
221 delete a;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 if (fd < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700224 jniThrowException(env, "java/io/FileNotFoundException",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 "This file can not be opened as a file descriptor; it is probably compressed");
226 return NULL;
227 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
230 if (offsets == NULL) {
231 close(fd);
232 return NULL;
233 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700234
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 offsets[0] = startOffset;
236 offsets[1] = length;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700239
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700240 jobject fileDesc = jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 if (fileDesc == NULL) {
242 close(fd);
243 return NULL;
244 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 return newParcelFileDescriptor(env, fileDesc);
247}
248
249static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
250 jstring fileName, jlongArray outOffsets)
251{
252 AssetManager* am = assetManagerForJavaObject(env, clazz);
253 if (am == NULL) {
254 return NULL;
255 }
256
Steve Block71f2cf12011-10-20 11:56:00 +0100257 ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258
Elliott Hughes69a017b2011-04-08 14:10:28 -0700259 ScopedUtfChars fileName8(env, fileName);
260 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261 return NULL;
262 }
263
Elliott Hughes69a017b2011-04-08 14:10:28 -0700264 Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265
266 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700267 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 return NULL;
269 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270
271 //printf("Created Asset Stream: %p\n", a);
272
273 return returnParcelFileDescriptor(env, a, outOffsets);
274}
275
Ashok Bhat896043d2014-01-17 16:02:38 +0000276static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 jint cookie,
278 jstring fileName,
279 jint mode)
280{
281 AssetManager* am = assetManagerForJavaObject(env, clazz);
282 if (am == NULL) {
283 return 0;
284 }
285
Steve Block71f2cf12011-10-20 11:56:00 +0100286 ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287
Elliott Hughes69a017b2011-04-08 14:10:28 -0700288 ScopedUtfChars fileName8(env, fileName);
289 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 return -1;
291 }
292
293 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
294 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700295 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296 return -1;
297 }
298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000300 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
301 (Asset::AccessMode)mode)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700302 : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303
304 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700305 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 return -1;
307 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308
309 //printf("Created Asset Stream: %p\n", a);
310
Ashok Bhat896043d2014-01-17 16:02:38 +0000311 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312}
313
314static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
315 jint cookie,
316 jstring fileName,
317 jlongArray outOffsets)
318{
319 AssetManager* am = assetManagerForJavaObject(env, clazz);
320 if (am == NULL) {
321 return NULL;
322 }
323
Steve Block71f2cf12011-10-20 11:56:00 +0100324 ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325
Elliott Hughes69a017b2011-04-08 14:10:28 -0700326 ScopedUtfChars fileName8(env, fileName);
327 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 return NULL;
329 }
330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800331 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000332 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700333 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334
335 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700336 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337 return NULL;
338 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339
340 //printf("Created Asset Stream: %p\n", a);
341
342 return returnParcelFileDescriptor(env, a, outOffsets);
343}
344
345static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
346 jstring fileName)
347{
348 AssetManager* am = assetManagerForJavaObject(env, clazz);
349 if (am == NULL) {
350 return NULL;
351 }
352
Elliott Hughes69a017b2011-04-08 14:10:28 -0700353 ScopedUtfChars fileName8(env, fileName);
354 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 return NULL;
356 }
357
Elliott Hughes69a017b2011-04-08 14:10:28 -0700358 AssetDir* dir = am->openDir(fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359
360 if (dir == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700361 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800362 return NULL;
363 }
364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365 size_t N = dir->getFileCount();
366
367 jobjectArray array = env->NewObjectArray(dir->getFileCount(),
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +0100368 g_stringClass, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 delete dir;
371 return NULL;
372 }
373
374 for (size_t i=0; i<N; i++) {
375 const String8& name = dir->getFileName(i);
376 jstring str = env->NewStringUTF(name.string());
377 if (str == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 delete dir;
379 return NULL;
380 }
381 env->SetObjectArrayElement(array, i, str);
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700382 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 }
384
385 delete dir;
386
387 return array;
388}
389
390static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000391 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392{
Ashok Bhat896043d2014-01-17 16:02:38 +0000393 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394
395 //printf("Destroying Asset Stream: %p\n", a);
396
397 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700398 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800399 return;
400 }
401
402 delete a;
403}
404
405static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000406 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407{
Ashok Bhat896043d2014-01-17 16:02:38 +0000408 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409
410 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700411 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800412 return -1;
413 }
414
415 uint8_t b;
416 ssize_t res = a->read(&b, 1);
417 return res == 1 ? b : -1;
418}
419
420static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000421 jlong assetHandle, jbyteArray bArray,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 jint off, jint len)
423{
Ashok Bhat896043d2014-01-17 16:02:38 +0000424 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425
426 if (a == NULL || bArray == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700427 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 return -1;
429 }
430
431 if (len == 0) {
432 return 0;
433 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 jsize bLen = env->GetArrayLength(bArray);
436 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700437 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 return -1;
439 }
440
441 jbyte* b = env->GetByteArrayElements(bArray, NULL);
442 ssize_t res = a->read(b+off, len);
443 env->ReleaseByteArrayElements(bArray, b, 0);
444
Ashok Bhat896043d2014-01-17 16:02:38 +0000445 if (res > 0) return static_cast<jint>(res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446
447 if (res < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700448 jniThrowException(env, "java/io/IOException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 }
450 return -1;
451}
452
453static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000454 jlong assetHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800455 jlong offset, jint whence)
456{
Ashok Bhat896043d2014-01-17 16:02:38 +0000457 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458
459 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700460 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 return -1;
462 }
463
464 return a->seek(
465 offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
466}
467
468static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000469 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470{
Ashok Bhat896043d2014-01-17 16:02:38 +0000471 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800472
473 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700474 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475 return -1;
476 }
477
478 return a->getLength();
479}
480
481static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000482 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800483{
Ashok Bhat896043d2014-01-17 16:02:38 +0000484 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800485
486 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700487 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800488 return -1;
489 }
490
491 return a->getRemainingLength();
492}
493
494static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
495 jstring path)
496{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700497 ScopedUtfChars path8(env, path);
498 if (path8.c_str() == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800499 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500 }
501
502 AssetManager* am = assetManagerForJavaObject(env, clazz);
503 if (am == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800504 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800505 }
506
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000507 int32_t cookie;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700508 bool res = am->addAssetPath(String8(path8.c_str()), &cookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800509
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000510 return (res) ? static_cast<jint>(cookie) : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800511}
512
Mårten Kongstad48d22322014-01-31 14:43:27 +0100513static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
514 jstring idmapPath)
515{
516 ScopedUtfChars idmapPath8(env, idmapPath);
517 if (idmapPath8.c_str() == NULL) {
518 return 0;
519 }
520
521 AssetManager* am = assetManagerForJavaObject(env, clazz);
522 if (am == NULL) {
523 return 0;
524 }
525
526 int32_t cookie;
527 bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
528
529 return (res) ? (jint)cookie : 0;
530}
531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
533{
534 AssetManager* am = assetManagerForJavaObject(env, clazz);
535 if (am == NULL) {
536 return JNI_TRUE;
537 }
538 return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
539}
540
541static void android_content_AssetManager_setLocale(JNIEnv* env, jobject clazz,
542 jstring locale)
543{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700544 ScopedUtfChars locale8(env, locale);
545 if (locale8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 return;
547 }
548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 AssetManager* am = assetManagerForJavaObject(env, clazz);
550 if (am == NULL) {
551 return;
552 }
553
Elliott Hughes69a017b2011-04-08 14:10:28 -0700554 am->setLocale(locale8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555}
556
557static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
558{
559 Vector<String8> locales;
560
561 AssetManager* am = assetManagerForJavaObject(env, clazz);
562 if (am == NULL) {
563 return NULL;
564 }
565
566 am->getLocales(&locales);
567
568 const int N = locales.size();
569
570 jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
571 if (result == NULL) {
572 return NULL;
573 }
574
575 for (int i=0; i<N; i++) {
Gilles Debunne0db187a2010-08-27 11:51:34 -0700576 jstring str = env->NewStringUTF(locales[i].string());
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700577 if (str == NULL) {
578 return NULL;
579 }
580 env->SetObjectArrayElement(result, i, str);
581 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 }
583
584 return result;
585}
586
587static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
588 jint mcc, jint mnc,
589 jstring locale, jint orientation,
590 jint touchscreen, jint density,
591 jint keyboard, jint keyboardHidden,
592 jint navigation,
593 jint screenWidth, jint screenHeight,
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700594 jint smallestScreenWidthDp,
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700595 jint screenWidthDp, jint screenHeightDp,
Tobias Haamel27b28b32010-02-09 23:09:17 +0100596 jint screenLayout, jint uiMode,
597 jint sdkVersion)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800598{
599 AssetManager* am = assetManagerForJavaObject(env, clazz);
600 if (am == NULL) {
601 return;
602 }
603
604 ResTable_config config;
605 memset(&config, 0, sizeof(config));
Elliott Hughes69a017b2011-04-08 14:10:28 -0700606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800607 const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700608
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800609 config.mcc = (uint16_t)mcc;
610 config.mnc = (uint16_t)mnc;
611 config.orientation = (uint8_t)orientation;
612 config.touchscreen = (uint8_t)touchscreen;
613 config.density = (uint16_t)density;
614 config.keyboard = (uint8_t)keyboard;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700615 config.inputFlags = (uint8_t)keyboardHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 config.navigation = (uint8_t)navigation;
617 config.screenWidth = (uint16_t)screenWidth;
618 config.screenHeight = (uint16_t)screenHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700619 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700620 config.screenWidthDp = (uint16_t)screenWidthDp;
621 config.screenHeightDp = (uint16_t)screenHeightDp;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700622 config.screenLayout = (uint8_t)screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100623 config.uiMode = (uint8_t)uiMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624 config.sdkVersion = (uint16_t)sdkVersion;
625 config.minorVersion = 0;
626 am->setConfiguration(config, locale8);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800628 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
629}
630
631static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
632 jstring name,
633 jstring defType,
634 jstring defPackage)
635{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700636 ScopedStringChars name16(env, name);
637 if (name16.get() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800638 return 0;
639 }
640
641 AssetManager* am = assetManagerForJavaObject(env, clazz);
642 if (am == NULL) {
643 return 0;
644 }
645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 const char16_t* defType16 = defType
647 ? env->GetStringChars(defType, NULL) : NULL;
648 jsize defTypeLen = defType
649 ? env->GetStringLength(defType) : 0;
650 const char16_t* defPackage16 = defPackage
651 ? env->GetStringChars(defPackage, NULL) : NULL;
652 jsize defPackageLen = defPackage
653 ? env->GetStringLength(defPackage) : 0;
654
655 jint ident = am->getResources().identifierForName(
Elliott Hughes69a017b2011-04-08 14:10:28 -0700656 name16.get(), name16.size(), defType16, defTypeLen, defPackage16, defPackageLen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800657
658 if (defPackage16) {
659 env->ReleaseStringChars(defPackage, defPackage16);
660 }
661 if (defType16) {
662 env->ReleaseStringChars(defType, defType16);
663 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664
665 return ident;
666}
667
668static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
669 jint resid)
670{
671 AssetManager* am = assetManagerForJavaObject(env, clazz);
672 if (am == NULL) {
673 return NULL;
674 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700677 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678 return NULL;
679 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 String16 str;
682 if (name.package != NULL) {
683 str.setTo(name.package, name.packageLen);
684 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700685 if (name.type8 != NULL || name.type != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800686 if (str.size() > 0) {
687 char16_t div = ':';
688 str.append(&div, 1);
689 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700690 if (name.type8 != NULL) {
691 str.append(String16(name.type8, name.typeLen));
692 } else {
693 str.append(name.type, name.typeLen);
694 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800695 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700696 if (name.name8 != NULL || name.name != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800697 if (str.size() > 0) {
698 char16_t div = '/';
699 str.append(&div, 1);
700 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700701 if (name.name8 != NULL) {
702 str.append(String16(name.name8, name.nameLen));
703 } else {
704 str.append(name.name, name.nameLen);
705 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708 return env->NewString((const jchar*)str.string(), str.size());
709}
710
711static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
712 jint resid)
713{
714 AssetManager* am = assetManagerForJavaObject(env, clazz);
715 if (am == NULL) {
716 return NULL;
717 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700718
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700720 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800721 return NULL;
722 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800724 if (name.package != NULL) {
725 return env->NewString((const jchar*)name.package, name.packageLen);
726 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700727
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800728 return NULL;
729}
730
731static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
732 jint resid)
733{
734 AssetManager* am = assetManagerForJavaObject(env, clazz);
735 if (am == NULL) {
736 return NULL;
737 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800739 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700740 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800741 return NULL;
742 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700743
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700744 if (name.type8 != NULL) {
745 return env->NewStringUTF(name.type8);
746 }
747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748 if (name.type != NULL) {
749 return env->NewString((const jchar*)name.type, name.typeLen);
750 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752 return NULL;
753}
754
755static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
756 jint resid)
757{
758 AssetManager* am = assetManagerForJavaObject(env, clazz);
759 if (am == NULL) {
760 return NULL;
761 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700764 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765 return NULL;
766 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700767
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700768 if (name.name8 != NULL) {
769 return env->NewStringUTF(name.name8);
770 }
771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 if (name.name != NULL) {
773 return env->NewString((const jchar*)name.name, name.nameLen);
774 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 return NULL;
777}
778
779static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
780 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700781 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 jobject outValue,
783 jboolean resolve)
784{
Dianne Hackborn1f7d3072013-02-11 17:03:32 -0800785 if (outValue == NULL) {
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800786 jniThrowNullPointerException(env, "outValue");
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700787 return 0;
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800788 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789 AssetManager* am = assetManagerForJavaObject(env, clazz);
790 if (am == NULL) {
791 return 0;
792 }
793 const ResTable& res(am->getResources());
794
795 Res_value value;
796 ResTable_config config;
797 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700798 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800799#if THROW_ON_BAD_ID
800 if (block == BAD_INDEX) {
801 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
802 return 0;
803 }
804#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 uint32_t ref = ident;
806 if (resolve) {
Dianne Hackbornfb5c3db2012-05-18 15:24:24 -0700807 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800808#if THROW_ON_BAD_ID
809 if (block == BAD_INDEX) {
810 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
811 return 0;
812 }
813#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800814 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000815 if (block >= 0) {
816 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
817 }
818
819 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800820}
821
822static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
823 jint ident, jint bagEntryId,
824 jobject outValue, jboolean resolve)
825{
826 AssetManager* am = assetManagerForJavaObject(env, clazz);
827 if (am == NULL) {
828 return 0;
829 }
830 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832 // Now lock down the resource object and start pulling stuff from it.
833 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -0700834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800835 ssize_t block = -1;
836 Res_value value;
837
838 const ResTable::bag_entry* entry = NULL;
839 uint32_t typeSpecFlags;
840 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
841
842 for (ssize_t i=0; i<entryCount; i++) {
843 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
844 block = entry->stringBlock;
845 value = entry->map.value;
846 }
847 entry++;
848 }
849
850 res.unlock();
851
852 if (block < 0) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000853 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800854 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700855
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856 uint32_t ref = ident;
857 if (resolve) {
858 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800859#if THROW_ON_BAD_ID
860 if (block == BAD_INDEX) {
861 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
862 return 0;
863 }
864#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000866 if (block >= 0) {
867 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
868 }
869
870 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800871}
872
873static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
874{
875 AssetManager* am = assetManagerForJavaObject(env, clazz);
876 if (am == NULL) {
877 return 0;
878 }
879 return am->getResources().getTableCount();
880}
881
Ashok Bhat896043d2014-01-17 16:02:38 +0000882static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 jint block)
884{
885 AssetManager* am = assetManagerForJavaObject(env, clazz);
886 if (am == NULL) {
887 return 0;
888 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000889 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890}
891
892static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
893 jint cookie)
894{
895 AssetManager* am = assetManagerForJavaObject(env, clazz);
896 if (am == NULL) {
897 return NULL;
898 }
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000899 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800900 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700901 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902 return NULL;
903 }
904 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800905 return str;
906}
907
Ashok Bhat896043d2014-01-17 16:02:38 +0000908static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800909{
910 AssetManager* am = assetManagerForJavaObject(env, clazz);
911 if (am == NULL) {
912 return 0;
913 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000914 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800915}
916
917static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000918 jlong themeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800919{
Ashok Bhat896043d2014-01-17 16:02:38 +0000920 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921 delete theme;
922}
923
924static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000925 jlong themeHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 jint styleRes,
927 jboolean force)
928{
Ashok Bhat896043d2014-01-17 16:02:38 +0000929 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 theme->applyStyle(styleRes, force ? true : false);
931}
932
933static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000934 jlong destHandle, jlong srcHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800935{
Ashok Bhat896043d2014-01-17 16:02:38 +0000936 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
937 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938 dest->setTo(*src);
939}
940
941static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +0000942 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800943{
Ashok Bhat896043d2014-01-17 16:02:38 +0000944 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945 const ResTable& res(theme->getResTable());
946
947 Res_value value;
948 // XXX value could be different in different configs!
949 uint32_t typeSpecFlags = 0;
950 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
951 uint32_t ref = 0;
952 if (resolve) {
953 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800954#if THROW_ON_BAD_ID
955 if (block == BAD_INDEX) {
956 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
957 return 0;
958 }
959#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800960 }
961 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
962}
963
964static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000965 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800966 jstring tag, jstring prefix)
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 const ResTable& res(theme->getResTable());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971 // XXX Need to use params.
972 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973}
974
975static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000976 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977 jint defStyleAttr,
978 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +0000979 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800980 jintArray attrs,
981 jintArray outValues,
982 jintArray outIndices)
983{
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700984 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700985 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700986 return JNI_FALSE;
987 }
988 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700989 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700990 return JNI_FALSE;
991 }
992 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700993 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 return JNI_FALSE;
995 }
996
Dianne Hackbornb8d81672009-11-20 14:26:42 -0800997 DEBUG_STYLES(LOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x xml=0x%x",
998 themeToken, defStyleAttr, defStyleRes, xmlParserToken));
Elliott Hughes69a017b2011-04-08 14:10:28 -0700999
Ashok Bhat896043d2014-01-17 16:02:38 +00001000 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001002 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001003 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 Res_value value;
1005
1006 const jsize NI = env->GetArrayLength(attrs);
1007 const jsize NV = env->GetArrayLength(outValues);
1008 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001009 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010 return JNI_FALSE;
1011 }
1012
1013 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1014 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001015 return JNI_FALSE;
1016 }
1017
1018 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1019 jint* dest = baseDest;
1020 if (dest == NULL) {
1021 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001022 return JNI_FALSE;
1023 }
1024
1025 jint* indices = NULL;
1026 int indicesIdx = 0;
1027 if (outIndices != NULL) {
1028 if (env->GetArrayLength(outIndices) > NI) {
1029 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1030 }
1031 }
1032
1033 // Load default style from attribute, if specified...
1034 uint32_t defStyleBagTypeSetFlags = 0;
1035 if (defStyleAttr != 0) {
1036 Res_value value;
1037 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1038 if (value.dataType == Res_value::TYPE_REFERENCE) {
1039 defStyleRes = value.data;
1040 }
1041 }
1042 }
1043
1044 // Retrieve the style class associated with the current XML tag.
1045 int style = 0;
1046 uint32_t styleBagTypeSetFlags = 0;
1047 if (xmlParser != NULL) {
1048 ssize_t idx = xmlParser->indexOfStyle();
1049 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1050 if (value.dataType == value.TYPE_ATTRIBUTE) {
1051 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1052 value.dataType = Res_value::TYPE_NULL;
1053 }
1054 }
1055 if (value.dataType == value.TYPE_REFERENCE) {
1056 style = value.data;
1057 }
1058 }
1059 }
1060
1061 // Now lock down the resource object and start pulling stuff from it.
1062 res.lock();
1063
1064 // Retrieve the default style bag, if requested.
1065 const ResTable::bag_entry* defStyleEnt = NULL;
1066 uint32_t defStyleTypeSetFlags = 0;
1067 ssize_t bagOff = defStyleRes != 0
1068 ? res.getBagLocked(defStyleRes, &defStyleEnt, &defStyleTypeSetFlags) : -1;
1069 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
1070 const ResTable::bag_entry* endDefStyleEnt = defStyleEnt +
1071 (bagOff >= 0 ? bagOff : 0);
1072
1073 // Retrieve the style class bag, if requested.
1074 const ResTable::bag_entry* styleEnt = NULL;
1075 uint32_t styleTypeSetFlags = 0;
1076 bagOff = style != 0 ? res.getBagLocked(style, &styleEnt, &styleTypeSetFlags) : -1;
1077 styleTypeSetFlags |= styleBagTypeSetFlags;
1078 const ResTable::bag_entry* endStyleEnt = styleEnt +
1079 (bagOff >= 0 ? bagOff : 0);
1080
1081 // Retrieve the XML attributes, if requested.
1082 const jsize NX = xmlParser ? xmlParser->getAttributeCount() : 0;
1083 jsize ix=0;
1084 uint32_t curXmlAttr = xmlParser ? xmlParser->getAttributeNameResID(ix) : 0;
1085
1086 static const ssize_t kXmlBlock = 0x10000000;
1087
1088 // Now iterate through all of the attributes that the client has requested,
1089 // filling in each with whatever data we can find.
1090 ssize_t block = 0;
1091 uint32_t typeSetFlags;
1092 for (jsize ii=0; ii<NI; ii++) {
1093 const uint32_t curIdent = (uint32_t)src[ii];
1094
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001095 DEBUG_STYLES(LOGI("RETRIEVING ATTR 0x%08x...", curIdent));
Elliott Hughes69a017b2011-04-08 14:10:28 -07001096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 // Try to find a value for this attribute... we prioritize values
1098 // coming from, first XML attributes, then XML style, then default
1099 // style, and finally the theme.
1100 value.dataType = Res_value::TYPE_NULL;
1101 value.data = 0;
1102 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001103 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104
1105 // Skip through XML attributes until the end or the next possible match.
1106 while (ix < NX && curIdent > curXmlAttr) {
1107 ix++;
1108 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1109 }
1110 // Retrieve the current XML attribute if it matches, and step to next.
1111 if (ix < NX && curIdent == curXmlAttr) {
1112 block = kXmlBlock;
1113 xmlParser->getAttributeValue(ix, &value);
1114 ix++;
1115 curXmlAttr = xmlParser->getAttributeNameResID(ix);
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001116 DEBUG_STYLES(LOGI("-> From XML: type=0x%x, data=0x%08x",
1117 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001118 }
1119
1120 // Skip through the style values until the end or the next possible match.
1121 while (styleEnt < endStyleEnt && curIdent > styleEnt->map.name.ident) {
1122 styleEnt++;
1123 }
1124 // Retrieve the current style attribute if it matches, and step to next.
1125 if (styleEnt < endStyleEnt && curIdent == styleEnt->map.name.ident) {
1126 if (value.dataType == Res_value::TYPE_NULL) {
1127 block = styleEnt->stringBlock;
1128 typeSetFlags = styleTypeSetFlags;
1129 value = styleEnt->map.value;
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001130 DEBUG_STYLES(LOGI("-> From style: type=0x%x, data=0x%08x",
1131 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001132 }
1133 styleEnt++;
1134 }
1135
1136 // Skip through the default style values until the end or the next possible match.
1137 while (defStyleEnt < endDefStyleEnt && curIdent > defStyleEnt->map.name.ident) {
1138 defStyleEnt++;
1139 }
1140 // Retrieve the current default style attribute if it matches, and step to next.
1141 if (defStyleEnt < endDefStyleEnt && curIdent == defStyleEnt->map.name.ident) {
1142 if (value.dataType == Res_value::TYPE_NULL) {
1143 block = defStyleEnt->stringBlock;
1144 typeSetFlags = defStyleTypeSetFlags;
1145 value = defStyleEnt->map.value;
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001146 DEBUG_STYLES(LOGI("-> From def style: type=0x%x, data=0x%08x",
1147 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148 }
1149 defStyleEnt++;
1150 }
1151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001152 uint32_t resid = 0;
1153 if (value.dataType != Res_value::TYPE_NULL) {
1154 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001155 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1156 &resid, &typeSetFlags, &config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001157 if (newBlock >= 0) block = newBlock;
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001158 DEBUG_STYLES(LOGI("-> Resolved attr: type=0x%x, data=0x%08x",
1159 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001160 } else {
1161 // If we still don't have a value for this attribute, try to find
1162 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1164 if (newBlock >= 0) {
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001165 DEBUG_STYLES(LOGI("-> From theme: type=0x%x, data=0x%08x",
1166 value.dataType, value.data));
Dianne Hackborn0d221012009-07-29 15:41:19 -07001167 newBlock = res.resolveReference(&value, block, &resid,
1168 &typeSetFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001169#if THROW_ON_BAD_ID
1170 if (newBlock == BAD_INDEX) {
1171 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1172 return JNI_FALSE;
1173 }
1174#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 if (newBlock >= 0) block = newBlock;
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001176 DEBUG_STYLES(LOGI("-> Resolved theme: type=0x%x, data=0x%08x",
1177 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001178 }
1179 }
1180
1181 // Deal with the special @null value -- it turns back to TYPE_NULL.
1182 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001183 DEBUG_STYLES(LOGI("-> Setting to @null!"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001184 value.dataType = Res_value::TYPE_NULL;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001185 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001186 }
1187
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001188 DEBUG_STYLES(LOGI("Attribute 0x%08x: type=0x%x, data=0x%08x",
1189 curIdent, value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190
1191 // Write the final value back to Java.
1192 dest[STYLE_TYPE] = value.dataType;
1193 dest[STYLE_DATA] = value.data;
1194 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001195 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001196 dest[STYLE_RESOURCE_ID] = resid;
1197 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001198 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001200 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1201 indicesIdx++;
1202 indices[indicesIdx] = ii;
1203 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 dest += STYLE_NUM_ENTRIES;
1206 }
1207
1208 res.unlock();
1209
1210 if (indices != NULL) {
1211 indices[0] = indicesIdx;
1212 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1213 }
1214 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1215 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1216
1217 return JNI_TRUE;
1218}
1219
1220static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001221 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001222 jintArray attrs,
1223 jintArray outValues,
1224 jintArray outIndices)
1225{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001226 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001227 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001228 return JNI_FALSE;
1229 }
1230 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001231 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001232 return JNI_FALSE;
1233 }
1234 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001235 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001236 return JNI_FALSE;
1237 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001239 AssetManager* am = assetManagerForJavaObject(env, clazz);
1240 if (am == NULL) {
1241 return JNI_FALSE;
1242 }
1243 const ResTable& res(am->getResources());
1244 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001245 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001246 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001248 const jsize NI = env->GetArrayLength(attrs);
1249 const jsize NV = env->GetArrayLength(outValues);
1250 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001251 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001252 return JNI_FALSE;
1253 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001255 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1256 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001257 return JNI_FALSE;
1258 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001260 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1261 jint* dest = baseDest;
1262 if (dest == NULL) {
1263 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001264 return JNI_FALSE;
1265 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 jint* indices = NULL;
1268 int indicesIdx = 0;
1269 if (outIndices != NULL) {
1270 if (env->GetArrayLength(outIndices) > NI) {
1271 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1272 }
1273 }
1274
1275 // Now lock down the resource object and start pulling stuff from it.
1276 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001278 // Retrieve the XML attributes, if requested.
1279 const jsize NX = xmlParser->getAttributeCount();
1280 jsize ix=0;
1281 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001283 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001285 // Now iterate through all of the attributes that the client has requested,
1286 // filling in each with whatever data we can find.
1287 ssize_t block = 0;
1288 uint32_t typeSetFlags;
1289 for (jsize ii=0; ii<NI; ii++) {
1290 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001292 // Try to find a value for this attribute...
1293 value.dataType = Res_value::TYPE_NULL;
1294 value.data = 0;
1295 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001296 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001298 // Skip through XML attributes until the end or the next possible match.
1299 while (ix < NX && curIdent > curXmlAttr) {
1300 ix++;
1301 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1302 }
1303 // Retrieve the current XML attribute if it matches, and step to next.
1304 if (ix < NX && curIdent == curXmlAttr) {
1305 block = kXmlBlock;
1306 xmlParser->getAttributeValue(ix, &value);
1307 ix++;
1308 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1309 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001311 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1312 uint32_t resid = 0;
1313 if (value.dataType != Res_value::TYPE_NULL) {
1314 // Take care of resolving the found resource to its final value.
1315 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001316 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1317 &typeSetFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001318#if THROW_ON_BAD_ID
1319 if (newBlock == BAD_INDEX) {
1320 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1321 return JNI_FALSE;
1322 }
1323#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001324 if (newBlock >= 0) block = newBlock;
1325 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001326
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001327 // Deal with the special @null value -- it turns back to TYPE_NULL.
1328 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1329 value.dataType = Res_value::TYPE_NULL;
1330 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001331
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001332 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001334 // Write the final value back to Java.
1335 dest[STYLE_TYPE] = value.dataType;
1336 dest[STYLE_DATA] = value.data;
1337 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001338 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001339 dest[STYLE_RESOURCE_ID] = resid;
1340 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001341 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001342
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001343 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1344 indicesIdx++;
1345 indices[indicesIdx] = ii;
1346 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348 dest += STYLE_NUM_ENTRIES;
1349 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 if (indices != NULL) {
1354 indices[0] = indicesIdx;
1355 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1356 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1359 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001360
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001361 return JNI_TRUE;
1362}
1363
1364static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1365 jint id)
1366{
1367 AssetManager* am = assetManagerForJavaObject(env, clazz);
1368 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001369 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001370 }
1371 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 res.lock();
1374 const ResTable::bag_entry* defStyleEnt = NULL;
1375 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1376 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001377
Ashok Bhat896043d2014-01-17 16:02:38 +00001378 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379}
1380
1381static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1382 jint id,
1383 jintArray outValues)
1384{
1385 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001386 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001387 return JNI_FALSE;
1388 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001390 AssetManager* am = assetManagerForJavaObject(env, clazz);
1391 if (am == NULL) {
1392 return JNI_FALSE;
1393 }
1394 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001395 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 Res_value value;
1397 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001399 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001400
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001401 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1402 jint* dest = baseDest;
1403 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001404 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001405 return JNI_FALSE;
1406 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 // Now lock down the resource object and start pulling stuff from it.
1409 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001410
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001411 const ResTable::bag_entry* arrayEnt = NULL;
1412 uint32_t arrayTypeSetFlags = 0;
1413 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1414 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1415 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001416
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417 int i = 0;
1418 uint32_t typeSetFlags;
1419 while (i < NV && arrayEnt < endArrayEnt) {
1420 block = arrayEnt->stringBlock;
1421 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001422 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001424
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001425 uint32_t resid = 0;
1426 if (value.dataType != Res_value::TYPE_NULL) {
1427 // Take care of resolving the found resource to its final value.
1428 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001429 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1430 &typeSetFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001431#if THROW_ON_BAD_ID
1432 if (newBlock == BAD_INDEX) {
1433 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1434 return JNI_FALSE;
1435 }
1436#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437 if (newBlock >= 0) block = newBlock;
1438 }
1439
1440 // Deal with the special @null value -- it turns back to TYPE_NULL.
1441 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1442 value.dataType = Res_value::TYPE_NULL;
1443 }
1444
1445 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1446
1447 // Write the final value back to Java.
1448 dest[STYLE_TYPE] = value.dataType;
1449 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001450 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451 dest[STYLE_RESOURCE_ID] = resid;
1452 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001453 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 dest += STYLE_NUM_ENTRIES;
1455 i+= STYLE_NUM_ENTRIES;
1456 arrayEnt++;
1457 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001459 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001462
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001464
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001465 return i;
1466}
1467
Ashok Bhat896043d2014-01-17 16:02:38 +00001468static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 jint cookie,
1470 jstring fileName)
1471{
1472 AssetManager* am = assetManagerForJavaObject(env, clazz);
1473 if (am == NULL) {
1474 return 0;
1475 }
1476
Steve Block71f2cf12011-10-20 11:56:00 +01001477 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001478
Elliott Hughes69a017b2011-04-08 14:10:28 -07001479 ScopedUtfChars fileName8(env, fileName);
1480 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001481 return 0;
1482 }
1483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +00001485 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_BUFFER)
Elliott Hughes69a017b2011-04-08 14:10:28 -07001486 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487
1488 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001489 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 return 0;
1491 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492
1493 ResXMLTree* block = new ResXMLTree();
1494 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1495 a->close();
1496 delete a;
1497
1498 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001499 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 return 0;
1501 }
1502
Ashok Bhat896043d2014-01-17 16:02:38 +00001503 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504}
1505
1506static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1507 jint arrayResId)
1508{
1509 AssetManager* am = assetManagerForJavaObject(env, clazz);
1510 if (am == NULL) {
1511 return NULL;
1512 }
1513 const ResTable& res(am->getResources());
1514
1515 const ResTable::bag_entry* startOfBag;
1516 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1517 if (N < 0) {
1518 return NULL;
1519 }
1520
1521 jintArray array = env->NewIntArray(N * 2);
1522 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523 res.unlockBag(startOfBag);
1524 return NULL;
1525 }
1526
1527 Res_value value;
1528 const ResTable::bag_entry* bag = startOfBag;
1529 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1530 jint stringIndex = -1;
1531 jint stringBlock = 0;
1532 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001533
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 // Take care of resolving the found resource to its final value.
1535 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1536 if (value.dataType == Res_value::TYPE_STRING) {
1537 stringIndex = value.data;
1538 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001539
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001540#if THROW_ON_BAD_ID
1541 if (stringBlock == BAD_INDEX) {
1542 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1543 return array;
1544 }
1545#endif
Elliott Hughes69a017b2011-04-08 14:10:28 -07001546
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001547 //todo: It might be faster to allocate a C array to contain
1548 // the blocknums and indices, put them in there and then
1549 // do just one SetIntArrayRegion()
1550 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1551 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1552 j = j + 2;
1553 }
1554 res.unlockBag(startOfBag);
1555 return array;
1556}
1557
1558static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1559 jint arrayResId)
1560{
1561 AssetManager* am = assetManagerForJavaObject(env, clazz);
1562 if (am == NULL) {
1563 return NULL;
1564 }
1565 const ResTable& res(am->getResources());
1566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 const ResTable::bag_entry* startOfBag;
1568 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1569 if (N < 0) {
1570 return NULL;
1571 }
1572
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001573 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001574 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 res.unlockBag(startOfBag);
1576 return NULL;
1577 }
1578
1579 Res_value value;
1580 const ResTable::bag_entry* bag = startOfBag;
1581 size_t strLen = 0;
1582 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1583 value = bag->map.value;
1584 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 // Take care of resolving the found resource to its final value.
1587 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001588#if THROW_ON_BAD_ID
1589 if (block == BAD_INDEX) {
1590 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1591 return array;
1592 }
1593#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001595 const ResStringPool* pool = res.getTableStringBlock(block);
1596 const char* str8 = pool->string8At(value.data, &strLen);
1597 if (str8 != NULL) {
1598 str = env->NewStringUTF(str8);
1599 } else {
1600 const char16_t* str16 = pool->stringAt(value.data, &strLen);
1601 str = env->NewString(str16, strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001602 }
1603
1604 // If one of our NewString{UTF} calls failed due to memory, an
1605 // exception will be pending.
1606 if (env->ExceptionCheck()) {
1607 res.unlockBag(startOfBag);
1608 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001609 }
Kenny Root780d2a12010-02-22 22:36:26 -08001610
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001611 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001612
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001613 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1614 // If we have a large amount of strings in our array, we might
1615 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001616 env->DeleteLocalRef(str);
1617 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 }
1619 res.unlockBag(startOfBag);
1620 return array;
1621}
1622
1623static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1624 jint arrayResId)
1625{
1626 AssetManager* am = assetManagerForJavaObject(env, clazz);
1627 if (am == NULL) {
1628 return NULL;
1629 }
1630 const ResTable& res(am->getResources());
1631
1632 const ResTable::bag_entry* startOfBag;
1633 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1634 if (N < 0) {
1635 return NULL;
1636 }
1637
1638 jintArray array = env->NewIntArray(N);
1639 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001640 res.unlockBag(startOfBag);
1641 return NULL;
1642 }
1643
1644 Res_value value;
1645 const ResTable::bag_entry* bag = startOfBag;
1646 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1647 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 // Take care of resolving the found resource to its final value.
1650 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001651#if THROW_ON_BAD_ID
1652 if (block == BAD_INDEX) {
1653 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1654 return array;
1655 }
1656#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001657 if (value.dataType >= Res_value::TYPE_FIRST_INT
1658 && value.dataType <= Res_value::TYPE_LAST_INT) {
1659 int intVal = value.data;
1660 env->SetIntArrayRegion(array, i, 1, &intVal);
1661 }
1662 }
1663 res.unlockBag(startOfBag);
1664 return array;
1665}
1666
Mårten Kongstad48d22322014-01-31 14:43:27 +01001667static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668{
Mårten Kongstad48d22322014-01-31 14:43:27 +01001669 if (isSystem) {
1670 verifySystemIdmaps();
1671 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672 AssetManager* am = new AssetManager();
1673 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001674 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 return;
1676 }
1677
1678 am->addDefaultAssets();
1679
Steve Block71f2cf12011-10-20 11:56:00 +01001680 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00001681 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682}
1683
1684static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
1685{
1686 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00001687 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01001688 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001689 if (am != NULL) {
1690 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00001691 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001692 }
1693}
1694
1695static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
1696{
1697 return Asset::getGlobalCount();
1698}
1699
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001700static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
1701{
1702 String8 alloc = Asset::getAssetAllocations();
1703 if (alloc.length() <= 0) {
1704 return NULL;
1705 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001706
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001707 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001708 return str;
1709}
1710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001711static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
1712{
1713 return AssetManager::getGlobalCount();
1714}
1715
1716// ----------------------------------------------------------------------------
1717
1718/*
1719 * JNI registration.
1720 */
1721static JNINativeMethod gAssetManagerMethods[] = {
1722 /* name, signature, funcPtr */
1723
1724 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00001725 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001726 (void*) android_content_AssetManager_openAsset },
1727 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
1728 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00001729 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001730 (void*) android_content_AssetManager_openNonAssetNative },
1731 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
1732 (void*) android_content_AssetManager_openNonAssetFdNative },
1733 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
1734 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00001735 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001736 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00001737 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00001739 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001740 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00001741 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001742 (void*) android_content_AssetManager_seekAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00001743 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001744 (void*) android_content_AssetManager_getAssetLength },
Ashok Bhat896043d2014-01-17 16:02:38 +00001745 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001746 (void*) android_content_AssetManager_getAssetRemainingLength },
Dianne Hackbornf7be4802013-04-12 14:52:58 -07001747 { "addAssetPathNative", "(Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001748 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad48d22322014-01-31 14:43:27 +01001749 { "addOverlayPath", "(Ljava/lang/String;)I",
1750 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001751 { "isUpToDate", "()Z",
1752 (void*) android_content_AssetManager_isUpToDate },
1753
1754 // Resources.
1755 { "setLocale", "(Ljava/lang/String;)V",
1756 (void*) android_content_AssetManager_setLocale },
1757 { "getLocales", "()[Ljava/lang/String;",
1758 (void*) android_content_AssetManager_getLocales },
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001759 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001760 (void*) android_content_AssetManager_setConfiguration },
1761 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
1762 (void*) android_content_AssetManager_getResourceIdentifier },
1763 { "getResourceName","(I)Ljava/lang/String;",
1764 (void*) android_content_AssetManager_getResourceName },
1765 { "getResourcePackageName","(I)Ljava/lang/String;",
1766 (void*) android_content_AssetManager_getResourcePackageName },
1767 { "getResourceTypeName","(I)Ljava/lang/String;",
1768 (void*) android_content_AssetManager_getResourceTypeName },
1769 { "getResourceEntryName","(I)Ljava/lang/String;",
1770 (void*) android_content_AssetManager_getResourceEntryName },
Kenny Root55fc8502010-10-28 14:47:01 -07001771 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 (void*) android_content_AssetManager_loadResourceValue },
1773 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
1774 (void*) android_content_AssetManager_loadResourceBagValue },
1775 { "getStringBlockCount","()I",
1776 (void*) android_content_AssetManager_getStringBlockCount },
Ashok Bhat896043d2014-01-17 16:02:38 +00001777 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001778 (void*) android_content_AssetManager_getNativeStringBlock },
1779 { "getCookieName","(I)Ljava/lang/String;",
1780 (void*) android_content_AssetManager_getCookieName },
1781
1782 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00001783 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001784 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00001785 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00001787 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001788 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00001789 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001790 (void*) android_content_AssetManager_copyTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00001791 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 (void*) android_content_AssetManager_loadThemeAttributeValue },
Ashok Bhat896043d2014-01-17 16:02:38 +00001793 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001794 (void*) android_content_AssetManager_dumpTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00001795 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001796 (void*) android_content_AssetManager_applyStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00001797 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001798 (void*) android_content_AssetManager_retrieveAttributes },
1799 { "getArraySize","(I)I",
1800 (void*) android_content_AssetManager_getArraySize },
1801 { "retrieveArray","(I[I)I",
1802 (void*) android_content_AssetManager_retrieveArray },
1803
1804 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00001805 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001806 (void*) android_content_AssetManager_openXmlAssetNative },
1807
1808 // Arrays.
1809 { "getArrayStringResource","(I)[Ljava/lang/String;",
1810 (void*) android_content_AssetManager_getArrayStringResource },
1811 { "getArrayStringInfo","(I)[I",
1812 (void*) android_content_AssetManager_getArrayStringInfo },
1813 { "getArrayIntResource","(I)[I",
1814 (void*) android_content_AssetManager_getArrayIntResource },
1815
1816 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01001817 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 (void*) android_content_AssetManager_init },
1819 { "destroy", "()V",
1820 (void*) android_content_AssetManager_destroy },
1821 { "getGlobalAssetCount", "()I",
1822 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001823 { "getAssetAllocations", "()Ljava/lang/String;",
1824 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825 { "getGlobalAssetManagerCount", "()I",
1826 (void*) android_content_AssetManager_getGlobalAssetCount },
1827};
1828
1829int register_android_content_AssetManager(JNIEnv* env)
1830{
1831 jclass typedValue = env->FindClass("android/util/TypedValue");
1832 LOG_FATAL_IF(typedValue == NULL, "Unable to find class android/util/TypedValue");
1833 gTypedValueOffsets.mType
1834 = env->GetFieldID(typedValue, "type", "I");
1835 LOG_FATAL_IF(gTypedValueOffsets.mType == NULL, "Unable to find TypedValue.type");
1836 gTypedValueOffsets.mData
1837 = env->GetFieldID(typedValue, "data", "I");
1838 LOG_FATAL_IF(gTypedValueOffsets.mData == NULL, "Unable to find TypedValue.data");
1839 gTypedValueOffsets.mString
1840 = env->GetFieldID(typedValue, "string", "Ljava/lang/CharSequence;");
1841 LOG_FATAL_IF(gTypedValueOffsets.mString == NULL, "Unable to find TypedValue.string");
1842 gTypedValueOffsets.mAssetCookie
1843 = env->GetFieldID(typedValue, "assetCookie", "I");
1844 LOG_FATAL_IF(gTypedValueOffsets.mAssetCookie == NULL, "Unable to find TypedValue.assetCookie");
1845 gTypedValueOffsets.mResourceId
1846 = env->GetFieldID(typedValue, "resourceId", "I");
1847 LOG_FATAL_IF(gTypedValueOffsets.mResourceId == NULL, "Unable to find TypedValue.resourceId");
1848 gTypedValueOffsets.mChangingConfigurations
1849 = env->GetFieldID(typedValue, "changingConfigurations", "I");
1850 LOG_FATAL_IF(gTypedValueOffsets.mChangingConfigurations == NULL, "Unable to find TypedValue.changingConfigurations");
1851 gTypedValueOffsets.mDensity = env->GetFieldID(typedValue, "density", "I");
1852 LOG_FATAL_IF(gTypedValueOffsets.mDensity == NULL, "Unable to find TypedValue.density");
1853
1854 jclass assetFd = env->FindClass("android/content/res/AssetFileDescriptor");
1855 LOG_FATAL_IF(assetFd == NULL, "Unable to find class android/content/res/AssetFileDescriptor");
1856 gAssetFileDescriptorOffsets.mFd
1857 = env->GetFieldID(assetFd, "mFd", "Landroid/os/ParcelFileDescriptor;");
1858 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mFd == NULL, "Unable to find AssetFileDescriptor.mFd");
1859 gAssetFileDescriptorOffsets.mStartOffset
1860 = env->GetFieldID(assetFd, "mStartOffset", "J");
1861 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mStartOffset == NULL, "Unable to find AssetFileDescriptor.mStartOffset");
1862 gAssetFileDescriptorOffsets.mLength
1863 = env->GetFieldID(assetFd, "mLength", "J");
1864 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mLength == NULL, "Unable to find AssetFileDescriptor.mLength");
1865
1866 jclass assetManager = env->FindClass("android/content/res/AssetManager");
1867 LOG_FATAL_IF(assetManager == NULL, "Unable to find class android/content/res/AssetManager");
1868 gAssetManagerOffsets.mObject
Ashok Bhat896043d2014-01-17 16:02:38 +00001869 = env->GetFieldID(assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001870 LOG_FATAL_IF(gAssetManagerOffsets.mObject == NULL, "Unable to find AssetManager.mObject");
1871
Carl Shapiroc1318ba2011-03-03 14:22:28 -08001872 jclass stringClass = env->FindClass("java/lang/String");
1873 LOG_FATAL_IF(stringClass == NULL, "Unable to find class java/lang/String");
1874 g_stringClass = (jclass)env->NewGlobalRef(stringClass);
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001875 LOG_FATAL_IF(g_stringClass == NULL, "Unable to create global reference for class java/lang/String");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001876
1877 return AndroidRuntime::registerNativeMethods(env,
1878 "android/content/res/AssetManager", gAssetManagerMethods, NELEM(gAssetManagerMethods));
1879}
1880
1881}; // namespace android