blob: 5fb2e42353a04208e1a915e4a07f18cf1ec6ba69 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/* //device/libs/android_runtime/android_util_AssetManager.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
Elliott Hughes69a017b2011-04-08 14:10:28 -07005** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008**
Elliott Hughes69a017b2011-04-08 14:10:28 -07009** http://www.apache.org/licenses/LICENSE-2.0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010**
Elliott Hughes69a017b2011-04-08 14:10:28 -070011** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015** limitations under the License.
16*/
17
18#define LOG_TAG "asset"
19
20#include <android_runtime/android_util_AssetManager.h>
21
22#include "jni.h"
23#include "JNIHelp.h"
Elliott Hughes69a017b2011-04-08 14:10:28 -070024#include "ScopedStringChars.h"
25#include "ScopedUtfChars.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026#include "android_util_Binder.h"
27#include <utils/misc.h>
28#include <android_runtime/AndroidRuntime.h>
29#include <utils/Log.h>
30
Mathias Agopianb13b9bd2012-02-17 18:27:36 -080031#include <androidfw/Asset.h>
32#include <androidfw/AssetManager.h>
33#include <androidfw/ResourceTypes.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034
Mårten Kongstad48d22322014-01-31 14:43:27 +010035#include <private/android_filesystem_config.h> // for AID_SYSTEM
36
Andreas Gampe987f79f2014-11-18 17:29:46 -080037#include "core_jni_helpers.h"
38
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039#include <stdio.h>
Mårten Kongstad48d22322014-01-31 14:43:27 +010040#include <sys/types.h>
41#include <sys/wait.h>
42
43#include <linux/capability.h>
44extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
45extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
46
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047
48namespace android {
49
Andreas Gampe0f0b4912014-11-12 08:03:48 -080050static const bool kThrowOnBadId = false;
51static const bool kDebugStyles = false;
52
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053// ----------------------------------------------------------------------------
54
55static struct typedvalue_offsets_t
56{
57 jfieldID mType;
58 jfieldID mData;
59 jfieldID mString;
60 jfieldID mAssetCookie;
61 jfieldID mResourceId;
62 jfieldID mChangingConfigurations;
63 jfieldID mDensity;
64} gTypedValueOffsets;
65
66static struct assetfiledescriptor_offsets_t
67{
68 jfieldID mFd;
69 jfieldID mStartOffset;
70 jfieldID mLength;
71} gAssetFileDescriptorOffsets;
72
73static struct assetmanager_offsets_t
74{
75 jfieldID mObject;
76} gAssetManagerOffsets;
77
Adam Lesinskide898ff2014-01-29 18:20:45 -080078static struct sparsearray_offsets_t
79{
80 jclass classObject;
81 jmethodID constructor;
82 jmethodID put;
83} gSparseArrayOffsets;
84
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085jclass g_stringClass = NULL;
86
87// ----------------------------------------------------------------------------
88
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089enum {
Dianne Hackborn0d221012009-07-29 15:41:19 -070090 STYLE_NUM_ENTRIES = 6,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 STYLE_TYPE = 0,
92 STYLE_DATA = 1,
93 STYLE_ASSET_COOKIE = 2,
94 STYLE_RESOURCE_ID = 3,
Dianne Hackborn0d221012009-07-29 15:41:19 -070095 STYLE_CHANGING_CONFIGURATIONS = 4,
96 STYLE_DENSITY = 5
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097};
98
99static jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
100 const Res_value& value, uint32_t ref, ssize_t block,
101 uint32_t typeSpecFlags, ResTable_config* config = NULL);
102
103jint copyValue(JNIEnv* env, jobject outValue, const ResTable* table,
104 const Res_value& value, uint32_t ref, ssize_t block,
105 uint32_t typeSpecFlags, ResTable_config* config)
106{
107 env->SetIntField(outValue, gTypedValueOffsets.mType, value.dataType);
108 env->SetIntField(outValue, gTypedValueOffsets.mAssetCookie,
Ashok Bhat896043d2014-01-17 16:02:38 +0000109 static_cast<jint>(table->getTableCookie(block)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 env->SetIntField(outValue, gTypedValueOffsets.mData, value.data);
111 env->SetObjectField(outValue, gTypedValueOffsets.mString, NULL);
112 env->SetIntField(outValue, gTypedValueOffsets.mResourceId, ref);
113 env->SetIntField(outValue, gTypedValueOffsets.mChangingConfigurations,
114 typeSpecFlags);
115 if (config != NULL) {
116 env->SetIntField(outValue, gTypedValueOffsets.mDensity, config->density);
117 }
118 return block;
119}
120
Mårten Kongstad48d22322014-01-31 14:43:27 +0100121// This is called by zygote (running as user root) as part of preloadResources.
122static void verifySystemIdmaps()
123{
124 pid_t pid;
125 char system_id[10];
126
127 snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
128
129 switch (pid = fork()) {
130 case -1:
131 ALOGE("failed to fork for idmap: %s", strerror(errno));
132 break;
133 case 0: // child
134 {
135 struct __user_cap_header_struct capheader;
136 struct __user_cap_data_struct capdata;
137
138 memset(&capheader, 0, sizeof(capheader));
139 memset(&capdata, 0, sizeof(capdata));
140
141 capheader.version = _LINUX_CAPABILITY_VERSION;
142 capheader.pid = 0;
143
144 if (capget(&capheader, &capdata) != 0) {
145 ALOGE("capget: %s\n", strerror(errno));
146 exit(1);
147 }
148
149 capdata.effective = capdata.permitted;
150 if (capset(&capheader, &capdata) != 0) {
151 ALOGE("capset: %s\n", strerror(errno));
152 exit(1);
153 }
154
155 if (setgid(AID_SYSTEM) != 0) {
156 ALOGE("setgid: %s\n", strerror(errno));
157 exit(1);
158 }
159
160 if (setuid(AID_SYSTEM) != 0) {
161 ALOGE("setuid: %s\n", strerror(errno));
162 exit(1);
163 }
164
165 execl(AssetManager::IDMAP_BIN, AssetManager::IDMAP_BIN, "--scan",
166 AssetManager::OVERLAY_DIR, AssetManager::TARGET_PACKAGE_NAME,
167 AssetManager::TARGET_APK_PATH, AssetManager::IDMAP_DIR, (char*)NULL);
168 ALOGE("failed to execl for idmap: %s", strerror(errno));
169 exit(1); // should never get here
170 }
171 break;
172 default: // parent
173 waitpid(pid, NULL, 0);
174 break;
175 }
176}
177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178// ----------------------------------------------------------------------------
179
180// this guy is exported to other jni routines
181AssetManager* assetManagerForJavaObject(JNIEnv* env, jobject obj)
182{
Ashok Bhat896043d2014-01-17 16:02:38 +0000183 jlong amHandle = env->GetLongField(obj, gAssetManagerOffsets.mObject);
184 AssetManager* am = reinterpret_cast<AssetManager*>(amHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185 if (am != NULL) {
186 return am;
187 }
188 jniThrowException(env, "java/lang/IllegalStateException", "AssetManager has been finalized!");
189 return NULL;
190}
191
Ashok Bhat896043d2014-01-17 16:02:38 +0000192static jlong android_content_AssetManager_openAsset(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193 jstring fileName, jint mode)
194{
195 AssetManager* am = assetManagerForJavaObject(env, clazz);
196 if (am == NULL) {
197 return 0;
198 }
199
Steve Block71f2cf12011-10-20 11:56:00 +0100200 ALOGV("openAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201
Elliott Hughes69a017b2011-04-08 14:10:28 -0700202 ScopedUtfChars fileName8(env, fileName);
203 if (fileName8.c_str() == NULL) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000204 jniThrowException(env, "java/lang/IllegalArgumentException", "Empty file name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205 return -1;
206 }
207
208 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
209 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700210 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 return -1;
212 }
213
Elliott Hughes69a017b2011-04-08 14:10:28 -0700214 Asset* a = am->open(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215
216 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700217 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 return -1;
219 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220
221 //printf("Created Asset Stream: %p\n", a);
222
Ashok Bhat896043d2014-01-17 16:02:38 +0000223 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224}
225
226static jobject returnParcelFileDescriptor(JNIEnv* env, Asset* a, jlongArray outOffsets)
227{
Kenny Rootddb76c42010-11-24 12:56:06 -0800228 off64_t startOffset, length;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 int fd = a->openFileDescriptor(&startOffset, &length);
230 delete a;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 if (fd < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700233 jniThrowException(env, "java/io/FileNotFoundException",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234 "This file can not be opened as a file descriptor; it is probably compressed");
235 return NULL;
236 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 jlong* offsets = (jlong*)env->GetPrimitiveArrayCritical(outOffsets, 0);
239 if (offsets == NULL) {
240 close(fd);
241 return NULL;
242 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 offsets[0] = startOffset;
245 offsets[1] = length;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247 env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700248
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700249 jobject fileDesc = jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250 if (fileDesc == NULL) {
251 close(fd);
252 return NULL;
253 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 return newParcelFileDescriptor(env, fileDesc);
256}
257
258static jobject android_content_AssetManager_openAssetFd(JNIEnv* env, jobject clazz,
259 jstring fileName, jlongArray outOffsets)
260{
261 AssetManager* am = assetManagerForJavaObject(env, clazz);
262 if (am == NULL) {
263 return NULL;
264 }
265
Steve Block71f2cf12011-10-20 11:56:00 +0100266 ALOGV("openAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267
Elliott Hughes69a017b2011-04-08 14:10:28 -0700268 ScopedUtfChars fileName8(env, fileName);
269 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 return NULL;
271 }
272
Elliott Hughes69a017b2011-04-08 14:10:28 -0700273 Asset* a = am->open(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274
275 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700276 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 return NULL;
278 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279
280 //printf("Created Asset Stream: %p\n", a);
281
282 return returnParcelFileDescriptor(env, a, outOffsets);
283}
284
Ashok Bhat896043d2014-01-17 16:02:38 +0000285static jlong android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 jint cookie,
287 jstring fileName,
288 jint mode)
289{
290 AssetManager* am = assetManagerForJavaObject(env, clazz);
291 if (am == NULL) {
292 return 0;
293 }
294
Steve Block71f2cf12011-10-20 11:56:00 +0100295 ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296
Elliott Hughes69a017b2011-04-08 14:10:28 -0700297 ScopedUtfChars fileName8(env, fileName);
298 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 return -1;
300 }
301
302 if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM
303 && mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700304 jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305 return -1;
306 }
307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000309 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(),
310 (Asset::AccessMode)mode)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700311 : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312
313 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700314 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 return -1;
316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317
318 //printf("Created Asset Stream: %p\n", a);
319
Ashok Bhat896043d2014-01-17 16:02:38 +0000320 return reinterpret_cast<jlong>(a);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321}
322
323static jobject android_content_AssetManager_openNonAssetFdNative(JNIEnv* env, jobject clazz,
324 jint cookie,
325 jstring fileName,
326 jlongArray outOffsets)
327{
328 AssetManager* am = assetManagerForJavaObject(env, clazz);
329 if (am == NULL) {
330 return NULL;
331 }
332
Steve Block71f2cf12011-10-20 11:56:00 +0100333 ALOGV("openNonAssetFd in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334
Elliott Hughes69a017b2011-04-08 14:10:28 -0700335 ScopedUtfChars fileName8(env, fileName);
336 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337 return NULL;
338 }
339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800340 Asset* a = cookie
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000341 ? am->openNonAsset(static_cast<int32_t>(cookie), fileName8.c_str(), Asset::ACCESS_RANDOM)
Elliott Hughes69a017b2011-04-08 14:10:28 -0700342 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_RANDOM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800343
344 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700345 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800346 return NULL;
347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348
349 //printf("Created Asset Stream: %p\n", a);
350
351 return returnParcelFileDescriptor(env, a, outOffsets);
352}
353
354static jobjectArray android_content_AssetManager_list(JNIEnv* env, jobject clazz,
355 jstring fileName)
356{
357 AssetManager* am = assetManagerForJavaObject(env, clazz);
358 if (am == NULL) {
359 return NULL;
360 }
361
Elliott Hughes69a017b2011-04-08 14:10:28 -0700362 ScopedUtfChars fileName8(env, fileName);
363 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364 return NULL;
365 }
366
Elliott Hughes69a017b2011-04-08 14:10:28 -0700367 AssetDir* dir = am->openDir(fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368
369 if (dir == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700370 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 return NULL;
372 }
373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374 size_t N = dir->getFileCount();
375
376 jobjectArray array = env->NewObjectArray(dir->getFileCount(),
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +0100377 g_stringClass, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 delete dir;
380 return NULL;
381 }
382
383 for (size_t i=0; i<N; i++) {
384 const String8& name = dir->getFileName(i);
385 jstring str = env->NewStringUTF(name.string());
386 if (str == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 delete dir;
388 return NULL;
389 }
390 env->SetObjectArrayElement(array, i, str);
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700391 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 }
393
394 delete dir;
395
396 return array;
397}
398
399static void android_content_AssetManager_destroyAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000400 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401{
Ashok Bhat896043d2014-01-17 16:02:38 +0000402 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403
404 //printf("Destroying Asset Stream: %p\n", a);
405
406 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700407 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 return;
409 }
410
411 delete a;
412}
413
414static jint android_content_AssetManager_readAssetChar(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000415 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416{
Ashok Bhat896043d2014-01-17 16:02:38 +0000417 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418
419 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700420 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 return -1;
422 }
423
424 uint8_t b;
425 ssize_t res = a->read(&b, 1);
426 return res == 1 ? b : -1;
427}
428
429static jint android_content_AssetManager_readAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000430 jlong assetHandle, jbyteArray bArray,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 jint off, jint len)
432{
Ashok Bhat896043d2014-01-17 16:02:38 +0000433 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434
435 if (a == NULL || bArray == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700436 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 return -1;
438 }
439
440 if (len == 0) {
441 return 0;
442 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700443
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 jsize bLen = env->GetArrayLength(bArray);
445 if (off < 0 || off >= bLen || len < 0 || len > bLen || (off+len) > bLen) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700446 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 return -1;
448 }
449
450 jbyte* b = env->GetByteArrayElements(bArray, NULL);
451 ssize_t res = a->read(b+off, len);
452 env->ReleaseByteArrayElements(bArray, b, 0);
453
Ashok Bhat896043d2014-01-17 16:02:38 +0000454 if (res > 0) return static_cast<jint>(res);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800455
456 if (res < 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700457 jniThrowException(env, "java/io/IOException", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 }
459 return -1;
460}
461
462static jlong android_content_AssetManager_seekAsset(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000463 jlong assetHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 jlong offset, jint whence)
465{
Ashok Bhat896043d2014-01-17 16:02:38 +0000466 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800467
468 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700469 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470 return -1;
471 }
472
473 return a->seek(
474 offset, (whence > 0) ? SEEK_END : (whence < 0 ? SEEK_SET : SEEK_CUR));
475}
476
477static jlong android_content_AssetManager_getAssetLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000478 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479{
Ashok Bhat896043d2014-01-17 16:02:38 +0000480 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481
482 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700483 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484 return -1;
485 }
486
487 return a->getLength();
488}
489
490static jlong android_content_AssetManager_getAssetRemainingLength(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000491 jlong assetHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800492{
Ashok Bhat896043d2014-01-17 16:02:38 +0000493 Asset* a = reinterpret_cast<Asset*>(assetHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800494
495 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -0700496 jniThrowNullPointerException(env, "asset");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 return -1;
498 }
499
500 return a->getRemainingLength();
501}
502
503static jint android_content_AssetManager_addAssetPath(JNIEnv* env, jobject clazz,
504 jstring path)
505{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700506 ScopedUtfChars path8(env, path);
507 if (path8.c_str() == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800508 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800509 }
510
511 AssetManager* am = assetManagerForJavaObject(env, clazz);
512 if (am == NULL) {
Glenn Kasten129e19c2012-01-10 17:57:36 -0800513 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800514 }
515
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000516 int32_t cookie;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700517 bool res = am->addAssetPath(String8(path8.c_str()), &cookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000519 return (res) ? static_cast<jint>(cookie) : 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800520}
521
Mårten Kongstad48d22322014-01-31 14:43:27 +0100522static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
523 jstring idmapPath)
524{
525 ScopedUtfChars idmapPath8(env, idmapPath);
526 if (idmapPath8.c_str() == NULL) {
527 return 0;
528 }
529
530 AssetManager* am = assetManagerForJavaObject(env, clazz);
531 if (am == NULL) {
532 return 0;
533 }
534
535 int32_t cookie;
536 bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
537
538 return (res) ? (jint)cookie : 0;
539}
540
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800541static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
542{
543 AssetManager* am = assetManagerForJavaObject(env, clazz);
544 if (am == NULL) {
545 return JNI_TRUE;
546 }
547 return am->isUpToDate() ? JNI_TRUE : JNI_FALSE;
548}
549
550static void android_content_AssetManager_setLocale(JNIEnv* env, jobject clazz,
551 jstring locale)
552{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700553 ScopedUtfChars locale8(env, locale);
554 if (locale8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 return;
556 }
557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558 AssetManager* am = assetManagerForJavaObject(env, clazz);
559 if (am == NULL) {
560 return;
561 }
562
Elliott Hughes69a017b2011-04-08 14:10:28 -0700563 am->setLocale(locale8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800564}
565
566static jobjectArray android_content_AssetManager_getLocales(JNIEnv* env, jobject clazz)
567{
568 Vector<String8> locales;
569
570 AssetManager* am = assetManagerForJavaObject(env, clazz);
571 if (am == NULL) {
572 return NULL;
573 }
574
575 am->getLocales(&locales);
576
577 const int N = locales.size();
578
579 jobjectArray result = env->NewObjectArray(N, g_stringClass, NULL);
580 if (result == NULL) {
581 return NULL;
582 }
583
584 for (int i=0; i<N; i++) {
Gilles Debunne0db187a2010-08-27 11:51:34 -0700585 jstring str = env->NewStringUTF(locales[i].string());
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700586 if (str == NULL) {
587 return NULL;
588 }
589 env->SetObjectArrayElement(result, i, str);
590 env->DeleteLocalRef(str);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591 }
592
593 return result;
594}
595
596static void android_content_AssetManager_setConfiguration(JNIEnv* env, jobject clazz,
597 jint mcc, jint mnc,
598 jstring locale, jint orientation,
599 jint touchscreen, jint density,
600 jint keyboard, jint keyboardHidden,
601 jint navigation,
602 jint screenWidth, jint screenHeight,
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700603 jint smallestScreenWidthDp,
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700604 jint screenWidthDp, jint screenHeightDp,
Tobias Haamel27b28b32010-02-09 23:09:17 +0100605 jint screenLayout, jint uiMode,
606 jint sdkVersion)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800607{
608 AssetManager* am = assetManagerForJavaObject(env, clazz);
609 if (am == NULL) {
610 return;
611 }
612
613 ResTable_config config;
614 memset(&config, 0, sizeof(config));
Elliott Hughes69a017b2011-04-08 14:10:28 -0700615
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 const char* locale8 = locale != NULL ? env->GetStringUTFChars(locale, NULL) : NULL;
Elliott Hughes69a017b2011-04-08 14:10:28 -0700617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800618 config.mcc = (uint16_t)mcc;
619 config.mnc = (uint16_t)mnc;
620 config.orientation = (uint8_t)orientation;
621 config.touchscreen = (uint8_t)touchscreen;
622 config.density = (uint16_t)density;
623 config.keyboard = (uint8_t)keyboard;
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700624 config.inputFlags = (uint8_t)keyboardHidden;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800625 config.navigation = (uint8_t)navigation;
626 config.screenWidth = (uint16_t)screenWidth;
627 config.screenHeight = (uint16_t)screenHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700628 config.smallestScreenWidthDp = (uint16_t)smallestScreenWidthDp;
Dianne Hackborn3fc982f2011-03-30 16:20:26 -0700629 config.screenWidthDp = (uint16_t)screenWidthDp;
630 config.screenHeightDp = (uint16_t)screenHeightDp;
Dianne Hackborn723738c2009-06-25 19:48:04 -0700631 config.screenLayout = (uint8_t)screenLayout;
Tobias Haamel27b28b32010-02-09 23:09:17 +0100632 config.uiMode = (uint8_t)uiMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 config.sdkVersion = (uint16_t)sdkVersion;
634 config.minorVersion = 0;
635 am->setConfiguration(config, locale8);
Elliott Hughes69a017b2011-04-08 14:10:28 -0700636
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800637 if (locale != NULL) env->ReleaseStringUTFChars(locale, locale8);
638}
639
640static jint android_content_AssetManager_getResourceIdentifier(JNIEnv* env, jobject clazz,
641 jstring name,
642 jstring defType,
643 jstring defPackage)
644{
Elliott Hughes69a017b2011-04-08 14:10:28 -0700645 ScopedStringChars name16(env, name);
646 if (name16.get() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800647 return 0;
648 }
649
650 AssetManager* am = assetManagerForJavaObject(env, clazz);
651 if (am == NULL) {
652 return 0;
653 }
654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800655 const char16_t* defType16 = defType
656 ? env->GetStringChars(defType, NULL) : NULL;
657 jsize defTypeLen = defType
658 ? env->GetStringLength(defType) : 0;
659 const char16_t* defPackage16 = defPackage
660 ? env->GetStringChars(defPackage, NULL) : NULL;
661 jsize defPackageLen = defPackage
662 ? env->GetStringLength(defPackage) : 0;
663
664 jint ident = am->getResources().identifierForName(
Elliott Hughes69a017b2011-04-08 14:10:28 -0700665 name16.get(), name16.size(), defType16, defTypeLen, defPackage16, defPackageLen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800666
667 if (defPackage16) {
668 env->ReleaseStringChars(defPackage, defPackage16);
669 }
670 if (defType16) {
671 env->ReleaseStringChars(defType, defType16);
672 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800673
674 return ident;
675}
676
677static jstring android_content_AssetManager_getResourceName(JNIEnv* env, jobject clazz,
678 jint resid)
679{
680 AssetManager* am = assetManagerForJavaObject(env, clazz);
681 if (am == NULL) {
682 return NULL;
683 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700684
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700686 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800687 return NULL;
688 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690 String16 str;
691 if (name.package != NULL) {
692 str.setTo(name.package, name.packageLen);
693 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700694 if (name.type8 != NULL || name.type != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800695 if (str.size() > 0) {
696 char16_t div = ':';
697 str.append(&div, 1);
698 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700699 if (name.type8 != NULL) {
700 str.append(String16(name.type8, name.typeLen));
701 } else {
702 str.append(name.type, name.typeLen);
703 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800704 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700705 if (name.name8 != NULL || name.name != NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706 if (str.size() > 0) {
707 char16_t div = '/';
708 str.append(&div, 1);
709 }
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700710 if (name.name8 != NULL) {
711 str.append(String16(name.name8, name.nameLen));
712 } else {
713 str.append(name.name, name.nameLen);
714 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800715 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800717 return env->NewString((const jchar*)str.string(), str.size());
718}
719
720static jstring android_content_AssetManager_getResourcePackageName(JNIEnv* env, jobject clazz,
721 jint resid)
722{
723 AssetManager* am = assetManagerForJavaObject(env, clazz);
724 if (am == NULL) {
725 return NULL;
726 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700727
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800728 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700729 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800730 return NULL;
731 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 if (name.package != NULL) {
734 return env->NewString((const jchar*)name.package, name.packageLen);
735 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800737 return NULL;
738}
739
740static jstring android_content_AssetManager_getResourceTypeName(JNIEnv* env, jobject clazz,
741 jint resid)
742{
743 AssetManager* am = assetManagerForJavaObject(env, clazz);
744 if (am == NULL) {
745 return NULL;
746 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700747
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700749 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800750 return NULL;
751 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700752
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700753 if (name.type8 != NULL) {
754 return env->NewStringUTF(name.type8);
755 }
756
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800757 if (name.type != NULL) {
758 return env->NewString((const jchar*)name.type, name.typeLen);
759 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 return NULL;
762}
763
764static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jobject clazz,
765 jint resid)
766{
767 AssetManager* am = assetManagerForJavaObject(env, clazz);
768 if (am == NULL) {
769 return NULL;
770 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 ResTable::resource_name name;
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700773 if (!am->getResources().getResourceName(resid, true, &name)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800774 return NULL;
775 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700776
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700777 if (name.name8 != NULL) {
778 return env->NewStringUTF(name.name8);
779 }
780
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800781 if (name.name != NULL) {
782 return env->NewString((const jchar*)name.name, name.nameLen);
783 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700784
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785 return NULL;
786}
787
788static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
789 jint ident,
Kenny Root55fc8502010-10-28 14:47:01 -0700790 jshort density,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791 jobject outValue,
792 jboolean resolve)
793{
Dianne Hackborn1f7d3072013-02-11 17:03:32 -0800794 if (outValue == NULL) {
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800795 jniThrowNullPointerException(env, "outValue");
Dianne Hackbornd45c68d2013-07-31 12:14:24 -0700796 return 0;
Dianne Hackborne5b50a62013-02-11 16:18:42 -0800797 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 AssetManager* am = assetManagerForJavaObject(env, clazz);
799 if (am == NULL) {
800 return 0;
801 }
802 const ResTable& res(am->getResources());
803
804 Res_value value;
805 ResTable_config config;
806 uint32_t typeSpecFlags;
Kenny Root55fc8502010-10-28 14:47:01 -0700807 ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800808 if (kThrowOnBadId) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800809 if (block == BAD_INDEX) {
810 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
811 return 0;
812 }
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800813 }
814 uint32_t ref = ident;
815 if (resolve) {
816 block = res.resolveReference(&value, block, &ref, &typeSpecFlags, &config);
817 if (kThrowOnBadId) {
818 if (block == BAD_INDEX) {
819 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
820 return 0;
821 }
822 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800823 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000824 if (block >= 0) {
825 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags, &config);
826 }
827
828 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829}
830
831static jint android_content_AssetManager_loadResourceBagValue(JNIEnv* env, jobject clazz,
832 jint ident, jint bagEntryId,
833 jobject outValue, jboolean resolve)
834{
835 AssetManager* am = assetManagerForJavaObject(env, clazz);
836 if (am == NULL) {
837 return 0;
838 }
839 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -0700840
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800841 // Now lock down the resource object and start pulling stuff from it.
842 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -0700843
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844 ssize_t block = -1;
845 Res_value value;
846
847 const ResTable::bag_entry* entry = NULL;
848 uint32_t typeSpecFlags;
849 ssize_t entryCount = res.getBagLocked(ident, &entry, &typeSpecFlags);
850
851 for (ssize_t i=0; i<entryCount; i++) {
852 if (((uint32_t)bagEntryId) == entry->map.name.ident) {
853 block = entry->stringBlock;
854 value = entry->map.value;
855 }
856 entry++;
857 }
858
859 res.unlock();
860
861 if (block < 0) {
Ashok Bhat896043d2014-01-17 16:02:38 +0000862 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800863 }
Elliott Hughes69a017b2011-04-08 14:10:28 -0700864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 uint32_t ref = ident;
866 if (resolve) {
867 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800868 if (kThrowOnBadId) {
869 if (block == BAD_INDEX) {
870 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
871 return 0;
872 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800873 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000875 if (block >= 0) {
876 return copyValue(env, outValue, &res, value, ref, block, typeSpecFlags);
877 }
878
879 return static_cast<jint>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800880}
881
882static jint android_content_AssetManager_getStringBlockCount(JNIEnv* env, jobject clazz)
883{
884 AssetManager* am = assetManagerForJavaObject(env, clazz);
885 if (am == NULL) {
886 return 0;
887 }
888 return am->getResources().getTableCount();
889}
890
Ashok Bhat896043d2014-01-17 16:02:38 +0000891static jlong android_content_AssetManager_getNativeStringBlock(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800892 jint block)
893{
894 AssetManager* am = assetManagerForJavaObject(env, clazz);
895 if (am == NULL) {
896 return 0;
897 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000898 return reinterpret_cast<jlong>(am->getResources().getTableStringBlock(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800899}
900
901static jstring android_content_AssetManager_getCookieName(JNIEnv* env, jobject clazz,
902 jint cookie)
903{
904 AssetManager* am = assetManagerForJavaObject(env, clazz);
905 if (am == NULL) {
906 return NULL;
907 }
Narayan Kamath745d4ef2014-01-27 11:17:22 +0000908 String8 name(am->getAssetPath(static_cast<int32_t>(cookie)));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800909 if (name.length() == 0) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -0700910 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "Empty cookie name");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800911 return NULL;
912 }
913 jstring str = env->NewStringUTF(name.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800914 return str;
915}
916
Adam Lesinskide898ff2014-01-29 18:20:45 -0800917static jobject android_content_AssetManager_getAssignedPackageIdentifiers(JNIEnv* env, jobject clazz)
918{
919 AssetManager* am = assetManagerForJavaObject(env, clazz);
920 if (am == NULL) {
921 return 0;
922 }
923
924 const ResTable& res = am->getResources();
925
926 jobject sparseArray = env->NewObject(gSparseArrayOffsets.classObject,
927 gSparseArrayOffsets.constructor);
928 const size_t N = res.getBasePackageCount();
929 for (size_t i = 0; i < N; i++) {
930 const String16 name = res.getBasePackageName(i);
931 env->CallVoidMethod(sparseArray, gSparseArrayOffsets.put, (jint) res.getBasePackageId(i),
932 env->NewString(name, name.size()));
933 }
934 return sparseArray;
935}
936
Ashok Bhat896043d2014-01-17 16:02:38 +0000937static jlong android_content_AssetManager_newTheme(JNIEnv* env, jobject clazz)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800938{
939 AssetManager* am = assetManagerForJavaObject(env, clazz);
940 if (am == NULL) {
941 return 0;
942 }
Ashok Bhat896043d2014-01-17 16:02:38 +0000943 return reinterpret_cast<jlong>(new ResTable::Theme(am->getResources()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944}
945
946static void android_content_AssetManager_deleteTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000947 jlong themeHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948{
Ashok Bhat896043d2014-01-17 16:02:38 +0000949 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 delete theme;
951}
952
953static void android_content_AssetManager_applyThemeStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000954 jlong themeHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800955 jint styleRes,
956 jboolean force)
957{
Ashok Bhat896043d2014-01-17 16:02:38 +0000958 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800959 theme->applyStyle(styleRes, force ? true : false);
960}
961
962static void android_content_AssetManager_copyTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000963 jlong destHandle, jlong srcHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964{
Ashok Bhat896043d2014-01-17 16:02:38 +0000965 ResTable::Theme* dest = reinterpret_cast<ResTable::Theme*>(destHandle);
966 ResTable::Theme* src = reinterpret_cast<ResTable::Theme*>(srcHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967 dest->setTo(*src);
968}
969
970static jint android_content_AssetManager_loadThemeAttributeValue(
Ashok Bhat896043d2014-01-17 16:02:38 +0000971 JNIEnv* env, jobject clazz, jlong themeHandle, jint ident, jobject outValue, jboolean resolve)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972{
Ashok Bhat896043d2014-01-17 16:02:38 +0000973 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974 const ResTable& res(theme->getResTable());
975
976 Res_value value;
977 // XXX value could be different in different configs!
978 uint32_t typeSpecFlags = 0;
979 ssize_t block = theme->getAttribute(ident, &value, &typeSpecFlags);
980 uint32_t ref = 0;
981 if (resolve) {
982 block = res.resolveReference(&value, block, &ref, &typeSpecFlags);
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800983 if (kThrowOnBadId) {
984 if (block == BAD_INDEX) {
985 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
986 return 0;
987 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -0800988 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800989 }
990 return block >= 0 ? copyValue(env, outValue, &res, value, ref, block, typeSpecFlags) : block;
991}
992
993static void android_content_AssetManager_dumpTheme(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +0000994 jlong themeHandle, jint pri,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800995 jstring tag, jstring prefix)
996{
Ashok Bhat896043d2014-01-17 16:02:38 +0000997 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800998 const ResTable& res(theme->getResTable());
Andreas Gampe0f0b4912014-11-12 08:03:48 -0800999 (void)res;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001000
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 // XXX Need to use params.
1002 theme->dumpToLog();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003}
1004
Alan Viverette52b999f2014-03-24 18:00:26 -07001005static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject clazz,
1006 jlong themeToken,
1007 jint defStyleAttr,
1008 jint defStyleRes,
1009 jintArray inValues,
1010 jintArray attrs,
1011 jintArray outValues,
1012 jintArray outIndices)
1013{
1014 if (themeToken == 0) {
1015 jniThrowNullPointerException(env, "theme token");
1016 return JNI_FALSE;
1017 }
1018 if (attrs == NULL) {
1019 jniThrowNullPointerException(env, "attrs");
1020 return JNI_FALSE;
1021 }
1022 if (outValues == NULL) {
1023 jniThrowNullPointerException(env, "out values");
1024 return JNI_FALSE;
1025 }
1026
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001027 if (kDebugStyles) {
1028 ALOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x",
1029 themeToken, defStyleAttr, defStyleRes);
1030 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001031
1032 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
1033 const ResTable& res = theme->getResTable();
1034 ResTable_config config;
1035 Res_value value;
1036
1037 const jsize NI = env->GetArrayLength(attrs);
1038 const jsize NV = env->GetArrayLength(outValues);
1039 if (NV < (NI*STYLE_NUM_ENTRIES)) {
1040 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
1041 return JNI_FALSE;
1042 }
1043
1044 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1045 if (src == NULL) {
1046 return JNI_FALSE;
1047 }
1048
1049 jint* srcValues = (jint*)env->GetPrimitiveArrayCritical(inValues, 0);
1050 const jsize NSV = srcValues == NULL ? 0 : env->GetArrayLength(inValues);
1051
1052 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1053 jint* dest = baseDest;
1054 if (dest == NULL) {
1055 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1056 return JNI_FALSE;
1057 }
1058
1059 jint* indices = NULL;
1060 int indicesIdx = 0;
1061 if (outIndices != NULL) {
1062 if (env->GetArrayLength(outIndices) > NI) {
1063 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1064 }
1065 }
1066
1067 // Load default style from attribute, if specified...
1068 uint32_t defStyleBagTypeSetFlags = 0;
1069 if (defStyleAttr != 0) {
1070 Res_value value;
1071 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1072 if (value.dataType == Res_value::TYPE_REFERENCE) {
1073 defStyleRes = value.data;
1074 }
1075 }
1076 }
1077
1078 // Now lock down the resource object and start pulling stuff from it.
1079 res.lock();
1080
1081 // Retrieve the default style bag, if requested.
1082 const ResTable::bag_entry* defStyleEnt = NULL;
1083 uint32_t defStyleTypeSetFlags = 0;
1084 ssize_t bagOff = defStyleRes != 0
1085 ? res.getBagLocked(defStyleRes, &defStyleEnt, &defStyleTypeSetFlags) : -1;
1086 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
1087 const ResTable::bag_entry* endDefStyleEnt = defStyleEnt +
1088 (bagOff >= 0 ? bagOff : 0);;
1089
1090 // Now iterate through all of the attributes that the client has requested,
1091 // filling in each with whatever data we can find.
1092 ssize_t block = 0;
1093 uint32_t typeSetFlags;
1094 for (jsize ii=0; ii<NI; ii++) {
1095 const uint32_t curIdent = (uint32_t)src[ii];
1096
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001097 if (kDebugStyles) {
1098 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1099 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001100
1101 // Try to find a value for this attribute... we prioritize values
1102 // coming from, first XML attributes, then XML style, then default
1103 // style, and finally the theme.
1104 value.dataType = Res_value::TYPE_NULL;
1105 value.data = 0;
1106 typeSetFlags = 0;
1107 config.density = 0;
1108
1109 // Retrieve the current input value if available.
1110 if (NSV > 0 && srcValues[ii] != 0) {
1111 block = -1;
1112 value.dataType = Res_value::TYPE_ATTRIBUTE;
1113 value.data = srcValues[ii];
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001114 if (kDebugStyles) {
1115 ALOGI("-> From values: type=0x%x, data=0x%08x", value.dataType, value.data);
1116 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001117 }
1118
1119 // Skip through the default style values until the end or the next possible match.
1120 while (defStyleEnt < endDefStyleEnt && curIdent > defStyleEnt->map.name.ident) {
1121 defStyleEnt++;
1122 }
1123 // Retrieve the current default style attribute if it matches, and step to next.
1124 if (defStyleEnt < endDefStyleEnt && curIdent == defStyleEnt->map.name.ident) {
1125 if (value.dataType == Res_value::TYPE_NULL) {
1126 block = defStyleEnt->stringBlock;
1127 typeSetFlags = defStyleTypeSetFlags;
1128 value = defStyleEnt->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001129 if (kDebugStyles) {
1130 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1131 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001132 }
1133 defStyleEnt++;
1134 }
1135
1136 uint32_t resid = 0;
1137 if (value.dataType != Res_value::TYPE_NULL) {
1138 // Take care of resolving the found resource to its final value.
1139 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1140 &resid, &typeSetFlags, &config);
1141 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001142 if (kDebugStyles) {
1143 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1144 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001145 } else {
1146 // If we still don't have a value for this attribute, try to find
1147 // it in the theme!
1148 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1149 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001150 if (kDebugStyles) {
1151 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1152 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001153 newBlock = res.resolveReference(&value, block, &resid,
1154 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001155 if (kThrowOnBadId) {
1156 if (newBlock == BAD_INDEX) {
1157 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1158 return JNI_FALSE;
1159 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001160 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001161 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001162 if (kDebugStyles) {
1163 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1164 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001165 }
1166 }
1167
1168 // Deal with the special @null value -- it turns back to TYPE_NULL.
1169 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001170 if (kDebugStyles) {
1171 ALOGI("-> Setting to @null!");
1172 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001173 value.dataType = Res_value::TYPE_NULL;
1174 block = -1;
1175 }
1176
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001177 if (kDebugStyles) {
1178 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType,
1179 value.data);
1180 }
Alan Viverette52b999f2014-03-24 18:00:26 -07001181
1182 // Write the final value back to Java.
1183 dest[STYLE_TYPE] = value.dataType;
1184 dest[STYLE_DATA] = value.data;
1185 dest[STYLE_ASSET_COOKIE] =
1186 block != -1 ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
1187 dest[STYLE_RESOURCE_ID] = resid;
1188 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
1189 dest[STYLE_DENSITY] = config.density;
1190
1191 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1192 indicesIdx++;
1193 indices[indicesIdx] = ii;
1194 }
1195
1196 dest += STYLE_NUM_ENTRIES;
1197 }
1198
1199 res.unlock();
1200
1201 if (indices != NULL) {
1202 indices[0] = indicesIdx;
1203 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1204 }
1205 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1206 env->ReleasePrimitiveArrayCritical(inValues, srcValues, 0);
1207 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1208
1209 return JNI_TRUE;
1210}
1211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001213 jlong themeToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001214 jint defStyleAttr,
1215 jint defStyleRes,
Ashok Bhat896043d2014-01-17 16:02:38 +00001216 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001217 jintArray attrs,
1218 jintArray outValues,
1219 jintArray outIndices)
1220{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001221 if (themeToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001222 jniThrowNullPointerException(env, "theme token");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001223 return JNI_FALSE;
1224 }
1225 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001226 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001227 return JNI_FALSE;
1228 }
1229 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001230 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231 return JNI_FALSE;
1232 }
1233
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001234 if (kDebugStyles) {
1235 ALOGI("APPLY STYLE: theme=0x%x defStyleAttr=0x%x defStyleRes=0x%x xml=0x%x",
1236 themeToken, defStyleAttr, defStyleRes, xmlParserToken);
1237 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001238
Ashok Bhat896043d2014-01-17 16:02:38 +00001239 ResTable::Theme* theme = reinterpret_cast<ResTable::Theme*>(themeToken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001240 const ResTable& res = theme->getResTable();
Ashok Bhat896043d2014-01-17 16:02:38 +00001241 ResXMLParser* xmlParser = reinterpret_cast<ResXMLParser*>(xmlParserToken);
Dianne Hackborn0d221012009-07-29 15:41:19 -07001242 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 Res_value value;
1244
1245 const jsize NI = env->GetArrayLength(attrs);
1246 const jsize NV = env->GetArrayLength(outValues);
1247 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001248 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249 return JNI_FALSE;
1250 }
1251
1252 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1253 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001254 return JNI_FALSE;
1255 }
1256
1257 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1258 jint* dest = baseDest;
1259 if (dest == NULL) {
1260 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001261 return JNI_FALSE;
1262 }
1263
1264 jint* indices = NULL;
1265 int indicesIdx = 0;
1266 if (outIndices != NULL) {
1267 if (env->GetArrayLength(outIndices) > NI) {
1268 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1269 }
1270 }
1271
1272 // Load default style from attribute, if specified...
1273 uint32_t defStyleBagTypeSetFlags = 0;
1274 if (defStyleAttr != 0) {
1275 Res_value value;
1276 if (theme->getAttribute(defStyleAttr, &value, &defStyleBagTypeSetFlags) >= 0) {
1277 if (value.dataType == Res_value::TYPE_REFERENCE) {
1278 defStyleRes = value.data;
1279 }
1280 }
1281 }
1282
1283 // Retrieve the style class associated with the current XML tag.
1284 int style = 0;
1285 uint32_t styleBagTypeSetFlags = 0;
1286 if (xmlParser != NULL) {
1287 ssize_t idx = xmlParser->indexOfStyle();
1288 if (idx >= 0 && xmlParser->getAttributeValue(idx, &value) >= 0) {
1289 if (value.dataType == value.TYPE_ATTRIBUTE) {
1290 if (theme->getAttribute(value.data, &value, &styleBagTypeSetFlags) < 0) {
1291 value.dataType = Res_value::TYPE_NULL;
1292 }
1293 }
1294 if (value.dataType == value.TYPE_REFERENCE) {
1295 style = value.data;
1296 }
1297 }
1298 }
1299
1300 // Now lock down the resource object and start pulling stuff from it.
1301 res.lock();
1302
1303 // Retrieve the default style bag, if requested.
1304 const ResTable::bag_entry* defStyleEnt = NULL;
1305 uint32_t defStyleTypeSetFlags = 0;
1306 ssize_t bagOff = defStyleRes != 0
1307 ? res.getBagLocked(defStyleRes, &defStyleEnt, &defStyleTypeSetFlags) : -1;
1308 defStyleTypeSetFlags |= defStyleBagTypeSetFlags;
1309 const ResTable::bag_entry* endDefStyleEnt = defStyleEnt +
1310 (bagOff >= 0 ? bagOff : 0);
1311
1312 // Retrieve the style class bag, if requested.
1313 const ResTable::bag_entry* styleEnt = NULL;
1314 uint32_t styleTypeSetFlags = 0;
1315 bagOff = style != 0 ? res.getBagLocked(style, &styleEnt, &styleTypeSetFlags) : -1;
1316 styleTypeSetFlags |= styleBagTypeSetFlags;
1317 const ResTable::bag_entry* endStyleEnt = styleEnt +
1318 (bagOff >= 0 ? bagOff : 0);
1319
1320 // Retrieve the XML attributes, if requested.
1321 const jsize NX = xmlParser ? xmlParser->getAttributeCount() : 0;
1322 jsize ix=0;
1323 uint32_t curXmlAttr = xmlParser ? xmlParser->getAttributeNameResID(ix) : 0;
1324
1325 static const ssize_t kXmlBlock = 0x10000000;
1326
1327 // Now iterate through all of the attributes that the client has requested,
1328 // filling in each with whatever data we can find.
1329 ssize_t block = 0;
1330 uint32_t typeSetFlags;
1331 for (jsize ii=0; ii<NI; ii++) {
1332 const uint32_t curIdent = (uint32_t)src[ii];
1333
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001334 if (kDebugStyles) {
1335 ALOGI("RETRIEVING ATTR 0x%08x...", curIdent);
1336 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001338 // Try to find a value for this attribute... we prioritize values
1339 // coming from, first XML attributes, then XML style, then default
1340 // style, and finally the theme.
1341 value.dataType = Res_value::TYPE_NULL;
1342 value.data = 0;
1343 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001344 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001345
1346 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001347 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348 ix++;
1349 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1350 }
1351 // Retrieve the current XML attribute if it matches, and step to next.
1352 if (ix < NX && curIdent == curXmlAttr) {
1353 block = kXmlBlock;
1354 xmlParser->getAttributeValue(ix, &value);
1355 ix++;
1356 curXmlAttr = xmlParser->getAttributeNameResID(ix);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001357 if (kDebugStyles) {
1358 ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data);
1359 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001360 }
1361
1362 // Skip through the style values until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001363 while (styleEnt < endStyleEnt && curIdent > styleEnt->map.name.ident) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001364 styleEnt++;
1365 }
1366 // Retrieve the current style attribute if it matches, and step to next.
1367 if (styleEnt < endStyleEnt && curIdent == styleEnt->map.name.ident) {
1368 if (value.dataType == Res_value::TYPE_NULL) {
1369 block = styleEnt->stringBlock;
1370 typeSetFlags = styleTypeSetFlags;
1371 value = styleEnt->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001372 if (kDebugStyles) {
1373 ALOGI("-> From style: type=0x%x, data=0x%08x", value.dataType, value.data);
1374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 }
1376 styleEnt++;
1377 }
1378
1379 // Skip through the default style values until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001380 while (defStyleEnt < endDefStyleEnt && curIdent > defStyleEnt->map.name.ident) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 defStyleEnt++;
1382 }
1383 // Retrieve the current default style attribute if it matches, and step to next.
1384 if (defStyleEnt < endDefStyleEnt && curIdent == defStyleEnt->map.name.ident) {
1385 if (value.dataType == Res_value::TYPE_NULL) {
1386 block = defStyleEnt->stringBlock;
1387 typeSetFlags = defStyleTypeSetFlags;
1388 value = defStyleEnt->map.value;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001389 if (kDebugStyles) {
1390 ALOGI("-> From def style: type=0x%x, data=0x%08x", value.dataType, value.data);
1391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 }
1393 defStyleEnt++;
1394 }
1395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 uint32_t resid = 0;
1397 if (value.dataType != Res_value::TYPE_NULL) {
1398 // Take care of resolving the found resource to its final value.
Dianne Hackborn0d221012009-07-29 15:41:19 -07001399 ssize_t newBlock = theme->resolveAttributeReference(&value, block,
1400 &resid, &typeSetFlags, &config);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001401 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001402 if (kDebugStyles) {
1403 ALOGI("-> Resolved attr: type=0x%x, data=0x%08x", value.dataType, value.data);
1404 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001405 } else {
1406 // If we still don't have a value for this attribute, try to find
1407 // it in the theme!
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 ssize_t newBlock = theme->getAttribute(curIdent, &value, &typeSetFlags);
1409 if (newBlock >= 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001410 if (kDebugStyles) {
1411 ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1412 }
Dianne Hackborn0d221012009-07-29 15:41:19 -07001413 newBlock = res.resolveReference(&value, block, &resid,
1414 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001415 if (kThrowOnBadId) {
1416 if (newBlock == BAD_INDEX) {
1417 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1418 return JNI_FALSE;
1419 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001420 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001421 if (newBlock >= 0) block = newBlock;
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001422 if (kDebugStyles) {
1423 ALOGI("-> Resolved theme: type=0x%x, data=0x%08x", value.dataType, value.data);
1424 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001425 }
1426 }
1427
1428 // Deal with the special @null value -- it turns back to TYPE_NULL.
1429 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001430 if (kDebugStyles) {
1431 ALOGI("-> Setting to @null!");
1432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001433 value.dataType = Res_value::TYPE_NULL;
Kenny Root7fbe4d22011-01-20 13:15:44 -08001434 block = kXmlBlock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001435 }
1436
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001437 if (kDebugStyles) {
1438 ALOGI("Attribute 0x%08x: type=0x%x, data=0x%08x", curIdent, value.dataType, value.data);
1439 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440
1441 // Write the final value back to Java.
1442 dest[STYLE_TYPE] = value.dataType;
1443 dest[STYLE_DATA] = value.data;
1444 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001445 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001446 dest[STYLE_RESOURCE_ID] = resid;
1447 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001448 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001449
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001450 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1451 indicesIdx++;
1452 indices[indicesIdx] = ii;
1453 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455 dest += STYLE_NUM_ENTRIES;
1456 }
1457
1458 res.unlock();
1459
1460 if (indices != NULL) {
1461 indices[0] = indicesIdx;
1462 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1463 }
1464 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1465 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
1466
1467 return JNI_TRUE;
1468}
1469
1470static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, jobject clazz,
Ashok Bhat896043d2014-01-17 16:02:38 +00001471 jlong xmlParserToken,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001472 jintArray attrs,
1473 jintArray outValues,
1474 jintArray outIndices)
1475{
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001476 if (xmlParserToken == 0) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001477 jniThrowNullPointerException(env, "xmlParserToken");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001478 return JNI_FALSE;
1479 }
1480 if (attrs == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001481 jniThrowNullPointerException(env, "attrs");
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001482 return JNI_FALSE;
1483 }
1484 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001485 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 return JNI_FALSE;
1487 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001488
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001489 AssetManager* am = assetManagerForJavaObject(env, clazz);
1490 if (am == NULL) {
1491 return JNI_FALSE;
1492 }
1493 const ResTable& res(am->getResources());
1494 ResXMLParser* xmlParser = (ResXMLParser*)xmlParserToken;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001495 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 Res_value value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001498 const jsize NI = env->GetArrayLength(attrs);
1499 const jsize NV = env->GetArrayLength(outValues);
1500 if (NV < (NI*STYLE_NUM_ENTRIES)) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001501 jniThrowException(env, "java/lang/IndexOutOfBoundsException", "out values too small");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 return JNI_FALSE;
1503 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001504
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 jint* src = (jint*)env->GetPrimitiveArrayCritical(attrs, 0);
1506 if (src == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 return JNI_FALSE;
1508 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1511 jint* dest = baseDest;
1512 if (dest == NULL) {
1513 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001514 return JNI_FALSE;
1515 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 jint* indices = NULL;
1518 int indicesIdx = 0;
1519 if (outIndices != NULL) {
1520 if (env->GetArrayLength(outIndices) > NI) {
1521 indices = (jint*)env->GetPrimitiveArrayCritical(outIndices, 0);
1522 }
1523 }
1524
1525 // Now lock down the resource object and start pulling stuff from it.
1526 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528 // Retrieve the XML attributes, if requested.
1529 const jsize NX = xmlParser->getAttributeCount();
1530 jsize ix=0;
1531 uint32_t curXmlAttr = xmlParser->getAttributeNameResID(ix);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001532
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001533 static const ssize_t kXmlBlock = 0x10000000;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001535 // Now iterate through all of the attributes that the client has requested,
1536 // filling in each with whatever data we can find.
1537 ssize_t block = 0;
1538 uint32_t typeSetFlags;
1539 for (jsize ii=0; ii<NI; ii++) {
1540 const uint32_t curIdent = (uint32_t)src[ii];
Elliott Hughes69a017b2011-04-08 14:10:28 -07001541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 // Try to find a value for this attribute...
1543 value.dataType = Res_value::TYPE_NULL;
1544 value.data = 0;
1545 typeSetFlags = 0;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001546 config.density = 0;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548 // Skip through XML attributes until the end or the next possible match.
Adam Powell908c7482014-10-01 18:11:18 +00001549 while (ix < NX && curIdent > curXmlAttr) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001550 ix++;
1551 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1552 }
1553 // Retrieve the current XML attribute if it matches, and step to next.
1554 if (ix < NX && curIdent == curXmlAttr) {
1555 block = kXmlBlock;
1556 xmlParser->getAttributeValue(ix, &value);
1557 ix++;
1558 curXmlAttr = xmlParser->getAttributeNameResID(ix);
1559 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001560
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001561 //printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1562 uint32_t resid = 0;
1563 if (value.dataType != Res_value::TYPE_NULL) {
1564 // Take care of resolving the found resource to its final value.
1565 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001566 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1567 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001568 if (kThrowOnBadId) {
1569 if (newBlock == BAD_INDEX) {
1570 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1571 return JNI_FALSE;
1572 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001573 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001574 if (newBlock >= 0) block = newBlock;
1575 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001577 // Deal with the special @null value -- it turns back to TYPE_NULL.
1578 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1579 value.dataType = Res_value::TYPE_NULL;
1580 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001583
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001584 // Write the final value back to Java.
1585 dest[STYLE_TYPE] = value.dataType;
1586 dest[STYLE_DATA] = value.data;
1587 dest[STYLE_ASSET_COOKIE] =
Ashok Bhat896043d2014-01-17 16:02:38 +00001588 block != kXmlBlock ? reinterpret_cast<jint>(res.getTableCookie(block)) : (jint)-1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 dest[STYLE_RESOURCE_ID] = resid;
1590 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001591 dest[STYLE_DENSITY] = config.density;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001593 if (indices != NULL && value.dataType != Res_value::TYPE_NULL) {
1594 indicesIdx++;
1595 indices[indicesIdx] = ii;
1596 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001597
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598 dest += STYLE_NUM_ENTRIES;
1599 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001600
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001603 if (indices != NULL) {
1604 indices[0] = indicesIdx;
1605 env->ReleasePrimitiveArrayCritical(outIndices, indices, 0);
1606 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001608 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
1609 env->ReleasePrimitiveArrayCritical(attrs, src, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 return JNI_TRUE;
1612}
1613
1614static jint android_content_AssetManager_getArraySize(JNIEnv* env, jobject clazz,
1615 jint id)
1616{
1617 AssetManager* am = assetManagerForJavaObject(env, clazz);
1618 if (am == NULL) {
Olivier Baillyd7c86722010-11-18 14:43:36 -08001619 return 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001620 }
1621 const ResTable& res(am->getResources());
Elliott Hughes69a017b2011-04-08 14:10:28 -07001622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001623 res.lock();
1624 const ResTable::bag_entry* defStyleEnt = NULL;
1625 ssize_t bagOff = res.getBagLocked(id, &defStyleEnt);
1626 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001627
Ashok Bhat896043d2014-01-17 16:02:38 +00001628 return static_cast<jint>(bagOff);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629}
1630
1631static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject clazz,
1632 jint id,
1633 jintArray outValues)
1634{
1635 if (outValues == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001636 jniThrowNullPointerException(env, "out values");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001637 return JNI_FALSE;
1638 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001640 AssetManager* am = assetManagerForJavaObject(env, clazz);
1641 if (am == NULL) {
1642 return JNI_FALSE;
1643 }
1644 const ResTable& res(am->getResources());
Dianne Hackborn0d221012009-07-29 15:41:19 -07001645 ResTable_config config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 Res_value value;
1647 ssize_t block;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001649 const jsize NV = env->GetArrayLength(outValues);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001651 jint* baseDest = (jint*)env->GetPrimitiveArrayCritical(outValues, 0);
1652 jint* dest = baseDest;
1653 if (dest == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001654 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001655 return JNI_FALSE;
1656 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001657
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658 // Now lock down the resource object and start pulling stuff from it.
1659 res.lock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001660
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001661 const ResTable::bag_entry* arrayEnt = NULL;
1662 uint32_t arrayTypeSetFlags = 0;
1663 ssize_t bagOff = res.getBagLocked(id, &arrayEnt, &arrayTypeSetFlags);
1664 const ResTable::bag_entry* endArrayEnt = arrayEnt +
1665 (bagOff >= 0 ? bagOff : 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001666
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001667 int i = 0;
1668 uint32_t typeSetFlags;
1669 while (i < NV && arrayEnt < endArrayEnt) {
1670 block = arrayEnt->stringBlock;
1671 typeSetFlags = arrayTypeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001672 config.density = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 value = arrayEnt->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 uint32_t resid = 0;
1676 if (value.dataType != Res_value::TYPE_NULL) {
1677 // Take care of resolving the found resource to its final value.
1678 //printf("Resolving attribute reference\n");
Dianne Hackborn0d221012009-07-29 15:41:19 -07001679 ssize_t newBlock = res.resolveReference(&value, block, &resid,
1680 &typeSetFlags, &config);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001681 if (kThrowOnBadId) {
1682 if (newBlock == BAD_INDEX) {
1683 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1684 return JNI_FALSE;
1685 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 if (newBlock >= 0) block = newBlock;
1688 }
1689
1690 // Deal with the special @null value -- it turns back to TYPE_NULL.
1691 if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
1692 value.dataType = Res_value::TYPE_NULL;
1693 }
1694
1695 //printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
1696
1697 // Write the final value back to Java.
1698 dest[STYLE_TYPE] = value.dataType;
1699 dest[STYLE_DATA] = value.data;
Ashok Bhat896043d2014-01-17 16:02:38 +00001700 dest[STYLE_ASSET_COOKIE] = reinterpret_cast<jint>(res.getTableCookie(block));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001701 dest[STYLE_RESOURCE_ID] = resid;
1702 dest[STYLE_CHANGING_CONFIGURATIONS] = typeSetFlags;
Dianne Hackborn0d221012009-07-29 15:41:19 -07001703 dest[STYLE_DENSITY] = config.density;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001704 dest += STYLE_NUM_ENTRIES;
1705 i+= STYLE_NUM_ENTRIES;
1706 arrayEnt++;
1707 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 i /= STYLE_NUM_ENTRIES;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001711 res.unlock();
Elliott Hughes69a017b2011-04-08 14:10:28 -07001712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 env->ReleasePrimitiveArrayCritical(outValues, baseDest, 0);
Elliott Hughes69a017b2011-04-08 14:10:28 -07001714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001715 return i;
1716}
1717
Ashok Bhat896043d2014-01-17 16:02:38 +00001718static jlong android_content_AssetManager_openXmlAssetNative(JNIEnv* env, jobject clazz,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001719 jint cookie,
1720 jstring fileName)
1721{
1722 AssetManager* am = assetManagerForJavaObject(env, clazz);
1723 if (am == NULL) {
1724 return 0;
1725 }
1726
Steve Block71f2cf12011-10-20 11:56:00 +01001727 ALOGV("openXmlAsset in %p (Java object %p)\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728
Elliott Hughes69a017b2011-04-08 14:10:28 -07001729 ScopedUtfChars fileName8(env, fileName);
1730 if (fileName8.c_str() == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 return 0;
1732 }
1733
Adam Lesinskide898ff2014-01-29 18:20:45 -08001734 int32_t assetCookie = static_cast<int32_t>(cookie);
1735 Asset* a = assetCookie
1736 ? am->openNonAsset(assetCookie, fileName8.c_str(), Asset::ACCESS_BUFFER)
1737 : am->openNonAsset(fileName8.c_str(), Asset::ACCESS_BUFFER, &assetCookie);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738
1739 if (a == NULL) {
Elliott Hughes69a017b2011-04-08 14:10:28 -07001740 jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001741 return 0;
1742 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001743
Adam Lesinskide898ff2014-01-29 18:20:45 -08001744 const DynamicRefTable* dynamicRefTable =
1745 am->getResources().getDynamicRefTableForCookie(assetCookie);
1746 ResXMLTree* block = new ResXMLTree(dynamicRefTable);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001747 status_t err = block->setTo(a->getBuffer(true), a->getLength(), true);
1748 a->close();
1749 delete a;
1750
1751 if (err != NO_ERROR) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001752 jniThrowException(env, "java/io/FileNotFoundException", "Corrupt XML binary file");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001753 return 0;
1754 }
1755
Ashok Bhat896043d2014-01-17 16:02:38 +00001756 return reinterpret_cast<jlong>(block);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001757}
1758
1759static jintArray android_content_AssetManager_getArrayStringInfo(JNIEnv* env, jobject clazz,
1760 jint arrayResId)
1761{
1762 AssetManager* am = assetManagerForJavaObject(env, clazz);
1763 if (am == NULL) {
1764 return NULL;
1765 }
1766 const ResTable& res(am->getResources());
1767
1768 const ResTable::bag_entry* startOfBag;
1769 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1770 if (N < 0) {
1771 return NULL;
1772 }
1773
1774 jintArray array = env->NewIntArray(N * 2);
1775 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001776 res.unlockBag(startOfBag);
1777 return NULL;
1778 }
1779
1780 Res_value value;
1781 const ResTable::bag_entry* bag = startOfBag;
1782 for (size_t i = 0, j = 0; ((ssize_t)i)<N; i++, bag++) {
1783 jint stringIndex = -1;
1784 jint stringBlock = 0;
1785 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 // Take care of resolving the found resource to its final value.
1788 stringBlock = res.resolveReference(&value, bag->stringBlock, NULL);
1789 if (value.dataType == Res_value::TYPE_STRING) {
1790 stringIndex = value.data;
1791 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001792
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001793 if (kThrowOnBadId) {
1794 if (stringBlock == BAD_INDEX) {
1795 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1796 return array;
1797 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001798 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001800 //todo: It might be faster to allocate a C array to contain
1801 // the blocknums and indices, put them in there and then
1802 // do just one SetIntArrayRegion()
1803 env->SetIntArrayRegion(array, j, 1, &stringBlock);
1804 env->SetIntArrayRegion(array, j + 1, 1, &stringIndex);
1805 j = j + 2;
1806 }
1807 res.unlockBag(startOfBag);
1808 return array;
1809}
1810
1811static jobjectArray android_content_AssetManager_getArrayStringResource(JNIEnv* env, jobject clazz,
1812 jint arrayResId)
1813{
1814 AssetManager* am = assetManagerForJavaObject(env, clazz);
1815 if (am == NULL) {
1816 return NULL;
1817 }
1818 const ResTable& res(am->getResources());
1819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 const ResTable::bag_entry* startOfBag;
1821 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1822 if (N < 0) {
1823 return NULL;
1824 }
1825
Vladimir Markoaa5fe3d2013-06-17 12:46:22 +01001826 jobjectArray array = env->NewObjectArray(N, g_stringClass, NULL);
Kenny Root485dd212010-05-06 16:06:48 -07001827 if (env->ExceptionCheck()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001828 res.unlockBag(startOfBag);
1829 return NULL;
1830 }
1831
1832 Res_value value;
1833 const ResTable::bag_entry* bag = startOfBag;
1834 size_t strLen = 0;
1835 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1836 value = bag->map.value;
1837 jstring str = NULL;
Kenny Root780d2a12010-02-22 22:36:26 -08001838
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 // Take care of resolving the found resource to its final value.
1840 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001841 if (kThrowOnBadId) {
1842 if (block == BAD_INDEX) {
1843 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1844 return array;
1845 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001846 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 if (value.dataType == Res_value::TYPE_STRING) {
Kenny Root780d2a12010-02-22 22:36:26 -08001848 const ResStringPool* pool = res.getTableStringBlock(block);
1849 const char* str8 = pool->string8At(value.data, &strLen);
1850 if (str8 != NULL) {
1851 str = env->NewStringUTF(str8);
1852 } else {
1853 const char16_t* str16 = pool->stringAt(value.data, &strLen);
1854 str = env->NewString(str16, strLen);
Kenny Root485dd212010-05-06 16:06:48 -07001855 }
1856
1857 // If one of our NewString{UTF} calls failed due to memory, an
1858 // exception will be pending.
1859 if (env->ExceptionCheck()) {
1860 res.unlockBag(startOfBag);
1861 return NULL;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001862 }
Kenny Root780d2a12010-02-22 22:36:26 -08001863
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001864 env->SetObjectArrayElement(array, i, str);
Kenny Root485dd212010-05-06 16:06:48 -07001865
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001866 // str is not NULL at that point, otherwise ExceptionCheck would have been true.
1867 // If we have a large amount of strings in our array, we might
1868 // overflow the local reference table of the VM.
Kenny Root485dd212010-05-06 16:06:48 -07001869 env->DeleteLocalRef(str);
1870 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001871 }
1872 res.unlockBag(startOfBag);
1873 return array;
1874}
1875
1876static jintArray android_content_AssetManager_getArrayIntResource(JNIEnv* env, jobject clazz,
1877 jint arrayResId)
1878{
1879 AssetManager* am = assetManagerForJavaObject(env, clazz);
1880 if (am == NULL) {
1881 return NULL;
1882 }
1883 const ResTable& res(am->getResources());
1884
1885 const ResTable::bag_entry* startOfBag;
1886 const ssize_t N = res.lockBag(arrayResId, &startOfBag);
1887 if (N < 0) {
1888 return NULL;
1889 }
1890
1891 jintArray array = env->NewIntArray(N);
1892 if (array == NULL) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001893 res.unlockBag(startOfBag);
1894 return NULL;
1895 }
1896
1897 Res_value value;
1898 const ResTable::bag_entry* bag = startOfBag;
1899 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1900 value = bag->map.value;
Elliott Hughes69a017b2011-04-08 14:10:28 -07001901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001902 // Take care of resolving the found resource to its final value.
1903 ssize_t block = res.resolveReference(&value, bag->stringBlock, NULL);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001904 if (kThrowOnBadId) {
1905 if (block == BAD_INDEX) {
1906 jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
1907 return array;
1908 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08001909 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001910 if (value.dataType >= Res_value::TYPE_FIRST_INT
1911 && value.dataType <= Res_value::TYPE_LAST_INT) {
1912 int intVal = value.data;
1913 env->SetIntArrayRegion(array, i, 1, &intVal);
1914 }
1915 }
1916 res.unlockBag(startOfBag);
1917 return array;
1918}
1919
Jon Miranda042ad632014-09-03 17:57:35 -07001920static jintArray android_content_AssetManager_getStyleAttributes(JNIEnv* env, jobject clazz,
1921 jint styleId)
1922{
1923 AssetManager* am = assetManagerForJavaObject(env, clazz);
1924 if (am == NULL) {
1925 return NULL;
1926 }
1927 const ResTable& res(am->getResources());
1928
1929 const ResTable::bag_entry* startOfBag;
1930 const ssize_t N = res.lockBag(styleId, &startOfBag);
1931 if (N < 0) {
1932 return NULL;
1933 }
1934
1935 jintArray array = env->NewIntArray(N);
1936 if (array == NULL) {
1937 res.unlockBag(startOfBag);
1938 return NULL;
1939 }
1940
Jon Miranda042ad632014-09-03 17:57:35 -07001941 const ResTable::bag_entry* bag = startOfBag;
1942 for (size_t i=0; ((ssize_t)i)<N; i++, bag++) {
1943 int resourceId = bag->map.name.ident;
1944 env->SetIntArrayRegion(array, i, 1, &resourceId);
1945 }
1946 res.unlockBag(startOfBag);
1947 return array;
1948}
1949
Mårten Kongstad48d22322014-01-31 14:43:27 +01001950static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001951{
Mårten Kongstad48d22322014-01-31 14:43:27 +01001952 if (isSystem) {
1953 verifySystemIdmaps();
1954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001955 AssetManager* am = new AssetManager();
1956 if (am == NULL) {
Gilles Debunne4d4040b2010-08-26 15:59:54 -07001957 jniThrowException(env, "java/lang/OutOfMemoryError", "");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001958 return;
1959 }
1960
1961 am->addDefaultAssets();
1962
Steve Block71f2cf12011-10-20 11:56:00 +01001963 ALOGV("Created AssetManager %p for Java object %p\n", am, clazz);
Ashok Bhat896043d2014-01-17 16:02:38 +00001964 env->SetLongField(clazz, gAssetManagerOffsets.mObject, reinterpret_cast<jlong>(am));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001965}
1966
1967static void android_content_AssetManager_destroy(JNIEnv* env, jobject clazz)
1968{
1969 AssetManager* am = (AssetManager*)
Ashok Bhat896043d2014-01-17 16:02:38 +00001970 (env->GetLongField(clazz, gAssetManagerOffsets.mObject));
Steve Block71f2cf12011-10-20 11:56:00 +01001971 ALOGV("Destroying AssetManager %p for Java object %p\n", am, clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001972 if (am != NULL) {
1973 delete am;
Ashok Bhat896043d2014-01-17 16:02:38 +00001974 env->SetLongField(clazz, gAssetManagerOffsets.mObject, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001975 }
1976}
1977
1978static jint android_content_AssetManager_getGlobalAssetCount(JNIEnv* env, jobject clazz)
1979{
1980 return Asset::getGlobalCount();
1981}
1982
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001983static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
1984{
1985 String8 alloc = Asset::getAssetAllocations();
1986 if (alloc.length() <= 0) {
1987 return NULL;
1988 }
Elliott Hughes69a017b2011-04-08 14:10:28 -07001989
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001990 jstring str = env->NewStringUTF(alloc.string());
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07001991 return str;
1992}
1993
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001994static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
1995{
1996 return AssetManager::getGlobalCount();
1997}
1998
1999// ----------------------------------------------------------------------------
2000
2001/*
2002 * JNI registration.
2003 */
2004static JNINativeMethod gAssetManagerMethods[] = {
2005 /* name, signature, funcPtr */
2006
2007 // Basic asset stuff.
Ashok Bhat896043d2014-01-17 16:02:38 +00002008 { "openAsset", "(Ljava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002009 (void*) android_content_AssetManager_openAsset },
2010 { "openAssetFd", "(Ljava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2011 (void*) android_content_AssetManager_openAssetFd },
Ashok Bhat896043d2014-01-17 16:02:38 +00002012 { "openNonAssetNative", "(ILjava/lang/String;I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002013 (void*) android_content_AssetManager_openNonAssetNative },
2014 { "openNonAssetFdNative", "(ILjava/lang/String;[J)Landroid/os/ParcelFileDescriptor;",
2015 (void*) android_content_AssetManager_openNonAssetFdNative },
2016 { "list", "(Ljava/lang/String;)[Ljava/lang/String;",
2017 (void*) android_content_AssetManager_list },
Ashok Bhat896043d2014-01-17 16:02:38 +00002018 { "destroyAsset", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002019 (void*) android_content_AssetManager_destroyAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002020 { "readAssetChar", "(J)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002021 (void*) android_content_AssetManager_readAssetChar },
Ashok Bhat896043d2014-01-17 16:02:38 +00002022 { "readAsset", "(J[BII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002023 (void*) android_content_AssetManager_readAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002024 { "seekAsset", "(JJI)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002025 (void*) android_content_AssetManager_seekAsset },
Ashok Bhat896043d2014-01-17 16:02:38 +00002026 { "getAssetLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002027 (void*) android_content_AssetManager_getAssetLength },
Ashok Bhat896043d2014-01-17 16:02:38 +00002028 { "getAssetRemainingLength", "(J)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002029 (void*) android_content_AssetManager_getAssetRemainingLength },
Dianne Hackbornf7be4802013-04-12 14:52:58 -07002030 { "addAssetPathNative", "(Ljava/lang/String;)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002031 (void*) android_content_AssetManager_addAssetPath },
Mårten Kongstad48d22322014-01-31 14:43:27 +01002032 { "addOverlayPath", "(Ljava/lang/String;)I",
2033 (void*) android_content_AssetManager_addOverlayPath },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002034 { "isUpToDate", "()Z",
2035 (void*) android_content_AssetManager_isUpToDate },
2036
2037 // Resources.
2038 { "setLocale", "(Ljava/lang/String;)V",
2039 (void*) android_content_AssetManager_setLocale },
2040 { "getLocales", "()[Ljava/lang/String;",
2041 (void*) android_content_AssetManager_getLocales },
Dianne Hackborn69cb8752011-05-19 18:13:32 -07002042 { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIIIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002043 (void*) android_content_AssetManager_setConfiguration },
2044 { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
2045 (void*) android_content_AssetManager_getResourceIdentifier },
2046 { "getResourceName","(I)Ljava/lang/String;",
2047 (void*) android_content_AssetManager_getResourceName },
2048 { "getResourcePackageName","(I)Ljava/lang/String;",
2049 (void*) android_content_AssetManager_getResourcePackageName },
2050 { "getResourceTypeName","(I)Ljava/lang/String;",
2051 (void*) android_content_AssetManager_getResourceTypeName },
2052 { "getResourceEntryName","(I)Ljava/lang/String;",
2053 (void*) android_content_AssetManager_getResourceEntryName },
Kenny Root55fc8502010-10-28 14:47:01 -07002054 { "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055 (void*) android_content_AssetManager_loadResourceValue },
2056 { "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
2057 (void*) android_content_AssetManager_loadResourceBagValue },
2058 { "getStringBlockCount","()I",
2059 (void*) android_content_AssetManager_getStringBlockCount },
Ashok Bhat896043d2014-01-17 16:02:38 +00002060 { "getNativeStringBlock","(I)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002061 (void*) android_content_AssetManager_getNativeStringBlock },
2062 { "getCookieName","(I)Ljava/lang/String;",
2063 (void*) android_content_AssetManager_getCookieName },
Adam Lesinskide898ff2014-01-29 18:20:45 -08002064 { "getAssignedPackageIdentifiers","()Landroid/util/SparseArray;",
2065 (void*) android_content_AssetManager_getAssignedPackageIdentifiers },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002066
2067 // Themes.
Ashok Bhat896043d2014-01-17 16:02:38 +00002068 { "newTheme", "()J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002069 (void*) android_content_AssetManager_newTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002070 { "deleteTheme", "(J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002071 (void*) android_content_AssetManager_deleteTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002072 { "applyThemeStyle", "(JIZ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002073 (void*) android_content_AssetManager_applyThemeStyle },
Ashok Bhat896043d2014-01-17 16:02:38 +00002074 { "copyTheme", "(JJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002075 (void*) android_content_AssetManager_copyTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002076 { "loadThemeAttributeValue", "(JILandroid/util/TypedValue;Z)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002077 (void*) android_content_AssetManager_loadThemeAttributeValue },
Ashok Bhat896043d2014-01-17 16:02:38 +00002078 { "dumpTheme", "(JILjava/lang/String;Ljava/lang/String;)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002079 (void*) android_content_AssetManager_dumpTheme },
Ashok Bhat896043d2014-01-17 16:02:38 +00002080 { "applyStyle","(JIIJ[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002081 (void*) android_content_AssetManager_applyStyle },
Alan Viverette607bd842014-09-12 12:36:35 -07002082 { "resolveAttrs","(JII[I[I[I[I)Z",
2083 (void*) android_content_AssetManager_resolveAttrs },
Ashok Bhat896043d2014-01-17 16:02:38 +00002084 { "retrieveAttributes","(J[I[I[I)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002085 (void*) android_content_AssetManager_retrieveAttributes },
2086 { "getArraySize","(I)I",
2087 (void*) android_content_AssetManager_getArraySize },
2088 { "retrieveArray","(I[I)I",
2089 (void*) android_content_AssetManager_retrieveArray },
2090
2091 // XML files.
Ashok Bhat896043d2014-01-17 16:02:38 +00002092 { "openXmlAssetNative", "(ILjava/lang/String;)J",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002093 (void*) android_content_AssetManager_openXmlAssetNative },
2094
2095 // Arrays.
2096 { "getArrayStringResource","(I)[Ljava/lang/String;",
2097 (void*) android_content_AssetManager_getArrayStringResource },
2098 { "getArrayStringInfo","(I)[I",
2099 (void*) android_content_AssetManager_getArrayStringInfo },
2100 { "getArrayIntResource","(I)[I",
2101 (void*) android_content_AssetManager_getArrayIntResource },
Jon Miranda042ad632014-09-03 17:57:35 -07002102 { "getStyleAttributes","(I)[I",
2103 (void*) android_content_AssetManager_getStyleAttributes },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002104
2105 // Bookkeeping.
Mårten Kongstad48d22322014-01-31 14:43:27 +01002106 { "init", "(Z)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002107 (void*) android_content_AssetManager_init },
2108 { "destroy", "()V",
2109 (void*) android_content_AssetManager_destroy },
2110 { "getGlobalAssetCount", "()I",
2111 (void*) android_content_AssetManager_getGlobalAssetCount },
Dianne Hackborn82e1ee92009-08-11 18:56:41 -07002112 { "getAssetAllocations", "()Ljava/lang/String;",
2113 (void*) android_content_AssetManager_getAssetAllocations },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002114 { "getGlobalAssetManagerCount", "()I",
Andreas Gampe32812612014-11-11 00:16:00 -08002115 (void*) android_content_AssetManager_getGlobalAssetManagerCount },
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002116};
2117
2118int register_android_content_AssetManager(JNIEnv* env)
2119{
Andreas Gampe987f79f2014-11-18 17:29:46 -08002120 jclass typedValue = FindClassOrDie(env, "android/util/TypedValue");
2121 gTypedValueOffsets.mType = GetFieldIDOrDie(env, typedValue, "type", "I");
2122 gTypedValueOffsets.mData = GetFieldIDOrDie(env, typedValue, "data", "I");
2123 gTypedValueOffsets.mString = GetFieldIDOrDie(env, typedValue, "string",
2124 "Ljava/lang/CharSequence;");
2125 gTypedValueOffsets.mAssetCookie = GetFieldIDOrDie(env, typedValue, "assetCookie", "I");
2126 gTypedValueOffsets.mResourceId = GetFieldIDOrDie(env, typedValue, "resourceId", "I");
2127 gTypedValueOffsets.mChangingConfigurations = GetFieldIDOrDie(env, typedValue,
2128 "changingConfigurations", "I");
2129 gTypedValueOffsets.mDensity = GetFieldIDOrDie(env, typedValue, "density", "I");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002130
Andreas Gampe987f79f2014-11-18 17:29:46 -08002131 jclass assetFd = FindClassOrDie(env, "android/content/res/AssetFileDescriptor");
2132 gAssetFileDescriptorOffsets.mFd = GetFieldIDOrDie(env, assetFd, "mFd",
2133 "Landroid/os/ParcelFileDescriptor;");
2134 gAssetFileDescriptorOffsets.mStartOffset = GetFieldIDOrDie(env, assetFd, "mStartOffset", "J");
2135 gAssetFileDescriptorOffsets.mLength = GetFieldIDOrDie(env, assetFd, "mLength", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002136
Andreas Gampe987f79f2014-11-18 17:29:46 -08002137 jclass assetManager = FindClassOrDie(env, "android/content/res/AssetManager");
2138 gAssetManagerOffsets.mObject = GetFieldIDOrDie(env, assetManager, "mObject", "J");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002139
Andreas Gampe987f79f2014-11-18 17:29:46 -08002140 jclass stringClass = FindClassOrDie(env, "java/lang/String");
2141 g_stringClass = MakeGlobalRefOrDie(env, stringClass);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142
Andreas Gampe987f79f2014-11-18 17:29:46 -08002143 jclass sparseArrayClass = FindClassOrDie(env, "android/util/SparseArray");
2144 gSparseArrayOffsets.classObject = MakeGlobalRefOrDie(env, sparseArrayClass);
2145 gSparseArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject,
2146 "<init>", "()V");
2147 gSparseArrayOffsets.put = GetMethodIDOrDie(env, gSparseArrayOffsets.classObject, "put",
2148 "(ILjava/lang/Object;)V");
Adam Lesinskide898ff2014-01-29 18:20:45 -08002149
Andreas Gampe987f79f2014-11-18 17:29:46 -08002150 return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods,
2151 NELEM(gAssetManagerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002152}
2153
2154}; // namespace android