blob: fba7255c0e95ee03d0bb24381e8507fbcf58adf0 [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>
Adam Lesinskia7d1d732014-10-01 18:24:54 -070036#include <androidfw/AttributeFinder.h>
Mathias Agopianb13b9bd2012-02-17 18:27:36 -080037#include <androidfw/ResourceTypes.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038
Mårten Kongstad48d22322014-01-31 14:43:27 +010039#include <private/android_filesystem_config.h> // for AID_SYSTEM
40
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041#include <stdio.h>
Mårten Kongstad48d22322014-01-31 14:43:27 +010042#include <sys/types.h>
43#include <sys/wait.h>
44
45#include <linux/capability.h>
46extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
47extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
48
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049
50namespace android {
51
52// ----------------------------------------------------------------------------
53
54static struct typedvalue_offsets_t
55{
56 jfieldID mType;
57 jfieldID mData;
58 jfieldID mString;
59 jfieldID mAssetCookie;
60 jfieldID mResourceId;
61 jfieldID mChangingConfigurations;
62 jfieldID mDensity;
63} gTypedValueOffsets;
64
65static struct assetfiledescriptor_offsets_t
66{
67 jfieldID mFd;
68 jfieldID mStartOffset;
69 jfieldID mLength;
70} gAssetFileDescriptorOffsets;
71
72static struct assetmanager_offsets_t
73{
74 jfieldID mObject;
75} gAssetManagerOffsets;
76
Adam Lesinskide898ff2014-01-29 18:20:45 -080077static struct sparsearray_offsets_t
78{
79 jclass classObject;
80 jmethodID constructor;
81 jmethodID put;
82} gSparseArrayOffsets;
83
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084jclass g_stringClass = NULL;
85
86// ----------------------------------------------------------------------------
87
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088enum {
Dianne Hackborn0d221012009-07-29 15:41:19 -070089 STYLE_NUM_ENTRIES = 6,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 STYLE_TYPE = 0,
91 STYLE_DATA = 1,
92 STYLE_ASSET_COOKIE = 2,
93 STYLE_RESOURCE_ID = 3,
Dianne Hackborn0d221012009-07-29 15:41:19 -070094 STYLE_CHANGING_CONFIGURATIONS = 4,
95 STYLE_DENSITY = 5
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096};
97
98static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
99 const Res_value& value, uint32_t ref, ssize_t block,
100 uint32_t typeSpecFlags, ResTable_config* config = NULL);
101
102jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
103 const Res_value& value, uint32_t ref, ssize_t block,
104 uint32_t typeSpecFlags, ResTable_config* config)
105{
106 env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
107 env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
Ashok Bhat896043d2014-01-17 16:02:38 +0000108 static_cast<jint>(table->getTableCookie(block)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109 env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
110 env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
111 env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
112 env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
113 typeSpecFlags);
114 if (config != NULL) {
115 env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
116 }
117 return block;
118}
119
Mårten Kongstad48d22322014-01-31 14:43:27 +0100120// This is called by zygote (running as user root) as part of preloadResources.
121static void verifySystemIdmaps()
122{
123 pid_t pid;
124 char system_id[10];
125
126 snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
127
128 switch (pid = fork()) {
129 case -1:
130 ALOGE("failed to fork for idmap: %s", strerror(errno));
131 break;
132 case 0: // child
133 {
134 struct __user_cap_header_struct capheader;
135 struct __user_cap_data_struct capdata;
136
137 memset(&capheader, 0, sizeof(capheader));
138 memset(&capdata, 0, sizeof(capdata));
139
140 capheader.version = _LINUX_CAPABILITY_VERSION;
141 capheader.pid = 0;
142
143 if (capget(&capheader, &capdata) != 0) {
144 ALOGE("capget: %s\n", strerror(errno));
145 exit(1);
146 }
147
148 capdata.effective = capdata.permitted;
149 if (capset(&capheader, &capdata) != 0) {
150 ALOGE("capset: %s\n", strerror(errno));
151 exit(1);
152 }
153
154 if (setgid(AID_SYSTEM) != 0) {
155 ALOGE("setgid: %s\n", strerror(errno));
156 exit(1);
157 }
158
159 if (setuid(AID_SYSTEM) != 0) {
160 ALOGE("setuid: %s\n", strerror(errno));
161 exit(1);
162 }
163
164 execl(AssetManager::IDMAP_BIN, AssetManager::IDMAP_BIN, "--scan",
165 AssetManager::OVERLAY_DIR, AssetManager::TARGET_PACKAGE_NAME,
166 AssetManager::TARGET_APK_PATH, AssetManager::IDMAP_DIR, (char*)NULL);
167 ALOGE("failed to execl for idmap: %s", strerror(errno));
168 exit(1); // should never get here
169 }
170 break;
171 default: // parent
172 waitpid(pid, NULL, 0);
173 break;
174 }
175}
176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177// ----------------------------------------------------------------------------
178
179// this guy is exported to other jni routines
180AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
181{
Ashok Bhat896043d2014-01-17 16:02:38 +0000182 jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
183 AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 if (am != NULL) {
185 return am;
186 }
187 jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
188 return NULL;
189}
190
Ashok Bhat896043d2014-01-17 16:02:38 +0000191static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 jstring fileName, jint mode)
193{
194 AssetManager* am = assetManagerForJavaObject(env, clazz);
195 if (am == NULL) {
196 return 0;
197 }
198
Steve Block71f2cf12011-10-20 11:56:00 +0100199 ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200
Elliott Hughes69a017b2011-04-08 14:10:28 -0700201 ScopedUtfChars fileName8(env, fileName);
202 if (fileName8.c_str() == NULL) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000203 jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 return -1;
205 }
206
207 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
208 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700209 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 return -1;
211 }
212
Elliott Hughes69a017b2011-04-08 14:10:28 -0700213 Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214
215 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700216 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 return -1;
218 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219
220 //printf("Created Asset Stream: %p\n", a);
221
Ashok Bhat896043d2014-01-17 16:02:38 +0000222 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223}
224
225static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
226{
Kenny Rootddb76c42010-11-24 12:56:06 -0800227 off64_t startOffset, length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 int fd = a->openFileDescriptor(&startOffset, &length);
229 delete a;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 if (fd < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700232 jniThrowException(env, "java/io/FileNotFoundException",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 "This file can not be opened as a file descriptor; it is probably compressed");
234 return NULL;
235 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
238 if (offsets == NULL) {
239 close(fd);
240 return NULL;
241 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243 offsets[0] = startOffset;
244 offsets[1] = length;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700247
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700248 jobject fileDesc = jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 if (fileDesc == NULL) {
250 close(fd);
251 return NULL;
252 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 return newParcelFileDescriptor(env, fileDesc);
255}
256
257static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
258 jstring fileName, jlongArray outOffsets)
259{
260 AssetManager* am = assetManagerForJavaObject(env, clazz);
261 if (am == NULL) {
262 return NULL;
263 }
264
Steve Block71f2cf12011-10-20 11:56:00 +0100265 ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266
Elliott Hughes69a017b2011-04-08 14:10:28 -0700267 ScopedUtfChars fileName8(env, fileName);
268 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 return NULL;
270 }
271
Elliott Hughes69a017b2011-04-08 14:10:28 -0700272 Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273
274 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700275 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 return NULL;
277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278
279 //printf("Created Asset Stream: %p\n", a);
280
281 return returnParcelFileDescriptor(env, a, outOffsets);
282}
283
Ashok Bhat896043d2014-01-17 16:02:38 +0000284static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285 jint cookie,
286 jstring fileName,
287 jint mode)
288{
289 AssetManager* am = assetManagerForJavaObject(env, clazz);
290 if (am == NULL) {
291 return 0;
292 }
293
Steve Block71f2cf12011-10-20 11:56:00 +0100294 ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295
Elliott Hughes69a017b2011-04-08 14:10:28 -0700296 ScopedUtfChars fileName8(env, fileName);
297 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298 return -1;
299 }
300
301 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
302 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700303 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 return -1;
305 }
306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000308 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
309 (Asset::AccessMode)mode)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700310 : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311
312 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700313 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 return -1;
315 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316
317 //printf("Created Asset Stream: %p\n", a);
318
Ashok Bhat896043d2014-01-17 16:02:38 +0000319 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320}
321
322static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
323 jint cookie,
324 jstring fileName,
325 jlongArray outOffsets)
326{
327 AssetManager* am = assetManagerForJavaObject(env, clazz);
328 if (am == NULL) {
329 return NULL;
330 }
331
Steve Block71f2cf12011-10-20 11:56:00 +0100332 ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333
Elliott Hughes69a017b2011-04-08 14:10:28 -0700334 ScopedUtfChars fileName8(env, fileName);
335 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 return NULL;
337 }
338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000340 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700341 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342
343 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700344 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800345 return NULL;
346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347
348 //printf("Created Asset Stream: %p\n", a);
349
350 return returnParcelFileDescriptor(env, a, outOffsets);
351}
352
353static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
354 jstring fileName)
355{
356 AssetManager* am = assetManagerForJavaObject(env, clazz);
357 if (am == NULL) {
358 return NULL;
359 }
360
Elliott Hughes69a017b2011-04-08 14:10:28 -0700361 ScopedUtfChars fileName8(env, fileName);
362 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 return NULL;
364 }
365
Elliott Hughes69a017b2011-04-08 14:10:28 -0700366 AssetDir* dir = am->openDir(fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800367
368 if (dir == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700369 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 return NULL;
371 }
372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800373 size_t N = dir->getFileCount();
374
375 jobjectArray array = env->NewObjectArray(dir->getFileCount(),
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +0100376 g_stringClass, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 delete dir;
379 return NULL;
380 }
381
382 for (size_t i=0; i<N; i++) {
383 const String8& name = dir->getFileName(i);
384 jstring str = env->NewStringUTF(name.string());
385 if (str == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 delete dir;
387 return NULL;
388 }
389 env->SetObjectArrayElement(array, i, str);
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700390 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 }
392
393 delete dir;
394
395 return array;
396}
397
398static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000399 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400{
Ashok Bhat896043d2014-01-17 16:02:38 +0000401 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402
403 //printf("Destroying Asset Stream: %p\n", a);
404
405 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700406 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 return;
408 }
409
410 delete a;
411}
412
413static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000414 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415{
Ashok Bhat896043d2014-01-17 16:02:38 +0000416 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417
418 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700419 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420 return -1;
421 }
422
423 uint8_t b;
424 ssize_t res = a->read(&b, 1);
425 return res == 1 ? b : -1;
426}
427
428static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000429 jlong assetHandle, jbyteArray bArray,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430 jint off, jint len)
431{
Ashok Bhat896043d2014-01-17 16:02:38 +0000432 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433
434 if (a == NULL || bArray == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700435 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 return -1;
437 }
438
439 if (len == 0) {
440 return 0;
441 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 jsize bLen = env->GetArrayLength(bArray);
444 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700445 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 return -1;
447 }
448
449 jbyte* b = env->GetByteArrayElements(bArray, NULL);
450 ssize_t res = a->read(b+off, len);
451 env->ReleaseByteArrayElements(bArray, b, 0);
452
Ashok Bhat896043d2014-01-17 16:02:38 +0000453 if (res > 0) return static_cast<jint>(res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454
455 if (res < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700456 jniThrowException(env, "java/io/IOException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 }
458 return -1;
459}
460
461static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000462 jlong assetHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 jlong offset, jint whence)
464{
Ashok Bhat896043d2014-01-17 16:02:38 +0000465 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466
467 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700468 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800469 return -1;
470 }
471
472 return a->seek(
473 offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
474}
475
476static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000477 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478{
Ashok Bhat896043d2014-01-17 16:02:38 +0000479 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480
481 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700482 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800483 return -1;
484 }
485
486 return a->getLength();
487}
488
489static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000490 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800491{
Ashok Bhat896043d2014-01-17 16:02:38 +0000492 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493
494 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700495 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800496 return -1;
497 }
498
499 return a->getRemainingLength();
500}
501
502static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
503 jstring path)
504{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700505 ScopedUtfChars path8(env, path);
506 if (path8.c_str() == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800507 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508 }
509
510 AssetManager* am = assetManagerForJavaObject(env, clazz);
511 if (am == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800512 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800513 }
514
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000515 int32_t cookie;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700516 bool res = am->addAssetPath(String8(path8.c_str()), &cookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000518 return (res) ? static_cast<jint>(cookie) : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519}
520
Mårten Kongstad48d22322014-01-31 14:43:27 +0100521static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
522 jstring idmapPath)
523{
524 ScopedUtfChars idmapPath8(env, idmapPath);
525 if (idmapPath8.c_str() == NULL) {
526 return 0;
527 }
528
529 AssetManager* am = assetManagerForJavaObject(env, clazz);
530 if (am == NULL) {
531 return 0;
532 }
533
534 int32_t cookie;
535 bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
536
537 return (res) ? (jint)cookie : 0;
538}
539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
541{
542 AssetManager* am = assetManagerForJavaObject(env, clazz);
543 if (am == NULL) {
544 return JNI_TRUE;
545 }
546 return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
547}
548
549static void android_content_AssetManager_setLocale(JNIEnv* env, jobject clazz,
550 jstring locale)
551{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700552 ScopedUtfChars locale8(env, locale);
553 if (locale8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 return;
555 }
556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 AssetManager* am = assetManagerForJavaObject(env, clazz);
558 if (am == NULL) {
559 return;
560 }
561
Elliott Hughes69a017b2011-04-08 14:10:28 -0700562 am->setLocale(locale8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563}
564
565static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
566{
567 Vector<String8> locales;
568
569 AssetManager* am = assetManagerForJavaObject(env, clazz);
570 if (am == NULL) {
571 return NULL;
572 }
573
574 am->getLocales(&locales);
575
576 const int N = locales.size();
577
578 jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
579 if (result == NULL) {
580 return NULL;
581 }
582
583 for (int i=0; i<N; i++) {
Gilles Debunne0db187a2010-08-27 11:51:34 -0700584 jstring str = env->NewStringUTF(locales[i].string());
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700585 if (str == NULL) {
586 return NULL;
587 }
588 env->SetObjectArrayElement(result, i, str);
589 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590 }
591
592 return result;
593}
594
595static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
596 jint mcc, jint mnc,
597 jstring locale, jint orientation,
598 jint touchscreen, jint density,
599 jint keyboard, jint keyboardHidden,
600 jint navigation,
601 jint screenWidth, jint screenHeight,
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700602 jint smallestScreenWidthDp,
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700603 jint screenWidthDp, jint screenHeightDp,
Tobias Haamel27b28b32010-02-09 23:09:17 +0100604 jint screenLayout, jint uiMode,
605 jint sdkVersion)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800606{
607 AssetManager* am = assetManagerForJavaObject(env, clazz);
608 if (am == NULL) {
609 return;
610 }
611
612 ResTable_config config;
613 memset(&config, 0, sizeof(config));
Elliott Hughes69a017b2011-04-08 14:10:28 -0700614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800615 const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800617 config.mcc = (uint16_t)mcc;
618 config.mnc = (uint16_t)mnc;
619 config.orientation = (uint8_t)orientation;
620 config.touchscreen = (uint8_t)touchscreen;
621 config.density = (uint16_t)density;
622 config.keyboard = (uint8_t)keyboard;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700623 config.inputFlags = (uint8_t)keyboardHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624 config.navigation = (uint8_t)navigation;
625 config.screenWidth = (uint16_t)screenWidth;
626 config.screenHeight = (uint16_t)screenHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700627 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700628 config.screenWidthDp = (uint16_t)screenWidthDp;
629 config.screenHeightDp = (uint16_t)screenHeightDp;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700630 config.screenLayout = (uint8_t)screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100631 config.uiMode = (uint8_t)uiMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800632 config.sdkVersion = (uint16_t)sdkVersion;
633 config.minorVersion = 0;
634 am->setConfiguration(config, locale8);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
637}
638
639static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
640 jstring name,
641 jstring defType,
642 jstring defPackage)
643{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700644 ScopedStringChars name16(env, name);
645 if (name16.get() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 return 0;
647 }
648
649 AssetManager* am = assetManagerForJavaObject(env, clazz);
650 if (am == NULL) {
651 return 0;
652 }
653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800654 const char16_t* defType16 = defType
655 ? env->GetStringChars(defType, NULL) : NULL;
656 jsize defTypeLen = defType
657 ? env->GetStringLength(defType) : 0;
658 const char16_t* defPackage16 = defPackage
659 ? env->GetStringChars(defPackage, NULL) : NULL;
660 jsize defPackageLen = defPackage
661 ? env->GetStringLength(defPackage) : 0;
662
663 jint ident = am->getResources().identifierForName(
Elliott Hughes69a017b2011-04-08 14:10:28 -0700664 name16.get(), name16.size(), defType16, defTypeLen, defPackage16, defPackageLen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800665
666 if (defPackage16) {
667 env->ReleaseStringChars(defPackage, defPackage16);
668 }
669 if (defType16) {
670 env->ReleaseStringChars(defType, defType16);
671 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672
673 return ident;
674}
675
676static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
677 jint resid)
678{
679 AssetManager* am = assetManagerForJavaObject(env, clazz);
680 if (am == NULL) {
681 return NULL;
682 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700685 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800686 return NULL;
687 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689 String16 str;
690 if (name.package != NULL) {
691 str.setTo(name.package, name.packageLen);
692 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700693 if (name.type8 != NULL || name.type != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 if (str.size() > 0) {
695 char16_t div = ':';
696 str.append(&div, 1);
697 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700698 if (name.type8 != NULL) {
699 str.append(String16(name.type8, name.typeLen));
700 } else {
701 str.append(name.type, name.typeLen);
702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700704 if (name.name8 != NULL || name.name != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705 if (str.size() > 0) {
706 char16_t div = '/';
707 str.append(&div, 1);
708 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700709 if (name.name8 != NULL) {
710 str.append(String16(name.name8, name.nameLen));
711 } else {
712 str.append(name.name, name.nameLen);
713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800714 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 return env->NewString((const jchar*)str.string(), str.size());
717}
718
719static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
720 jint resid)
721{
722 AssetManager* am = assetManagerForJavaObject(env, clazz);
723 if (am == NULL) {
724 return NULL;
725 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800727 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700728 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 return NULL;
730 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 if (name.package != NULL) {
733 return env->NewString((const jchar*)name.package, name.packageLen);
734 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736 return NULL;
737}
738
739static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
740 jint resid)
741{
742 AssetManager* am = assetManagerForJavaObject(env, clazz);
743 if (am == NULL) {
744 return NULL;
745 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700748 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800749 return NULL;
750 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700751
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700752 if (name.type8 != NULL) {
753 return env->NewStringUTF(name.type8);
754 }
755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 if (name.type != NULL) {
757 return env->NewString((const jchar*)name.type, name.typeLen);
758 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 return NULL;
761}
762
763static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
764 jint resid)
765{
766 AssetManager* am = assetManagerForJavaObject(env, clazz);
767 if (am == NULL) {
768 return NULL;
769 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700770
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800771 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700772 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773 return NULL;
774 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700775
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700776 if (name.name8 != NULL) {
777 return env->NewStringUTF(name.name8);
778 }
779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 if (name.name != NULL) {
781 return env->NewString((const jchar*)name.name, name.nameLen);
782 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 return NULL;
785}
786
787static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
788 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700789 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790 jobject outValue,
791 jboolean resolve)
792{
Dianne Hackborn1f7d3072013-02-11 17:03:32 -0800793 if (outValue == NULL) {
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800794 jniThrowNullPointerException(env, "outValue");
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700795 return 0;
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800796 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 AssetManager* am = assetManagerForJavaObject(env, clazz);
798 if (am == NULL) {
799 return 0;
800 }
801 const ResTable& res(am->getResources());
802
803 Res_value value;
804 ResTable_config config;
805 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700806 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800807#if THROW_ON_BAD_ID
808 if (block == BAD_INDEX) {
809 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
810 return 0;
811 }
812#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800813 uint32_t ref = ident;
814 if (resolve) {
Dianne Hackbornfb5c3db2012-05-18 15:24:24 -0700815 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800816#if THROW_ON_BAD_ID
817 if (block == BAD_INDEX) {
818 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
819 return 0;
820 }
821#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000823 if (block >= 0) {
824 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
825 }
826
827 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828}
829
830static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
831 jint ident, jint bagEntryId,
832 jobject outValue, jboolean resolve)
833{
834 AssetManager* am = assetManagerForJavaObject(env, clazz);
835 if (am == NULL) {
836 return 0;
837 }
838 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 // Now lock down the resource object and start pulling stuff from it.
841 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -0700842
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800843 ssize_t block = -1;
844 Res_value value;
845
846 const ResTable::bag_entry* entry = NULL;
847 uint32_t typeSpecFlags;
848 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
849
850 for (ssize_t i=0; i<entryCount; i++) {
851 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
852 block = entry->stringBlock;
853 value = entry->map.value;
854 }
855 entry++;
856 }
857
858 res.unlock();
859
860 if (block < 0) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000861 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800862 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 uint32_t ref = ident;
865 if (resolve) {
866 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800867#if THROW_ON_BAD_ID
868 if (block == BAD_INDEX) {
869 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
870 return 0;
871 }
872#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000874 if (block >= 0) {
875 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
876 }
877
878 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879}
880
881static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
882{
883 AssetManager* am = assetManagerForJavaObject(env, clazz);
884 if (am == NULL) {
885 return 0;
886 }
887 return am->getResources().getTableCount();
888}
889
Ashok Bhat896043d2014-01-17 16:02:38 +0000890static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800891 jint block)
892{
893 AssetManager* am = assetManagerForJavaObject(env, clazz);
894 if (am == NULL) {
895 return 0;
896 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000897 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800898}
899
900static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
901 jint cookie)
902{
903 AssetManager* am = assetManagerForJavaObject(env, clazz);
904 if (am == NULL) {
905 return NULL;
906 }
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000907 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800908 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700909 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 return NULL;
911 }
912 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913 return str;
914}
915
Adam Lesinskide898ff2014-01-29 18:20:45 -0800916static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
917{
918 AssetManager* am = assetManagerForJavaObject(env, clazz);
919 if (am == NULL) {
920 return 0;
921 }
922
923 const ResTable& res = am->getResources();
924
925 jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
926 gSparseArrayOffsets.constructor);
927 const size_t N = res.getBasePackageCount();
928 for (size_t i = 0; i < N; i++) {
929 const String16 name = res.getBasePackageName(i);
930 env->CallVoidMethod(sparseArray, gSparseArrayOffsets.put, (jint) res.getBasePackageId(i),
931 env->NewString(name, name.size()));
932 }
933 return sparseArray;
934}
935
Ashok Bhat896043d2014-01-17 16:02:38 +0000936static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800937{
938 AssetManager* am = assetManagerForJavaObject(env, clazz);
939 if (am == NULL) {
940 return 0;
941 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000942 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800943}
944
945static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000946 jlong themeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947{
Ashok Bhat896043d2014-01-17 16:02:38 +0000948 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949 delete theme;
950}
951
952static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000953 jlong themeHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 jint styleRes,
955 jboolean force)
956{
Ashok Bhat896043d2014-01-17 16:02:38 +0000957 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800958 theme->applyStyle(styleRes, force ? true : false);
959}
960
961static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000962 jlong destHandle, jlong srcHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800963{
Ashok Bhat896043d2014-01-17 16:02:38 +0000964 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
965 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800966 dest->setTo(*src);
967}
968
969static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +0000970 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971{
Ashok Bhat896043d2014-01-17 16:02:38 +0000972 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 const ResTable& res(theme->getResTable());
974
975 Res_value value;
976 // XXX value could be different in different configs!
977 uint32_t typeSpecFlags = 0;
978 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
979 uint32_t ref = 0;
980 if (resolve) {
981 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800982#if THROW_ON_BAD_ID
983 if (block == BAD_INDEX) {
984 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
985 return 0;
986 }
987#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 }
989 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
990}
991
992static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000993 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 jstring tag, jstring prefix)
995{
Ashok Bhat896043d2014-01-17 16:02:38 +0000996 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 const ResTable& res(theme->getResTable());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700998
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 // XXX Need to use params.
1000 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001}
1002
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001003class XmlAttributeFinder : public BackTrackingAttributeFinder<XmlAttributeFinder, jsize> {
1004public:
1005 XmlAttributeFinder(const ResXMLParser* parser)
1006 : BackTrackingAttributeFinder(0, parser != NULL ? parser->getAttributeCount() : 0)
1007 , mParser(parser) {}
1008
1009 inline uint32_t getAttribute(jsize index) const {
1010 return mParser->getAttributeNameResID(index);
1011 }
1012
1013private:
1014 const ResXMLParser* mParser;
1015};
1016
1017class BagAttributeFinder : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
1018public:
1019 BagAttributeFinder(const ResTable::bag_entry* start, const ResTable::bag_entry* end)
1020 : BackTrackingAttributeFinder(start, end) {}
1021
1022 inline uint32_t getAttribute(const ResTable::bag_entry* entry) const {
1023 return entry->map.name.ident;
1024 }
1025};
1026
Alan Viverette52b999f2014-03-24 18:00:26 -07001027static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1028 jlong themeToken,
1029 jint defStyleAttr,
1030 jint defStyleRes,
1031 jintArray inValues,
1032 jintArray attrs,
1033 jintArray outValues,
1034 jintArray outIndices)
1035{
1036 if (themeToken == 0) {
1037 jniThrowNullPointerException(env, "theme token");
1038 return JNI_FALSE;
1039 }
1040 if (attrs == NULL) {
1041 jniThrowNullPointerException(env, "attrs");
1042 return JNI_FALSE;
1043 }
1044 if (outValues == NULL) {
1045 jniThrowNullPointerException(env, "out values");
1046 return JNI_FALSE;
1047 }
1048
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001049 DEBUG_STYLES(ALOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x",
Alan Viverette52b999f2014-03-24 18:00:26 -07001050 themeToken, defStyleAttr, defStyleRes));
1051
1052 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1053 const ResTable& res = theme->getResTable();
1054 ResTable_config config;
1055 Res_value value;
1056
1057 const jsize NI = env->GetArrayLength(attrs);
1058 const jsize NV = env->GetArrayLength(outValues);
1059 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1060 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1061 return JNI_FALSE;
1062 }
1063
1064 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1065 if (src == NULL) {
1066 return JNI_FALSE;
1067 }
1068
1069 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1070 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1071
1072 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1073 jint* dest = baseDest;
1074 if (dest == NULL) {
1075 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1076 return JNI_FALSE;
1077 }
1078
1079 jint* indices = NULL;
1080 int indicesIdx = 0;
1081 if (outIndices != NULL) {
1082 if (env->GetArrayLength(outIndices) > NI) {
1083 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1084 }
1085 }
1086
1087 // Load default style from attribute, if specified...
1088 uint32_t defStyleBagTypeSetFlags = 0;
1089 if (defStyleAttr != 0) {
1090 Res_value value;
1091 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1092 if (value.dataType == Res_value::TYPE_REFERENCE) {
1093 defStyleRes = value.data;
1094 }
1095 }
1096 }
1097
1098 // Now lock down the resource object and start pulling stuff from it.
1099 res.lock();
1100
1101 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001102 const ResTable::bag_entry* defStyleStart = NULL;
Alan Viverette52b999f2014-03-24 18:00:26 -07001103 uint32_t defStyleTypeSetFlags = 0;
1104 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001105 ? res.getBagLocked(defStyleRes, &defStyleStart, &defStyleTypeSetFlags) : -1;
Alan Viverette52b999f2014-03-24 18:00:26 -07001106 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001107 const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
1108 BagAttributeFinder defStyleAttrFinder(defStyleStart, defStyleEnd);
Alan Viverette52b999f2014-03-24 18:00:26 -07001109
1110 // Now iterate through all of the attributes that the client has requested,
1111 // filling in each with whatever data we can find.
1112 ssize_t block = 0;
1113 uint32_t typeSetFlags;
1114 for (jsize ii=0; ii<NI; ii++) {
1115 const uint32_t curIdent = (uint32_t)src[ii];
1116
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001117 DEBUG_STYLES(ALOGI("RETRIEVING ATTR 0x%08x...", curIdent));
Alan Viverette52b999f2014-03-24 18:00:26 -07001118
1119 // Try to find a value for this attribute... we prioritize values
1120 // coming from, first XML attributes, then XML style, then default
1121 // style, and finally the theme.
1122 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001123 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001124 typeSetFlags = 0;
1125 config.density = 0;
1126
1127 // Retrieve the current input value if available.
1128 if (NSV > 0 && srcValues[ii] != 0) {
1129 block = -1;
1130 value.dataType = Res_value::TYPE_ATTRIBUTE;
1131 value.data = srcValues[ii];
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001132 DEBUG_STYLES(ALOGI("-> From values: type=0x%x, data=0x%08x",
Alan Viverette52b999f2014-03-24 18:00:26 -07001133 value.dataType, value.data));
1134 }
1135
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001136 if (value.dataType == Res_value::TYPE_NULL) {
1137 const ResTable::bag_entry* const defStyleEntry = defStyleAttrFinder.find(curIdent);
1138 if (defStyleEntry != defStyleEnd) {
1139 block = defStyleEntry->stringBlock;
Alan Viverette52b999f2014-03-24 18:00:26 -07001140 typeSetFlags = defStyleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001141 value = defStyleEntry->map.value;
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001142 DEBUG_STYLES(ALOGI("-> From def style: type=0x%x, data=0x%08x",
Alan Viverette52b999f2014-03-24 18:00:26 -07001143 value.dataType, value.data));
1144 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001145 }
1146
1147 uint32_t resid = 0;
1148 if (value.dataType != Res_value::TYPE_NULL) {
1149 // Take care of resolving the found resource to its final value.
1150 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1151 &resid, &typeSetFlags, &config);
1152 if (newBlock >= 0) block = newBlock;
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001153 DEBUG_STYLES(ALOGI("-> Resolved attr: type=0x%x, data=0x%08x",
Alan Viverette52b999f2014-03-24 18:00:26 -07001154 value.dataType, value.data));
1155 } else {
1156 // If we still don't have a value for this attribute, try to find
1157 // it in the theme!
1158 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1159 if (newBlock >= 0) {
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001160 DEBUG_STYLES(ALOGI("-> From theme: type=0x%x, data=0x%08x",
Alan Viverette52b999f2014-03-24 18:00:26 -07001161 value.dataType, value.data));
1162 newBlock = res.resolveReference(&value, block, &resid,
1163 &typeSetFlags, &config);
1164#if THROW_ON_BAD_ID
1165 if (newBlock == BAD_INDEX) {
1166 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1167 return JNI_FALSE;
1168 }
1169#endif
1170 if (newBlock >= 0) block = newBlock;
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001171 DEBUG_STYLES(ALOGI("-> Resolved theme: type=0x%x, data=0x%08x",
Alan Viverette52b999f2014-03-24 18:00:26 -07001172 value.dataType, value.data));
1173 }
1174 }
1175
1176 // Deal with the special @null value -- it turns back to TYPE_NULL.
1177 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001178 DEBUG_STYLES(ALOGI("-> Setting to @null!"));
Alan Viverette52b999f2014-03-24 18:00:26 -07001179 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001180 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001181 block = -1;
1182 }
1183
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001184 DEBUG_STYLES(ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x",
Alan Viverette52b999f2014-03-24 18:00:26 -07001185 curIdent, value.dataType, value.data));
1186
1187 // Write the final value back to Java.
1188 dest[STYLE_TYPE] = value.dataType;
1189 dest[STYLE_DATA] = value.data;
1190 dest[STYLE_ASSET_COOKIE] =
1191 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1192 dest[STYLE_RESOURCE_ID] = resid;
1193 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1194 dest[STYLE_DENSITY] = config.density;
1195
1196 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1197 indicesIdx++;
1198 indices[indicesIdx] = ii;
1199 }
1200
1201 dest += STYLE_NUM_ENTRIES;
1202 }
1203
1204 res.unlock();
1205
1206 if (indices != NULL) {
1207 indices[0] = indicesIdx;
1208 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1209 }
1210 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1211 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1212 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1213
1214 return JNI_TRUE;
1215}
1216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001217static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001218 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001219 jint defStyleAttr,
1220 jint defStyleRes,
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 (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001227 jniThrowNullPointerException(env, "theme token");
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 }
1238
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001239 DEBUG_STYLES(ALOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x xml=0x%x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001240 themeToken, defStyleAttr, defStyleRes, xmlParserToken));
Elliott Hughes69a017b2011-04-08 14:10:28 -07001241
Ashok Bhat896043d2014-01-17 16:02:38 +00001242 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001244 ResXMLParser* xmlParser = reinterpret_cast<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;
1247
1248 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 }
1254
1255 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 }
1259
1260 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 }
1266
1267 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 // Load default style from attribute, if specified...
1276 uint32_t defStyleBagTypeSetFlags = 0;
1277 if (defStyleAttr != 0) {
1278 Res_value value;
1279 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1280 if (value.dataType == Res_value::TYPE_REFERENCE) {
1281 defStyleRes = value.data;
1282 }
1283 }
1284 }
1285
1286 // Retrieve the style class associated with the current XML tag.
1287 int style = 0;
1288 uint32_t styleBagTypeSetFlags = 0;
1289 if (xmlParser != NULL) {
1290 ssize_t idx = xmlParser->indexOfStyle();
1291 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1292 if (value.dataType == value.TYPE_ATTRIBUTE) {
1293 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1294 value.dataType = Res_value::TYPE_NULL;
1295 }
1296 }
1297 if (value.dataType == value.TYPE_REFERENCE) {
1298 style = value.data;
1299 }
1300 }
1301 }
1302
1303 // Now lock down the resource object and start pulling stuff from it.
1304 res.lock();
1305
1306 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001307 const ResTable::bag_entry* defStyleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001308 uint32_t defStyleTypeSetFlags = 0;
1309 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001310 ? res.getBagLocked(defStyleRes, &defStyleAttrStart, &defStyleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001311 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001312 const ResTable::bag_entry* const defStyleAttrEnd = defStyleAttrStart + (bagOff >= 0 ? bagOff : 0);
1313 BagAttributeFinder defStyleAttrFinder(defStyleAttrStart, defStyleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001314
1315 // Retrieve the style class bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001316 const ResTable::bag_entry* styleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001317 uint32_t styleTypeSetFlags = 0;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001318 bagOff = style != 0 ? res.getBagLocked(style, &styleAttrStart, &styleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001319 styleTypeSetFlags |= styleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001320 const ResTable::bag_entry* const styleAttrEnd = styleAttrStart + (bagOff >= 0 ? bagOff : 0);
1321 BagAttributeFinder styleAttrFinder(styleAttrStart, styleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001322
1323 // Retrieve the XML attributes, if requested.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001324 static const ssize_t kXmlBlock = 0x10000000;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001325 XmlAttributeFinder xmlAttrFinder(xmlParser);
1326 const jsize xmlAttrEnd = xmlParser != NULL ? xmlParser->getAttributeCount() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001327
1328 // Now iterate through all of the attributes that the client has requested,
1329 // filling in each with whatever data we can find.
1330 ssize_t block = 0;
1331 uint32_t typeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001332 for (jsize ii = 0; ii < NI; ii++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001333 const uint32_t curIdent = (uint32_t)src[ii];
1334
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001335 DEBUG_STYLES(ALOGI("RETRIEVING ATTR 0x%08x...", curIdent));
Elliott Hughes69a017b2011-04-08 14:10:28 -07001336
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001337 // Try to find a value for this attribute... we prioritize values
1338 // coming from, first XML attributes, then XML style, then default
1339 // style, and finally the theme.
1340 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001341 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001342 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001343 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001344
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001345 // Walk through the xml attributes looking for the requested attribute.
1346 const jsize xmlAttrIdx = xmlAttrFinder.find(curIdent);
1347 if (xmlAttrIdx != xmlAttrEnd) {
1348 // We found the attribute we were looking for.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349 block = kXmlBlock;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001350 xmlParser->getAttributeValue(xmlAttrIdx, &value);
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001351 DEBUG_STYLES(ALOGI("-> From XML: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001352 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 }
1354
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001355 if (value.dataType == Res_value::TYPE_NULL) {
1356 // Walk through the style class values looking for the requested attribute.
1357 const ResTable::bag_entry* const styleAttrEntry = styleAttrFinder.find(curIdent);
1358 if (styleAttrEntry != styleAttrEnd) {
1359 // We found the attribute we were looking for.
1360 block = styleAttrEntry->stringBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001361 typeSetFlags = styleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001362 value = styleAttrEntry->map.value;
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001363 DEBUG_STYLES(ALOGI("-> From style: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001364 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001365 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001366 }
1367
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001368 if (value.dataType == Res_value::TYPE_NULL) {
1369 // Walk through the default style values looking for the requested attribute.
1370 const ResTable::bag_entry* const defStyleAttrEntry = defStyleAttrFinder.find(curIdent);
1371 if (defStyleAttrEntry != defStyleAttrEnd) {
1372 // We found the attribute we were looking for.
1373 block = defStyleAttrEntry->stringBlock;
1374 typeSetFlags = styleTypeSetFlags;
1375 value = defStyleAttrEntry->map.value;
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001376 DEBUG_STYLES(ALOGI("-> From def style: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001377 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379 }
1380
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 uint32_t resid = 0;
1382 if (value.dataType != Res_value::TYPE_NULL) {
1383 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001384 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1385 &resid, &typeSetFlags, &config);
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001386 if (newBlock >= 0) {
1387 block = newBlock;
1388 }
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001389 DEBUG_STYLES(ALOGI("-> Resolved attr: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001390 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001391 } else {
1392 // If we still don't have a value for this attribute, try to find
1393 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001394 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1395 if (newBlock >= 0) {
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001396 DEBUG_STYLES(ALOGI("-> From theme: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001397 value.dataType, value.data));
Dianne Hackborn0d221012009-07-29 15:41:19 -07001398 newBlock = res.resolveReference(&value, block, &resid,
1399 &typeSetFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001400#if THROW_ON_BAD_ID
1401 if (newBlock == BAD_INDEX) {
1402 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1403 return JNI_FALSE;
1404 }
1405#endif
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001406 if (newBlock >= 0) {
1407 block = newBlock;
1408 }
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001409 DEBUG_STYLES(ALOGI("-> Resolved theme: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001410 value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001411 }
1412 }
1413
1414 // Deal with the special @null value -- it turns back to TYPE_NULL.
1415 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001416 DEBUG_STYLES(ALOGI("-> Setting to @null!"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001418 value.data = Res_value::DATA_NULL_UNDEFINED;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001419 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001420 }
1421
Adam Lesinskiccf25c7b2014-08-08 15:32:40 -07001422 DEBUG_STYLES(ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x",
Dianne Hackbornb8d81672009-11-20 14:26:42 -08001423 curIdent, value.dataType, value.data));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001424
1425 // Write the final value back to Java.
1426 dest[STYLE_TYPE] = value.dataType;
1427 dest[STYLE_DATA] = value.data;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001428 dest[STYLE_ASSET_COOKIE] = block != kXmlBlock ?
1429 static_cast<jint>(res.getTableCookie(block)) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001430 dest[STYLE_RESOURCE_ID] = resid;
1431 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001432 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001433
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1435 indicesIdx++;
1436 indices[indicesIdx] = ii;
1437 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001439 dest += STYLE_NUM_ENTRIES;
1440 }
1441
1442 res.unlock();
1443
1444 if (indices != NULL) {
1445 indices[0] = indicesIdx;
1446 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1447 }
1448 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1449 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1450
1451 return JNI_TRUE;
1452}
1453
1454static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001455 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 jintArray attrs,
1457 jintArray outValues,
1458 jintArray outIndices)
1459{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001460 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001461 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001462 return JNI_FALSE;
1463 }
1464 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001465 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001466 return JNI_FALSE;
1467 }
1468 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001469 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 return JNI_FALSE;
1471 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 AssetManager* am = assetManagerForJavaObject(env, clazz);
1474 if (am == NULL) {
1475 return JNI_FALSE;
1476 }
1477 const ResTable& res(am->getResources());
1478 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001479 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001481
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001482 const jsize NI = env->GetArrayLength(attrs);
1483 const jsize NV = env->GetArrayLength(outValues);
1484 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001485 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 return JNI_FALSE;
1487 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001488
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001489 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1490 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001491 return JNI_FALSE;
1492 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1495 jint* dest = baseDest;
1496 if (dest == NULL) {
1497 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001498 return JNI_FALSE;
1499 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 jint* indices = NULL;
1502 int indicesIdx = 0;
1503 if (outIndices != NULL) {
1504 if (env->GetArrayLength(outIndices) > NI) {
1505 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1506 }
1507 }
1508
1509 // Now lock down the resource object and start pulling stuff from it.
1510 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001511
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 // Retrieve the XML attributes, if requested.
1513 const jsize NX = xmlParser->getAttributeCount();
1514 jsize ix=0;
1515 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 // Now iterate through all of the attributes that the client has requested,
1520 // filling in each with whatever data we can find.
1521 ssize_t block = 0;
1522 uint32_t typeSetFlags;
1523 for (jsize ii=0; ii<NI; ii++) {
1524 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001526 // Try to find a value for this attribute...
1527 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001528 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001529 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001530 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001533 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 ix++;
1535 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1536 }
1537 // Retrieve the current XML attribute if it matches, and step to next.
1538 if (ix < NX && curIdent == curXmlAttr) {
1539 block = kXmlBlock;
1540 xmlParser->getAttributeValue(ix, &value);
1541 ix++;
1542 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1543 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001545 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1546 uint32_t resid = 0;
1547 if (value.dataType != Res_value::TYPE_NULL) {
1548 // Take care of resolving the found resource to its final value.
1549 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001550 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1551 &typeSetFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001552#if THROW_ON_BAD_ID
1553 if (newBlock == BAD_INDEX) {
1554 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1555 return JNI_FALSE;
1556 }
1557#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 if (newBlock >= 0) block = newBlock;
1559 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001560
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001561 // Deal with the special @null value -- it turns back to TYPE_NULL.
1562 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1563 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001564 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001565 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569 // Write the final value back to Java.
1570 dest[STYLE_TYPE] = value.dataType;
1571 dest[STYLE_DATA] = value.data;
1572 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001573 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001574 dest[STYLE_RESOURCE_ID] = resid;
1575 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001576 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001577
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001578 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1579 indicesIdx++;
1580 indices[indicesIdx] = ii;
1581 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001583 dest += STYLE_NUM_ENTRIES;
1584 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001588 if (indices != NULL) {
1589 indices[0] = indicesIdx;
1590 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1591 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001593 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1594 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001595
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 return JNI_TRUE;
1597}
1598
1599static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1600 jint id)
1601{
1602 AssetManager* am = assetManagerForJavaObject(env, clazz);
1603 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001604 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001605 }
1606 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001608 res.lock();
1609 const ResTable::bag_entry* defStyleEnt = NULL;
1610 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1611 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001612
Ashok Bhat896043d2014-01-17 16:02:38 +00001613 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614}
1615
1616static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1617 jint id,
1618 jintArray outValues)
1619{
1620 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001621 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 return JNI_FALSE;
1623 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001625 AssetManager* am = assetManagerForJavaObject(env, clazz);
1626 if (am == NULL) {
1627 return JNI_FALSE;
1628 }
1629 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001630 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001631 Res_value value;
1632 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1637 jint* dest = baseDest;
1638 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001639 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001640 return JNI_FALSE;
1641 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643 // Now lock down the resource object and start pulling stuff from it.
1644 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 const ResTable::bag_entry* arrayEnt = NULL;
1647 uint32_t arrayTypeSetFlags = 0;
1648 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1649 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1650 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 int i = 0;
1653 uint32_t typeSetFlags;
1654 while (i < NV && arrayEnt < endArrayEnt) {
1655 block = arrayEnt->stringBlock;
1656 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001657 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001660 uint32_t resid = 0;
1661 if (value.dataType != Res_value::TYPE_NULL) {
1662 // Take care of resolving the found resource to its final value.
1663 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001664 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1665 &typeSetFlags, &config);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001666#if THROW_ON_BAD_ID
1667 if (newBlock == BAD_INDEX) {
1668 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1669 return JNI_FALSE;
1670 }
1671#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672 if (newBlock >= 0) block = newBlock;
1673 }
1674
1675 // Deal with the special @null value -- it turns back to TYPE_NULL.
1676 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1677 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001678 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 }
1680
1681 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1682
1683 // Write the final value back to Java.
1684 dest[STYLE_TYPE] = value.dataType;
1685 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001686 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 dest[STYLE_RESOURCE_ID] = resid;
1688 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001689 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 dest += STYLE_NUM_ENTRIES;
1691 i+= STYLE_NUM_ENTRIES;
1692 arrayEnt++;
1693 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001694
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001695 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001697 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 return i;
1702}
1703
Ashok Bhat896043d2014-01-17 16:02:38 +00001704static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705 jint cookie,
1706 jstring fileName)
1707{
1708 AssetManager* am = assetManagerForJavaObject(env, clazz);
1709 if (am == NULL) {
1710 return 0;
1711 }
1712
Steve Block71f2cf12011-10-20 11:56:00 +01001713 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001714
Elliott Hughes69a017b2011-04-08 14:10:28 -07001715 ScopedUtfChars fileName8(env, fileName);
1716 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001717 return 0;
1718 }
1719
Adam Lesinskide898ff2014-01-29 18:20:45 -08001720 int32_t assetCookie = static_cast<int32_t>(cookie);
1721 Asset* a = assetCookie
1722 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1723 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001724
1725 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001726 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001727 return 0;
1728 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001729
Adam Lesinskide898ff2014-01-29 18:20:45 -08001730 const DynamicRefTable* dynamicRefTable =
1731 am->getResources().getDynamicRefTableForCookie(assetCookie);
1732 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001733 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1734 a->close();
1735 delete a;
1736
1737 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001738 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 return 0;
1740 }
1741
Ashok Bhat896043d2014-01-17 16:02:38 +00001742 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001743}
1744
1745static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1746 jint arrayResId)
1747{
1748 AssetManager* am = assetManagerForJavaObject(env, clazz);
1749 if (am == NULL) {
1750 return NULL;
1751 }
1752 const ResTable& res(am->getResources());
1753
1754 const ResTable::bag_entry* startOfBag;
1755 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1756 if (N < 0) {
1757 return NULL;
1758 }
1759
1760 jintArray array = env->NewIntArray(N * 2);
1761 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762 res.unlockBag(startOfBag);
1763 return NULL;
1764 }
1765
1766 Res_value value;
1767 const ResTable::bag_entry* bag = startOfBag;
1768 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1769 jint stringIndex = -1;
1770 jint stringBlock = 0;
1771 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001773 // Take care of resolving the found resource to its final value.
1774 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1775 if (value.dataType == Res_value::TYPE_STRING) {
1776 stringIndex = value.data;
1777 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001778
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001779#if THROW_ON_BAD_ID
1780 if (stringBlock == BAD_INDEX) {
1781 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1782 return array;
1783 }
1784#endif
Elliott Hughes69a017b2011-04-08 14:10:28 -07001785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786 //todo: It might be faster to allocate a C array to contain
1787 // the blocknums and indices, put them in there and then
1788 // do just one SetIntArrayRegion()
1789 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1790 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1791 j = j + 2;
1792 }
1793 res.unlockBag(startOfBag);
1794 return array;
1795}
1796
1797static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1798 jint arrayResId)
1799{
1800 AssetManager* am = assetManagerForJavaObject(env, clazz);
1801 if (am == NULL) {
1802 return NULL;
1803 }
1804 const ResTable& res(am->getResources());
1805
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001806 const ResTable::bag_entry* startOfBag;
1807 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1808 if (N < 0) {
1809 return NULL;
1810 }
1811
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001812 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001813 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 res.unlockBag(startOfBag);
1815 return NULL;
1816 }
1817
1818 Res_value value;
1819 const ResTable::bag_entry* bag = startOfBag;
1820 size_t strLen = 0;
1821 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1822 value = bag->map.value;
1823 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825 // Take care of resolving the found resource to its final value.
1826 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001827#if THROW_ON_BAD_ID
1828 if (block == BAD_INDEX) {
1829 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1830 return array;
1831 }
1832#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001833 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001834 const ResStringPool* pool = res.getTableStringBlock(block);
1835 const char* str8 = pool->string8At(value.data, &strLen);
1836 if (str8 != NULL) {
1837 str = env->NewStringUTF(str8);
1838 } else {
1839 const char16_t* str16 = pool->stringAt(value.data, &strLen);
1840 str = env->NewString(str16, strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001841 }
1842
1843 // If one of our NewString{UTF} calls failed due to memory, an
1844 // exception will be pending.
1845 if (env->ExceptionCheck()) {
1846 res.unlockBag(startOfBag);
1847 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001848 }
Kenny Root780d2a12010-02-22 22:36:26 -08001849
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001850 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001851
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001852 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1853 // If we have a large amount of strings in our array, we might
1854 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001855 env->DeleteLocalRef(str);
1856 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001857 }
1858 res.unlockBag(startOfBag);
1859 return array;
1860}
1861
1862static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1863 jint arrayResId)
1864{
1865 AssetManager* am = assetManagerForJavaObject(env, clazz);
1866 if (am == NULL) {
1867 return NULL;
1868 }
1869 const ResTable& res(am->getResources());
1870
1871 const ResTable::bag_entry* startOfBag;
1872 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1873 if (N < 0) {
1874 return NULL;
1875 }
1876
1877 jintArray array = env->NewIntArray(N);
1878 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001879 res.unlockBag(startOfBag);
1880 return NULL;
1881 }
1882
1883 Res_value value;
1884 const ResTable::bag_entry* bag = startOfBag;
1885 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1886 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001887
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001888 // Take care of resolving the found resource to its final value.
1889 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001890#if THROW_ON_BAD_ID
1891 if (block == BAD_INDEX) {
1892 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1893 return array;
1894 }
1895#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001896 if (value.dataType >= Res_value::TYPE_FIRST_INT
1897 && value.dataType <= Res_value::TYPE_LAST_INT) {
1898 int intVal = value.data;
1899 env->SetIntArrayRegion(array, i, 1, &intVal);
1900 }
1901 }
1902 res.unlockBag(startOfBag);
1903 return array;
1904}
1905
Jon Miranda042ad632014-09-03 17:57:35 -07001906static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
1907 jint styleId)
1908{
1909 AssetManager* am = assetManagerForJavaObject(env, clazz);
1910 if (am == NULL) {
1911 return NULL;
1912 }
1913 const ResTable& res(am->getResources());
1914
1915 const ResTable::bag_entry* startOfBag;
1916 const ssize_t N = res.lockBag(styleId, &startOfBag);
1917 if (N < 0) {
1918 return NULL;
1919 }
1920
1921 jintArray array = env->NewIntArray(N);
1922 if (array == NULL) {
1923 res.unlockBag(startOfBag);
1924 return NULL;
1925 }
1926
1927 Res_value value;
1928 const ResTable::bag_entry* bag = startOfBag;
1929 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1930 int resourceId = bag->map.name.ident;
1931 env->SetIntArrayRegion(array, i, 1, &resourceId);
1932 }
1933 res.unlockBag(startOfBag);
1934 return array;
1935}
1936
Mårten Kongstad48d22322014-01-31 14:43:27 +01001937static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001938{
Mårten Kongstad48d22322014-01-31 14:43:27 +01001939 if (isSystem) {
1940 verifySystemIdmaps();
1941 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001942 AssetManager* am = new AssetManager();
1943 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001944 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001945 return;
1946 }
1947
1948 am->addDefaultAssets();
1949
Steve Block71f2cf12011-10-20 11:56:00 +01001950 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00001951 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001952}
1953
1954static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
1955{
1956 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00001957 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01001958 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001959 if (am != NULL) {
1960 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00001961 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001962 }
1963}
1964
1965static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
1966{
1967 return Asset::getGlobalCount();
1968}
1969
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001970static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
1971{
1972 String8 alloc = Asset::getAssetAllocations();
1973 if (alloc.length() <= 0) {
1974 return NULL;
1975 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001976
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001977 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001978 return str;
1979}
1980
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001981static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
1982{
1983 return AssetManager::getGlobalCount();
1984}
1985
1986// ----------------------------------------------------------------------------
1987
1988/*
1989 * JNI registration.
1990 */
1991static JNINativeMethod gAssetManagerMethods[] = {
1992 /* name, signature, funcPtr */
1993
1994 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00001995 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001996 (void*) android_content_AssetManager_openAsset },
1997 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
1998 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00001999 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002000 (void*) android_content_AssetManager_openNonAssetNative },
2001 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2002 (void*) android_content_AssetManager_openNonAssetFdNative },
2003 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
2004 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00002005 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002006 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002007 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002008 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00002009 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002010 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002011 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002012 (void*) android_content_AssetManager_seekAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002013 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002014 (void*) android_content_AssetManager_getAssetLength },
Ashok Bhat896043d2014-01-17 16:02:38 +00002015 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002016 (void*) android_content_AssetManager_getAssetRemainingLength },
Dianne Hackbornf7be4802013-04-12 14:52:58 -07002017 { "addAssetPathNative", "(Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002018 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad48d22322014-01-31 14:43:27 +01002019 { "addOverlayPath", "(Ljava/lang/String;)I",
2020 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002021 { "isUpToDate", "()Z",
2022 (void*) android_content_AssetManager_isUpToDate },
2023
2024 // Resources.
2025 { "setLocale", "(Ljava/lang/String;)V",
2026 (void*) android_content_AssetManager_setLocale },
2027 { "getLocales", "()[Ljava/lang/String;",
2028 (void*) android_content_AssetManager_getLocales },
Dianne Hackborn69cb8752011-05-19 18:13:32 -07002029 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002030 (void*) android_content_AssetManager_setConfiguration },
2031 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
2032 (void*) android_content_AssetManager_getResourceIdentifier },
2033 { "getResourceName","(I)Ljava/lang/String;",
2034 (void*) android_content_AssetManager_getResourceName },
2035 { "getResourcePackageName","(I)Ljava/lang/String;",
2036 (void*) android_content_AssetManager_getResourcePackageName },
2037 { "getResourceTypeName","(I)Ljava/lang/String;",
2038 (void*) android_content_AssetManager_getResourceTypeName },
2039 { "getResourceEntryName","(I)Ljava/lang/String;",
2040 (void*) android_content_AssetManager_getResourceEntryName },
Kenny Root55fc8502010-10-28 14:47:01 -07002041 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002042 (void*) android_content_AssetManager_loadResourceValue },
2043 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
2044 (void*) android_content_AssetManager_loadResourceBagValue },
2045 { "getStringBlockCount","()I",
2046 (void*) android_content_AssetManager_getStringBlockCount },
Ashok Bhat896043d2014-01-17 16:02:38 +00002047 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002048 (void*) android_content_AssetManager_getNativeStringBlock },
2049 { "getCookieName","(I)Ljava/lang/String;",
2050 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002051 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2052 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002053
2054 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002055 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002056 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002057 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002058 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002059 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002060 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002061 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002062 (void*) android_content_AssetManager_copyTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002063 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002064 (void*) android_content_AssetManager_loadThemeAttributeValue },
Ashok Bhat896043d2014-01-17 16:02:38 +00002065 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002066 (void*) android_content_AssetManager_dumpTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002067 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002068 (void*) android_content_AssetManager_applyStyle },
Alan Viverette607bd842014-09-12 12:36:35 -07002069 { "resolveAttrs","(JII[I[I[I[I)Z",
2070 (void*) android_content_AssetManager_resolveAttrs },
Ashok Bhat896043d2014-01-17 16:02:38 +00002071 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002072 (void*) android_content_AssetManager_retrieveAttributes },
2073 { "getArraySize","(I)I",
2074 (void*) android_content_AssetManager_getArraySize },
2075 { "retrieveArray","(I[I)I",
2076 (void*) android_content_AssetManager_retrieveArray },
2077
2078 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002079 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002080 (void*) android_content_AssetManager_openXmlAssetNative },
2081
2082 // Arrays.
2083 { "getArrayStringResource","(I)[Ljava/lang/String;",
2084 (void*) android_content_AssetManager_getArrayStringResource },
2085 { "getArrayStringInfo","(I)[I",
2086 (void*) android_content_AssetManager_getArrayStringInfo },
2087 { "getArrayIntResource","(I)[I",
2088 (void*) android_content_AssetManager_getArrayIntResource },
Jon Miranda042ad632014-09-03 17:57:35 -07002089 { "getStyleAttributes","(I)[I",
2090 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002091
2092 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002093 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002094 (void*) android_content_AssetManager_init },
2095 { "destroy", "()V",
2096 (void*) android_content_AssetManager_destroy },
2097 { "getGlobalAssetCount", "()I",
2098 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002099 { "getAssetAllocations", "()Ljava/lang/String;",
2100 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002101 { "getGlobalAssetManagerCount", "()I",
2102 (void*) android_content_AssetManager_getGlobalAssetCount },
2103};
2104
2105int register_android_content_AssetManager(JNIEnv* env)
2106{
2107 jclass typedValue = env->FindClass("android/util/TypedValue");
2108 LOG_FATAL_IF(typedValue == NULL, "Unable to find class android/util/TypedValue");
2109 gTypedValueOffsets.mType
2110 = env->GetFieldID(typedValue, "type", "I");
2111 LOG_FATAL_IF(gTypedValueOffsets.mType == NULL, "Unable to find TypedValue.type");
2112 gTypedValueOffsets.mData
2113 = env->GetFieldID(typedValue, "data", "I");
2114 LOG_FATAL_IF(gTypedValueOffsets.mData == NULL, "Unable to find TypedValue.data");
2115 gTypedValueOffsets.mString
2116 = env->GetFieldID(typedValue, "string", "Ljava/lang/CharSequence;");
2117 LOG_FATAL_IF(gTypedValueOffsets.mString == NULL, "Unable to find TypedValue.string");
2118 gTypedValueOffsets.mAssetCookie
2119 = env->GetFieldID(typedValue, "assetCookie", "I");
2120 LOG_FATAL_IF(gTypedValueOffsets.mAssetCookie == NULL, "Unable to find TypedValue.assetCookie");
2121 gTypedValueOffsets.mResourceId
2122 = env->GetFieldID(typedValue, "resourceId", "I");
2123 LOG_FATAL_IF(gTypedValueOffsets.mResourceId == NULL, "Unable to find TypedValue.resourceId");
2124 gTypedValueOffsets.mChangingConfigurations
2125 = env->GetFieldID(typedValue, "changingConfigurations", "I");
2126 LOG_FATAL_IF(gTypedValueOffsets.mChangingConfigurations == NULL, "Unable to find TypedValue.changingConfigurations");
2127 gTypedValueOffsets.mDensity = env->GetFieldID(typedValue, "density", "I");
2128 LOG_FATAL_IF(gTypedValueOffsets.mDensity == NULL, "Unable to find TypedValue.density");
2129
2130 jclass assetFd = env->FindClass("android/content/res/AssetFileDescriptor");
2131 LOG_FATAL_IF(assetFd == NULL, "Unable to find class android/content/res/AssetFileDescriptor");
2132 gAssetFileDescriptorOffsets.mFd
2133 = env->GetFieldID(assetFd, "mFd", "Landroid/os/ParcelFileDescriptor;");
2134 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mFd == NULL, "Unable to find AssetFileDescriptor.mFd");
2135 gAssetFileDescriptorOffsets.mStartOffset
2136 = env->GetFieldID(assetFd, "mStartOffset", "J");
2137 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mStartOffset == NULL, "Unable to find AssetFileDescriptor.mStartOffset");
2138 gAssetFileDescriptorOffsets.mLength
2139 = env->GetFieldID(assetFd, "mLength", "J");
2140 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mLength == NULL, "Unable to find AssetFileDescriptor.mLength");
2141
2142 jclass assetManager = env->FindClass("android/content/res/AssetManager");
2143 LOG_FATAL_IF(assetManager == NULL, "Unable to find class android/content/res/AssetManager");
2144 gAssetManagerOffsets.mObject
Ashok Bhat896043d2014-01-17 16:02:38 +00002145 = env->GetFieldID(assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 LOG_FATAL_IF(gAssetManagerOffsets.mObject == NULL, "Unable to find AssetManager.mObject");
2147
Carl Shapiroc1318ba2011-03-03 14:22:28 -08002148 jclass stringClass = env->FindClass("java/lang/String");
2149 LOG_FATAL_IF(stringClass == NULL, "Unable to find class java/lang/String");
2150 g_stringClass = (jclass)env->NewGlobalRef(stringClass);
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01002151 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 -08002152
Adam Lesinskide898ff2014-01-29 18:20:45 -08002153 jclass sparseArrayClass = env->FindClass("android/util/SparseArray");
2154 LOG_FATAL_IF(sparseArrayClass == NULL, "Unable to find class android/util/SparseArray");
2155 gSparseArrayOffsets.classObject = (jclass) env->NewGlobalRef(sparseArrayClass);
2156 gSparseArrayOffsets.constructor =
2157 env->GetMethodID(gSparseArrayOffsets.classObject, "<init>", "()V");
2158 LOG_FATAL_IF(gSparseArrayOffsets.constructor == NULL, "Unable to find SparseArray.<init>()");
2159 gSparseArrayOffsets.put =
2160 env->GetMethodID(gSparseArrayOffsets.classObject, "put", "(ILjava/lang/Object;)V");
2161 LOG_FATAL_IF(gSparseArrayOffsets.put == NULL, "Unable to find SparseArray.put(int, V)");
2162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002163 return AndroidRuntime::registerNativeMethods(env,
2164 "android/content/res/AssetManager", gAssetManagerMethods, NELEM(gAssetManagerMethods));
2165}
2166
2167}; // namespace android