blob: c0076a80ee6a63cf0fdb30e59d125d69073ddb0c [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/* //device/libs/android_runtime/android_util_AssetManager.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
Elliott Hughes69a017b2011-04-08 14:10:28 -07005** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008**
Elliott Hughes69a017b2011-04-08 14:10:28 -07009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010**
Elliott Hughes69a017b2011-04-08 14:10:28 -070011** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015** limitations under the License.
16*/
17
18#define LOG_TAG "asset"
19
20#include <android_runtime/android_util_AssetManager.h>
21
22#include "jni.h"
23#include "JNIHelp.h"
Elliott Hughes69a017b2011-04-08 14:10:28 -070024#include "ScopedStringChars.h"
25#include "ScopedUtfChars.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026#include "android_util_Binder.h"
27#include <utils/misc.h>
28#include <android_runtime/AndroidRuntime.h>
29#include <utils/Log.h>
30
Mathias Agopianb13b9bd2012-02-17 18:27:36 -080031#include <androidfw/Asset.h>
32#include <androidfw/AssetManager.h>
Adam Lesinskia7d1d732014-10-01 18:24:54 -070033#include <androidfw/AttributeFinder.h>
Mathias Agopianb13b9bd2012-02-17 18:27:36 -080034#include <androidfw/ResourceTypes.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035
Mårten Kongstad48d22322014-01-31 14:43:27 +010036#include <private/android_filesystem_config.h> // for AID_SYSTEM
37
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038#include <stdio.h>
Mårten Kongstad48d22322014-01-31 14:43:27 +010039#include <sys/types.h>
40#include <sys/wait.h>
41
42#include <linux/capability.h>
43extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
44extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
45
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046
47namespace android {
48
Andreas Gampe0f0b4912014-11-12 08:03:48 -080049static const bool kThrowOnBadId = false;
50static const bool kDebugStyles = false;
51
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052// ----------------------------------------------------------------------------
53
54static struct typedvalue_offsets_t
55{
56 jfieldID mType;
57 jfieldID mData;
58 jfieldID mString;
59 jfieldID mAssetCookie;
60 jfieldID mResourceId;
61 jfieldID mChangingConfigurations;
62 jfieldID mDensity;
63} gTypedValueOffsets;
64
65static struct assetfiledescriptor_offsets_t
66{
67 jfieldID mFd;
68 jfieldID mStartOffset;
69 jfieldID mLength;
70} gAssetFileDescriptorOffsets;
71
72static struct assetmanager_offsets_t
73{
74 jfieldID mObject;
75} gAssetManagerOffsets;
76
Adam Lesinskide898ff2014-01-29 18:20:45 -080077static struct sparsearray_offsets_t
78{
79 jclass classObject;
80 jmethodID constructor;
81 jmethodID put;
82} gSparseArrayOffsets;
83
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084jclass g_stringClass = NULL;
85
86// ----------------------------------------------------------------------------
87
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088enum {
Dianne Hackborn0d221012009-07-29 15:41:19 -070089 STYLE_NUM_ENTRIES = 6,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 STYLE_TYPE = 0,
91 STYLE_DATA = 1,
92 STYLE_ASSET_COOKIE = 2,
93 STYLE_RESOURCE_ID = 3,
Dianne Hackborn0d221012009-07-29 15:41:19 -070094 STYLE_CHANGING_CONFIGURATIONS = 4,
95 STYLE_DENSITY = 5
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096};
97
98static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
99 const Res_value& value, uint32_t ref, ssize_t block,
100 uint32_t typeSpecFlags, ResTable_config* config = NULL);
101
102jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
103 const Res_value& value, uint32_t ref, ssize_t block,
104 uint32_t typeSpecFlags, ResTable_config* config)
105{
106 env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
107 env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
Ashok Bhat896043d2014-01-17 16:02:38 +0000108 static_cast<jint>(table->getTableCookie(block)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109 env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
110 env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
111 env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
112 env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
113 typeSpecFlags);
114 if (config != NULL) {
115 env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
116 }
117 return block;
118}
119
Mårten Kongstad48d22322014-01-31 14:43:27 +0100120// This is called by zygote (running as user root) as part of preloadResources.
121static void verifySystemIdmaps()
122{
123 pid_t pid;
124 char system_id[10];
125
126 snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
127
128 switch (pid = fork()) {
129 case -1:
130 ALOGE("failed to fork for idmap: %s", strerror(errno));
131 break;
132 case 0: // child
133 {
134 struct __user_cap_header_struct capheader;
135 struct __user_cap_data_struct capdata;
136
137 memset(&capheader, 0, sizeof(capheader));
138 memset(&capdata, 0, sizeof(capdata));
139
140 capheader.version = _LINUX_CAPABILITY_VERSION;
141 capheader.pid = 0;
142
143 if (capget(&capheader, &capdata) != 0) {
144 ALOGE("capget: %s\n", strerror(errno));
145 exit(1);
146 }
147
148 capdata.effective = capdata.permitted;
149 if (capset(&capheader, &capdata) != 0) {
150 ALOGE("capset: %s\n", strerror(errno));
151 exit(1);
152 }
153
154 if (setgid(AID_SYSTEM) != 0) {
155 ALOGE("setgid: %s\n", strerror(errno));
156 exit(1);
157 }
158
159 if (setuid(AID_SYSTEM) != 0) {
160 ALOGE("setuid: %s\n", strerror(errno));
161 exit(1);
162 }
163
164 execl(AssetManager::IDMAP_BIN, AssetManager::IDMAP_BIN, "--scan",
165 AssetManager::OVERLAY_DIR, AssetManager::TARGET_PACKAGE_NAME,
166 AssetManager::TARGET_APK_PATH, AssetManager::IDMAP_DIR, (char*)NULL);
167 ALOGE("failed to execl for idmap: %s", strerror(errno));
168 exit(1); // should never get here
169 }
170 break;
171 default: // parent
172 waitpid(pid, NULL, 0);
173 break;
174 }
175}
176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177// ----------------------------------------------------------------------------
178
179// this guy is exported to other jni routines
180AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
181{
Ashok Bhat896043d2014-01-17 16:02:38 +0000182 jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
183 AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 if (am != NULL) {
185 return am;
186 }
187 jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
188 return NULL;
189}
190
Ashok Bhat896043d2014-01-17 16:02:38 +0000191static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 jstring fileName, jint mode)
193{
194 AssetManager* am = assetManagerForJavaObject(env, clazz);
195 if (am == NULL) {
196 return 0;
197 }
198
Steve Block71f2cf12011-10-20 11:56:00 +0100199 ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200
Elliott Hughes69a017b2011-04-08 14:10:28 -0700201 ScopedUtfChars fileName8(env, fileName);
202 if (fileName8.c_str() == NULL) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000203 jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 return -1;
205 }
206
207 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
208 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700209 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 return -1;
211 }
212
Elliott Hughes69a017b2011-04-08 14:10:28 -0700213 Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214
215 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700216 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 return -1;
218 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219
220 //printf("Created Asset Stream: %p\n", a);
221
Ashok Bhat896043d2014-01-17 16:02:38 +0000222 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223}
224
225static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
226{
Kenny Rootddb76c42010-11-24 12:56:06 -0800227 off64_t startOffset, length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 int fd = a->openFileDescriptor(&startOffset, &length);
229 delete a;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 if (fd < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700232 jniThrowException(env, "java/io/FileNotFoundException",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 "This file can not be opened as a file descriptor; it is probably compressed");
234 return NULL;
235 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
238 if (offsets == NULL) {
239 close(fd);
240 return NULL;
241 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243 offsets[0] = startOffset;
244 offsets[1] = length;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700247
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700248 jobject fileDesc = jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 if (fileDesc == NULL) {
250 close(fd);
251 return NULL;
252 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 return newParcelFileDescriptor(env, fileDesc);
255}
256
257static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
258 jstring fileName, jlongArray outOffsets)
259{
260 AssetManager* am = assetManagerForJavaObject(env, clazz);
261 if (am == NULL) {
262 return NULL;
263 }
264
Steve Block71f2cf12011-10-20 11:56:00 +0100265 ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266
Elliott Hughes69a017b2011-04-08 14:10:28 -0700267 ScopedUtfChars fileName8(env, fileName);
268 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 return NULL;
270 }
271
Elliott Hughes69a017b2011-04-08 14:10:28 -0700272 Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273
274 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700275 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 return NULL;
277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278
279 //printf("Created Asset Stream: %p\n", a);
280
281 return returnParcelFileDescriptor(env, a, outOffsets);
282}
283
Ashok Bhat896043d2014-01-17 16:02:38 +0000284static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285 jint cookie,
286 jstring fileName,
287 jint mode)
288{
289 AssetManager* am = assetManagerForJavaObject(env, clazz);
290 if (am == NULL) {
291 return 0;
292 }
293
Steve Block71f2cf12011-10-20 11:56:00 +0100294 ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295
Elliott Hughes69a017b2011-04-08 14:10:28 -0700296 ScopedUtfChars fileName8(env, fileName);
297 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298 return -1;
299 }
300
301 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
302 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700303 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 return -1;
305 }
306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000308 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
309 (Asset::AccessMode)mode)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700310 : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311
312 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700313 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 return -1;
315 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316
317 //printf("Created Asset Stream: %p\n", a);
318
Ashok Bhat896043d2014-01-17 16:02:38 +0000319 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320}
321
322static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
323 jint cookie,
324 jstring fileName,
325 jlongArray outOffsets)
326{
327 AssetManager* am = assetManagerForJavaObject(env, clazz);
328 if (am == NULL) {
329 return NULL;
330 }
331
Steve Block71f2cf12011-10-20 11:56:00 +0100332 ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333
Elliott Hughes69a017b2011-04-08 14:10:28 -0700334 ScopedUtfChars fileName8(env, fileName);
335 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 return NULL;
337 }
338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000340 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700341 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342
343 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700344 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800345 return NULL;
346 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347
348 //printf("Created Asset Stream: %p\n", a);
349
350 return returnParcelFileDescriptor(env, a, outOffsets);
351}
352
353static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
354 jstring fileName)
355{
356 AssetManager* am = assetManagerForJavaObject(env, clazz);
357 if (am == NULL) {
358 return NULL;
359 }
360
Elliott Hughes69a017b2011-04-08 14:10:28 -0700361 ScopedUtfChars fileName8(env, fileName);
362 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 return NULL;
364 }
365
Elliott Hughes69a017b2011-04-08 14:10:28 -0700366 AssetDir* dir = am->openDir(fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800367
368 if (dir == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700369 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 return NULL;
371 }
372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800373 size_t N = dir->getFileCount();
374
375 jobjectArray array = env->NewObjectArray(dir->getFileCount(),
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +0100376 g_stringClass, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 delete dir;
379 return NULL;
380 }
381
382 for (size_t i=0; i<N; i++) {
383 const String8& name = dir->getFileName(i);
384 jstring str = env->NewStringUTF(name.string());
385 if (str == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 delete dir;
387 return NULL;
388 }
389 env->SetObjectArrayElement(array, i, str);
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700390 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 }
392
393 delete dir;
394
395 return array;
396}
397
398static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000399 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400{
Ashok Bhat896043d2014-01-17 16:02:38 +0000401 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402
403 //printf("Destroying Asset Stream: %p\n", a);
404
405 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700406 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 return;
408 }
409
410 delete a;
411}
412
413static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000414 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415{
Ashok Bhat896043d2014-01-17 16:02:38 +0000416 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417
418 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700419 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420 return -1;
421 }
422
423 uint8_t b;
424 ssize_t res = a->read(&b, 1);
425 return res == 1 ? b : -1;
426}
427
428static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000429 jlong assetHandle, jbyteArray bArray,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430 jint off, jint len)
431{
Ashok Bhat896043d2014-01-17 16:02:38 +0000432 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433
434 if (a == NULL || bArray == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700435 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 return -1;
437 }
438
439 if (len == 0) {
440 return 0;
441 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 jsize bLen = env->GetArrayLength(bArray);
444 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700445 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 return -1;
447 }
448
449 jbyte* b = env->GetByteArrayElements(bArray, NULL);
450 ssize_t res = a->read(b+off, len);
451 env->ReleaseByteArrayElements(bArray, b, 0);
452
Ashok Bhat896043d2014-01-17 16:02:38 +0000453 if (res > 0) return static_cast<jint>(res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454
455 if (res < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700456 jniThrowException(env, "java/io/IOException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 }
458 return -1;
459}
460
461static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000462 jlong assetHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 jlong offset, jint whence)
464{
Ashok Bhat896043d2014-01-17 16:02:38 +0000465 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466
467 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700468 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800469 return -1;
470 }
471
472 return a->seek(
473 offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
474}
475
476static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000477 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478{
Ashok Bhat896043d2014-01-17 16:02:38 +0000479 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480
481 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700482 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800483 return -1;
484 }
485
486 return a->getLength();
487}
488
489static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000490 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800491{
Ashok Bhat896043d2014-01-17 16:02:38 +0000492 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493
494 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700495 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800496 return -1;
497 }
498
499 return a->getRemainingLength();
500}
501
502static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
503 jstring path)
504{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700505 ScopedUtfChars path8(env, path);
506 if (path8.c_str() == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800507 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508 }
509
510 AssetManager* am = assetManagerForJavaObject(env, clazz);
511 if (am == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800512 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800513 }
514
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000515 int32_t cookie;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700516 bool res = am->addAssetPath(String8(path8.c_str()), &cookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800517
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000518 return (res) ? static_cast<jint>(cookie) : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519}
520
Mårten Kongstad48d22322014-01-31 14:43:27 +0100521static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
522 jstring idmapPath)
523{
524 ScopedUtfChars idmapPath8(env, idmapPath);
525 if (idmapPath8.c_str() == NULL) {
526 return 0;
527 }
528
529 AssetManager* am = assetManagerForJavaObject(env, clazz);
530 if (am == NULL) {
531 return 0;
532 }
533
534 int32_t cookie;
535 bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
536
537 return (res) ? (jint)cookie : 0;
538}
539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
541{
542 AssetManager* am = assetManagerForJavaObject(env, clazz);
543 if (am == NULL) {
544 return JNI_TRUE;
545 }
546 return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
547}
548
549static void android_content_AssetManager_setLocale(JNIEnv* env, jobject clazz,
550 jstring locale)
551{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700552 ScopedUtfChars locale8(env, locale);
553 if (locale8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 return;
555 }
556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 AssetManager* am = assetManagerForJavaObject(env, clazz);
558 if (am == NULL) {
559 return;
560 }
561
Elliott Hughes69a017b2011-04-08 14:10:28 -0700562 am->setLocale(locale8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563}
564
565static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
566{
567 Vector<String8> locales;
568
569 AssetManager* am = assetManagerForJavaObject(env, clazz);
570 if (am == NULL) {
571 return NULL;
572 }
573
574 am->getLocales(&locales);
575
576 const int N = locales.size();
577
578 jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
579 if (result == NULL) {
580 return NULL;
581 }
582
583 for (int i=0; i<N; i++) {
Gilles Debunne0db187a2010-08-27 11:51:34 -0700584 jstring str = env->NewStringUTF(locales[i].string());
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700585 if (str == NULL) {
586 return NULL;
587 }
588 env->SetObjectArrayElement(result, i, str);
589 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590 }
591
592 return result;
593}
594
595static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
596 jint mcc, jint mnc,
597 jstring locale, jint orientation,
598 jint touchscreen, jint density,
599 jint keyboard, jint keyboardHidden,
600 jint navigation,
601 jint screenWidth, jint screenHeight,
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700602 jint smallestScreenWidthDp,
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700603 jint screenWidthDp, jint screenHeightDp,
Tobias Haamel27b28b32010-02-09 23:09:17 +0100604 jint screenLayout, jint uiMode,
605 jint sdkVersion)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800606{
607 AssetManager* am = assetManagerForJavaObject(env, clazz);
608 if (am == NULL) {
609 return;
610 }
611
612 ResTable_config config;
613 memset(&config, 0, sizeof(config));
Elliott Hughes69a017b2011-04-08 14:10:28 -0700614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800615 const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800617 config.mcc = (uint16_t)mcc;
618 config.mnc = (uint16_t)mnc;
619 config.orientation = (uint8_t)orientation;
620 config.touchscreen = (uint8_t)touchscreen;
621 config.density = (uint16_t)density;
622 config.keyboard = (uint8_t)keyboard;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700623 config.inputFlags = (uint8_t)keyboardHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624 config.navigation = (uint8_t)navigation;
625 config.screenWidth = (uint16_t)screenWidth;
626 config.screenHeight = (uint16_t)screenHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700627 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700628 config.screenWidthDp = (uint16_t)screenWidthDp;
629 config.screenHeightDp = (uint16_t)screenHeightDp;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700630 config.screenLayout = (uint8_t)screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100631 config.uiMode = (uint8_t)uiMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800632 config.sdkVersion = (uint16_t)sdkVersion;
633 config.minorVersion = 0;
634 am->setConfiguration(config, locale8);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
637}
638
639static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
640 jstring name,
641 jstring defType,
642 jstring defPackage)
643{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700644 ScopedStringChars name16(env, name);
645 if (name16.get() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800646 return 0;
647 }
648
649 AssetManager* am = assetManagerForJavaObject(env, clazz);
650 if (am == NULL) {
651 return 0;
652 }
653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800654 const char16_t* defType16 = defType
655 ? env->GetStringChars(defType, NULL) : NULL;
656 jsize defTypeLen = defType
657 ? env->GetStringLength(defType) : 0;
658 const char16_t* defPackage16 = defPackage
659 ? env->GetStringChars(defPackage, NULL) : NULL;
660 jsize defPackageLen = defPackage
661 ? env->GetStringLength(defPackage) : 0;
662
663 jint ident = am->getResources().identifierForName(
Elliott Hughes69a017b2011-04-08 14:10:28 -0700664 name16.get(), name16.size(), defType16, defTypeLen, defPackage16, defPackageLen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800665
666 if (defPackage16) {
667 env->ReleaseStringChars(defPackage, defPackage16);
668 }
669 if (defType16) {
670 env->ReleaseStringChars(defType, defType16);
671 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672
673 return ident;
674}
675
676static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
677 jint resid)
678{
679 AssetManager* am = assetManagerForJavaObject(env, clazz);
680 if (am == NULL) {
681 return NULL;
682 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700685 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800686 return NULL;
687 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689 String16 str;
690 if (name.package != NULL) {
691 str.setTo(name.package, name.packageLen);
692 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700693 if (name.type8 != NULL || name.type != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 if (str.size() > 0) {
695 char16_t div = ':';
696 str.append(&div, 1);
697 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700698 if (name.type8 != NULL) {
699 str.append(String16(name.type8, name.typeLen));
700 } else {
701 str.append(name.type, name.typeLen);
702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800703 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700704 if (name.name8 != NULL || name.name != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705 if (str.size() > 0) {
706 char16_t div = '/';
707 str.append(&div, 1);
708 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700709 if (name.name8 != NULL) {
710 str.append(String16(name.name8, name.nameLen));
711 } else {
712 str.append(name.name, name.nameLen);
713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800714 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 return env->NewString((const jchar*)str.string(), str.size());
717}
718
719static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
720 jint resid)
721{
722 AssetManager* am = assetManagerForJavaObject(env, clazz);
723 if (am == NULL) {
724 return NULL;
725 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800727 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700728 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 return NULL;
730 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 if (name.package != NULL) {
733 return env->NewString((const jchar*)name.package, name.packageLen);
734 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736 return NULL;
737}
738
739static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
740 jint resid)
741{
742 AssetManager* am = assetManagerForJavaObject(env, clazz);
743 if (am == NULL) {
744 return NULL;
745 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700746
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700748 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800749 return NULL;
750 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700751
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700752 if (name.type8 != NULL) {
753 return env->NewStringUTF(name.type8);
754 }
755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 if (name.type != NULL) {
757 return env->NewString((const jchar*)name.type, name.typeLen);
758 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 return NULL;
761}
762
763static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
764 jint resid)
765{
766 AssetManager* am = assetManagerForJavaObject(env, clazz);
767 if (am == NULL) {
768 return NULL;
769 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700770
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800771 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700772 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773 return NULL;
774 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700775
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700776 if (name.name8 != NULL) {
777 return env->NewStringUTF(name.name8);
778 }
779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 if (name.name != NULL) {
781 return env->NewString((const jchar*)name.name, name.nameLen);
782 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 return NULL;
785}
786
787static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
788 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700789 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790 jobject outValue,
791 jboolean resolve)
792{
Dianne Hackborn1f7d3072013-02-11 17:03:32 -0800793 if (outValue == NULL) {
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800794 jniThrowNullPointerException(env, "outValue");
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700795 return 0;
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800796 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 AssetManager* am = assetManagerForJavaObject(env, clazz);
798 if (am == NULL) {
799 return 0;
800 }
801 const ResTable& res(am->getResources());
802
803 Res_value value;
804 ResTable_config config;
805 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700806 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800807 if (kThrowOnBadId) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800808 if (block == BAD_INDEX) {
809 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
810 return 0;
811 }
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800812 }
813 uint32_t ref = ident;
814 if (resolve) {
815 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
816 if (kThrowOnBadId) {
817 if (block == BAD_INDEX) {
818 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
819 return 0;
820 }
821 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800822 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000823 if (block >= 0) {
824 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
825 }
826
827 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828}
829
830static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
831 jint ident, jint bagEntryId,
832 jobject outValue, jboolean resolve)
833{
834 AssetManager* am = assetManagerForJavaObject(env, clazz);
835 if (am == NULL) {
836 return 0;
837 }
838 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 // Now lock down the resource object and start pulling stuff from it.
841 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -0700842
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800843 ssize_t block = -1;
844 Res_value value;
845
846 const ResTable::bag_entry* entry = NULL;
847 uint32_t typeSpecFlags;
848 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
849
850 for (ssize_t i=0; i<entryCount; i++) {
851 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
852 block = entry->stringBlock;
853 value = entry->map.value;
854 }
855 entry++;
856 }
857
858 res.unlock();
859
860 if (block < 0) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000861 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800862 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 uint32_t ref = ident;
865 if (resolve) {
866 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800867 if (kThrowOnBadId) {
868 if (block == BAD_INDEX) {
869 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
870 return 0;
871 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800872 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000874 if (block >= 0) {
875 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
876 }
877
878 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879}
880
881static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
882{
883 AssetManager* am = assetManagerForJavaObject(env, clazz);
884 if (am == NULL) {
885 return 0;
886 }
887 return am->getResources().getTableCount();
888}
889
Ashok Bhat896043d2014-01-17 16:02:38 +0000890static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800891 jint block)
892{
893 AssetManager* am = assetManagerForJavaObject(env, clazz);
894 if (am == NULL) {
895 return 0;
896 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000897 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800898}
899
900static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
901 jint cookie)
902{
903 AssetManager* am = assetManagerForJavaObject(env, clazz);
904 if (am == NULL) {
905 return NULL;
906 }
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000907 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800908 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700909 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 return NULL;
911 }
912 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913 return str;
914}
915
Adam Lesinskide898ff2014-01-29 18:20:45 -0800916static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
917{
918 AssetManager* am = assetManagerForJavaObject(env, clazz);
919 if (am == NULL) {
920 return 0;
921 }
922
923 const ResTable& res = am->getResources();
924
925 jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
926 gSparseArrayOffsets.constructor);
927 const size_t N = res.getBasePackageCount();
928 for (size_t i = 0; i < N; i++) {
929 const String16 name = res.getBasePackageName(i);
930 env->CallVoidMethod(sparseArray, gSparseArrayOffsets.put, (jint) res.getBasePackageId(i),
931 env->NewString(name, name.size()));
932 }
933 return sparseArray;
934}
935
Ashok Bhat896043d2014-01-17 16:02:38 +0000936static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800937{
938 AssetManager* am = assetManagerForJavaObject(env, clazz);
939 if (am == NULL) {
940 return 0;
941 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000942 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800943}
944
945static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000946 jlong themeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947{
Ashok Bhat896043d2014-01-17 16:02:38 +0000948 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800949 delete theme;
950}
951
952static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000953 jlong themeHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 jint styleRes,
955 jboolean force)
956{
Ashok Bhat896043d2014-01-17 16:02:38 +0000957 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800958 theme->applyStyle(styleRes, force ? true : false);
959}
960
961static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000962 jlong destHandle, jlong srcHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800963{
Ashok Bhat896043d2014-01-17 16:02:38 +0000964 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
965 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800966 dest->setTo(*src);
967}
968
969static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +0000970 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971{
Ashok Bhat896043d2014-01-17 16:02:38 +0000972 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 const ResTable& res(theme->getResTable());
974
975 Res_value value;
976 // XXX value could be different in different configs!
977 uint32_t typeSpecFlags = 0;
978 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
979 uint32_t ref = 0;
980 if (resolve) {
981 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800982 if (kThrowOnBadId) {
983 if (block == BAD_INDEX) {
984 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
985 return 0;
986 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800987 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 }
989 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
990}
991
992static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000993 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 jstring tag, jstring prefix)
995{
Ashok Bhat896043d2014-01-17 16:02:38 +0000996 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 const ResTable& res(theme->getResTable());
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800998 (void)res;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700999
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 // XXX Need to use params.
1001 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002}
1003
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001004class XmlAttributeFinder : public BackTrackingAttributeFinder<XmlAttributeFinder, jsize> {
1005public:
1006 XmlAttributeFinder(const ResXMLParser* parser)
1007 : BackTrackingAttributeFinder(0, parser != NULL ? parser->getAttributeCount() : 0)
1008 , mParser(parser) {}
1009
1010 inline uint32_t getAttribute(jsize index) const {
1011 return mParser->getAttributeNameResID(index);
1012 }
1013
1014private:
1015 const ResXMLParser* mParser;
1016};
1017
1018class BagAttributeFinder : public BackTrackingAttributeFinder<BagAttributeFinder, const ResTable::bag_entry*> {
1019public:
1020 BagAttributeFinder(const ResTable::bag_entry* start, const ResTable::bag_entry* end)
1021 : BackTrackingAttributeFinder(start, end) {}
1022
1023 inline uint32_t getAttribute(const ResTable::bag_entry* entry) const {
1024 return entry->map.name.ident;
1025 }
1026};
1027
Alan Viverette52b999f2014-03-24 18:00:26 -07001028static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1029 jlong themeToken,
1030 jint defStyleAttr,
1031 jint defStyleRes,
1032 jintArray inValues,
1033 jintArray attrs,
1034 jintArray outValues,
1035 jintArray outIndices)
1036{
1037 if (themeToken == 0) {
1038 jniThrowNullPointerException(env, "theme token");
1039 return JNI_FALSE;
1040 }
1041 if (attrs == NULL) {
1042 jniThrowNullPointerException(env, "attrs");
1043 return JNI_FALSE;
1044 }
1045 if (outValues == NULL) {
1046 jniThrowNullPointerException(env, "out values");
1047 return JNI_FALSE;
1048 }
1049
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001050 if (kDebugStyles) {
1051 ALOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x",
1052 themeToken, defStyleAttr, defStyleRes);
1053 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001054
1055 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1056 const ResTable& res = theme->getResTable();
1057 ResTable_config config;
1058 Res_value value;
1059
1060 const jsize NI = env->GetArrayLength(attrs);
1061 const jsize NV = env->GetArrayLength(outValues);
1062 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1063 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1064 return JNI_FALSE;
1065 }
1066
1067 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1068 if (src == NULL) {
1069 return JNI_FALSE;
1070 }
1071
1072 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1073 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1074
1075 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1076 jint* dest = baseDest;
1077 if (dest == NULL) {
1078 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1079 return JNI_FALSE;
1080 }
1081
1082 jint* indices = NULL;
1083 int indicesIdx = 0;
1084 if (outIndices != NULL) {
1085 if (env->GetArrayLength(outIndices) > NI) {
1086 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1087 }
1088 }
1089
1090 // Load default style from attribute, if specified...
1091 uint32_t defStyleBagTypeSetFlags = 0;
1092 if (defStyleAttr != 0) {
1093 Res_value value;
1094 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1095 if (value.dataType == Res_value::TYPE_REFERENCE) {
1096 defStyleRes = value.data;
1097 }
1098 }
1099 }
1100
1101 // Now lock down the resource object and start pulling stuff from it.
1102 res.lock();
1103
1104 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001105 const ResTable::bag_entry* defStyleStart = NULL;
Alan Viverette52b999f2014-03-24 18:00:26 -07001106 uint32_t defStyleTypeSetFlags = 0;
1107 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001108 ? res.getBagLocked(defStyleRes, &defStyleStart, &defStyleTypeSetFlags) : -1;
Alan Viverette52b999f2014-03-24 18:00:26 -07001109 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001110 const ResTable::bag_entry* const defStyleEnd = defStyleStart + (bagOff >= 0 ? bagOff : 0);
1111 BagAttributeFinder defStyleAttrFinder(defStyleStart, defStyleEnd);
Alan Viverette52b999f2014-03-24 18:00:26 -07001112
1113 // Now iterate through all of the attributes that the client has requested,
1114 // filling in each with whatever data we can find.
1115 ssize_t block = 0;
1116 uint32_t typeSetFlags;
1117 for (jsize ii=0; ii<NI; ii++) {
1118 const uint32_t curIdent = (uint32_t)src[ii];
1119
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001120 if (kDebugStyles) {
1121 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1122 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001123
1124 // Try to find a value for this attribute... we prioritize values
1125 // coming from, first XML attributes, then XML style, then default
1126 // style, and finally the theme.
1127 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001128 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001129 typeSetFlags = 0;
1130 config.density = 0;
1131
1132 // Retrieve the current input value if available.
1133 if (NSV > 0 && srcValues[ii] != 0) {
1134 block = -1;
1135 value.dataType = Res_value::TYPE_ATTRIBUTE;
1136 value.data = srcValues[ii];
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001137 if (kDebugStyles) {
1138 ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
1139 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001140 }
1141
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001142 if (value.dataType == Res_value::TYPE_NULL) {
1143 const ResTable::bag_entry* const defStyleEntry = defStyleAttrFinder.find(curIdent);
1144 if (defStyleEntry != defStyleEnd) {
1145 block = defStyleEntry->stringBlock;
Alan Viverette52b999f2014-03-24 18:00:26 -07001146 typeSetFlags = defStyleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001147 value = defStyleEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001148 if (kDebugStyles) {
1149 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1150 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001151 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001152 }
1153
1154 uint32_t resid = 0;
1155 if (value.dataType != Res_value::TYPE_NULL) {
1156 // Take care of resolving the found resource to its final value.
1157 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1158 &resid, &typeSetFlags, &config);
1159 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001160 if (kDebugStyles) {
1161 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1162 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001163 } else {
1164 // If we still don't have a value for this attribute, try to find
1165 // it in the theme!
1166 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1167 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001168 if (kDebugStyles) {
1169 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1170 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001171 newBlock = res.resolveReference(&value, block, &resid,
1172 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001173 if (kThrowOnBadId) {
1174 if (newBlock == BAD_INDEX) {
1175 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1176 return JNI_FALSE;
1177 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001178 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001179 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001180 if (kDebugStyles) {
1181 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1182 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001183 }
1184 }
1185
1186 // Deal with the special @null value -- it turns back to TYPE_NULL.
1187 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001188 if (kDebugStyles) {
1189 ALOGI("-> Setting to @null!");
1190 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001191 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001192 value.data = Res_value::DATA_NULL_UNDEFINED;
Alan Viverette52b999f2014-03-24 18:00:26 -07001193 block = -1;
1194 }
1195
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001196 if (kDebugStyles) {
1197 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
1198 value.data);
1199 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001200
1201 // Write the final value back to Java.
1202 dest[STYLE_TYPE] = value.dataType;
1203 dest[STYLE_DATA] = value.data;
1204 dest[STYLE_ASSET_COOKIE] =
1205 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1206 dest[STYLE_RESOURCE_ID] = resid;
1207 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1208 dest[STYLE_DENSITY] = config.density;
1209
1210 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1211 indicesIdx++;
1212 indices[indicesIdx] = ii;
1213 }
1214
1215 dest += STYLE_NUM_ENTRIES;
1216 }
1217
1218 res.unlock();
1219
1220 if (indices != NULL) {
1221 indices[0] = indicesIdx;
1222 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1223 }
1224 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1225 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1226 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1227
1228 return JNI_TRUE;
1229}
1230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001232 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001233 jint defStyleAttr,
1234 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +00001235 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001236 jintArray attrs,
1237 jintArray outValues,
1238 jintArray outIndices)
1239{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001240 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001241 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001242 return JNI_FALSE;
1243 }
1244 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001245 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001246 return JNI_FALSE;
1247 }
1248 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001249 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001250 return JNI_FALSE;
1251 }
1252
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001253 if (kDebugStyles) {
1254 ALOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x xml=0x%x",
1255 themeToken, defStyleAttr, defStyleRes, xmlParserToken);
1256 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001257
Ashok Bhat896043d2014-01-17 16:02:38 +00001258 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001260 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001261 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001262 Res_value value;
1263
1264 const jsize NI = env->GetArrayLength(attrs);
1265 const jsize NV = env->GetArrayLength(outValues);
1266 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001267 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001268 return JNI_FALSE;
1269 }
1270
1271 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1272 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001273 return JNI_FALSE;
1274 }
1275
1276 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1277 jint* dest = baseDest;
1278 if (dest == NULL) {
1279 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001280 return JNI_FALSE;
1281 }
1282
1283 jint* indices = NULL;
1284 int indicesIdx = 0;
1285 if (outIndices != NULL) {
1286 if (env->GetArrayLength(outIndices) > NI) {
1287 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1288 }
1289 }
1290
1291 // Load default style from attribute, if specified...
1292 uint32_t defStyleBagTypeSetFlags = 0;
1293 if (defStyleAttr != 0) {
1294 Res_value value;
1295 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1296 if (value.dataType == Res_value::TYPE_REFERENCE) {
1297 defStyleRes = value.data;
1298 }
1299 }
1300 }
1301
1302 // Retrieve the style class associated with the current XML tag.
1303 int style = 0;
1304 uint32_t styleBagTypeSetFlags = 0;
1305 if (xmlParser != NULL) {
1306 ssize_t idx = xmlParser->indexOfStyle();
1307 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1308 if (value.dataType == value.TYPE_ATTRIBUTE) {
1309 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1310 value.dataType = Res_value::TYPE_NULL;
1311 }
1312 }
1313 if (value.dataType == value.TYPE_REFERENCE) {
1314 style = value.data;
1315 }
1316 }
1317 }
1318
1319 // Now lock down the resource object and start pulling stuff from it.
1320 res.lock();
1321
1322 // Retrieve the default style bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001323 const ResTable::bag_entry* defStyleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001324 uint32_t defStyleTypeSetFlags = 0;
1325 ssize_t bagOff = defStyleRes != 0
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001326 ? res.getBagLocked(defStyleRes, &defStyleAttrStart, &defStyleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001327 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001328 const ResTable::bag_entry* const defStyleAttrEnd = defStyleAttrStart + (bagOff >= 0 ? bagOff : 0);
1329 BagAttributeFinder defStyleAttrFinder(defStyleAttrStart, defStyleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330
1331 // Retrieve the style class bag, if requested.
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001332 const ResTable::bag_entry* styleAttrStart = NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001333 uint32_t styleTypeSetFlags = 0;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001334 bagOff = style != 0 ? res.getBagLocked(style, &styleAttrStart, &styleTypeSetFlags) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001335 styleTypeSetFlags |= styleBagTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001336 const ResTable::bag_entry* const styleAttrEnd = styleAttrStart + (bagOff >= 0 ? bagOff : 0);
1337 BagAttributeFinder styleAttrFinder(styleAttrStart, styleAttrEnd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001338
1339 // Retrieve the XML attributes, if requested.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001340 static const ssize_t kXmlBlock = 0x10000000;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001341 XmlAttributeFinder xmlAttrFinder(xmlParser);
1342 const jsize xmlAttrEnd = xmlParser != NULL ? xmlParser->getAttributeCount() : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001343
1344 // Now iterate through all of the attributes that the client has requested,
1345 // filling in each with whatever data we can find.
1346 ssize_t block = 0;
1347 uint32_t typeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001348 for (jsize ii = 0; ii < NI; ii++) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349 const uint32_t curIdent = (uint32_t)src[ii];
1350
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001351 if (kDebugStyles) {
1352 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1353 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001355 // Try to find a value for this attribute... we prioritize values
1356 // coming from, first XML attributes, then XML style, then default
1357 // style, and finally the theme.
1358 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001359 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001360 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001361 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001363 // Walk through the xml attributes looking for the requested attribute.
1364 const jsize xmlAttrIdx = xmlAttrFinder.find(curIdent);
1365 if (xmlAttrIdx != xmlAttrEnd) {
1366 // We found the attribute we were looking for.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001367 block = kXmlBlock;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001368 xmlParser->getAttributeValue(xmlAttrIdx, &value);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001369 if (kDebugStyles) {
1370 ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
1371 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 }
1373
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001374 if (value.dataType == Res_value::TYPE_NULL) {
1375 // Walk through the style class values looking for the requested attribute.
1376 const ResTable::bag_entry* const styleAttrEntry = styleAttrFinder.find(curIdent);
1377 if (styleAttrEntry != styleAttrEnd) {
1378 // We found the attribute we were looking for.
1379 block = styleAttrEntry->stringBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001380 typeSetFlags = styleTypeSetFlags;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001381 value = styleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001382 if (kDebugStyles) {
1383 ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
1384 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001386 }
1387
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001388 if (value.dataType == Res_value::TYPE_NULL) {
1389 // Walk through the default style values looking for the requested attribute.
1390 const ResTable::bag_entry* const defStyleAttrEntry = defStyleAttrFinder.find(curIdent);
1391 if (defStyleAttrEntry != defStyleAttrEnd) {
1392 // We found the attribute we were looking for.
1393 block = defStyleAttrEntry->stringBlock;
1394 typeSetFlags = styleTypeSetFlags;
1395 value = defStyleAttrEntry->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001396 if (kDebugStyles) {
1397 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1398 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001399 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001400 }
1401
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 uint32_t resid = 0;
1403 if (value.dataType != Res_value::TYPE_NULL) {
1404 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001405 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1406 &resid, &typeSetFlags, &config);
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001407 if (newBlock >= 0) {
1408 block = newBlock;
1409 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001410
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001411 if (kDebugStyles) {
1412 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1413 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001414 } else {
1415 // If we still don't have a value for this attribute, try to find
1416 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001417 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1418 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001419 if (kDebugStyles) {
1420 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1421 }
Dianne Hackborn0d221012009-07-29 15:41:19 -07001422 newBlock = res.resolveReference(&value, block, &resid,
1423 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001424 if (kThrowOnBadId) {
1425 if (newBlock == BAD_INDEX) {
1426 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1427 return JNI_FALSE;
1428 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001429 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001430
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001431 if (newBlock >= 0) {
1432 block = newBlock;
1433 }
Adam Lesinski11bdd5b2014-11-17 12:17:16 -08001434
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001435 if (kDebugStyles) {
1436 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1437 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001438 }
1439 }
1440
1441 // Deal with the special @null value -- it turns back to TYPE_NULL.
1442 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001443 if (kDebugStyles) {
1444 ALOGI("-> Setting to @null!");
1445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001446 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001447 value.data = Res_value::DATA_NULL_UNDEFINED;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001448 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001449 }
1450
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001451 if (kDebugStyles) {
1452 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
1453 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454
1455 // Write the final value back to Java.
1456 dest[STYLE_TYPE] = value.dataType;
1457 dest[STYLE_DATA] = value.data;
Adam Lesinskia7d1d732014-10-01 18:24:54 -07001458 dest[STYLE_ASSET_COOKIE] = block != kXmlBlock ?
1459 static_cast<jint>(res.getTableCookie(block)) : -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 dest[STYLE_RESOURCE_ID] = resid;
1461 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001462 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001464 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1465 indicesIdx++;
1466 indices[indicesIdx] = ii;
1467 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 dest += STYLE_NUM_ENTRIES;
1470 }
1471
1472 res.unlock();
1473
1474 if (indices != NULL) {
1475 indices[0] = indicesIdx;
1476 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1477 }
1478 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1479 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1480
1481 return JNI_TRUE;
1482}
1483
1484static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001485 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 jintArray attrs,
1487 jintArray outValues,
1488 jintArray outIndices)
1489{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001490 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001491 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001492 return JNI_FALSE;
1493 }
1494 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001495 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001496 return JNI_FALSE;
1497 }
1498 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001499 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 return JNI_FALSE;
1501 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001503 AssetManager* am = assetManagerForJavaObject(env, clazz);
1504 if (am == NULL) {
1505 return JNI_FALSE;
1506 }
1507 const ResTable& res(am->getResources());
1508 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001509 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001511
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 const jsize NI = env->GetArrayLength(attrs);
1513 const jsize NV = env->GetArrayLength(outValues);
1514 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001515 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 return JNI_FALSE;
1517 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1520 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001521 return JNI_FALSE;
1522 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001524 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1525 jint* dest = baseDest;
1526 if (dest == NULL) {
1527 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528 return JNI_FALSE;
1529 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 jint* indices = NULL;
1532 int indicesIdx = 0;
1533 if (outIndices != NULL) {
1534 if (env->GetArrayLength(outIndices) > NI) {
1535 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1536 }
1537 }
1538
1539 // Now lock down the resource object and start pulling stuff from it.
1540 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 // Retrieve the XML attributes, if requested.
1543 const jsize NX = xmlParser->getAttributeCount();
1544 jsize ix=0;
1545 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001546
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001547 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 // Now iterate through all of the attributes that the client has requested,
1550 // filling in each with whatever data we can find.
1551 ssize_t block = 0;
1552 uint32_t typeSetFlags;
1553 for (jsize ii=0; ii<NI; ii++) {
1554 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001556 // Try to find a value for this attribute...
1557 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001558 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001560 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001562 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001563 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001564 ix++;
1565 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1566 }
1567 // Retrieve the current XML attribute if it matches, and step to next.
1568 if (ix < NX && curIdent == curXmlAttr) {
1569 block = kXmlBlock;
1570 xmlParser->getAttributeValue(ix, &value);
1571 ix++;
1572 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1573 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001574
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1576 uint32_t resid = 0;
1577 if (value.dataType != Res_value::TYPE_NULL) {
1578 // Take care of resolving the found resource to its final value.
1579 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001580 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1581 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001582 if (kThrowOnBadId) {
1583 if (newBlock == BAD_INDEX) {
1584 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1585 return JNI_FALSE;
1586 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001587 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001588 if (newBlock >= 0) block = newBlock;
1589 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 // Deal with the special @null value -- it turns back to TYPE_NULL.
1592 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1593 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001594 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001597 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 // Write the final value back to Java.
1600 dest[STYLE_TYPE] = value.dataType;
1601 dest[STYLE_DATA] = value.data;
1602 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001603 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001604 dest[STYLE_RESOURCE_ID] = resid;
1605 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001606 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001608 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1609 indicesIdx++;
1610 indices[indicesIdx] = ii;
1611 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 dest += STYLE_NUM_ENTRIES;
1614 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001615
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001616 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 if (indices != NULL) {
1619 indices[0] = indicesIdx;
1620 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1621 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1624 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001625
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001626 return JNI_TRUE;
1627}
1628
1629static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1630 jint id)
1631{
1632 AssetManager* am = assetManagerForJavaObject(env, clazz);
1633 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001634 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 }
1636 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638 res.lock();
1639 const ResTable::bag_entry* defStyleEnt = NULL;
1640 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1641 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001642
Ashok Bhat896043d2014-01-17 16:02:38 +00001643 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001644}
1645
1646static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1647 jint id,
1648 jintArray outValues)
1649{
1650 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001651 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 return JNI_FALSE;
1653 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001655 AssetManager* am = assetManagerForJavaObject(env, clazz);
1656 if (am == NULL) {
1657 return JNI_FALSE;
1658 }
1659 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001660 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001661 Res_value value;
1662 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001663
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001664 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001666 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1667 jint* dest = baseDest;
1668 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001669 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 return JNI_FALSE;
1671 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 // Now lock down the resource object and start pulling stuff from it.
1674 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676 const ResTable::bag_entry* arrayEnt = NULL;
1677 uint32_t arrayTypeSetFlags = 0;
1678 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1679 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1680 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001681
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 int i = 0;
1683 uint32_t typeSetFlags;
1684 while (i < NV && arrayEnt < endArrayEnt) {
1685 block = arrayEnt->stringBlock;
1686 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001687 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 uint32_t resid = 0;
1691 if (value.dataType != Res_value::TYPE_NULL) {
1692 // Take care of resolving the found resource to its final value.
1693 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001694 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1695 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001696 if (kThrowOnBadId) {
1697 if (newBlock == BAD_INDEX) {
1698 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1699 return JNI_FALSE;
1700 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001701 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 if (newBlock >= 0) block = newBlock;
1703 }
1704
1705 // Deal with the special @null value -- it turns back to TYPE_NULL.
1706 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1707 value.dataType = Res_value::TYPE_NULL;
Alan Viverettef2969402014-10-29 17:09:36 -07001708 value.data = Res_value::DATA_NULL_UNDEFINED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 }
1710
1711 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1712
1713 // Write the final value back to Java.
1714 dest[STYLE_TYPE] = value.dataType;
1715 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001716 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001717 dest[STYLE_RESOURCE_ID] = resid;
1718 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001719 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 dest += STYLE_NUM_ENTRIES;
1721 i+= STYLE_NUM_ENTRIES;
1722 arrayEnt++;
1723 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001724
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001725 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001727 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001728
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001729 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 return i;
1732}
1733
Ashok Bhat896043d2014-01-17 16:02:38 +00001734static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001735 jint cookie,
1736 jstring fileName)
1737{
1738 AssetManager* am = assetManagerForJavaObject(env, clazz);
1739 if (am == NULL) {
1740 return 0;
1741 }
1742
Steve Block71f2cf12011-10-20 11:56:00 +01001743 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001744
Elliott Hughes69a017b2011-04-08 14:10:28 -07001745 ScopedUtfChars fileName8(env, fileName);
1746 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747 return 0;
1748 }
1749
Adam Lesinskide898ff2014-01-29 18:20:45 -08001750 int32_t assetCookie = static_cast<int32_t>(cookie);
1751 Asset* a = assetCookie
1752 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1753 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001754
1755 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001756 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001757 return 0;
1758 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001759
Adam Lesinskide898ff2014-01-29 18:20:45 -08001760 const DynamicRefTable* dynamicRefTable =
1761 am->getResources().getDynamicRefTableForCookie(assetCookie);
1762 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001763 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1764 a->close();
1765 delete a;
1766
1767 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001768 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001769 return 0;
1770 }
1771
Ashok Bhat896043d2014-01-17 16:02:38 +00001772 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001773}
1774
1775static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1776 jint arrayResId)
1777{
1778 AssetManager* am = assetManagerForJavaObject(env, clazz);
1779 if (am == NULL) {
1780 return NULL;
1781 }
1782 const ResTable& res(am->getResources());
1783
1784 const ResTable::bag_entry* startOfBag;
1785 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1786 if (N < 0) {
1787 return NULL;
1788 }
1789
1790 jintArray array = env->NewIntArray(N * 2);
1791 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 res.unlockBag(startOfBag);
1793 return NULL;
1794 }
1795
1796 Res_value value;
1797 const ResTable::bag_entry* bag = startOfBag;
1798 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1799 jint stringIndex = -1;
1800 jint stringBlock = 0;
1801 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001803 // Take care of resolving the found resource to its final value.
1804 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1805 if (value.dataType == Res_value::TYPE_STRING) {
1806 stringIndex = value.data;
1807 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001808
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001809 if (kThrowOnBadId) {
1810 if (stringBlock == BAD_INDEX) {
1811 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1812 return array;
1813 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001814 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001816 //todo: It might be faster to allocate a C array to contain
1817 // the blocknums and indices, put them in there and then
1818 // do just one SetIntArrayRegion()
1819 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1820 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1821 j = j + 2;
1822 }
1823 res.unlockBag(startOfBag);
1824 return array;
1825}
1826
1827static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1828 jint arrayResId)
1829{
1830 AssetManager* am = assetManagerForJavaObject(env, clazz);
1831 if (am == NULL) {
1832 return NULL;
1833 }
1834 const ResTable& res(am->getResources());
1835
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001836 const ResTable::bag_entry* startOfBag;
1837 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1838 if (N < 0) {
1839 return NULL;
1840 }
1841
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001842 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001843 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844 res.unlockBag(startOfBag);
1845 return NULL;
1846 }
1847
1848 Res_value value;
1849 const ResTable::bag_entry* bag = startOfBag;
1850 size_t strLen = 0;
1851 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1852 value = bag->map.value;
1853 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001855 // Take care of resolving the found resource to its final value.
1856 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001857 if (kThrowOnBadId) {
1858 if (block == BAD_INDEX) {
1859 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1860 return array;
1861 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001862 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001863 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001864 const ResStringPool* pool = res.getTableStringBlock(block);
1865 const char* str8 = pool->string8At(value.data, &strLen);
1866 if (str8 != NULL) {
1867 str = env->NewStringUTF(str8);
1868 } else {
1869 const char16_t* str16 = pool->stringAt(value.data, &strLen);
1870 str = env->NewString(str16, strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001871 }
1872
1873 // If one of our NewString{UTF} calls failed due to memory, an
1874 // exception will be pending.
1875 if (env->ExceptionCheck()) {
1876 res.unlockBag(startOfBag);
1877 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001878 }
Kenny Root780d2a12010-02-22 22:36:26 -08001879
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001880 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001881
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001882 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1883 // If we have a large amount of strings in our array, we might
1884 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001885 env->DeleteLocalRef(str);
1886 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001887 }
1888 res.unlockBag(startOfBag);
1889 return array;
1890}
1891
1892static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1893 jint arrayResId)
1894{
1895 AssetManager* am = assetManagerForJavaObject(env, clazz);
1896 if (am == NULL) {
1897 return NULL;
1898 }
1899 const ResTable& res(am->getResources());
1900
1901 const ResTable::bag_entry* startOfBag;
1902 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1903 if (N < 0) {
1904 return NULL;
1905 }
1906
1907 jintArray array = env->NewIntArray(N);
1908 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001909 res.unlockBag(startOfBag);
1910 return NULL;
1911 }
1912
1913 Res_value value;
1914 const ResTable::bag_entry* bag = startOfBag;
1915 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1916 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001917
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001918 // Take care of resolving the found resource to its final value.
1919 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001920 if (kThrowOnBadId) {
1921 if (block == BAD_INDEX) {
1922 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1923 return array;
1924 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001925 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001926 if (value.dataType >= Res_value::TYPE_FIRST_INT
1927 && value.dataType <= Res_value::TYPE_LAST_INT) {
1928 int intVal = value.data;
1929 env->SetIntArrayRegion(array, i, 1, &intVal);
1930 }
1931 }
1932 res.unlockBag(startOfBag);
1933 return array;
1934}
1935
Jon Miranda042ad632014-09-03 17:57:35 -07001936static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
1937 jint styleId)
1938{
1939 AssetManager* am = assetManagerForJavaObject(env, clazz);
1940 if (am == NULL) {
1941 return NULL;
1942 }
1943 const ResTable& res(am->getResources());
1944
1945 const ResTable::bag_entry* startOfBag;
1946 const ssize_t N = res.lockBag(styleId, &startOfBag);
1947 if (N < 0) {
1948 return NULL;
1949 }
1950
1951 jintArray array = env->NewIntArray(N);
1952 if (array == NULL) {
1953 res.unlockBag(startOfBag);
1954 return NULL;
1955 }
1956
Jon Miranda042ad632014-09-03 17:57:35 -07001957 const ResTable::bag_entry* bag = startOfBag;
1958 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1959 int resourceId = bag->map.name.ident;
1960 env->SetIntArrayRegion(array, i, 1, &resourceId);
1961 }
1962 res.unlockBag(startOfBag);
1963 return array;
1964}
1965
Mårten Kongstad48d22322014-01-31 14:43:27 +01001966static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001967{
Mårten Kongstad48d22322014-01-31 14:43:27 +01001968 if (isSystem) {
1969 verifySystemIdmaps();
1970 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001971 AssetManager* am = new AssetManager();
1972 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001973 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001974 return;
1975 }
1976
1977 am->addDefaultAssets();
1978
Steve Block71f2cf12011-10-20 11:56:00 +01001979 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00001980 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001981}
1982
1983static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
1984{
1985 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00001986 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01001987 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001988 if (am != NULL) {
1989 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00001990 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001991 }
1992}
1993
1994static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
1995{
1996 return Asset::getGlobalCount();
1997}
1998
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001999static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
2000{
2001 String8 alloc = Asset::getAssetAllocations();
2002 if (alloc.length() <= 0) {
2003 return NULL;
2004 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07002005
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002006 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002007 return str;
2008}
2009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002010static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
2011{
2012 return AssetManager::getGlobalCount();
2013}
2014
2015// ----------------------------------------------------------------------------
2016
2017/*
2018 * JNI registration.
2019 */
2020static JNINativeMethod gAssetManagerMethods[] = {
2021 /* name, signature, funcPtr */
2022
2023 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00002024 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002025 (void*) android_content_AssetManager_openAsset },
2026 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2027 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00002028 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002029 (void*) android_content_AssetManager_openNonAssetNative },
2030 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2031 (void*) android_content_AssetManager_openNonAssetFdNative },
2032 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
2033 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00002034 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002035 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002036 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002037 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00002038 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002039 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002040 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002041 (void*) android_content_AssetManager_seekAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002042 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002043 (void*) android_content_AssetManager_getAssetLength },
Ashok Bhat896043d2014-01-17 16:02:38 +00002044 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002045 (void*) android_content_AssetManager_getAssetRemainingLength },
Dianne Hackbornf7be4802013-04-12 14:52:58 -07002046 { "addAssetPathNative", "(Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002047 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad48d22322014-01-31 14:43:27 +01002048 { "addOverlayPath", "(Ljava/lang/String;)I",
2049 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002050 { "isUpToDate", "()Z",
2051 (void*) android_content_AssetManager_isUpToDate },
2052
2053 // Resources.
2054 { "setLocale", "(Ljava/lang/String;)V",
2055 (void*) android_content_AssetManager_setLocale },
2056 { "getLocales", "()[Ljava/lang/String;",
2057 (void*) android_content_AssetManager_getLocales },
Dianne Hackborn69cb8752011-05-19 18:13:32 -07002058 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002059 (void*) android_content_AssetManager_setConfiguration },
2060 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
2061 (void*) android_content_AssetManager_getResourceIdentifier },
2062 { "getResourceName","(I)Ljava/lang/String;",
2063 (void*) android_content_AssetManager_getResourceName },
2064 { "getResourcePackageName","(I)Ljava/lang/String;",
2065 (void*) android_content_AssetManager_getResourcePackageName },
2066 { "getResourceTypeName","(I)Ljava/lang/String;",
2067 (void*) android_content_AssetManager_getResourceTypeName },
2068 { "getResourceEntryName","(I)Ljava/lang/String;",
2069 (void*) android_content_AssetManager_getResourceEntryName },
Kenny Root55fc8502010-10-28 14:47:01 -07002070 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002071 (void*) android_content_AssetManager_loadResourceValue },
2072 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
2073 (void*) android_content_AssetManager_loadResourceBagValue },
2074 { "getStringBlockCount","()I",
2075 (void*) android_content_AssetManager_getStringBlockCount },
Ashok Bhat896043d2014-01-17 16:02:38 +00002076 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002077 (void*) android_content_AssetManager_getNativeStringBlock },
2078 { "getCookieName","(I)Ljava/lang/String;",
2079 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002080 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2081 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082
2083 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002084 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002085 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002086 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002087 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002088 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002089 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002090 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002091 (void*) android_content_AssetManager_copyTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002092 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002093 (void*) android_content_AssetManager_loadThemeAttributeValue },
Ashok Bhat896043d2014-01-17 16:02:38 +00002094 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002095 (void*) android_content_AssetManager_dumpTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002096 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002097 (void*) android_content_AssetManager_applyStyle },
Alan Viverette607bd842014-09-12 12:36:35 -07002098 { "resolveAttrs","(JII[I[I[I[I)Z",
2099 (void*) android_content_AssetManager_resolveAttrs },
Ashok Bhat896043d2014-01-17 16:02:38 +00002100 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002101 (void*) android_content_AssetManager_retrieveAttributes },
2102 { "getArraySize","(I)I",
2103 (void*) android_content_AssetManager_getArraySize },
2104 { "retrieveArray","(I[I)I",
2105 (void*) android_content_AssetManager_retrieveArray },
2106
2107 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002108 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109 (void*) android_content_AssetManager_openXmlAssetNative },
2110
2111 // Arrays.
2112 { "getArrayStringResource","(I)[Ljava/lang/String;",
2113 (void*) android_content_AssetManager_getArrayStringResource },
2114 { "getArrayStringInfo","(I)[I",
2115 (void*) android_content_AssetManager_getArrayStringInfo },
2116 { "getArrayIntResource","(I)[I",
2117 (void*) android_content_AssetManager_getArrayIntResource },
Jon Miranda042ad632014-09-03 17:57:35 -07002118 { "getStyleAttributes","(I)[I",
2119 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002120
2121 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002122 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002123 (void*) android_content_AssetManager_init },
2124 { "destroy", "()V",
2125 (void*) android_content_AssetManager_destroy },
2126 { "getGlobalAssetCount", "()I",
2127 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002128 { "getAssetAllocations", "()Ljava/lang/String;",
2129 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002130 { "getGlobalAssetManagerCount", "()I",
Andreas Gampe32812612014-11-11 00:16:00 -08002131 (void*) android_content_AssetManager_getGlobalAssetManagerCount },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002132};
2133
2134int register_android_content_AssetManager(JNIEnv* env)
2135{
2136 jclass typedValue = env->FindClass("android/util/TypedValue");
2137 LOG_FATAL_IF(typedValue == NULL, "Unable to find class android/util/TypedValue");
2138 gTypedValueOffsets.mType
2139 = env->GetFieldID(typedValue, "type", "I");
2140 LOG_FATAL_IF(gTypedValueOffsets.mType == NULL, "Unable to find TypedValue.type");
2141 gTypedValueOffsets.mData
2142 = env->GetFieldID(typedValue, "data", "I");
2143 LOG_FATAL_IF(gTypedValueOffsets.mData == NULL, "Unable to find TypedValue.data");
2144 gTypedValueOffsets.mString
2145 = env->GetFieldID(typedValue, "string", "Ljava/lang/CharSequence;");
2146 LOG_FATAL_IF(gTypedValueOffsets.mString == NULL, "Unable to find TypedValue.string");
2147 gTypedValueOffsets.mAssetCookie
2148 = env->GetFieldID(typedValue, "assetCookie", "I");
2149 LOG_FATAL_IF(gTypedValueOffsets.mAssetCookie == NULL, "Unable to find TypedValue.assetCookie");
2150 gTypedValueOffsets.mResourceId
2151 = env->GetFieldID(typedValue, "resourceId", "I");
2152 LOG_FATAL_IF(gTypedValueOffsets.mResourceId == NULL, "Unable to find TypedValue.resourceId");
2153 gTypedValueOffsets.mChangingConfigurations
2154 = env->GetFieldID(typedValue, "changingConfigurations", "I");
2155 LOG_FATAL_IF(gTypedValueOffsets.mChangingConfigurations == NULL, "Unable to find TypedValue.changingConfigurations");
2156 gTypedValueOffsets.mDensity = env->GetFieldID(typedValue, "density", "I");
2157 LOG_FATAL_IF(gTypedValueOffsets.mDensity == NULL, "Unable to find TypedValue.density");
2158
2159 jclass assetFd = env->FindClass("android/content/res/AssetFileDescriptor");
2160 LOG_FATAL_IF(assetFd == NULL, "Unable to find class android/content/res/AssetFileDescriptor");
2161 gAssetFileDescriptorOffsets.mFd
2162 = env->GetFieldID(assetFd, "mFd", "Landroid/os/ParcelFileDescriptor;");
2163 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mFd == NULL, "Unable to find AssetFileDescriptor.mFd");
2164 gAssetFileDescriptorOffsets.mStartOffset
2165 = env->GetFieldID(assetFd, "mStartOffset", "J");
2166 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mStartOffset == NULL, "Unable to find AssetFileDescriptor.mStartOffset");
2167 gAssetFileDescriptorOffsets.mLength
2168 = env->GetFieldID(assetFd, "mLength", "J");
2169 LOG_FATAL_IF(gAssetFileDescriptorOffsets.mLength == NULL, "Unable to find AssetFileDescriptor.mLength");
2170
2171 jclass assetManager = env->FindClass("android/content/res/AssetManager");
2172 LOG_FATAL_IF(assetManager == NULL, "Unable to find class android/content/res/AssetManager");
2173 gAssetManagerOffsets.mObject
Ashok Bhat896043d2014-01-17 16:02:38 +00002174 = env->GetFieldID(assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002175 LOG_FATAL_IF(gAssetManagerOffsets.mObject == NULL, "Unable to find AssetManager.mObject");
2176
Carl Shapiroc1318ba2011-03-03 14:22:28 -08002177 jclass stringClass = env->FindClass("java/lang/String");
2178 LOG_FATAL_IF(stringClass == NULL, "Unable to find class java/lang/String");
2179 g_stringClass = (jclass)env->NewGlobalRef(stringClass);
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01002180 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 -08002181
Adam Lesinskide898ff2014-01-29 18:20:45 -08002182 jclass sparseArrayClass = env->FindClass("android/util/SparseArray");
2183 LOG_FATAL_IF(sparseArrayClass == NULL, "Unable to find class android/util/SparseArray");
2184 gSparseArrayOffsets.classObject = (jclass) env->NewGlobalRef(sparseArrayClass);
2185 gSparseArrayOffsets.constructor =
2186 env->GetMethodID(gSparseArrayOffsets.classObject, "<init>", "()V");
2187 LOG_FATAL_IF(gSparseArrayOffsets.constructor == NULL, "Unable to find SparseArray.<init>()");
2188 gSparseArrayOffsets.put =
2189 env->GetMethodID(gSparseArrayOffsets.classObject, "put", "(ILjava/lang/Object;)V");
2190 LOG_FATAL_IF(gSparseArrayOffsets.put == NULL, "Unable to find SparseArray.put(int, V)");
2191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192 return AndroidRuntime::registerNativeMethods(env,
2193 "android/content/res/AssetManager", gAssetManagerMethods, NELEM(gAssetManagerMethods));
2194}
2195
2196}; // namespace android